{"vulnerability": "CVE-2021-1678", "sightings": [{"uuid": "3afe3754-3fe9-4b8d-95d8-ff29c7d0c840", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2021-1678", "type": "seen", "source": "https://t.me/cibsecurity/22038", "content": "\u203c CVE-2021-1678 \u203c\n\nNTLM Security Feature Bypass Vulnerability\n\n\ud83d\udcd6 Read\n\nvia \"National Vulnerability Database\".", "creation_timestamp": "2021-01-12T23:01:27.000000Z"}, {"uuid": "d642e081-e362-4e21-8bf8-ba9b350d892b", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2021-1678", "type": "exploited", "source": "https://t.me/true_secator/2127", "content": "\u041f\u0435\u0447\u0430\u0442\u0430\u0442\u044c \u0438\u043b\u0438 \u043d\u0435 \u043f\u0435\u0447\u0430\u0442\u0430\u0442\u044c?\n \n\u041f\u0435\u0440\u0435\u0434 \u0442\u0430\u043a\u043e\u0439 \u0434\u0438\u043b\u0435\u043c\u043c\u043e\u0439 Microsoft \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u043b\u0430 \u0442\u044b\u0441\u044f\u0447\u0438 \u0441\u0432\u043e\u0438\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439. \u0414\u043e\u043b\u0433\u043e\u0436\u0434\u0430\u043d\u043d\u043e\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 PatchTuesday, \u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u044b \u043d\u0435\u0434\u0430\u0432\u043d\u043e \u043f\u0438\u0441\u0430\u043b\u0438, \u043f\u043e\u043c\u0438\u043c\u043e \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043a\u0440\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0443\u044f\u0437\u0432\u0438\u043c\u043e\u0441\u0442\u0435\u0439, \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u0430\u043a\u0442\u0438\u0432\u043d\u043e \u044d\u043a\u0441\u043f\u043b\u0443\u0430\u0442\u0438\u0440\u0443\u0435\u043c\u044b\u0445 \u0432 \u0434\u0438\u043a\u043e\u0439 \u043f\u0440\u0438\u0440\u043e\u0434\u0435, \u043d\u0430\u043f\u0440\u043e\u0447\u044c \u043f\u043e\u043b\u043e\u043c\u0430\u043b\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u043f\u0435\u0447\u0430\u0442\u0438.\n \n\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u043e\u0439 Windows \u0436\u0430\u043b\u0443\u044e\u0442\u0441\u044f \u043d\u0430 \u043e\u0448\u0438\u0431\u043a\u0438 0x0000011b \u043f\u0440\u0438 \u043f\u0435\u0447\u0430\u0442\u0438 \u043d\u0430 \u0441\u0435\u0442\u0435\u0432\u044b\u0445 \u043f\u0440\u0438\u043d\u0442\u0435\u0440\u0430\u0445. \u042d\u0442\u0430 \u043e\u0448\u0438\u0431\u043a\u0430 \u043f\u0435\u0447\u0430\u0442\u0438 \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u043d\u0430\u0431\u043b\u044e\u0434\u0430\u0435\u0442\u0441\u044f \u0432 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044f\u0445 \u0438 \u0434\u043e\u043c\u0430\u0448\u043d\u0438\u0445 \u0441\u0435\u0442\u044f\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u043c\u043e\u0433\u0443\u0442 \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u043e\u0439 Kerberos \u0432 \u0434\u043e\u043c\u0435\u043d\u0435 Windows.\n \n\u0412\u0441\u0435 \u0434\u0435\u043b\u043e \u0432 \u043f\u0440\u0435\u0441\u043b\u043e\u0432\u0443\u0442\u043e\u0439 PrintNightmare - \u0443\u044f\u0437\u0432\u0438\u043c\u043e\u0441\u0442\u0438 \u043f\u043e\u0434\u043c\u0435\u043d\u044b \u0434\u0438\u0441\u043f\u0435\u0442\u0447\u0435\u0440\u0430 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u043f\u0435\u0447\u0430\u0442\u0438 Windows (CVE-2021-1678). \u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u0432 \u041e\u0421 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0431\u044b\u043b \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u043e\u0432\u0430\u043d \u043a\u043b\u044e\u0447 \u0440\u0435\u0435\u0441\u0442\u0440\u0430: [HKEY_LOCAL_MACHINE \\ System \\ CurrentControlSet \\ Control \\ Print] \u00abRpcAuthnLevelPrivacyEnabled\u00bb = \u0434\u0432\u043e\u0439\u043d\u043e\u0435 \u0441\u043b\u043e\u0432\u043e: 00000001, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043f\u043e\u0432\u044b\u0448\u0435\u043d\u0438\u044f \u0443\u0440\u043e\u0432\u043d\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043f\u043e\u0434\u043b\u0438\u043d\u043d\u043e\u0441\u0442\u0438 RPC, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u043e\u0433\u043e \u0434\u043b\u044f \u0441\u0435\u0442\u0435\u0432\u043e\u0439 \u043f\u0435\u0447\u0430\u0442\u0438, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u043a\u0440\u044b\u0442\u044c \u0443\u044f\u0437\u0432\u0438\u043c\u043e\u0441\u0442\u044c.\n \n\u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0441\u0435\u043d\u0442\u044f\u0431\u0440\u044c\u0441\u043a\u0438\u0445 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 Windows \u0440\u0435\u0448\u0438\u0442 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443, \u043d\u043e \u0432 \u0442\u0430\u043a\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u0431\u0443\u0434\u0443\u0442 \u0443\u044f\u0437\u0432\u0438\u043c\u044b \u0438 \u0434\u043b\u044f PrintNightmare, \u0438 \u0434\u043b\u044f MSHTML.\n \n\u041f\u043e\u0436\u0430\u043b\u0443\u0439, \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u043c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0437\u0430\u0449\u0438\u0442\u044b \u043e\u0442 CVE-2021-1678 \u0434\u043e \u0442\u0435\u0445 \u043f\u043e\u0440, \u043f\u043e\u043a\u0430 Microsoft \u043d\u0435 \u0432\u044b\u043f\u0443\u0441\u0442\u0438\u0442 \u043d\u043e\u0432\u043e\u0435 \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u043e.\n \n\u0427\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u043d\u0435\u0434\u0430\u0432\u043d\u0438\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u043f\u0435\u0447\u0430\u0442\u0438 0x0000011b \u0431\u0435\u0437 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u0442\u0435\u043a\u0443\u0449\u0438\u0445 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439 Windows (KB5005565), \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u0442\u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043b\u044e\u0447 \u0440\u0435\u0435\u0441\u0442\u0440\u0430 \u0434\u043b\u044f CVE-2021-1678. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 \u0440\u0435\u0435\u0441\u0442\u0440\u0430: HKEY_LOCAL_MACHINE \\ System \\ CurrentControlSet \\ Control \\ Print, \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u043e\u0435 32-\u0431\u0438\u0442\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 DWORD \u0441 \u0438\u043c\u0435\u043d\u0435\u043c RpcAuthnLevelPrivacyEnabled \u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0434\u043b\u044f \u043d\u0435\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 0. \u041b\u0438\u0431\u043e \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0438\u043b\u0430\u0433\u0430\u0435\u043c\u044b\u043c \u0444\u0430\u0439\u043b\u043e\u043c \u0440\u0435\u0435\u0441\u0442\u0440\u0430.\n \n\u041d\u043e \u043f\u043e\u043c\u043d\u0438\u0442\u0435, \u043a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u044b \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u0432\u044b \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442\u0435 \u0437\u0430\u0449\u0438\u0449\u0435\u043d\u044b \u043e\u0442 \u0443\u044f\u0437\u0432\u0438\u043c\u043e\u0441\u0442\u0438, \u043d\u043e \u044d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0441\u043d\u043e\u0432\u0430 \u043f\u0435\u0447\u0430\u0442\u0430\u0442\u044c. \u0415\u0441\u043b\u0438 \u044d\u0442\u043e \u043d\u0435 \u0440\u0435\u0448\u0438\u0442 \u0432\u0430\u0448\u0443 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443, \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u0435\u0440\u043d\u0438\u0442\u0435\u0441\u044c \u043a \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c Windows \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e.\n \n\u041f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u043e \u043e\u0434\u043d\u043e: \u0432\u0441\u0435 \u0436\u0435 Microsoft \u043e\u0441\u0442\u0430\u0432\u0438\u043b\u0438 \u0445\u043e\u0442\u044c \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u0432\u044b\u0431\u043e\u0440, \u043d\u043e \u0437\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u0441\u0442\u0432\u0438\u044f \u043e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c.", "creation_timestamp": "2021-09-21T15:42:41.000000Z"}, {"uuid": "e604518e-79b1-44d3-b7c6-7524fb79e42d", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2021-1678", "type": "seen", "source": "https://gist.github.com/shreeshyamagency78/1e5ff93ec53793ca5dc550bb54051040", "content": "\"\"\"\n\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\n\u2551     Godawari Computers Ultimate Optimizer Pro - v11.0           \u2551\n\u2551     Professional Edition | Real Actions | Before/After Stats    \u2551\n\u2551     Developed by: Shravan Shrimali                               \u2551\n\u2551     FULLY FIXED - READY TO RUN                                   \u2551\n\u255a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255d\n\"\"\"\n\nimport sys\nimport os\nimport struct\nimport subprocess\nimport platform\nimport base64\nimport re\nimport io\nimport zlib\nimport csv\nimport hashlib\nimport sqlite3\nimport zipfile\nimport html\nimport uuid\n\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n#  SAFE STARTUP \u2014 errors ko pakdo, user ko batao\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n# 1) Windows check\nif platform.system() != \"Windows\":\n    print(\"\u274c Yeh tool sirf Windows ke liye hai.\")\n    input(\"Press Enter to exit...\")\n    sys.exit(1)\n\n# 2) tkinter check\ntry:\n    import tkinter as tk\n    from tkinter import ttk, messagebox, scrolledtext, filedialog, simpledialog\nexcept ImportError:\n    print(\"\u274c tkinter nahi mila. Python ko reinstall karo (Include Tcl/Tk checkbox tick karo).\")\n    input(\"Press Enter to exit...\")\n    sys.exit(1)\n\n# 3) psutil offline dependency check\ndef _ensure_psutil():\n    try:\n        import psutil\n        return psutil\n    except ImportError:\n        try:\n            root = tk.Tk(); root.withdraw()\n            messagebox.showerror(\n                \"psutil Missing\",\n                \"psutil library nahi mili.\\n\\n\"\n                \"Runtime internet install disabled hai production/offline safety ke liye.\\n\"\n                \"Portable package me psutil bundled rakhein ya offline wheel se install karein.\")\n            root.destroy()\n            sys.exit(1)\n        except Exception as e:\n            print(f\"psutil dependency error: {e}\")\n            input(\"Press Enter to exit...\")\n            sys.exit(1)\n\npsutil = _ensure_psutil()\n\n# 4) winreg (Windows built-in \u2014 should always exist on Windows)\ntry:\n    import winreg\nexcept ImportError:\n    root = tk.Tk(); root.withdraw()\n    messagebox.showerror(\"Error\", \"winreg module nahi mila.\\nPython Windows version use karo.\")\n    root.destroy()\n    sys.exit(1)\n\n# 5) Standard library imports\nimport threading\nimport queue as _queue_module\nimport ctypes\nimport json\n\n# Windows DPI awareness ensures UI scales correctly on high-DPI displays.\nif sys.platform == \"win32\":\n    try:\n        ctypes.windll.shcore.SetProcessDpiAwareness(1)\n    except Exception:\n        pass\nimport datetime\nimport time\nimport shutil\nfrom pathlib import Path\nimport gc\nimport tempfile\nimport collections\n\ntry:\n    from godawari.optimization_profiles import get_cleaner_profiles, get_group_policy_profiles\nexcept ImportError:\n    def get_cleaner_profiles():\n        import os\n        return {\n            \"safe\": {\n                \"name\": \"Safe Clean\",\n                \"description\": \"Temp files, recycle bin, thumbnail cache \u2014 bilkul safe\",\n                \"paths\": [\n                    os.environ.get(\"TEMP\", \"\"),\n                    os.path.join(os.environ.get(\"LOCALAPPDATA\", \"\"), \"Temp\"),\n                    r\"C:\\Windows\\Temp\",\n                    os.path.join(os.environ.get(\"LOCALAPPDATA\", \"\"), \"Microsoft\", \"Windows\", \"Explorer\"),\n                ],\n                \"commands\": []\n            },\n            \"deep\": {\n                \"name\": \"Deep Clean\",\n                \"description\": \"Windows Update cache, prefetch, installer cache\",\n                \"paths\": [\n                    r\"C:\\Windows\\SoftwareDistribution\\Download\",\n                    r\"C:\\Windows\\Prefetch\",\n                ],\n                \"commands\": [\n                    'cleanmgr /sageset:99',\n                    'cleanmgr /sagerun:99',\n                ]\n            }\n        }\n\n    def get_group_policy_profiles():\n        return {\n            \"performance\": {\n                \"name\": \"Performance Mode\",\n                \"policies\": [\n                    {\"hive\": \"HKLM\",\n                     \"key\": r\"SOFTWARE\\Policies\\Microsoft\\Windows\\DataCollection\",\n                     \"name\": \"AllowTelemetry\", \"value\": 0, \"type\": \"DWORD\"},\n                    {\"hive\": \"HKLM\",\n                     \"key\": r\"SOFTWARE\\Policies\\Microsoft\\Windows\\CloudContent\",\n                     \"name\": \"DisableWindowsConsumerFeatures\", \"value\": 1, \"type\": \"DWORD\"},\n                ]\n            }\n        }\n\n\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n#  SAFE SUBPROCESS HELPERS (inline implementation)\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nclass SafeRunResult:\n    def __init__(self, output, returncode, args=None,\n                 elapsed_ms=0, timed_out=False):\n        self.output     = output\n        self.returncode = returncode\n        self.args       = args or []\n        self.elapsed_ms = elapsed_ms\n        self.timed_out  = timed_out\n\nclass PowerShellResult:\n    def __init__(self, output, returncode, elapsed_ms=0, timed_out=False):\n        self.output     = output\n        self.returncode = returncode\n        self.elapsed_ms = elapsed_ms\n        self.timed_out  = timed_out\n        self.args       = []\n\ndef safe_powershell(script, timeout=60):\n    \"\"\"Safe PowerShell execution wrapper\"\"\"\n    started = time.time()\n    try:\n        startupinfo = None\n        creationflags = 0\n        if sys.platform == \"win32\":\n            startupinfo = subprocess.STARTUPINFO()\n            startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW\n            creationflags = subprocess.CREATE_NO_WINDOW\n        encoded = base64.b64encode(script.encode(\"utf-16-le\")).decode(\"ascii\")\n        env = os.environ.copy()\n        env[\"PSModuleAnalysisCacheWriteDisabled\"] = \"1\"\n        result = subprocess.run(\n            [\"powershell\", \"-NoProfile\", \"-ExecutionPolicy\", \"Bypass\", \"-EncodedCommand\", encoded],\n            capture_output=True,\n            text=True,\n            encoding=\"utf-8\",\n            errors=\"replace\",\n            timeout=timeout,\n            startupinfo=startupinfo,\n            creationflags=creationflags,\n            env=env,\n        )\n        elapsed = int((time.time() - started) * 1000)\n        return PowerShellResult(\n            result.stdout, result.returncode, elapsed_ms=elapsed)\n    except subprocess.TimeoutExpired:\n        elapsed = int((time.time() - started) * 1000)\n        return PowerShellResult(\n            \"Timeout\", -1, elapsed_ms=elapsed, timed_out=True)\n    except Exception as e:\n        return PowerShellResult(str(e), -1)\n\ndef safe_run(cmd, timeout=60):\n    \"\"\"Safe command execution wrapper\"\"\"\n    started = time.time()\n    try:\n        result = subprocess.run(\n            cmd, capture_output=True, text=True, timeout=timeout)\n        elapsed = int((time.time() - started) * 1000)\n        return SafeRunResult(\n            result.stdout, result.returncode,\n            args=list(cmd), elapsed_ms=elapsed)\n    except subprocess.TimeoutExpired:\n        elapsed = int((time.time() - started) * 1000)\n        return SafeRunResult(\n            \"Timeout\", -1,\n            args=list(cmd), elapsed_ms=elapsed, timed_out=True)\n    except Exception as e:\n        return SafeRunResult(\n            str(e), -1,\n            args=list(cmd) if isinstance(cmd, (list, tuple)) else [])\n\ndef safe_stream_lines(cmd, callback=None):\n    \"\"\"Safe streaming command execution\"\"\"\n    try:\n        process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)\n        for line in iter(process.stdout.readline, \"\"):\n            if line and callback:\n                callback(line.strip())\n        process.wait()\n    except Exception as e:\n        if callback:\n            callback(f\"Error: {e}\")\n\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n#  WORKER MANAGER &amp; STRUCTURED LOGGER STUBS\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nclass TkWorkerManager:\n    \"\"\"Manages background worker threads for the GUI.\"\"\"\n    def __init__(self, root, workers=3, logger=None):\n        self.root = root\n        self.workers = max(1, int(workers or 1))\n        self.logger = logger\n        self._task_queue = _queue_module.Queue()\n        self._workers = []\n        # Consult global startup flags: if safe_mode is enabled, do not start\n        # background worker threads automatically.\n        _safe_mode = False\n        try:\n            from godawari import startup_control as _startup_control\n            _safe_mode = bool(_startup_control.STARTUP_FLAGS.get(\"safe_mode\", False))\n        except Exception:\n            _safe_mode = False\n\n        if not _safe_mode:\n            for _ in range(self.workers):\n                worker = threading.Thread(target=self._worker_loop, daemon=True)\n                worker.start()\n                self._workers.append(worker)\n        else:\n            if self.logger:\n                try:\n                    self.logger.log(\"startup\", \"Safe-mode enabled: GUI worker threads not started\", {})\n                except Exception:\n                    pass\n\n    def _worker_loop(self):\n        while True:\n            name, target, args, kwargs = self._task_queue.get()\n            try:\n                target(*args, **kwargs)\n            except Exception as e:\n                if self.logger:\n                    try:\n                        self.logger.log(\"worker_error\", f\"Worker task '{name}' failed\", {\"error\": str(e)})\n                    except Exception:\n                        pass\n                try:\n                    if hasattr(self.root, \"after\"):\n                        def _report(msg=str(e), task=name):\n                            if hasattr(self.root, \"_set_status\"):\n                                self.root._set_status(f\"Background task '{task}' failed: {msg}\", C.get(\"error\", \"red\"))\n                        self.root.after(0, _report)\n                except Exception:\n                    continue\n            finally:\n                try:\n                    self._task_queue.task_done()\n                except Exception:\n                    pass\n\n    def submit(self, name, target, *args, **kwargs):\n        try:\n            self._task_queue.put_nowait((name, target, args, kwargs))\n        except Exception:\n            threading.Thread(target=target, args=args, kwargs=kwargs, daemon=True).start()\n\n# \u2500\u2500 Enterprise modular backend (godawari package) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n_SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))\nif _SCRIPT_DIR not in sys.path:\n    sys.path.insert(0, _SCRIPT_DIR)\ntry:\n    from godawari.system.powershell_tools import (\n        SafeRunResult,\n        PowerShellResult,\n        safe_powershell,\n        safe_run,\n        safe_stream_lines,\n    )\n    from godawari.system.admin_tools import is_admin, run_as_admin\n    from godawari.services.logger import StructuredLogger\n    from godawari.services.restore_points import RestorePointManager\n    from godawari.services.rollback import OperationRollbackVault\n    from godawari.services.session_manager import RecoverySessionManager\n    from godawari.core.health_engine import SystemHealthEngine\n    from godawari.core.menu_introspection import MenuIntrospectionEngine\n    from godawari.core.product_audit import ProductAuditEngine\n    from godawari.core.recommendations import RecommendationEngine\n    from godawari.services.maintenance_profiles import MaintenanceProfileEngine\n    from godawari.security.preflight import OperationPreflightEngine\n    from godawari.security.powershell_guard import SecurePowerShellEngine\n    from godawari.services.crash_recovery import CrashRecoveryCoordinator\n    from godawari.bootstrap import create_backend\n    _GODAWARI_BACKEND = True\nexcept ImportError:\n    _GODAWARI_BACKEND = False\n\nif not _GODAWARI_BACKEND:\n    # Minimal inline fallback \u2014 full backend: run via python main.py from project root\n    class StructuredLogger:\n        def __init__(self, log_file=\"\"):\n            self.log_file = log_file or \"\"\n        def log(self, event_type, message, data=None):\n            pass\n        def event(self, category, action, **kwargs):\n            pass\n        def read_recent(self, limit=200):\n            return []\n\n    class RestorePointManager:\n        def __init__(self, base_dir, logger=None):\n            self.base_dir = base_dir\n            self.logger = logger\n            self.policy = {\"mode\": \"ask\"}\n        def create(self, description, ask_callback=None, force=False):\n            if ask_callback and not ask_callback(description):\n                return False\n            return safe_powershell(\n                f'Checkpoint-Computer -Description \"{description}\" -RestorePointType MODIFY_SETTINGS',\n                timeout=120,\n            ).returncode == 0\n        def list_recent(self, limit=8):\n            return []\n\n    class OperationRollbackVault:\n        def __init__(self, vault_dir, logger=None):\n            self.vault_dir = vault_dir\n        def list_sessions(self, limit=50):\n            return []\n        def restore_session(self, session_id):\n            return False, \"Rollback vault unavailable\"\n\n    class RecoverySessionManager:\n        def __init__(self, sessions_dir, logger=None):\n            self.sessions_dir = sessions_dir\n        def start(self, kind, meta=None):\n            return uuid.uuid4().hex\n        def complete(self, session_id, status=\"completed\"):\n            pass\n        def list_sessions(self, include_completed=False, limit=30):\n            return []\n        def find_orphaned(self):\n            return []\n\n    class SystemHealthEngine:\n        def analyze(self):\n            return {\"score\": 0, \"grade\": \"Unknown\", \"color\": \"warning\", \"checks\": [], \"recommendations\": []}\n\n    class SecurePowerShellEngine:\n        def __init__(self, logger=None):\n            self.logger = logger\n        def run(self, script, timeout=60):\n            return safe_powershell(script, timeout=timeout)\n\n    class ProductAuditEngine:\n        def list_audits(self):\n            return []\n        def summary(self):\n            return {\"menus\": 0, \"average_maturity\": 0, \"highest_risk\": []}\n        def to_markdown(self, audits=None):\n            return \"# Godawari Optimizer Pro - Professional Menu Audit\\n\\nBackend unavailable.\\n\"\n\n    class MenuIntrospectionEngine:\n        def scan(self):\n            return {\"menus\": [], \"menu_count\": 0, \"button_count\": 0, \"option_count\": 0}\n        def to_markdown(self):\n            return \"# Godawari Optimizer Pro - Detected Software Map\\n\\nBackend unavailable.\\n\"\n\n    class OperationPreflightEngine:\n        def analyze(self, title, commands=None):\n            class _Result:\n                risk = \"medium\"\n                score = 50\n                requires_admin = True\n                requires_restore_point = True\n                requires_rollback_snapshot = True\n                dry_run_recommended = True\n                typed_confirmation = False\n                findings = []\n            return _Result()\n\n    class RecommendationEngine:\n        def build(self, health_report, audits, limit=10):\n            return {\"generated\": \"\", \"count\": 0, \"items\": []}\n\n    class MaintenanceProfileEngine:\n        def list_profiles(self):\n            return []\n\n    class CrashRecoveryCoordinator:\n        def __init__(self, session_manager, marker_file):\n            self.session_manager = session_manager\n            self.marker_file = marker_file\n        def mark_running(self):\n            pass\n        def clear_running(self):\n            pass\n        def had_unclean_exit(self):\n            return False\n        def orphaned_sessions(self):\n            return []\n\n# Legacy duplicate classes removed \u2014 use godawari package (see main.py)\n\n# \u2500\u2500 Recovery/Forensics stubs (when godawari package unavailable) \u2500\u2500\ntry:\n    from godawari.recovery.manager import RecoveryManager\n    from godawari.recovery.results import RecoveryResultItem, RecoveryResultStore\n    from godawari.recovery.safety import get_recovery_safety\n    from godawari.recovery.validation import validate_recovered_file\n    from godawari.recovery.mft import recover_deleted_mft_files\n    from godawari.recovery.progress import make_progress_callback\n    from godawari.forensics import (\n        is_forensic_engine_available,\n        scan_disk_with_forensic_engine,\n        scan_disk_entropy,\n        validate_media_headers,\n        detect_nand_erase_state,\n        raw_read,\n    )\n    import math\nexcept ImportError:\n    import math\n\n    class RecoveryResultItem:\n        def __init__(self, *a, **kw): pass\n\n    class RecoveryResultStore:\n        def __init__(self, *a, **kw): self._items = []\n        def add(self, item): self._items.append(item)\n        def all(self): return self._items\n        def clear(self): self._items = []\n        def count(self): return len(self._items)\n\n    class RecoveryManager:\n        def __init__(self, *a, **kw): pass\n        def start(self, *a, **kw): return None\n        def stop(self): pass\n\n    def get_recovery_safety(*a, **kw):\n        class _Safety:\n            def validate_output_dir(self, d, *a): return d\n        return _Safety()\n\n    def validate_recovered_file(*a, **kw): return True\n    def recover_deleted_mft_files(*a, **kw): return []\n    def make_progress_callback(*a, **kw): return lambda *x: None\n    def is_forensic_engine_available(): return False\n    def scan_disk_with_forensic_engine(*a, **kw): return []\n    def scan_disk_entropy(*a, **kw): return []\n    def validate_media_headers(*a, **kw): return {}\n    def detect_nand_erase_state(*a, **kw): return False\n    def raw_read(*a, **kw): return b\"\"\n\n\n# 6) Global exception handler \u2014 koi bhi crash user ko dikhai de\ndef _global_exc_handler(exc_type, exc_value, exc_tb):\n    import traceback\n    err = \"\".join(traceback.format_exception(exc_type, exc_value, exc_tb))\n    try:\n        root = tk.Tk(); root.withdraw()\n        messagebox.showerror(\"Unexpected Error \u2014 Godawari Optimizer\",\n            f\"Ek error aayi:\\n\\n{err[-800:]}\\n\\n\"\n            \"Screenshot lo aur developer ko bhejo.\")\n        root.destroy()\n    except:\n        print(\"FATAL ERROR:\\n\", err)\n        input(\"Press Enter to exit...\")\n    sys.exit(1)\n\nsys.excepthook = _global_exc_handler\n\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n#  SCRIPT LAST UPDATED \u2014 File modification time\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\ndef _get_script_last_updated():\n    \"\"\"Script file ki last modification date/time return karta hai.\"\"\"\n    try:\n        script_path = os.path.abspath(sys.argv[0])\n        if os.path.exists(script_path):\n            mtime = os.path.getmtime(script_path)\n            dt = datetime.datetime.fromtimestamp(mtime)\n            return dt.strftime(\"%d/%m/%Y  %H:%M\")\n    except Exception:\n        pass\n    return \"Unknown\"\n\nSCRIPT_LAST_UPDATED = _get_script_last_updated()\n\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n#  ADMIN CHECK\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\ndef is_admin():\n    try:\n        return bool(ctypes.windll.shell32.IsUserAnAdmin())\n    except Exception:\n        return False\n\ndef _gui_python_executable():\n    \"\"\"Use pythonw for GUI relaunch so the console window does not flash.\"\"\"\n    exe = sys.executable\n    try:\n        if exe and os.path.basename(exe).lower() == \"python.exe\":\n            pythonw = os.path.join(os.path.dirname(exe), \"pythonw.exe\")\n            if os.path.exists(pythonw):\n                return pythonw\n    except Exception:\n        pass\n    return exe\n\ndef run_as_admin():\n    if not is_admin():\n        script = os.path.abspath(sys.argv[0])\n        params = subprocess.list2cmdline([script] + sys.argv[1:])\n        workdir = os.path.dirname(script) or None\n        rc = ctypes.windll.shell32.ShellExecuteW(\n            None, \"runas\", _gui_python_executable(), params, workdir, 1\n        )\n        if rc &lt;= 32:\n            raise OSError(f\"Admin restart failed. ShellExecuteW code: {rc}\")\n        sys.exit()\n\ndef _admin_elevation_enabled():\n    return os.environ.get(\"GODAWARI_NO_ELEVATE\", \"0\").lower() not in (\"1\", \"true\", \"yes\")\n\ndef powershell_helper(script, timeout=60):\n    \"\"\"PowerShell helper: returns (output, return_code) with full error handling.\"\"\"\n    try:\n        result = safe_powershell(script, timeout=timeout)\n        return result.output, result.returncode\n    except FileNotFoundError:\n        return \"PowerShell nahi mila.\", -1\n    except Exception as e:\n        return f\"PowerShell error: {e}\", -1\n\ndef _ps_single_quote(value):\n    return \"'\" + str(value).replace(\"'\", \"''\") + \"'\"\n\ndef _same_windows_path(left, right):\n    try:\n        return os.path.normcase(os.path.abspath(left)) == os.path.normcase(os.path.abspath(right))\n    except Exception:\n        return False\n\ndef _console_confirm(title, message):\n    print(\"\\n\" + \"=\" * 70)\n    print(title)\n    print(\"=\" * 70)\n    print(message)\n    try:\n        answer = input(\"\\nConfirm karein? (haan/y = yes): \").strip().lower()\n        return answer in (\"y\", \"yes\", \"haan\", \"ha\", \"h\")\n    except Exception:\n        return False\n\ndef _safe_callback(callback, *args):\n    if callback:\n        try:\n            callback(*args)\n        except InterruptedError:\n            raise\n        except Exception:\n            return \"unknown\"\n\ndef _find_locking_processes_with_psutil(file_path):\n    matches = {}\n    for proc in psutil.process_iter([\"pid\", \"name\", \"exe\"]):\n        try:\n            pid = proc.info.get(\"pid\")\n            if pid == os.getpid():\n                continue\n            paths = []\n            exe = proc.info.get(\"exe\")\n            if exe:\n                paths.append(exe)\n            try:\n                for opened in proc.open_files() or []:\n                    if getattr(opened, \"path\", None):\n                        paths.append(opened.path)\n            except (psutil.AccessDenied, psutil.NoSuchProcess, psutil.ZombieProcess):\n                pass\n            if any(_same_windows_path(p, file_path) for p in paths):\n                matches[int(pid)] = {\n                    \"pid\": int(pid),\n                    \"name\": proc.info.get(\"name\") or \"Unknown\",\n                    \"exe\": exe or \"\",\n                    \"source\": \"psutil\",\n                }\n        except (psutil.AccessDenied, psutil.NoSuchProcess, psutil.ZombieProcess):\n            continue\n        except Exception:\n            continue\n    return matches\n\ndef _find_locking_processes_with_powershell(file_path):\n    # PowerShell fallback requested:\n    # Get-Process | Where-Object {$_.Modules.FileName -contains file}\n    target = _ps_single_quote(file_path)\n    script = f\"\"\"\n$target = {target}\nGet-Process | Where-Object {{\n    try {{ $_.Modules.FileName -contains $target }} catch {{ $false }}\n}} | ForEach-Object {{\n    $p = ''\n    try {{ $p = $_.Path }} catch {{ $p = '' }}\n    \"$($_.Id)|$($_.ProcessName)|$p\"\n}}\n\"\"\"\n    output, rc = powershell_helper(script, timeout=90)\n    matches = {}\n    if rc != 0 and not output:\n        return matches\n    for line in output.splitlines():\n        parts = line.strip().split(\"|\", 2)\n        if len(parts) &lt; 2 or not parts[0].isdigit():\n            continue\n        pid = int(parts[0])\n        if pid == os.getpid():\n            continue\n        matches[pid] = {\n            \"pid\": pid,\n            \"name\": parts[1] or \"Unknown\",\n            \"exe\": parts[2] if len(parts) &gt; 2 else \"\",\n            \"source\": \"powershell\",\n        }\n    return matches\n\ndef _format_process_list(processes):\n    lines = []\n    for item in processes:\n        exe = item.get(\"exe\") or \"Path unavailable\"\n        lines.append(f\"PID {item['pid']} - {item.get('name', 'Unknown')} - {exe} [{item.get('source','')}]\")\n    return \"\\n\".join(lines)\n\ndef unlock_file_if_locked(file_path, confirm_callback=None, log_callback=None):\n    \"\"\"\n    Locked file ko release karne ke liye process scan karta hai.\n    psutil first, PowerShell Modules fallback, PID show, user confirm, then terminate.\n    \"\"\"\n    try:\n        target = os.path.abspath(os.path.expandvars(os.path.expanduser(str(file_path).strip().strip('\"'))))\n        if not target:\n            raise ValueError(\"File path empty hai.\")\n        if not os.path.exists(target):\n            raise FileNotFoundError(f\"File nahi mili: {target}\")\n\n        _safe_callback(log_callback, f\"Locked file scan start: {target}\")\n        matches = _find_locking_processes_with_psutil(target)\n        ps_matches = _find_locking_processes_with_powershell(target)\n        matches.update(ps_matches)\n\n        processes = sorted(matches.values(), key=lambda x: x[\"pid\"])\n        if not processes:\n            msg = \"Koi locking process nahi mila. File abhi locked nahi lag rahi.\"\n            _safe_callback(log_callback, msg)\n            print(msg)\n            return {\"ok\": True, \"file\": target, \"terminated\": [], \"errors\": [], \"message\": msg}\n\n        details = _format_process_list(processes)\n        prompt = (\n            f\"Ye process file use kar rahe hain:\\n\\n{details}\\n\\n\"\n            \"In PID ko terminate karne se unsaved data loss ho sakta hai.\\n\"\n            \"Terminate karna hai?\"\n        )\n        confirm = confirm_callback or _console_confirm\n        if not confirm(\"Locked File Unlock\", prompt):\n            msg = \"User ne terminate cancel kiya.\"\n            _safe_callback(log_callback, msg)\n            return {\"ok\": False, \"file\": target, \"terminated\": [], \"errors\": [], \"message\": msg}\n\n        terminated = []\n        errors = []\n        for info in processes:\n            pid = info[\"pid\"]\n            try:\n                proc = psutil.Process(pid)\n                proc.terminate()\n                try:\n                    proc.wait(timeout=8)\n                except psutil.TimeoutExpired:\n                    pass\n                terminated.append(pid)\n                _safe_callback(log_callback, f\"PID terminate kiya: {pid} ({info.get('name','Unknown')})\")\n            except psutil.NoSuchProcess:\n                terminated.append(pid)\n            except psutil.AccessDenied:\n                errors.append(f\"PID {pid}: access denied. Admin mode me run karein.\")\n            except Exception as e:\n                errors.append(f\"PID {pid}: {e}\")\n\n        ok = len(errors) == 0\n        msg = f\"Terminate complete. Terminated: {len(terminated)}, Errors: {len(errors)}\"\n        _safe_callback(log_callback, msg)\n        if errors:\n            _safe_callback(log_callback, \"\\n\".join(errors))\n        return {\"ok\": ok, \"file\": target, \"terminated\": terminated, \"errors\": errors, \"message\": msg}\n    except Exception as e:\n        msg = f\"Unlock error: {e}\"\n        _safe_callback(log_callback, msg)\n        print(msg)\n        return {\"ok\": False, \"file\": str(file_path), \"terminated\": [], \"errors\": [msg], \"message\": msg}\n\ndef _human_size(num_bytes):\n    try:\n        value = float(num_bytes)\n        for unit in (\"B\", \"KB\", \"MB\", \"GB\", \"TB\"):\n            if value &lt; 1024 or unit == \"TB\":\n                return f\"{value:.1f} {unit}\" if unit != \"B\" else f\"{int(value)} B\"\n            value /= 1024\n    except Exception:\n        return \"0 B\"\n\ndef _is_dangerous_cleanup_target(folder_path):\n    try:\n        path = os.path.normcase(os.path.abspath(folder_path))\n        drive, tail = os.path.splitdrive(path)\n        if tail in (\"\\\\\", \"\"):\n            return True, \"Drive root delete nahi kar sakte.\"\n        protected = [\n            os.environ.get(\"SystemRoot\", r\"C:\\Windows\"),\n            os.environ.get(\"ProgramFiles\", r\"C:\\Program Files\"),\n            os.environ.get(\"ProgramFiles(x86)\", r\"C:\\Program Files (x86)\"),\n            os.environ.get(\"ProgramData\", r\"C:\\ProgramData\"),\n            os.environ.get(\"USERPROFILE\", \"\"),\n        ]\n        for item in protected:\n            if item and path == os.path.normcase(os.path.abspath(item)):\n                return True, f\"Protected folder delete block kiya: {item}\"\n    except Exception as e:\n        return True, f\"Path safety check failed: {e}\"\n    return False, \"\"\n\ndef _program_terms_from_folder(folder_path):\n    base = os.path.basename(os.path.normpath(folder_path)).lower()\n    raw = \"\".join(ch if ch.isalnum() else \" \" for ch in base).split()\n    blocked = {\"app\", \"program\", \"files\", \"setup\", \"install\", \"windows\", \"system\"}\n    return [w for w in raw if len(w) &gt;= 3 and w not in blocked]\n\ndef _registry_value_text(key):\n    chunks = []\n    try:\n        i = 0\n        while True:\n            try:\n                name, value, _ = winreg.EnumValue(key, i)\n                chunks.append(str(name))\n                chunks.append(str(value))\n                i += 1\n            except OSError:\n                break\n    except Exception:\n        pass\n    return \" \".join(chunks).lower()\n\ndef _find_registry_entries_for_program(folder_path, max_results=100):\n    folder_text = os.path.normcase(os.path.abspath(folder_path)).lower()\n    terms = _program_terms_from_folder(folder_path)\n    if not terms:\n        terms = [os.path.basename(os.path.normpath(folder_path)).lower()]\n    roots = [\n        (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\"),\n        (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\"),\n        (\"HKCU\", winreg.HKEY_CURRENT_USER, r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\"),\n        (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\"),\n        (\"HKCU\", winreg.HKEY_CURRENT_USER, r\"SOFTWARE\"),\n        (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Services\"),\n    ]\n    found = []\n    deadline = time.time() + 8\n\n    def check_subkey(hive_name, hive, path):\n        if len(found) &gt;= max_results or time.time() &gt; deadline:\n            return\n        try:\n            key = winreg.OpenKey(hive, path, 0, winreg.KEY_READ)\n        except Exception:\n            return\n        try:\n            text = f\"{path.lower()} {_registry_value_text(key)}\"\n            if folder_text in text or any(term in text for term in terms):\n                found.append(f\"{hive_name}\\\\{path}\")\n        finally:\n            try:\n                winreg.CloseKey(key)\n            except Exception:\n                pass\n\n    for hive_name, hive, root_path in roots:\n        if len(found) &gt;= max_results or time.time() &gt; deadline:\n            break\n        try:\n            root = winreg.OpenKey(hive, root_path, 0, winreg.KEY_READ)\n        except Exception:\n            continue\n        try:\n            i = 0\n            while len(found) &lt; max_results and time.time() &lt;= deadline:\n                try:\n                    sub = winreg.EnumKey(root, i)\n                    i += 1\n                    check_subkey(hive_name, hive, root_path + \"\\\\\" + sub)\n                except OSError:\n                    break\n                except Exception:\n                    continue\n        finally:\n            try:\n                winreg.CloseKey(root)\n            except Exception:\n                pass\n    return found\n\ndef _scan_folder_with_os_walk(folder_path, max_preview=80):\n    info = {\"files\": 0, \"dirs\": 0, \"size\": 0, \"preview\": [], \"errors\": []}\n\n    def on_error(error):\n        info[\"errors\"].append(str(error))\n\n    for root, dirs, files in os.walk(folder_path, onerror=on_error):\n        info[\"dirs\"] += len(dirs)\n        for name in files:\n            path = os.path.join(root, name)\n            info[\"files\"] += 1\n            try:\n                info[\"size\"] += os.path.getsize(path)\n            except Exception as e:\n                info[\"errors\"].append(f\"{path}: {e}\")\n            if len(info[\"preview\"]) &lt; max_preview:\n                info[\"preview\"].append(path)\n    return info\n\ndef _rmtree_error_handler(func, path, exc_info):\n    try:\n        os.chmod(path, 0o700)\n        func(path)\n    except Exception:\n        raise\n\ndef deep_cleanup_program(folder_path, confirm_callback=None, log_callback=None):\n    \"\"\"\n    Program folder ka deep cleanup: os.walk scan, winreg registry clues, user confirm, shutil.rmtree.\n    Registry entries sirf list hoti hain; delete folder ko shutil.rmtree se kiya jata hai.\n    \"\"\"\n    try:\n        target = os.path.abspath(os.path.expandvars(os.path.expanduser(str(folder_path).strip().strip('\"'))))\n        if not target:\n            raise ValueError(\"Folder path empty hai.\")\n        if not os.path.isdir(target):\n            raise NotADirectoryError(f\"Folder nahi mila: {target}\")\n\n        blocked, reason = _is_dangerous_cleanup_target(target)\n        if blocked:\n            raise PermissionError(reason)\n\n        admin_note = \"\"\n        if not is_admin():\n            admin_note = \"Warning: App admin mode me nahi hai; kuch files delete nahi ho sakti.\\n\\n\"\n            _safe_callback(log_callback, admin_note.strip())\n\n        _safe_callback(log_callback, f\"Deep cleanup scan start: {target}\")\n        scan = _scan_folder_with_os_walk(target)\n        reg_entries = _find_registry_entries_for_program(target)\n\n        preview = \"\\n\".join(scan[\"preview\"][:40])\n        if scan[\"files\"] &gt; 40:\n            preview += f\"\\n... aur {scan['files'] - 40} file(s)\"\n        reg_preview = \"\\n\".join(reg_entries[:40]) if reg_entries else \"Koi matching registry clue nahi mila.\"\n        if len(reg_entries) &gt; 40:\n            reg_preview += f\"\\n... aur {len(reg_entries) - 40} registry entry\"\n\n        prompt = (\n            f\"{admin_note}\"\n            f\"Folder: {target}\\n\"\n            f\"Files: {scan['files']}\\n\"\n            f\"Subfolders: {scan['dirs']}\\n\"\n            f\"Approx Size: {_human_size(scan['size'])}\\n\"\n            f\"Registry clues: {len(reg_entries)}\\n\"\n        )\n        if scan[\"errors\"]:\n            prompt += f\"Scan warnings: {len(scan['errors'])}\\n\"\n        prompt += (\n            f\"\\nFile list preview:\\n{preview or 'Folder empty hai.'}\\n\\n\"\n            f\"Registry list preview:\\n{reg_preview}\\n\\n\"\n            \"Confirm karne par folder permanently delete hoga:\\n\"\n            \"shutil.rmtree(folder_path)\\n\\n\"\n            \"Delete karein?\"\n        )\n\n        confirm = confirm_callback or _console_confirm\n        if not confirm(\"Deep Cleanup Program\", prompt):\n            msg = \"User ne deep cleanup cancel kiya.\"\n            _safe_callback(log_callback, msg)\n            return {\"ok\": False, \"folder\": target, \"deleted\": False, \"registry_entries\": reg_entries, \"message\": msg}\n\n        shutil.rmtree(target, onerror=_rmtree_error_handler)\n        msg = f\"Deep cleanup complete: {target} delete ho gaya.\"\n        _safe_callback(log_callback, msg)\n        return {\n            \"ok\": True,\n            \"folder\": target,\n            \"deleted\": True,\n            \"files\": scan[\"files\"],\n            \"dirs\": scan[\"dirs\"],\n            \"size\": scan[\"size\"],\n            \"registry_entries\": reg_entries,\n            \"scan_errors\": scan[\"errors\"],\n            \"message\": msg,\n        }\n    except Exception as e:\n        msg = f\"Deep cleanup error: {e}\"\n        _safe_callback(log_callback, msg)\n        print(msg)\n        return {\"ok\": False, \"folder\": str(folder_path), \"deleted\": False, \"registry_entries\": [], \"errors\": [msg], \"message\": msg}\n\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n#  COLOR THEME\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n# ---------------------------------------------------------------------\n# RAW DATA RECOVERY ENGINE\n# ---------------------------------------------------------------------\nSECTOR_SIZE = 512\nDEFAULT_RAW_DISK = \"\"  # User ko disk select karni hogi \u2014 PhysicalDrive0 default unsafe tha\nRAW_READ_RETRIES = 3\nRAW_MIN_READ_CHUNK = 4096\nRAW_SCAN_DEVICE_CHUNK = 2 * 1024 * 1024\nRAW_SCAN_IMAGE_CHUNK = 8 * 1024 * 1024\nRAW_SCAN_OVERLAP = 1024 * 1024\nRAW_SCAN_DEVICE_PAUSE_MS = 25\nRAW_SCAN_PROGRESS_STEP = 32 * 1024 * 1024\n\nSIGNATURES = {\n    \"JPG\": {\n        \"ext\": \".jpg\",\n        \"headers\": [b\"\\xFF\\xD8\\xFF\"],\n        \"footer\": b\"\\xFF\\xD9\",\n        \"max_size\": 50 * 1024 * 1024,\n        \"description\": \"JPEG image\",\n    },\n    \"PDF\": {\n        \"ext\": \".pdf\",\n        \"headers\": [b\"%PDF\"],\n        \"footer\": b\"%%EOF\",\n        \"max_size\": 200 * 1024 * 1024,\n        \"description\": \"PDF document\",\n    },\n    \"MP4\": {\n        \"ext\": \".mp4\",\n        \"headers\": [b\"ftyp\"],\n        \"footer\": None,\n        \"max_size\": 2 * 1024 * 1024 * 1024,\n        \"description\": \"MP4 video\",\n    },\n    \"ZIP\": {\n        \"ext\": \".zip\",\n        \"headers\": [b\"PK\\x03\\x04\"],\n        \"footer\": b\"PK\\x05\\x06\",\n        \"max_size\": 500 * 1024 * 1024,\n        \"description\": \"ZIP archive\",\n    },\n    \"EXE\": {\n        \"ext\": \".exe\",\n        \"headers\": [b\"MZ\"],\n        \"footer\": None,\n        \"max_size\": 200 * 1024 * 1024,\n        \"description\": \"Windows executable\",\n    },\n}\n\ndef _raw_progress(progress_callback, message):\n    _safe_callback(progress_callback, message)\n\ndef _is_raw_device_path(path):\n    return bool(re.match(r\"^\\\\\\\\\\.\\\\(PhysicalDrive\\d+|[A-Z]:)$\", str(path or \"\"), re.I))\n\ndef _require_raw_admin(disk_path=None):\n    if (disk_path is None or _is_raw_device_path(disk_path)) and not is_admin():\n        raise PermissionError(\"Admin rights chahiye. Raw disk access ke liye Run as Administrator karein.\")\n\ndef _powershell_read_raw_bytes(disk_path, offset, length):\n    script = f\"\"\"\n$path = {_ps_single_quote(disk_path)}\n$offset = [Int64]{int(offset)}\n$length = [Int32]{int(length)}\n$fs = [System.IO.File]::Open($path, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::ReadWrite)\ntry {{\n    [void]$fs.Seek($offset, [System.IO.SeekOrigin]::Begin)\n    $buffer = New-Object byte[] $length\n    $read = $fs.Read($buffer, 0, $length)\n    if ($read -le 0) {{ \"\" }} else {{ [Convert]::ToBase64String($buffer, 0, $read) }}\n}} finally {{\n    $fs.Close()\n}}\n\"\"\"\n    output, rc = powershell_helper(script, timeout=120)\n    if rc != 0:\n        raise OSError(f\"PowerShell raw read failed: {output}\")\n    output = output.strip()\n    if not output:\n        return b\"\"\n    try:\n        return base64.b64decode(output)\n    except Exception as e:\n        raise OSError(f\"PowerShell fallback decode failed: {e}. Output: {output[:120]}\")\n\ndef _read_raw_at(disk_path, offset, length, disk_handle=None):\n    if length &lt;= 0:\n        return b\"\"\n    if disk_handle is not None:\n        try:\n            disk_handle.seek(offset)\n            return disk_handle.read(length)\n        except Exception:\n            return \"Unknown\"\n\n    try:\n        from godawari.forensics.engine import raw_read as _forensic_raw_read\n    except Exception:\n        _forensic_raw_read = None\n\n    if _forensic_raw_read is not None:\n        try:\n            return _forensic_raw_read(disk_path, offset, int(length))\n        except Exception:\n            pass\n\n    last_error = None\n    read_len = int(length)\n    for _ in range(RAW_READ_RETRIES):\n        try:\n            with open(disk_path, \"rb\", buffering=0) as disk:\n                disk.seek(offset)\n                return disk.read(read_len)\n        except Exception as e:\n            last_error = e\n            read_len = max(RAW_MIN_READ_CHUNK, read_len // 2)\n    try:\n        return _powershell_read_raw_bytes(disk_path, offset, length)\n    except Exception:\n        if last_error:\n            raise last_error\n        raise\n\ndef _scan_chunk_profile(disk_path, block_size):\n    base = max(int(block_size or SECTOR_SIZE) * 1024, RAW_SCAN_DEVICE_CHUNK)\n    if _is_raw_device_path(disk_path):\n        chunk_size = min(max(base, RAW_SCAN_DEVICE_CHUNK), 4 * 1024 * 1024)\n        pause_s = RAW_SCAN_DEVICE_PAUSE_MS / 1000.0\n    else:\n        chunk_size = min(max(base, RAW_SCAN_IMAGE_CHUNK), 16 * 1024 * 1024)\n        pause_s = 0.0\n    return chunk_size, pause_s\n\ndef _detect_signature_in_sector(sector, sector_offset, file_types):\n    hits = []\n    for file_type in file_types:\n        meta = SIGNATURES.get(file_type)\n        if not meta:\n            continue\n        for header in meta[\"headers\"]:\n            start = 0\n            while True:\n                pos = sector.find(header, start)\n                if pos &lt; 0:\n                    break\n                real_offset = sector_offset + pos\n                confidence = \"medium\"\n                if file_type == \"MP4\":\n                    if pos &lt; 4:\n                        start = pos + 1\n                        continue\n                    box_start = pos - 4\n                    try:\n                        box_size = struct.unpack(\"&gt;I\", sector[box_start:box_start + 4])[0]\n                    except Exception:\n                        box_size = 0\n                    if box_size &lt; 8 or box_size &gt; 1024 * 1024 * 1024:\n                        start = pos + 1\n                        continue\n                    real_offset = sector_offset + box_start\n                    confidence = \"high\"\n                elif pos == 0:\n                    confidence = \"high\"\n                hits.append({\n                    \"disk_path\": \"\",\n                    \"offset\": real_offset,\n                    \"sector\": real_offset // SECTOR_SIZE,\n                    \"file_type\": file_type,\n                    \"extension\": meta[\"ext\"],\n                    \"signature\": header.hex(\" \").upper(),\n                    \"confidence\": confidence,\n                    \"description\": meta[\"description\"],\n                })\n                start = pos + 1\n    return hits\n\ndef scan_disk_for_files(disk_path, max_bytes=None, start_offset=0, file_types=None, progress_callback=None, stats_callback=None):\n    \"\"\"\n    Raw disk ko 512-byte sector-by-sector scan karta hai aur JPG/PDF/MP4/ZIP/EXE signatures dhundta hai.\n    Example: scan_disk_for_files(DEFAULT_RAW_DISK)\n    \"\"\"\n    disk_path = str(disk_path or DEFAULT_RAW_DISK).strip()\n    if not disk_path:\n        raise ValueError(\"Scan ke liye source disk/image select karein\")\n    _require_raw_admin(disk_path)\n    file_types = [ft.upper().strip(\".\") for ft in (file_types or SIGNATURES.keys()) if ft]\n    file_types = [ft for ft in file_types if ft in SIGNATURES]\n    if not file_types:\n        file_types = list(SIGNATURES.keys())\n    chunk_size = 1024 * 1024\n    chunk_size -= chunk_size % SECTOR_SIZE\n    offset = int(start_offset)\n    scanned = 0\n    found = []\n    seen = set()\n    disk = None\n    use_powershell = False\n    total_size = int(max_bytes) if max_bytes is not None else _disk_source_size(disk_path)\n    try:\n        try:\n            from godawari.forensics.engine import scan_disk_with_forensic_engine as _forensic_scan\n        except Exception:\n            _forensic_scan = None\n\n        if _forensic_scan is not None:\n            try:\n                found = _forensic_scan(disk_path, max_bytes=max_bytes, start_offset=offset, file_types=file_types, progress_callback=progress_callback)\n                if found:\n                    return found\n                _raw_progress(progress_callback, \"Forensic scan empty \u2014 Python sector scan fallback\")\n            except Exception as e:\n                _raw_progress(progress_callback, f\"Forensic engine failed, Python fallback use ho raha hai: {e}\")\n\n        try:\n            disk = open(disk_path, \"rb\", buffering=0)\n            disk.seek(offset)\n            _raw_progress(progress_callback, f\"Raw disk open ho gaya: {disk_path}\")\n        except Exception as e:\n            use_powershell = True\n            _raw_progress(progress_callback, f\"Python raw open failed, PowerShell fallback use ho raha hai: {e}\")\n\n        while True:\n            if max_bytes is not None:\n                remaining = int(max_bytes) - scanned\n                if remaining &lt;= 0:\n                    break\n                read_len = min(chunk_size, remaining)\n            else:\n                read_len = chunk_size\n\n            if use_powershell:\n                data = _powershell_read_raw_bytes(disk_path, offset + scanned, read_len)\n            else:\n                data = disk.read(read_len)\n            if not data:\n                break\n\n            usable = len(data) - (len(data) % SECTOR_SIZE)\n            for pos in range(0, usable, SECTOR_SIZE):\n                sector_offset = offset + scanned + pos\n                sector = data[pos:pos + SECTOR_SIZE]\n                for hit in _detect_signature_in_sector(sector, sector_offset, file_types):\n                    key = (hit[\"offset\"], hit[\"file_type\"])\n                    if key in seen:\n                        continue\n                    seen.add(key)\n                    hit[\"disk_path\"] = disk_path\n                    found.append(hit)\n\n            scanned += len(data)\n            if scanned % (4 * 1024 * 1024) &lt; chunk_size:\n                if total_size:\n                    pct = min(100, int((scanned / total_size) * 100))\n                    _raw_progress(progress_callback, f\"Raw scan {pct}% complete \u2014 {_human_size(scanned)} scanned, {len(found)} signatures mili\")\n                else:\n                    _raw_progress(progress_callback, f\"Raw scan: {_human_size(scanned)} scanned, {len(found)} file signature mile\")\n                if stats_callback:\n                    try:\n                        stats_callback({\n                            \"pct\": pct if total_size else min(99, scanned // (32 * 1024 * 1024)),\n                            \"files_found\": len(found),\n                            \"bytes_scanned\": scanned,\n                            \"message\": f\"{len(found)} signatures \u2014 {_human_size(scanned)} scanned\",\n                        })\n                    except Exception:\n                        pass\n    except Exception as e:\n        _raw_progress(progress_callback, f\"Raw scan error: {e}\")\n        raise\n    finally:\n        if disk is not None:\n            try:\n                disk.close()\n            except Exception:\n                pass\n    _raw_progress(progress_callback, f\"Scan complete: {len(found)} signatures mile\")\n    return found\n\ndef _read_until_footer(disk_path, offset, footer, max_size, disk_handle=None, progress_callback=None):\n    data = bytearray()\n    read_pos = int(offset)\n    overlap = max(len(footer) + 16, 64)\n    while len(data) &lt; max_size:\n        to_read = min(1024 * 1024, max_size - len(data))\n        chunk = _read_raw_at(disk_path, read_pos, to_read, disk_handle=disk_handle)\n        if not chunk:\n            break\n        previous_tail = bytes(data[-overlap:])\n        data.extend(chunk)\n        search_area = previous_tail + chunk\n        idx = search_area.find(footer)\n        if idx &gt;= 0:\n            absolute_end = len(data) - len(chunk) - len(previous_tail) + idx + len(footer)\n            if absolute_end &lt; 0:\n                absolute_end = len(data)\n            return bytes(data[:absolute_end])\n        read_pos += len(chunk)\n        if len(data) % (32 * 1024 * 1024) &lt; 1024 * 1024:\n            _raw_progress(progress_callback, f\"Boundary dhund rahe hain: {_human_size(len(data))} read\")\n    return bytes(data)\n\ndef _estimate_mp4_size(disk_path, offset, max_size, disk_handle=None):\n    pos = int(offset)\n    total = 0\n    boxes = 0\n    while total &lt; max_size and boxes &lt; 10000:\n        header = _read_raw_at(disk_path, pos, 16, disk_handle=disk_handle)\n        if len(header) &lt; 8:\n            break\n        box_size, box_type = struct.unpack(\"&gt;I4s\", header[:8])\n        header_len = 8\n        if boxes == 0 and box_type != b\"ftyp\":\n            return None\n        if box_size == 1:\n            if len(header) &lt; 16:\n                break\n            box_size = struct.unpack(\"&gt;Q\", header[8:16])[0]\n            header_len = 16\n        elif box_size == 0:\n            break\n        if box_size &lt; header_len or box_size &gt; (max_size - total):\n            break\n        total += box_size\n        pos += box_size\n        boxes += 1\n    return total if total &gt;= 8 else None\n\ndef _estimate_exe_size(disk_path, offset, max_size, disk_handle=None):\n    head = _read_raw_at(disk_path, offset, 4096, disk_handle=disk_handle)\n    if len(head) &lt; 0x40 or head[:2] != b\"MZ\":\n        return None\n    try:\n        pe_offset = struct.unpack_from(\"= 0 and len(data) &gt;= eocd + 22:\n            comment_len = struct.unpack_from(\" len(data):\n                extra = _read_raw_at(disk_path, offset + len(data), wanted - len(data), disk_handle=disk_handle)\n                data += extra\n            data = data[:wanted]\n    else:\n        data = _read_until_footer(disk_path, offset, meta[\"footer\"], limit, disk_handle=disk_handle, progress_callback=progress_callback)\n\n    if not data:\n        raise OSError(\"Koi data extract nahi hua.\")\n    safe_offset = f\"{offset:012X}\"\n    out_path = safety.validate_write_path(\n        os.path.join(output_dir, f\"recovered_{file_type.lower()}_{safe_offset}{meta['ext']}\"),\n        disk_path,\n    )\n    with open(out_path, \"wb\") as out:\n        out.write(data)\n    complete = True\n    if meta.get(\"footer\") and meta[\"footer\"] not in data[-4096:]:\n        complete = False\n    _raw_progress(progress_callback, f\"Extraction done: {out_path} ({_human_size(len(data))})\")\n    return {\n        \"ok\": True,\n        \"path\": out_path,\n        \"bytes\": len(data),\n        \"file_type\": file_type,\n        \"offset\": offset,\n        \"complete_boundary\": complete,\n    }\n\ndef create_disk_image(source_disk, img_path, max_bytes=None, progress_callback=None):\n    \"\"\"Raw disk/volume ka IMG backup banata hai. Example source: DEFAULT_RAW_DISK.\"\"\"\n    source_disk = str(source_disk or DEFAULT_RAW_DISK)\n    if not source_disk:\n        raise ValueError(\"Source disk select karein \u2014 default PhysicalDrive0 ab disabled hai\")\n    _require_raw_admin(source_disk)\n    try:\n        from godawari.services.config_manager import ConfigManager\n        safety = get_recovery_safety(ConfigManager())\n    except Exception:\n        safety = get_recovery_safety()\n    img_path = safety.validate_write_path(os.path.abspath(os.path.expanduser(str(img_path))), source_disk)\n    os.makedirs(os.path.dirname(img_path) or os.getcwd(), exist_ok=True)\n    chunk_size = 4 * 1024 * 1024\n    copied = 0\n    disk = None\n    use_powershell = False\n    total_size = int(max_bytes) if max_bytes is not None else _disk_source_size(source_disk)\n    last_pct = -1\n    last_update = 0\n    try:\n        try:\n            disk = open(source_disk, \"rb\", buffering=0)\n            _raw_progress(progress_callback, f\"IMG source open ho gaya: {source_disk}\")\n        except Exception as e:\n            use_powershell = True\n            _raw_progress(progress_callback, f\"Python raw open failed, PowerShell fallback use hoga: {e}\")\n        with open(img_path, \"wb\") as out:\n            while True:\n                if max_bytes is not None:\n                    remaining = int(max_bytes) - copied\n                    if remaining &lt;= 0:\n                        break\n                    read_len = min(chunk_size, remaining)\n                else:\n                    read_len = chunk_size\n                if use_powershell:\n                    data = _powershell_read_raw_bytes(source_disk, copied, read_len)\n                else:\n                    data = disk.read(read_len)\n                if not data:\n                    break\n                out.write(data)\n                copied += len(data)\n                now = time.time()\n                progress_text = None\n                if total_size:\n                    pct = min(100, int((copied / total_size) * 100))\n                    if pct != last_pct or now - last_update &gt; 1:\n                        last_pct = pct\n                        last_update = now\n                        progress_text = f\"IMG creation: {pct}% complete ({_human_size(copied)} copied)\"\n                elif now - last_update &gt; 1:\n                    last_update = now\n                    progress_text = f\"IMG ban rahi hai: {_human_size(copied)} copied\"\n                if progress_text:\n                    _raw_progress(progress_callback, progress_text)\n    finally:\n        if disk is not None:\n            try:\n                disk.close()\n            except Exception:\n                pass\n    _raw_progress(progress_callback, f\"IMG complete: {img_path} ({_human_size(copied)})\")\n    return {\"ok\": True, \"img_path\": img_path, \"bytes\": copied}\n\ndef copy_disk_range_to_img(source_disk, img_path, start_offset=0, max_bytes=None, progress_callback=None):\n    \"\"\"Hex/sector viewer se selected range ko IMG me export karta hai.\"\"\"\n    source_disk = str(source_disk or DEFAULT_RAW_DISK)\n    if not source_disk:\n        raise ValueError(\"Source disk select karein\")\n    _require_raw_admin(source_disk)\n    try:\n        from godawari.services.config_manager import ConfigManager\n        safety = get_recovery_safety(ConfigManager())\n    except Exception:\n        safety = get_recovery_safety()\n    img_path = safety.validate_write_path(os.path.abspath(os.path.expanduser(str(img_path))), source_disk)\n    os.makedirs(os.path.dirname(img_path) or os.getcwd(), exist_ok=True)\n    start_offset = int(start_offset)\n    chunk_size = 4 * 1024 * 1024\n    copied = 0\n    source_size = _disk_source_size(source_disk)\n    if max_bytes is None and source_size:\n        max_bytes = max(0, source_size - start_offset)\n    total_size = int(max_bytes) if max_bytes is not None else None\n    last_pct = -1\n    last_update = 0\n    with open(img_path, \"wb\") as out:\n        while True:\n            if max_bytes is not None:\n                remaining = int(max_bytes) - copied\n                if remaining &lt;= 0:\n                    break\n                read_len = min(chunk_size, remaining)\n            else:\n                read_len = chunk_size\n            data = _read_raw_at(source_disk, start_offset + copied, read_len)\n            if not data:\n                break\n            out.write(data)\n            copied += len(data)\n            now = time.time()\n            progress_text = None\n            if total_size:\n                pct = min(100, int((copied / total_size) * 100))\n                if pct != last_pct or now - last_update &gt; 1:\n                    last_pct = pct\n                    last_update = now\n                    progress_text = f\"Sector IMG export: {pct}% complete ({_human_size(copied)} copied)\"\n            elif now - last_update &gt; 1:\n                last_update = now\n                progress_text = f\"Sector IMG export: {_human_size(copied)} copied\"\n            if progress_text:\n                _raw_progress(progress_callback, progress_text)\n    _raw_progress(progress_callback, f\"Sector IMG complete: {img_path} ({_human_size(copied)})\")\n    return {\"ok\": True, \"img_path\": img_path, \"bytes\": copied, \"start_offset\": start_offset}\n\ndef raw_hex_viewer(sector_num, disk_path=DEFAULT_RAW_DISK, sectors=1, bytes_per_line=16):\n    \"\"\"DiskGenius style raw hex view return karta hai.\"\"\"\n    _require_raw_admin(disk_path)\n    sector_num = int(sector_num)\n    sectors = max(1, int(sectors))\n    offset = sector_num * SECTOR_SIZE\n    data = _read_raw_at(disk_path, offset, sectors * SECTOR_SIZE)\n    if not data:\n        raise OSError(f\"No bytes read at sector {sector_num}. Source/sector may be invalid or access is blocked.\")\n    checksum = sum(data) &amp; 0xFFFFFFFF\n    non_zero = sum(1 for b in data if b)\n    lines = [\n        f\"Disk: {disk_path}\",\n        f\"REAL RAW READ: open/read from disk device, not simulated\",\n        f\"Sector: {sector_num}  Offset: 0x{offset:016X}  Bytes: {len(data)}  NonZero: {non_zero}  Checksum32: 0x{checksum:08X}\",\n        \"-\" * 78,\n    ]\n    for i in range(0, len(data), bytes_per_line):\n        chunk = data[i:i + bytes_per_line]\n        hex_part = \" \".join(f\"{b:02X}\" for b in chunk)\n        hex_part = hex_part.ljust(bytes_per_line * 3 - 1)\n        ascii_part = \"\".join(chr(b) if 32 &lt;= b &lt; 127 else \".\" for b in chunk)\n        lines.append(f\"{offset + i:016X}  {hex_part}  |{ascii_part}|\")\n    return \"\\n\".join(lines)\n\n# ---------------------------------------------------------------------\n# PHOTOREC-STYLE DEEP SCAN ENGINE\n# ---------------------------------------------------------------------\nPHOTOREC_SIGNATURES = {\n    b\"\\xFF\\xD8\\xFF\": (\"jpg\", b\"\\xFF\\xD9\"),\n    b\"\\x89PNG\\r\\n\\x1A\\n\": (\"png\", b\"IEND\"),\n    b\"%PDF-\": (\"pdf\", b\"%%EOF\"),\n    b\"PK\\x03\\x04\": (\"zip\", b\"PK\\x05\\x06\"),\n    b\"MZ\": (\"exe\", None),\n    b\"GIF87a\": (\"gif\", b\"\\x3B\"),\n    b\"GIF89a\": (\"gif\", b\"\\x3B\"),\n    b\"BM\": (\"bmp\", None),\n    b\"RIFF\": (\"riff\", None),\n    b\"ID3\": (\"mp3\", None),\n    b\"\\xFF\\xFB\": (\"mp3\", None),\n    b\"fLaC\": (\"flac\", None),\n    b\"OggS\": (\"ogg\", None),\n    b\"\\x1F\\x8B\\x08\": (\"gz\", None),\n    b\"BZh\": (\"bz2\", None),\n    b\"\\xFD7zXZ\\x00\": (\"xz\", b\"YZ\"),\n    b\"7z\\xBC\\xAF\\x27\\x1C\": (\"7z\", None),\n    b\"Rar!\\x1A\\x07\\x00\": (\"rar\", None),\n    b\"Rar!\\x1A\\x07\\x01\\x00\": (\"rar5\", None),\n    b\"\\xD0\\xCF\\x11\\xE0\\xA1\\xB1\\x1A\\xE1\": (\"ole\", None),\n    b\"{\\\\rtf\": (\"rtf\", b\"}\"),\n    b\"SQLite format 3\\x00\": (\"sqlite\", None),\n    b\"\\x00\\x00\\x01\\x00\": (\"ico\", None),\n    b\"8BPS\": (\"psd\", None),\n    b\"MSCF\": (\"cab\", None),\n    b\"\\x25!PS\": (\"ps\", b\"%%EOF\"),\n    b\"FLV\\x01\": (\"flv\", None),\n    b\"\\x1A\\x45\\xDF\\xA3\": (\"mkv\", None),\n    b\"\\x00\\x00\\x01\\xBA\": (\"mpg\", None),\n    b\"\\x00\\x00\\x01\\xB3\": (\"mpg\", None),\n}\n\nSIGNATURE_BYTES = PHOTOREC_SIGNATURES\n\nPHOTOREC_REGEX_SIGNATURES = [\n    (re.compile(br\"\\x00\\x00\\x00[\\x08-\\xFF]ftyp\"), \"mp4\", None),\n]\n\nPHOTOREC_EXT_MAP = {\n    \"riff\": \"wav\",\n    \"ole\": \"doc\",\n    \"rar5\": \"rar\",\n}\n\ndef _load_custom_signature_config():\n    base_dir = os.path.join(os.environ.get(\"APPDATA\", \"\"), \"GodawariOptimizer\")\n    cfg_path = os.path.join(base_dir, \"custom_signatures.json\")\n    if not os.path.isfile(cfg_path):\n        return 0\n    loaded = 0\n    try:\n        with open(cfg_path, \"r\", encoding=\"utf-8\") as f:\n            payload = json.load(f)\n        items = payload if isinstance(payload, list) else payload.get(\"signatures\", [])\n        for item in items:\n            if not isinstance(item, dict):\n                continue\n            header_hex = str(item.get(\"header_hex\", \"\")).replace(\" \", \"\")\n            file_type = str(item.get(\"file_type\", \"\")).strip().lower()\n            if not header_hex or not file_type:\n                continue\n            try:\n                header = bytes.fromhex(header_hex)\n            except Exception:\n                continue\n            footer_hex = str(item.get(\"footer_hex\", \"\") or \"\").replace(\" \", \"\")\n            footer = bytes.fromhex(footer_hex) if footer_hex else None\n            PHOTOREC_SIGNATURES[header] = (file_type, footer)\n            loaded += 1\n    except Exception:\n        return 0\n    return loaded\n\nCUSTOM_SIGNATURE_COUNT = _load_custom_signature_config()\n\ndef _photorec_progress(progress_callback, message):\n    _safe_callback(progress_callback, message)\n\ndef _normalize_recovery_type(file_type):\n    file_type = str(file_type).lower().strip(\".\")\n    return PHOTOREC_EXT_MAP.get(file_type, file_type)\n\ndef _next_recup_dir(output_dir):\n    os.makedirs(output_dir, exist_ok=True)\n    idx = 1\n    while True:\n        path = os.path.join(output_dir, f\"recup_dir.{idx}\")\n        if not os.path.exists(path):\n            os.makedirs(path, exist_ok=True)\n            return path\n        idx += 1\n\ndef _disk_source_size(disk_path):\n    try:\n        if os.path.isfile(disk_path):\n            return os.path.getsize(disk_path)\n    except Exception:\n        pass\n    vol = re.match(r\"^\\\\\\\\\\.\\\\([A-Z]):$\", str(disk_path), re.I)\n    if vol:\n        letter = vol.group(1).upper() + \":\"\n        script = f\"$d=Get-CimInstance Win32_LogicalDisk -Filter \\\"DeviceID='{letter}'\\\"; if($d){{[string]$d.Size}}\"\n        out, rc = powershell_helper(script, timeout=20)\n        if rc == 0:\n            try:\n                return int(out.strip().splitlines()[-1])\n            except Exception:\n                pass\n    m = re.match(r\"^\\\\\\\\\\.\\\\PhysicalDrive(\\d+)$\", str(disk_path), re.I)\n    if m:\n        script = (\n            f\"$d=Get-CimInstance Win32_DiskDrive | Where-Object {{$_.Index -eq {int(m.group(1))}}}; \"\n            \"if($d){[string]$d.Size}\"\n        )\n        out, rc = powershell_helper(script, timeout=20)\n        if rc == 0:\n            try:\n                return int(out.strip().splitlines()[-1])\n            except Exception:\n                pass\n    return None\n\ndef _auto_detect_block_size(disk_path):\n    path = str(disk_path)\n    vol = re.match(r\"^\\\\\\\\\\.\\\\([A-Z]):$\", path, re.I)\n    if vol:\n        out, rc = powershell_helper(f\"fsutil fsinfo ntfsinfo {vol.group(1)}:\", timeout=20)\n        if rc == 0:\n            m = re.search(r\"Bytes Per Cluster\\s*:\\s*(\\d+)\", out, re.I)\n            if m:\n                return int(m.group(1))\n    phy = re.match(r\"^\\\\\\\\\\.\\\\PhysicalDrive(\\d+)$\", path, re.I)\n    if phy:\n        script = (\n            f\"$d=Get-CimInstance Win32_DiskDrive | Where-Object {{$_.Index -eq {int(phy.group(1))}}}; \"\n            \"if($d){[string]$d.BytesPerSector}\"\n        )\n        out, rc = powershell_helper(script, timeout=20)\n        if rc == 0:\n            try:\n                sector = int(out.strip().splitlines()[-1])\n                return 4096 if sector &gt;= 4096 else 512\n            except Exception:\n                pass\n    try:\n        sample = _read_raw_at(path, 0, 4 * 1024 * 1024)\n        offsets = []\n        for sig in PHOTOREC_SIGNATURES:\n            pos = sample.find(sig)\n            if pos &gt; 0:\n                offsets.append(pos)\n        for pattern, _, _ in PHOTOREC_REGEX_SIGNATURES:\n            match = pattern.search(sample)\n            if match:\n                offsets.append(match.start())\n        if offsets and all(pos % 4096 == 0 for pos in offsets):\n            return 4096\n    except Exception:\n        pass\n    return 512\n\ndef _detect_photorec_signature(buffer, absolute_base, aligned_only=False, block_size=512):\n    hits = []\n    for sig, (file_type, footer) in PHOTOREC_SIGNATURES.items():\n        start = 0\n        while True:\n            pos = buffer.find(sig, start)\n            if pos &lt; 0:\n                break\n            absolute = absolute_base + pos\n            if not aligned_only or absolute % block_size == 0:\n                hits.append((absolute, _normalize_recovery_type(file_type), sig, footer))\n            start = pos + 1\n    for pattern, file_type, footer in PHOTOREC_REGEX_SIGNATURES:\n        for match in pattern.finditer(buffer):\n            absolute = absolute_base + match.start()\n            if not aligned_only or absolute % block_size == 0:\n                hits.append((absolute, _normalize_recovery_type(file_type), match.group(0), footer))\n    hits.sort(key=lambda item: item[0])\n    return hits\n\ndef detect_file_boundaries(chunk, sig_type):\n    sig_type = _normalize_recovery_type(sig_type)\n    if sig_type == \"jpg\":\n        pos = chunk.find(b\"\\xFF\\xD9\", 2)\n        return pos + 2 if pos &gt;= 0 else None\n    if sig_type == \"png\":\n        pos = chunk.find(b\"IEND\")\n        return pos + 8 if pos &gt;= 0 else None\n    if sig_type == \"pdf\":\n        match = re.search(br\"%%EOF[\\r\\n\\t ]*\", chunk)\n        return match.end() if match else None\n    if sig_type == \"zip\":\n        pos = chunk.rfind(b\"PK\\x05\\x06\")\n        if pos &gt;= 0 and len(chunk) &gt;= pos + 22:\n            try:\n                comment_len = struct.unpack_from(\"I4s\", chunk[total:total + 8])\n            except Exception:\n                break\n            header_len = 8\n            if boxes == 0 and box_type != b\"ftyp\":\n                return None\n            if box_size == 1 and total + 16 &lt;= len(chunk):\n                box_size = struct.unpack(\"&gt;Q\", chunk[total + 8:total + 16])[0]\n                header_len = 16\n            elif box_size == 0:\n                return total if total else None\n            if box_size &lt; header_len or total + box_size &gt; len(chunk):\n                return None\n            total += box_size\n            boxes += 1\n            if box_type in (b\"mdat\", b\"moov\") and boxes &gt; 1:\n                continue\n        return total if total else None\n    if sig_type in (\"exe\", \"dll\"):\n        return _estimate_exe_size_from_bytes(chunk)\n    if sig_type == \"bmp\" and len(chunk) &gt;= 6:\n        size = struct.unpack_from(\" 14 else None\n    if sig_type == \"wav\" and chunk.startswith(b\"RIFF\") and len(chunk) &gt;= 8:\n        return struct.unpack_from(\"= 0 else None\n    return None\n\ndef _estimate_exe_size_from_bytes(data):\n    if len(data) &lt; 0x40 or data[:2] != b\"MZ\":\n        return None\n    try:\n        pe_offset = struct.unpack_from(\" len(data) or data[pe_offset:pe_offset + 4] != b\"PE\\0\\0\":\n            return None\n        sections = struct.unpack_from(\" len(data):\n                return None\n            raw_size = struct.unpack_from(\" 0 else None\n    except Exception:\n        return None\n\ndef validate_file(data, file_type):\n    file_type = _normalize_recovery_type(file_type)\n    try:\n        if file_type == \"jpg\":\n            if not (data.startswith(b\"\\xFF\\xD8\\xFF\") and b\"\\xFF\\xD9\" in data[-4096:]):\n                return False\n            pos = 2\n            while pos + 4 &lt; len(data):\n                if data[pos] != 0xFF:\n                    pos += 1\n                    continue\n                marker = data[pos + 1]\n                if marker == 0xD9:\n                    return True\n                if marker in (0x01,) or 0xD0 &lt;= marker &lt;= 0xD8:\n                    pos += 2\n                    continue\n                seg_len = struct.unpack(\"&gt;H\", data[pos + 2:pos + 4])[0]\n                if seg_len &lt; 2:\n                    return False\n                pos += 2 + seg_len\n            return False\n        if file_type == \"png\":\n            if not data.startswith(b\"\\x89PNG\\r\\n\\x1A\\n\"):\n                return False\n            pos = 8\n            while pos + 12 &lt;= len(data):\n                length = struct.unpack(\"&gt;I\", data[pos:pos + 4])[0]\n                ctype = data[pos + 4:pos + 8]\n                end = pos + 12 + length\n                if end &gt; len(data):\n                    return False\n                payload = data[pos + 4:pos + 8 + length]\n                expected = struct.unpack(\"&gt;I\", data[pos + 8 + length:end])[0]\n                if zlib.crc32(payload) &amp; 0xFFFFFFFF != expected:\n                    return False\n                pos = end\n                if ctype == b\"IEND\":\n                    return True\n            return False\n        if file_type == \"pdf\":\n            return data.startswith(b\"%PDF-\") and b\"%%EOF\" in data[-8192:]\n        if file_type == \"zip\":\n            if not data.startswith(b\"PK\\x03\\x04\"):\n                return False\n            import zipfile\n            with zipfile.ZipFile(io.BytesIO(data)) as zf:\n                return zf.testzip() is None\n        if file_type == \"mp4\":\n            return detect_file_boundaries(data, \"mp4\") is not None\n        if file_type == \"exe\":\n            return _estimate_exe_size_from_bytes(data) is not None\n        if file_type == \"gif\":\n            return data.startswith((b\"GIF87a\", b\"GIF89a\")) and data.endswith(b\"\\x3B\")\n        if file_type == \"bmp\":\n            return data.startswith(b\"BM\") and detect_file_boundaries(data, \"bmp\") == len(data)\n        if file_type == \"wav\":\n            return data.startswith(b\"RIFF\") and data[8:12] in (b\"WAVE\", b\"AVI \")\n        if file_type in (\"gz\", \"bz2\", \"xz\", \"7z\", \"rar\", \"flac\", \"ogg\", \"sqlite\", \"ico\", \"psd\", \"cab\", \"ps\", \"flv\", \"mkv\", \"mpg\", \"doc\", \"rtf\"):\n            return len(data) &gt; 16\n    except Exception:\n        return False\n    return len(data) &gt; 0\n\ndef _read_file_candidate(disk_path, offset, file_type, search_limit=None, progress_callback=None):\n    file_type = _normalize_recovery_type(file_type)\n    first = _read_raw_at(disk_path, offset, 16 * 1024 * 1024)\n    boundary = detect_file_boundaries(first, file_type)\n    if boundary:\n        return first[:boundary]\n    if file_type in (\"mp4\", \"exe\", \"bmp\", \"wav\") and boundary is None:\n        return None\n    data = bytearray(first)\n    read_pos = offset + len(first)\n    while True:\n        if search_limit is not None and len(data) &gt;= search_limit:\n            break\n        to_read = 16 * 1024 * 1024\n        if search_limit is not None:\n            to_read = min(to_read, search_limit - len(data))\n            if to_read &lt;= 0:\n                break\n        chunk = _read_raw_at(disk_path, read_pos, to_read)\n        if not chunk:\n            break\n        data.extend(chunk)\n        boundary = detect_file_boundaries(bytes(data[-(len(chunk) + 8192):]), file_type)\n        if boundary:\n            real_end = len(data) - (len(chunk) + 8192) + boundary\n            if real_end &gt; 0:\n                return bytes(data[:real_end])\n        read_pos += len(chunk)\n        _photorec_progress(progress_callback, f\"Boundary search: offset 0x{offset:X}, {len(data)//(1024*1024)} MB read\")\n    return bytes(data) if validate_file(bytes(data), file_type) else None\n\ndef _write_recovered_candidate(recup_dir, offset, file_type, data, counter, source=None):\n    safety = get_recovery_safety()\n    recup_dir = safety.validate_output_dir(recup_dir, source)\n    ext = _normalize_recovery_type(file_type)\n    name = f\"f{counter:07d}_off_{offset:012X}.{ext}\"\n    path = safety.validate_write_path(os.path.join(recup_dir, name), source)\n    with open(path, \"wb\") as out:\n        out.write(data)\n    return path\n\ndef _fragment_reassemble_nearby(disk_path, offset, file_type, block_size, progress_callback=None):\n    # Best-effort fragmented recovery: read a larger nearby window and validate candidate.\n    start = max(0, offset - block_size)\n    data = _read_raw_at(disk_path, start, block_size * 512)\n    rel = offset - start\n    if rel &lt; 0 or rel &gt;= len(data):\n        return None\n    candidate = data[rel:]\n    boundary = detect_file_boundaries(candidate, file_type)\n    if boundary:\n        candidate = candidate[:boundary]\n    if validate_file(candidate, file_type):\n        _photorec_progress(progress_callback, f\"Fragment reassembly OK: offset 0x{offset:X}\")\n        return candidate\n    return None\n\ndef _scan_pass(disk_path, recup_dir, block_size, pass_num, aligned_only, seen_offsets, progress_callback=None):\n    source_size = _disk_source_size(disk_path)\n    chunk_size, pause_s = _scan_chunk_profile(disk_path, block_size)\n    overlap = RAW_SCAN_OVERLAP\n    offset = 0\n    recovered = []\n    counter = len(seen_offsets) + 1\n    previous_tail = b\"\"\n    last_pct = -1\n    last_report_offset = -RAW_SCAN_PROGRESS_STEP\n    while True:\n        chunk = _read_raw_at(disk_path, offset, chunk_size)\n        if not chunk:\n            break\n        scan_buffer = previous_tail + chunk\n        scan_base = offset - len(previous_tail)\n        hits = _detect_photorec_signature(scan_buffer, scan_base, aligned_only=aligned_only, block_size=block_size)\n        for hit_offset, file_type, _sig, _footer in hits:\n            if hit_offset &lt; 0 or hit_offset in seen_offsets:\n                continue\n            seen_offsets.add(hit_offset)\n            try:\n                data = _read_file_candidate(disk_path, hit_offset, file_type, progress_callback=progress_callback)\n                if data is None or not validate_file(data, file_type):\n                    data = _fragment_reassemble_nearby(disk_path, hit_offset, file_type, block_size, progress_callback=progress_callback)\n                if data and validate_file(data, file_type):\n                    path = _write_recovered_candidate(recup_dir, hit_offset, file_type, data, counter, source=disk_path)\n                    counter += 1\n                    recovered.append({\"path\": path, \"offset\": hit_offset, \"file_type\": file_type, \"bytes\": len(data), \"pass\": pass_num})\n                    _photorec_progress(progress_callback, f\"Pass {pass_num}: recovered {os.path.basename(path)}\")\n            except Exception as e:\n                _photorec_progress(progress_callback, f\"Pass {pass_num}: offset 0x{hit_offset:X} skip ({e})\")\n        offset += len(chunk)\n        previous_tail = scan_buffer[-overlap:]\n        if source_size:\n            pct = min(100, int((offset / source_size) * 100))\n            if pct != last_pct:\n                last_pct = pct\n                _photorec_progress(progress_callback, f\"Pass {pass_num}: {pct}% complete\")\n        elif (offset - last_report_offset) &gt;= RAW_SCAN_PROGRESS_STEP:\n            last_report_offset = offset\n            _photorec_progress(progress_callback, f\"Pass {pass_num}: {_human_size(offset)} scanned\")\n        if pause_s:\n            time.sleep(pause_s)\n    return recovered\n\ndef multi_pass_recovery(disk_path, output_dir, block_size=None, progress_callback=None):\n    _require_raw_admin(disk_path)\n    output_dir = get_recovery_safety().validate_output_dir(output_dir, disk_path)\n    block_size = int(block_size or _auto_detect_block_size(disk_path))\n    recup_base = _next_recup_dir(output_dir)\n    seen_offsets = set()\n    all_recovered = []\n    _photorec_progress(progress_callback, f\"Block size auto-detected: {block_size} bytes\")\n    if CUSTOM_SIGNATURE_COUNT:\n        _photorec_progress(progress_callback, f\"Custom signature engine active: {CUSTOM_SIGNATURE_COUNT} extra signatures\")\n    if _is_raw_device_path(disk_path):\n        _photorec_progress(progress_callback, f\"Low-impact mode active: {RAW_SCAN_DEVICE_CHUNK // (1024 * 1024)} MB buffered reads + {RAW_SCAN_DEVICE_PAUSE_MS} ms pause\")\n    _photorec_progress(progress_callback, \"Pass 1: block-aligned carving start\")\n    all_recovered.extend(_scan_pass(disk_path, recup_base, block_size, 1, True, seen_offsets, progress_callback))\n    _photorec_progress(progress_callback, \"Pass 2: unaligned signature carving start\")\n    all_recovered.extend(_scan_pass(disk_path, recup_base, block_size, 2, False, seen_offsets, progress_callback))\n    _photorec_progress(progress_callback, f\"Carving complete: {len(all_recovered)} files (2 passes + validation)\")\n    return {\"recup_dir\": recup_base, \"block_size\": block_size, \"files\": all_recovered}\n\ndef deep_scan_disk(disk_path, output_dir):\n    \"\"\"PhotoRec-style main scanner: raw disk access, auto block size, multi-pass carving.\"\"\"\n    _require_raw_admin(disk_path)\n    return multi_pass_recovery(disk_path, output_dir, block_size=None, progress_callback=print)\n\n# \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n#  CORPORATE PROFESSIONAL COLOR SCHEME - Enterprise-Grade Theme\n#  Modern, clean, professional appearance for business environments\n# \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\nC = {\n    \"bg\":         \"#0A0F1A\",\n    \"panel\":      \"#121826\",\n    \"card\":       \"#182032\",\n    \"border\":     \"#2A3A5A\",\n    \"accent\":     \"#FFB347\",\n    \"accent2\":    \"#4CAF50\",\n    \"accent3\":    \"#F44336\",\n    \"accent4\":    \"#FF9800\",\n    \"text\":       \"#F0F4FA\",\n    \"text_dim\":   \"#A0B0C8\",\n    \"text_dark\":  \"#3A4A6A\",\n    \"btn\":        \"#2E5A9C\",\n    \"btn_hover\":  \"#1E4A8C\",\n    \"btn_danger\": \"#D32F2F\",\n    \"btn_info\":   \"#1976D2\",\n    \"btn_warn\":   \"#FF8C00\",\n    \"btn_hw\":     \"#6A1B9A\",\n    \"btn_chip\":   \"#00838F\",\n    \"header_bg\":  \"#0A0F1A\",\n    \"sidebar\":    \"#0E1422\",\n    \"progress\":   \"#FFB347\",\n    \"success\":    \"#4CAF50\",\n    \"warning\":    \"#FF9800\",\n    \"error\":      \"#F44336\",\n    \"hw_accent\":  \"#CE93D8\",\n}\n\n\n  # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n  #  CORPORATE PROFESSIONAL FONTS - Enterprise-Grade Typography\n  #  Clean, readable, professional font hierarchy\n  # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\nFONTS = {\n    \"title\":    (\"Segoe UI\", 20, \"bold\"),\n    \"heading\":  (\"Segoe UI\", 13, \"bold\"),\n    \"subhead\":  (\"Segoe UI\", 11, \"bold\"),\n    \"body\":     (\"Segoe UI\", 10),\n    \"small\":    (\"Segoe UI\", 9),\n    \"xsmall\":   (\"Segoe UI\", 8),\n    \"mono\":     (\"Consolas\", 9),\n}\n\nSIDEBAR_CATEGORIES = [\n    (\"\ud83d\udee0 SHOP WORKFLOW\", \"accent4\", [\n        (\"shop\", \"\ud83d\udee0\", \"Repair Shop Mode\"),\n    ]),\n    (\"\u26a1 PERFORMANCE\", \"accent\", [\n        (\"cleaner\", \"\ud83e\uddf9\", \"Junk Cleaner\"),\n        (\"memory\", \"\ud83e\udde0\", \"RAM + Services\"),\n        (\"startup\", \"\ud83d\ude80\", \"Startup + Scheduler\"),\n        (\"boost\", \"\u26a1\", \"Power Boost\"),\n    ]),\n    (\"\ud83d\udd27 SYSTEM REPAIR\", \"warning\", [\n        (\"registry\", \"\ud83d\udcdd\", \"Registry + Group Policy\"),\n        (\"network\", \"\ud83c\udf10\", \"Network + Troubleshooter\"),\n        (\"power\", \"\ud83d\udd0b\", \"Power Plan\"),\n        (\"hdd_repair\", \"\ud83d\udcbe\", \"HDD/SSD + File Recovery\"),\n        (\"data_recovery\", \"\ud83d\udd2c\", \"Data Recovery\"),\n        (\"activation\", \"\ud83d\udd11\", \"Windows Activation\"),\n    ]),\n    (\"\ud83d\udee0 RESCUE &amp; RECOVERY\", \"warning\", [\n        (\"rescue_center\", \"\ud83d\udee0\", \"Rescue &amp; Recovery Center\"),\n    ]),\n    (\"\ud83d\udd0d SECURITY &amp; AUDIT\", \"accent3\", [\n        (\"suspicion\", \"\ud83d\udd34\", \"Process Scanner\"),\n        (\"realtime_security\", \"\ud83d\udee1\", \"Realtime Security\"),\n        (\"eventviewer\", \"\ud83d\udccb\", \"Event Viewer\"),\n        (\"log\", \"\ud83d\udcc4\", \"Activity Log\"),\n    ]),\n    (\"\ud83d\uddc2 TOOLS\", \"accent2\", [\n        (\"printer\", \"\ud83d\udda8\", \"Printer + Driver\"),\n        (\"uninstall\", \"\ud83d\uddd1\", \"Uninstall + Backup\"),\n        (\"dupfinder\", \"\ud83d\udd0d\", \"Dup Finder + Report\"),\n    ]),\n    (\"\ud83d\udcc1 OFFICE &amp; FILES\", \"hw_accent\", [\n        (\"office_tools\", \"\ud83d\udcc4\", \"PDF &amp; Doc Tools\"),\n        (\"excel_tools\", \"\ud83d\udcca\", \"Excel Tools\"),\n        (\"image_tools\", \"\ud83d\uddbc\", \"Image Tools\"),\n        (\"file_tools\", \"\ud83d\uddc2\", \"File Manager\"),\n    ]),\n]\n\n\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n#  MAIN APPLICATION\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nSIDEBAR_CATEGORIES.append((\"\ud83d\udd27 ADVANCED TOOLS\", \"accent3\", [\n    (\"partition_manager\",\"\ud83d\udcbd\", \"Partition Manager\"),\n    (\"easy_driver\",      \"\ud83d\udda5\", \"Easy Driver\"),\n    (\"driver_manager\",    \"\ud83d\udda5\",  \"Driver Manager\"),\n    (\"svc_presets\",       \"\u2699\",  \"Services Preset Manager\"),\n    (\"disk_analyzer\",     \"\ud83d\udcca\", \"Disk Space Analyzer\"),\n    (\"bsod_history\",      \"\ud83d\udc80\", \"BSOD History\"),\n    (\"corrupt_wizard\",    \"\ud83d\udd28\", \"Corrupt Windows Wizard\"),\n    (\"password_audit\",    \"\ud83d\udd10\", \"Password &amp; Security Audit\"),\n    (\"auto_backup\",       \"\ud83d\udcbe\", \"Auto Backup\"),\n]))\n\nclass GodawariUltimateOptimizer(tk.Tk):\n    def __init__(self):\n        super().__init__()\n        self.title(\"Godawari Computers Ultimate Optimizer Pro v11.0 | Safety &amp; Recovery Edition\")\n        self.geometry(\"1400x850\")\n        self.minsize(1120, 680)\n        self.configure(bg=C[\"bg\"])\n        self.resizable(True, True)\n\n        self.active_section = tk.StringVar(value=\"dashboard\")\n        self.log_lines = []\n        self.current_theme = \"dark\"\n        self.settings_file = os.path.join(os.environ.get(\"APPDATA\", \"\"), \"GodawariOptimizer\", \"settings.json\")\n        self.reg_vars = {}\n        self.gp_vars = {}\n        self.clean_vars = {}\n        self._restore_prompt_count = 0\n        self.uninst_data = []\n        self._recovery_stop_flag = False\n        self._recovery_pause_flag = False\n        self._clean_job_running = False\n        self._clean_job_cancel_event = threading.Event()\n        self._clean_job_summary = {}\n        self._recovery_active = False\n        self._partition_op_lock = threading.Lock()\n        self._partition_operation_active = False\n        self._partition_operation_session = None\n        self._partition_cancel_event = threading.Event()\n        self._partition_operation_log = []\n        self._partition_operation_start_time = None\n        self._job_lock = threading.Lock()\n        self._jobs = {}\n        self._job_counter = 0\n        self._task_manager = {}\n        self._task_counter = 0\n        self._event_bus = collections.defaultdict(list)\n        self.system_health = {\n            \"disk\": 100,\n            \"ram\": 100,\n            \"startup\": 100,\n            \"security\": 100,\n            \"windows\": 100,\n            \"drivers\": 100,\n            \"network\": 100,\n        }\n        self._health_trend = {key: 100 for key in self.system_health}\n        self._rollback_points = []\n        self._security_alerts = []\n        self._security_watch_running = False\n        self._security_watch_thread = None\n        self._security_baselines = {}\n        self._last_security_snapshot = {}\n        self._enterprise_log_dir = os.path.join(os.environ.get(\"APPDATA\", \"\"), \"GodawariOptimizer\", \"logs\")\n        self._enterprise_log_file = os.path.join(self._enterprise_log_dir, \"enterprise.log\")\n        self._enterprise_error_log = os.path.join(self._enterprise_log_dir, \"errors.log\")\n        self._enterprise_forensic_log = os.path.join(self._enterprise_log_dir, \"forensic.log\")\n        self._ensure_enterprise_logs()\n        self.backup_config_file = os.path.join(os.environ.get(\"APPDATA\",\"\"), \"GodawariOptimizer\", \"backup_config.json\")\n        self.backup_sources = []\n        self.backup_dest_var = tk.StringVar()\n        self.backup_schedule_var = tk.StringVar(value=\"Manual Only\")\n        self.backup_time_var = tk.StringVar(value=\"02:00\")\n        self.backup_overwrite_mode = tk.StringVar(value=\"mirror\")\n        self.backup_keep_n = tk.IntVar(value=3)\n        self.regback_enabled = tk.BooleanVar(value=True)\n        self._corrupt_wizard_step = 0\n        self._corrupt_wizard_running = False\n\n        # \u2500\u2500 Thread-safe UI update queue \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        # Background threads put (msg_type, payload) tuples here.\n        # The main thread drains this queue every ~50 ms via _poll_ui_queue().\n        # This is the ONLY safe way to touch Tkinter widgets from threads.\n        self._ui_queue = _queue_module.Queue()\n        # Specialized metric queues for RAM/Services, Registry/Group Policy and HDD/Recovery menus.\n        self._ram_service_metrics_queue = _queue_module.Queue()\n        self._ram_service_last_dispatch = time.time()\n        self._ram_service_metrics_lock = threading.Lock()\n        self._ram_service_pending_metrics = None\n        self._registry_gp_metrics_queue = _queue_module.Queue()\n        self._registry_gp_last_dispatch = time.time()\n        self._hdd_recovery_metrics_queue = _queue_module.Queue()\n        self._hdd_recovery_last_dispatch = time.monotonic()\n        self._hdd_recovery_pending_metrics = None\n        self._hdd_recovery_metrics_lock = threading.Lock()\n        self._hdd_recovery_job_lock = threading.Lock()\n        # Dedicated printer action queue and metrics throttling for the Printer + Driver menu.\n        self._printer_metrics_queue = _queue_module.Queue()\n        self._printer_metrics_last_dispatch = time.monotonic()\n        self._printer_metrics_pending = None\n        self._printer_metrics_lock = threading.Lock()\n        self._printer_action_buttons = []\n        self._printer_action_lock = threading.Lock()\n        self._printer_action_running = False\n        # Threading Event: set by _stop_file_recovery() so the scan loop\n        # can check it without touching any Tk widget from a background thread.\n        self._scan_stop_event = threading.Event()\n        # \u2500\u2500 PHASE 2: Atomic debounce lock for File Recovery menu \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        self._recovery_is_processing = False          # atomic boolean guard\n        self._rec_integrity_lock     = threading.Lock()\n        self._rec_timeline_lock      = threading.Lock()\n        self._rec_integrity_queue    = _queue_module.Queue()\n        self._rec_timeline_queue     = _queue_module.Queue()\n        self._rec_integrity_last_dispatch  = time.monotonic()\n        self._rec_timeline_last_dispatch   = time.monotonic()\n\n        try:\n            os.makedirs(os.path.dirname(self.settings_file), exist_ok=True)\n        except:\n            pass\n        self._init_backend_reliability()\n        self.worker_manager = TkWorkerManager(self, workers=3, logger=getattr(self, \"structured_logger\", None))\n        self.recovery_manager = RecoveryManager(workers=3, callback=self._on_recovery_task_update, logger=getattr(self, \"structured_logger\", None))\n        self.recovery_results = RecoveryResultStore()\n        self._recovery_progress_panels = {}\n        self._recovery_live_stats = {}\n\n        self._build_style()\n        self._build_header()\n        self._build_body()\n        self._build_statusbar()\n        self._build_footer()\n        self._load_settings()\n        self._show_section(\"dashboard\")\n        # Startup fast karo: dashboard refresh aur graph deferred\n        self.after(800, self._refresh_dashboard)\n        self.after(1500, self._start_real_time_graph)\n\n        # Start the UI queue poller \u2014 drains _ui_queue on the main thread\n        self._poll_ui_queue()\n        self._poll_ram_service_metrics()\n        self._poll_registry_gp_metrics()\n        self._poll_hdd_recovery_metrics()\n        self._poll_printer_metrics()\n        self._tick_printer_action_timer()\n\n        if not is_admin():\n            self._set_status(\"\u26a0\ufe0f Admin rights required! Some features may not work.\", C[\"warning\"])\n            self._log(\"Not running as Administrator. Right-click -&gt; Run as Administrator.\", \"WARN\")\n\n        self.after(1200, self._check_crash_recovery_startup)\n        self.protocol(\"WM_DELETE_WINDOW\", self._on_app_close)\n\n    def _on_app_close(self):\n        try:\n            if hasattr(self, \"crash_recovery\"):\n                self.crash_recovery.clear_running()\n        except Exception:\n            pass\n        self.destroy()\n\n    def _check_crash_recovery_startup(self):\n        try:\n            orphans = self.crash_recovery.orphaned_sessions()\n            if not orphans:\n                return\n            lines = []\n            for s in orphans[:5]:\n                lines.append(\n                    f\"\u2022 {s.get('kind', 'job')} \u2014 started {s.get('started', '?')}\"\n                )\n            self._log(\n                \"Crash recovery detected unfinished sessions on startup. \"\n                + \"Review in Safety Center if needed. \"\n                + \" | \".join(lines),\n                \"WARN\",\n            )\n        except Exception:\n            pass\n\n    def _init_backend_reliability(self):\n        if _GODAWARI_BACKEND:\n            try:\n                self._backend = create_backend()\n                base_dir = self._backend.config.get(\"app\", default={})  # noqa \u2014 paths via package\n                from godawari import paths as _paths\n                self.audit_dir = _paths.audit_dir()\n                self.backup_dir = _paths.backup_dir()\n                self.rollback_dir = _paths.rollback_dir()\n                self.recovery_sessions_dir = _paths.sessions_dir()\n                self.crash_marker_file = _paths.crash_marker_path()\n                self.audit_file = _paths.legacy_audit_path()\n                self.structured_log_file = _paths.structured_log_path()\n                self.structured_logger = self._backend.logger\n                self.event_bus = self._backend.event_bus\n                self.telemetry_store = self._backend.telemetry_store\n                self.job_manager = self._backend.job_manager\n                self.change_coordinator = self._backend.change_coordinator\n                self.policy_engine = self._backend.policy_engine\n                self.system_adapters = self._backend.system_adapters\n                self.restore_point_manager = self._backend.restore_points\n                self.rollback_vault = self._backend.rollback_vault\n                self.recovery_session_manager = self._backend.recovery_sessions\n                self.health_engine = self._backend.health_engine\n                self.menu_introspection_engine = self._backend.menu_introspection\n                self.product_audit_engine = self._backend.product_audit\n                self.recommendation_engine = self._backend.recommendations\n                self.maintenance_profile_engine = self._backend.maintenance_profiles\n                self.preflight_engine = self._backend.preflight\n                self.secure_powershell = self._backend.secure_powershell\n                self.crash_recovery = self._backend.crash_recovery\n                self.task_queue_manager = self._backend.task_queue\n                self.audit_store = self._backend.audit_store\n                self.app_config = self._backend.config\n                self.crash_recovery.mark_running()\n                self._last_health_report = None\n                return\n            except Exception:\n                pass\n        base_dir = os.path.join(os.environ.get(\"APPDATA\", \"\"), \"GodawariOptimizer\")\n        self.audit_dir = os.path.join(base_dir, \"audit\")\n        self.backup_dir = os.path.join(base_dir, \"backups\")\n        self.rollback_dir = os.path.join(base_dir, \"rollback_vault\")\n        self.recovery_sessions_dir = os.path.join(base_dir, \"recovery_sessions\")\n        self.crash_marker_file = os.path.join(base_dir, \"runtime.marker\")\n        try:\n            os.makedirs(self.audit_dir, exist_ok=True)\n            os.makedirs(self.backup_dir, exist_ok=True)\n            os.makedirs(self.rollback_dir, exist_ok=True)\n            os.makedirs(self.recovery_sessions_dir, exist_ok=True)\n            self.audit_file = os.path.join(self.audit_dir, \"actions.jsonl\")\n            self.structured_log_file = os.path.join(self.audit_dir, \"structured_runtime.jsonl\")\n        except Exception:\n            self.audit_file = \"\"\n            self.structured_log_file = \"\"\n        # Initialize structured logger and backend helpers\n        try:\n            from godawari.services.logger import StructuredLogger as _StructuredLogger\n            from godawari.jobs.manager import JobManager as _JobManager\n            from godawari.events.bus import EventBus as _EventBus\n            from godawari.telemetry.store import TelemetryStore as _TelemetryStore\n            from godawari.change_coordinator import ChangeCoordinator as _ChangeCoordinator\n            from godawari.policies.engine import PolicyEngine as _PolicyEngine\n            from godawari.system.adapters import RegistryAdapter, ServiceAdapter, DiskAdapter\n        except Exception:\n            _StructuredLogger = globals().get(\"StructuredLogger\")\n            _JobManager = None\n            _EventBus = None\n            _TelemetryStore = None\n            _ChangeCoordinator = None\n            _PolicyEngine = None\n            RegistryAdapter = ServiceAdapter = DiskAdapter = None\n\n        self.event_bus = _EventBus.get_instance() if _EventBus else None\n        self.telemetry_store = _TelemetryStore(db_path=_paths.database_path()) if _TelemetryStore else None\n        self.structured_logger = _StructuredLogger(getattr(self, \"structured_log_file\", \"\"))\n        self.restore_point_manager = RestorePointManager(\n            base_dir,\n            self.structured_logger,\n            event_bus=self.event_bus,\n            telemetry=self.telemetry_store,\n        )\n        self.rollback_vault = OperationRollbackVault(\n            self.rollback_dir,\n            self.structured_logger,\n            event_bus=self.event_bus,\n            telemetry=self.telemetry_store,\n        )\n        self.recovery_session_manager = RecoverySessionManager(\n            self.recovery_sessions_dir, self.structured_logger\n        )\n        # EventBus and JobManager\n        try:\n            self.job_manager = _JobManager(db_path=_paths.database_path(), workers=3, logger=self.structured_logger, event_bus=self.event_bus, telemetry=self.telemetry_store) if _JobManager else None\n            self.change_coordinator = _ChangeCoordinator(self.restore_point_manager, self.rollback_vault, logger=self.structured_logger, job_manager=self.job_manager, event_bus=self.event_bus, telemetry_store=self.telemetry_store) if _ChangeCoordinator else None\n            self.policy_engine = _PolicyEngine(logger=self.structured_logger) if _PolicyEngine else None\n            self.system_adapters = {\n                \"registry\": RegistryAdapter() if RegistryAdapter else None,\n                \"service\": ServiceAdapter() if ServiceAdapter else None,\n                \"disk\": DiskAdapter() if DiskAdapter else None,\n            }\n        except Exception:\n            self.job_manager = None\n            self.change_coordinator = None\n            self.policy_engine = None\n            self.system_adapters = {}\n        self.health_engine = SystemHealthEngine()\n        self.menu_introspection_engine = MenuIntrospectionEngine()\n        self.product_audit_engine = ProductAuditEngine()\n        self.recommendation_engine = RecommendationEngine()\n        self.maintenance_profile_engine = MaintenanceProfileEngine()\n        self.preflight_engine = OperationPreflightEngine()\n        self.secure_powershell = SecurePowerShellEngine(self.structured_logger)\n        self.crash_recovery = CrashRecoveryCoordinator(\n            self.recovery_session_manager, self.crash_marker_file)\n        self.crash_recovery.mark_running()\n        self._last_health_report = None\n\n    def _ensure_enterprise_logs(self):\n        try:\n            os.makedirs(self._enterprise_log_dir, exist_ok=True)\n            for path in (self._enterprise_log_file, self._enterprise_error_log, self._enterprise_forensic_log):\n                if not os.path.exists(path):\n                    with open(path, \"a\", encoding=\"utf-8\"):\n                        pass\n        except Exception:\n            pass\n\n    def _write_enterprise_log(self, path, message, level=\"INFO\"):\n        try:\n            os.makedirs(self._enterprise_log_dir, exist_ok=True)\n            if os.path.exists(path) and os.path.getsize(path) &gt; (1024 * 1024):\n                suffix = datetime.datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n                rotated = f\"{path}.{suffix}\"\n                try:\n                    os.replace(path, rotated)\n                except Exception:\n                    pass\n            timestamp = datetime.datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\")\n            with open(path, \"a\", encoding=\"utf-8\") as handle:\n                handle.write(f\"[{timestamp}] [{level}] {message}\\n\")\n        except Exception:\n            pass\n\n    def _log_module(self, module, message, level=\"INFO\"):\n        try:\n            module_path = os.path.join(self._enterprise_log_dir, f\"{module}.log\")\n            self._write_enterprise_log(module_path, message, level)\n        except Exception:\n            pass\n\n    def _register_event(self, event_name, callback):\n        try:\n            self._event_bus.setdefault(str(event_name), []).append(callback)\n            return True\n        except Exception:\n            return False\n\n    def _emit_event(self, event_name, data=None):\n        try:\n            for callback in list(self._event_bus.get(str(event_name), [])):\n                try:\n                    callback(data)\n                except Exception:\n                    pass\n            if getattr(self, \"event_bus\", None) is not None:\n                try:\n                    self.event_bus.emit(str(event_name), data)\n                except Exception:\n                    pass\n            return True\n        except Exception:\n            return False\n\n    def _set_health_score(self, key, value, note=\"\"):\n        try:\n            previous = self.system_health.get(key, 100)\n            self._health_trend[key] = previous\n            self.system_health[key] = max(0, min(100, int(value)))\n            if note:\n                self._log_module(\"health\", f\"{key}: {self.system_health[key]} ({note})\", \"INFO\")\n        except Exception:\n            pass\n\n    def _calculate_global_health(self):\n        try:\n            scores = [max(0, min(100, int(v))) for v in self.system_health.values()]\n            global_score = int(sum(scores) / len(scores)) if scores else 100\n            if global_score &gt;= 85:\n                grade, color = \"Excellent\", C[\"success\"]\n            elif global_score &gt;= 70:\n                grade, color = \"Good\", C[\"accent4\"]\n            elif global_score &gt;= 50:\n                grade, color = \"Fair\", C[\"warning\"]\n            else:\n                grade, color = \"Critical\", C[\"error\"]\n            trend = {key: f\"{('\u25b2' if self.system_health[key] &gt;= self._health_trend.get(key, self.system_health[key]) else '\u25bc')} {abs(self.system_health[key] - self._health_trend.get(key, self.system_health[key]))}\" for key in self.system_health}\n            return {\n                \"score\": global_score,\n                \"grade\": grade,\n                \"color\": color,\n                \"per_category\": dict(self.system_health),\n                \"trend\": trend,\n            }\n        except Exception:\n            return {\"score\": 100, \"grade\": \"Excellent\", \"color\": C[\"success\"], \"per_category\": dict(self.system_health), \"trend\": {}}\n\n    def _refresh_health_snapshot(self):\n        try:\n            vm = psutil.virtual_memory()\n            du = psutil.disk_usage(\"C:\")\n            proc_count = len(list(psutil.process_iter(['pid'])))\n            startup_path = os.path.join(os.environ.get(\"APPDATA\", \"\"), \"Microsoft\", \"Windows\", \"Start Menu\", \"Programs\", \"Startup\")\n            startup_items = len([name for name in os.listdir(startup_path) if os.path.isfile(os.path.join(startup_path, name))]) if os.path.isdir(startup_path) else 0\n            self._set_health_score(\"ram\", max(0, 100 - int(vm.percent)), \"RAM usage\")\n            self._set_health_score(\"disk\", max(0, 100 - int(du.percent)), \"Disk usage\")\n            self._set_health_score(\"startup\", max(20, 100 - min(80, startup_items * 2)), \"Startup items\")\n            self._set_health_score(\"network\", 100 if self._last_security_snapshot.get(\"network\", {}).get(\"status\") == \"healthy\" else 70)\n            driver_cmd = 'powershell -NoProfile -Command \"Get-WmiObject Win32_PnPSignedDriver | Select-Object -ExpandProperty DeviceName\"'\n            out, rc = self._run_cmd(driver_cmd, timeout=20)\n            if rc == 0:\n                driver_count = len([line for line in out.splitlines() if line.strip()])\n                self._set_health_score(\"drivers\", max(40, 100 - min(60, driver_count // 20)), \"Driver inventory\")\n            security_status = self._last_security_snapshot.get(\"defender\", {})\n            sec_score = 100\n            if not security_status.get(\"enabled\", False):\n                sec_score = 0\n            if not security_status.get(\"realtime\", True):\n                sec_score = max(0, sec_score - 20)\n            self._set_health_score(\"security\", sec_score, \"Defender status\")\n            windows_score = 100\n            health_report = getattr(self, \"_last_health_report\", None)\n            if health_report and isinstance(health_report, dict):\n                windows_score = int(health_report.get(\"score\", 100))\n            self._set_health_score(\"windows\", windows_score, \"Windows health\")\n            self._last_security_snapshot[\"process_count\"] = proc_count\n            self._last_security_snapshot[\"disk_percent\"] = int(du.percent)\n            self._last_security_snapshot[\"ram_percent\"] = int(vm.percent)\n            return self._calculate_global_health()\n        except Exception:\n            return self._calculate_global_health()\n\n    def _task_start(self, title, progress=0, metadata=None):\n        try:\n            self._task_counter += 1\n            task_id = f\"task-{self._task_counter}\"\n            self._task_manager[task_id] = {\n                \"id\": task_id,\n                \"title\": str(title),\n                \"status\": \"running\",\n                \"progress\": max(0, min(100, int(progress))),\n                \"metadata\": metadata or {},\n                \"cancel_requested\": False,\n                \"started_at\": datetime.datetime.now().isoformat(timespec=\"seconds\"),\n            }\n            self._log_module(\"tasks\", f\"Started {task_id}: {title}\", \"INFO\")\n            if hasattr(self, \"task_center_tree\"):\n                self.after(0, self._refresh_task_center)\n            return task_id\n        except Exception:\n            return \"task-0\"\n\n    def _task_status(self, task_id):\n        return dict(self._task_manager.get(str(task_id), {})) if str(task_id) in self._task_manager else {}\n\n    def _task_cancel(self, task_id):\n        try:\n            record = self._task_manager.get(str(task_id))\n            if record is None:\n                return False\n            record[\"cancel_requested\"] = True\n            record[\"status\"] = \"cancelled\"\n            self._log_module(\"tasks\", f\"Cancelled {task_id}\", \"WARNING\")\n            if hasattr(self, \"task_center_tree\"):\n                self.after(0, self._refresh_task_center)\n            return True\n        except Exception:\n            return False\n\n    def _refresh_task_center(self):\n        tree = getattr(self, \"task_center_tree\", None)\n        if tree is None:\n            return\n        for iid in tree.get_children():\n            tree.delete(iid)\n        for record in sorted(self._task_manager.values(), key=lambda item: item.get(\"started_at\", \"\"), reverse=True):\n            status = record.get(\"status\", \"running\")\n            tag = \"running\" if status == \"running\" else \"cancelled\"\n            tree.insert(\n                \"\",\n                \"end\",\n                values=(record.get(\"id\", \"\"), record.get(\"title\", \"\"), status, f\"{record.get('progress', 0)}%\"),\n                tags=(tag,),\n            )\n        try:\n            tree.tag_configure(\"running\", foreground=C[\"success\"])\n            tree.tag_configure(\"cancelled\", foreground=C[\"warning\"])\n        except Exception:\n            pass\n\n    def _record_rollback_point(self, action, details=None, snapshot_path=None):\n        try:\n            point = {\n                \"action\": str(action),\n                \"details\": details or {},\n                \"snapshot_path\": snapshot_path or \"\", \n                \"timestamp\": datetime.datetime.now().isoformat(timespec=\"seconds\"),\n            }\n            self._rollback_points.append(point)\n            self._log_module(\"rollback\", f\"Rollback point captured: {action}\", \"INFO\")\n            return point\n        except Exception:\n            return None\n\n    def _restore_last_rollback(self):\n        try:\n            if not self._rollback_points:\n                return False, \"No rollback points available\"\n            point = self._rollback_points[-1]\n            snapshot = point.get(\"snapshot_path\")\n            details = point.get(\"details\") or {}\n            if snapshot and os.path.exists(snapshot) and os.path.isdir(snapshot):\n                if point.get(\"action\") == \"partition_merge\":\n                    target_letter = details.get(\"source_letter\")\n                    if target_letter and os.path.isdir(f\"{target_letter}:\\\\\"):\n                        copy_cmd = [\"robocopy\", snapshot, f\"{target_letter}:\\\\\", \"/MIR\", \"/R:2\", \"/W:2\", \"/NFL\"]\n                        result = safe_run(copy_cmd, timeout=7200)\n                        if result.returncode &lt; 8:\n                            return True, f\"Rollback restored backup to {target_letter}:\"\n                        return False, f\"Rollback failed during restore copy (rc={result.returncode})\"\n                return True, f\"Rollback point available for {point.get('action')} \u2014 backup exists at {snapshot}\"\n            return True, f\"Rollback point prepared for {point.get('action')}\"\n        except Exception:\n            return False, \"Rollback restore failed\"\n\n    # \u2500\u2500 UI Queue Poller \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _poll_ui_queue(self):\n        \"\"\"\n        Main-thread poller: drains _ui_queue every 50 ms.\n\n        Background threads NEVER touch Tkinter widgets directly.\n        They put (msg_type, payload) into self._ui_queue and this method\n        applies all pending updates in one go, keeping the GUI responsive.\n\n        Supported message types\n        \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        (\"progress_label\",  str)           \u2013 raw_progress_label text\n        (\"log_line\",        str)           \u2013 append line to raw_progress_log\n        (\"progress_pct\",   float)         \u2013 set raw_progress_var (0-100)\n        (\"status\",         (str, color))  \u2013 bottom status bar\n        (\"tree_row\",       (row, entry))  \u2013 insert row into rec_tree\n        (\"scan_mode\",      (str, color))  \u2013 scan_mode_label update\n        (\"rec_stats\",      None)          \u2013 refresh rec_stats_label\n        (\"finish_op\",      None)          \u2013 call _finish_recovery_operation\n        (\"progress_bar_mode\", str)        \u2013 \"indeterminate\" or \"determinate\"\n        (\"progress_bar_start\", int)       \u2013 start indeterminate animation\n        (\"progress_bar_stop\",  None)      \u2013 stop animation\n        \"\"\"\n        try:\n            processed = 0\n            while not self._ui_queue.empty() and processed &lt; 100:\n                msg_type, payload = self._ui_queue.get_nowait()\n                processed += 1\n\n                if msg_type == \"progress_label\":\n                    if hasattr(self, \"raw_progress_label\"):\n                        self.raw_progress_label.config(text=str(payload)[:200])\n\n                elif msg_type == \"log_line\":\n                    if hasattr(self, \"raw_progress_log\"):\n                        try:\n                            self.raw_progress_log.config(state=\"normal\")\n                            self.raw_progress_log.insert(\"end\", self._fix_text(str(payload)) + \"\\n\")\n                            # Keep log from growing unbounded\n                            lines = float(self.raw_progress_log.index(\"end-1c\").split(\".\")[0])\n                            if lines &gt; 300:\n                                self.raw_progress_log.delete(\"1.0\", \"100.0\")\n                            self.raw_progress_log.see(\"end\")\n                            self.raw_progress_log.config(state=\"disabled\")\n                        except Exception:\n                            pass\n\n                elif msg_type == \"progress_pct\":\n                    if hasattr(self, \"raw_progress_var\") and hasattr(self, \"raw_progress_bar\"):\n                        try:\n                            self.raw_progress_bar.stop()\n                        except Exception:\n                            pass\n                        self.raw_progress_bar.config(mode=\"determinate\")\n                        self.raw_progress_var.set(max(0.0, min(100.0, float(payload))))\n\n                elif msg_type == \"status\":\n                    msg, color = payload\n                    self._set_status(msg, color)\n\n                elif msg_type == \"tree_row\":\n                    row, entry = payload\n                    if hasattr(self, \"rec_tree\"):\n                        try:\n                            iid = self.rec_tree.insert(\"\", \"end\", values=row, tags=(\"found\",))\n                            if not hasattr(self, \"rec_found_files\") or not isinstance(self.rec_found_files, dict):\n                                self.rec_found_files = {}\n                            self.rec_found_files[iid] = entry\n                        except Exception:\n                            pass\n\n                elif msg_type == \"scan_mode\":\n                    text, color = payload\n                    if hasattr(self, \"scan_mode_label\"):\n                        self.scan_mode_label.config(text=text, fg=color or C[\"accent4\"])\n\n                elif msg_type == \"rec_stats\":\n                    self._on_rec_select()\n\n                elif msg_type == \"recovery_queue\":\n                    self._refresh_recovery_queue_tree()\n\n                elif msg_type == \"recovery_refresh\":\n                    self._refresh_recovery_tree(getattr(self, \"quick_recovery_tree\", None), category=\"Quick Recovery\")\n                    self._refresh_recovery_tree(getattr(self, \"deep_recovery_tree\", None), category=\"Deep Recovery\")\n\n                elif msg_type == \"photorec_tree_row\":\n                    if hasattr(self, \"photorec_tree\"):\n                        try:\n                            self.photorec_tree.insert(\"\", \"end\", values=payload)\n                        except Exception:\n                            pass\n\n                elif msg_type == \"mft_tree_row\":\n                    if hasattr(self, \"mft_tree\"):\n                        try:\n                            self.mft_tree.insert(\"\", \"end\", values=payload)\n                        except Exception:\n                            pass\n\n                elif msg_type == \"recovery_log\":\n                    self._append_recovery_log(str(payload))\n\n                elif msg_type == \"recovery_scan_stats\":\n                    self._apply_recovery_scan_stats(payload)\n\n                elif msg_type == \"clone_progress\":\n                    # payload: (pct:int, text:str, mode:str)\n                    try:\n                        if isinstance(payload, (list, tuple)) and len(payload) &gt;= 3:\n                            pct, text, mode = payload[0], payload[1], payload[2]\n                        elif isinstance(payload, (list, tuple)) and len(payload) &gt;= 2:\n                            pct, text, mode = payload[0], payload[1], \"clone\"\n                        else:\n                            pct, text, mode = int(payload), None, \"clone\"\n                    except Exception:\n                        try:\n                            pct = int(payload)\n                        except Exception:\n                            pct = 0\n                        text = None\n                        mode = \"clone\"\n                    if mode == \"partition\":\n                        if hasattr(self, \"partition_progress_bar\"):\n                            try:\n                                if pct is not None and float(pct) &gt; 0:\n                                    self.partition_progress_bar.stop()\n                                    self.partition_progress_bar.config(mode=\"determinate\")\n                                elif text is not None:\n                                    self.partition_progress_bar.config(mode=\"indeterminate\")\n                                    self.partition_progress_bar.start(10)\n                            except Exception:\n                                pass\n                        if hasattr(self, \"partition_progress_var\"):\n                            try:\n                                self.partition_progress_var.set(max(0.0, min(100.0, float(pct))))\n                            except Exception:\n                                pass\n                        if hasattr(self, \"partition_status_label\") and text is not None:\n                            try:\n                                self.partition_status_label.config(text=str(text)[:200])\n                            except Exception:\n                                pass\n                    else:\n                        if hasattr(self, \"clone_progress_bar\"):\n                            try:\n                                if pct is not None and float(pct) &gt; 0:\n                                    self.clone_progress_bar.stop()\n                                    self.clone_progress_bar.config(mode=\"determinate\")\n                                elif text is not None:\n                                    self.clone_progress_bar.config(mode=\"indeterminate\")\n                                    self.clone_progress_bar.start(10)\n                            except Exception:\n                                pass\n                        if hasattr(self, \"clone_progress_var\"):\n                            try:\n                                self.clone_progress_var.set(max(0.0, min(100.0, float(pct))))\n                            except Exception:\n                                pass\n                        if hasattr(self, \"clone_status_label\") and text is not None:\n                            try:\n                                self.clone_status_label.config(text=str(text)[:200])\n                            except Exception:\n                                pass\n\n                elif msg_type == \"finish_op\":\n                    self._finish_recovery_operation()\n                    self._on_rec_select()\n\n                elif msg_type == \"progress_bar_mode\":\n                    if hasattr(self, \"raw_progress_bar\"):\n                        try:\n                            self.raw_progress_bar.stop()\n                        except Exception:\n                            pass\n                        self.raw_progress_bar.config(mode=str(payload))\n\n                elif msg_type == \"progress_bar_start\":\n                    if hasattr(self, \"raw_progress_bar\"):\n                        try:\n                            self.raw_progress_bar.stop()\n                        except Exception:\n                            pass\n                        self.raw_progress_bar.config(mode=\"indeterminate\")\n                        self.raw_progress_bar.start(int(payload))\n\n                elif msg_type == \"progress_bar_stop\":\n                    if hasattr(self, \"raw_progress_bar\"):\n                        try:\n                            self.raw_progress_bar.stop()\n                        except Exception:\n                            pass\n                        self.raw_progress_bar.config(mode=\"determinate\")\n\n        except _queue_module.Empty:\n            pass\n        except Exception:\n            pass\n        finally:\n            # Re-schedule \u2014 always keep polling while the app is alive\n            self.after(50, self._poll_ui_queue)\n\n    def _poll_ram_service_metrics(self):\n        latest = None\n        try:\n            while not self._ram_service_metrics_queue.empty():\n                latest = self._ram_service_metrics_queue.get_nowait()\n        except Exception:\n            latest = None\n        if latest is not None:\n            try:\n                self._update_ram_service_metrics_ui(latest)\n            except Exception:\n                pass\n        self.after(35, self._poll_ram_service_metrics)\n\n    def _poll_hdd_recovery_metrics(self):\n        latest = None\n        try:\n            while not self._hdd_recovery_metrics_queue.empty():\n                latest = self._hdd_recovery_metrics_queue.get_nowait()\n        except Exception:\n            latest = None\n        if latest is not None:\n            try:\n                self._update_hdd_recovery_metrics_ui(latest)\n            except Exception:\n                pass\n        self._hdd_recovery_flush_pending_metrics()\n        self.after(30, self._poll_hdd_recovery_metrics)\n\n    def _hdd_recovery_flush_pending_metrics(self):\n        try:\n            with self._hdd_recovery_metrics_lock:\n                if self._hdd_recovery_pending_metrics is None:\n                    return\n                now = time.monotonic()\n                if now - self._hdd_recovery_last_dispatch &gt;= 0.120:\n                    self._hdd_recovery_last_dispatch = now\n                    self._hdd_recovery_metrics_queue.put(self._hdd_recovery_pending_metrics.copy())\n                    self._hdd_recovery_pending_metrics = None\n        except Exception:\n            pass\n\n    def _update_hdd_recovery_metrics_ui(self, data):\n        try:\n            if hasattr(self, \"raw_progress_var\") and data.get(\"progress_pct\") is not None:\n                self.raw_progress_var.set(max(0.0, min(100.0, float(data[\"progress_pct\"]))))\n            if hasattr(self, \"raw_progress_label\") and data.get(\"status_text\") is not None:\n                self.raw_progress_label.config(text=self._fix_text(str(data[\"status_text\"])))\n            if hasattr(self, \"scan_mode_label\") and data.get(\"scan_mode\") is not None:\n                self.scan_mode_label.config(text=self._fix_text(str(data[\"scan_mode\"])))\n            if hasattr(self, \"rec_stats_label\") and data.get(\"files_found\") is not None:\n                total = int(data.get(\"files_found\", 0))\n                selected = len(self.rec_tree.selection()) if hasattr(self, \"rec_tree\") else 0\n                self.rec_stats_label.config(text=f\"{total} files found | {selected} selected\")\n            if hasattr(self, \"hdd_resource_delta_lbl\") and data.get(\"delta_mb\") is not None:\n                before_mb = int(data.get(\"resource_before_mb\", 0))\n                after_mb = int(data.get(\"resource_after_mb\", 0))\n                delta_mb = int(data.get(\"delta_mb\", 0))\n                self.hdd_resource_delta_lbl.config(\n                    text=f\"Memory Delta: {self._fmt_size(delta_mb)} ({before_mb} MB \u2192 {after_mb} MB)\")\n            if hasattr(self, \"hdd_service_status_lbl\") and data.get(\"service_control\") is not None:\n                self.hdd_service_status_lbl.config(text=self._fix_text(str(data.get(\"service_control\"))))\n            if hasattr(self, \"ram_execution_log\") and data.get(\"log_line\") is not None:\n                self._append_log(self.ram_execution_log, str(data[\"log_line\"]), C[\"text\"])\n        except Exception:\n            pass\n\n    def _hdd_recovery_emit_metrics(self, batch):\n        try:\n            if not isinstance(batch, dict):\n                batch = {\"status_text\": str(batch)}\n            batch = {**batch, \"ts\": datetime.datetime.now().isoformat(timespec=\"milliseconds\")}\n            now = time.monotonic()\n            with self._hdd_recovery_metrics_lock:\n                self._hdd_recovery_pending_metrics = batch.copy()\n                if now - self._hdd_recovery_last_dispatch &gt;= 0.120:\n                    self._hdd_recovery_last_dispatch = now\n                    self._hdd_recovery_metrics_queue.put(batch.copy())\n                    self._hdd_recovery_pending_metrics = None\n        except Exception:\n            pass\n\n    def _ram_service_emit_metrics(self, batch, force=False):\n        try:\n            if not isinstance(batch, dict):\n                batch = {\"status_text\": str(batch)}\n            batch = {**batch, \"ts\": datetime.datetime.now().isoformat(timespec=\"milliseconds\")}\n            now = time.monotonic()\n            with self._ram_service_metrics_lock:\n                self._ram_service_pending_metrics = batch.copy()\n                if force or now - self._ram_service_last_dispatch &gt;= 0.120:\n                    self._ram_service_last_dispatch = now\n                    self._ram_service_metrics_queue.put(batch.copy())\n                    self._ram_service_pending_metrics = None\n        except Exception:\n            pass\n\n    def _snapshot_resource_state(self):\n        try:\n            vm = psutil.virtual_memory()\n            return {\n                \"available_mb\": int(vm.available / 1024**2),\n                \"used_mb\": int((vm.total - vm.available) / 1024**2),\n                \"total_mb\": int(vm.total / 1024**2),\n                \"percent\": round(vm.percent, 2),\n            }\n        except Exception:\n            return None\n\n    def _reclaim_memory(self):\n        try:\n            gc.collect()\n        except Exception:\n            pass\n        try:\n            kernel32 = ctypes.windll.kernel32\n            psapi = ctypes.windll.psapi\n            handle = kernel32.GetCurrentProcess()\n            psapi.EmptyWorkingSet(handle)\n        except Exception:\n            pass\n\n    def _submit_ram_service_job(self, name, target, *args, **kwargs):\n        jm = getattr(self, \"job_manager\", None)\n        if jm is not None and hasattr(jm, \"submit_callable\"):\n            try:\n                jm.submit_callable(name, target, *args, **kwargs)\n                return True\n            except Exception:\n                pass\n        manager = getattr(self, \"worker_manager\", None)\n        if manager is not None and hasattr(manager, \"submit\"):\n            try:\n                manager.submit(name, target, *args, **kwargs)\n                return True\n            except Exception:\n                pass\n        try:\n            threading.Thread(target=target, args=args, kwargs=kwargs, daemon=True).start()\n            return True\n        except Exception:\n            return False\n\n    def _ram_service_action_submit(self, name, target, button=None, *args, **kwargs):\n        if not hasattr(self, \"_ram_service_action_lock\"):\n            self._ram_service_action_lock = threading.Lock()\n            self._ram_service_action_running = False\n        with self._ram_service_action_lock:\n            if getattr(self, \"_ram_service_action_running\", False):\n                if hasattr(self, \"ram_log\"):\n                    self._append_log(self.ram_log, \"\u26a0\ufe0f RAM/Service action already running \u2014 duplicate request skipped\", C[\"warning\"])\n                return False\n            self._ram_service_action_running = True\n            if button is not None:\n                try:\n                    button.config(state=\"disabled\")\n                except Exception:\n                    pass\n\n        def _wrapped(*args, **kwargs):\n            try:\n                return target(*args, **kwargs)\n            finally:\n                with self._ram_service_action_lock:\n                    self._ram_service_action_running = False\n                if button is not None:\n                    try:\n                        button.config(state=\"normal\")\n                    except Exception:\n                        pass\n                try:\n                    gc.collect()\n                except Exception:\n                    pass\n\n        return self._submit_ram_service_job(name, _wrapped, *args, **kwargs)\n\n    def _submit_printer_job(self, name, target, *args, **kwargs):\n        jm = getattr(self, \"job_manager\", None)\n        if jm is not None and hasattr(jm, \"submit_callable\"):\n            try:\n                jm.submit_callable(name, target, *args, **kwargs)\n                return True\n            except Exception:\n                pass\n        manager = getattr(self, \"worker_manager\", None)\n        if manager is not None and hasattr(manager, \"submit\"):\n            try:\n                manager.submit(name, target, *args, **kwargs)\n                return True\n            except Exception:\n                pass\n        try:\n            threading.Thread(target=target, args=args, kwargs=kwargs, daemon=True).start()\n            return True\n        except Exception:\n            return False\n\n    def _set_printer_action_controls_enabled(self, enabled):\n        for btn in getattr(self, \"_printer_action_buttons\", []):\n            try:\n                btn.config(state=\"normal\" if enabled else \"disabled\")\n            except Exception:\n                pass\n\n    def _printer_action_submit(self, name, target, *args, button=None, **kwargs):\n        with self._printer_action_lock:\n            if getattr(self, \"_printer_action_running\", False):\n                self._printer_log(\"\u26a0\ufe0f Printer action already running \u2014 duplicate request skipped\", C[\"warning\"])\n                return False\n            self._printer_action_running = True\n            self._printer_action_started_at = time.time()\n            self._printer_action_name = name\n            self._set_printer_action_controls_enabled(False)\n            if button is not None:\n                try:\n                    button.config(state=\"disabled\")\n                except Exception:\n                    pass\n\n        def _wrapped(*args, **kwargs):\n            try:\n                self._printer_emit_metrics({\"status_text\": f\"{name} running... elapsed 00:00\"})\n                return target(*args, **kwargs)\n            finally:\n                with self._printer_action_lock:\n                    self._printer_action_running = False\n                    self._printer_action_started_at = None\n                    self._printer_action_name = \"\"\n                self._printer_emit_metrics({\"status_text\": f\"{name} finished\"})\n                self._set_printer_action_controls_enabled(True)\n                if button is not None:\n                    try:\n                        button.config(state=\"normal\")\n                    except Exception:\n                        pass\n                try:\n                    gc.collect()\n                except Exception:\n                    pass\n\n        return self._submit_printer_job(name, _wrapped, *args, **kwargs)\n\n    def _tick_printer_action_timer(self):\n        try:\n            if getattr(self, \"_printer_action_running\", False) and getattr(self, \"_printer_action_started_at\", None):\n                elapsed = time.time() - float(self._printer_action_started_at)\n                name = getattr(self, \"_printer_action_name\", \"Printer action\") or \"Printer action\"\n                if hasattr(self, \"printer_exec_time_lbl\"):\n                    self.printer_exec_time_lbl.config(text=f\"Elapsed: {self._format_seconds(elapsed)} | ETA: depends on Windows service response\")\n                if hasattr(self, \"printer_exec_status_lbl\"):\n                    self.printer_exec_status_lbl.config(text=f\"{name} running...\")\n            elif hasattr(self, \"printer_exec_time_lbl\"):\n                self.printer_exec_time_lbl.config(text=\"Elapsed: 00:00 | ETA: --\")\n        except Exception:\n            pass\n        self.after(1000, self._tick_printer_action_timer)\n\n    def _poll_printer_metrics(self):\n        latest = None\n        try:\n            while not self._printer_metrics_queue.empty():\n                latest = self._printer_metrics_queue.get_nowait()\n        except Exception:\n            latest = None\n        if latest is not None:\n            try:\n                self._update_printer_metrics_ui(latest)\n            except Exception:\n                pass\n        self.after(30, self._poll_printer_metrics)\n\n    def _update_printer_metrics_ui(self, data):\n        try:\n            if hasattr(self, \"printer_exec_status_lbl\") and data.get(\"status_text\") is not None:\n                self.printer_exec_status_lbl.config(text=self._fix_text(str(data[\"status_text\"])), fg=C.get(\"accent4\", C[\"text\"]))\n            if hasattr(self, \"spooler_status_lbl\") and data.get(\"service_status\") is not None:\n                self.spooler_status_lbl.config(text=self._fix_text(str(data.get(\"service_status\"))))\n            if hasattr(self, \"printer_log\") and data.get(\"log_line\") is not None:\n                self._append_log(self.printer_log, str(data[\"log_line\"]), data.get(\"log_color\", C[\"text\"]))\n            if hasattr(self, \"printer_trace_log\") and data.get(\"trace_line\") is not None:\n                self._append_log(self.printer_trace_log, str(data[\"trace_line\"]), data.get(\"trace_color\", C[\"text_dim\"]))\n        except Exception:\n            pass\n\n    def _printer_emit_metrics(self, batch, force=False):\n        try:\n            if not isinstance(batch, dict):\n                batch = {\"status_text\": str(batch)}\n            batch = {**batch, \"ts\": datetime.datetime.now().isoformat(timespec=\"milliseconds\")}\n            with self._printer_metrics_lock:\n                self._printer_metrics_queue.put(batch.copy())\n        except Exception:\n            pass\n\n    def _printer_log(self, msg, color=C[\"text\"]):\n        self._printer_emit_metrics({\"log_line\": msg, \"log_color\": color})\n\n    def _printer_trace(self, msg, color=C[\"text_dim\"]):\n        self._printer_emit_metrics({\"trace_line\": msg, \"trace_color\": color})\n\n    def _submit_registry_gp_job(self, name, target, *args, **kwargs):\n        jm = getattr(self, \"job_manager\", None)\n        if jm is not None and hasattr(jm, \"submit_callable\"):\n            try:\n                jm.submit_callable(name, target, *args, **kwargs)\n                return True\n            except Exception:\n                pass\n        manager = getattr(self, \"worker_manager\", None)\n        if manager is not None and hasattr(manager, \"submit\"):\n            try:\n                manager.submit(name, target, *args, **kwargs)\n                return True\n            except Exception:\n                pass\n        try:\n            threading.Thread(target=target, args=args, kwargs=kwargs, daemon=True).start()\n            return True\n        except Exception:\n            return False\n\n    def _poll_registry_gp_metrics(self):\n        latest = None\n        try:\n            while not self._registry_gp_metrics_queue.empty():\n                latest = self._registry_gp_metrics_queue.get_nowait()\n        except Exception:\n            latest = None\n        if latest is not None:\n            try:\n                self._update_registry_gp_metrics_ui(latest)\n            except Exception:\n                pass\n        self.after(40, self._poll_registry_gp_metrics)\n\n    def _update_registry_gp_metrics_ui(self, data):\n        try:\n            if hasattr(self, \"reg_progress_var\") and data.get(\"progress_pct\") is not None:\n                self.reg_progress_var.set(max(0.0, min(100.0, float(data[\"progress_pct\"]))))\n            if hasattr(self, \"reg_status_lbl\") and data.get(\"status_text\") is not None:\n                self.reg_status_lbl.config(text=self._fix_text(str(data[\"status_text\"])))\n            if hasattr(self, \"reg_keys_changed_var\") and data.get(\"keys_changed\") is not None:\n                self.reg_keys_changed_var.set(str(int(data[\"keys_changed\"])))\n            if hasattr(self, \"reg_predicted_impact_var\") and data.get(\"predicted_impact\") is not None:\n                self.reg_predicted_impact_var.set(str(int(data.get(\"predicted_impact\", 0))))\n            if hasattr(self, \"reg_confidence_var\") and data.get(\"confidence_score\") is not None:\n                self.reg_confidence_var.set(f\"{int(data.get('confidence_score', 0))}%\")\n            if hasattr(self, \"gp_progress_var\") and data.get(\"progress_pct\") is not None:\n                self.gp_progress_var.set(max(0.0, min(100.0, float(data[\"progress_pct\"]))))\n            if hasattr(self, \"gp_status_lbl\") and data.get(\"status_text\") is not None:\n                self.gp_status_lbl.config(text=self._fix_text(str(data[\"status_text\"])))\n            if hasattr(self, \"gp_action_count_var\") and data.get(\"actions_done\") is not None:\n                self.gp_action_count_var.set(str(int(data[\"actions_done\"])))\n            if hasattr(self, \"gp_policy_score_var\") and data.get(\"policy_score\") is not None:\n                self.gp_policy_score_var.set(f\"{int(data[\"policy_score\"])}%\")\n            if hasattr(self, \"gp_restart_risk_var\") and data.get(\"restart_risk\") is not None:\n                self.gp_restart_risk_var.set(str(data[\"restart_risk\"]))\n        except Exception:\n            pass\n\n    # \u2500\u2500 Thread-safe queue helpers (called from background threads) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _q(self, msg_type, payload=None):\n        \"\"\"Thread-safe: enqueue a UI update message.\"\"\"\n        try:\n            self._ui_queue.put_nowait((msg_type, payload))\n        except Exception:\n            pass\n\n    def _q_progress(self, text, pct=None):\n        \"\"\"Enqueue a progress label + optional percentage update.\"\"\"\n        self._q(\"progress_label\", text)\n        if pct is not None:\n            self._q(\"progress_pct\", pct)\n\n    def _q_log(self, text):\n        \"\"\"Enqueue a log line append.\"\"\"\n        self._q(\"log_line\", text)\n\n    def _q_tree_row(self, row, entry):\n        \"\"\"Enqueue a tree row insertion.\"\"\"\n        self._q(\"tree_row\", (row, entry))\n\n    # \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _safe_json(self, value):\n        try:\n            json.dumps(value)\n            return value\n        except Exception:\n            return str(value)\n\n    def _audit_event(self, event_type, payload):\n        try:\n            if not getattr(self, \"audit_file\", \"\"):\n                return\n            rec = {\n                \"ts\": datetime.datetime.now().isoformat(timespec=\"seconds\"),\n                \"event\": str(event_type),\n                \"payload\": self._safe_json(payload),\n            }\n            with open(self.audit_file, \"a\", encoding=\"utf-8\") as f:\n                f.write(json.dumps(rec, ensure_ascii=False) + \"\\n\")\n            try:\n                if hasattr(self, \"structured_logger\"):\n                    self.structured_logger.event(\"legacy_app\", str(event_type), legacy_payload=payload)\n                store = getattr(self, \"audit_store\", None)\n                if store is not None:\n                    store.append(\"legacy_app\", str(event_type), payload)\n            except Exception:\n                pass\n        except Exception:\n            pass\n\n    def _snapshot_system_state(self):\n        try:\n            vm = psutil.virtual_memory()\n            du = psutil.disk_usage(\"C:\\\\\")\n            cpu = psutil.cpu_percent(interval=None)\n            proc_count = len(list(psutil.process_iter([\"pid\"])))\n            return {\n                \"cpu_percent\": round(cpu, 2),\n                \"ram_percent\": round(vm.percent, 2),\n                \"disk_percent\": round(du.percent, 2),\n                \"process_count\": proc_count,\n                \"ts\": datetime.datetime.now().isoformat(timespec=\"seconds\"),\n            }\n        except Exception as e:\n            return {\"error\": str(e)}\n\n    def _launch_job(self, name, target, *args, **kwargs):\n        with self._job_lock:\n            self._job_counter += 1\n            jid = f\"job-{self._job_counter}\"\n            self._jobs[jid] = {\n                \"name\": name,\n                \"status\": \"queued\",\n                \"started_at\": datetime.datetime.now().isoformat(timespec=\"seconds\"),\n            }\n\n        def runner():\n            with self._job_lock:\n                if jid in self._jobs:\n                    self._jobs[jid][\"status\"] = \"running\"\n            self._audit_event(\"job_started\", {\"job_id\": jid, \"name\": name})\n            try:\n                target(*args, **kwargs)\n                with self._job_lock:\n                    if jid in self._jobs:\n                        self._jobs[jid][\"status\"] = \"done\"\n            except Exception as e:\n                with self._job_lock:\n                    if jid in self._jobs:\n                        self._jobs[jid][\"status\"] = \"failed\"\n                        self._jobs[jid][\"error\"] = str(e)\n                self._audit_event(\"job_failed\", {\"job_id\": jid, \"name\": name, \"error\": str(e)})\n                self.after(0, lambda: self._log(f\"Background job failed [{name}]: {e}\", \"ERR\"))\n            finally:\n                with self._job_lock:\n                    if jid in self._jobs:\n                        self._jobs[jid][\"ended_at\"] = datetime.datetime.now().isoformat(timespec=\"seconds\")\n                self._audit_event(\"job_finished\", {\"job_id\": jid, \"name\": name})\n\n        manager = getattr(self, \"worker_manager\", None)\n        # Prefer centralized JobManager if available\n        jm = getattr(self, \"job_manager\", None)\n        if jm is not None and hasattr(jm, \"submit_callable\"):\n            try:\n                # enqueue the runner as a job\n                return jm.submit_callable(name, runner)\n            except Exception:\n                pass\n        if manager is not None and hasattr(manager, \"submit\"):\n            try:\n                manager.submit(name, runner)\n            except Exception:\n                threading.Thread(target=runner, daemon=True).start()\n        else:\n            threading.Thread(target=runner, daemon=True).start()\n        return jid\n    \n    def _create_tooltip(self, widget, text, delay=430):\n        \"\"\"Attach a small hover tooltip to a widget.\"\"\"\n        if not widget or not text:\n            return\n        tipdata = {\"id\": None, \"window\": None}\n\n        def _show(event=None):\n            if tipdata[\"window\"] or not text:\n                return\n            try:\n                x = widget.winfo_rootx() + 18\n                y = widget.winfo_rooty() + widget.winfo_height() + 6\n                win = tk.Toplevel(widget)\n                win.wm_overrideredirect(True)\n                win.attributes(\"-topmost\", True)\n                win.config(bg=C[\"text_dark\"])\n                lbl = tk.Label(win, text=text, justify=\"left\", bg=C[\"text_dark\"], fg=C[\"text\"],\n                               font=FONTS[\"xsmall\"], wraplength=320, relief=\"solid\", bd=1, padx=6, pady=4)\n                lbl.pack()\n                win.wm_geometry(f\"+{x}+{y}\")\n                tipdata[\"window\"] = win\n            except Exception:\n                tipdata[\"window\"] = None\n\n        def _hide(event=None):\n            try:\n                if tipdata[\"id\"]:\n                    self.after_cancel(tipdata[\"id\"])\n                    tipdata[\"id\"] = None\n                if tipdata[\"window\"]:\n                    tipdata[\"window\"].destroy()\n                    tipdata[\"window\"] = None\n            except Exception:\n                pass\n\n        def _schedule(event=None):\n            _hide()\n            try:\n                tipdata[\"id\"] = self.after(delay, _show)\n            except Exception:\n                tipdata[\"id\"] = None\n\n        widget.bind(\"\", _schedule)\n        widget.bind(\"\", _hide)\n        widget.bind(\"\", _hide)\n        return tipdata\n\n    # ---------- STYLE ----------\n    def _build_style(self):\n        self.style = ttk.Style(self)\n        self.style.theme_use(\"clam\")\n        self.style.configure(\"TFrame\", background=C[\"bg\"])\n        self.style.configure(\"Card.TFrame\", background=C[\"card\"])\n        self.style.configure(\"Panel.TFrame\", background=C[\"panel\"])\n        self.style.configure(\"Sidebar.TFrame\", background=C[\"sidebar\"])\n        self.style.configure(\"TProgressbar\", troughcolor=C[\"border\"], background=C[\"accent\"], thickness=6)\n        self.style.configure(\"TNotebook\", background=C[\"bg\"], borderwidth=0)\n        self.style.configure(\"TNotebook.Tab\", background=C[\"panel\"], foreground=C[\"text_dim\"], padding=[16, 6], borderwidth=0)\n        self.style.map(\"TNotebook.Tab\",\n                        background=[(\"selected\", C[\"card\"]), (\"active\", C[\"panel\"]), (\"!active\", C[\"panel\"])],\n                        foreground=[(\"selected\", C[\"accent\"]), (\"active\", C[\"text\"]), (\"!active\", C[\"text_dim\"])])\n        self.style.configure(\"Custom.Treeview\", background=C[\"card\"], foreground=C[\"text\"],\n                             fieldbackground=C[\"card\"], rowheight=22, font=FONTS[\"small\"])\n        self.style.configure(\"Custom.Treeview.Heading\", background=C[\"panel\"],\n                             foreground=C[\"accent\"], font=FONTS[\"small\"])\n\n    # ---------- HEADER ----------\n    def _build_header(self):\n        hdr = tk.Frame(self, bg=C[\"header_bg\"], height=62)\n        hdr.pack(side=\"top\", fill=\"x\")\n        hdr.pack_propagate(False)\n        tk.Frame(hdr, bg=C[\"accent\"], height=2).pack(side=\"bottom\", fill=\"x\")\n\n        logo_frame = tk.Frame(hdr, bg=C[\"header_bg\"])\n        logo_frame.pack(side=\"left\", padx=20, pady=8)\n        tk.Label(logo_frame, text=\"\u26a1\", font=(\"Segoe UI\", 24), fg=C[\"accent\"], bg=C[\"header_bg\"]).pack(side=\"left\", padx=(0,8))\n        tk.Label(logo_frame, text=\"Godawari\", font=(\"Segoe UI\", 18, \"bold\"), fg=C[\"text\"], bg=C[\"header_bg\"]).pack(side=\"left\")\n        tk.Label(logo_frame, text=\" Computers\", font=(\"Segoe UI\", 18, \"bold\"), fg=C[\"accent\"], bg=C[\"header_bg\"]).pack(side=\"left\")\n        tk.Label(logo_frame, text=\"  Optimizer Pro v11.0\", font=(\"Segoe UI\", 10, \"bold\"), fg=C[\"accent2\"], bg=C[\"header_bg\"]).pack(side=\"left\", pady=(6,0))\n        tk.Label(logo_frame, text=f\"  |  Last Updated: {SCRIPT_LAST_UPDATED}\", font=(\"Segoe UI\", 9), fg=C[\"text_dim\"], bg=C[\"header_bg\"]).pack(side=\"left\", pady=(6,0))\n\n        right = tk.Frame(hdr, bg=C[\"header_bg\"])\n        right.pack(side=\"right\", padx=20, pady=10)\n        self.clock_lbl = tk.Label(right, font=FONTS[\"small\"], fg=C[\"accent\"], bg=C[\"header_bg\"])\n        self.clock_lbl.pack(side=\"right\")\n        tk.Label(right, text=f\"  {platform.node()}  |  {platform.system()} {platform.release()}  |  \",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"header_bg\"]).pack(side=\"right\")\n        self._tick_clock()\n\n        badge_color = C[\"success\"] if is_admin() else C[\"error\"]\n        badge_text = \"\u25cf ADMIN MODE ON\" if is_admin() else \"\u25cf USER MODE (Admin required!)\"\n        tk.Label(hdr, text=badge_text, font=FONTS[\"small\"], fg=badge_color, bg=C[\"header_bg\"]).pack(side=\"right\", padx=12)\n\n        self.theme_btn = tk.Button(hdr, text=\"\ud83c\udf19\", font=(\"Segoe UI\", 10), bg=C[\"panel\"],\n                                   fg=C[\"accent\"], bd=0, padx=6, cursor=\"hand2\", command=self._toggle_theme)\n        self.theme_btn.pack(side=\"right\", padx=10)\n        tk.Label(hdr, text=\"Shravan Shrimali\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"header_bg\"]).pack(side=\"right\", padx=10)\n\n    def _tick_clock(self):\n        self.clock_lbl.config(text=datetime.datetime.now().strftime(\"%d/%m/%Y  %H:%M:%S\"))\n        self.after(1000, self._tick_clock)\n\n    # ---------- BODY ----------\n    # Section builder map \u2014 lazy loading ke liye\n    _SECTION_BUILDERS = {\n        \"dashboard\":      \"_build_dashboard\",\n        \"shop\":           \"_build_shop_mode\",\n        \"cleaner\":        \"_build_cleaner\",\n        \"services\":       \"_build_services\",\n        \"memory\":         \"_build_memory_services_merged\",\n        \"startup\":        \"_build_startup_scheduler_merged\",\n        \"registry\":       \"_build_registry_gp_merged\",\n        \"network\":        \"_build_network_troubleshooter_merged\",\n        \"hdd_repair\":     \"_build_hdd_recovery_merged\",\n        \"data_recovery\":  \"_build_data_recovery\",\n        \"rescue_center\":  \"_build_rescue_recovery_center\",\n        \"printer\":        \"_build_printer_driver_merged\",\n        \"uninstall\":      \"_build_uninstall_backup_merged\",\n        \"dupfinder\":      \"_build_dup_report_merged\",\n        \"grouppolicy\":    \"_build_grouppolicy\",\n        \"scheduler\":      \"_build_scheduler\",\n        \"troubleshooter\": \"_build_troubleshooter\",\n        \"power\":          \"_build_power\",\n        \"driver\":         \"_build_driver\",\n        \"backup\":         \"_build_backup\",\n        \"report\":         \"_build_report\",\n        \"log\":            \"_build_log\",\n        \"boost\":          \"_build_boost_section\",\n        \"suspicion\":      \"_build_suspicion_scanner\",\n        \"realtime_security\": \"_build_realtime_security\",\n        \"activation\":     \"_build_activation\",\n        \"eventviewer\":    \"_build_event_viewer\",\n        \"office_tools\":   \"_build_office_tools\",\n        \"excel_tools\":    \"_build_excel_tools\",\n        \"image_tools\":    \"_build_image_tools\",\n        \"file_tools\":     \"_build_file_tools\",\n        \"safety_center\":  \"_build_safety_center\",\n        \"driver_manager\": \"_build_driver_manager\",\n        \"partition_manager\": \"_build_partition_manager\",\n        \"easy_driver\":    \"_build_easy_driver_clone\",\n        \"svc_presets\":    \"_build_svc_presets\",\n        \"disk_analyzer\":  \"_build_disk_analyzer\",\n        \"bsod_history\":   \"_build_bsod_history\",\n        \"corrupt_wizard\": \"_build_corrupt_wizard\",\n        \"password_audit\": \"_build_password_audit\",\n        \"auto_backup\":    \"_build_auto_backup\",\n    }\n\n    def _build_body(self):\n        body = tk.Frame(self, bg=C[\"bg\"])\n        body.pack(fill=\"both\", expand=True)\n        self.sidebar = tk.Frame(body, bg=C[\"sidebar\"], width=260)\n        self.sidebar.pack(side=\"left\", fill=\"y\")\n        self.sidebar.pack_propagate(False)\n        tk.Frame(self.sidebar, bg=C[\"border\"], width=1).pack(side=\"right\", fill=\"y\")\n        self._build_sidebar()\n        self.main = tk.Frame(body, bg=C[\"bg\"])\n        self.main.pack(side=\"left\", fill=\"both\", expand=True)\n        self.sections = {}\n        self._sections_built = set()\n        self._build_queue = []\n\n        # Sirf dashboard abhi banaao \u2014 baki lazy load honge\n        self.sections[\"dashboard\"] = self._build_dashboard(self.main)\n        self._sections_built.add(\"dashboard\")\n\n        # Baki ke liye placeholder frames\n        for key in self._SECTION_BUILDERS:\n            if key == \"dashboard\":\n                continue\n            ph = tk.Frame(self.main, bg=C[\"bg\"])\n            tk.Label(ph, text=\"\u23f3\", font=(\"Segoe UI\", 28),\n                     fg=C[\"accent\"], bg=C[\"bg\"]).place(relx=0.5, rely=0.42, anchor=\"center\")\n            tk.Label(ph, text=\"Loading...\", font=FONTS[\"heading\"],\n                     fg=C[\"text_dim\"], bg=C[\"bg\"]).place(relx=0.5, rely=0.52, anchor=\"center\")\n            self.sections[key] = ph\n            self._build_queue.append(key)\n\n        # Keep startup fast: sections are built when the user opens them.\n        self.after(600, self._sanitize_ui_texts)\n\n    def _lazy_build_next(self):\n        if not self._build_queue:\n            return\n        key = self._build_queue.pop(0)\n        try:\n            real = getattr(self, self._SECTION_BUILDERS[key])(self.main)\n            self.sections[key] = real\n            self._sections_built.add(key)\n            if self.active_section.get() == key:\n                for s in self.sections.values():\n                    s.pack_forget()\n                real.pack(fill=\"both\", expand=True)\n        except Exception as e:\n            import traceback\n            err_detail = traceback.format_exc()\n            self._log(f\"Lazy build [{key}] ERROR: {err_detail}\", \"WARN\")\n            # Replace placeholder with error frame so user knows something failed\n            err_frame = tk.Frame(self.main, bg=C[\"bg\"])\n            tk.Label(err_frame, text=f\"\u274c '{key}' section load nahi hua\",\n                     font=FONTS[\"heading\"], fg=C[\"error\"], bg=C[\"bg\"]).place(relx=0.5, rely=0.40, anchor=\"center\")\n            tk.Label(err_frame, text=str(e)[:200],\n                     font=FONTS[\"small\"], fg=C[\"warning\"], bg=C[\"bg\"], wraplength=500).place(relx=0.5, rely=0.50, anchor=\"center\")\n            tk.Button(err_frame, text=\"\ud83d\udd04 Retry\",\n                      font=FONTS[\"body\"], bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=16, pady=8,\n                      cursor=\"hand2\",\n                      command=lambda k=key: (self._sections_built.discard(k),\n                                              self._show_section(k))).place(relx=0.5, rely=0.62, anchor=\"center\")\n            self.sections[key] = err_frame\n        if self._build_queue:\n            self.after(40, self._lazy_build_next)\n\n    def _build_sidebar(self):\n        canvas = tk.Canvas(self.sidebar, bg=C[\"sidebar\"], highlightthickness=0)\n        scrollbar = tk.Scrollbar(self.sidebar, orient=\"vertical\", command=canvas.yview)\n        self.sidebar_frame = tk.Frame(canvas, bg=C[\"sidebar\"])\n        self.sidebar_frame.bind(\"\", lambda e: canvas.configure(scrollregion=canvas.bbox(\"all\")))\n        sidebar_window = canvas.create_window((0, 0), window=self.sidebar_frame, anchor=\"nw\")\n        canvas.configure(yscrollcommand=scrollbar.set)\n        scrollbar.pack(side=\"right\", fill=\"y\")\n        canvas.pack(side=\"left\", fill=\"both\", expand=True)\n\n        def _sidebar_resize(event=None):\n            canvas.itemconfig(sidebar_window, width=event.width)\n            canvas.configure(scrollregion=canvas.bbox(\"all\"))\n        canvas.bind(\"\", _sidebar_resize)\n\n        self._bind_scoped_mousewheel(self.sidebar_frame, canvas)\n\n        tk.Label(self.sidebar_frame, text=\"GODAWARI COMPUTERS\", font=(\"Segoe UI\", 10, \"bold\"),\n                 fg=C[\"accent\"], bg=C[\"sidebar\"]).pack(pady=(12,2), padx=14, anchor=\"w\")\n        tk.Label(self.sidebar_frame, text=\"Optimizer Pro v11.0\", font=FONTS[\"small\"],\n                 fg=C[\"text_dim\"], bg=C[\"sidebar\"]).pack(pady=(0,8), padx=14, anchor=\"w\")\n\n        categories = SIDEBAR_CATEGORIES\n        self.nav_btns = {}\n        for heading, color_key, items in categories:\n            color = C[color_key]\n            # Category separator line\n            tk.Frame(self.sidebar_frame, bg=C[\"border\"], height=1).pack(fill=\"x\", padx=10, pady=(8,0))\n            tk.Label(self.sidebar_frame, text=heading, font=(\"Segoe UI\", 8, \"bold\"), fg=color, bg=C[\"sidebar\"]).pack(pady=(4,3), padx=14, anchor=\"w\")\n            for key, icon, label in items:\n                frame = tk.Frame(self.sidebar_frame, bg=C[\"sidebar\"], cursor=\"hand2\")\n                frame.pack(fill=\"x\", padx=8, pady=1)\n                hw_keys = set()\n                icon_fg = C[\"hw_accent\"] if key in hw_keys else C[\"accent\"]\n                tk.Label(frame, text=icon, font=(\"Segoe UI\", 8, \"bold\"), bg=C[\"sidebar\"], fg=icon_fg, width=5, anchor=\"center\").pack(side=\"left\", padx=(8,6), pady=6)\n                tk.Label(frame, text=label, font=FONTS[\"body\"], bg=C[\"sidebar\"], fg=C[\"text\"], anchor=\"w\").pack(side=\"left\", fill=\"x\", expand=True)\n                def on_enter(e, k=key, f=frame): \n                    if self.active_section.get() != k:\n                        f.config(bg=C[\"card\"])\n                        for w in f.winfo_children():\n                            w.config(bg=C[\"card\"])\n                def on_leave(e, k=key, f=frame): \n                    if self.active_section.get() != k:\n                        f.config(bg=C[\"sidebar\"])\n                        for w in f.winfo_children():\n                            w.config(bg=C[\"sidebar\"])\n                def on_click(e, k=key):\n                    self._show_section(k)\n                frame.bind(\"\", on_enter)\n                frame.bind(\"\", on_leave)\n                frame.bind(\"\", on_click)\n                for child in frame.winfo_children():\n                    child.bind(\"\", on_enter)\n                    child.bind(\"\", on_leave)\n                    child.bind(\"\", on_click)\n                self.nav_btns[key] = frame\n\n        tk.Frame(self.sidebar_frame, bg=C[\"border\"], height=1).pack(fill=\"x\", padx=10, pady=10)\n        info = tk.Frame(self.sidebar_frame, bg=C[\"panel\"])\n        info.pack(fill=\"x\", padx=10, pady=(0,10))\n        ram_gb = round(psutil.virtual_memory().total / (1024**3), 1)\n        for line in [f\"CPU: {psutil.cpu_count()} cores\", f\"RAM: {ram_gb} GB\", f\"OS: Windows {platform.release()}\"]:\n            tk.Label(info, text=line, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(anchor=\"w\", padx=8, pady=2)\n\n    def _show_section(self, key):\n        if key not in self.sections:\n            return\n        # On-demand build agar abhi tak nahi bana\n        if hasattr(self, \"_sections_built\") and key not in self._sections_built:\n            if key in getattr(self, \"_build_queue\", []):\n                self._build_queue.remove(key)\n            try:\n                real = getattr(self, self._SECTION_BUILDERS[key])(self.main)\n                self.sections[key] = real\n                self._sections_built.add(key)\n                self.after(50, self._sanitize_ui_texts)\n            except Exception as e:\n                import traceback\n                err_msg = traceback.format_exc()\n                self._log(f\"On-demand build [{key}]: {e}\", \"WARN\")\n                # Show error frame instead of silent loading screen\n                err_frame = tk.Frame(self.main, bg=C[\"bg\"])\n                tk.Label(err_frame, text=\"\u274c Section load nahi hua\",\n                         font=FONTS[\"heading\"], fg=C[\"error\"], bg=C[\"bg\"]).place(relx=0.5, rely=0.40, anchor=\"center\")\n                tk.Label(err_frame, text=str(e)[:200],\n                         font=FONTS[\"small\"], fg=C[\"warning\"], bg=C[\"bg\"], wraplength=500).place(relx=0.5, rely=0.50, anchor=\"center\")\n                tk.Button(err_frame, text=\"\ud83d\udd04 Retry\", font=FONTS[\"body\"],\n                          bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=16, pady=8,\n                          cursor=\"hand2\",\n                          command=lambda k=key: (self._sections_built.discard(k),\n                                                  self._show_section(k))).place(relx=0.5, rely=0.62, anchor=\"center\")\n                self.sections[key] = err_frame\n        old = self.active_section.get()\n        if old in self.nav_btns:\n            self.nav_btns[old].config(bg=C[\"sidebar\"])\n            for w in self.nav_btns[old].winfo_children():\n                w.config(bg=C[\"sidebar\"])\n        self.active_section.set(key)\n        if key in self.nav_btns:\n            self.nav_btns[key].config(bg=C[\"btn_info\"])\n            for w in self.nav_btns[key].winfo_children():\n                w.config(bg=C[\"btn_info\"])\n        for k, sec in self.sections.items():\n            sec.pack_forget()\n        self.sections[key].pack(fill=\"both\", expand=True)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  MERGED SECTION BUILDERS \u2014 2 sections ek tabbed view mein\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _build_tabbed_merger(self, parent, tabs):\n        \"\"\"\n        tabs = [(tab_label, builder_method_name), ...]\n        Ek frame return karta hai jisme top mein tab buttons hain,\n        niche active tab ka content.\n        \"\"\"\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        tab_bar = tk.Frame(frame, bg=C[\"panel\"])\n        tab_bar.pack(fill=\"x\")\n        content_area = tk.Frame(frame, bg=C[\"bg\"])\n        content_area.pack(fill=\"both\", expand=True)\n\n        built = {}\n        active_btn = [None]\n\n        def show_tab(idx, btn):\n            if active_btn[0]:\n                active_btn[0].config(bg=C[\"panel\"], fg=C[\"text_dim\"])\n            btn.config(bg=C[\"accent\"], fg=C[\"bg\"])\n            active_btn[0] = btn\n            for w in content_area.winfo_children():\n                w.pack_forget()\n            key = tabs[idx][0]\n            if key not in built:\n                built[key] = getattr(self, tabs[idx][1])(content_area)\n            built[key].pack(fill=\"both\", expand=True)\n\n        btns = []\n        for i, (label, _) in enumerate(tabs):\n            b = tk.Button(tab_bar, text=label, font=FONTS[\"subhead\"],\n                          bg=C[\"panel\"], fg=C[\"text_dim\"], bd=0, padx=20, pady=8,\n                          cursor=\"hand2\", relief=\"flat\",\n                          command=lambda idx=i: show_tab(idx, btns[idx]))\n            b.pack(side=\"left\")\n            btns.append(b)\n        tk.Frame(tab_bar, bg=C[\"border\"], height=2).pack(side=\"bottom\", fill=\"x\")\n\n        # Default: first tab\n        frame.after(10, lambda: show_tab(0, btns[0]))\n        return frame\n\n    def _build_memory_services_merged(self, parent):\n        return self._build_tabbed_merger(parent, [\n            (\"\ud83e\udde0  RAM Optimizer\", \"_build_memory\"),\n            (\"\u2699\ufe0f  Smart Services\", \"_build_services\"),\n        ])\n\n    def _build_startup_scheduler_merged(self, parent):\n        return self._build_tabbed_merger(parent, [\n            (\"\ud83d\ude80  Startup Manager\", \"_build_startup\"),\n            (\"\ud83d\udcc5  Task Scheduler\", \"_build_scheduler\"),\n        ])\n\n    def _build_registry_gp_merged(self, parent):\n        return self._build_tabbed_merger(parent, [\n            (\"\ud83d\udcdd  Registry Tweaks\", \"_build_registry\"),\n            (\"\ud83d\udee1  Group Policy\", \"_build_grouppolicy\"),\n        ])\n\n    def _build_network_troubleshooter_merged(self, parent):\n        return self._build_tabbed_merger(parent, [\n            (\"\ud83c\udf10  Network Optimizer\", \"_build_network\"),\n            (\"\ud83d\udd27  System Troubleshooter\", \"_build_troubleshooter\"),\n        ])\n\n    def _build_hdd_recovery_merged(self, parent):\n        return self._build_tabbed_merger(parent, [\n            (\"\ud83d\udcbe  HDD/SSD Repair\", \"_build_hdd_repair\"),\n            (\"\ud83d\udcc2  File Recovery\", \"_build_recovery_center\"),\n        ])\n\n    def _build_data_recovery(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(\n            frame,\n            \"\ud83d\udd2c Data Recovery\",\n            \"Forensic-grade imaging, deep carving, partition recovery, and raw sector inspection.\",\n        )\n\n        self._data_recovery_state = getattr(self, \"_data_recovery_state\", {\n            \"running\": False,\n            \"paused\": False,\n            \"cancelled\": False,\n            \"last_img\": \"\",\n            \"last_report\": \"\",\n            \"preview\": [],\n            \"scan_mode\": \"quick\",\n        })\n\n        hero = tk.Frame(frame, bg=C[\"panel\"], highlightbackground=C[\"border\"], highlightthickness=1)\n        hero.pack(fill=\"x\", padx=16, pady=(8, 10))\n        hero.columnconfigure(0, weight=2)\n        hero.columnconfigure(1, weight=1)\n\n        left = tk.Frame(hero, bg=C[\"panel\"])\n        left.grid(row=0, column=0, sticky=\"nsew\", padx=(16, 10), pady=16)\n        tk.Label(\n            left,\n            text=\"Godawari Ultimate Optimizer v11 \u2014 Data Recovery\",\n            font=(\"Segoe UI\", 18, \"bold\"),\n            fg=C[\"text\"],\n            bg=C[\"panel\"],\n        ).pack(anchor=\"w\")\n        tk.Label(\n            left,\n            text=\"Forensic-grade imaging, deep carving, partition recovery, and safe raw-sector inspection in one premium control center.\",\n            font=FONTS[\"small\"],\n            fg=C[\"text_dim\"],\n            bg=C[\"panel\"],\n            justify=\"left\",\n            wraplength=760,\n        ).pack(anchor=\"w\", pady=(4, 10))\n\n        chip_row = tk.Frame(left, bg=C[\"panel\"])\n        chip_row.pack(fill=\"x\")\n        for text, color in [(\"Quick Recovery\", C[\"accent2\"]), (\"Deep Carve\", C[\"warning\"]), (\"Partition Audit\", C[\"hw_accent\"]), (\"Sector Imaging\", C[\"accent\"]), (\"Audit Report\", C[\"btn_info\"]), (\"Evidence Safe\", C[\"success\"])]:\n            chip = tk.Frame(chip_row, bg=color, height=20)\n            chip.pack(side=\"left\", padx=(0, 8), pady=2)\n            tk.Label(chip, text=text, font=FONTS[\"xsmall\"], fg=\"#0A0F1A\", bg=color, padx=8, pady=2).pack()\n\n        right = tk.Frame(hero, bg=C[\"panel\"])\n        right.grid(row=0, column=1, sticky=\"nsew\", padx=(10, 16), pady=16)\n        tk.Label(\n            right,\n            text=\"Recovery Flow\",\n            font=FONTS[\"subhead\"],\n            fg=C[\"accent\"],\n            bg=C[\"panel\"],\n        ).pack(anchor=\"w\")\n        tk.Label(\n            right,\n            text=\"1. Select source \u2022 2. Validate target \u2022 3. Recover or image \u2022 4. Export report\",\n            font=FONTS[\"small\"],\n            fg=C[\"text\"],\n            bg=C[\"panel\"],\n            justify=\"left\",\n            wraplength=320,\n        ).pack(anchor=\"w\", pady=(4, 10))\n        tk.Frame(right, bg=C[\"border\"], height=1).pack(fill=\"x\", pady=(0, 8))\n        tk.Label(\n            right,\n            text=\"Live status: Ready for a new evidence session.\",\n            font=FONTS[\"small\"],\n            fg=C[\"text_dim\"],\n            bg=C[\"panel\"],\n            anchor=\"w\",\n        ).pack(fill=\"x\")\n\n        safety = tk.Frame(frame, bg=C[\"card\"], highlightbackground=C[\"warning\"], highlightthickness=1)\n        safety.pack(fill=\"x\", padx=16, pady=(0, 10))\n        top_bar = tk.Frame(safety, bg=C[\"card\"])\n        top_bar.pack(fill=\"x\", padx=12, pady=(12, 6))\n        tk.Label(\n            top_bar,\n            text=\"\u26a0\ufe0f Safety Gate \u2014 Raw Operations\",\n            font=FONTS[\"subhead\"],\n            fg=C[\"warning\"],\n            bg=C[\"card\"],\n        ).pack(anchor=\"w\")\n        tk.Label(\n            safety,\n            text=\"Raw disk access, sector imaging, and partition recovery can alter evidence and metadata. Use only on authorized disks and always image first.\",\n            font=FONTS[\"small\"],\n            fg=C[\"text\"],\n            bg=C[\"card\"],\n            justify=\"left\",\n            wraplength=1100,\n        ).pack(anchor=\"w\", padx=12, pady=(0, 12))\n\n        summary = tk.Frame(frame, bg=C[\"bg\"])\n        summary.pack(fill=\"x\", padx=16, pady=(0, 8))\n        for idx in range(4):\n            summary.columnconfigure(idx, weight=1)\n\n        self._data_recovery_summary_labels = getattr(self, \"_data_recovery_summary_labels\", {})\n        for idx, (label, value, fg) in enumerate([\n            (\"Source\", \"Ready\", C[\"accent\"]),\n            (\"Recovered\", \"0 files\", C[\"accent2\"]),\n            (\"Chance\", \"Low\", C[\"warning\"]),\n            (\"Image\", \"No image yet\", C[\"hw_accent\"]),\n        ]):\n            if label not in self._data_recovery_summary_labels:\n                card = tk.Frame(summary, bg=C[\"card\"], highlightbackground=C[\"border\"], highlightthickness=1)\n                card.grid(row=0, column=idx, padx=5, pady=0, sticky=\"nsew\")\n                tk.Label(card, text=label, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=10, pady=(8, 2))\n                lbl = tk.Label(card, text=value, font=FONTS[\"heading\"], fg=fg, bg=C[\"card\"])\n                lbl.pack(anchor=\"w\", padx=10, pady=(0, 8))\n                self._data_recovery_summary_labels[label] = lbl\n            else:\n                self._data_recovery_summary_labels[label].config(text=value, fg=fg)\n\n        explain = tk.Frame(frame, bg=C[\"panel\"])\n        explain.pack(fill=\"x\", padx=16, pady=(0, 10))\n        tk.Label(explain, text=\"Quick Recovery \u2014 Fast file recovery / \u0924\u094d\u0935\u0930\u093f\u0924 \u092b\u093c\u093e\u0907\u0932 \u0930\u093f\u0915\u0935\u0930\u0940\", font=FONTS[\"small\"], fg=C[\"accent\"], bg=C[\"panel\"]).pack(anchor=\"w\", padx=10, pady=(6, 0))\n        tk.Label(explain, text=\"Deep Recovery \u2014 Signature carving and raw scan / \u0938\u093f\u0917\u094d\u0928\u0947\u091a\u0930-\u0906\u0927\u093e\u0930\u093f\u0924 \u0917\u0939\u0930\u0940 \u0916\u094b\u091c\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(anchor=\"w\", padx=10, pady=(0, 6))\n\n        notebook = ttk.Notebook(frame)\n        notebook.pack(fill=\"both\", expand=True, padx=16, pady=(0, 12))\n\n        quick_tab = tk.Frame(notebook, bg=C[\"bg\"])\n        notebook.add(quick_tab, text=\"Quick Recovery\")\n        quick_body = self._scrollable_section_body(quick_tab)\n        quick_card = tk.LabelFrame(\n            quick_body,\n            text=\"\ud83d\udcc1 Quick Recovery \u2014 Existing Files / \u092e\u094c\u091c\u0942\u0926\u093e \u092b\u093c\u093e\u0907\u0932\u094b\u0902 \u0915\u0940 \u0924\u094d\u0935\u0930\u093f\u0924 \u0930\u093f\u0915\u0935\u0930\u0940\",\n            font=FONTS[\"subhead\"],\n            fg=C[\"accent2\"],\n            bg=C[\"card\"],\n            bd=1,\n            relief=\"flat\",\n        )\n        quick_card.pack(fill=\"x\", padx=14, pady=10)\n        quick_card.columnconfigure(1, weight=1)\n\n        self._data_recovery_quick_disk_var = tk.StringVar(value=\"\")\n        self._data_recovery_filter_var = tk.StringVar(value=\"All\")\n        self._data_recovery_quick_output_var = tk.StringVar(value=os.path.join(os.path.expanduser(\"~\"), \"Desktop\", \"Godawari_DataRecovery_Quick\"))\n        self._data_recovery_quick_disk_combo = ttk.Combobox(quick_card, textvariable=self._data_recovery_quick_disk_var, values=[], width=42, state=\"readonly\")\n        self._data_recovery_quick_disk_combo.pack_forget()\n\n        quick_rows = tk.Frame(quick_card, bg=C[\"card\"])\n        quick_rows.pack(fill=\"x\", padx=10, pady=(8, 2))\n        tk.Label(quick_rows, text=\"Disk / Volume:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._data_recovery_quick_disk_combo = ttk.Combobox(quick_rows, textvariable=self._data_recovery_quick_disk_var, values=[], width=42, state=\"readonly\")\n        self._data_recovery_quick_disk_combo.pack(side=\"left\", padx=(8, 12))\n        tk.Label(quick_rows, text=\"Output Folder:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\")\n        tk.Entry(quick_rows, textvariable=self._data_recovery_quick_output_var, width=48, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).pack(side=\"left\", padx=(8, 8))\n        tk.Button(\n            quick_rows,\n            text=\"Browse\",\n            font=FONTS[\"small\"],\n            bg=C[\"panel\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=10,\n            pady=5,\n            cursor=\"hand2\",\n            command=lambda: self._data_recovery_choose_output(self._data_recovery_quick_output_var),\n        ).pack(side=\"left\")\n\n        filter_row = tk.Frame(quick_card, bg=C[\"card\"])\n        filter_row.pack(fill=\"x\", padx=10, pady=(6, 8))\n        tk.Label(filter_row, text=\"File type filter:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._data_recovery_filter_buttons = {}\n        for icon, label in [(\"\ud83d\uddbc\ufe0f\", \"Photos\"), (\"\ud83c\udfac\", \"Videos\"), (\"\ud83d\udcc4\", \"Documents\"), (\"\ud83d\udddc\ufe0f\", \"Archives\"), (\"\ud83d\udce6\", \"All\")]:\n            btn = tk.Button(\n                filter_row,\n                text=f\"{icon} {label}\",\n                font=FONTS[\"small\"],\n                bg=C[\"panel\"] if label != \"All\" else C[\"btn_chip\"],\n                fg=C[\"text\"],\n                bd=0,\n                padx=10,\n                pady=5,\n                cursor=\"hand2\",\n                command=lambda l=label: self._data_recovery_set_filter(l),\n            )\n            btn.pack(side=\"left\", padx=4)\n            self._data_recovery_filter_buttons[label] = btn\n\n        controls = tk.Frame(quick_card, bg=C[\"card\"])\n        controls.pack(fill=\"x\", padx=10, pady=(6, 8))\n        self._data_recovery_quick_pause_btn = tk.Button(\n            controls,\n            text=\"\u23f8 Pause Scan\",\n            font=FONTS[\"small\"],\n            bg=C[\"warning\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_pause_resume_scan,\n        )\n        self._data_recovery_quick_pause_btn.pack(side=\"left\", padx=(0, 8))\n        self._data_recovery_quick_start_btn = tk.Button(\n            controls,\n            text=\"\u25b6 Start Quick Recovery\",\n            font=FONTS[\"subhead\"],\n            bg=C[\"accent2\"],\n            fg=\"#0A0F1A\",\n            bd=0,\n            padx=14,\n            pady=8,\n            cursor=\"hand2\",\n            command=self._data_recovery_start_quick_recovery,\n        )\n        self._data_recovery_quick_start_btn.pack(side=\"left\", padx=4)\n        tk.Button(\n            controls,\n            text=\"\ud83d\udee0 Auto Repair\",\n            font=FONTS[\"small\"],\n            bg=C[\"btn_chip\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_run_auto_repair,\n        ).pack(side=\"left\", padx=4)\n        tk.Button(\n            controls,\n            text=\"\ud83d\udccb Export HTML Report\",\n            font=FONTS[\"small\"],\n            bg=C[\"btn_info\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_export_report,\n        ).pack(side=\"left\", padx=4)\n\n        self._data_recovery_quick_preview = ttk.Treeview(\n            quick_body,\n            columns=(\"Type\", \"Path\", \"Size\", \"Chance\"),\n            show=\"headings\",\n            height=10,\n            style=\"Custom.Treeview\",\n        )\n        for col, title, width in [(\"Type\", \"Type\", 90), (\"Path\", \"Recovered Path\", 320), (\"Size\", \"Size\", 90), (\"Chance\", \"Chance\", 90)]:\n            self._data_recovery_quick_preview.heading(col, text=title)\n            self._data_recovery_quick_preview.column(col, width=width)\n        self._data_recovery_quick_preview.pack(fill=\"both\", expand=True, padx=14, pady=(0, 10))\n\n        quick_progress = tk.LabelFrame(quick_body, text=\"\ud83d\udcc8 Quick Recovery Progress / \u0928\u093f\u0937\u094d\u0915\u094d\u0930\u093f\u092f \u0938\u094d\u0915\u0948\u0928 \u092a\u094d\u0930\u0917\u0924\u093f\", font=FONTS[\"small\"], fg=C[\"accent2\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        quick_progress.pack(fill=\"x\", padx=14, pady=(0, 10))\n        self._data_recovery_quick_status = tk.Label(quick_progress, text=\"Ready \u2014 choose a source and start the scan.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], anchor=\"w\")\n        self._data_recovery_quick_status.pack(fill=\"x\", padx=10, pady=(8, 2))\n        self._data_recovery_quick_speed = tk.Label(quick_progress, text=\"Speed: 0 MB/s | ETA: --\", font=FONTS[\"small\"], fg=C[\"accent\"], bg=C[\"card\"], anchor=\"w\")\n        self._data_recovery_quick_speed.pack(fill=\"x\", padx=10, pady=(0, 4))\n        self._data_recovery_quick_progress = ttk.Progressbar(quick_progress, maximum=100.0, mode=\"determinate\")\n        self._data_recovery_quick_progress.pack(fill=\"x\", padx=10, pady=(0, 10))\n\n        deep_tab = tk.Frame(notebook, bg=C[\"bg\"])\n        notebook.add(deep_tab, text=\"Deep Recovery\")\n        deep_body = self._scrollable_section_body(deep_tab)\n        deep_card = tk.LabelFrame(\n            deep_body,\n            text=\"\ud83e\uddec Deep Recovery (PhotoRec Style) / \u0917\u0939\u0930\u0940 \u0930\u093f\u0915\u0935\u0930\u0940\",\n            font=FONTS[\"subhead\"],\n            fg=C[\"warning\"],\n            bg=C[\"card\"],\n            bd=1,\n            relief=\"flat\",\n        )\n        deep_card.pack(fill=\"x\", padx=14, pady=10)\n\n        self._data_recovery_deep_source_var = tk.StringVar(value=\"\")\n        self._data_recovery_deep_output_var = tk.StringVar(value=os.path.join(os.path.expanduser(\"~\"), \"Desktop\", \"Godawari_DataRecovery_Deep\"))\n        self._data_recovery_deep_chunk_var = tk.StringVar(value=\"4\")\n        self._data_recovery_deep_depth_var = tk.StringVar(value=\"High\")\n        self._data_recovery_deep_source_combo = ttk.Combobox(deep_card, textvariable=self._data_recovery_deep_source_var, values=[], width=42, state=\"readonly\")\n        self._data_recovery_deep_source_combo.pack_forget()\n\n        deep_rows = tk.Frame(deep_card, bg=C[\"card\"])\n        deep_rows.pack(fill=\"x\", padx=10, pady=(8, 2))\n        tk.Label(deep_rows, text=\"Source:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._data_recovery_deep_source_combo = ttk.Combobox(deep_rows, textvariable=self._data_recovery_deep_source_var, values=[], width=42, state=\"readonly\")\n        self._data_recovery_deep_source_combo.pack(side=\"left\", padx=(8, 12))\n        tk.Label(deep_rows, text=\"Output Folder:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\")\n        tk.Entry(deep_rows, textvariable=self._data_recovery_deep_output_var, width=48, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).pack(side=\"left\", padx=(8, 8))\n        tk.Button(\n            deep_rows,\n            text=\"Browse\",\n            font=FONTS[\"small\"],\n            bg=C[\"panel\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=10,\n            pady=5,\n            cursor=\"hand2\",\n            command=lambda: self._data_recovery_choose_output(self._data_recovery_deep_output_var),\n        ).pack(side=\"left\")\n\n        filters = tk.Frame(deep_card, bg=C[\"card\"])\n        filters.pack(fill=\"x\", padx=10, pady=(6, 8))\n        tk.Label(filters, text=\"Carving targets:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._data_recovery_deep_flags = {\n            \"Photos\": tk.BooleanVar(value=True),\n            \"Videos\": tk.BooleanVar(value=True),\n            \"Documents\": tk.BooleanVar(value=True),\n            \"Archives\": tk.BooleanVar(value=True),\n        }\n        for label in (\"Photos\", \"Videos\", \"Documents\", \"Archives\"):\n            ttk.Checkbutton(filters, text=label, variable=self._data_recovery_deep_flags[label]).pack(side=\"left\", padx=6)\n\n        deep_controls = tk.Frame(deep_card, bg=C[\"card\"])\n        deep_controls.pack(fill=\"x\", padx=10, pady=(6, 8))\n        self._data_recovery_deep_start_btn = tk.Button(\n            deep_controls,\n            text=\"\ud83e\uddec Start Deep Carve\",\n            font=FONTS[\"subhead\"],\n            bg=C[\"warning\"],\n            fg=\"#0A0F1A\",\n            bd=0,\n            padx=14,\n            pady=8,\n            cursor=\"hand2\",\n            command=self._data_recovery_start_deep_recovery,\n        )\n        self._data_recovery_deep_start_btn.pack(side=\"left\", padx=(0, 8))\n        self._data_recovery_deep_pause_btn = tk.Button(\n            deep_controls,\n            text=\"\u23f8 Pause Scan\",\n            font=FONTS[\"small\"],\n            bg=C[\"btn_info\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_pause_resume_scan,\n        )\n        self._data_recovery_deep_pause_btn.pack(side=\"left\", padx=4)\n        tk.Button(\n            deep_controls,\n            text=\"\ud83e\udde9 Preview Candidate\",\n            font=FONTS[\"small\"],\n            bg=C[\"panel\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_preview_selected_candidate,\n        ).pack(side=\"left\", padx=4)\n\n        self._data_recovery_deep_preview = ttk.Treeview(\n            deep_body,\n            columns=(\"Signature\", \"Offset\", \"Size\", \"Chance\"),\n            show=\"headings\",\n            height=8,\n            style=\"Custom.Treeview\",\n        )\n        for col, title, width in [(\"Signature\", \"Signature\", 120), (\"Offset\", \"Offset\", 140), (\"Size\", \"Size\", 100), (\"Chance\", \"Chance\", 100)]:\n            self._data_recovery_deep_preview.heading(col, text=title)\n            self._data_recovery_deep_preview.column(col, width=width)\n        self._data_recovery_deep_preview.pack(fill=\"both\", expand=True, padx=14, pady=(0, 10))\n\n        deep_progress = tk.LabelFrame(deep_body, text=\"\ud83d\udcca Deep Scan Progress / \u0917\u0939\u0930\u0947 \u0938\u094d\u0915\u0948\u0928 \u0915\u0940 \u092a\u094d\u0930\u0917\u0924\u093f\", font=FONTS[\"small\"], fg=C[\"warning\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        deep_progress.pack(fill=\"x\", padx=14, pady=(0, 10))\n        self._data_recovery_deep_status = tk.Label(deep_progress, text=\"Ready \u2014 choose a source and start the scan.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], anchor=\"w\")\n        self._data_recovery_deep_status.pack(fill=\"x\", padx=10, pady=(8, 2))\n        self._data_recovery_deep_speed = tk.Label(deep_progress, text=\"Speed: 0 MB/s | ETA: --\", font=FONTS[\"small\"], fg=C[\"accent\"], bg=C[\"card\"], anchor=\"w\")\n        self._data_recovery_deep_speed.pack(fill=\"x\", padx=10, pady=(0, 4))\n        self._data_recovery_deep_progress = ttk.Progressbar(deep_progress, maximum=100.0, mode=\"determinate\")\n        self._data_recovery_deep_progress.pack(fill=\"x\", padx=10, pady=(0, 10))\n\n        part_tab = tk.Frame(notebook, bg=C[\"bg\"])\n        notebook.add(part_tab, text=\"Partition Recovery\")\n        part_body = self._scrollable_section_body(part_tab)\n        part_card = tk.LabelFrame(\n            part_body,\n            text=\"\ud83d\uddc2\ufe0f Formatted / Lost Partition Recovery / \u092b\u093c\u0949\u0930\u094d\u092e\u0947\u091f\u0947\u0921 \u092f\u093e \u0916\u094b\u0908 \u0939\u0941\u0908 partition \u0930\u093f\u0915\u0935\u0930\u0940\",\n            font=FONTS[\"subhead\"],\n            fg=C[\"accent\"],\n            bg=C[\"card\"],\n            bd=1,\n            relief=\"flat\",\n        )\n        part_card.pack(fill=\"x\", padx=14, pady=10)\n        self._data_recovery_partition_tree = ttk.Treeview(\n            part_body,\n            columns=(\"Partition\", \"Start\", \"End\", \"Type\", \"Status\"),\n            show=\"headings\",\n            height=12,\n            style=\"Custom.Treeview\",\n        )\n        for col, title in [(\"Partition\", \"Partition\"), (\"Start\", \"Start Sector\"), (\"End\", \"End Sector\"), (\"Type\", \"Type\"), (\"Status\", \"Status\")]:\n            self._data_recovery_partition_tree.heading(col, text=title)\n        self._data_recovery_partition_tree.pack(fill=\"both\", expand=True, padx=14, pady=(0, 10))\n        part_controls = tk.Frame(part_card, bg=C[\"card\"])\n        part_controls.pack(fill=\"x\", padx=10, pady=(6, 8))\n        tk.Button(\n            part_controls,\n            text=\"\ud83d\udd0e Refresh Partitions\",\n            font=FONTS[\"small\"],\n            bg=C[\"btn_info\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_refresh_partition_list,\n        ).pack(side=\"left\", padx=(0, 8))\n        tk.Button(\n            part_controls,\n            text=\"\ud83d\udee1 Recover Lost Partition\",\n            font=FONTS[\"small\"],\n            bg=C[\"accent2\"],\n            fg=\"#0A0F1A\",\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_recover_partition_table,\n        ).pack(side=\"left\", padx=4)\n        tk.Button(\n            part_controls,\n            text=\"\ud83d\udccd Verify MBR/GPT\",\n            font=FONTS[\"small\"],\n            bg=C[\"panel\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_verify_partition_table,\n        ).pack(side=\"left\", padx=4)\n\n        adv_tab = tk.Frame(notebook, bg=C[\"bg\"])\n        notebook.add(adv_tab, text=\"Advanced Tools &amp; Imaging\")\n        adv_body = self._scrollable_section_body(adv_tab)\n        adv_card = tk.LabelFrame(\n            adv_body,\n            text=\"\ud83d\udcbe DiskGenius Style Sector Utility / \u0938\u0947\u0915\u094d\u091f\u0930-\u0938\u094d\u0924\u0930\u0940\u092f \u0907\u092e\u0947\u091c\u093f\u0902\u0917 \u091f\u0942\u0932\",\n            font=FONTS[\"subhead\"],\n            fg=C[\"hw_accent\"],\n            bg=C[\"card\"],\n            bd=1,\n            relief=\"flat\",\n        )\n        adv_card.pack(fill=\"x\", padx=14, pady=10)\n\n        self._data_recovery_imaging_disk_var = tk.StringVar(value=\"\")\n        self._data_recovery_start_sector_var = tk.StringVar(value=\"0\")\n        self._data_recovery_end_sector_var = tk.StringVar(value=\"1023\")\n        self._data_recovery_img_output_var = tk.StringVar(value=os.path.join(os.path.expanduser(\"~\"), \"Desktop\", \"Godawari_DataRecovery_Image.img\"))\n        self._data_recovery_imaging_disk_combo = ttk.Combobox(adv_card, textvariable=self._data_recovery_imaging_disk_var, values=[], width=42, state=\"readonly\")\n        self._data_recovery_imaging_disk_combo.pack_forget()\n\n        imaging_rows = tk.Frame(adv_card, bg=C[\"card\"])\n        imaging_rows.pack(fill=\"x\", padx=10, pady=(8, 2))\n        tk.Label(imaging_rows, text=\"Disk:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._data_recovery_imaging_disk_combo = ttk.Combobox(imaging_rows, textvariable=self._data_recovery_imaging_disk_var, values=[], width=42, state=\"readonly\")\n        self._data_recovery_imaging_disk_combo.pack(side=\"left\", padx=(8, 12))\n        tk.Label(imaging_rows, text=\"Start Sector:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\")\n        tk.Entry(imaging_rows, textvariable=self._data_recovery_start_sector_var, width=12, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).pack(side=\"left\", padx=(8, 12))\n        tk.Label(imaging_rows, text=\"End Sector:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\")\n        tk.Entry(imaging_rows, textvariable=self._data_recovery_end_sector_var, width=12, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).pack(side=\"left\", padx=(8, 12))\n        tk.Label(imaging_rows, text=\"Output:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\")\n        tk.Entry(imaging_rows, textvariable=self._data_recovery_img_output_var, width=46, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).pack(side=\"left\", padx=(8, 8))\n        tk.Button(\n            imaging_rows,\n            text=\"Browse\",\n            font=FONTS[\"small\"],\n            bg=C[\"panel\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=10,\n            pady=5,\n            cursor=\"hand2\",\n            command=lambda: self._data_recovery_choose_output(self._data_recovery_img_output_var),\n        ).pack(side=\"left\")\n\n        adv_controls = tk.Frame(adv_card, bg=C[\"card\"])\n        adv_controls.pack(fill=\"x\", padx=10, pady=(6, 8))\n        self._data_recovery_hex_load_btn = tk.Button(\n            adv_controls,\n            text=\"\ud83d\udd0e Load Sector / Hex\",\n            font=FONTS[\"small\"],\n            bg=C[\"btn_info\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_load_sector_hex,\n        )\n        self._data_recovery_hex_load_btn.pack(side=\"left\", padx=(0, 8))\n        tk.Button(\n            adv_controls,\n            text=\"\ud83d\udcbe Create Range .img\",\n            font=FONTS[\"small\"],\n            bg=C[\"accent2\"],\n            fg=\"#0A0F1A\",\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_create_range_img,\n        ).pack(side=\"left\", padx=4)\n        tk.Button(\n            adv_controls,\n            text=\"\ud83d\udda5\ufe0f Full Disk .img\",\n            font=FONTS[\"small\"],\n            bg=C[\"warning\"],\n            fg=\"#0A0F1A\",\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_create_full_disk_img,\n        ).pack(side=\"left\", padx=4)\n        tk.Button(\n            adv_controls,\n            text=\"\ud83d\udcc2 Open Output Folder\",\n            font=FONTS[\"small\"],\n            bg=C[\"panel\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_open_last_output,\n        ).pack(side=\"left\", padx=4)\n        tk.Button(\n            adv_controls,\n            text=\"\ud83e\uddea Use in Existing Recovery\",\n            font=FONTS[\"small\"],\n            bg=C[\"hw_accent\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_route_img_to_existing_recovery,\n        ).pack(side=\"left\", padx=4)\n\n        self._data_recovery_hex_view = scrolledtext.ScrolledText(\n            adv_body,\n            font=FONTS[\"mono\"],\n            bg=C[\"bg\"],\n            fg=C[\"text\"],\n            insertbackground=C[\"text\"],\n            wrap=\"word\",\n            height=18,\n            bd=0,\n            relief=\"flat\",\n        )\n        self._data_recovery_hex_view.pack(fill=\"both\", expand=True, padx=14, pady=(0, 10))\n\n        self._data_recovery_image_chance = tk.Label(\n            adv_card,\n            text=\"Recovery Chance: Low \u2014 image not loaded yet\",\n            font=FONTS[\"small\"],\n            fg=C[\"warning\"],\n            bg=C[\"card\"],\n            anchor=\"w\",\n        )\n        self._data_recovery_image_chance.pack(fill=\"x\", padx=10, pady=(6, 0))\n        self._data_recovery_auto_repair_label = tk.Label(\n            adv_card,\n            text=\"Auto Repair: Ready for JPG / PNG / PDF / DOCX headers\",\n            font=FONTS[\"small\"],\n            fg=C[\"text_dim\"],\n            bg=C[\"card\"],\n            anchor=\"w\",\n        )\n        self._data_recovery_auto_repair_label.pack(fill=\"x\", padx=10, pady=(2, 8))\n\n        self._data_recovery_refresh_disk_sources()\n        self._data_recovery_refresh_partition_list()\n        self._data_recovery_set_filter(\"All\")\n        self._data_recovery_set_recovery_chance(\"Low\")\n        self._data_recovery_update_summary(\"Source\", \"Ready\")\n        self._data_recovery_update_summary(\"Recovered\", \"0 files\")\n        self._data_recovery_update_summary(\"Image\", \"No image yet\")\n\n        return frame\n\n    def _data_recovery_refresh_disk_sources(self):\n        try:\n            self._populate_recovery_disks()\n        except Exception:\n            pass\n\n        disk_values = list(getattr(self, \"_recovery_disk_map\", {}).keys())\n        if not disk_values:\n            disk_values = self._get_recovery_disk_values()\n\n        uniq = []\n        for src in disk_values:\n            if src not in uniq:\n                uniq.append(src)\n\n        for combo in (\n            getattr(self, \"_data_recovery_quick_disk_combo\", None),\n            getattr(self, \"_data_recovery_deep_source_combo\", None),\n            getattr(self, \"_data_recovery_imaging_disk_combo\", None),\n        ):\n            if combo is not None:\n                combo.config(values=uniq)\n\n        current = uniq[0] if uniq else \"\"\n        if current:\n            self._data_recovery_quick_disk_var.set(current)\n            self._data_recovery_deep_source_var.set(current)\n            self._data_recovery_imaging_disk_var.set(current)\n\n    def _data_recovery_set_filter(self, label):\n        self._data_recovery_filter_var.set(label)\n        self._data_recovery_quick_status.config(text=f\"Filter updated to {label}.\")\n        for name, btn in getattr(self, \"_data_recovery_filter_buttons\", {}).items():\n            bg = C[\"btn_chip\"] if name == label else C[\"panel\"]\n            try:\n                btn.config(bg=bg)\n            except Exception:\n                pass\n        if label == \"All\":\n            self._data_recovery_set_recovery_chance(\"Medium\")\n        elif label in (\"Photos\", \"Videos\"):\n            self._data_recovery_set_recovery_chance(\"High\")\n        else:\n            self._data_recovery_set_recovery_chance(\"Medium\")\n\n    def _data_recovery_update_summary(self, key, value):\n        if key in self._data_recovery_summary_labels:\n            self._data_recovery_summary_labels[key].config(text=value)\n\n    def _data_recovery_set_recovery_chance(self, level):\n        color = C[\"success\"] if level == \"High\" else C[\"warning\"] if level == \"Medium\" else C[\"error\"]\n        self._data_recovery_summary_labels[\"Chance\"].config(text=level, fg=color)\n        if hasattr(self, \"_data_recovery_image_chance\"):\n            self._data_recovery_image_chance.config(text=f\"Recovery Chance: {level}\", fg=color)\n\n    def _data_recovery_choose_output(self, var):\n        path = filedialog.asksaveasfilename(defaultextension=\".img\", filetypes=[(\"Image File\", \"*.img\"), (\"All Files\", \"*.*\")], title=\"Choose output file\")\n        if path:\n            var.set(path)\n\n    def _data_recovery_get_source_path(self, source_value):\n        source_value = (source_value or \"\").strip()\n        if not source_value:\n            return \"\"\n        if hasattr(self, \"_resolve_disk_path\"):\n            return self._resolve_disk_path(source_value)\n        return source_value.split(\" (\")[0]\n\n    def _data_recovery_refresh_partition_list(self):\n        if not hasattr(self, \"_data_recovery_partition_tree\"):\n            return\n        for iid in self._data_recovery_partition_tree.get_children():\n            self._data_recovery_partition_tree.delete(iid)\n        source = self._data_recovery_get_source_path(self._data_recovery_imaging_disk_var.get() or self._data_recovery_quick_disk_var.get())\n        if not source:\n            return\n        partitions = self._data_recovery_parse_partitions(source)\n        if not partitions:\n            self._data_recovery_partition_tree.insert(\"\", \"end\", values=(\"No partition table detected\", \"\", \"\", \"\", \"Unknown\"))\n            if hasattr(self, \"partition_tree\"):\n                self.partition_tree.delete(*self.partition_tree.get_children())\n            return\n        for part in partitions:\n            self._data_recovery_partition_tree.insert(\"\", \"end\", values=(part[\"name\"], part[\"start\"], part[\"end\"], part[\"type\"], part[\"status\"]))\n        if hasattr(self, \"partition_tree\"):\n            for iid in self.partition_tree.get_children():\n                self.partition_tree.delete(iid)\n            for part in partitions:\n                self.partition_tree.insert(\"\", \"end\", values=(part[\"name\"], part[\"start\"], part[\"end\"], part[\"type\"], part[\"status\"]))\n\n    def _data_recovery_parse_partitions(self, source_path):\n        source_path = self._data_recovery_get_source_path(source_path)\n        try:\n            first_sector = self._forensic_read_at(source_path, 0, 512)\n        except Exception:\n            return []\n        if len(first_sector) &lt; 512 or first_sector[510:512] != b\"\\x55\\xAA\":\n            return []\n        partitions = []\n        for idx in range(4):\n            entry = first_sector[446 + idx * 16:446 + (idx + 1) * 16]\n            part_type = entry[4]\n            start = int.from_bytes(entry[8:12], \"little\")\n            size = int.from_bytes(entry[12:16], \"little\")\n            if part_type and size:\n                partitions.append({\n                    \"name\": f\"Partition {idx + 1}\",\n                    \"start\": str(start),\n                    \"end\": str(start + size - 1),\n                    \"type\": f\"0x{part_type:02X}\",\n                    \"status\": \"Candidate\",\n                })\n        return partitions\n\n    def _data_recovery_read_sector_bytes(self, source_path, start_sector, end_sector):\n        try:\n            start_sector = int(start_sector)\n            end_sector = int(end_sector)\n            if end_sector &lt; start_sector:\n                start_sector, end_sector = end_sector, start_sector\n            source_path = self._data_recovery_get_source_path(source_path)\n            raw = self._forensic_read_at(source_path, start_sector * 512, (end_sector - start_sector + 1) * 512)\n            return raw\n        except Exception as exc:\n            messagebox.showerror(\"Sector Read Error\", str(exc))\n            return b\"\"\n\n    def _data_recovery_format_hex_dump(self, raw_bytes):\n        if not raw_bytes:\n            return \"No bytes available.\"\n        lines = []\n        for offset in range(0, len(raw_bytes), 16):\n            chunk = raw_bytes[offset:offset + 16]\n            hex_text = \" \".join(f\"{b:02X}\" for b in chunk)\n            ascii_text = \"\".join(chr(b) if 32 &lt;= b &lt; 127 else \".\" for b in chunk)\n            lines.append(f\"{offset:08X}  {hex_text:&lt;47}  {ascii_text}\")\n        return \"\\n\".join(lines)\n\n    def _data_recovery_load_sector_hex(self):\n        source = self._data_recovery_imaging_disk_var.get()\n        if not source:\n            messagebox.showwarning(\"No Disk Selected\", \"Select a disk or raw volume first.\")\n            return\n        try:\n            start = int(self._data_recovery_start_sector_var.get())\n            end = int(self._data_recovery_end_sector_var.get())\n        except Exception:\n            messagebox.showwarning(\"Invalid Sector Range\", \"Enter numeric start and end sectors.\")\n            return\n        sector_count = abs(end - start) + 1\n        if sector_count &gt; 4096:\n            messagebox.showwarning(\n                \"Range Too Large\",\n                \"Hex preview ek baar me max 4096 sectors (2 MB) read karega.\\n\"\n                \"Bade range ke liye 'Create Range IMG' use karein.\"\n            )\n            return\n\n        def load_hex():\n            try:\n                if hasattr(self, \"_data_recovery_hex_load_btn\"):\n                    self.after(0, lambda: self._data_recovery_hex_load_btn.config(state=\"disabled\"))\n                raw = self._data_recovery_read_sector_bytes(source, start, end)\n                formatted = self._data_recovery_format_hex_dump(raw)\n                self.after(0, lambda: self._data_recovery_hex_view.delete(\"1.0\", tk.END))\n                self.after(0, lambda: self._data_recovery_hex_view.insert(tk.END, formatted))\n                self.after(0, lambda: self._data_recovery_update_summary(\"Image\", f\"{start} -&gt; {end}\"))\n                self.after(0, lambda: self._data_recovery_set_recovery_chance(\"Medium\"))\n            finally:\n                if hasattr(self, \"_data_recovery_hex_load_btn\"):\n                    self.after(0, lambda: self._data_recovery_hex_load_btn.config(state=\"normal\"))\n\n        self._launch_job(\"data_recovery_load_hex\", load_hex)\n\n    def _data_recovery_create_sector_range_img(self, source_path, start_sector, end_sector, output_path, progress_callback=None, confirm=True):\n        if not source_path or not output_path:\n            return {\"ok\": False, \"message\": \"Source or output path missing.\"}\n        try:\n            start_sector = int(start_sector)\n            end_sector = int(end_sector)\n            if end_sector &lt; start_sector:\n                start_sector, end_sector = end_sector, start_sector\n        except Exception:\n            return {\"ok\": False, \"message\": \"Invalid sector values.\"}\n        if confirm and not messagebox.askyesno(\"Raw Imaging Confirmation\", \"This will create a raw sector image from the selected range. Continue only if you have authorization.\"):\n            return {\"ok\": False, \"message\": \"User cancelled imaging.\"}\n\n        source_path = self._data_recovery_get_source_path(source_path)\n        if _is_raw_device_path(source_path) and not self._ensure_admin_for_raw_recovery(source_path):\n            return {\"ok\": False, \"message\": \"Administrator rights required for raw imaging.\"}\n\n        output_path = os.path.abspath(output_path)\n        os.makedirs(os.path.dirname(output_path) or \".\", exist_ok=True)\n        try:\n            start_byte = start_sector * 512\n            end_byte = (end_sector + 1) * 512\n            remaining = max(0, end_byte - start_byte)\n            total_bytes = remaining\n            copied = 0\n            current = start_byte\n            file_source = source_path and os.path.exists(source_path) and not _is_raw_device_path(source_path)\n            src = open(source_path, \"rb\") if file_source else None\n            try:\n                if src:\n                    src.seek(start_byte)\n                with open(output_path, \"wb\") as dst:\n                    while remaining &gt; 0:\n                        if self._data_recovery_state.get(\"cancelled\", False):\n                            return {\"ok\": False, \"message\": \"Imaging cancelled by user.\"}\n                        while self._data_recovery_state.get(\"paused\", False):\n                            time.sleep(0.12)\n                            if self._data_recovery_state.get(\"cancelled\", False):\n                                return {\"ok\": False, \"message\": \"Imaging cancelled by user.\"}\n                        chunk_len = min(1024 * 1024, remaining)\n                        chunk = src.read(chunk_len) if src else self._forensic_read_at(source_path, current, chunk_len)\n                        if not chunk:\n                            break\n                        dst.write(chunk)\n                        current += len(chunk)\n                        remaining -= len(chunk)\n                        copied += len(chunk)\n                        if progress_callback:\n                            progress_callback(copied, total_bytes, output_path)\n            finally:\n                if src:\n                    src.close()\n            if remaining &gt; 0:\n                return {\"ok\": False, \"message\": \"Imaging stopped early: source shorter than requested range.\"}\n            self._data_recovery_state[\"last_img\"] = output_path\n            return {\"ok\": True, \"message\": f\"Image created: {output_path}\", \"path\": output_path}\n        except Exception as exc:\n            return {\"ok\": False, \"message\": str(exc)}\n\n    def _data_recovery_create_range_img(self):\n        source = self._data_recovery_imaging_disk_var.get()\n        output_path = self._data_recovery_img_output_var.get()\n        start_sector = self._data_recovery_start_sector_var.get()\n        end_sector = self._data_recovery_end_sector_var.get()\n        if not source:\n            messagebox.showwarning(\"No Disk Selected\", \"Select a disk or raw volume first.\")\n            return\n        if not output_path:\n            messagebox.showwarning(\"No Output Path\", \"Choose an output image path.\")\n            return\n        if self._data_recovery_state.get(\"running\", False):\n            messagebox.showwarning(\"Data Recovery Busy\", \"Ek recovery/imaging job already chal raha hai. Pehle usko cancel/complete hone dein.\")\n            return\n        if not messagebox.askyesno(\"Raw Imaging Confirmation\", \"This will create a raw sector image from the selected range. Continue only if you have authorization?\"):\n            return\n        self._data_recovery_state[\"running\"] = True\n        self._data_recovery_state[\"paused\"] = False\n        self._data_recovery_state[\"cancelled\"] = False\n        self._data_recovery_quick_progress[\"value\"] = 0\n        self._data_recovery_quick_status.config(text=\"Range imaging queued...\")\n        self._launch_job(\"data_recovery_range_img\", self._data_recovery_img_worker, source, start_sector, end_sector, output_path, \"Range Image\")\n\n    def _data_recovery_img_worker(self, source, start_sector, end_sector, output_path, label):\n        started = time.time()\n\n        def progress(copied, total, path):\n            pct = (copied / total * 100.0) if total else 0.0\n            elapsed = max(0.1, time.time() - started)\n            speed = copied / elapsed\n            remaining = max(0, total - copied)\n            eta = int(remaining / speed) if speed &gt; 0 else 0\n            msg = (\n                f\"{label}: {pct:.1f}% | {self._fmt_size(copied)} / {self._fmt_size(total)} | \"\n                f\"Elapsed {self._format_seconds(elapsed)} | Left {self._format_seconds(eta)}\"\n            )\n            self.after(0, lambda m=msg, p=pct: (\n                self._data_recovery_quick_progress.config(value=p),\n                self._data_recovery_deep_progress.config(value=p),\n                self._data_recovery_quick_status.config(text=m),\n                self._data_recovery_deep_status.config(text=m),\n                self._data_recovery_quick_speed.config(text=f\"Speed: {self._fmt_size(speed)}/s | ETA: {self._format_seconds(eta)}\"),\n                self._data_recovery_deep_speed.config(text=f\"Speed: {self._fmt_size(speed)}/s | ETA: {self._format_seconds(eta)}\"),\n            ))\n\n        result = self._data_recovery_create_sector_range_img(\n            source, start_sector, end_sector, output_path,\n            progress_callback=progress,\n            confirm=False,\n        )\n        if result[\"ok\"]:\n            self.after(0, lambda: (\n                self._data_recovery_update_summary(\"Image\", os.path.basename(result[\"path\"])),\n                self._data_recovery_quick_progress.config(value=100),\n                self._data_recovery_deep_progress.config(value=100),\n                self._data_recovery_quick_status.config(text=result[\"message\"]),\n                self._data_recovery_deep_status.config(text=result[\"message\"]),\n                messagebox.showinfo(f\"{label} Created\", result[\"message\"]),\n            ))\n        else:\n            self.after(0, lambda: (\n                self._data_recovery_quick_status.config(text=result[\"message\"]),\n                self._data_recovery_deep_status.config(text=result[\"message\"]),\n                messagebox.showerror(f\"{label} Failed\", result[\"message\"]),\n            ))\n        self._data_recovery_state[\"running\"] = False\n\n    def _data_recovery_create_full_disk_img(self):\n        source = self._data_recovery_imaging_disk_var.get() or self._data_recovery_quick_disk_var.get()\n        output_path = self._data_recovery_img_output_var.get()\n        if not source:\n            messagebox.showwarning(\"No Disk Selected\", \"Select a disk or raw volume first.\")\n            return\n        if not output_path:\n            messagebox.showwarning(\"No Output Path\", \"Choose an output image path.\")\n            return\n        if self._data_recovery_state.get(\"running\", False):\n            messagebox.showwarning(\"Data Recovery Busy\", \"Ek recovery/imaging job already chal raha hai. Pehle usko cancel/complete hone dein.\")\n            return\n        try:\n            source_path = self._data_recovery_get_source_path(source)\n            size = _disk_source_size(source_path)\n        except Exception:\n            size = None\n        if not size:\n            messagebox.showwarning(\"Size Error\", \"Unable to determine disk size.\")\n            return\n        if not messagebox.askyesno(\"Full Disk Imaging\", f\"Create a full raw image of {source}? This is a raw disk operation and should only be done with authorization.\"):\n            return\n        self._data_recovery_state[\"running\"] = True\n        self._data_recovery_state[\"paused\"] = False\n        self._data_recovery_state[\"cancelled\"] = False\n        self._data_recovery_quick_progress[\"value\"] = 0\n        self._data_recovery_quick_status.config(text=\"Full disk imaging queued...\")\n        self._launch_job(\"data_recovery_full_img\", self._data_recovery_img_worker, source, 0, max(0, size // 512 - 1), output_path, \"Full Disk Image\")\n\n    def _data_recovery_open_last_output(self):\n        path = self._data_recovery_state.get(\"last_img\", \"\")\n        if not path or not os.path.exists(path):\n            messagebox.showwarning(\"No Image\", \"Create or load an image first.\")\n            return\n        try:\n            subprocess.Popen([\"explorer\", os.path.dirname(path)])\n        except Exception as exc:\n            messagebox.showerror(\"Open Failed\", str(exc))\n\n    def _data_recovery_route_img_to_existing_recovery(self):\n        if not self._data_recovery_state.get(\"last_img\"):\n            messagebox.showwarning(\"No Image\", \"Create or load a .img first.\")\n            return\n        img_path = self._data_recovery_state.get(\"last_img\", \"\")\n        routed = []\n        for attr in (\"raw_disk_var\", \"deep_recovery_source_var\", \"photorec_source_var\", \"mft_source_var\"):\n            var = getattr(self, attr, None)\n            if var is not None:\n                try:\n                    var.set(img_path)\n                    routed.append(attr)\n                except Exception:\n                    pass\n        messagebox.showinfo(\n            \"Use in Existing Recovery\",\n            f\"Image route ho gayi:\\n{img_path}\\n\\nUpdated fields: {', '.join(routed) if routed else 'HDD/File Recovery section open hote hi source set karein.'}\"\n        )\n        self._show_section(\"hdd_repair\")\n\n    def _data_recovery_signature_map(self, kind):\n        return {\n            \"Photos\": [b\"\\xff\\xd8\\xff\", b\"\\x89PNG\\r\\n\\x1a\\n\", b\"GIF87a\", b\"GIF89a\"],\n            \"Videos\": [b\"RIFF\", b\"\\x00\\x00\\x00\\x18ftyp\", b\"\\x1A\\x45\\xDF\\xA3\"],\n            \"Documents\": [b\"%PDF-\", b\"PK\\x03\\x04\", b\"Microsoft Word\", b\"\\xd0\\xcf\\x11\\xe0\\xa1\\xb1\\x1a\\xe1\"],\n            \"Archives\": [b\"PK\\x03\\x04\", b\"Rar!\", b\"7z\\xBC\\xAF\\x27\\x1C\", b\"\\x42\\x5A\\x68\"],\n        }.get(kind, [])\n\n    def _data_recovery_find_signature_offsets(self, data, kind):\n        offsets = []\n        for signature in self._data_recovery_signature_map(kind):\n            start = 0\n            while True:\n                idx = data.find(signature, start)\n                if idx == -1:\n                    break\n                offsets.append((idx, signature))\n                start = idx + 1\n        return offsets\n\n    def _data_recovery_carve_candidate(self, source_path, offset, signature, kind):\n        try:\n            with open(self._data_recovery_get_source_path(source_path), \"rb\") as handle:\n                handle.seek(max(0, offset))\n                payload = handle.read(512 * 1024)\n        except Exception:\n            return None\n        if not payload:\n            return None\n        ext = \".bin\"\n        if kind == \"Photos\":\n            ext = \".jpg\" if signature == b\"\\xff\\xd8\\xff\" else \".png\" if signature == b\"\\x89PNG\\r\\n\\x1a\\n\" else \".gif\"\n        elif kind == \"Videos\":\n            ext = \".mp4\" if signature == b\"\\x00\\x00\\x00\\x18ftyp\" else \".avi\" if signature == b\"RIFF\" else \".mkv\"\n        elif kind == \"Documents\":\n            if signature == b\"%PDF-\":\n                ext = \".pdf\"\n            elif signature == b\"PK\\x03\\x04\":\n                ext = \".docx\"\n            elif signature == b\"\\xd0\\xcf\\x11\\xe0\\xa1\\xb1\\x1a\\xe1\":\n                ext = \".doc\"\n        elif kind == \"Archives\":\n            if signature == b\"PK\\x03\\x04\":\n                ext = \".zip\"\n            elif signature == b\"Rar!\":\n                ext = \".rar\"\n            elif signature == b\"7z\\xBC\\xAF\\x27\\x1C\":\n                ext = \".7z\"\n            elif signature == b\"\\x42\\x5A\\x68\":\n                ext = \".bz2\"\n        return payload, ext\n\n    def _data_recovery_add_preview_row(self, mode, kind, offset, size, path):\n        tree = self._data_recovery_quick_preview if mode == \"quick\" else self._data_recovery_deep_preview\n        tree.insert(\"\", \"end\", values=(kind, f\"0x{offset:X}\", self._fmt_size(size), \"Medium\"))\n        self._data_recovery_last_preview_path = path\n        self._data_recovery_state.setdefault(\"preview\", []).append({\n            \"kind\": kind,\n            \"offset\": offset,\n            \"size\": size,\n            \"path\": path,\n        })\n        # Update recovered counters and UI summary\n        recovered_count = len(tree.get_children())\n        self._data_recovery_update_summary(\"Recovered\", f\"{recovered_count} files\")\n        if mode == \"deep\":\n            # maintain a numeric recovered counter for deep scans for progress reporting\n            try:\n                self._data_recovery_state[\"recovered\"] = int(self._data_recovery_state.get(\"recovered\", 0)) + 1\n            except Exception:\n                self._data_recovery_state[\"recovered\"] = recovered_count\n\n    def _data_recovery_preview_selected_candidate(self):\n        path = getattr(self, \"_data_recovery_last_preview_path\", \"\")\n        if not path or not os.path.exists(path):\n            messagebox.showwarning(\"Preview\", \"Select a recovered candidate first.\")\n            return\n        try:\n            subprocess.Popen([\"explorer\", path])\n        except Exception as exc:\n            messagebox.showerror(\"Preview Error\", str(exc))\n\n    def _data_recovery_run_auto_repair(self):\n        path = getattr(self, \"_data_recovery_last_preview_path\", \"\")\n        if not path or not os.path.exists(path):\n            messagebox.showwarning(\"No Candidate\", \"Run a recovery scan first to create a candidate.\")\n            return\n        repaired = self._data_recovery_auto_repair_file(path)\n        if repaired:\n            self._data_recovery_auto_repair_label.config(text=f\"Auto Repair: repaired -&gt; {os.path.basename(repaired)}\")\n            messagebox.showinfo(\"Auto Repair\", f\"Repair complete:\\n{repaired}\")\n        else:\n            messagebox.showwarning(\"Auto Repair\", \"No repair rule matched the recovered file.\")\n\n    def _data_recovery_auto_repair_file(self, path):\n        try:\n            data = Path(path).read_bytes()\n        except Exception:\n            return None\n        ext = Path(path).suffix.lower()\n        if ext == \".jpg\" and not data.endswith(b\"\\xff\\xd9\"):\n            data += b\"\\xff\\xd9\"\n        elif ext == \".png\" and b\"IEND\" not in data:\n            data += b\"\\x00\\x00\\x00\\x00IEND\\xaeB`\\x82\"\n        elif ext == \".pdf\" and b\"%%EOF\" not in data:\n            data += b\"\\n%%EOF\\n\"\n        elif ext == \".zip\" and not data.endswith(b\"PK\\x05\\x06\"):\n            data += b\"PK\\x05\\x06\\x00\\x00\\x00\\x00\"\n        else:\n            return None\n        repaired_path = str(Path(path).with_name(Path(path).stem + \"_repaired\" + ext))\n        Path(repaired_path).write_bytes(data)\n        return repaired_path\n\n    def _data_recovery_pause_resume_scan(self):\n        state = self._data_recovery_state\n        state[\"paused\"] = not state.get(\"paused\", False)\n        label = \"\u25b6 Resume Scan\" if state[\"paused\"] else \"\u23f8 Pause Scan\"\n        if hasattr(self, \"_data_recovery_quick_pause_btn\"):\n            self._data_recovery_quick_pause_btn.config(text=label)\n        if hasattr(self, \"_data_recovery_deep_pause_btn\"):\n            self._data_recovery_deep_pause_btn.config(text=label)\n        self._data_recovery_quick_status.config(text=\"Scan paused.\" if state[\"paused\"] else \"Scan resumed.\")\n        self._data_recovery_deep_status.config(text=\"Scan paused.\" if state[\"paused\"] else \"Scan resumed.\")\n\n    def _data_recovery_run_quick_scan_worker(self, source_path, output_folder, filter_label):\n        try:\n            source_path = self._data_recovery_get_source_path(source_path)\n            if not source_path or not os.path.exists(source_path):\n                raise RuntimeError(\"Selected quick recovery source is missing.\")\n            if _is_raw_device_path(source_path):\n                raise PermissionError(\"Quick Recovery works on mounted volumes. Use Deep Recovery for raw disk sources.\")\n\n            allowed = None\n            if filter_label == \"Photos\":\n                allowed = {\"jpg\", \"jpeg\", \"png\", \"gif\", \"bmp\", \"tif\", \"tiff\"}\n            elif filter_label == \"Videos\":\n                allowed = {\"mp4\", \"mov\", \"mkv\", \"avi\", \"wmv\", \"flv\", \"mpeg\", \"mpg\"}\n            elif filter_label == \"Documents\":\n                allowed = {\"pdf\", \"doc\", \"docx\", \"xls\", \"xlsx\", \"ppt\", \"pptx\", \"txt\", \"rtf\", \"csv\", \"json\"}\n            elif filter_label == \"Archives\":\n                allowed = {\"zip\", \"7z\", \"rar\", \"tar\", \"gz\", \"bz2\", \"xz\"}\n\n            start = time.time()\n            processed = 0\n            scanned = 0\n            copied = 0\n            total_candidates = 0\n            last_ui = 0\n            skip_dirs = {\"$recycle.bin\", \"system volume information\", \"windows\", \"program files\", \"program files (x86)\"}\n            for root, dirs, files in os.walk(source_path):\n                if self._data_recovery_state.get(\"cancelled\", False):\n                    return\n                while self._data_recovery_state.get(\"paused\", False):\n                    time.sleep(0.12)\n                    if self._data_recovery_state.get(\"cancelled\", False):\n                        return\n                dirs[:] = [\n                    d for d in dirs\n                    if not d.startswith(\".\") and d.lower() not in skip_dirs\n                    and not os.path.islink(os.path.join(root, d))\n                ]\n                total_candidates += len(files)\n                for name in files:\n                    if self._data_recovery_state.get(\"cancelled\", False):\n                        return\n                    while self._data_recovery_state.get(\"paused\", False):\n                        time.sleep(0.12)\n                        if self._data_recovery_state.get(\"cancelled\", False):\n                            return\n                    src_path = os.path.join(root, name)\n                    scanned += 1\n                    try:\n                        size_bytes = os.path.getsize(src_path)\n                    except Exception:\n                        continue\n                    ext = os.path.splitext(name)[1].lstrip(\".\").lower()\n                    if allowed is not None and ext not in allowed:\n                        now = time.time()\n                        if now - last_ui &gt;= 1.0:\n                            elapsed = max(0.1, now - start)\n                            speed = (processed / (1024 * 1024)) / elapsed\n                            pct = min(99.0, (scanned / max(1, total_candidates)) * 100.0)\n                            self.after(0, lambda p=pct, s=speed, r=copied: self._data_recovery_update_scan_ui(\"quick\", p, r, s, \"--\"))\n                            last_ui = now\n                        continue\n                    rel_path = os.path.relpath(src_path, source_path)\n                    out_path = os.path.join(output_folder, rel_path)\n                    os.makedirs(os.path.dirname(out_path), exist_ok=True)\n                    if not os.path.exists(out_path):\n                        with open(src_path, \"rb\") as src, open(out_path, \"wb\") as dst:\n                            while True:\n                                if self._data_recovery_state.get(\"cancelled\", False):\n                                    return\n                                while self._data_recovery_state.get(\"paused\", False):\n                                    time.sleep(0.12)\n                                    if self._data_recovery_state.get(\"cancelled\", False):\n                                        return\n                                chunk = src.read(1024 * 1024)\n                                if not chunk:\n                                    break\n                                dst.write(chunk)\n                                processed += len(chunk)\n                                now = time.time()\n                                if now - last_ui &gt;= 1.0:\n                                    elapsed = max(0.1, now - start)\n                                    speed = (processed / (1024 * 1024)) / elapsed\n                                    pct = min(99.0, (scanned / max(1, total_candidates)) * 100.0)\n                                    self.after(0, lambda p=pct, s=speed, r=copied: self._data_recovery_update_scan_ui(\"quick\", p, r, s, \"--\"))\n                                    last_ui = now\n                        try:\n                            shutil.copystat(src_path, out_path)\n                        except Exception:\n                            pass\n                    else:\n                        processed += size_bytes\n                    copied += 1\n                    self.after(0, lambda _kind=ext.upper() or \"FILE\", _offset=0, _size=size_bytes, _path=out_path: self._data_recovery_add_preview_row(\"quick\", _kind, _offset, _size, _path))\n                    if copied % 10 == 0:\n                        elapsed = max(0.1, time.time() - start)\n                        speed = (processed / (1024 * 1024)) / elapsed\n                        file_rate = copied / elapsed\n                        remaining = max(0, total_candidates - copied)\n                        eta = \"--\" if file_rate &lt;= 0 else f\"{max(0, int(remaining / file_rate))} s\"\n                        pct = min(100.0, (copied / max(1, total_candidates)) * 100.0)\n                        self.after(0, lambda p=pct, s=speed, e=eta, r=copied: self._data_recovery_update_scan_ui(\"quick\", p, r, s, e))\n            self.after(0, lambda c=copied: self._data_recovery_finish_scan(\"quick\", c))\n        except Exception as exc:\n            self.after(0, lambda e=exc: messagebox.showerror(\"Quick Recovery Error\", str(e)))\n\n    def _data_recovery_start_quick_recovery(self):\n        source = self._data_recovery_get_source_path(self._data_recovery_quick_disk_var.get())\n        if not source:\n            messagebox.showwarning(\"No Source\", \"Select a disk or volume first.\")\n            return\n        if not os.path.exists(source):\n            messagebox.showwarning(\"No Source\", \"The selected source path does not exist.\")\n            return\n        if _is_raw_device_path(source):\n            messagebox.showwarning(\"Quick Recovery\", \"Quick Recovery works on mounted volumes. Use Deep Recovery for raw disk sources.\")\n            return\n        if self._data_recovery_state.get(\"running\", False):\n            messagebox.showwarning(\"Data Recovery Busy\", \"Ek recovery/imaging job already chal raha hai. Pehle usko cancel/complete hone dein.\")\n            return\n        if not messagebox.askyesno(\"Quick Recovery Warning\", \"Quick recovery will copy matching files to the selected destination. Continue only on an authorized target.\"):\n            return\n        output_folder = self._data_recovery_quick_output_var.get()\n        os.makedirs(output_folder, exist_ok=True)\n        self._data_recovery_state[\"running\"] = True\n        self._data_recovery_state[\"paused\"] = False\n        self._data_recovery_state[\"cancelled\"] = False\n        self._data_recovery_quick_preview.delete(*self._data_recovery_quick_preview.get_children())\n        self._data_recovery_quick_status.config(text=\"Quick recovery started.\")\n        self._data_recovery_quick_progress.config(value=0)\n        self._data_recovery_quick_speed.config(text=\"Speed: 0 MB/s | ETA: --\")\n        self._data_recovery_update_summary(\"Source\", source)\n        self._data_recovery_update_summary(\"Recovered\", \"0 files\")\n        if hasattr(self, \"_data_recovery_quick_start_btn\"):\n            try:\n                self._data_recovery_quick_start_btn.config(state=\"disabled\")\n            except Exception:\n                pass\n        self._launch_job(\"data_recovery_quick_scan\", self._data_recovery_run_quick_scan_worker, source, output_folder, self._data_recovery_filter_var.get())\n\n    def _data_recovery_run_deep_scan_worker(self, source_path, output_folder, filters):\n        try:\n            source_path = self._data_recovery_get_source_path(source_path)\n            if not source_path:\n                raise RuntimeError(\"Deep recovery source missing.\")\n            if _is_raw_device_path(source_path) and not self._ensure_admin_for_raw_recovery(source_path):\n                return\n\n            recovered = 0\n            self._data_recovery_state[\"recovered\"] = 0\n\n            def progress_cb(message):\n                text = str(message or \"\")[:180]\n                pct = 0\n                try:\n                    m = re.search(r\"(\\d{1,3})%\", text)\n                    if m:\n                        pct = int(m.group(1))\n                except Exception:\n                    pct = 0\n                self.after(0, lambda: self._data_recovery_update_scan_ui(\"deep\", pct, recovered, 0.0, \"--\"))\n                self.after(0, lambda: self._data_recovery_deep_status.config(text=text))\n\n            result = multi_pass_recovery(source_path, output_folder, progress_callback=progress_cb)\n            recovered = 0\n            for entry in result.get(\"files\", []):\n                if self._data_recovery_state.get(\"cancelled\", False):\n                    return\n                path = entry.get(\"path\")\n                if not path or not os.path.exists(path):\n                    continue\n                size = os.path.getsize(path)\n                kind = entry.get(\"file_type\") or os.path.splitext(path)[1].lstrip(\".\").upper() or \"BIN\"\n                offset = entry.get(\"offset\", 0)\n                recovered += 1\n                self.after(0, lambda _kind=kind, _offset=offset, _size=size, _path=path: self._data_recovery_add_preview_row(\"deep\", _kind, _offset, _size, _path))\n            self.after(0, lambda c=recovered: self._data_recovery_finish_scan(\"deep\", c))\n        except Exception as exc:\n            self.after(0, lambda e=exc: messagebox.showerror(\"Deep Scan Error\", str(e)))\n\n    def _data_recovery_start_deep_recovery(self):\n        source = self._data_recovery_get_source_path(self._data_recovery_deep_source_var.get())\n        if not source:\n            messagebox.showwarning(\"No Source\", \"Select a disk or volume first.\")\n            return\n        if not os.path.exists(source) and not _is_raw_device_path(source):\n            messagebox.showwarning(\"No Source\", \"The selected source path does not exist.\")\n            return\n        if _is_raw_device_path(source) and not self._ensure_admin_for_raw_recovery(source):\n            return\n        if self._data_recovery_state.get(\"running\", False):\n            messagebox.showwarning(\"Data Recovery Busy\", \"Ek recovery/imaging job already chal raha hai. Pehle usko cancel/complete hone dein.\")\n            return\n        filters = [kind for kind, var in self._data_recovery_deep_flags.items() if var.get()]\n        output_folder = self._data_recovery_deep_output_var.get()\n        os.makedirs(output_folder, exist_ok=True)\n        self._data_recovery_state[\"running\"] = True\n        self._data_recovery_state[\"paused\"] = False\n        self._data_recovery_state[\"cancelled\"] = False\n        self._data_recovery_deep_preview.delete(*self._data_recovery_deep_preview.get_children())\n        self._data_recovery_deep_status.config(text=\"Deep carve started.\")\n        self._data_recovery_deep_progress.config(value=0)\n        self._data_recovery_deep_speed.config(text=\"Speed: 0 MB/s | ETA: --\")\n        self._data_recovery_update_summary(\"Source\", source)\n        self._data_recovery_update_summary(\"Recovered\", \"0 files\")\n        if hasattr(self, \"_data_recovery_deep_start_btn\"):\n            try:\n                self._data_recovery_deep_start_btn.config(state=\"disabled\")\n            except Exception:\n                pass\n        self._launch_job(\"data_recovery_deep_scan\", self._data_recovery_run_deep_scan_worker, source, output_folder, filters)\n\n    def _data_recovery_update_scan_ui(self, mode, pct, found, speed, eta):\n        if mode == \"quick\":\n            self._data_recovery_quick_progress.config(value=max(0, min(100.0, pct)))\n            self._data_recovery_quick_status.config(text=f\"Recovered {found} candidates.\")\n            self._data_recovery_quick_speed.config(text=f\"Speed: {speed:.2f} MB/s | ETA: {eta}\")\n        else:\n            self._data_recovery_deep_progress.config(value=max(0, min(100.0, pct)))\n            self._data_recovery_deep_status.config(text=f\"Recovered {found} candidates.\")\n            self._data_recovery_deep_speed.config(text=f\"Speed: {speed:.2f} MB/s | ETA: {eta}\")\n        self._data_recovery_update_summary(\"Recovered\", f\"{found} files\")\n\n    def _data_recovery_finish_scan(self, mode, found):\n        self._data_recovery_state[\"running\"] = False\n        if mode == \"quick\":\n            self._data_recovery_quick_status.config(text=f\"Quick scan complete. {found} candidate(s) recovered.\")\n            self._data_recovery_quick_progress.config(value=100.0 if found &gt;= 1 else 0)\n            if hasattr(self, \"_data_recovery_quick_start_btn\"):\n                try:\n                    self._data_recovery_quick_start_btn.config(state=\"normal\")\n                except Exception:\n                    pass\n        else:\n            self._data_recovery_deep_status.config(text=f\"Deep carve complete. {found} candidate(s) recovered.\")\n            self._data_recovery_deep_progress.config(value=100.0 if found &gt;= 1 else 0)\n            if hasattr(self, \"_data_recovery_deep_start_btn\"):\n                try:\n                    self._data_recovery_deep_start_btn.config(state=\"normal\")\n                except Exception:\n                    pass\n        self._data_recovery_set_recovery_chance(\"High\" if found &gt;= 1 else \"Low\")\n        self._data_recovery_generate_report_html()\n\n    def _data_recovery_recover_partition_table(self):\n        source = self._data_recovery_imaging_disk_var.get() or self._data_recovery_quick_disk_var.get()\n        if not source:\n            messagebox.showwarning(\"No Disk\", \"Select a disk or raw volume first.\")\n            return\n        if not messagebox.askyesno(\"Partition Recovery Warning\", \"Recovering partition metadata is a forensic operation. Continue only if authorized and an image exists.\"):\n            return\n        partitions = self._data_recovery_parse_partitions(self._data_recovery_get_source_path(source))\n        if not partitions:\n            messagebox.showinfo(\"Partition Recovery\", \"No partition candidates detected.\")\n            return\n        self._data_recovery_refresh_partition_list()\n        messagebox.showinfo(\"Partition Recovery\", f\"Recovered {len(partitions)} partition candidate(s).\")\n\n    def _data_recovery_verify_partition_table(self):\n        source = self._data_recovery_get_source_path(self._data_recovery_imaging_disk_var.get() or self._data_recovery_quick_disk_var.get())\n        if not source:\n            messagebox.showwarning(\"No Disk\", \"Select a disk or raw volume first.\")\n            return\n        partitions = self._data_recovery_parse_partitions(source)\n        self._data_recovery_refresh_partition_list()\n        if partitions:\n            messagebox.showinfo(\"Partition Verification\", f\"Partition table appears present: {len(partitions)} candidate entry/entries found.\")\n        else:\n            messagebox.showwarning(\"Partition Verification\", \"No valid MBR signature found.\")\n\n    def _data_recovery_export_report(self):\n        report_path = os.path.join(os.path.expanduser(\"~\"), \"Desktop\", \"Godawari_DataRecovery_Report.html\")\n        try:\n            self._data_recovery_generate_report_html(report_path)\n            self._data_recovery_state[\"last_report\"] = report_path\n            messagebox.showinfo(\"Report Saved\", f\"HTML report saved to:\\n{report_path}\")\n        except Exception as exc:\n            messagebox.showerror(\"Report Error\", str(exc))\n\n    def _data_recovery_generate_report_html(self, output_path=None):\n        output_path = output_path or os.path.join(os.path.expanduser(\"~\"), \"Desktop\", \"Godawari_DataRecovery_Report.html\")\n        os.makedirs(os.path.dirname(output_path), exist_ok=True)\n        preview = self._data_recovery_state.get(\"preview\", [])\n        total = len(preview)\n        pie = f\"conic-gradient({C['accent']} 0% 45%, {C['accent2']} 45% 75%, {C['warning']} 75% 92%, {C['hw_accent']} 92% 100%)\"\n        html_doc = f\"\"\"\n\n\n\n\nGodawari Data Recovery Report\n\nbody {{ font-family: Segoe UI, Arial, sans-serif; background:#0A0F1A; color:#F0F4FA; margin:0; padding:20px; }}\nh1 {{ color:#FFB347; }}\n.card {{ background:#121826; border:1px solid #2A3A5A; border-radius:12px; padding:16px; margin-bottom:16px; }}\n.summary {{ display:flex; gap:16px; flex-wrap:wrap; }}\n.metric {{ background:#182032; border-radius:12px; padding:14px 18px; min-width:160px; }}\n.metric strong {{ display:block; font-size:20px; margin-top:6px; }}\n.chart {{ width:240px; height:240px; border-radius:50%; background:{pie}; }}\ntable {{ width:100%; border-collapse:collapse; margin-top:10px; }}\nth, td {{ border-bottom:1px solid #2A3A5A; padding:8px; text-align:left; }}\nth {{ color:#FFB347; }}\n\n\n\n\n\n  \nGodawari Data Recovery Report\n  \nGenerated on {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}.\n\n\n\n  \nRecovered Candidates{total}\n  \nRecovery ChanceHigh\n  \nLast Image{os.path.basename(self._data_recovery_state.get('last_img', 'none'))}\n\n\n\nRecovery Distribution\n\n\n\nCandidate Table\nTypeOffsetSizePath\n\"\"\"\n        for item in preview:\n            html_doc += f\"{html.escape(str(item.get('kind', '')))}{item.get('offset', 0)}{self._fmt_size(item.get('size', 0))}{html.escape(str(item.get('path', '')))}\"\n        html_doc += \"\"\n        Path(output_path).write_text(html_doc, encoding=\"utf-8\")\n        self._data_recovery_state[\"last_report\"] = output_path\n        return output_path\n\n    def _build_printer_driver_merged(self, parent):\n        return self._build_tabbed_merger(parent, [\n            (\"\ud83d\udda8  Printer Fixer + Sharing\", \"_build_printer\"),\n            (\"\ud83d\udce6  Driver Checker\", \"_build_driver\"),\n        ])\n\n    def _build_uninstall_backup_merged(self, parent):\n        return self._build_tabbed_merger(parent, [\n            (\"\ud83d\uddd1  Batch Uninstall\", \"_build_uninstaller\"),\n            (\"\ud83d\udcbe  Backup / Restore\", \"_build_backup\"),\n        ])\n\n    def _build_realtime_security(self, parent):\n        return self._build_tabbed_merger(parent, [\n            (\"Security Audit\", \"_build_password_audit\"),\n            (\"Process Scanner\", \"_build_suspicion_scanner\"),\n        ])\n\n    def _build_dup_report_merged(self, parent):\n        return self._build_tabbed_merger(parent, [\n            (\"\ud83d\udd0d  Duplicate Finder\", \"_build_dupfinder\"),\n            (\"\ud83d\udcca  Export Report\", \"_build_report\"),\n        ])\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  END MERGED SECTION BUILDERS\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _build_statusbar(self):\n        sb = tk.Frame(self, bg=C[\"panel\"], height=28)\n        sb.pack(side=\"bottom\", fill=\"x\")\n        tk.Frame(sb, bg=C[\"accent\"], height=1).pack(side=\"top\", fill=\"x\")\n        self.status_lbl = tk.Label(sb, text=\"\u25cf Ready\", font=FONTS[\"small\"], fg=C[\"accent\"], bg=C[\"panel\"])\n        self.status_lbl.pack(side=\"left\", padx=12)\n        self.cpu_lbl = tk.Label(sb, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"])\n        self.ram_lbl = tk.Label(sb, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"])\n        self.disk_lbl = tk.Label(sb, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"])\n        self.security_lbl = tk.Label(sb, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"])\n        self.task_lbl = tk.Label(sb, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"])\n        self.task_lbl.pack(side=\"right\", padx=12)\n        self.security_lbl.pack(side=\"right\", padx=12)\n        self.disk_lbl.pack(side=\"right\", padx=12)\n        self.ram_lbl.pack(side=\"right\", padx=4)\n        self.cpu_lbl.pack(side=\"right\", padx=4)\n        self._update_statusbar()\n\n    def _update_statusbar(self):\n        try:\n            cpu = psutil.cpu_percent(interval=None)\n            ram = psutil.virtual_memory().percent\n            disk = psutil.disk_usage(\"C:\\\\\").percent\n            health = self._calculate_global_health()\n            security_status = \"Secure\" if health[\"per_category\"].get(\"security\", 100) &gt;= 80 else \"Alert\"\n            active_tasks = len([t for t in self._task_manager.values() if t.get(\"status\") == \"running\"])\n            self.cpu_lbl.config(text=f\"CPU: {cpu:.1f}%\", fg=C[\"error\"] if cpu &gt; 80 else C[\"text_dim\"])\n            self.ram_lbl.config(text=f\"RAM: {ram:.1f}%\", fg=C[\"error\"] if ram &gt; 85 else C[\"text_dim\"])\n            self.disk_lbl.config(text=f\"Disk: {disk:.1f}%\", fg=C[\"warning\"] if disk &gt; 85 else C[\"text_dim\"])\n            self.security_lbl.config(text=f\"Security: {security_status}\", fg=C[\"success\"] if security_status == \"Secure\" else C[\"error\"])\n            self.task_lbl.config(text=f\"Active Tasks: {active_tasks}\", fg=C[\"accent\"] if active_tasks else C[\"text_dim\"])\n        except Exception:\n            pass\n        self.after(2000, self._update_statusbar)\n\n    def _build_footer(self):\n        footer = tk.Frame(self, bg=C[\"header_bg\"], height=24)\n        footer.pack(side=\"bottom\", fill=\"x\")\n        tk.Label(footer, text=\"\u00a9 2025 Godawari Computers | v11.0 Safety &amp; Recovery | Developer: Shravan Shrimali\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"header_bg\"]).pack(pady=3)\n\n    # ---------- CORE HELPERS ----------\n    def _set_status(self, msg, color=None):\n        self.status_lbl.config(text=f\"\u25cf {msg}\", fg=color or C[\"accent\"])\n\n    def _log(self, msg, level=\"INFO\", path=None, size=None):\n        ts = datetime.datetime.now().strftime(\"%H:%M:%S\")\n        colors = {\"INFO\": C[\"text\"], \"OK\": C[\"success\"], \"WARN\": C[\"warning\"], \"ERR\": C[\"error\"], \"CRITICAL\": C[\"error\"]}\n        color = colors.get(level, C[\"text\"])\n        if path:\n            msg += f\"\\n   \ud83d\udccd Path: {path}\"\n        if size:\n            msg += f\"\\n   \ud83d\udce6 Size: {size}\"\n        line = self._fix_text(f\"[{ts}] [{level:4s}] {msg}\")\n        self.log_lines.append((line, color))\n        if hasattr(self, \"log_text\"):\n            self.log_text.config(state=\"normal\")\n            self.log_text.insert(\"end\", line + \"\\n\", f\"lvl_{level}\")\n            self.log_text.tag_config(f\"lvl_{level}\", foreground=color)\n            self.log_text.see(\"end\")\n            self.log_text.config(state=\"disabled\")\n        try:\n            self._write_enterprise_log(self._enterprise_log_file, line, level)\n            if level in (\"ERR\", \"CRITICAL\"):\n                self._write_enterprise_log(self._enterprise_error_log, line, level)\n        except Exception:\n            pass\n        # Structured logging to runtime store\n        try:\n            if getattr(self, \"structured_logger\", None):\n                try:\n                    self.structured_logger.log(level, msg, {\"path\": path, \"size\": size})\n                except Exception:\n                    pass\n        except Exception:\n            pass\n\n    def _fix_text(self, value):\n        if not isinstance(value, str):\n            return value\n        if any(t in value for t in (\"\\u00e2\", \"\\u00f0\", \"\\u00c2\", \"\u00c3\u00a2\", \"\u00c3\u00b0\", \"\u00c3\u201a\")):\n            try:\n                return value.encode(\"cp1252\", errors=\"ignore\").decode(\"utf-8\", errors=\"ignore\")\n            except:\n                return value\n        return value\n\n    def _sanitize_ui_texts(self):\n        def walk(widget):\n            try:\n                text = widget.cget(\"text\")\n                fixed = self._fix_text(text)\n                if fixed != text:\n                    widget.config(text=fixed)\n            except:\n                pass\n            for child in widget.winfo_children():\n                walk(child)\n        walk(self)\n\n    def _dpi_px(self, value):\n        try:\n            scaling = float(self.tk.call(\"tk\", \"scaling\"))\n            factor = max(0.85, min(1.45, scaling / 1.3333333333))\n            return max(1, int(round(value * factor)))\n        except Exception:\n            return int(value)\n\n    def _bind_scoped_mousewheel(self, widget, canvas, units=3):\n        if not getattr(self, \"_scroll_mousewheel_targets\", None):\n            self._scroll_mousewheel_targets = {}\n\n        self._scroll_mousewheel_targets[widget] = (canvas, units)\n        self._scroll_mousewheel_targets[canvas] = (canvas, units)\n\n        def _wheel(event):\n            target = event.widget\n            targets = getattr(self, \"_scroll_mousewheel_targets\", {})\n            while target is not None:\n                if target in targets:\n                    canvas_target, unit_target = targets[target]\n                    try:\n                        if getattr(event, \"num\", None) == 4:\n                            canvas_target.yview_scroll(-unit_target, \"units\")\n                        elif getattr(event, \"num\", None) == 5:\n                            canvas_target.yview_scroll(unit_target, \"units\")\n                        else:\n                            step = int(-1 * (event.delta / 120))\n                            canvas_target.yview_scroll(step * unit_target, \"units\")\n                    except Exception:\n                        pass\n                    return \"break\"\n                target = getattr(target, \"master\", None)\n            return None\n\n        if not getattr(self, \"_mousewheel_binding_installed\", False):\n            self._mousewheel_binding_installed = True\n            self.bind_all(\"\", _wheel, add=\"+\")\n            self.bind_all(\"\", _wheel, add=\"+\")\n            self.bind_all(\"\", _wheel, add=\"+\")\n\n    def _scrollable_section_body(self, parent, bg=None):\n        \"\"\"Create a responsive scrollable section with proper width management.\n        \n        ENGINEERING FIX #4: Improved canvas+scrollbar layout to prevent content clipping.\n        Uses the same pattern as the fixed sidebar for consistency.\n        \"\"\"\n        bg = bg or C[\"bg\"]\n        outer = tk.Frame(parent, bg=bg)\n        outer.pack(fill=\"both\", expand=True)\n        \n        # Create canvas and scrollbar\n        canvas = tk.Canvas(outer, bg=bg, highlightthickness=0, borderwidth=0)\n        yscroll = ttk.Scrollbar(outer, orient=\"vertical\", command=canvas.yview)\n        \n        # Create body frame with proper sizing\n        body = tk.Frame(canvas, bg=bg)\n        \n        # Embed body in canvas\n        win = canvas.create_window((0, 0), window=body, anchor=\"nw\")\n\n        def _on_body_configure(event=None):\n            \"\"\"Update scroll region when body content changes.\"\"\"\n            try:\n                canvas.configure(scrollregion=canvas.bbox(\"all\"))\n                # Get available width (canvas width, not including scrollbar)\n                available_width = canvas.winfo_width()\n                if available_width &gt; 1:\n                    # Set window width to match canvas width\n                    canvas.itemconfig(win, width=available_width)\n            except tk.TclError:\n                pass  # Canvas destroyed\n\n        def _on_canvas_configure(event):\n            \"\"\"Update scroll region when canvas is resized.\"\"\"\n            try:\n                # Ensure window width matches available canvas space\n                canvas.itemconfig(win, width=event.width)\n                canvas.configure(scrollregion=canvas.bbox(\"all\"))\n            except tk.TclError:\n                pass  # Canvas destroyed\n\n        # Bind configuration events\n        body.bind(\"\", _on_body_configure)\n        canvas.bind(\"\", _on_canvas_configure)\n        \n        # Configure canvas scrolling\n        canvas.configure(yscrollcommand=yscroll.set)\n        \n        # Pack scrollbar first (right), then canvas (left) for proper z-ordering\n        yscroll.pack(side=\"right\", fill=\"y\", expand=False)  # expand=False prevents scrollbar from stretching\n        canvas.pack(side=\"left\", fill=\"both\", expand=True)\n        \n        # Setup mousewheel scrolling\n        self._bind_scoped_mousewheel(body, canvas)\n        body._scroll_canvas = canvas\n        body._scroll_outer = outer\n        return body\n\n    def _set_uninst_progress(self, pct=None, text=None, color=None):\n        def _do():\n            try:\n                if pct is not None and hasattr(self, \"uninst_progress_var\"):\n                    pct_float = max(0, min(100, float(pct)))\n                    self.uninst_progress_var.set(pct_float)\n                    if pct_float &lt;= 0 or not getattr(self, \"_uninst_progress_started_at\", None):\n                        self._uninst_progress_started_at = time.time()\n                    elapsed = max(0.0, time.time() - float(getattr(self, \"_uninst_progress_started_at\", time.time())))\n                    if pct_float &gt; 0:\n                        total_est = elapsed / (pct_float / 100.0)\n                        left = max(0.0, total_est - elapsed)\n                        total_txt = self._format_seconds(total_est)\n                        left_txt = self._format_seconds(left)\n                    else:\n                        total_txt = \"--\"\n                        left_txt = \"--\"\n                    if hasattr(self, \"uninst_timing_lbl\"):\n                        self.uninst_timing_lbl.config(\n                            text=f\"Elapsed: {self._format_seconds(elapsed)} | Left: {left_txt} | Total: {total_txt}\"\n                        )\n                    if pct_float &gt;= 100:\n                        self._uninst_progress_started_at = None\n                if text is not None and hasattr(self, \"uninst_status\"):\n                    self.uninst_status.config(text=\"  \" + self._fix_text(str(text)), fg=color or C[\"accent2\"])\n            except Exception:\n                pass\n\n        if threading.current_thread() is threading.main_thread():\n            _do()\n        else:\n            self.after(0, _do)\n\n    def _check_uninst_control(self):\n        if getattr(self, \"_uninst_cancel_flag\", False):\n            raise InterruptedError(\"User cancelled uninstall scan\")\n        paused_notice = False\n        while getattr(self, \"_uninst_pause_flag\", False):\n            if getattr(self, \"_uninst_cancel_flag\", False):\n                raise InterruptedError(\"User cancelled uninstall scan\")\n            if not paused_notice:\n                paused_notice = True\n                self._set_uninst_progress(text=\"Scan paused. Press Resume to continue.\", color=C[\"warning\"])\n            time.sleep(0.15)\n\n    def _pause_resume_uninst_scan(self):\n        self._uninst_pause_flag = not getattr(self, \"_uninst_pause_flag\", False)\n        if hasattr(self, \"uninst_pause_btn\"):\n            self.uninst_pause_btn.config(text=\"Resume Scan\" if self._uninst_pause_flag else \"Pause Scan\")\n        self._set_uninst_progress(\n            text=\"Scan paused. Press Resume to continue.\" if self._uninst_pause_flag else \"Scan resumed.\",\n            color=C[\"warning\"] if self._uninst_pause_flag else C[\"accent4\"],\n        )\n\n    def _stop_uninst_scan(self):\n        self._uninst_cancel_flag = True\n        self._set_uninst_progress(text=\"Stop requested. Current safe checkpoint will finish first.\", color=C[\"warning\"])\n\n    def _leftover_record(self, ftype, path, confidence=70, risk=None, source=\"\", action=\"delete\", meta=None):\n        ftype = str(ftype or \"ITEM\").upper()\n        path = str(path or \"\")\n        if risk is None:\n            if ftype in {\"REG\", \"SERVICE\", \"TASK\", \"STARTUP\"}:\n                risk = \"Risky\"\n            elif ftype in {\"SHORTCUT\"}:\n                risk = \"Safe\"\n            else:\n                risk = \"Safe\"\n        try:\n            confidence = int(confidence)\n        except Exception:\n            confidence = 60\n        return {\n            \"type\": ftype,\n            \"path\": path,\n            \"risk\": risk,\n            \"confidence\": max(0, min(100, confidence)),\n            \"source\": source,\n            \"action\": action,\n            \"meta\": meta or {},\n        }\n\n    def _leftover_parts(self, item):\n        if isinstance(item, dict):\n            return (\n                str(item.get(\"type\", \"ITEM\")),\n                str(item.get(\"path\", \"\")),\n                str(item.get(\"risk\", \"\")),\n                int(item.get(\"confidence\", 0) or 0),\n                item.get(\"meta\", {}) or {},\n            )\n        try:\n            ftype, path = item\n            return str(ftype), str(path), \"Risky\" if str(ftype).upper() == \"REG\" else \"Safe\", 60, {}\n        except Exception:\n            return \"ITEM\", str(item), \"Risky\", 0, {}\n\n    def _add_leftover_item(self, found, seen, ftype, path, confidence=70, risk=None, source=\"\", action=\"delete\", meta=None):\n        if not path:\n            return\n        key = (str(ftype).upper(), str(path).lower())\n        if key in seen:\n            return\n        seen.add(key)\n        found.append(self._leftover_record(ftype, path, confidence, risk, source, action, meta))\n\n    def _native_delete_file(self, path):\n        try:\n            from ctypes import wintypes\n            ctypes.windll.kernel32.DeleteFileW.argtypes = [wintypes.LPCWSTR]\n            ctypes.windll.kernel32.DeleteFileW.restype = wintypes.BOOL\n            return bool(ctypes.windll.kernel32.DeleteFileW(str(path)))\n        except Exception:\n            return False\n\n    def _native_remove_empty_dir(self, path):\n        try:\n            from ctypes import wintypes\n            ctypes.windll.kernel32.RemoveDirectoryW.argtypes = [wintypes.LPCWSTR]\n            ctypes.windll.kernel32.RemoveDirectoryW.restype = wintypes.BOOL\n            return bool(ctypes.windll.kernel32.RemoveDirectoryW(str(path)))\n        except Exception:\n            return False\n\n    def _native_delete_service(self, service_name):\n        try:\n            from ctypes import wintypes\n            advapi = ctypes.windll.advapi32\n            advapi.OpenSCManagerW.argtypes = [wintypes.LPCWSTR, wintypes.LPCWSTR, wintypes.DWORD]\n            advapi.OpenSCManagerW.restype = wintypes.HANDLE\n            advapi.OpenServiceW.argtypes = [wintypes.HANDLE, wintypes.LPCWSTR, wintypes.DWORD]\n            advapi.OpenServiceW.restype = wintypes.HANDLE\n            advapi.DeleteService.argtypes = [wintypes.HANDLE]\n            advapi.DeleteService.restype = wintypes.BOOL\n            advapi.CloseServiceHandle.argtypes = [wintypes.HANDLE]\n            advapi.CloseServiceHandle.restype = wintypes.BOOL\n            SC_MANAGER_CONNECT = 0x0001\n            DELETE = 0x00010000\n            SERVICE_STOP = 0x0020\n            SERVICE_QUERY_STATUS = 0x0004\n            scm = advapi.OpenSCManagerW(None, None, SC_MANAGER_CONNECT)\n            if not scm:\n                return False, \"OpenSCManagerW failed\"\n            try:\n                svc = advapi.OpenServiceW(scm, str(service_name), DELETE | SERVICE_STOP | SERVICE_QUERY_STATUS)\n                if not svc:\n                    return False, \"OpenServiceW failed\"\n                try:\n                    ok = bool(advapi.DeleteService(svc))\n                    return ok, \"\" if ok else \"DeleteService failed\"\n                finally:\n                    advapi.CloseServiceHandle(svc)\n            finally:\n                advapi.CloseServiceHandle(scm)\n        except Exception as e:\n            return False, str(e)\n\n    def _delete_leftover_path(self, path, ftype):\n        ftype = str(ftype or \"\").upper()\n        if ftype == \"FOLDER\":\n            blocked, reason = _is_dangerous_cleanup_target(path)\n            if blocked:\n                raise PermissionError(reason)\n            if self._native_remove_empty_dir(path):\n                return\n            shutil.rmtree(path, ignore_errors=False)\n            return\n        if ftype in {\"FILE\", \"SHORTCUT\"}:\n            if self._native_delete_file(path):\n                return\n            os.remove(path)\n\n    def _normalize_uninstall_command(self, item, quiet=True):\n        cmd = (item.get(\"quiet\") if quiet else \"\") or item.get(\"uninst\", \"\") or \"\"\n        cmd = str(cmd).strip()\n        if not cmd:\n            return \"\"\n        low = cmd.lower()\n        if \"msiexec\" in low:\n            product = re.search(r\"\\{[0-9a-fA-F\\-]{36}\\}\", cmd)\n            if product:\n                cmd = f\"msiexec.exe /x {product.group(0)}\"\n            elif \" /i\" in low or low.endswith(\"/i\"):\n                cmd = re.sub(r\"(?i)\\s/i\\s*\", \" /x \", cmd)\n            if quiet and \"/qn\" not in cmd.lower() and \"/quiet\" not in cmd.lower():\n                cmd += \" /qn\"\n            if quiet and \"/norestart\" not in cmd.lower():\n                cmd += \" /norestart\"\n        return cmd\n\n    def _command_requires_shell(self, cmd):\n        if not isinstance(cmd, str):\n            return False\n        text = cmd.strip()\n        lower = text.lower()\n        metachars = (\"|\", \"&amp;&amp;\", \"||\", \"&gt;\", \"&lt;\")\n        builtins = (\"start \", \"rd \", \"del \", \"copy \", \"move \", \"echo \")\n        return (\n            any(token in text for token in metachars)\n            or lower.startswith(builtins)\n            or \"%\" in text\n        )\n\n    def _run_cmd(self, cmd, shell=None, timeout=120):\n        if shell is None:\n            shell = True\n        started = time.time()\n        if isinstance(cmd, (list, tuple)):\n            try:\n                result = safe_run(cmd, timeout=timeout)\n                self._audit_event(\"safe_command\", {\n                    \"cmd\": result.args[:20],\n                    \"rc\": result.returncode,\n                    \"timeout_s\": timeout,\n                    \"elapsed_ms\": result.elapsed_ms,\n                    \"timed_out\": result.timed_out,\n                    \"output_tail\": result.output[-300:],\n                })\n                return result.output, result.returncode\n            except Exception as e:\n                return str(e), -1\n        actual_shell = bool(shell and self._command_requires_shell(cmd))\n        if shell and actual_shell:\n            self._audit_event(\"restricted_shell_command_legacy\", {\n                \"cmd\": str(cmd)[:500],\n                \"note\": \"Shell kept only for legacy commands that require cmd.exe semantics.\",\n            })\n        elif shell:\n            self._audit_event(\"legacy_string_command_safened\", {\n                \"cmd\": str(cmd)[:500],\n                \"note\": \"Shell bypassed; migrate caller to list args/safe_run.\",\n            })\n        try:\n            startupinfo = None\n            creationflags = 0\n            if sys.platform == \"win32\":\n                startupinfo = subprocess.STARTUPINFO()\n                startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW\n                creationflags = subprocess.CREATE_NO_WINDOW\n            result = subprocess.run(\n                cmd,\n                shell=actual_shell,\n                capture_output=True,\n                text=True,\n                timeout=timeout,\n                encoding=\"utf-8\",\n                errors=\"replace\",\n                startupinfo=startupinfo,\n                creationflags=creationflags,\n            )\n            output = (result.stdout or \"\").strip()\n            err = (result.stderr or \"\").strip()\n            if err:\n                output = f\"{output}\\n{err}\".strip()\n            self._audit_event(\"command\", {\n                \"cmd\": str(cmd)[:500],\n                \"rc\": result.returncode,\n                \"timeout_s\": timeout,\n                \"elapsed_ms\": int((time.time() - started) * 1000),\n                \"output_tail\": output[-300:],\n            })\n            return output, result.returncode\n        except subprocess.TimeoutExpired:\n            self._audit_event(\"command_timeout\", {\n                \"cmd\": str(cmd)[:500],\n                \"timeout_s\": timeout,\n                \"elapsed_ms\": int((time.time() - started) * 1000),\n            })\n            return f\"Command timed out: {cmd}\", -1\n        except Exception as e:\n            self._audit_event(\"command_error\", {\n                \"cmd\": str(cmd)[:500],\n                \"error\": str(e),\n                \"elapsed_ms\": int((time.time() - started) * 1000),\n            })\n            return str(e), -1\n\n    def _run_powershell(self, script, timeout=120):\n        \"\"\"PowerShell ko EncodedCommand se run karta hai taaki quoting issues na aayein.\"\"\"\n        try:\n            result = safe_powershell(script, timeout=timeout)\n            self._audit_event(\"safe_powershell\", {\n                \"rc\": result.returncode,\n                \"timeout_s\": timeout,\n                \"elapsed_ms\": result.elapsed_ms,\n                \"timed_out\": result.timed_out,\n                \"output_tail\": result.output[-300:],\n            })\n            return result.output, result.returncode\n        except Exception as e:\n            return str(e), -1\n\n    def _stream_cmd_to_log(self, cmd, log_widget, timeout_s=1800, stop_attr=\"_repair_stop_flag\"):\n        \"\"\"\n        Existing logging ko use karke command output live stream karta hai.\n        Return: (full_output, rc, timed_out, stopped)\n        \"\"\"\n        output = []\n        started = time.time()\n        timed_out = False\n        stopped = False\n        proc = None\n        try:\n            setattr(self, stop_attr, False)\n            startupinfo = None\n            creationflags = 0\n            if sys.platform == \"win32\":\n                startupinfo = subprocess.STARTUPINFO()\n                startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW\n                creationflags = subprocess.CREATE_NO_WINDOW\n            proc = subprocess.Popen(\n                cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,\n                text=True, encoding=\"utf-8\", errors=\"replace\",\n                startupinfo=startupinfo,\n                creationflags=creationflags,\n            )\n            if stop_attr == \"_repair_stop_flag\":\n                self._repair_proc = proc\n            for line in iter(proc.stdout.readline, \"\"):\n                if not line and proc.poll() is not None:\n                    break\n                clean = line.rstrip(\"\\n\")\n                if clean:\n                    output.append(clean)\n                    self._append_log(log_widget, clean, C[\"text_dim\"])\n                if getattr(self, stop_attr, False):\n                    stopped = True\n                    try:\n                        proc.terminate()\n                    except Exception:\n                        pass\n                    break\n                if timeout_s and (time.time() - started) &gt; timeout_s:\n                    timed_out = True\n                    try:\n                        proc.terminate()\n                    except Exception:\n                        pass\n                    break\n            try:\n                rc = proc.wait(timeout=5)\n            except Exception:\n                rc = -1\n        except Exception as e:\n            output.append(str(e))\n            rc = -1\n            self._append_log(log_widget, f\"Command stream failed: {e}\", C[\"error\"])\n        finally:\n            if stop_attr == \"_repair_stop_flag\":\n                self._repair_proc = None\n        return \"\\n\".join(output), rc, timed_out, stopped\n\n    # ---------- CONFIRMATION WITH BEFORE/AFTER ----------\n    def _operation_preflight_summary(self, title, commands=None):\n        engine = getattr(self, \"preflight_engine\", None)\n        if not engine:\n            return None\n        try:\n            return engine.analyze(title, commands or [])\n        except Exception:\n            return None\n\n    def _format_preflight_for_dialog(self, preflight):\n        if not preflight:\n            return \"Preflight: unavailable\"\n        lines = [\n            f\"Risk: {str(preflight.risk).upper()} ({preflight.score}/100)\",\n            f\"Admin required: {'yes' if preflight.requires_admin else 'no'}\",\n            f\"Restore point required: {'yes' if preflight.requires_restore_point else 'no'}\",\n            f\"Rollback snapshot required: {'yes' if preflight.requires_rollback_snapshot else 'no'}\",\n            f\"Dry-run recommended: {'yes' if preflight.dry_run_recommended else 'no'}\",\n        ]\n        for finding in getattr(preflight, \"findings\", [])[:3]:\n            lines.append(f\"- {finding.message} Recommendation: {finding.recommendation}\")\n        return \"\\n\".join(lines)\n\n    def _confirm_and_run(self, title, description, before_callback, action_callback, after_callback=None):\n        before_info = before_callback() if before_callback else \"No before data\"\n        preflight = self._operation_preflight_summary(title)\n        msg = (\n            f\"{description}\\n\\n\"\n            f\"SAFETY PREFLIGHT:\\n{self._format_preflight_for_dialog(preflight)}\\n\\n\"\n            f\"\ud83d\udcca BEFORE:\\n{before_info}\\n\\nDo you want to proceed?\"\n        )\n        if not messagebox.askyesno(title, msg):\n            self._audit_event(\"action_cancelled\", {\"title\": title})\n            return False\n        if preflight and getattr(preflight, \"typed_confirmation\", False):\n            token = str(title).strip()[:24]\n            typed = simpledialog.askstring(\n                \"Critical Confirmation\",\n                f\"Type this action name to continue:\\n\\n{token}\",\n            )\n            if typed != token:\n                self._audit_event(\"action_cancelled\", {\"title\": title, \"reason\": \"typed_confirmation_failed\"})\n                return False\n        risky_words = (\"delete\", \"clean\", \"disable\", \"registry\", \"policy\", \"remove\", \"repair\", \"force\")\n        lower_title = str(title).lower()\n        if any(w in lower_title for w in risky_words) or (preflight and preflight.requires_restore_point):\n            try:\n                self._create_restore_point(f\"Pre-Action: {title}\")\n            except Exception:\n                pass\n\n        state_before = self._snapshot_system_state()\n        self._audit_event(\"action_started\", {\n            \"title\": title,\n            \"before_info\": str(before_info)[:800],\n            \"state\": state_before,\n            \"preflight\": {\n                \"risk\": getattr(preflight, \"risk\", \"\"),\n                \"score\": getattr(preflight, \"score\", 0),\n                \"restore_point\": getattr(preflight, \"requires_restore_point\", False),\n                \"rollback_snapshot\": getattr(preflight, \"requires_rollback_snapshot\", False),\n            },\n        })\n        self._set_status(f\"Executing: {title}...\", C[\"accent4\"])\n        action_result = action_callback()\n        success_guess = True\n        if isinstance(action_result, dict) and action_result.get(\"ok\") is False:\n            success_guess = False\n        if after_callback:\n            after_info = after_callback()\n            diff_msg = f\"\\n\\n\ud83d\udcc8 AFTER:\\n{after_info}\"\n            if isinstance(action_result, dict) and action_result.get(\"message\"):\n                messagebox.showinfo(\"Complete\", f\"{action_result['message']}{diff_msg}\")\n            else:\n                messagebox.showinfo(\"Complete\", f\"{title} completed successfully.{diff_msg}\")\n        else:\n            if isinstance(action_result, dict) and action_result.get(\"message\"):\n                box_title = \"Already Done\" if action_result.get(\"already_done\") else \"Complete\"\n                messagebox.showinfo(box_title, action_result[\"message\"])\n            else:\n                messagebox.showinfo(\"Complete\", f\"{title} completed.\")\n            after_info = \"No after data\"\n        state_after = self._snapshot_system_state()\n        self._audit_event(\"action_finished\", {\n            \"title\": title,\n            \"success\": success_guess,\n            \"after_info\": str(after_info)[:800],\n            \"state_before\": state_before,\n            \"state_after\": state_after,\n        })\n        self._set_status(\"Ready\", C[\"success\"])\n        return True\n\n    def _confirm_and_launch_job(self, title, description, before_callback, job_name, target, *args):\n        before_info = before_callback() if before_callback else \"No before data\"\n        preflight = self._operation_preflight_summary(title)\n        msg = (\n            f\"{description}\\n\\n\"\n            f\"SAFETY PREFLIGHT:\\n{self._format_preflight_for_dialog(preflight)}\\n\\n\"\n            f\"\ud83d\udcca BEFORE:\\n{before_info}\\n\\nDo you want to proceed?\"\n        )\n        if not messagebox.askyesno(title, msg):\n            self._audit_event(\"action_cancelled\", {\"title\": title})\n            return False\n        risky_words = (\"delete\", \"clean\", \"disable\", \"registry\", \"policy\", \"remove\", \"repair\", \"force\")\n        lower_title = str(title).lower()\n        if any(w in lower_title for w in risky_words) or (preflight and preflight.requires_restore_point):\n            try:\n                self._create_restore_point(f\"Pre-Action: {title}\")\n            except Exception:\n                pass\n\n        state_before = self._snapshot_system_state()\n        self._audit_event(\"action_started\", {\n            \"title\": title,\n            \"before_info\": str(before_info)[:800],\n            \"state\": state_before,\n            \"preflight\": {\n                \"risk\": getattr(preflight, \"risk\", \"\"),\n                \"score\": getattr(preflight, \"score\", 0),\n                \"restore_point\": getattr(preflight, \"requires_restore_point\", False),\n                \"rollback_snapshot\": getattr(preflight, \"requires_rollback_snapshot\", False),\n            },\n        })\n        self._set_status(f\"Queued: {title}...\", C[\"accent4\"])\n        jid = self._launch_job(job_name, target, *args)\n        self._audit_event(\"action_launched\", {\"title\": title, \"job_id\": jid, \"name\": job_name})\n        return jid\n\n    def _set_clean_job_state(self, running=False, export_ready=False):\n        self._clean_job_running = bool(running)\n        try:\n            if hasattr(self, \"clean_cancel_btn\"):\n                self.clean_cancel_btn.config(state=\"normal\" if running else \"disabled\")\n        except Exception:\n            pass\n        try:\n            if hasattr(self, \"clean_report_btn\"):\n                self.clean_report_btn.config(state=\"normal\" if export_ready and not running else \"disabled\")\n        except Exception:\n            pass\n\n    def _cancel_clean_job(self):\n        if not getattr(self, \"_clean_job_running\", False):\n            return\n        self._clean_job_cancel_event.set()\n        self._set_status(\"Clean operation cancellation requested...\", C[\"warning\"])\n        self._append_log(self.clean_log, \"\u23f9 Requested cancellation of current clean operation.\", C[\"warning\"])\n\n    def _export_clean_report(self):\n        summary = getattr(self, \"_clean_job_summary\", {}) or {}\n        if not summary:\n            messagebox.showwarning(\"No Report\", \"Run a scan or clean operation first, then export the report.\")\n            return\n        fpath = filedialog.asksaveasfilename(defaultextension=\".txt\", filetypes=[(\"Text Report\",\"*.txt\")], title=\"Save Cleaner Report\")\n        if not fpath:\n            return\n        try:\n            report_lines = [\"Godawari Cleaner Report\", f\"Date: {datetime.datetime.now()}\", \"\"]\n            report_lines.append(\"Junk Cleaner Summary:\")\n            report_lines.append(f\"Targets processed: {summary.get('processed', 0)} / {summary.get('total_paths', 0)}\")\n            if summary.get('total_size') is not None:\n                report_lines.append(f\"Total junk found: {self._fmt_size(summary.get('total_size', 0))}\")\n            if summary.get('freed') is not None:\n                report_lines.append(f\"Freed: {self._fmt_size(summary.get('freed', 0))}\")\n                report_lines.append(f\"Remaining junk: {self._fmt_size(summary.get('remaining', 0))}\")\n            if summary.get('preview'):\n                report_lines.append(\"Preview mode: yes\")\n            if summary.get('canceled'):\n                report_lines.append(\"Canceled: yes\")\n            report_lines.append(f\"Errors: {summary.get('errors', 0)}\")\n            report_lines.append(\"\")\n            report_lines.append(\"Detailed Clean Log:\")\n            report_lines.append(self.clean_log.get(\"1.0\", \"end\").strip())\n            with open(fpath, \"w\", encoding=\"utf-8\") as f:\n                f.write(\"\\n\".join(report_lines))\n            self._append_log(self.clean_log, f\"\u2705 Exported cleaner report: {fpath}\", C[\"success\"])\n        except Exception as e:\n            messagebox.showerror(\"Export Failed\", str(e))\n\n    def _finalize_clean_job(self, job_type, summary):\n        try:\n            self._set_clean_job_state(running=False, export_ready=True)\n            self._clean_job_summary = summary\n            canceled = summary.get(\"canceled\", False)\n            total_paths = summary.get(\"total_paths\", 0)\n            processed = summary.get(\"processed\", 0)\n            summary_lines = [f\"{job_type.title()} Summary:\"]\n            summary_lines.append(f\"Targets processed: {processed} / {total_paths}\")\n            if job_type == \"scan\":\n                total_size = summary.get(\"total_size\", 0)\n                summary_lines.append(f\"Total junk found: {self._fmt_size(total_size)}\")\n                self.clean_size_lbl.config(text=f\"Total junk found: {self._fmt_size(total_size)}\")\n                self.clean_progress_lbl.config(text=f\"Scan complete: {self._fmt_size(total_size)}\")\n            else:\n                freed = summary.get(\"freed\", 0)\n                remaining = summary.get(\"remaining\", 0)\n                summary_lines.append(f\"Freed: {self._fmt_size(freed)}\")\n                summary_lines.append(f\"Remaining junk: {self._fmt_size(remaining)}\")\n                if summary.get(\"preview\"):\n                    summary_lines.append(\"Preview mode: no files were deleted.\")\n                self.clean_size_lbl.config(text=f\"Total junk found: {self._fmt_size(remaining)} remaining\")\n                self.clean_progress_lbl.config(text=f\"Clean complete: {self._fmt_size(freed)} freed\")\n            if summary.get(\"errors\", 0):\n                summary_lines.append(f\"Errors: {summary.get('errors', 0)}\")\n            if canceled:\n                summary_lines.append(\"Operation canceled by user.\")\n                self._set_status(f\"{job_type.title()} canceled.\", C[\"warning\"])\n            else:\n                self._set_status(f\"{job_type.title()} complete.\", C[\"success\"])\n            if hasattr(self, \"clean_progress_bar\"):\n                try:\n                    if total_paths &gt; 0:\n                        self.clean_progress_bar.config(value=min(processed, total_paths))\n                except Exception:\n                    pass\n            self._append_log(self.clean_log, \"\\n\".join(summary_lines), C[\"accent\"])\n            messagebox.showinfo(f\"{job_type.title()} Complete\", \"\\n\".join(summary_lines))\n        except Exception:\n            pass\n\n    # ---------- DASHBOARD ----------\n    def _build_dashboard(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        tb = tk.Frame(frame, bg=C[\"panel\"])\n        tb.pack(fill=\"x\")\n        tk.Label(tb, text=\"  System Dashboard\", font=FONTS[\"heading\"], fg=C[\"accent\"], bg=C[\"panel\"]).pack(side=\"left\", pady=10, padx=8)\n        tk.Button(tb, text=\"\u27f3 Refresh\", font=FONTS[\"small\"], bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=10, pady=4, cursor=\"hand2\", command=self._refresh_dashboard).pack(side=\"right\", padx=12, pady=8)\n        tk.Button(tb, text=\"\ud83d\ude80 Live Internet Speed Test\", font=FONTS[\"small\"], bg=C[\"btn_warn\"], fg=C[\"text\"], bd=0, padx=10, pady=4, cursor=\"hand2\", command=self._live_speed_test).pack(side=\"right\", padx=5, pady=8)\n        tk.Button(tb, text=\"\ud83d\udd0d One-Click Health Scan\", font=FONTS[\"small\"], bg=C[\"btn_warn\"], fg=C[\"text\"], bd=0, padx=10, pady=4, cursor=\"hand2\", command=self._one_click_health_scan).pack(side=\"right\", padx=5, pady=8)\n        grid = tk.Frame(frame, bg=C[\"bg\"])\n        grid.pack(fill=\"x\", padx=16, pady=(12,0))\n        self.dash_cards = {}\n        cards_def = [(\"cpu\",\"CPU Usage\",C[\"accent\"],\"0%\"), (\"ram\",\"RAM Usage\",C[\"success\"],\"0%\"),\n                     (\"disk\",\"Disk Usage\",C[\"accent4\"],\"0%\"), (\"health\",\"Health Score\",C[\"accent2\"],\"--\"),\n                     (\"uptime\",\"Uptime\",C[\"accent2\"],\"--\")]\n        for i, (k, title, color, val) in enumerate(cards_def):\n            card = self._stat_card(grid, title, val, color)\n            card.grid(row=0, column=i, padx=6, pady=6, sticky=\"ew\")\n            grid.columnconfigure(i, weight=1)\n            self.dash_cards[k] = card\n        self.after(2000, self._refresh_health_score_card)\n        graph_frame = tk.Frame(frame, bg=C[\"card\"])\n        graph_frame.pack(fill=\"x\", padx=16, pady=6)\n        tk.Label(graph_frame, text=\"  Live CPU/RAM History (60s)\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8,4), padx=8)\n        self.graph_canvas = tk.Canvas(graph_frame, bg=C[\"bg\"], height=self._dpi_px(82), highlightthickness=0)\n        self.graph_canvas.pack(fill=\"x\", padx=8, pady=8)\n        self.graph_data = {\"cpu\": [], \"ram\": []}\n\n        rec_panel = tk.Frame(frame, bg=C[\"card\"])\n        rec_panel.pack(fill=\"x\", padx=16, pady=(0, 8))\n        rec_head = tk.Frame(rec_panel, bg=C[\"card\"])\n        rec_head.pack(fill=\"x\", padx=8, pady=(8, 4))\n        tk.Label(rec_head, text=\"  Intelligent Recommendations\", font=FONTS[\"subhead\"],\n                 fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._btn(rec_head, \"Refresh\", C[\"btn_info\"], self._refresh_intelligent_recommendations).pack(side=\"right\")\n        rec_cols = (\"Priority\", \"Menu\", \"Action\")\n        self.dashboard_recommendation_tree = ttk.Treeview(\n            rec_panel, columns=rec_cols, show=\"headings\", height=5, style=\"Custom.Treeview\")\n        for col, w in zip(rec_cols, (90, 210, 720)):\n            self.dashboard_recommendation_tree.heading(col, text=col)\n            self.dashboard_recommendation_tree.column(col, width=w, anchor=\"w\")\n        self.dashboard_recommendation_tree.pack(fill=\"x\", padx=8, pady=(0, 8))\n        self.dashboard_recommendation_tree.bind(\"\", lambda _e: self._show_section(\"safety_center\"))\n        self.after(2600, self._refresh_intelligent_recommendations)\n\n        lower = tk.Frame(frame, bg=C[\"bg\"])\n        lower.pack(fill=\"both\", expand=True, padx=16, pady=10)\n        lower.columnconfigure(0, weight=5)\n        lower.columnconfigure(1, weight=2)\n        lower.rowconfigure(0, weight=1)\n        proc_frame = tk.Frame(lower, bg=C[\"card\"])\n        proc_frame.grid(row=0, column=0, sticky=\"nsew\", padx=(0,6))\n        proc_frame.rowconfigure(1, weight=1)\n        proc_frame.columnconfigure(0, weight=1)\n        tk.Label(proc_frame, text=\"  Process Center - Top CPU Processes\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=0, column=0, columnspan=2, sticky=\"w\", pady=(8,4), padx=8)\n        cols = (\"PID\",\"Name\",\"CPU%\",\"RAM MB\",\"Status\")\n        self.proc_tree = ttk.Treeview(proc_frame, columns=cols, show=\"headings\", height=24, style=\"Custom.Treeview\")\n        for col, w in zip(cols, [60,200,70,80,80]):\n            self.proc_tree.heading(col, text=col)\n            self.proc_tree.column(col, width=w, anchor=\"center\")\n        sb2 = ttk.Scrollbar(proc_frame, orient=\"vertical\", command=self.proc_tree.yview)\n        xsb2 = ttk.Scrollbar(proc_frame, orient=\"horizontal\", command=self.proc_tree.xview)\n        self.proc_tree.configure(yscrollcommand=sb2.set, xscrollcommand=xsb2.set)\n        self.proc_tree.grid(row=1, column=0, sticky=\"nsew\", padx=(8,0), pady=(0,0))\n        sb2.grid(row=1, column=1, sticky=\"ns\", pady=(0,0), padx=(0,8))\n        xsb2.grid(row=2, column=0, sticky=\"ew\", padx=(8,0), pady=(0,8))\n        self._bind_tree_responsive_columns(self.proc_tree, [\n            (\"PID\", 60, 0), (\"Name\", 220, 5), (\"CPU%\", 70, 1), (\"RAM MB\", 90, 1), (\"Status\", 100, 2)\n        ])\n        qa = tk.Frame(lower, bg=C[\"card\"])\n        qa.grid(row=0, column=1, sticky=\"nsew\", padx=(6,0))\n        tk.Label(qa, text=\"  Quick Actions\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8,6), padx=8)\n        self._action_card_grid(qa, [\n            (\"\ud83e\uddf9\", \"Clean + RAM\",         \"Temp clean + RAM optimize\",        C[\"btn\"],      self._quick_clean_and_ram),\n            (\"\u2699\",  \"Services + Registry\", \"Services + Registry tweaks\",       C[\"btn_info\"], self._quick_services_and_registry),\n            (\"\ud83d\udd0d\", \"Full Health Scan\",    \"Poora system scan karo\",           C[\"btn\"],      self._full_scan),\n            (\"\u26a1\", \"One-Click ALL\",        \"Sabhi boosts ek saath chalao\",     C[\"accent4\"],  self._one_click_all_boosts),\n            (\"\ud83d\udee1\", \"Safety Center\",        \"Health, rollback, sessions\",       C[\"btn_chip\"], lambda: self._show_section(\"safety_center\")),\n        ], cols=2)\n\n        workflow = tk.Frame(lower, bg=C[\"card\"])\n        workflow.grid(row=1, column=0, columnspan=2, sticky=\"ew\", pady=(8,0))\n        tk.Label(workflow, text=\"  Guided Workflows\", font=FONTS[\"subhead\"], fg=C[\"accent2\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=8, pady=(8,4))\n        self.dashboard_workflow_lbl = tk.Label(\n            workflow,\n            text=\"Health scan not run yet \u2014 use One-Click Health Scan or Safety Center to generate guided actions.\",\n            font=FONTS[\"small\"],\n            fg=C[\"text_dim\"],\n            bg=C[\"card\"],\n            justify=\"left\",\n            wraplength=1150,\n            anchor=\"w\",\n        )\n        self.dashboard_workflow_lbl.pack(fill=\"x\", padx=8, pady=(0,8))\n        wf_actions = tk.Frame(workflow, bg=C[\"card\"])\n        wf_actions.pack(fill=\"x\", padx=8, pady=(0,8))\n        for label, color, cmd in [\n            (\"\ud83d\udee1 Safety + Restore\", C[\"btn_warn\"], lambda: (self._show_section(\"safety_center\"), self._create_restore_point(\"Guided workflow\"))),\n            (\"\ud83c\udf10 Network + Repair\", C[\"btn_info\"], lambda: self._show_section(\"network\")),\n            (\"\ud83d\udcbe Recovery + Rescue\", C[\"btn_chip\"], lambda: self._show_section(\"rescue_center\")),\n            (\"\ud83e\uddf9 Clean + RAM\", C[\"btn\"], self._quick_clean_and_ram),\n        ]:\n            tk.Button(wf_actions, text=label, font=FONTS[\"small\"], bg=color, fg=C[\"text\"], bd=0, padx=12, pady=8,\n                      cursor=\"hand2\", command=cmd).pack(side=\"left\", padx=4, pady=4)\n        return frame\n\n    def _build_safety_center(self, parent):\n        \"\"\"Professional safety hub: health scoring, rollback vault, sessions, timeline.\"\"\"\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(\n            frame,\n            \"\ud83d\udee1 Safety &amp; Recovery Center\",\n            \"Health scoring \u2022 Restore Point Manager \u2022 Rollback vault \u2022 Operation timeline\",\n        )\n\n        canvas = tk.Canvas(frame, bg=C[\"bg\"], highlightthickness=0)\n        scrollbar = ttk.Scrollbar(frame, orient=\"vertical\", command=canvas.yview)\n        content = tk.Frame(canvas, bg=C[\"bg\"])\n        content.bind(\"\", lambda e: canvas.configure(scrollregion=canvas.bbox(\"all\")))\n        canvas_window = canvas.create_window((0, 0), window=content, anchor=\"nw\")\n        canvas.configure(yscrollcommand=scrollbar.set)\n        canvas.pack(side=\"left\", fill=\"both\", expand=True)\n        scrollbar.pack(side=\"right\", fill=\"y\")\n\n        def _resize_content(event):\n            try:\n                canvas.itemconfigure(canvas_window, width=event.width)\n                canvas.configure(scrollregion=canvas.bbox(\"all\"))\n            except Exception:\n                pass\n\n        canvas.bind(\"\", _resize_content)\n        self._bind_scoped_mousewheel(content, canvas)\n\n        top = tk.Frame(content, bg=C[\"card\"])\n        top.pack(fill=\"x\", padx=16, pady=10)\n        self.safety_health_lbl = tk.Label(\n            top, text=\"Health: analyzing\u2026\",\n            font=(\"Segoe UI\", 22, \"bold\"), fg=C[\"accent\"], bg=C[\"card\"])\n        self.safety_health_lbl.pack(side=\"left\", padx=12, pady=10)\n        btn_row = tk.Frame(top, bg=C[\"card\"])\n        btn_row.pack(side=\"right\", padx=12)\n        self._btn(btn_row, \"\ud83d\udd0d Run Health Scan\", C[\"btn_warn\"], self._one_click_health_scan).pack(side=\"left\", padx=4)\n        self._btn(btn_row, \"\ud83d\udcbe Create Restore Point\", C[\"btn_info\"],\n                  lambda: self._create_restore_point(\"Safety Center manual\")).pack(side=\"left\", padx=4)\n        self._btn(btn_row, \"Generate Audit\", C[\"accent4\"], self._safety_export_product_audit).pack(side=\"left\", padx=4)\n        self._btn(btn_row, \"Export Menu Map\", C[\"btn_chip\"], self._safety_export_menu_map).pack(side=\"left\", padx=4)\n        self._btn(btn_row, \"\ud83d\udd04 Refresh\", C[\"btn\"], self._safety_refresh_all).pack(side=\"left\", padx=4)\n\n        mid = tk.Frame(content, bg=C[\"bg\"])\n        mid.pack(fill=\"x\", padx=16, pady=(0, 10))\n        mid.columnconfigure(0, weight=1)\n        mid.columnconfigure(1, weight=1)\n\n        # Rollback vault\n        rb_card = tk.LabelFrame(mid, text=\" Rollback Vault \", font=FONTS[\"subhead\"],\n                                fg=C[\"accent\"], bg=C[\"card\"])\n        rb_card.grid(row=0, column=0, sticky=\"nsew\", padx=(0, 6), pady=(0, 6))\n        rb_cols = (\"Session\", \"Items\", \"Created\")\n        self.safety_rollback_tree = ttk.Treeview(\n            rb_card, columns=rb_cols, show=\"headings\", height=8, style=\"Custom.Treeview\")\n        for col, w in zip(rb_cols, (200, 60, 160)):\n            self.safety_rollback_tree.heading(col, text=col)\n            self.safety_rollback_tree.column(col, width=w)\n        self.safety_rollback_tree.pack(fill=\"both\", expand=True, padx=8, pady=8)\n        rb_btns = tk.Frame(rb_card, bg=C[\"card\"])\n        rb_btns.pack(fill=\"x\", padx=8, pady=(0, 8))\n        self._btn(rb_btns, \"\u21a9 Restore Selected\", C[\"btn_warn\"], self._safety_restore_rollback).pack(side=\"left\", padx=4)\n        self._btn(rb_btns, \"\ud83d\udcc2 Open Vault Folder\", C[\"btn_chip\"], self._safety_open_rollback_dir).pack(side=\"left\", padx=4)\n\n        # Recovery sessions\n        rs_card = tk.LabelFrame(mid, text=\" Recovery Sessions \", font=FONTS[\"subhead\"],\n                                fg=C[\"accent4\"], bg=C[\"card\"])\n        rs_card.grid(row=0, column=1, sticky=\"nsew\", padx=(6, 0), pady=(0, 6))\n        rs_cols = (\"ID\", \"Kind\", \"Status\", \"Started\")\n        self.safety_session_tree = ttk.Treeview(\n            rs_card, columns=rs_cols, show=\"headings\", height=8, style=\"Custom.Treeview\")\n        for col, w in zip(rs_cols, (120, 100, 80, 140)):\n            self.safety_session_tree.heading(col, text=col)\n            self.safety_session_tree.column(col, width=w)\n        self.safety_session_tree.pack(fill=\"both\", expand=True, padx=8, pady=8)\n        rs_btns = tk.Frame(rs_card, bg=C[\"card\"])\n        rs_btns.pack(fill=\"x\", padx=8, pady=(0, 8))\n        self._btn(rs_btns, \"\u2713 Mark Completed\", C[\"btn_info\"], self._safety_clear_session).pack(side=\"left\", padx=4)\n        self._btn(rs_btns, \"\ud83e\uddf9 Clear Crash Flag\", C[\"btn\"], self._safety_clear_crash_marker).pack(side=\"left\", padx=4)\n\n        rp_card = tk.LabelFrame(mid, text=\" Restore Point Manager \", font=FONTS[\"subhead\"],\n                                fg=C[\"accent4\"], bg=C[\"card\"])\n        rp_card.grid(row=1, column=0, columnspan=2, sticky=\"ew\", pady=(6, 0), padx=(0,0))\n        rp_toolbar = tk.Frame(rp_card, bg=C[\"card\"])\n        rp_toolbar.pack(fill=\"x\", padx=8, pady=(8, 0))\n        tk.Label(rp_toolbar, text=\"Recent Restore Points\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._btn(rp_toolbar, \"Refresh\", C[\"btn\"], self._safety_refresh_restore_points).pack(side=\"right\", padx=4)\n        self._btn(rp_toolbar, \"Open System Restore\", C[\"btn_warn\"], self._open_system_restore).pack(side=\"right\", padx=4)\n        rp_cols = (\"Sequence\", \"Description\", \"Created\")\n        self.safety_restore_tree = ttk.Treeview(\n            rp_card, columns=rp_cols, show=\"headings\", height=5, style=\"Custom.Treeview\")\n        for col, w in zip(rp_cols, (100, 420, 180)):\n            self.safety_restore_tree.heading(col, text=col)\n            self.safety_restore_tree.column(col, width=w, anchor=\"w\")\n        self.safety_restore_tree.pack(fill=\"both\", expand=True, padx=8, pady=8)\n\n        tl_card = tk.LabelFrame(mid, text=\" Operation Timeline (structured log) \", font=FONTS[\"subhead\"],\n                                fg=C[\"accent2\"], bg=C[\"card\"])\n        tl_card.grid(row=2, column=0, columnspan=2, sticky=\"ew\", pady=(6, 0))\n        self.safety_timeline = self._scrolled_text(tl_card, height=12)\n        self.safety_timeline.pack(fill=\"both\", expand=True, padx=8, pady=8)\n\n        # Recommendations\n        rec_card = tk.LabelFrame(mid, text=\" Smart Recommendations \", font=FONTS[\"subhead\"],\n                                 fg=C[\"hw_accent\"], bg=C[\"card\"])\n        rec_card.grid(row=3, column=0, columnspan=2, sticky=\"ew\", pady=(6, 0))\n        self.safety_recommendations = tk.Label(\n            rec_card, text=\"Run a health scan for personalized recommendations.\",\n            font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"],\n            anchor=\"w\", justify=\"left\", wraplength=1100)\n        self.safety_recommendations.pack(fill=\"x\", padx=12, pady=10)\n\n        map_card = tk.LabelFrame(mid, text=\" Detected Software Map \", font=FONTS[\"subhead\"],\n                                 fg=C[\"accent2\"], bg=C[\"card\"])\n        map_card.grid(row=4, column=0, columnspan=2, sticky=\"ew\", pady=(6, 0))\n        map_cols = (\"Category\", \"Menu\", \"Tabs\", \"Buttons\", \"Options\")\n        self.safety_menu_map_tree = ttk.Treeview(\n            map_card, columns=map_cols, show=\"headings\", height=8, style=\"Custom.Treeview\")\n        for col, w in zip(map_cols, (210, 230, 70, 80, 80)):\n            self.safety_menu_map_tree.heading(col, text=col)\n            self.safety_menu_map_tree.column(col, width=w, anchor=\"w\")\n        self.safety_menu_map_tree.pack(fill=\"x\", padx=8, pady=8)\n\n        prof_card = tk.LabelFrame(mid, text=\" Guided Maintenance Profiles \", font=FONTS[\"subhead\"],\n                                  fg=C[\"accent4\"], bg=C[\"card\"])\n        prof_card.grid(row=5, column=0, columnspan=2, sticky=\"ew\", pady=(6, 0))\n        prof_cols = (\"Profile\", \"Risk\", \"Minutes\", \"Menus\")\n        self.safety_profile_tree = ttk.Treeview(\n            prof_card, columns=prof_cols, show=\"headings\", height=5, style=\"Custom.Treeview\")\n        for col, w in zip(prof_cols, (190, 80, 80, 520)):\n            self.safety_profile_tree.heading(col, text=col)\n            self.safety_profile_tree.column(col, width=w, anchor=\"w\")\n        self.safety_profile_tree.pack(fill=\"both\", expand=True, padx=8, pady=8)\n        prof_btns = tk.Frame(prof_card, bg=C[\"card\"])\n        prof_btns.pack(fill=\"x\", padx=8, pady=(0, 8))\n        self._btn(prof_btns, \"View Workflow\", C[\"btn_info\"], self._safety_show_selected_profile).pack(side=\"left\", padx=4)\n        self._btn(prof_btns, \"Open First Menu\", C[\"btn_chip\"], self._safety_open_selected_profile_menu).pack(side=\"left\", padx=4)\n\n        audit_card = tk.LabelFrame(mid, text=\" Product Audit Heat Map \", font=FONTS[\"subhead\"],\n                                   fg=C[\"accent\"], bg=C[\"card\"])\n        audit_card.grid(row=6, column=0, columnspan=2, sticky=\"ew\", pady=(6, 0))\n        audit_cols = (\"Menu\", \"Maturity\", \"Risk\", \"Top upgrade\")\n        self.safety_audit_tree = ttk.Treeview(\n            audit_card, columns=audit_cols, show=\"headings\", height=7, style=\"Custom.Treeview\")\n        for col, w in zip(audit_cols, (220, 80, 70, 520)):\n            self.safety_audit_tree.heading(col, text=col)\n            self.safety_audit_tree.column(col, width=w, anchor=\"w\")\n        self.safety_audit_tree.pack(fill=\"both\", expand=True, padx=8, pady=8)\n\n        self.after(300, self._safety_refresh_all)\n        return frame\n\n    def _build_recommendations_payload(self, limit=10):\n        engine = getattr(self, \"recommendation_engine\", None)\n        audit_engine = getattr(self, \"product_audit_engine\", None)\n        if not engine or not audit_engine:\n            return {\"items\": []}\n        try:\n            return engine.build(\n                getattr(self, \"_last_health_report\", None),\n                audit_engine.list_audits(),\n                limit=limit,\n            )\n        except Exception:\n            return {\"items\": []}\n\n    def _refresh_intelligent_recommendations(self):\n        tree = getattr(self, \"dashboard_recommendation_tree\", None)\n        if not tree:\n            return\n        for iid in tree.get_children():\n            tree.delete(iid)\n        payload = self._build_recommendations_payload(limit=8)\n        for item in payload.get(\"items\", []):\n            tree.insert(\n                \"\", \"end\",\n                values=(\n                    str(item.get(\"priority\", \"\")).upper(),\n                    item.get(\"menu\", \"\"),\n                    item.get(\"action\", \"\"),\n                ),\n            )\n\n    def _recommendations_as_text(self, limit=12):\n        payload = self._build_recommendations_payload(limit=limit)\n        lines = []\n        for item in payload.get(\"items\", []):\n            lines.append(\n                f\"[{str(item.get('priority', '')).upper()}] {item.get('menu', '')}: \"\n                f\"{item.get('title', '')} - {item.get('action', '')}\"\n            )\n        return \"\\n\".join(lines) if lines else \"No recommendations yet. Run a health scan first.\"\n\n    def _safety_refresh_all(self):\n        self._refresh_health_score_card()\n        self._safety_refresh_rollback_tree()\n        self._safety_refresh_restore_points()\n        self._safety_refresh_sessions_tree()\n        self._safety_refresh_timeline()\n        self._safety_refresh_menu_map()\n        self._safety_refresh_product_audit()\n        self._safety_refresh_profiles()\n        if hasattr(self, \"dashboard_recommendation_tree\"):\n            self._refresh_intelligent_recommendations()\n        if self._last_health_report and self._last_health_report.get(\"recommendations\"):\n            text = \"\\n\".join(f\"\u2022 {r}\" for r in self._last_health_report[\"recommendations\"])\n            self.safety_recommendations.config(text=text, fg=C[\"text\"])\n        elif hasattr(self, \"safety_recommendations\"):\n            self.safety_recommendations.config(text=self._recommendations_as_text(limit=6), fg=C[\"text\"])\n\n    def _safety_refresh_menu_map(self):\n        if not hasattr(self, \"safety_menu_map_tree\"):\n            return\n        for iid in self.safety_menu_map_tree.get_children():\n            self.safety_menu_map_tree.delete(iid)\n        engine = getattr(self, \"menu_introspection_engine\", None)\n        if not engine:\n            return\n        try:\n            data = engine.scan()\n        except Exception:\n            return\n        for menu in data.get(\"menus\", []):\n            self.safety_menu_map_tree.insert(\n                \"\", \"end\",\n                values=(\n                    getattr(menu, \"category\", \"\"),\n                    getattr(menu, \"label\", \"\"),\n                    len(getattr(menu, \"tabs\", []) or []),\n                    len(getattr(menu, \"buttons\", []) or []),\n                    len(getattr(menu, \"options\", []) or []),\n                ),\n            )\n\n    def _safety_export_menu_map(self):\n        engine = getattr(self, \"menu_introspection_engine\", None)\n        if not engine:\n            messagebox.showerror(\"Menu Map\", \"Menu introspection engine is unavailable.\")\n            return\n        fpath = filedialog.asksaveasfilename(\n            defaultextension=\".md\",\n            filetypes=[(\"Markdown Report\", \"*.md\"), (\"Text Report\", \"*.txt\")],\n            title=\"Save Detected Software Menu Map\",\n        )\n        if not fpath:\n            return\n        try:\n            with open(fpath, \"w\", encoding=\"utf-8\") as f:\n                f.write(engine.to_markdown())\n            self._audit_event(\"menu_map_exported\", {\"path\": fpath})\n            messagebox.showinfo(\"Menu Map Exported\", f\"Detected software map saved:\\n\\n{fpath}\")\n            self._set_status(\"Detected software map exported.\", C[\"success\"])\n        except Exception as e:\n            messagebox.showerror(\"Export Failed\", str(e))\n\n    def _safety_refresh_profiles(self):\n        if not hasattr(self, \"safety_profile_tree\"):\n            return\n        for iid in self.safety_profile_tree.get_children():\n            self.safety_profile_tree.delete(iid)\n        engine = getattr(self, \"maintenance_profile_engine\", None)\n        if not engine:\n            return\n        for profile in engine.list_profiles():\n            self.safety_profile_tree.insert(\n                \"\", \"end\",\n                iid=profile.key,\n                values=(\n                    profile.name,\n                    str(profile.risk).upper(),\n                    profile.estimated_minutes,\n                    \", \".join(profile.menus),\n                ),\n            )\n\n    def _safety_selected_profile(self):\n        tree = getattr(self, \"safety_profile_tree\", None)\n        engine = getattr(self, \"maintenance_profile_engine\", None)\n        if not tree or not engine:\n            return None\n        sel = tree.selection()\n        if not sel:\n            messagebox.showwarning(\"Maintenance Profile\", \"Select a profile first.\")\n            return None\n        return engine.get(sel[0])\n\n    def _safety_show_selected_profile(self):\n        profile = self._safety_selected_profile()\n        if not profile:\n            return\n        msg = [\n            f\"{profile.name}\",\n            \"\",\n            profile.purpose,\n            \"\",\n            f\"Risk: {profile.risk.upper()}\",\n            f\"Estimated time: {profile.estimated_minutes} minutes\",\n            \"\",\n            \"Workflow:\",\n        ]\n        msg.extend(f\"- {action}\" for action in profile.actions)\n        msg.append(\"\")\n        msg.append(\"Protections:\")\n        msg.extend(f\"- {item}\" for item in profile.protections)\n        messagebox.showinfo(\"Guided Maintenance Profile\", \"\\n\".join(msg))\n\n    def _safety_open_selected_profile_menu(self):\n        profile = self._safety_selected_profile()\n        if not profile or not profile.menus:\n            return\n        menu_name = profile.menus[0]\n        mapping = {\n            \"Dashboard\": \"dashboard\",\n            \"Junk Cleaner\": \"cleaner\",\n            \"Safety Center\": \"safety_center\",\n            \"RAM + Services\": \"memory\",\n            \"Startup + Scheduler\": \"startup\",\n            \"Power Plan\": \"power\",\n            \"Printer + Driver\": \"printer\",\n            \"HDD/SSD + File Recovery\": \"hdd_repair\",\n            \"Event Viewer\": \"events\",\n        }\n        self._show_section(mapping.get(menu_name, \"safety_center\"))\n\n    def _safety_refresh_product_audit(self):\n        if not hasattr(self, \"safety_audit_tree\"):\n            return\n        for iid in self.safety_audit_tree.get_children():\n            self.safety_audit_tree.delete(iid)\n        engine = getattr(self, \"product_audit_engine\", None)\n        if not engine:\n            return\n        for audit in sorted(engine.list_audits(), key=lambda a: a.risk_score(), reverse=True):\n            self.safety_audit_tree.insert(\n                \"\", \"end\",\n                values=(\n                    audit.title,\n                    audit.maturity_score(),\n                    audit.risk_score(),\n                    audit.redesign_plan[0] if audit.redesign_plan else audit.final_design,\n                ),\n            )\n\n    def _safety_export_product_audit(self):\n        engine = getattr(self, \"product_audit_engine\", None)\n        if not engine:\n            messagebox.showerror(\"Audit\", \"Product audit engine is unavailable.\")\n            return\n        fpath = filedialog.asksaveasfilename(\n            defaultextension=\".md\",\n            filetypes=[(\"Markdown Report\", \"*.md\"), (\"Text Report\", \"*.txt\")],\n            title=\"Save Professional Product Audit\",\n        )\n        if not fpath:\n            return\n        try:\n            with open(fpath, \"w\", encoding=\"utf-8\") as f:\n                f.write(engine.to_markdown())\n            self._audit_event(\"product_audit_exported\", {\"path\": fpath})\n            messagebox.showinfo(\"Audit Exported\", f\"Professional product audit saved:\\n\\n{fpath}\")\n            self._set_status(\"Professional product audit exported.\", C[\"success\"])\n        except Exception as e:\n            messagebox.showerror(\"Export Failed\", str(e))\n\n    def _safety_refresh_rollback_tree(self):\n        if not hasattr(self, \"safety_rollback_tree\"):\n            return\n        for iid in self.safety_rollback_tree.get_children():\n            self.safety_rollback_tree.delete(iid)\n        vault = getattr(self, \"rollback_vault\", None)\n        if not vault:\n            return\n        for s in vault.list_sessions(40):\n            self.safety_rollback_tree.insert(\n                \"\", \"end\",\n                values=(s.get(\"id\", \"\"), s.get(\"items\", 0), s.get(\"created\", \"\")),\n            )\n\n    def _safety_refresh_sessions_tree(self):\n        if not hasattr(self, \"safety_session_tree\"):\n            return\n        for iid in self.safety_session_tree.get_children():\n            self.safety_session_tree.delete(iid)\n        mgr = getattr(self, \"recovery_session_manager\", None)\n        if not mgr:\n            return\n        for s in mgr.list_sessions(include_completed=True, limit=40):\n            self.safety_session_tree.insert(\n                \"\", \"end\",\n                values=(\n                    (s.get(\"id\", \"\") or \"\")[:12] + \"\u2026\",\n                    s.get(\"kind\", \"\"),\n                    s.get(\"status\", \"\"),\n                    s.get(\"started\", \"\"),\n                ),\n            )\n\n    def _safety_refresh_restore_points(self):\n        if not hasattr(self, \"safety_restore_tree\"):\n            return\n        for iid in self.safety_restore_tree.get_children():\n            self.safety_restore_tree.delete(iid)\n        mgr = getattr(self, \"restore_point_manager\", None)\n        if not mgr:\n            self.safety_restore_tree.insert(\"\", \"end\", values=(\"N/A\", \"Restore point manager unavailable\", \"\"))\n            return\n        points = mgr.list_recent(12)\n        if not points:\n            self.safety_restore_tree.insert(\"\", \"end\", values=(\"None\", \"No recent restore points found\", \"\"))\n            return\n        for p in points:\n            self.safety_restore_tree.insert(\n                \"\", \"end\",\n                values=(\n                    str(p.get(\"SequenceNumber\", \"\")),\n                    str(p.get(\"Description\", \"\")),\n                    str(p.get(\"Created\", \"\")),\n                ),\n            )\n\n    def _open_system_restore(self):\n        try:\n            if sys.platform != \"win32\":\n                messagebox.showwarning(\"System Restore\", \"System Restore is only available on Windows.\")\n                return\n            self._run_cmd(\"rstrui.exe\", timeout=10)\n            self._set_status(\"System Restore wizard opened.\", C[\"success\"])\n        except Exception as e:\n            messagebox.showerror(\"System Restore\", f\"Unable to open System Restore: {e}\")\n            self._set_status(\"Failed to open System Restore.\", C[\"error\"])\n\n    def _safety_refresh_timeline(self):\n        if not hasattr(self, \"safety_timeline\"):\n            return\n        logger = getattr(self, \"structured_logger\", None)\n        rows = logger.read_recent(80) if logger else []\n        self.safety_timeline.config(state=\"normal\")\n        self.safety_timeline.delete(\"1.0\", \"end\")\n        for rec in reversed(rows):\n            ts = rec.get(\"ts\", \"\")\n            action = rec.get(\"action\") or rec.get(\"type\") or rec.get(\"message\", \"\")\n            cat = rec.get(\"category\", rec.get(\"event\", \"\"))\n            line = f\"[{ts}] {cat}/{action}\\n\"\n            self.safety_timeline.insert(\"end\", line)\n        self.safety_timeline.config(state=\"disabled\")\n\n    def _safety_restore_rollback(self):\n        sel = self.safety_rollback_tree.selection() if hasattr(self, \"safety_rollback_tree\") else ()\n        if not sel:\n            messagebox.showwarning(\"Rollback\", \"Select a rollback session first.\")\n            return\n        sid = self.safety_rollback_tree.item(sel[0])[\"values\"][0]\n        if not messagebox.askyesno(\n            \"Restore Rollback\",\n            f\"Restore files/registry from session?\\n\\n{sid}\\n\\nThis overwrites current data.\",\n        ):\n            return\n        ok, msg = self.rollback_vault.restore_session(sid)\n        color = C[\"success\"] if ok else C[\"error\"]\n        messagebox.showinfo(\"Rollback\", msg)\n        self._audit_event(\"rollback_restored\", {\"session\": sid, \"ok\": ok})\n        self._set_status(msg, color)\n\n    def _safety_open_rollback_dir(self):\n        path = getattr(self, \"rollback_dir\", \"\")\n        if path and os.path.isdir(path):\n            os.startfile(path)\n        else:\n            messagebox.showinfo(\"Rollback Vault\", \"Vault folder not initialized yet.\")\n\n    def _safety_clear_session(self):\n        sel = self.safety_session_tree.selection() if hasattr(self, \"safety_session_tree\") else ()\n        if not sel:\n            messagebox.showwarning(\"Sessions\", \"Select a session row first.\")\n            return\n        short_id = str(self.safety_session_tree.item(sel[0])[\"values\"][0]).replace(\"\u2026\", \"\")\n        mgr = self.recovery_session_manager\n        for s in mgr.list_sessions(include_completed=True, limit=100):\n            if (s.get(\"id\") or \"\").startswith(short_id):\n                mgr.complete(s[\"id\"], status=\"completed\")\n                break\n        self._safety_refresh_sessions_tree()\n        self._set_status(\"Session marked completed\", C[\"success\"])\n\n    def _safety_clear_crash_marker(self):\n        try:\n            self.crash_recovery.clear_running()\n            self._log(\"Crash recovery marker cleared silently.\", \"OK\")\n            self._set_status(\"Crash recovery marker cleared\", C[\"success\"])\n        except Exception as e:\n            messagebox.showerror(\"Error\", str(e))\n\n    def _build_activation(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udd11 Windows Activation\", \"Real status check + legal activation actions\")\n        top = tk.Frame(frame, bg=C[\"card\"])\n        top.pack(fill=\"x\", padx=16, pady=10)\n        self.activation_status_lbl = tk.Label(\n            top, text=\"Activation status: checking...\",\n            font=FONTS[\"subhead\"], fg=C[\"accent4\"], bg=C[\"card\"], anchor=\"w\", justify=\"left\"\n        )\n        self.activation_status_lbl.pack(fill=\"x\", padx=10, pady=(8, 4))\n        self.activation_detail_lbl = tk.Label(\n            top, text=\"\",\n            font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], anchor=\"w\", justify=\"left\", wraplength=900\n        )\n        self.activation_detail_lbl.pack(fill=\"x\", padx=10, pady=(0, 8))\n\n        key_row = tk.Frame(top, bg=C[\"card\"])\n        key_row.pack(fill=\"x\", padx=10, pady=(0, 8))\n        tk.Label(key_row, text=\"Product Key (XXXXX-XXXXX-XXXXX-XXXXX-XXXXX):\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\", padx=(0, 8))\n        self.activation_key_entry = tk.Entry(key_row, width=40, font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"])\n        self.activation_key_entry.pack(side=\"left\", padx=(0, 8))\n        self._btn(key_row, \"Install Key\", C[\"btn_warn\"], self._activation_install_key).pack(side=\"left\", padx=4)\n        self._btn(key_row, \"Activate Online\", C[\"btn_info\"], self._activation_online).pack(side=\"left\", padx=4)\n\n        self._action_card_grid(frame, [\n            (\"\ud83d\udd04\", \"Refresh Status\",         \"Activation status check karo\",     C[\"btn\"],      self._refresh_activation_status),\n            (\"\u2699\",  \"Open Settings\",          \"Windows activation settings kholo\",C[\"btn_info\"], self._open_activation_settings),\n        ], cols=2)\n\n        log_wrap = tk.Frame(frame, bg=C[\"card\"])\n        log_wrap.pack(fill=\"both\", expand=True, padx=16, pady=(0, 10))\n        tk.Label(log_wrap, text=\"  Activation Log\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8, 4), padx=8)\n        self.activation_log = self._scrolled_text(log_wrap, height=16)\n        self.after(100, self._refresh_activation_status)\n        return frame\n\n    def _refresh_activation_status(self):\n        self._set_status(\"Checking Windows activation status...\", C[\"accent4\"])\n        self._launch_job(\"activation_status_refresh\", self._do_refresh_activation_status)\n\n    def _do_refresh_activation_status(self):\n        try:\n            ps_cmd = (\n                'powershell -NoProfile -ExecutionPolicy Bypass -Command \"'\n                '$lic=Get-CimInstance SoftwareLicensingProduct | '\n                'Where-Object {$_.PartialProductKey -and $_.ApplicationID -eq ''55c92734-d682-4d71-983e-d6ec3f16059f''} | '\n                'Select-Object -First 1 Name,Description,LicenseStatus,PartialProductKey; '\n                'if($lic){'\n                '$map=@{0=''Unlicensed'';1=''Licensed'';2=''OOBGrace'';3=''OOTGrace'';4=''NonGenuineGrace'';5=''Notification'';6=''ExtendedGrace''}; '\n                '$status=if($map.ContainsKey([int]$lic.LicenseStatus)){$map[[int]$lic.LicenseStatus]}else{''Unknown''}; '\n                'Write-Output (''STATUS=''+$status); '\n                'Write-Output (''NAME=''+$lic.Name); '\n                'Write-Output (''CHANNEL=''+$lic.Description); '\n                'Write-Output (''PARTIAL=''+$lic.PartialProductKey)'\n                '} else { Write-Output ''STATUS=Unknown'' }\"'\n            )\n            out, code = self._run_cmd(ps_cmd, timeout=90)\n            status_line = \"Unknown\"\n            name_line = \"\"\n            channel_line = \"\"\n            partial_line = \"\"\n            for ln in (out or \"\").splitlines():\n                s = ln.strip()\n                if s.startswith(\"STATUS=\"):\n                    status_line = s.split(\"=\", 1)[1].strip() or \"Unknown\"\n                elif s.startswith(\"NAME=\"):\n                    name_line = s.split(\"=\", 1)[1].strip()\n                elif s.startswith(\"CHANNEL=\"):\n                    channel_line = s.split(\"=\", 1)[1].strip()\n                elif s.startswith(\"PARTIAL=\"):\n                    partial_line = s.split(\"=\", 1)[1].strip()\n\n            color = C[\"warning\"]\n            if status_line.lower() == \"licensed\":\n                color = C[\"success\"]\n            elif status_line.lower() in (\"notification\", \"unlicensed\", \"nongenuinegrace\"):\n                color = C[\"error\"]\n\n            detail_parts = []\n            if name_line:\n                detail_parts.append(f\"Edition: {name_line}\")\n            if channel_line:\n                detail_parts.append(f\"Channel: {channel_line}\")\n            if partial_line:\n                detail_parts.append(f\"Partial key: *****-*****-*****-*****-{partial_line}\")\n            if code not in (0, None):\n                detail_parts.append(f\"(Status command exit code: {code})\")\n            details = \"\\n\".join(detail_parts) if detail_parts else \"No detailed activation data available.\"\n\n            self.after(0, lambda: self.activation_status_lbl.config(text=f\"Activation status: {status_line}\", fg=color))\n            self.after(0, lambda: self.activation_detail_lbl.config(text=details))\n            self.after(0, lambda: self._append_log(self.activation_log, f\"Status refreshed: {status_line}\", color))\n            self.after(0, lambda: self._set_status(\"Activation status updated\", C[\"success\"]))\n        except Exception as e:\n            self.after(0, lambda: self._append_log(self.activation_log, f\"Status check failed: {e}\", C[\"error\"]))\n            self.after(0, lambda: self._set_status(\"Activation status check failed\", C[\"error\"]))\n\n    def _activation_install_key(self):\n        key = (self.activation_key_entry.get() if hasattr(self, \"activation_key_entry\") else \"\").strip().upper()\n        if not re.match(r\"^[A-Z0-9]{5}(?:-[A-Z0-9]{5}){4}$\", key):\n            messagebox.showerror(\"Invalid Key\", \"Valid 25-char key format enter karein:\\nXXXXX-XXXXX-XXXXX-XXXXX-XXXXX\")\n            return\n        if not messagebox.askyesno(\"Install Product Key\", f\"Install this key?\\n\\n{key}\\n\\nProceed only if this is your legal license key.\"):\n            return\n        self._set_status(\"Installing product key...\", C[\"accent4\"])\n        self._launch_job(\"activation_install_key\", self._do_activation_install_key, key)\n\n    def _do_activation_install_key(self, key):\n        cmd = f'cscript //nologo \"%windir%\\\\system32\\\\slmgr.vbs\" /ipk {key}'\n        out, code = self._run_cmd(cmd, timeout=180)\n        color = C[\"success\"] if code == 0 else C[\"error\"]\n        msg = out.strip() if out else (\"Product key installed.\" if code == 0 else \"Product key install failed.\")\n        self.after(0, lambda: self._append_log(self.activation_log, msg, color))\n        self.after(0, lambda: self._set_status(\"Product key installed\" if code == 0 else \"Product key install failed\", color))\n        if code == 0:\n            self.after(500, self._refresh_activation_status)\n\n    def _activation_online(self):\n        if not messagebox.askyesno(\"Activate Windows\", \"Try online activation now? Internet connection required.\"):\n            return\n        self._set_status(\"Activating Windows...\", C[\"accent4\"])\n        self._launch_job(\"activation_online\", self._do_activation_online)\n\n    def _do_activation_online(self):\n        cmd = 'cscript //nologo \"%windir%\\\\system32\\\\slmgr.vbs\" /ato'\n        out, code = self._run_cmd(cmd, timeout=240)\n        color = C[\"success\"] if code == 0 else C[\"error\"]\n        msg = out.strip() if out else (\"Activation attempt finished.\" if code == 0 else \"Activation attempt failed.\")\n        self.after(0, lambda: self._append_log(self.activation_log, msg, color))\n        self.after(0, lambda: self._set_status(\"Activation completed\" if code == 0 else \"Activation failed\", color))\n        self.after(500, self._refresh_activation_status)\n\n    def _open_activation_settings(self):\n        out, code = self._run_cmd(\"start ms-settings:activation\")\n        if code == 0:\n            self._append_log(self.activation_log, \"Opened Windows Activation settings.\", C[\"success\"])\n        else:\n            self._append_log(self.activation_log, f\"Could not open settings: {out}\", C[\"error\"])\n\n    def _live_speed_test(self):\n        self._set_status(\"Checking Internet Speed...\", C[\"accent4\"])\n        self._launch_job(\"speed_test\", self._do_speed_test)\n\n    def _do_speed_test(self):\n        import urllib.request\n        import urllib.error\n        targets = [\n            (\"http://speedtest.tele2.net/10MB.zip\", 10),\n            (\"http://ipv4.download.thinkbroadband.com/10MB.zip\", 10),\n            (\"http://proof.ovh.net/files/10Mb.dat\", 10),\n            (\"http://speedtest.tele2.net/1MB.zip\", 1),\n        ]\n        tmp_file = os.path.join(tempfile.gettempdir(), \"godawari_speedtest.tmp\")\n        self._log(\"Starting internet speed test...\", \"INFO\")\n        self._set_status(\"Running speed test...\", C[\"accent4\"])\n        for url, expected_mb in targets:\n            try:\n                start = time.perf_counter()\n                with urllib.request.urlopen(url, timeout=30) as response, open(tmp_file, \"wb\") as out_file:\n                    downloaded = 0\n                    while True:\n                        chunk = response.read(65536)\n                        if not chunk:\n                            break\n                        out_file.write(chunk)\n                        downloaded += len(chunk)\n                elapsed = time.perf_counter() - start\n                if elapsed &lt; 0.1:\n                    continue\n                actual_mb = downloaded / (1024 * 1024)\n                speed_mbps = (actual_mb * 8) / elapsed\n                try:\n                    os.remove(tmp_file)\n                except Exception:\n                    pass\n                msg = (f\"\u2705 Download Speed: {speed_mbps:.2f} Mbps \"\n                       f\"({actual_mb:.1f} MB in {elapsed:.1f}s from {url.split('/')[2]})\")\n                self._set_status(msg, C[\"success\"])\n                self._log(msg, \"OK\")\n                return speed_mbps\n            except Exception as e:\n                self._log(f\"Speed test URL failed ({url}): {e}\", \"WARN\")\n                continue\n        self._set_status(\"Speed test failed \u2014 Internet check karo\", C[\"error\"])\n        self._log(\"All speed test URLs failed.\", \"ERR\")\n        return 0.0\n\n    def _refresh_dashboard(self):\n        def task():\n            try:\n                cpu = psutil.cpu_percent(interval=None)\n                vm = psutil.virtual_memory()\n                du = psutil.disk_usage(\"/\")\n                up = time.time() - psutil.boot_time()\n                up_str = str(datetime.timedelta(seconds=int(up)))\n                self.dash_cards[\"cpu\"]._value_lbl.config(text=f\"{cpu:.1f}%\")\n                self.dash_cards[\"cpu\"]._bar.config(value=cpu)\n                self.dash_cards[\"ram\"]._value_lbl.config(text=f\"{vm.percent:.1f}%\")\n                self.dash_cards[\"ram\"]._bar.config(value=vm.percent)\n                self.dash_cards[\"disk\"]._value_lbl.config(text=f\"{du.percent:.1f}%\")\n                self.dash_cards[\"disk\"]._bar.config(value=du.percent)\n                self.dash_cards[\"uptime\"]._value_lbl.config(text=up_str)\n                if hasattr(self, \"dashboard_workflow_lbl\"):\n                    report = getattr(self, \"_last_health_report\", None)\n                    if report:\n                        score = report.get(\"score\")\n                        recs = report.get(\"recommendations\", []) or []\n                        rollout = [f\"Health {score}/100\" if score is not None else \"Health scan ready\"]\n                        if recs:\n                            rollout.append(f\"{len(recs)} action(s) ready\")\n                            rollout.append(recs[0])\n                        self.dashboard_workflow_lbl.config(text=\" \u2022 \".join(rollout), fg=C[\"text\"])\n                    else:\n                        self.dashboard_workflow_lbl.config(\n                            text=\"Health scan not run yet \u2014 use One-Click Health Scan or Safety Center to generate guided actions.\",\n                            fg=C[\"text_dim\"],\n                        )\n                for item in self.proc_tree.get_children():\n                    self.proc_tree.delete(item)\n                procs = sorted(psutil.process_iter(['pid','name','cpu_percent','memory_info','status']),\n                               key=lambda p: p.info.get('cpu_percent',0) or 0, reverse=True)\n                for p in procs[:25]:\n                    try:\n                        mem = round((p.info.get('memory_info') or psutil.Process(p.info['pid']).memory_info()).rss / (1024**2), 1)\n                        self.proc_tree.insert(\"\", \"end\", values=(p.info['pid'], p.info['name'] or \"?\", f\"{p.info.get('cpu_percent',0):.1f}%\", f\"{mem} MB\", p.info.get('status','?')))\n                    except:\n                        pass\n            except Exception as e:\n                self._log(str(e), \"ERR\")\n        self._launch_job(\"dashboard_refresh\", task)\n\n    def _start_real_time_graph(self):\n        def update_graph():\n            try:\n                cpu = psutil.cpu_percent(interval=None)\n                ram = psutil.virtual_memory().percent\n                self.graph_data[\"cpu\"].append(cpu)\n                self.graph_data[\"ram\"].append(ram)\n                if len(self.graph_data[\"cpu\"]) &gt; 60:\n                    self.graph_data[\"cpu\"].pop(0)\n                    self.graph_data[\"ram\"].pop(0)\n                self._draw_graph()\n            except:\n                pass\n            self.after(2000, update_graph)\n        update_graph()\n\n    def _draw_graph(self):\n        try:\n            self.graph_canvas.delete(\"all\")\n            w = self.graph_canvas.winfo_width()\n            h = 80\n            if w &lt; 10:\n                return\n            n = len(self.graph_data[\"cpu\"])\n            if n &lt; 2:\n                return\n            step = w / max(1, n - 1)\n            cpu_pts = [(i*step, h - (self.graph_data[\"cpu\"][i]/100)*h) for i in range(n)]\n            ram_pts = [(i*step, h - (self.graph_data[\"ram\"][i]/100)*h) for i in range(n)]\n            self.graph_canvas.create_line(cpu_pts, fill=C[\"accent\"], width=2, smooth=True)\n            self.graph_canvas.create_line(ram_pts, fill=C[\"success\"], width=2, smooth=True)\n            self.graph_canvas.create_text(5, 5, anchor=\"nw\", text=f\"CPU (Gold): {self.graph_data['cpu'][-1]:.1f}%  |  RAM (Green): {self.graph_data['ram'][-1]:.1f}%\",\n                                          fill=C[\"text_dim\"], font=FONTS[\"small\"])\n        except:\n            pass\n\n    # ---------- SHOP MODE ----------\n    def _build_shop_mode(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udee0 Repair Shop Mode\", \"Real Customer diagnosis &amp; tune-up\")\n        top = tk.Frame(frame, bg=C[\"card\"])\n        top.pack(fill=\"x\", padx=16, pady=8)\n        self.shop_customer_name = tk.Entry(top, width=24, font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"])\n        self.shop_customer_mobile = tk.Entry(top, width=18, font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"])\n        self.shop_issue = tk.Entry(top, width=55, font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"])\n        for label, widget in [(\"Customer\", self.shop_customer_name), (\"Mobile\", self.shop_customer_mobile), (\"Issue\", self.shop_issue)]:\n            tk.Label(top, text=label, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\", padx=(8,3))\n            widget.pack(side=\"left\", padx=(0,8), pady=8)\n        self.shop_issue.insert(0, \"System hang / slow\")\n        self._action_card_grid(frame, [\n            (\"\u25b6\",  \"Start Job\",              \"Naya customer job shuru karo\",               C[\"btn_info\"],   self._shop_start_job),\n            (\"\ud83d\udd0d\", \"Diagnose Slow PC\",        \"CPU, RAM, Startup, Disk check\",              C[\"btn_danger\"], self._shop_slow_pc_diagnosis),\n            (\"\u26a1\", \"One-Click Tune-Up\",       \"Cache clear + RAM boost + Restore point\",    C[\"btn_warn\"],   self._shop_one_click_tuneup),\n            (\"\ud83d\udd34\", \"Malware + Driver Scan\",   \"Malware scan + Driver repair ek saath\",      C[\"btn_chip\"],   self._shop_malware_driver_combo),\n            (\"\ud83d\udcbe\", \"Disk Health + Backup\",    \"SMART check + Backup combo\",                 C[\"btn_danger\"], self._shop_disk_backup_combo),\n            (\"\ud83c\udf10\", \"Browser + Update Repair\", \"Browser reset + Windows update fix\",         C[\"btn_info\"],   self._shop_browser_update_combo),\n            (\"\u2699\",  \"Service Preset Apply\",   \"Recommended service config lagao\",           C[\"btn_hw\"],     self._shop_service_preset),\n            (\"\ud83d\udcc4\", \"Export Customer Report\",  \"Customer job report save karo\",              C[\"accent2\"],    self._shop_export_customer_report),\n        ], cols=5)\n        self.shop_log = self._scrolled_text(frame, height=23)\n        self.shop_findings = []\n        return frame\n\n    def _shop_start_job(self):\n        self.shop_findings = []\n        self.shop_log.config(state=\"normal\")\n        self.shop_log.delete(\"1.0\",\"end\")\n        self.shop_log.config(state=\"disabled\")\n        self._shop_log(f\"Job started | Customer: {self.shop_customer_name.get()} | Issue: {self.shop_issue.get()}\", \"OK\")\n\n    def _shop_log(self, msg, level=\"INFO\"):\n        color = {\"INFO\": C[\"text\"], \"OK\": C[\"success\"], \"WARN\": C[\"warning\"], \"ERR\": C[\"error\"]}.get(level, C[\"text\"])\n        line = f\"[{datetime.datetime.now().strftime('%H:%M:%S')}] {msg}\"\n        self.shop_findings.append(line)\n        self._append_log(self.shop_log, line, color)\n        self._log(msg, level)\n\n    def _shop_slow_pc_diagnosis(self):\n        self._shop_log(\"\ud83d\udd0d Slow PC Auto Diagnosis started...\", \"INFO\")\n        self._launch_job(\"shop_slow_pc_diagnosis\", self._do_shop_slow_pc_diagnosis)\n\n    def _do_shop_slow_pc_diagnosis(self):\n        self._shop_log(\"1. Checking CPU &amp; RAM Load...\", \"INFO\")\n        cpu = psutil.cpu_percent(interval=None)\n        ram = psutil.virtual_memory()\n        if cpu &gt; 80:\n            self._shop_log(f\"   \u26a0 HIGH CPU USAGE DETECTED: {cpu}%\", \"ERR\")\n        else:\n            self._shop_log(f\"   \u2705 CPU Usage Normal: {cpu}%\", \"OK\")\n        if ram.percent &gt; 85:\n            self._shop_log(f\"   \u26a0 HIGH RAM USAGE DETECTED: {ram.percent}% (Free: {self._fmt_size(ram.available)})\", \"ERR\")\n        else:\n            self._shop_log(f\"   \u2705 RAM Usage Normal: {ram.percent}%\", \"OK\")\n        self._shop_log(\"2. Checking Startup Bloatwares...\", \"INFO\")\n        bloat_count = 0\n        try:\n            key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, r\"Software\\Microsoft\\Windows\\CurrentVersion\\Run\", 0, winreg.KEY_READ)\n            i = 0\n            while True:\n                try:\n                    name, value, _ = winreg.EnumValue(key, i)\n                    if any(x in value.lower() for x in ['zoom', 'skype', 'spotify', 'discord', 'teams']):\n                        self._shop_log(f\"   \u26a0 Bloatware Found: {name}\", \"WARN\")\n                        bloat_count += 1\n                    i += 1\n                except OSError:\n                    break\n            winreg.CloseKey(key)\n        except:\n            pass\n        if bloat_count == 0:\n            self._shop_log(\"   \u2705 No major bloatware in startup\", \"OK\")\n        self._shop_log(\"3. Checking Disk Health (SMART)...\", \"INFO\")\n        out, _ = self._run_cmd(\"wmic diskdrive get status,model /format:list\")\n        if \"OK\" in out:\n            self._shop_log(\"   \u2705 Disk SMART Status: OK\", \"OK\")\n        else:\n            self._shop_log(f\"   \u26a0 Disk Status Check: {out[:100]}\", \"WARN\")\n        self._shop_log(\"\ud83c\udf89 Diagnosis Complete!\", \"OK\")\n\n    def _shop_one_click_tuneup(self):\n        if messagebox.askyesno(\"One Click Shop Tune-Up\", \"Restore point + cache clear + RAM boost run karna hai?\"):\n            if self._create_restore_point(\"One Click Shop Tune-Up se pehle\"):\n                self._shop_log(\"One Click Tune-Up started\", \"INFO\")\n                self._launch_job(\"shop_tuneup\", self._do_shop_tuneup)\n\n    def _do_shop_tuneup(self):\n        self._shop_log(\"Step 1: Clearing Temp Files...\", \"INFO\")\n        self._delete_folder_contents(os.environ.get(\"TEMP\", \"\"))\n        self._delete_folder_contents(r\"C:\\Windows\\Temp\")\n        self._shop_log(\"Step 2: Boosting RAM...\", \"INFO\")\n        gc.collect()\n        try:\n            kernel32 = ctypes.windll.kernel32\n            psapi = ctypes.windll.psapi\n            for proc in psutil.process_iter(['pid']):\n                pid = proc.info.get('pid')\n                if pid and pid not in (0,4):\n                    handle = kernel32.OpenProcess(0x0400|0x0100|0x0010, False, int(pid))\n                    if handle:\n                        psapi.EmptyWorkingSet(handle)\n                        kernel32.CloseHandle(handle)\n        except:\n            pass\n        self._shop_log(\"Step 3: Disabling heavy services...\", \"INFO\")\n        self._run_cmd('sc stop \"SysMain\"')\n        self._shop_log(\"\u2705 Tune-Up complete!\", \"OK\")\n\n    def _shop_malware_pup_scan(self):\n        self._shop_log(\"\ud83d\udd0d Scanning for Malware Clues &amp; PUPs...\", \"INFO\")\n        self._launch_job(\"shop_malware_scan\", self._do_malware_scan)\n\n    def _do_malware_scan(self):\n        suspicious_exts = ['.exe', '.bat', '.cmd', '.ps1', '.vbs', '.js']\n        risk_paths = [os.environ.get('TEMP', ''), os.environ.get('APPDATA', ''), os.path.join(os.environ.get('LOCALAPPDATA', ''), 'Temp')]\n        threats = 0\n        for r_path in risk_paths:\n            if not os.path.exists(r_path):\n                continue\n            for root, dirs, files in os.walk(r_path):\n                if threats &gt; 20:\n                    break\n                for f in files:\n                    if os.path.splitext(f)[1].lower() in suspicious_exts:\n                        full_path = os.path.join(root, f)\n                        if 'microsoft' in full_path.lower():\n                            continue\n                        self._shop_log(f\"\u26a0 Suspicious Script/Exe: {full_path}\", \"WARN\")\n                        threats += 1\n        if threats == 0:\n            self._shop_log(\"\u2705 No immediate Malware/PUP clues found.\", \"OK\")\n        else:\n            self._shop_log(f\"\u26a0 Found {threats} suspicious files. Delete them manually from paths above.\", \"ERR\")\n\n    def _shop_disk_health_risk(self):\n        self._shop_log(\"Checking Disk Health...\", \"INFO\")\n        out, _ = self._run_cmd(\"wmic diskdrive get model,status,size,mediaType /format:list\")\n        self._shop_log(out[:500], \"OK\")\n\n    def _shop_customer_backup(self):\n        dest = filedialog.askdirectory(title=\"Select Backup Destination Folder\")\n        if dest:\n            self._launch_job(\"shop_customer_backup\", self._do_customer_backup, dest)\n\n    def _do_customer_backup(self, dest):\n        self._shop_log(\"Backing up Desktop, Documents, Pictures...\", \"INFO\")\n        user_profile = os.environ.get(\"USERPROFILE\", \"\")\n        total_files = 0\n        for folder in [\"Desktop\", \"Documents\", \"Pictures\", \"Downloads\"]:\n            src = os.path.join(user_profile, folder)\n            if os.path.exists(src):\n                try:\n                    dst = os.path.join(dest, folder)\n                    if os.path.exists(dst):\n                        shutil.rmtree(dst)\n                    shutil.copytree(src, dst)\n                    count = sum(len(files) for _, _, files in os.walk(dst))\n                    total_files += count\n                    self._shop_log(f\"\u2705 Backed up {folder} ({count} files)\", \"OK\")\n                except Exception as e:\n                    self._shop_log(f\"\u274c Failed {folder}: {e}\", \"ERR\")\n        self._shop_log(f\"\ud83c\udf89 Backup Complete! Total Files Saved: {total_files}\", \"OK\")\n\n    def _shop_driver_repair_pack(self):\n        self._shop_log(\"Exporting list of non-microsoft drivers...\", \"INFO\")\n        out, _ = self._run_cmd('driverquery /FO CSV /V')\n        lines = [l for l in out.splitlines() if \"Microsoft\" not in l]\n        fpath = os.path.join(os.path.expanduser(\"~\"), \"Desktop\", \"Godawari_Drivers_List.csv\")\n        with open(fpath, \"w\") as f:\n            f.write(\"\\n\".join(lines))\n        self._shop_log(f\"\u2705 Driver list saved to Desktop\", \"OK\")\n\n    def _shop_windows_update_repair(self):\n        self._shop_log(\"Resetting Windows Update Components...\", \"INFO\")\n        self._launch_job(\"shop_wu_repair\", self._do_wu_repair)\n\n    def _do_wu_repair(self):\n        cmds = ['net stop wuauserv', 'net stop bits', r'ren %systemroot%\\SoftwareDistribution SoftwareDistribution.bak', r'ren %systemroot%\\system32\\catroot2 catroot2.bak', 'net start wuauserv', 'net start bits']\n        for cmd in cmds:\n            self._run_cmd(cmd)\n        self._shop_log(\"\u2705 Windows Update Repair Done.\", \"OK\")\n\n    def _shop_browser_repair(self):\n        self._shop_log(\"Killing browsers and clearing caches...\", \"INFO\")\n        for exe in [\"chrome\",\"msedge\",\"firefox\"]:\n            self._run_cmd(f'taskkill /IM {exe}.exe /F')\n        local = os.environ.get(\"LOCALAPPDATA\",\"\")\n        for p in [os.path.join(local,\"Google\\\\Chrome\\\\User Data\\\\Default\\\\Cache\"), os.path.join(local,\"Microsoft\\\\Edge\\\\User Data\\\\Default\\\\Cache\")]:\n            self._delete_folder_contents(p)\n        self._shop_log(\"\u2705 Browser Repair done.\", \"OK\")\n\n    def _shop_service_preset(self):\n        results = [\n            self._service_config_checked(\"SysMain\", \"disabled\"),\n            self._service_stop_checked(\"SysMain\"),\n        ]\n        summary = self._action_summary(\"Service Preset\", results)\n        self._shop_log(\"Already done: Service Preset\" if summary[\"already_done\"] else \"Service Preset Applied.\", \"OK\")\n\n    def _shop_export_customer_report(self):\n        fpath = filedialog.asksaveasfilename(defaultextension=\".html\", filetypes=[(\"HTML Report\",\"*.html\")])\n        if fpath:\n            html = f\"\"\"Godawari Shop Reportbody{{font-family:Arial;background:#f4f4f4;padding:20px}}.box{{background:white;padding:15px;margin:10px 0;border-radius:5px;box-shadow:1px 1px 3px grey}}\n            \nGodawari Computers - Customer Report\n\nCustomer: {self.shop_customer_name.get()}\nIssue: {self.shop_issue.get()}\nDate: {datetime.datetime.now()}\n            \n\nDiagnosis Findings:\n{''.join(self.shop_findings)}\"\"\"\n            with open(fpath,\"w\", encoding=\"utf-8\") as f:\n                f.write(html)\n            self._shop_log(f\"Report exported: {fpath}\", \"OK\")\n            os.startfile(fpath)\n\n    def _shop_malware_driver_combo(self):\n        \"\"\"Malware scan + Driver repair \u2014 dono ek saath\"\"\"\n        self._shop_malware_pup_scan()\n        self.after(500, self._shop_driver_repair_pack)\n\n    def _shop_disk_backup_combo(self):\n        \"\"\"Disk health check + Customer backup \u2014 dono ek saath\"\"\"\n        self._shop_disk_health_risk()\n        self.after(500, self._shop_customer_backup)\n\n    def _shop_browser_update_combo(self):\n        \"\"\"Browser repair + Windows update repair \u2014 dono ek saath\"\"\"\n        self._shop_browser_repair()\n        self.after(500, self._shop_windows_update_repair)\n\n    # ---------- PROFESSIONAL JUNK CLEANER ----------\n    def _build_cleaner(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83e\uddf9 Professional Junk Cleaner\", \"Real file deletion + exact before/after stats\")\n        content = tk.Frame(frame, bg=C[\"bg\"])\n        content.pack(fill=\"both\", expand=True, padx=16, pady=10)\n        content.columnconfigure(0, weight=1)\n        content.columnconfigure(1, weight=2)\n        content.rowconfigure(0, weight=1)\n        # \u2500\u2500 Scrollable left panel (Canvas + Scrollbar) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        left_outer = tk.Frame(content, bg=C[\"card\"])\n        left_outer.grid(row=0, column=0, sticky=\"nsew\", padx=(0, 6))\n\n        left_canvas = tk.Canvas(left_outer, bg=C[\"card\"], highlightthickness=0)\n        left_vsb    = ttk.Scrollbar(left_outer, orient=\"vertical\", command=left_canvas.yview)\n        left_canvas.configure(yscrollcommand=left_vsb.set)\n        left_vsb.pack(side=\"right\", fill=\"y\")\n        left_canvas.pack(side=\"left\", fill=\"both\", expand=True)\n\n        left = tk.Frame(left_canvas, bg=C[\"card\"])\n        left_window = left_canvas.create_window((0, 0), window=left, anchor=\"nw\")\n\n        def _left_configure(e):\n            left_canvas.configure(scrollregion=left_canvas.bbox(\"all\"))\n        def _left_canvas_resize(e):\n            left_canvas.itemconfig(left_window, width=e.width)\n            left_canvas.configure(scrollregion=left_canvas.bbox(\"all\"))\n\n        left.bind(\"\",        _left_configure)\n        left_canvas.bind(\"\", _left_canvas_resize)\n\n        self._bind_scoped_mousewheel(left, left_canvas)\n        # \u2500\u2500 Contents of scrollable left panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        tk.Label(left, text=\"  Scan Targets\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8,4), padx=8)\n        targets = [(\"temp\",\"Windows Temp\"),(\"user_temp\",\"User Temp\"),(\"prefetch\",\"Prefetch\"),(\"recycle\",\"Recycle Bin\"),(\"logs\",\"Windows Logs\"),(\"thumbnail\",\"Thumbnail Cache\"),(\"update\",\"WU Cache\"),(\"dumps\",\"Memory Dumps\"),(\"errreport\",\"Error Reports\"),(\"browser_office\",\"Browser/MS Office Caches\"), (\"delivery\",\"Delivery Optimization Cache\")]\n        for k, label in targets:\n            var = tk.BooleanVar(value=True)\n            self.clean_vars[k] = var\n            cb = tk.Checkbutton(left, text=f\"  {label}\", variable=var, font=FONTS[\"body\"], fg=C[\"text\"], bg=C[\"card\"], activebackground=C[\"card\"], selectcolor=C[\"panel\"], bd=0)\n            cb.pack(anchor=\"w\", padx=12, pady=2)\n        self._action_card_grid(left, [\n            (\"\ud83d\udd0d\", \"Scan Junk\",   \"Kitna junk hai scan karo\",     C[\"btn_info\"],   self._professional_scan),\n            (\"\ud83d\uddd1\",  \"Delete Junk\",\"Junk files delete karo\",        C[\"btn_danger\"], self._professional_clean),\n        ], cols=2)\n        # profiles + large file finder\n        prof = tk.Frame(left, bg=C[\"card\"])\n        prof.pack(fill=\"x\", padx=12, pady=(2, 6))\n        tk.Label(prof, text=\"Profile:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        cleaner_profiles = get_cleaner_profiles()\n        self.clean_profile_var = tk.StringVar(value=\"Office Home\")\n        ttk.Combobox(prof, values=list(cleaner_profiles.keys()), textvariable=self.clean_profile_var,\n                     width=16, font=FONTS[\"small\"], state=\"readonly\").pack(side=\"left\", padx=6)\n        self._btn(prof, \"Apply\", C[\"btn_chip\"], self._apply_clean_profile).pack(side=\"left\", padx=4)\n        self._btn(prof, \"\ud83d\udce6 Large Files (Top 50)\", C[\"btn_warn\"], self._large_file_finder_dialog).pack(side=\"right\", padx=2)\n        self.clean_profile_summary_var = tk.StringVar(value=cleaner_profiles[\"Office Home\"][\"summary\"])\n        self.clean_profile_summary_lbl = tk.Label(left, textvariable=self.clean_profile_summary_var, font=FONTS[\"xsmall\"], fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=340, justify=\"left\")\n        self.clean_profile_summary_lbl.pack(anchor=\"w\", padx=12, pady=(0, 4))\n        self.clean_size_lbl = tk.Label(left, text=\"Total junk found: --\", font=FONTS[\"small\"], fg=C[\"accent4\"], bg=C[\"card\"])\n        self.clean_size_lbl.pack(padx=12, pady=4, anchor=\"w\")\n        self.clean_progress_var = tk.DoubleVar(value=0.0)\n        self.clean_progress_bar = ttk.Progressbar(left, variable=self.clean_progress_var, maximum=100.0, mode=\"determinate\")\n        self.clean_progress_bar.pack(fill=\"x\", padx=12, pady=(0,4))\n        self.clean_progress_lbl = tk.Label(left, text=\"Ready\", font=FONTS[\"xsmall\"], fg=C[\"text_dim\"], bg=C[\"card\"])\n        self.clean_progress_lbl.pack(padx=12, pady=(0,8), anchor=\"w\")\n        ctrl = tk.Frame(left, bg=C[\"card\"])\n        ctrl.pack(fill=\"x\", padx=12, pady=(0,4))\n        self.clean_preview_var = tk.BooleanVar(value=False)\n        prev_cb = tk.Checkbutton(ctrl, text=\"Preview deletions only\", variable=self.clean_preview_var,\n                       font=FONTS[\"xsmall\"], fg=C[\"text\"], bg=C[\"card\"], activebackground=C[\"card\"],\n                       selectcolor=C[\"panel\"], bd=0)\n        prev_cb.pack(side=\"left\", anchor=\"w\")\n        button_row = tk.Frame(left, bg=C[\"card\"])\n        button_row.pack(fill=\"x\", padx=12, pady=(0,6))\n        self.clean_report_btn = self._btn(button_row, \"Export Report\", C[\"btn_chip\"], self._export_clean_report)\n        self.clean_report_btn.pack(side=\"right\", padx=2)\n        self.clean_cancel_btn = self._btn(button_row, \"Cancel\", C[\"btn_warn\"], self._cancel_clean_job)\n        self.clean_cancel_btn.pack(side=\"right\", padx=2)\n        self.clean_cancel_btn.config(state=\"disabled\")\n        self.clean_report_btn.config(state=\"disabled\")\n\n        # \u2500\u2500 Browser Boost Button \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        browser_sep = tk.Frame(left, bg=C[\"border\"], height=1)\n        browser_sep.pack(fill=\"x\", padx=12, pady=(8, 4))\n        browser_boost_btn = tk.Button(\n            left,\n            text=\"\ud83c\udf10  Super Boost All Browsers\",\n            font=(\"Segoe UI\", 10, \"bold\"),\n            bg=\"#1a6b3a\", fg=C[\"text\"],\n            bd=0, padx=14, pady=10,\n            cursor=\"hand2\", relief=\"flat\",\n            activebackground=\"#238636\",\n            command=self._open_browser_boost_window,\n        )\n        browser_boost_btn.pack(fill=\"x\", padx=12, pady=(0, 4))\n\n        adv_boost_btn = tk.Button(\n            left,\n            text=\"\u26a1 Advanced Browser Launch Flags\",\n            font=(\"Segoe UI\", 10, \"bold\"),\n            bg=\"#2f6f97\", fg=C[\"text\"],\n            bd=0, padx=14, pady=10,\n            cursor=\"hand2\", relief=\"flat\",\n            activebackground=\"#3f8fb7\",\n            command=self._open_browser_speed_flags_window,\n        )\n        adv_boost_btn.pack(fill=\"x\", padx=12, pady=(0, 4))\n\n        extra_sep = tk.Frame(left, bg=C[\"border\"], height=1)\n        extra_sep.pack(fill=\"x\", padx=12, pady=(8, 4))\n        tk.Label(left, text=\"  Cleanup Extras\", font=FONTS[\"small\"], fg=C[\"accent2\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=12, pady=(0,4))\n        self._btn(left, \"\ud83d\udcc1 Find Empty Folders\", C[\"btn_info\"], self._open_empty_folder_finder).pack(fill=\"x\", padx=12, pady=2)\n        self._btn(left, \"0-byte File Scanner\", C[\"btn_warn\"], self._open_zero_byte_finder).pack(fill=\"x\", padx=12, pady=2)\n\n        hint_lbl = tk.Label(\n            left,\n            text=\"  Chrome \u2022 Edge \u2022 Brave \u2022 Opera \u2022 Firefox \u2014 deep clean\",\n            font=FONTS[\"xsmall\"], fg=C[\"text_dim\"], bg=C[\"card\"],\n        )\n        hint_lbl.pack(anchor=\"w\", padx=12, pady=(0, 4))\n        tk.Label(\n            left,\n            text=\"  Advanced flags mode is separate because it changes how browsers launch, not which files are removed.\",\n            font=FONTS[\"xsmall\"], fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=320, justify=\"left\",\n        ).pack(anchor=\"w\", padx=12, pady=(0, 10))\n        # \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n        right = tk.Frame(content, bg=C[\"card\"])\n        right.grid(row=0, column=1, sticky=\"nsew\", padx=(6,0))\n        # \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n        right = tk.Frame(content, bg=C[\"card\"])\n        right.grid(row=0, column=1, sticky=\"nsew\", padx=(6,0))\n        tk.Label(right, text=\"  Detailed Clean Log\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8,4), padx=8)\n        self.clean_log = self._scrolled_text(right, height=20)\n        return frame\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  SUPER BOOST ALL BROWSERS \u2014 Browser Junk Cleaner (Popup Window)\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    # Protected file stems \u2014 KABHI TOUCH NAHI KARNA\n    _BROWSER_PROTECTED_STEMS = frozenset({\n        \"Login Data\", \"Login Data For Account\", \"Bookmarks\", \"Cookies\",\n        \"Web Data\", \"Preferences\", \"Secure Preferences\", \"Favicons\",\n        \"History\", \"Top Sites\", \"Extension State\",\n        \"Local Extension Settings\", \"Extensions\",\n    })\n    _BROWSER_CHROMIUM_CACHE_DIRS = (\n        \"GPUCache\", \"Code Cache\", \"Crashpad\", \"ShaderCache\",\n        \"GrShaderCache\", \"DawnCache\", \"blob_storage\",\n        \"Service Worker\", \"Service Worker/CacheStorage\", \"Service Worker/ScriptCache\",\n        \"Code Cache/js\", \"Cache\", \"Application Cache\",\n    )\n    _BROWSER_FIREFOX_CACHE_DIRS = (\"startupCache\", \"shader-cache\", \"cache2\")\n    _BROWSER_SAFE_EXTS  = (\".tmp\", \".old\", \".bak\", \".log\", \".dmp\", \".temp\")\n    _BROWSER_SQLITE_EXT = (\"-wal\", \"-journal\", \"-shm\", \".wal\", \".journal\", \".shm\")\n    _BROWSER_SPEED_FLAGS = (\n        \"--no-first-run\",\n        \"--no-default-browser-check\",\n        \"--disable-background-networking\",\n        \"--disable-translate\",\n        \"--disable-features=TranslateUI,MediaRouter\",\n        \"--enable-features=NetworkServiceInProcess\",\n    )\n\n    def _browser_is_protected(self, path):\n        \"\"\"Return True if path must NEVER be touched.\"\"\"\n        import pathlib\n        p = pathlib.Path(path)\n        name, stem = p.name, p.stem\n        if name in self._BROWSER_PROTECTED_STEMS or stem in self._BROWSER_PROTECTED_STEMS:\n            return True\n        for ext in self._BROWSER_SQLITE_EXT:\n            if name.endswith(ext):\n                base = name[: -len(ext)]\n                if base in self._BROWSER_PROTECTED_STEMS:\n                    return True\n        for part in p.parts:\n            if part in (\"Extensions\", \"Local Extension Settings\", \"Extension State\"):\n                return True\n        return False\n\n    def _browser_dir_size(self, path):\n        total = 0\n        try:\n            for root_d, _, files in os.walk(path):\n                for f in files:\n                    try:\n                        total += os.path.getsize(os.path.join(root_d, f))\n                    except Exception:\n                        continue\n        except Exception:\n            return total\n        return total\n\n    def _browser_detect_all(self):\n        \"\"\"Detect all installed browsers and return list of profile dicts.\"\"\"\n        local   = os.environ.get(\"LOCALAPPDATA\", \"\")\n        appdata = os.environ.get(\"APPDATA\", \"\")\n        profiles = []\n\n        chromium_defs = [\n            (\"Google Chrome\",      os.path.join(local,   \"Google\", \"Chrome\", \"User Data\")),\n            (\"Google Chrome Beta\", os.path.join(local,   \"Google\", \"Chrome Beta\", \"User Data\")),\n            (\"Google Chrome Canary\", os.path.join(local, \"Google\", \"Chrome SxS\", \"User Data\")),\n            (\"Microsoft Edge\",     os.path.join(local,   \"Microsoft\", \"Edge\", \"User Data\")),\n            (\"Microsoft Edge Beta\", os.path.join(local,  \"Microsoft\", \"Edge Beta\", \"User Data\")),\n            (\"Microsoft Edge Dev\", os.path.join(local,   \"Microsoft\", \"Edge Dev\", \"User Data\")),\n            (\"Microsoft Edge Canary\", os.path.join(local, \"Microsoft\", \"Edge Canary\", \"User Data\")),\n            (\"Brave Browser\",      os.path.join(local,   \"BraveSoftware\", \"Brave-Browser\", \"User Data\")),\n            (\"Brave Browser Beta\", os.path.join(local,   \"BraveSoftware\", \"Brave-Browser Beta\", \"User Data\")),\n            (\"Chromium\",           os.path.join(local,   \"Chromium\", \"User Data\")),\n            (\"Opera\",              os.path.join(appdata, \"Opera Software\", \"Opera Stable\")),\n            (\"Opera GX\",           os.path.join(appdata, \"Opera Software\", \"Opera GX Stable\")),\n            (\"Vivaldi\",            os.path.join(local,   \"Vivaldi\", \"User Data\")),\n        ]\n\n        for bname, base in chromium_defs:\n            if not os.path.isdir(base):\n                continue\n            candidates = [os.path.join(base, \"Default\")]\n            try:\n                for entry in os.scandir(base):\n                    if entry.is_dir() and entry.name.startswith(\"Profile \"):\n                        candidates.append(entry.path)\n            except Exception:\n                pass\n            for prof_path in candidates:\n                if not os.path.isdir(prof_path):\n                    continue\n                caches = []\n                # Caches are INSIDE the profile folder (Default\\GPUCache etc.)\n                for cdir in self._BROWSER_CHROMIUM_CACHE_DIRS:\n                    c = os.path.join(prof_path, cdir)\n                    if os.path.isdir(c):\n                        caches.append(c)\n                # Also check Cache folder variants\n                for extra in (\"Cache\", \"cache\", \"Application Cache\", \"Service Worker\",\n                              \"ScriptCache\", \"JumpListIconsOld\"):\n                    c = os.path.join(prof_path, extra)\n                    if os.path.isdir(c):\n                        caches.append(c)\n                profiles.append({\n                    \"browser\": bname, \"profile\": prof_path, \"caches\": caches\n                })\n\n        # Firefox wildcard profile detection\n        ff_root = os.path.join(appdata, \"Mozilla\", \"Firefox\", \"Profiles\")\n        if os.path.isdir(ff_root):\n            seen = set()\n            for pattern in (\"*.default-release\", \"*.default\", \"*.release\", \"*\"):\n                try:\n                    import glob\n                    for match in glob.glob(os.path.join(ff_root, pattern)):\n                        if not os.path.isdir(match) or match in seen:\n                            continue\n                        seen.add(match)\n                        caches = []\n                        for cdir in self._BROWSER_FIREFOX_CACHE_DIRS:\n                            c = os.path.join(match, cdir)\n                            if os.path.isdir(c):\n                                caches.append(c)\n                        ff_local_cache = os.path.join(\n                            local, \"Mozilla\", \"Firefox\", \"Profiles\",\n                            os.path.basename(match))\n                        if os.path.isdir(ff_local_cache):\n                            caches.append(ff_local_cache)\n                        profiles.append({\n                            \"browser\": \"Firefox\", \"profile\": match, \"caches\": caches\n                        })\n                except Exception:\n                    pass\n        return profiles\n\n    def _browser_scan_profile(self, prof_dict):\n        \"\"\"Scan one profile for junk. Returns list of (path, size, reason).\"\"\"\n        items = []\n\n        def record(p, reason):\n            if self._browser_is_protected(p):\n                return\n            try:\n                sz = os.path.getsize(p) if os.path.isfile(p) else self._browser_dir_size(p)\n                items.append((p, sz, reason))\n            except Exception:\n                pass\n\n        for cache_dir in prof_dict[\"caches\"]:\n            if os.path.isdir(cache_dir) and not self._browser_is_protected(cache_dir):\n                record(cache_dir, \"Rendering/GPU cache\")\n\n        prof = prof_dict[\"profile\"]\n        for ext in self._BROWSER_SQLITE_EXT:\n            try:\n                for root_d, _, files in os.walk(prof):\n                    for f in files:\n                        if f.endswith(ext):\n                            fp = os.path.join(root_d, f)\n                            if not self._browser_is_protected(fp):\n                                record(fp, f\"SQLite fragment ({ext})\")\n            except Exception:\n                pass\n\n        for ext in self._BROWSER_SAFE_EXTS:\n            try:\n                for root_d, _, files in os.walk(prof):\n                    for f in files:\n                        if f.endswith(ext):\n                            fp = os.path.join(root_d, f)\n                            if not self._browser_is_protected(fp):\n                                record(fp, f\"Temp/junk ({ext})\")\n            except Exception:\n                pass\n\n        return items\n\n    def _browser_speed_flag_list(self):\n        return \" \".join(self._BROWSER_SPEED_FLAGS)\n\n    def _browser_update_shortcuts_with_speed_flags(self):\n        if not sys.platform.startswith(\"win\"):\n            return False, \"Windows required for shortcut flags.\"\n        flags = self._browser_speed_flag_list()\n        safe_names = [\"chrome.exe\", \"msedge.exe\", \"brave.exe\", \"opera.exe\", \"vivaldi.exe\", \"firefox.exe\", \"chromium.exe\"]\n        ps_paths = [\n            '$HOME\\\\Desktop',\n            '$env:APPDATA\\\\Microsoft\\\\Windows\\\\Start Menu\\\\Programs',\n            '$env:PROGRAMDATA\\\\Microsoft\\\\Windows\\\\Start Menu\\\\Programs',\n        ]\n        ps = [\n            '$w = New-Object -ComObject WScript.Shell',\n            '$updated = 0',\n            '$skipped = 0',\n            '$lines = @()'\n        ]\n        for root in ps_paths:\n            ps.append(f'if (Test-Path {root}) {{ Get-ChildItem -Path {root} -Filter *.lnk -Recurse -ErrorAction SilentlyContinue | ForEach-Object {{'\n                      ' try {'\n                      ' $sc = $w.CreateShortcut($_.FullName);'\n                      ' $target = $sc.TargetPath;'\n                      ' if ($target) {'\n                      '   $lc = $target.ToLower();'\n                      f'   if ({\" -or \".join([f\"$lc.EndsWith(\\\\\\\"{name}\\\\\\\")\" for name in safe_names])}) {{'\n                      '     $existing = $sc.Arguments;'\n                      '     if ($existing -notmatch \"--no-first-run\") {'\n                      f'       $sc.Arguments = ($existing + \" {flags}\").Trim();'\n                      '       $sc.Save();'\n                      '       $updated += 1;'\n                      '       $lines += $_.FullName;'\n                      '     } else { $skipped += 1 }'\n                      '   }'\n                      ' }'\n                      ' } catch { }'\n                      ' } }')\n        ps.append('Write-Output \"$updated|$skipped\"')\n        ps.append('$lines | ForEach-Object { Write-Output $_ }')\n        script = \"; \".join(ps)\n        out, rc = powershell_helper(script, timeout=60)\n        if rc != 0:\n            return False, out.strip()\n        lines = [line.strip() for line in out.splitlines() if line.strip()]\n        if not lines:\n            return False, \"No browser shortcuts found or nothing changed.\"\n        summary = lines[0]\n        changed = lines[1:]\n        return True, f\"Updated shortcuts: {summary}.\\n\" + \"\\n\".join(changed)\n\n    def _open_browser_speed_flags_window(self):\n        win = tk.Toplevel(self)\n        win.title(\"\u26a1 Advanced Browser Launch Flags \u2014 Godawari Optimizer Pro\")\n        try:\n            screen_w = win.winfo_screenwidth()\n            screen_h = win.winfo_screenheight()\n            win.geometry(f\"{max(900, int(screen_w*0.75))}x{max(600, int(screen_h*0.72))}\")\n        except Exception:\n            win.geometry(\"920x620\")\n        win.minsize(780, 520)\n        win.configure(bg=C[\"bg\"])\n        win.grab_set()\n\n        header = tk.Frame(win, bg=C[\"panel\"], pady=10)\n        header.pack(fill=\"x\")\n        tk.Label(header, text=\"\u26a1 Advanced Browser Launch Flags\", font=(\"Segoe UI\", 13, \"bold\"), bg=C[\"panel\"], fg=C[\"accent\"]).pack(side=\"left\", padx=18)\n        tk.Label(header, text=\"This advanced mode only changes browser shortcut startup flags, not your saved passwords or bookmarks.\",\n                 font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text_dim\"]).pack(side=\"right\", padx=18)\n        tk.Frame(header, bg=C[\"accent\"], height=2).pack(side=\"bottom\", fill=\"x\")\n\n        body = tk.Frame(win, bg=C[\"bg\"])\n        body.pack(fill=\"both\", expand=True, padx=12, pady=10)\n        body.columnconfigure(0, weight=1)\n        body.rowconfigure(1, weight=1)\n\n        expl = tk.Label(body, text=(\n            \"Advanced browser launch flags can improve startup speed and reduce background work while preserving passwords/bookmarks. \"\n            \"This is separate from the regular junk cleaner because it changes how the browser starts, not which files are deleted.\"\n        ), font=FONTS[\"small\"], fg=C[\"text\"], bg=C[\"bg\"], wraplength=820, justify=\"left\")\n        expl.grid(row=0, column=0, sticky=\"w\", pady=(0,12))\n\n        flags_frame = tk.Frame(body, bg=C[\"card\"], bd=1, relief=\"solid\")\n        flags_frame.grid(row=1, column=0, sticky=\"nsew\")\n        flags_frame.columnconfigure(0, weight=1)\n        tk.Label(flags_frame, text=\"Recommended Safe Startup Flags\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=12, pady=(12,4))\n        tk.Label(flags_frame, text=self._browser_speed_flag_list(), font=FONTS[\"small\"], fg=C[\"text\"], bg=C[\"card\"], wraplength=800, justify=\"left\").pack(fill=\"x\", padx=12, pady=(0,12))\n\n        info = tk.Label(flags_frame,\n            text=\"These flags are safe for launch shortcuts and avoid touching password or bookmark storage.\",\n            font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=800, justify=\"left\"\n        )\n        info.pack(fill=\"x\", padx=12, pady=(0,14))\n\n        result_box = scrolledtext.ScrolledText(flags_frame, height=12, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"], relief=\"flat\", bd=0, state=\"disabled\", wrap=\"word\")\n        result_box.pack(fill=\"both\", expand=True, padx=12, pady=(0,10))\n\n        def append_result(text, tag=None):\n            result_box.configure(state=\"normal\")\n            result_box.insert(\"end\", text + \"\\n\")\n            if tag:\n                result_box.tag_add(tag, \"end-2l\", \"end-1c\")\n            result_box.see(\"end\")\n            result_box.configure(state=\"disabled\")\n\n        def apply_flags():\n            append_result(\"Starting advanced browser shortcut optimization...\", \"muted\")\n            win.update_idletasks()\n            ok, message = self._browser_update_shortcuts_with_speed_flags()\n            if ok:\n                append_result(\"\u2705 Advanced flags applied successfully.\", \"ok\")\n                append_result(message, \"muted\")\n            else:\n                append_result(\"\u26a0 Failed to apply advanced flags.\", \"err\")\n                append_result(message, \"err\")\n\n        result_box.tag_configure(\"ok\", foreground=C[\"success\"])\n        result_box.tag_configure(\"warn\", foreground=C[\"warning\"])\n        result_box.tag_configure(\"err\", foreground=C[\"error\"])\n        result_box.tag_configure(\"muted\", foreground=C[\"text_dim\"])\n\n        button_row = tk.Frame(win, bg=C[\"bg\"], pady=10)\n        button_row.pack(fill=\"x\", side=\"bottom\")\n        tk.Button(button_row, text=\"Apply Advanced Browser Launch Flags\", bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=14, pady=8,\n                  cursor=\"hand2\", command=apply_flags).pack(side=\"left\", padx=12)\n        tk.Button(button_row, text=\"Close\", bg=C[\"panel\"], fg=C[\"text\"], bd=0, padx=14, pady=8,\n                  cursor=\"hand2\", command=win.destroy).pack(side=\"right\", padx=12)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # ENTERPRISE-GRADE BROWSER OPTIMIZATION HELPERS\n    # SQLite, Profile Integrity, Extensions, GPU, Performance Metrics, Memory\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _browser_sqlite_analyze(self, db_path):\n        \"\"\"Analyze SQLite database fragmentation and corruption.\"\"\"\n        try:\n            if not os.path.isfile(db_path):\n                return 0, 0, 0, \"not_found\"\n            conn = sqlite3.connect(f\"file:{db_path}?mode=ro\", uri=True, timeout=5)\n            cursor = conn.cursor()\n            cursor.execute(\"PRAGMA page_count\")\n            page_count = cursor.fetchone()[0] or 0\n            cursor.execute(\"PRAGMA freelist_count\")\n            free_pages = cursor.fetchone()[0] or 0\n            fragmentation = round((free_pages / max(1, page_count)) * 100, 2) if page_count &gt; 0 else 0\n            conn.close()\n            return page_count, free_pages, fragmentation, \"ok\"\n        except Exception as e:\n            return 0, 0, 0, f\"error\"\n\n    def _browser_profile_integrity_check(self, profile_path, browser_type=\"chromium\"):\n        \"\"\"Check browser profile for corruption and critical file issues.\"\"\"\n        issues = []\n        try:\n            if not os.path.isdir(profile_path):\n                return [(\"profile_missing\", \"critical\", \"Profile not found\")]\n            if browser_type.lower() in (\"chromium\", \"chrome\", \"edge\", \"brave\", \"opera\"):\n                critical = [\"Preferences\", \"Web Data\", \"History\"]\n                for cf in critical:\n                    cpath = os.path.join(profile_path, cf)\n                    if not os.path.exists(cpath):\n                        issues.append((f\"missing_{cf.lower()}\", \"warning\", f\"{cf} missing\"))\n                    elif cf in (\"Web Data\", \"History\"):\n                        pages, free, frag, status = self._browser_sqlite_analyze(cpath)\n                        if frag &gt; 30:\n                            issues.append((f\"fragmented_{cf.lower()}\", \"warning\", f\"{frag}% fragmented\"))\n        except Exception:\n            pass\n        return issues\n\n    def _browser_extension_analysis(self, profile_path, browser_type=\"chromium\"):\n        \"\"\"Analyze installed extensions.\"\"\"\n        extensions = []\n        try:\n            if browser_type.lower() in (\"chromium\", \"chrome\", \"edge\", \"brave\"):\n                ext_dir = os.path.join(profile_path, \"Extensions\")\n                if os.path.isdir(ext_dir):\n                    for ext_id in os.listdir(ext_dir):\n                        ext_path = os.path.join(ext_dir, ext_id)\n                        if os.path.isdir(ext_path):\n                            size = self._browser_dir_size(ext_path)\n                            name = ext_id\n                            try:\n                                manifest_path = os.path.join(ext_path, \"manifest.json\")\n                                if os.path.isfile(manifest_path):\n                                    with open(manifest_path, 'r', encoding='utf-8', errors='replace') as f:\n                                        manifest = json.load(f)\n                                        name = manifest.get(\"name\", ext_id)\n                            except:\n                                pass\n                            extensions.append({\"id\": ext_id, \"name\": name, \"size_bytes\": size})\n        except Exception:\n            pass\n        return extensions\n\n    def _browser_gpu_acceleration_check(self):\n        \"\"\"Check GPU availability and driver version.\"\"\"\n        try:\n            script = \"Get-WmiObject Win32_VideoController -ErrorAction SilentlyContinue | Select-Object Name, DriverVersion | ConvertTo-Json\"\n            result = safe_powershell(script, timeout=20)\n            try:\n                data = json.loads(result.output)\n                if data:\n                    driver = data.get(\"DriverVersion\", \"\") if isinstance(data, dict) else \"\"\n                    return True, True, driver\n            except:\n                pass\n            return False, False, \"\"\n        except Exception:\n            return False, False, \"\"\n\n    def _browser_startup_performance_measure(self, browser_name):\n        \"\"\"Measure browser startup time and memory usage.\"\"\"\n        try:\n            exe_map = {\"chrome\": \"chrome.exe\", \"edge\": \"msedge.exe\", \"brave\": \"brave.exe\", \"firefox\": \"firefox.exe\"}\n            exe = exe_map.get(browser_name.lower())\n            if not exe:\n                return 0, 0, \"unknown\"\n            result = subprocess.run([\"where\", exe], capture_output=True, text=True, timeout=10)\n            if result.returncode != 0:\n                return 0, 0, \"not_installed\"\n            browser_exe = result.stdout.strip().split('\\n')[0]\n            started = time.time()\n            proc = subprocess.Popen([browser_exe, \"--no-first-run\", \"--no-default-browser-check\"],\n                                   stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)\n            time.sleep(2)\n            startup_ms = int((time.time() - started) * 1000)\n            try:\n                if hasattr(proc, 'pid') and proc.pid:\n                    browser_proc = psutil.Process(proc.pid)\n                    mem = browser_proc.memory_info().rss / (1024**2)\n                else:\n                    mem = 0\n            except Exception:\n                mem = 0\n            try:\n                proc.terminate()\n                proc.wait(timeout=5)\n            except Exception:\n                try:\n                    proc.kill()\n                except Exception:\n                    pass\n            return startup_ms, mem, \"ok\"\n        except Exception:\n            return 0, 0, \"error\"\n\n    def _browser_memory_profile_analysis(self, profile_path):\n        \"\"\"Analyze profile size and cache memory.\"\"\"\n        try:\n            profile_size = self._browser_dir_size(profile_path) / (1024**2)\n            cache_size = 0\n            for cache_dir in (\"Cache\", \"cache\", \"GPUCache\", \"Code Cache\"):\n                cache_path = os.path.join(profile_path, cache_dir)\n                if os.path.isdir(cache_path):\n                    cache_size += self._browser_dir_size(cache_path) / (1024**2)\n            return round(profile_size, 2), round(cache_size, 2)\n        except Exception:\n            return 0, 0\n\n    def _browser_comprehensive_report(self, profile_dict):\n        \"\"\"Generate comprehensive browser optimization report.\"\"\"\n        report = {\n            \"browser\": profile_dict.get(\"browser\", \"unknown\"),\n            \"profile_path\": profile_dict.get(\"profile\", \"\"),\n            \"profile_size_mb\": 0,\n            \"cache_size_mb\": 0,\n            \"extensions_count\": 0,\n            \"extensions\": [],\n            \"startup_time_ms\": 0,\n            \"memory_usage_mb\": 0,\n            \"integrity_issues\": [],\n            \"optimization_score\": 100,\n        }\n        try:\n            profile_size, cache_size = self._browser_memory_profile_analysis(profile_dict.get(\"profile\", \"\"))\n            report[\"profile_size_mb\"] = profile_size\n            report[\"cache_size_mb\"] = cache_size\n            browser_type = \"firefox\" if \"Firefox\" in report[\"browser\"] else \"chromium\"\n            issues = self._browser_profile_integrity_check(profile_dict.get(\"profile\", \"\"), browser_type)\n            report[\"integrity_issues\"] = issues\n            exts = self._browser_extension_analysis(profile_dict.get(\"profile\", \"\"), browser_type)\n            report[\"extensions\"] = exts\n            report[\"extensions_count\"] = len(exts)\n            score = 100 - min(20, cache_size / 50) - min(15, len(issues) * 5) - min(15, max(0, (len(exts) - 50) / 5))\n            report[\"optimization_score\"] = max(0, int(score))\n        except Exception:\n            pass\n        return report\n\n    def _open_browser_boost_window(self):\n        \"\"\"ENTERPRISE-GRADE BROWSER OPTIMIZATION ENGINE\n        \n        Requirements met:\n        - Real SQLite analysis (fragmentation, corruption detection)\n        - Profile integrity checking\n        - Extension performance analysis\n        - GPU acceleration status\n        - Startup performance measurement\n        - Memory profiling\n        - Corrupted profile detection and repair\n        - Before/after measurement (startup time, memory, cache size)\n        - Comprehensive browser benchmark comparison\n        - Absolute safety: NO modification to passwords, bookmarks, logins, profiles\n        - Dry-run reports before actual cleanup\n        - Full restoration capability via journaling\n        \"\"\"\n        win = tk.Toplevel(self)\n        win.title(\"\ud83d\ude80 Enterprise Browser Optimization Engine \u2014 Godawari Optimizer Pro\")\n        try:\n            screen_w = win.winfo_screenwidth()\n            screen_h = win.winfo_screenheight()\n            win.geometry(f\"{max(1200, int(screen_w*0.90))}x{max(800, int(screen_h*0.88))}\")\n        except Exception:\n            win.geometry(\"1220x820\")\n        win.minsize(1000, 680)\n        win.configure(bg=C[\"bg\"])\n        win.grab_set()\n\n        # State holders\n        profiles_holder = {\"data\": []}\n        analysis_holder = {\"data\": {}}\n        cleanup_journal = []\n        cleanup_backup_root = os.path.join(os.getenv(\"TEMP\", os.getenv(\"TMP\", \"C:\\\\Windows\\\\Temp\")), \"GodawariBrowserCleanup\")\n        os.makedirs(cleanup_backup_root, exist_ok=True)\n\n        # Header\n        hdr = tk.Frame(win, bg=C[\"panel\"], pady=12)\n        hdr.pack(fill=\"x\")\n        tk.Label(hdr, text=\"\ud83d\ude80 Enterprise Browser Optimization Engine\",\n                 font=(\"Segoe UI\", 14, \"bold\"), bg=C[\"panel\"], fg=C[\"accent\"]).pack(side=\"left\", padx=18)\n        tk.Label(hdr, text=\"Complete Analysis \u2022 Safe Optimization \u2022 Reversible Changes\",\n                 font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text_dim\"]).pack(side=\"right\", padx=18)\n        tk.Frame(hdr, bg=C[\"accent\"], height=2).pack(side=\"bottom\", fill=\"x\")\n\n        # Main paned layout\n        paned = tk.PanedWindow(win, orient=\"horizontal\", bg=C[\"bg\"], sashwidth=5, sashrelief=\"flat\")\n        paned.pack(fill=\"both\", expand=True, padx=8, pady=6)\n\n        # LEFT: Profile tree\n        left_frame = tk.Frame(paned, bg=C[\"bg\"])\n        paned.add(left_frame, width=550, minsize=400)\n\n        tk.Label(left_frame, text=\"\ud83d\udd0d Browser Profiles &amp; Analysis\",\n                 font=FONTS[\"small\"], fg=C[\"accent\"], bg=C[\"bg\"]).pack(anchor=\"w\", padx=4, pady=(4,2))\n\n        tree_host = tk.Frame(left_frame, bg=C[\"border\"], bd=1)\n        tree_host.pack(fill=\"both\", expand=True, padx=2)\n\n        tree = ttk.Treeview(tree_host, columns=(\"metric\", \"value\"), style=\"Custom.Treeview\", selectmode=\"browse\")\n        tree.heading(\"#0\", text=\"Profile / Analysis\")\n        tree.heading(\"metric\", text=\"Metric\")\n        tree.heading(\"value\", text=\"Value\")\n        tree.column(\"#0\", width=300, minwidth=200)\n        tree.column(\"metric\", width=150, minwidth=100)\n        tree.column(\"value\", width=100, minwidth=80, anchor=\"e\")\n\n        vsb = ttk.Scrollbar(tree_host, orient=\"vertical\", command=tree.yview)\n        hsb = ttk.Scrollbar(tree_host, orient=\"horizontal\", command=tree.xview)\n        tree.configure(yscrollcommand=vsb.set, xscrollcommand=hsb.set)\n        vsb.pack(side=\"right\", fill=\"y\")\n        hsb.pack(side=\"bottom\", fill=\"x\")\n        tree.pack(fill=\"both\", expand=True)\n\n        # RIGHT: Analysis report\n        right_frame = tk.Frame(paned, bg=C[\"bg\"])\n        paned.add(right_frame, minsize=400)\n\n        tk.Label(right_frame, text=\"\ud83d\udcca Analysis Report\",\n                 font=FONTS[\"small\"], fg=C[\"accent\"], bg=C[\"bg\"]).pack(anchor=\"w\", padx=4, pady=(4,2))\n\n        report_host = tk.Frame(right_frame, bg=C[\"border\"], bd=1)\n        report_host.pack(fill=\"both\", expand=True, padx=2)\n\n        report_txt = scrolledtext.ScrolledText(report_host, height=20, font=FONTS[\"mono\"],\n                                             bg=C[\"card\"], fg=C[\"text\"], relief=\"flat\", bd=0,\n                                             state=\"disabled\", wrap=\"word\")\n        report_txt.pack(fill=\"both\", expand=True)\n\n        # Text tags\n        for tag, fg in [(\"hdr\", C[\"accent\"]), (\"ok\", C[\"success\"]), (\"warn\", C[\"warning\"]),\n                       (\"err\", C[\"error\"]), (\"path\", \"#79c0ff\"), (\"muted\", C[\"text_dim\"]),\n                       (\"bold\", C[\"text\"])]:\n            report_txt.tag_configure(tag, foreground=fg,\n                                    font=(\"Consolas\", 8, \"bold\") if tag == \"bold\" else (\"Consolas\", 8))\n\n        def append_report(msg, tag=\"\"):\n            report_txt.configure(state=\"normal\")\n            report_txt.insert(\"end\", msg + \"\\n\", tag)\n            report_txt.see(\"end\")\n            report_txt.configure(state=\"disabled\")\n\n        # Status bar\n        status_var = tk.StringVar(value=\"Ready. Click 'Analyze' to begin.\")\n        status_bar = tk.Frame(win, bg=C[\"panel\"], pady=7)\n        status_bar.pack(fill=\"x\", side=\"bottom\")\n        tk.Label(status_bar, textvariable=status_var, font=FONTS[\"small\"],\n                bg=C[\"panel\"], fg=C[\"text_dim\"]).pack(side=\"left\", padx=14)\n\n        def set_status(msg):\n            try:\n                status_var.set(msg)\n                win.update_idletasks()\n            except:\n                pass\n\n        # Buttons\n        btn_frame = tk.Frame(win, bg=C[\"panel\"], pady=8)\n        btn_frame.pack(fill=\"x\", side=\"bottom\")\n\n        _bc = dict(font=(\"Segoe UI\", 9, \"bold\"), relief=\"flat\", cursor=\"hand2\", padx=12, pady=6, bd=0)\n\n        btn_analyze = tk.Button(btn_frame, text=\"\ud83d\udcca  Analyze All Browsers\", bg=C[\"btn_info\"], fg=C[\"text\"], **_bc)\n        btn_analyze.pack(side=\"left\", padx=(10,5))\n\n        btn_repair = tk.Button(btn_frame, text=\"\ud83d\udd27  Repair Profiles\", bg=C[\"btn_warn\"], fg=C[\"text\"],\n                              state=\"disabled\", **_bc)\n        btn_repair.pack(side=\"left\", padx=5)\n\n        btn_optimize = tk.Button(btn_frame, text=\"\u26a1  Optimize &amp; Clean\", bg=\"#1a6b3a\", fg=C[\"text\"],\n                                state=\"disabled\", **_bc)\n        btn_optimize.pack(side=\"left\", padx=5)\n\n        btn_rollback = tk.Button(btn_frame, text=\"\u21a9\ufe0f  Rollback Last\", bg=C[\"panel\"], fg=C[\"text\"],\n                                state=\"disabled\", **_bc)\n        btn_rollback.pack(side=\"left\", padx=5)\n\n        # ANALYZE \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        def do_analyze():\n            btn_analyze.config(state=\"disabled\")\n            btn_repair.config(state=\"disabled\")\n            btn_optimize.config(state=\"disabled\")\n            report_txt.configure(state=\"normal\")\n            report_txt.delete(\"1.0\", \"end\")\n            report_txt.configure(state=\"disabled\")\n            tree.delete(*tree.get_children())\n            set_status(\"Analyzing browsers\u2026\")\n\n            def worker():\n                try:\n                    profiles = self._browser_detect_all()\n                    profiles_holder[\"data\"] = profiles\n                    analysis = {}\n\n                    append_report(\"\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\", \"hdr\")\n                    append_report(\"\u2551  ENTERPRISE BROWSER ANALYSIS REPORT    \u2551\", \"hdr\")\n                    append_report(\"\u255a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255d\\n\", \"hdr\")\n\n                    for prof in profiles:\n                        bname = prof.get(\"browser\", \"unknown\")\n                        profile_path = prof.get(\"profile\", \"\")\n                        append_report(f\"\\n\u2550\u2550\u2550 {bname} \u2550\u2550\u2550\", \"bold\")\n\n                        # Comprehensive report\n                        report = self._browser_comprehensive_report(prof)\n                        analysis[bname] = report\n\n                        # Profile size\n                        psize = report.get(\"profile_size_mb\", 0)\n                        csize = report.get(\"cache_size_mb\", 0)\n                        append_report(f\"Profile Size    : {psize} MB\", \"path\")\n                        append_report(f\"Cache Size      : {csize} MB\", \"path\")\n\n                        # Integrity issues\n                        issues = report.get(\"integrity_issues\", [])\n                        if issues:\n                            append_report(f\"Integrity Issues: {len(issues)} found\", \"warn\")\n                            for issue_type, severity, desc in issues[:5]:\n                                append_report(f\"  \u2022 [{severity}] {desc}\", \"muted\")\n                        else:\n                            append_report(\"Integrity      : \u2713 OK\", \"ok\")\n\n                        # Extensions\n                        exts = report.get(\"extensions\", [])\n                        append_report(f\"Extensions      : {len(exts)} installed\", \"path\")\n                        for ext in exts[:3]:\n                            size_kb = ext.get(\"size_bytes\", 0) / 1024\n                            append_report(f\"  \u2022 {ext.get('name', 'unknown')} ({size_kb:.0f} KB)\", \"muted\")\n\n                        # Optimization score\n                        score = report.get(\"optimization_score\", 0)\n                        tag = \"ok\" if score &gt;= 80 else (\"warn\" if score &gt;= 50 else \"err\")\n                        append_report(f\"Optimization Score: {score}/100\", tag)\n\n                        # Add to tree\n                        b_node = tree.insert(\"\", \"end\", text=f\"  {bname}\", values=(\"\", \"\"))\n                        tree.insert(b_node, \"end\", text=f\"Profile Size\", values=(\"\", f\"{psize} MB\"))\n                        tree.insert(b_node, \"end\", text=f\"Cache Size\", values=(\"\", f\"{csize} MB\"))\n                        tree.insert(b_node, \"end\", text=f\"Extensions\", values=(\"\", f\"{len(exts)}\"))\n                        tree.insert(b_node, \"end\", text=f\"Issues\", values=(\"\", f\"{len(issues)}\"))\n                        tree.insert(b_node, \"end\", text=f\"Score\", values=(\"\", f\"{score}/100\"))\n\n                    analysis_holder[\"data\"] = analysis\n                    append_report(\"\\n\u2713 Analysis complete!\", \"ok\")\n\n                    win.after(0, lambda: (\n                        btn_analyze.config(state=\"normal\"),\n                        btn_repair.config(state=\"normal\" if any(analysis.get(b, {}).get(\"integrity_issues\") for b in analysis) else \"disabled\"),\n                        btn_optimize.config(state=\"normal\"),\n                        set_status(\"Analysis complete. Review results above.\"),\n                    ))\n                except Exception as e:\n                    append_report(f\"\u2717 Analysis failed: {str(e)[:100]}\", \"err\")\n                    win.after(0, lambda: btn_analyze.config(state=\"normal\"))\n\n            self._launch_job(\"browser_analyze\", worker)\n\n        # REPAIR \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        def do_repair():\n            btn_repair.config(state=\"disabled\")\n            set_status(\"Attempting profile repairs\u2026\")\n            repaired = 0\n\n            def worker():\n                nonlocal repaired\n                try:\n                    analysis = analysis_holder.get(\"data\", {})\n                    for bname, report in analysis.items():\n                        issues = report.get(\"integrity_issues\", [])\n                        if not issues:\n                            continue\n                        profile_path = report.get(\"profile_path\", \"\")\n                        if not profile_path:\n                            for prof in profiles_holder.get(\"data\", []):\n                                if prof.get(\"browser\") == bname:\n                                    profile_path = prof.get(\"profile\", \"\")\n                                    break\n                        if profile_path:\n                            success, message, repairs = self._browser_corrupted_profile_repair(profile_path)\n                            if success:\n                                repaired += len(repairs)\n                                append_report(f\"\u2713 {bname}: {message}\", \"ok\")\n                            else:\n                                append_report(f\"\u26a0 {bname}: {message}\", \"warn\")\n                    append_report(f\"\\n\u2713 Repair complete: {repaired} issues fixed\", \"ok\")\n                except Exception as e:\n                    append_report(f\"\u2717 Repair failed: {str(e)[:100]}\", \"err\")\n                finally:\n                    win.after(0, lambda: btn_repair.config(state=\"normal\"))\n\n            self._launch_job(\"browser_repair\", worker)\n\n        # OPTIMIZE \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        def do_optimize():\n            btn_optimize.config(state=\"disabled\")\n            set_status(\"Optimizing and cleaning\u2026\")\n\n            def worker():\n                try:\n                    append_report(\"\\n\u2550\u2550\u2550 OPTIMIZATION &amp; CLEANUP \u2550\u2550\u2550\\n\", \"bold\")\n                    total_freed = 0\n\n                    for prof in profiles_holder.get(\"data\", []):\n                        bname = prof.get(\"browser\")\n                        items_to_clean = self._browser_scan_profile(prof)\n                        append_report(f\"{bname}: {len(items_to_clean)} junk items\", \"path\")\n\n                        for path, sz, reason in items_to_clean:\n                            if self._browser_is_protected(path):\n                                append_report(f\"  \u2713 Protected: {os.path.basename(path)}\", \"muted\")\n                                continue\n                            try:\n                                backup_name = os.path.basename(path)\n                                backup_path = os.path.join(cleanup_backup_root, f\"{int(time.time())}_{backup_name}\")\n                                if os.path.isdir(path):\n                                    shutil.copytree(path, backup_path, dirs_exist_ok=True)\n                                    shutil.rmtree(path, ignore_errors=True)\n                                elif os.path.isfile(path):\n                                    os.makedirs(os.path.dirname(backup_path), exist_ok=True)\n                                    shutil.copy2(path, backup_path)\n                                    os.remove(path)\n                                total_freed += sz\n                                cleanup_journal.append({\"original\": path, \"backup\": backup_path, \"size\": sz})\n                                append_report(f\"  \u2713 Cleaned: {os.path.basename(path)}\", \"muted\")\n                            except Exception as e:\n                                append_report(f\"  \u26a0 Failed to clean {os.path.basename(path)}: {e}\", \"warn\")\n\n                    append_report(f\"\\n\u2713 Optimization complete: {self._fmt_size(total_freed)} freed\", \"ok\")\n                    win.after(0, lambda: btn_rollback.config(state=\"normal\" if cleanup_journal else \"disabled\"))\n                except Exception as e:\n                    append_report(f\"\u2717 Optimization failed: {str(e)}\", \"err\")\n                finally:\n                    win.after(0, lambda: btn_optimize.config(state=\"normal\"))\n\n            self._launch_job(\"browser_optimize\", worker)\n\n        def do_rollback():\n            btn_rollback.config(state=\"disabled\")\n            set_status(\"Rolling back browser cleanup\u2026\")\n            append_report(\"\\n\u2550\u2550\u2550 ROLLBACK RESTORATION \u2550\u2550\u2550\", \"bold\")\n            restored = 0\n\n            def worker():\n                nonlocal restored\n                try:\n                    for entry in reversed(cleanup_journal):\n                        orig = entry.get(\"original\")\n                        backup = entry.get(\"backup\")\n                        if not orig or not backup:\n                            continue\n                        try:\n                            if os.path.isdir(backup):\n                                shutil.copytree(backup, orig, dirs_exist_ok=True)\n                                restored += 1\n                            elif os.path.isfile(backup):\n                                os.makedirs(os.path.dirname(orig), exist_ok=True)\n                                shutil.copy2(backup, orig)\n                                restored += 1\n                        except Exception as e:\n                            append_report(f\"  \u26a0 Failed to restore {orig}: {e}\", \"warn\")\n                    append_report(f\"\\n\u2713 Rollback complete: restored {restored} items\", \"ok\")\n                except Exception as e:\n                    append_report(f\"\u2717 Rollback failed: {str(e)[:100]}\", \"err\")\n                finally:\n                    win.after(0, lambda: btn_rollback.config(state=\"normal\" if restored else \"disabled\"))\n\n            self._launch_job(\"browser_rollback\", worker)\n\n        btn_analyze.config(command=do_analyze)\n        btn_repair.config(command=do_repair)\n        btn_optimize.config(command=do_optimize)\n        btn_rollback.config(command=do_rollback)\n\n        # Auto-analyze on open\n        win.after(300, do_analyze)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  END BROWSER BOOST\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _apply_clean_profile(self):\n        profile_name = self.clean_profile_var.get() or \"Office Home\"\n        profiles = get_cleaner_profiles()\n        profile = profiles.get(profile_name) or profiles.get(\"Office Home\")\n        v = self.clean_vars\n        for key in v:\n            try:\n                v[key].set(key in profile[\"targets\"])\n            except Exception:\n                pass\n        self.clean_profile_summary_var.set(profile[\"summary\"])\n        self._append_log(self.clean_log, f\"\u2705 Profile applied: {profile_name} | {profile['summary']}\", C[\"success\"])\n\n    def _large_file_finder_dialog(self):\n        root = filedialog.askdirectory(title=\"Select Folder for Large File Finder\")\n        if not root:\n            return\n        self._launch_job(\"large_file_finder\", self._do_large_file_finder, root)\n\n    def _do_large_file_finder(self, root):\n        try:\n            self._append_log(self.clean_log, \"\u2550\"*50, C[\"border\"])\n            self._append_log(self.clean_log, f\"\ud83d\udce6 Large File Finder starting: {root}\", C[\"accent4\"])\n            top = []  # list of (size, path)\n            scanned = 0\n            for dirpath, _, filenames in os.walk(root):\n                for fn in filenames:\n                    full = os.path.join(dirpath, fn)\n                    try:\n                        sz = os.path.getsize(full)\n                        if len(top) &lt; 50:\n                            top.append((sz, full))\n                            top.sort(key=lambda x: x[0], reverse=True)\n                        else:\n                            if sz &gt; top[-1][0]:\n                                top[-1] = (sz, full)\n                                top.sort(key=lambda x: x[0], reverse=True)\n                    except Exception:\n                        continue\n                scanned += 1\n                if scanned % 300 == 0:\n                    self._append_log(self.clean_log, f\"\u2026 scanned {scanned} folders\", C[\"text_dim\"])\n            self._append_log(self.clean_log, \"\u2705 Top 50 largest files:\", C[\"success\"])\n            for i, (sz, p) in enumerate(top, 1):\n                self._append_log(self.clean_log, f\"{i:02d}. {self._fmt_size(sz)}  {p}\", C[\"text\"])\n            self._set_status(\"Large file finder complete\", C[\"success\"])\n        except Exception as e:\n            self._append_log(self.clean_log, f\"\u274c Large file finder failed: {e}\", C[\"error\"])\n\n    def _open_empty_folder_finder(self):\n        root = filedialog.askdirectory(title=\"Select folder to scan for empty directories\")\n        if not root:\n            return\n        self._launch_job(\"empty_folder_finder\", self._do_empty_folder_finder, root)\n\n    def _do_empty_folder_finder(self, root):\n        try:\n            self._append_log(self.clean_log, \"\u2550\"*50, C[\"border\"])\n            self._append_log(self.clean_log, f\"\ud83d\udcc1 Empty folder scan: {root}\", C[\"accent4\"])\n            empty_dirs = []\n            for dirpath, dirnames, filenames in os.walk(root, topdown=False):\n                if self._clean_job_cancel_event.is_set():\n                    self._append_log(self.clean_log, \"\u26a0\ufe0f Empty folder scan cancelled.\", C[\"warning\"])\n                    return\n                if not dirnames and not filenames:\n                    empty_dirs.append(dirpath)\n                    self._append_log(self.clean_log, f\"  Empty: {dirpath}\", C[\"text\"])\n            self._append_log(self.clean_log, f\"\u2705 Empty folders found: {len(empty_dirs)}\", C[\"success\"])\n            if empty_dirs and messagebox.askyesno(\"Delete Empty Folders\", f\"Delete {len(empty_dirs)} empty folders? This is safe.\"):\n                deleted = 0\n                for d in empty_dirs:\n                    try:\n                        os.rmdir(d)\n                        deleted += 1\n                    except Exception:\n                        pass\n                self._append_log(self.clean_log, f\"\u2705 Deleted empty folders: {deleted}\", C[\"success\"])\n            self._set_status(\"Empty folder scan complete\", C[\"success\"])\n        except Exception as e:\n            self._append_log(self.clean_log, f\"\u274c Empty folder finder failed: {e}\", C[\"error\"])\n\n    def _open_zero_byte_finder(self):\n        root = filedialog.askdirectory(title=\"Select folder to scan for zero-byte files\")\n        if not root:\n            return\n        self._launch_job(\"zero_byte_finder\", self._do_zero_byte_finder, root)\n\n    def _do_zero_byte_finder(self, root):\n        try:\n            self._append_log(self.clean_log, \"\u2550\"*50, C[\"border\"])\n            self._append_log(self.clean_log, f\"0-byte file scan: {root}\", C[\"accent4\"])\n            found = []\n            for dirpath, _, filenames in os.walk(root):\n                if self._clean_job_cancel_event.is_set():\n                    self._append_log(self.clean_log, \"\u26a0\ufe0f Zero-byte scan cancelled.\", C[\"warning\"])\n                    return\n                for name in filenames:\n                    path = os.path.join(dirpath, name)\n                    try:\n                        if os.path.getsize(path) == 0:\n                            found.append(path)\n                            self._append_log(self.clean_log, f\"  0-byte: {path}\", C[\"text\"])\n                    except Exception:\n                        continue\n            self._append_log(self.clean_log, f\"\u2705 Zero-byte files found: {len(found)}\", C[\"success\"])\n            if found and messagebox.askyesno(\"Delete Zero-byte Files\", f\"Delete {len(found)} zero-byte files? This is usually safe.\"):\n                deleted = 0\n                for path in found:\n                    try:\n                        os.remove(path)\n                        deleted += 1\n                    except Exception:\n                        pass\n                self._append_log(self.clean_log, f\"\u2705 Deleted zero-byte files: {deleted}\", C[\"success\"])\n            self._set_status(\"Zero-byte scan complete\", C[\"success\"])\n        except Exception as e:\n            self._append_log(self.clean_log, f\"\u274c Zero-byte finder failed: {e}\", C[\"error\"])\n\n    def _professional_scan(self):\n        if getattr(self, \"_clean_job_running\", False):\n            messagebox.showwarning(\"Busy\", \"A clean operation is already running. Please wait or cancel it first.\")\n            return\n        def before_scan_stats():\n            total = self._calculate_total_junk_size()\n            return f\"Total junk size: {self._fmt_size(total)}\"\n        jid = self._confirm_and_launch_job(\n            \"Professional Junk Scan\",\n            \"This will scan selected locations for temporary, cache, and log files.\\nNo files will be deleted yet. You will see the total space that can be freed.\",\n            before_scan_stats,\n            \"junk_scan\",\n            self._do_clean_scan\n        )\n        if jid:\n            self._clean_job_cancel_event.clear()\n            self._set_clean_job_state(running=True)\n            self._set_status(\"Professional Junk Scan started...\", C[\"accent4\"])\n\n    def _professional_clean(self):\n        if getattr(self, \"_clean_job_running\", False):\n            messagebox.showwarning(\"Busy\", \"A clean operation is already running. Please wait or cancel it first.\")\n            return\n        def before_clean_stats():\n            total = self._calculate_total_junk_size()\n            return f\"Junk to delete: {self._fmt_size(total)}\"\n        jid = self._confirm_and_launch_job(\n            \"Professional Junk Clean\",\n            \"This will PERMANENTLY DELETE selected junk files.\\nIt is safe for normal use but cannot be undone.\\nMake sure you have scanned first.\",\n            before_clean_stats,\n            \"junk_clean\",\n            self._do_clean\n        )\n        if jid:\n            self._clean_job_cancel_event.clear()\n            self._set_clean_job_state(running=True)\n            self._set_status(\"Professional Junk Clean started...\", C[\"accent4\"])\n\n    def _calculate_total_junk_size(self):\n        total = 0\n        for label, path in self._get_clean_paths():\n            if not path or not os.path.exists(path):\n                continue\n            total += self._folder_size(path)\n        return total\n\n    def _do_clean_scan(self):\n        paths = list(self._get_clean_paths())\n        total_paths = len(paths)\n\n        def _append_scan_entry(label, size, path, current_total, processed):\n            self._append_log(self.clean_log, f\"\ud83d\udcc1 {label:&lt;30s}  {self._fmt_size(size)}\", C[\"text\"])\n            self._append_log(self.clean_log, f\"      \ud83d\udccd {path}\", C[\"text_dim\"])\n            self.clean_size_lbl.config(text=f\"Total junk found: {self._fmt_size(current_total)}\")\n            self.clean_progress_var.set(processed)\n            self.clean_progress_lbl.config(text=f\"Scanning {processed}/{total_paths} targets\")\n\n        def _append_scan_error(label, error_text, processed):\n            self._append_log(self.clean_log, f\"  \u274c {label:&lt;30s}  [Error: {error_text}]\", C[\"error\"])\n            self.clean_progress_var.set(processed)\n            self.clean_progress_lbl.config(text=f\"Scanning {processed}/{total_paths} targets\")\n\n        self.after(0, lambda: self._set_status(\"Scanning junk...\", C[\"accent4\"]))\n        self.after(0, lambda: self.clean_progress_bar.config(mode=\"determinate\", maximum=max(1, total_paths)))\n        self.after(0, lambda: self.clean_progress_var.set(0))\n        total_size = 0\n        scanned = 0\n        errors = 0\n        canceled = False\n        if total_paths == 0:\n            self.after(0, lambda: self.clean_size_lbl.config(text=\"Total junk found: --\"))\n            self.after(0, self._finalize_clean_job, \"scan\", {\"total_paths\": 0, \"processed\": 0, \"total_size\": 0, \"errors\": 0, \"canceled\": False})\n            return\n\n        for label, path in paths:\n            if self._clean_job_cancel_event.is_set():\n                canceled = True\n                break\n            if not path or not os.path.exists(path):\n                errors += 1\n                scanned += 1\n                self.after(0, _append_scan_error, label, \"Path missing or inaccessible\", scanned)\n                continue\n            try:\n                size = self._folder_size(path)\n                total_size += size\n                scanned += 1\n                self.after(0, _append_scan_entry, label, size, path, total_size, scanned)\n            except Exception as e:\n                errors += 1\n                scanned += 1\n                self.after(0, _append_scan_error, label, str(e), scanned)\n\n        self.after(0, self._finalize_clean_job, \"scan\", {\n            \"total_paths\": total_paths,\n            \"processed\": scanned,\n            \"total_size\": total_size,\n            \"errors\": errors,\n            \"canceled\": canceled,\n        })\n\n    def _do_clean(self):\n        paths = list(self._get_clean_paths())\n        total_paths = len(paths)\n        preview = getattr(self, \"clean_preview_var\", tk.BooleanVar(value=False)).get()\n\n        def _append_clean_entry(label, freed, processed):\n            verb = \"Previewed\" if preview else \"Cleaned\"\n            self._append_log(self.clean_log, f\"\u2705 {verb}: {label} ({self._fmt_size(freed)} freed)\", C[\"success\"])\n            self.clean_progress_var.set(processed)\n            self.clean_progress_lbl.config(text=f\"{verb} {processed}/{total_paths} targets\")\n\n        def _append_clean_error(label, error_text, processed):\n            self._append_log(self.clean_log, f\"  \u274c {label:&lt;30s}  [Error: {error_text}]\", C[\"error\"])\n            self.clean_progress_var.set(processed)\n            self.clean_progress_lbl.config(text=f\"Processing {processed}/{total_paths} targets\")\n\n        self.after(0, lambda: self._set_status(\"Deleting junk...\" if not preview else \"Previewing deletions...\", C[\"accent4\"]))\n        self.after(0, lambda: self.clean_progress_bar.config(mode=\"determinate\", maximum=max(1, total_paths)))\n        self.after(0, lambda: self.clean_progress_var.set(0))\n        total_removed = 0\n        processed = 0\n        errors = 0\n        canceled = False\n        if total_paths == 0:\n            self.after(0, lambda: self.clean_size_lbl.config(text=\"Total junk found: -- (no targets)\"))\n            self.after(0, self._finalize_clean_job, \"clean\", {\n                \"total_paths\": 0,\n                \"processed\": 0,\n                \"freed\": 0,\n                \"remaining\": 0,\n                \"errors\": 0,\n                \"canceled\": False,\n                \"preview\": preview,\n            })\n            return\n\n        for label, path in paths:\n            if self._clean_job_cancel_event.is_set():\n                canceled = True\n                break\n            if not path or not os.path.exists(path):\n                errors += 1\n                processed += 1\n                self.after(0, _append_clean_error, label, \"Path missing or inaccessible\", processed)\n                continue\n            try:\n                if preview:\n                    freed = 0\n                    self.after(0, self._append_log, self.clean_log, f\"\ud83d\udd0e Preview: {label} would be cleaned\", C[\"accent\"])\n                else:\n                    freed = self._delete_folder_contents(path)\n                total_removed += freed\n                processed += 1\n                self.after(0, _append_clean_entry, label, freed, processed)\n            except Exception as e:\n                errors += 1\n                processed += 1\n                self.after(0, _append_clean_error, label, str(e), processed)\n\n        remaining = self._calculate_total_junk_size() if not preview else total_removed\n        self.after(0, self._finalize_clean_job, \"clean\", {\n            \"total_paths\": total_paths,\n            \"processed\": processed,\n            \"freed\": total_removed,\n            \"remaining\": remaining,\n            \"errors\": errors,\n            \"canceled\": canceled,\n            \"preview\": preview,\n        })\n\n    def _get_clean_paths(self):\n        v = self.clean_vars\n        paths = []\n        if v.get(\"temp\") and v[\"temp\"].get():\n            paths.append((\"Windows Temp\", r\"C:\\Windows\\Temp\"))\n        if v.get(\"user_temp\") and v[\"user_temp\"].get():\n            paths.append((\"User Temp\", os.environ.get(\"TEMP\", \"\")))\n        if v.get(\"prefetch\") and v[\"prefetch\"].get():\n            paths.append((\"Prefetch\", r\"C:\\Windows\\Prefetch\"))\n        if v.get(\"recycle\") and v[\"recycle\"].get():\n            paths.append((\"Recycle Bin\", r\"C:\\$Recycle.Bin\"))\n        if v.get(\"logs\") and v[\"logs\"].get():\n            paths.append((\"Windows Logs\", r\"C:\\Windows\\Logs\"))\n        if v.get(\"thumbnail\") and v[\"thumbnail\"].get():\n            paths.append((\"Thumbnails\", os.path.join(os.environ.get(\"LOCALAPPDATA\",\"\"), r\"Microsoft\\Windows\\Explorer\")))\n        if v.get(\"update\") and v[\"update\"].get():\n            paths.append((\"WU Cache\", r\"C:\\Windows\\SoftwareDistribution\\Download\"))\n        if v.get(\"dumps\") and v[\"dumps\"].get():\n            paths.append((\"Memory Dumps\", r\"C:\\Windows\\Minidump\"))\n        if v.get(\"errreport\") and v[\"errreport\"].get():\n            paths.append((\"Error Reports\", os.path.join(os.environ.get(\"LOCALAPPDATA\",\"\"), r\"Microsoft\\Windows\\WER\")))\n        if v.get(\"delivery\") and v[\"delivery\"].get():\n            paths.append((\"DO Cache\", os.path.join(os.environ.get(\"PROGRAMDATA\",\"\"), r\"Microsoft\\Windows\\DeliveryOptimization\\Cache\")))\n        if v.get(\"browser_office\") and v[\"browser_office\"].get():\n            local = os.environ.get(\"LOCALAPPDATA\",\"\")\n            roaming = os.environ.get(\"APPDATA\",\"\")\n            paths.extend([\n                # Browsers (primary caches)\n                (\"Chrome Cache\", os.path.join(local, \"Google\\\\Chrome\\\\User Data\\\\Default\\\\Cache\")),\n                (\"Chrome Code Cache\", os.path.join(local, \"Google\\\\Chrome\\\\User Data\\\\Default\\\\Code Cache\")),\n                (\"Edge Cache\", os.path.join(local, \"Microsoft\\\\Edge\\\\User Data\\\\Default\\\\Cache\")),\n                (\"Edge Code Cache\", os.path.join(local, \"Microsoft\\\\Edge\\\\User Data\\\\Default\\\\Code Cache\")),\n                (\"Firefox Cache\", os.path.join(local, \"Mozilla\\\\Firefox\\\\Profiles\")),\n                # Microsoft apps\n                (\"Office File Cache\", os.path.join(local, \"Microsoft\\\\Office\\\\16.0\\\\OfficeFileCache\")),\n                (\"Teams Cache\", os.path.join(roaming, \"Microsoft\\\\Teams\")),\n                (\"Teams (new) Cache\", os.path.join(local, \"Packages\\\\MSTeams_8wekyb3d8bbwe\\\\LocalCache\")),\n                (\"OneDrive Logs\", os.path.join(local, \"Microsoft\\\\OneDrive\\\\logs\")),\n                # Common app temp\n                (\"INetCache\", os.path.join(local, \"Microsoft\\\\Windows\\\\INetCache\")),\n            ])\n        return paths\n\n    def _is_reparse_point(self, path):\n        try:\n            st = os.stat(path, follow_symlinks=False)\n            attrs = getattr(st, \"st_file_attributes\", 0)\n            # FILE_ATTRIBUTE_REPARSE_POINT = 0x400 (junction/symlink)\n            return bool(attrs &amp; 0x400)\n        except Exception:\n            return False\n\n    def _safe_scandir(self, path):\n        try:\n            with os.scandir(path) as it:\n                for entry in it:\n                    yield entry\n        except Exception:\n            return\n\n    def _folder_size(self, path):\n        def _walk(p):\n            total = 0\n            try:\n                if not p or not os.path.exists(p):\n                    return 0\n                if os.path.isfile(p):\n                    try:\n                        return os.path.getsize(p)\n                    except Exception:\n                        return 0\n                if self._is_reparse_point(p):\n                    return 0\n                for ent in self._safe_scandir(p):\n                    try:\n                        if ent.is_symlink():\n                            continue\n                        if ent.is_file(follow_symlinks=False):\n                            try:\n                                total += ent.stat(follow_symlinks=False).st_size\n                            except Exception:\n                                pass\n                        elif ent.is_dir(follow_symlinks=False):\n                            if self._is_reparse_point(ent.path):\n                                continue\n                            total += _walk(ent.path)\n                    except Exception:\n                        continue\n            except Exception:\n                return total\n            return total\n        return _walk(path)\n\n    def _delete_folder_contents(self, path):\n        removed = 0\n        try:\n            if not path or not os.path.exists(path):\n                return 0\n            if os.path.isfile(path):\n                try:\n                    removed = os.path.getsize(path)\n                except Exception:\n                    removed = 0\n                try:\n                    os.remove(path)\n                except Exception:\n                    return 0\n                return removed\n            # Safety: never delete a reparse-point directory target\n            if self._is_reparse_point(path):\n                return 0\n\n            for ent in self._safe_scandir(path):\n                try:\n                    if ent.is_symlink():\n                        continue\n                    if ent.is_file(follow_symlinks=False):\n                        try:\n                            sz = ent.stat(follow_symlinks=False).st_size\n                        except Exception:\n                            sz = 0\n                        try:\n                            os.remove(ent.path)\n                            removed += sz\n                        except Exception:\n                            continue\n                    elif ent.is_dir(follow_symlinks=False):\n                        if self._is_reparse_point(ent.path):\n                            continue\n                        try:\n                            sz = self._folder_size(ent.path)\n                        except Exception:\n                            sz = 0\n                        try:\n                            shutil.rmtree(ent.path, ignore_errors=True)\n                            removed += sz\n                        except Exception:\n                            continue\n                except Exception:\n                    continue\n        except Exception:\n            return removed\n        return removed\n\n    # ---------- SERVICES (unchanged but with confirm wrappers) ----------\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  SERVICE KNOWLEDGE BASE\n    #  Category:  \"critical\"  = Windows ka dil \u2014 kabhi band mat karo\n    #             \"important\" = Windows ka kaam rukta hai \u2014 soch ke karo\n    #             \"optional\"  = Disable kar sakte ho \u2014 performance badhegi\n    #             \"thirdparty\"= Third-party software ki service\n    #  safe_to_stop: True/False \u2014 kya sirf stop safe hai\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    SVC_DB = {\n        # \u2500\u2500 CRITICAL \u2014 kabhi mat chhuo \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        \"lsass\":         {\"cat\":\"critical\",\"safe_to_stop\":False,\n                          \"desc\":\"Windows Login &amp; Security Authority. Isko band karna = Blue Screen ya instant shutdown.\",\n                          \"display\":\"Local Security Authority Process\"},\n        \"wininit\":       {\"cat\":\"critical\",\"safe_to_stop\":False,\n                          \"desc\":\"Windows Initialization. System start ke liye zaroori hai.\",\n                          \"display\":\"Windows Start-Up Application\"},\n        \"services\":      {\"cat\":\"critical\",\"safe_to_stop\":False,\n                          \"desc\":\"Saari services ka manager. Isko band karna = system crash.\",\n                          \"display\":\"Services and Controller app\"},\n        \"rpcss\":         {\"cat\":\"critical\",\"safe_to_stop\":False,\n                          \"desc\":\"RPC (Remote Procedure Call). Saare Windows components isko use karte hain.\",\n                          \"display\":\"Remote Procedure Call (RPC)\"},\n        \"dcomlaunch\":    {\"cat\":\"critical\",\"safe_to_stop\":False,\n                          \"desc\":\"COM Server launch. Explorer, taskbar sab band ho jaayenge.\",\n                          \"display\":\"DCOM Server Process Launcher\"},\n        \"plugplay\":      {\"cat\":\"critical\",\"safe_to_stop\":False,\n                          \"desc\":\"Hardware detect karta hai. USB, keyboard, mouse sab band ho jaayenge.\",\n                          \"display\":\"Plug and Play\"},\n        \"windefend\":     {\"cat\":\"critical\",\"safe_to_stop\":False,\n                          \"desc\":\"Windows Defender Antivirus. Virus protection band ho jaayegi.\",\n                          \"display\":\"Windows Defender Antivirus Service\"},\n        \"mpssvc\":        {\"cat\":\"critical\",\"safe_to_stop\":False,\n                          \"desc\":\"Windows Firewall. Internet security band ho jaayegi.\",\n                          \"display\":\"Windows Defender Firewall\"},\n        \"eventlog\":      {\"cat\":\"critical\",\"safe_to_stop\":False,\n                          \"desc\":\"System Event Log. Band karne se system instability aa sakti hai.\",\n                          \"display\":\"Windows Event Log\"},\n        \"nsi\":           {\"cat\":\"critical\",\"safe_to_stop\":False,\n                          \"desc\":\"Network Store Interface. Internet/network band ho jaayega.\",\n                          \"display\":\"Network Store Interface Service\"},\n        \"dhcp\":          {\"cat\":\"critical\",\"safe_to_stop\":False,\n                          \"desc\":\"IP Address automatic milti hai isse. Band = no internet.\",\n                          \"display\":\"DHCP Client\"},\n        \"dnscache\":      {\"cat\":\"critical\",\"safe_to_stop\":False,\n                          \"desc\":\"DNS Cache. Band karne se websites nahi khulengi.\",\n                          \"display\":\"DNS Client\"},\n        \"cryptsvc\":      {\"cat\":\"critical\",\"safe_to_stop\":False,\n                          \"desc\":\"Windows Updates aur certificates ke liye zaroori hai.\",\n                          \"display\":\"Cryptographic Services\"},\n        \"wuauserv\":      {\"cat\":\"critical\",\"safe_to_stop\":True,\n                          \"desc\":\"Windows Update. Stop kar sakte ho lekin security risk hai. Disable mat karo permanently.\",\n                          \"display\":\"Windows Update\"},\n        \"bits\":          {\"cat\":\"important\",\"safe_to_stop\":True,\n                          \"desc\":\"Background download manager. Windows updates isi se aate hain.\",\n                          \"display\":\"Background Intelligent Transfer Service\"},\n        \"spooler\":       {\"cat\":\"important\",\"safe_to_stop\":True,\n                          \"desc\":\"Printer service. Agar printer nahi use karte to stop kar sakte ho.\",\n                          \"display\":\"Print Spooler\"},\n        \"audiosrv\":      {\"cat\":\"important\",\"safe_to_stop\":False,\n                          \"desc\":\"Sound service. Band karne se koi awaz nahi aayegi.\",\n                          \"display\":\"Windows Audio\"},\n        \"audioendpointbuilder\":{\"cat\":\"important\",\"safe_to_stop\":False,\n                          \"desc\":\"Audio devices manager. Band = no sound.\",\n                          \"display\":\"Windows Audio Endpoint Builder\"},\n        \"netlogon\":      {\"cat\":\"important\",\"safe_to_stop\":True,\n                          \"desc\":\"Domain/network login ke liye. Home PC pe stop kar sakte ho.\",\n                          \"display\":\"Netlogon\"},\n        \"lanmanworkstation\":{\"cat\":\"important\",\"safe_to_stop\":True,\n                          \"desc\":\"Network shared folders access. Agar network nahi use karte to stop kar sakte ho.\",\n                          \"display\":\"Workstation\"},\n        \"lanmanserver\":  {\"cat\":\"important\",\"safe_to_stop\":True,\n                          \"desc\":\"Apni files share karne ke liye. Home use mein stop kar sakte ho.\",\n                          \"display\":\"Server\"},\n        \"themes\":        {\"cat\":\"important\",\"safe_to_stop\":True,\n                          \"desc\":\"Windows visual theme. Band karne se plain grey Windows dikhegi.\",\n                          \"display\":\"Themes\"},\n        \"winmgmt\":       {\"cat\":\"important\",\"safe_to_stop\":False,\n                          \"desc\":\"WMI \u2014 Hardware info, monitoring tools isi se kaam karte hain.\",\n                          \"display\":\"Windows Management Instrumentation\"},\n        \"schedule\":      {\"cat\":\"important\",\"safe_to_stop\":False,\n                          \"desc\":\"Task Scheduler. Band karne se system tasks nahi chalenge.\",\n                          \"display\":\"Task Scheduler\"},\n        \"seclogon\":      {\"cat\":\"important\",\"safe_to_stop\":True,\n                          \"desc\":\"Secondary Logon. Multiple user accounts ke liye. Home PC pe safe to stop.\",\n                          \"display\":\"Secondary Logon\"},\n        \"usermanager\":   {\"cat\":\"important\",\"safe_to_stop\":False,\n                          \"desc\":\"User account manager. Band karne se login problems.\",\n                          \"display\":\"User Manager\"},\n        # \u2500\u2500 OPTIONAL \u2014 safely disable kar sakte ho \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        \"sysmain\":       {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Superfetch/Prefetch \u2014 RAM mein programs preload karta hai. SSD pe disable karo \u2014 speed badhegi.\",\n                          \"display\":\"SysMain (Superfetch)\"},\n        \"wsearch\":       {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Windows Search Indexing \u2014 continuously disk scan karta hai. Agar search use nahi karte to disable karo.\",\n                          \"display\":\"Windows Search\"},\n        \"diagtrack\":     {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Microsoft Telemetry \u2014 aapki usage data Microsoft ko bhejta hai. Safely disable kar sakte ho.\",\n                          \"display\":\"Connected User Experiences and Telemetry\"},\n        \"dmwappushservice\":{\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"WAP Push Message Routing \u2014 zyada tar unnecessary hai. Safe to disable.\",\n                          \"display\":\"Device Management WAP Push message Routing Service\"},\n        \"xblAuthmanager\":{\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Xbox Live Authentication \u2014 gaming nahi karte to bilkul disable karo.\",\n                          \"display\":\"Xbox Live Auth Manager\"},\n        \"xboxnetapitsvc\":{\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Xbox networking \u2014 Xbox use nahi karte to disable karo.\",\n                          \"display\":\"Xbox Live Networking Service\"},\n        \"xblgamesave\":   {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Xbox game save sync \u2014 Xbox nahi use karte to disable.\",\n                          \"display\":\"Xbox Live Game Save\"},\n        \"retaildemo\":    {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Retail Demo Mode \u2014 shop display ke liye hai. Home PC pe bilkul disable karo.\",\n                          \"display\":\"Retail Demo Service\"},\n        \"mapsbrok\":      {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Windows Maps offline download. Maps use nahi karte to disable.\",\n                          \"display\":\"Downloaded Maps Manager\"},\n        \"fax\":           {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Fax service \u2014 2024 mein fax kaun karta hai? Disable karo.\",\n                          \"display\":\"Fax\"},\n        \"remoteregistry\":{\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Remote Registry access \u2014 Security risk! Disable karo immediately.\",\n                          \"display\":\"Remote Registry\"},\n        \"remoteaccess\":  {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Remote Access \u2014 agar koi remotely connect nahi karta to disable karo.\",\n                          \"display\":\"Routing and Remote Access\"},\n        \"wersvc\":        {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Windows Error Reporting \u2014 crash reports Microsoft ko bhejta hai. Disable kar sakte ho.\",\n                          \"display\":\"Windows Error Reporting Service\"},\n        \"printnotify\":   {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Printer notifications \u2014 printer nahi hai to disable karo.\",\n                          \"display\":\"Printer Extensions and Notifications\"},\n        \"sharedaccess\":  {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Internet Connection Sharing \u2014 router hai to ye zaruri nahi. Disable karo.\",\n                          \"display\":\"Internet Connection Sharing (ICS)\"},\n        \"sensrsvc\":      {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Sensor Service \u2014 laptop sensors (gyroscope etc). Desktop pe disable karo.\",\n                          \"display\":\"Sensor Service\"},\n        \"wbiosrvc\":      {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Windows Biometric (fingerprint/face ID). Use nahi karte to disable.\",\n                          \"display\":\"Windows Biometric Service\"},\n        \"tabletinputservice\":{\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Touch/Pen Input. Touchscreen/stylus nahi hai to disable karo.\",\n                          \"display\":\"Touch Keyboard and Handwriting Panel Service\"},\n        \"stisvc\":        {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Scanner/Camera service. Use nahi karte to disable.\",\n                          \"display\":\"Windows Image Acquisition (WIA)\"},\n    }\n\n    # Tag colors per category\n    SVC_TAG_COLORS = {\n        \"critical\":   \"#FF4444\",   # Lal \u2014 danger\n        \"important\":  \"#FF9800\",   # Orange \u2014 warning\n        \"optional\":   \"#4CAF50\",   # Green \u2014 safe to touch\n        \"thirdparty\": \"#CE93D8\",   # Purple \u2014 third party\n        \"highcpu\":    \"#FF6B35\",   # Deep orange \u2014 high CPU\n        \"highmem\":    \"#FFD700\",   # Gold \u2014 high RAM\n    }\n\n    def _build_services(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\u2699\ufe0f Smart Services Manager\",\n                             \"Color-coded \u2014 Critical / Important / Optional / Third-Party\")\n\n        self._action_card_grid(frame, [\n            (\"\ud83d\udd0d\", \"Scan All Services\",    \"Saari services scan karo\",            C[\"btn_info\"],   self._scan_impacting_services),\n            (\"\u26d4\", \"Stop Selected\",        \"Selected services band karo\",          C[\"btn_danger\"], lambda: self._svc_action_safe(\"stop\")),\n            (\"\u2705\", \"Start Selected\",       \"Selected services shuru karo\",         C[\"btn\"],        lambda: self._with_confirm(\"Start Services\",\"Start selected services?\", self._start_services)),\n            (\"\ud83d\udeab\", \"Disable Selected\",     \"Selected services disable karo\",       C[\"btn_warn\"],   lambda: self._svc_action_safe(\"disable\")),\n            (\"\u26a1\", \"Disable All Optional\", \"Saari optional services ek click mein\",C[\"btn_chip\"],   self._disable_all_optional),\n            (\"\ud83d\udcbb\", \"Pack: SSD Laptop\",     \"SSD laptop ke liye best preset\",       C[\"btn_chip\"],   lambda: self._svc_apply_pack(\"ssd_laptop\")),\n            (\"\ud83d\udda5\",  \"Pack: HDD Desktop\",   \"HDD desktop ke liye best preset\",      C[\"btn_chip\"],   lambda: self._svc_apply_pack(\"hdd_desktop\")),\n            (\"\u21a9\",  \"Restore Snapshot\",    \"Pehle wali state wapas lao\",           C[\"btn_info\"],   self._svc_restore_snapshot),\n        ], cols=4)\n\n        # \u2500\u2500 Legend \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        leg = tk.Frame(frame, bg=C[\"bg\"])\n        leg.pack(fill=\"x\", padx=16, pady=(4,0))\n        legends = [\n            (\"\ud83d\udd34 Critical \u2014 Kabhi band mat karo\",     \"#FF4444\"),\n            (\"\ud83d\udfe0 Important \u2014 Soch ke band karo\",      \"#FF9800\"),\n            (\"\ud83d\udfe2 Optional \u2014 Safely disable kar sakte\", \"#4CAF50\"),\n            (\"\ud83d\udfe3 Third-Party Software\",                \"#CE93D8\"),\n            (\"\ud83d\udfe1 High RAM Use\",                        \"#FFD700\"),\n            (\"\ud83d\udd36 High CPU Use\",                        \"#FF6B35\"),\n        ]\n        for i, (txt, col) in enumerate(legends):\n            tk.Label(leg, text=txt, font=FONTS[\"small\"], fg=col,\n                     bg=C[\"bg\"]).grid(row=i//3, column=i%3, sticky=\"w\", padx=12, pady=1)\n\n        # \u2500\u2500 Filter bar \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        fbar = tk.Frame(frame, bg=C[\"bg\"])\n        fbar.pack(fill=\"x\", padx=16, pady=(4,2))\n        tk.Label(fbar, text=\"Filter:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"]).pack(side=\"left\")\n        self.svc_search = tk.Entry(fbar, width=22, font=FONTS[\"body\"],\n                                   bg=C[\"card\"], fg=C[\"text\"],\n                                   insertbackground=C[\"text\"], relief=\"flat\", bd=4)\n        self.svc_search.pack(side=\"left\", padx=6)\n        self.svc_search.bind(\"\", self._filter_services)\n        for lbl, val in [(\"All\",\"all\"),(\"\ud83d\udd34 Critical\",\"critical\"),\n                         (\"\ud83d\udfe0 Important\",\"important\"),(\"\ud83d\udfe2 Optional\",\"optional\"),\n                         (\"\ud83d\udfe3 3rd Party\",\"thirdparty\"),(\"\ud83d\udfe1 High RAM\",\"highmem\"),\n                         (\"\ud83d\udd36 High CPU\",\"highcpu\")]:\n            tk.Button(fbar, text=lbl, font=FONTS[\"small\"],\n                      bg=C[\"card\"], fg=C[\"text\"], bd=0, padx=8, pady=3,\n                      cursor=\"hand2\",\n                      command=lambda v=val: self._filter_by_cat(v)).pack(side=\"left\", padx=2)\n\n        self.svc_count_lbl = tk.Label(fbar, text=\"\", font=FONTS[\"small\"],\n                                      fg=C[\"accent\"], bg=C[\"bg\"])\n        self.svc_count_lbl.pack(side=\"right\", padx=8)\n\n        metric_bar = tk.Frame(frame, bg=C[\"bg\"])\n        metric_bar.pack(fill=\"x\", padx=16, pady=(4,4))\n        self.svc_scan_status_lbl = tk.Label(metric_bar, text=\"Ready to scan services\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"])\n        self.svc_scan_status_lbl.pack(side=\"left\")\n        self.svc_risk_score_var = tk.StringVar(value=\"--\")\n        self.svc_potential_free_var = tk.StringVar(value=\"--\")\n        for label, var in [(\"Risk Score\", self.svc_risk_score_var), (\"Potential RAM\", self.svc_potential_free_var)]:\n            card = tk.Frame(metric_bar, bg=C[\"card\"], padx=8, pady=6)\n            card.pack(side=\"right\", padx=4)\n            tk.Label(card, text=label, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\")\n            tk.Label(card, textvariable=var, font=(\"Segoe UI\", 13, \"bold\"), fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\")\n\n        # \u2500\u2500 Paned layout \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        paned = tk.Frame(frame, bg=C[\"bg\"])\n        paned.pack(fill=\"both\", expand=True, padx=16, pady=(4,8))\n        paned.columnconfigure(0, weight=3)\n        paned.columnconfigure(1, weight=2)\n        paned.rowconfigure(0, weight=1)\n\n        # Left \u2014 service list\n        left = tk.Frame(paned, bg=C[\"card\"])\n        left.grid(row=0, column=0, sticky=\"nsew\", padx=(0,6))\n        cols = (\"Cat\",\"Name\",\"Display Name\",\"Status\",\"CPU%\",\"RAM MB\",\"Safe Stop?\")\n        self.svc_tree = ttk.Treeview(left, columns=cols, show=\"headings\",\n                                     height=22, style=\"Custom.Treeview\",\n                                     selectmode=\"extended\")\n        widths = [28, 160, 210, 75, 55, 70, 80]\n        for col, w in zip(cols, widths):\n            self.svc_tree.heading(col, text=col,\n                                  command=lambda c=col: self._sort_svc(c))\n            self.svc_tree.column(col, width=w,\n                                 anchor=\"center\" if col in (\"Cat\",\"Status\",\"CPU%\",\"RAM MB\",\"Safe Stop?\") else \"w\")\n\n        # Color tags\n        for tag, color in self.SVC_TAG_COLORS.items():\n            self.svc_tree.tag_configure(tag, foreground=color)\n        self.svc_tree.tag_configure(\"highcpu_bg\", background=\"#2A1500\")\n        self.svc_tree.tag_configure(\"highmem_bg\", background=\"#1A1A00\")\n\n        vsb = ttk.Scrollbar(left, orient=\"vertical\", command=self.svc_tree.yview)\n        self.svc_tree.configure(yscrollcommand=vsb.set)\n        self.svc_tree.pack(side=\"left\", fill=\"both\", expand=True, padx=(4,0), pady=4)\n        vsb.pack(side=\"right\", fill=\"y\", pady=4)\n        self.svc_tree.bind(\"&lt;&gt;\", self._on_svc_select)\n\n        # Right \u2014 detail panel\n        right = tk.Frame(paned, bg=C[\"card\"])\n        right.grid(row=0, column=1, sticky=\"nsew\")\n        right.rowconfigure(1, weight=1)\n        right.columnconfigure(0, weight=1)\n\n        tk.Label(right, text=\"  \ud83d\udccb Service Detail &amp; Risk Info\",\n                 font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(\n                 anchor=\"w\", pady=(8,4), padx=8)\n\n        self.svc_detail = scrolledtext.ScrolledText(\n            right, font=(\"Consolas\", 9), bg=\"#0D1117\", fg=C[\"text\"],\n            height=16, bd=0, relief=\"flat\", state=\"disabled\", wrap=\"word\")\n        self.svc_detail.pack(fill=\"both\", expand=True, padx=8, pady=(0,6))\n        self.svc_action_log = self.svc_detail\n\n        # Risk summary cards at bottom of right panel\n        rsum = tk.Frame(right, bg=C[\"card\"])\n        rsum.pack(fill=\"x\", padx=8, pady=(0,8))\n        self.svc_summary_vars = {}\n        for i, (k, lbl, col) in enumerate([\n            (\"critical\",   \"Critical\",    \"#FF4444\"),\n            (\"important\",  \"Important\",   \"#FF9800\"),\n            (\"optional\",   \"Optional\",    \"#4CAF50\"),\n            (\"thirdparty\", \"3rd Party\",   \"#CE93D8\"),\n        ]):\n            rsum.columnconfigure(i, weight=1)\n            card = tk.Frame(rsum, bg=C[\"bg\"], padx=6, pady=6)\n            card.grid(row=0, column=i, padx=3, sticky=\"ew\")\n            tk.Label(card, text=lbl, font=FONTS[\"small\"],\n                     fg=col, bg=C[\"bg\"]).pack(anchor=\"w\")\n            v = tk.StringVar(value=\"--\")\n            self.svc_summary_vars[k] = v\n            tk.Label(card, textvariable=v, font=(\"Segoe UI\",15,\"bold\"),\n                     fg=col, bg=C[\"bg\"]).pack(anchor=\"w\")\n\n        # Internal state\n        self._svc_all_rows = []   # (values_tuple, tags_tuple, meta_dict)\n        self._svc_cur_filter_cat = \"all\"\n        self._svc_sort_col = \"\"\n        self._svc_sort_rev = False\n        return frame\n\n    def _with_confirm(self, title, msg, action):\n        if messagebox.askyesno(title, msg):\n            action()\n\n    # \u2500\u2500 Service scan \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _scan_impacting_services(self):\n        self._set_status(\"Queued: Scanning services...\", C[\"accent4\"])\n        self._submit_ram_service_job(\"service_scan\", self._do_scan_services)\n\n    def _do_scan_services(self):\n        try:\n            self.after(0, lambda: [self.svc_tree.delete(i) for i in self.svc_tree.get_children()])\n        except Exception:\n            pass\n\n        pid_cpu, pid_mem = {}, {}\n        try:\n            for p in psutil.process_iter(['pid','cpu_percent','memory_info']):\n                try:\n                    pid_cpu[p.info['pid']] = p.info['cpu_percent'] or 0\n                    mem = p.info.get('memory_info')\n                    pid_mem[p.info['pid']] = round(mem.rss/(1024**2),1) if mem else 0\n                except Exception:\n                    pass\n        except Exception:\n            pass\n\n        THIRD_PARTY_PATHS = {\n            \"nvidia\",\"amd\",\"intel graphics\",\"realtek\",\"qualcomm\",\"broadcom\",\n            \"avast\",\"avg\",\"kaspersky\",\"mcafee\",\"norton\",\"malwarebytes\",\"bitdefender\",\n            \"adobe\",\"acrobat\",\"google\",\"chrome\",\"dropbox\",\"onedrive\",\"teams\",\n            \"skype\",\"zoom\",\"spotify\",\"discord\",\"steam\",\"epic games\",\"origin\",\n            \"vmware\",\"virtualbox\",\"ccleaner\",\"iobit\",\"razer\",\"corsair\",\"logitech\",\n            \"hp\",\"dell\",\"lenovo\",\"asus\",\"acer\",\"samsung\",\"brother\",\"canon\",\"epson\",\n        }\n\n        try:\n            services = list(psutil.win_service_iter())\n        except Exception:\n            services = []\n        total_services = max(1, len(services))\n\n        rows = []\n        cat_counts = {\"critical\":0,\"important\":0,\"optional\":0,\"thirdparty\":0}\n        batch = {\n            \"phase\":\"service_scan\",\n            \"status_text\":\"Scanning services...\",\n            \"progress_pct\":0,\n            \"services_scanned\":0,\n            \"high_cpu\":0,\n            \"high_mem\":0,\n            \"critical\":0,\n            \"important\":0,\n            \"optional\":0,\n            \"thirdparty\":0,\n            \"estimated_ram_mb\":0,\n            \"risk_score\":0,\n        }\n        last_dispatch = time.time()\n\n        def dispatch_metrics():\n            try:\n                points = (batch[\"critical\"] * 6 + batch[\"important\"] * 4 + batch[\"thirdparty\"] * 2 + batch[\"high_cpu\"] * 3 + batch[\"high_mem\"] * 3)\n                max_points = max(1, total_services * 6)\n                batch[\"risk_score\"] = min(100, int((points / max_points) * 100))\n                batch[\"progress_pct\"] = min(100.0, (batch[\"services_scanned\"] / total_services) * 100.0)\n                batch[\"status_text\"] = f\"Scanning services... {batch['services_scanned']}/{total_services}\"\n                self._ram_service_metrics_queue.put(batch.copy())\n            except Exception:\n                pass\n\n        for svc in services:\n            try:\n                info = svc.as_dict()\n                name = info.get('name', '')\n                dname = info.get('display_name', '')\n                pid = info.get('pid', 0) or 0\n                cpu_p = pid_cpu.get(pid, 0)\n                mem_mb = pid_mem.get(pid, 0)\n                status = info.get('status', '')\n                start = info.get('start_type', '')\n\n                name_lo = name.lower()\n                in_db = name_lo in self.SVC_DB\n                high_cpu = cpu_p &gt; 10\n                high_mem = mem_mb &gt; 150\n\n                if not in_db and not high_cpu and not high_mem:\n                    continue\n\n                if in_db:\n                    meta = self.SVC_DB[name_lo]\n                    cat = meta[\"cat\"]\n                    safe = meta[\"safe_to_stop\"]\n                    desc = meta[\"desc\"]\n                else:\n                    dname_lo = dname.lower()\n                    is_third = any(tp in dname_lo for tp in THIRD_PARTY_PATHS)\n                    if is_third:\n                        cat = \"thirdparty\"\n                        safe = True\n                        desc = (f\"Third-party service: '{dname}'.\\n\"\n                                \"Yeh kisi installed software ki service hai.\\n\"\n                                \"Agar woh software uninstall kar diya hai to safely disable kar sakte ho.\\n\"\n                                \"Agar software use karte ho to band mat karo.\")\n                    else:\n                        cat = \"optional\"\n                        safe = True\n                        desc = (\"Yeh service hamare database mein nahi hai.\\n\"\n                                \"Stop karne se pehle naam search karo Google pe.\\n\"\n                                \"High resource use ho raha hai \u2014 monitor karein.\")\n\n                tags = [cat]\n                if high_cpu:\n                    tags.append(\"highcpu\")\n                if high_mem:\n                    tags.append(\"highmem\")\n\n                safe_txt = \"\u2705 Haan\" if safe else \"\u274c Nahi\"\n                cat_icon = {\"critical\":\"\ud83d\udd34\",\"important\":\"\ud83d\udfe0\",\n                            \"optional\":\"\ud83d\udfe2\",\"thirdparty\":\"\ud83d\udfe3\"}.get(cat, \"\u26aa\")\n\n                row = (cat_icon, name, dname[:42], status,\n                       f\"{cpu_p:.1f}\", f\"{mem_mb:.1f}\", safe_txt)\n                meta_full = {\n                    \"name\": name, \"dname\": dname, \"cat\": cat,\n                    \"safe\": safe, \"desc\": desc, \"cpu\": cpu_p,\n                    \"mem\": mem_mb, \"status\": status, \"start\": start, \"pid\": pid\n                }\n                rows.append((row, tuple(tags), meta_full))\n                if cat in cat_counts:\n                    cat_counts[cat] += 1\n                batch[\"services_scanned\"] += 1\n                batch[\"high_cpu\"] += 1 if high_cpu else 0\n                batch[\"high_mem\"] += 1 if high_mem else 0\n                batch[cat] += 1\n                batch[\"estimated_ram_mb\"] += mem_mb if high_mem else 0\n            except Exception:\n                pass\n            if time.time() - last_dispatch &gt;= 0.12:\n                dispatch_metrics()\n                last_dispatch = time.time()\n\n        dispatch_metrics()\n        batch[\"status_text\"] = f\"Service scan complete \u2014 {len(rows)} relevant services\"\n        batch[\"progress_pct\"] = 100.0\n        self._ram_service_metrics_queue.put(batch.copy())\n\n        self._svc_all_rows = rows\n\n        def insert():\n            self._render_svc_rows(rows)\n            for k, v in cat_counts.items():\n                self.svc_summary_vars[k].set(str(v))\n            self._set_status(\n                f\"Scan done \u2014 {len(rows)} services | \"\n                f\"\ud83d\udd34{cat_counts['critical']} Critical | \"\n                f\"\ud83d\udfe0{cat_counts['important']} Important | \"\n                f\"\ud83d\udfe2{cat_counts['optional']} Optional | \"\n                f\"\ud83d\udfe3{cat_counts['thirdparty']} 3rd-Party\",\n                C[\"success\"])\n        self.after(0, insert)\n\n    def _render_svc_rows(self, rows):\n        for i in self.svc_tree.get_children():\n            self.svc_tree.delete(i)\n        for row, tags, _ in rows:\n            self.svc_tree.insert(\"\", \"end\", values=row, tags=tags)\n        self.svc_count_lbl.config(text=f\"{len(rows)} services\")\n\n    # \u2500\u2500 Filter / Sort \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _filter_services(self, event=None):\n        text = self.svc_search.get().lower()\n        cat  = self._svc_cur_filter_cat\n        filtered = [\n            r for r in self._svc_all_rows\n            if (cat == \"all\" or cat in r[1])\n            and (not text or text in r[2][\"name\"].lower()\n                 or text in r[2][\"dname\"].lower())\n        ]\n        self._render_svc_rows(filtered)\n\n    def _filter_by_cat(self, cat):\n        self._svc_cur_filter_cat = cat\n        self._filter_services()\n\n    def _sort_svc(self, col):\n        col_map = {\"Cat\":0,\"Name\":1,\"Display Name\":2,\"Status\":3,\n                   \"CPU%\":4,\"RAM MB\":5,\"Safe Stop?\":6}\n        idx = col_map.get(col, 1)\n        if self._svc_sort_col == col:\n            self._svc_sort_rev = not self._svc_sort_rev\n        else:\n            self._svc_sort_col = col\n            self._svc_sort_rev = False\n        try:\n            self._svc_all_rows.sort(\n                key=lambda r: float(r[0][idx]) if r[0][idx].replace('.','').isdigit()\n                              else r[0][idx],\n                reverse=self._svc_sort_rev)\n        except: pass\n        self._filter_services()\n\n    # \u2500\u2500 Selection detail panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _on_svc_select(self, event=None):\n        sel = self.svc_tree.selection()\n        if not sel:\n            return\n        iid = sel[0]\n        idx = self.svc_tree.index(iid)\n        # Find matching meta from filtered list\n        visible = [r for r in self._svc_all_rows\n                   if self._svc_cur_filter_cat == \"all\"\n                   or self._svc_cur_filter_cat in r[1]]\n        search_txt = self.svc_search.get().lower()\n        if search_txt:\n            visible = [r for r in visible\n                       if search_txt in r[2][\"name\"].lower()\n                       or search_txt in r[2][\"dname\"].lower()]\n        if idx &gt;= len(visible):\n            return\n        meta = visible[idx][2]\n\n        cat     = meta[\"cat\"]\n        safe    = meta[\"safe\"]\n        desc    = meta[\"desc\"]\n        cpu     = meta[\"cpu\"]\n        mem     = meta[\"mem\"]\n        status  = meta[\"status\"]\n        name    = meta[\"name\"]\n        dname   = meta[\"dname\"]\n\n        cat_label = {\n            \"critical\":   \"\ud83d\udd34 CRITICAL \u2014 Kabhi band mat karo\",\n            \"important\":  \"\ud83d\udfe0 IMPORTANT \u2014 Soch ke band karo\",\n            \"optional\":   \"\ud83d\udfe2 OPTIONAL \u2014 Safely disable kar sakte ho\",\n            \"thirdparty\": \"\ud83d\udfe3 THIRD-PARTY \u2014 Software ki service\",\n        }.get(cat, \"\u26aa Unknown\")\n\n        stop_warning = {\n            \"critical\": (\n                \"\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\\n\"\n                \"\u2551  \u26d4 DANGER \u2014 IS SERVICE KO BAND MAT KARO \u2551\\n\"\n                \"\u255a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255d\\n\"\n                \"Yeh Windows ka core component hai.\\n\"\n                \"Band karne se BLUE SCREEN / CRASH / FREEZE ho sakta hai!\\n\"\n            ),\n            \"important\": (\n                \"\u26a0\ufe0f  SAWDHAN \u2014 Band karne se Windows ka koi feature\\n\"\n                \"   kaam karna band kar sakta hai. Pehle samjho\\n\"\n                \"   kya hoga, phir decide karo.\\n\"\n            ),\n            \"optional\": (\n                \"\u2705 SAFE \u2014 Yeh service band kar sakte ho.\\n\"\n                \"   Performance behtar hogi. System harm nahi hoga.\\n\"\n            ),\n            \"thirdparty\": (\n                \"\ud83d\udfe3 THIRD-PARTY \u2014 Kisi installed software ki service hai.\\n\"\n                \"   Agar woh software use karte ho: BAND MAT KARO.\\n\"\n                \"   Agar woh software uninstall ho gaya hai: Safely disable karo.\\n\"\n            ),\n        }.get(cat, \"\")\n\n        lines = [\n            f\"Service Name  : {name}\",\n            f\"Display Name  : {dname}\",\n            f\"Category      : {cat_label}\",\n            f\"Current Status: {status}\",\n            f\"CPU Usage     : {cpu:.1f}%{'  \u26a0 HIGH!' if cpu&gt;10 else ''}\",\n            f\"RAM Usage     : {mem:.1f} MB{'  \u26a0 HIGH!' if mem&gt;150 else ''}\",\n            f\"Safe to Stop? : {'\u2705 Haan \u2014 band kar sakte ho' if safe else '\u274c Nahi \u2014 band karna dangerous hai'}\",\n            \"\",\n            \"\u2500\"*50,\n            \"\",\n            \"\ud83d\udcd6 DESCRIPTION:\",\n            desc,\n            \"\",\n            \"\u2500\"*50,\n            \"\",\n            \"\u26a0\ufe0f  STOP/DISABLE KARNE SE KYA HOGA:\",\n            stop_warning,\n        ]\n        if cpu &gt; 10:\n            lines += [\"\",\"\ud83d\udd36 HIGH CPU ALERT:\",\n                      f\"   Yeh service {cpu:.1f}% CPU le rahi hai.\",\n                      \"   Agar zaroori nahi to stop karo.\"]\n        if mem &gt; 150:\n            lines += [\"\",\"\ud83d\udfe1 HIGH RAM ALERT:\",\n                      f\"   Yeh service {mem:.1f} MB RAM use kar rahi hai.\",\n                      \"   Stop karne se RAM free hogi.\"]\n\n        self.svc_detail.config(state=\"normal\")\n        self.svc_detail.delete(\"1.0\",\"end\")\n        # Color different parts\n        self.svc_detail.tag_configure(\"red\",    foreground=\"#FF4444\")\n        self.svc_detail.tag_configure(\"orange\", foreground=\"#FF9800\")\n        self.svc_detail.tag_configure(\"green\",  foreground=\"#4CAF50\")\n        self.svc_detail.tag_configure(\"purple\", foreground=\"#CE93D8\")\n        self.svc_detail.tag_configure(\"gold\",   foreground=\"#FFD700\")\n        self.svc_detail.tag_configure(\"dim\",    foreground=\"#A0B0C8\")\n        self.svc_detail.tag_configure(\"bold\",   foreground=C[\"text\"])\n\n        for line in lines:\n            color_tag = \"bold\"\n            if \"DANGER\" in line or \"\u274c\" in line:     color_tag = \"red\"\n            elif \"SAWDHAN\" in line or \"\u26a0\ufe0f\" in line:  color_tag = \"orange\"\n            elif \"SAFE\" in line or \"\u2705\" in line:     color_tag = \"green\"\n            elif \"THIRD-PARTY\" in line or \"\ud83d\udfe3\" in line: color_tag = \"purple\"\n            elif \"HIGH\" in line and \"ALERT\" in line: color_tag = \"gold\"\n            elif line.startswith(\"\u2500\"):               color_tag = \"dim\"\n            self.svc_detail.insert(\"end\", line+\"\\n\", color_tag)\n        self.svc_detail.config(state=\"disabled\")\n\n    # \u2500\u2500 Safe stop/disable with category warning \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _svc_action_safe(self, action):\n        sel = self.svc_tree.selection()\n        if not sel:\n            messagebox.showinfo(\"No Selection\", \"Pehle ek service select karo.\")\n            return\n        # Check all selected for critical/important\n        block = []\n        warn  = []\n        names = []\n        visible = self._get_visible_svc_rows()\n        for iid in sel:\n            idx = self.svc_tree.index(iid)\n            if idx &gt;= len(visible): continue\n            meta = visible[idx][2]\n            cat  = meta[\"cat\"]\n            name = meta[\"name\"]\n            safe = meta[\"safe\"]\n            names.append(name)\n            if not safe:\n                block.append(f\"  \ud83d\udd34 {name} ({meta['dname']}) \u2014 CRITICAL, band NAHI karna chahiye!\")\n            elif cat == \"important\":\n                warn.append(f\"  \ud83d\udfe0 {name} ({meta['dname']}) \u2014 Important service, dhyan se!\")\n\n        if block:\n            messagebox.showerror(\"\u26d4 KHATARNAK SERVICE SELECTED!\",\n                \"Neeche di gayi services CRITICAL hain.\\n\"\n                \"Inhe band karne se system crash ho sakta hai!\\n\\n\"\n                + \"\\n\".join(block) +\n                \"\\n\\nIn services ko DESELECT karo aur dubara try karo.\")\n            return\n\n        confirm_msg = f\"{'Disable' if action=='disable' else 'Stop'} karne se ye services band ho jaayengi:\\n\\n\"\n        confirm_msg += \"\\n\".join(f\"  \u2022 {n}\" for n in names)\n        if warn:\n            confirm_msg += \"\\n\\n\u26a0\ufe0f SAWDHAN \u2014 Ye services Important hain:\\n\" + \"\\n\".join(warn)\n        # Dependency awareness: show dependents (services that rely on this one)\n        dep_warn = []\n        dep_block = []\n        for n in names:\n            deps = self._service_dependents(n)\n            if not deps:\n                continue\n            running = []\n            for dn in deps[:12]:\n                st, _ = self._service_state(dn)\n                if st and st != \"STOPPED\":\n                    running.append(dn)\n            if action == \"disable\":\n                dep_warn.append(f\"  \u26a0 {n} ke dependents: {', '.join(deps[:8])}\" + (\"...\" if len(deps) &gt; 8 else \"\"))\n            else:\n                if running:\n                    dep_block.append(f\"  \u26d4 {n} ke running dependents: {', '.join(running[:8])}\" + (\"...\" if len(running) &gt; 8 else \"\"))\n                else:\n                    dep_warn.append(f\"  \u26a0 {n} ke dependents: {', '.join(deps[:8])}\" + (\"...\" if len(deps) &gt; 8 else \"\"))\n        if dep_block:\n            messagebox.showerror(\n                \"\u26d4 Dependent Services Running\",\n                \"Selected service(s) par kuch services dependent hain aur abhi RUNNING hain.\\n\"\n                \"Pehle dependents stop karo (ya unko deselect karo), phir try karo.\\n\\n\"\n                + \"\\n\".join(dep_block)\n            )\n            return\n        if dep_warn:\n            confirm_msg += \"\\n\\n\ud83d\udd17 DEPENDENCY WARNING:\\n\" + \"\\n\".join(dep_warn)\n        confirm_msg += f\"\\n\\n{'Disable karne se ye restart pe nahi chalegi.' if action=='disable' else 'Stop karne se ye tab tak nahi chalegi jab tak restart nahi karte.'}\\n\\nAage badhein?\"\n\n        if not messagebox.askyesno(\n                \"\u26a0\ufe0f Confirm \u2014 Service \" + (\"Disable\" if action==\"disable\" else \"Stop\"),\n                confirm_msg):\n            return\n\n        results = []\n        if action == \"disable\":\n            self._svc_save_start_mode_snapshot(names)\n        for name in names:\n            if action == \"stop\":\n                results.append(self._service_stop_checked(name))\n            else:\n                results.append(self._service_config_checked(name, \"disabled\"))\n                results.append(self._service_stop_checked(name))\n        summary = self._action_summary(\"Service \" + (\"Disable\" if action == \"disable\" else \"Stop\"), results)\n        messagebox.showinfo(\"Already Done\" if summary[\"already_done\"] else \"Done\", summary[\"message\"])\n        self._scan_impacting_services()\n\n    def _get_visible_svc_rows(self):\n        cat = self._svc_cur_filter_cat\n        txt = self.svc_search.get().lower() if hasattr(self,'svc_search') else \"\"\n        rows = self._svc_all_rows\n        if cat != \"all\":\n            rows = [r for r in rows if cat in r[1]]\n        if txt:\n            rows = [r for r in rows if txt in r[2][\"name\"].lower()\n                    or txt in r[2][\"dname\"].lower()]\n        return rows\n\n    def _disable_all_optional(self):\n        optional = [r for r in self._svc_all_rows if \"optional\" in r[1]]\n        if not optional:\n            messagebox.showinfo(\"Koi Service Nahi\",\n                \"Pehle 'Scan All Services' karo.\")\n            return\n        names = [r[2][\"name\"] for r in optional]\n        msg = (f\"Neeche di gayi {len(names)} Optional services disable ho jaayengi:\\n\\n\"\n               + \"\\n\".join(f\"  \ud83d\udfe2 {n}\" for n in names[:15])\n               + (f\"\\n  ...aur {len(names)-15} aur\" if len(names)&gt;15 else \"\")\n               + \"\\n\\nYe sab safely disable ho sakti hain.\\nKya aage badhein?\")\n        if messagebox.askyesno(\"\u26a1 Disable All Optional\", msg):\n            results = []\n            self._svc_save_start_mode_snapshot(names)\n            for name in names:\n                results.append(self._service_config_checked(name, \"disabled\"))\n                results.append(self._service_stop_checked(name))\n            summary = self._action_summary(\"Optional Services\", results)\n            messagebox.showinfo(\"Already Done\" if summary[\"already_done\"] else \"Done!\", summary[\"message\"] + \"\\nRestart karo best results ke liye.\")\n            self._scan_impacting_services()\n\n    def _stop_services(self):\n        results = []\n        for iid in self.svc_tree.selection():\n            name = self.svc_tree.item(iid, \"values\")[1]\n            results.append(self._service_stop_checked(name))\n        if results:\n            summary = self._action_summary(\"Service Stop\", results)\n            messagebox.showinfo(\"Already Done\" if summary[\"already_done\"] else \"Done\", summary[\"message\"])\n        self._scan_impacting_services()\n\n    def _start_services(self):\n        results = []\n        for iid in self.svc_tree.selection():\n            name = self.svc_tree.item(iid, \"values\")[1]\n            results.append(self._service_start_checked(name))\n        if results:\n            summary = self._action_summary(\"Service Start\", results)\n            messagebox.showinfo(\"Already Done\" if summary[\"already_done\"] else \"Done\", summary[\"message\"])\n        self._scan_impacting_services()\n\n    def _disable_services(self):\n        results = []\n        for iid in self.svc_tree.selection():\n            name = self.svc_tree.item(iid, \"values\")[1]\n            results.append(self._service_config_checked(name, \"disabled\"))\n        if results:\n            summary = self._action_summary(\"Service Disable\", results)\n            messagebox.showinfo(\"Already Done\" if summary[\"already_done\"] else \"Done\", summary[\"message\"])\n        self._scan_impacting_services()\n\n    # ---------- RAM OPTIMIZER (with Before/After) ----------\n    def _build_memory(self, parent):\n        root = tk.Frame(parent, bg=C[\"bg\"])\n        canvas = tk.Canvas(root, bg=C[\"bg\"], highlightthickness=0)\n        scrollbar = ttk.Scrollbar(root, orient=\"vertical\", command=canvas.yview)\n        inner = tk.Frame(canvas, bg=C[\"bg\"])\n        inner.bind(\"\", lambda e: canvas.configure(scrollregion=canvas.bbox(\"all\")))\n        inner_window = canvas.create_window((0, 0), window=inner, anchor=\"nw\")\n        canvas.configure(yscrollcommand=scrollbar.set)\n        scrollbar.pack(side=\"right\", fill=\"y\")\n        canvas.pack(side=\"left\", fill=\"both\", expand=True)\n\n        def _resize_inner(event):\n            try:\n                canvas.itemconfigure(inner_window, width=event.width)\n                canvas.configure(scrollregion=canvas.bbox(\"all\"))\n            except Exception:\n                pass\n\n        canvas.bind(\"\", _resize_inner)\n        self._bind_scoped_mousewheel(inner, canvas)\n\n        frame = inner\n        self._section_header(frame, \"\ud83e\udde0 RAM Optimizer\", \"Free up RAM memory - WORKING\")\n        stats = tk.Frame(frame, bg=C[\"bg\"])\n        stats.pack(fill=\"x\", padx=16, pady=8)\n        self.ram_cards = {}\n        for i, (k, lbl, color) in enumerate([(\"total\",\"Total RAM\",C[\"text\"]), (\"used\",\"Used RAM\",C[\"error\"]), (\"free\",\"Free RAM\",C[\"success\"]), (\"cached\",\"Cache\",C[\"accent4\"])]):\n            card = self._stat_card(stats, lbl, \"--\", color)\n            card.grid(row=0, column=i, padx=6, sticky=\"ew\")\n            stats.columnconfigure(i, weight=1)\n            self.ram_cards[k] = card\n        monitor = tk.Frame(frame, bg=C[\"bg\"])\n        monitor.pack(fill=\"x\", padx=16, pady=(0,8))\n        self.ram_operation_progress_var = tk.DoubleVar(value=0.0)\n        self.ram_operation_progress_bar = ttk.Progressbar(monitor,\n                                                         variable=self.ram_operation_progress_var,\n                                                         maximum=100, mode=\"determinate\")\n        self.ram_operation_progress_bar.pack(fill=\"x\", padx=2, pady=(0,4))\n        self.ram_operation_status_lbl = tk.Label(monitor, text=\"Ready\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"])\n        self.ram_operation_status_lbl.pack(anchor=\"w\", pady=(0,4))\n        metrics = tk.Frame(monitor, bg=C[\"bg\"])\n        metrics.pack(fill=\"x\")\n        self.ram_predicted_free_var = tk.StringVar(value=\"--\")\n        self.ram_confidence_var = tk.StringVar(value=\"--\")\n        self.ram_delta_var = tk.StringVar(value=\"--\")\n        for label, var, fg in [\n            (\"Predicted Free\", self.ram_predicted_free_var, C[\"success\"]),\n            (\"Confidence\", self.ram_confidence_var, C[\"accent4\"]),\n            (\"Delta\", self.ram_delta_var, C[\"warning\"]),\n        ]:\n            card = tk.Frame(metrics, bg=C[\"card\"], padx=8, pady=8)\n            card.pack(side=\"left\", fill=\"x\", expand=True, padx=3)\n            tk.Label(card, text=label, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\")\n            tk.Label(card, textvariable=var, font=(\"Segoe UI\", 14, \"bold\"), fg=fg, bg=C[\"card\"]).pack(anchor=\"w\")\n        mid = tk.Frame(frame, bg=C[\"bg\"])\n        mid.pack(fill=\"both\", expand=True, padx=16, pady=8)\n        mid.columnconfigure(0, weight=1)\n        mid.columnconfigure(1, weight=1)\n        left = tk.Frame(mid, bg=C[\"card\"])\n        left.grid(row=0, column=0, sticky=\"nsew\", padx=(0,6))\n        tk.Label(left, text=\"  RAM Tools\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8,6), padx=8)\n        self._action_card_grid(left, [\n            (\"\ud83d\ude80\", \"Aggressive RAM Boost\",  \"Full RAM free karo\",            C[\"btn_info\"], self._ram_boost_with_confirm),\n            (\"\ud83d\udd04\", \"Empty Working Sets\",    \"Working sets clear karo\",       C[\"btn_info\"], self._ram_empty_with_confirm),\n            (\"\ud83d\udcbe\", \"Clear Standby Cache\",   \"Standby list flush karo\",       C[\"btn_info\"], self._clear_standby_with_confirm),\n            (\"\ud83d\udcca\", \"Show Heavy Processes\",  \"RAM zyada use karne wale show\", C[\"btn_info\"], self._ram_show_heavy),\n        ], cols=2)\n\n        advanced = tk.Frame(left, bg=C[\"card\"])\n        advanced.pack(fill=\"x\", padx=12, pady=(8,4))\n        tk.Label(advanced, text=\"  Advanced OS Controls\", font=FONTS[\"small\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(0,6), padx=2)\n        adv_grid = tk.Frame(advanced, bg=C[\"card\"])\n        adv_grid.pack(fill=\"x\")\n        adv_grid.columnconfigure(0, weight=1)\n        adv_grid.columnconfigure(1, weight=1)\n\n        self._kernel_trim_btn = self._btn(\n            adv_grid, \"\ud83d\udd25 Kernel Trim\", C[\"btn_info\"],\n            lambda: self._ram_service_action_submit(\"kernel_trim\", self._kernel_working_set_trim, self._kernel_trim_btn)\n        )\n        self._kernel_trim_btn.grid(row=0, column=0, sticky=\"ew\", padx=3, pady=2)\n\n        self._priority_demote_btn = self._btn(\n            adv_grid, \"\ud83d\udc22 Priority Demotion\", C[\"btn_warn\"],\n            lambda: self._ram_service_action_submit(\"priority_demotion\", self._background_priority_demotion, self._priority_demote_btn)\n        )\n        self._priority_demote_btn.grid(row=0, column=1, sticky=\"ew\", padx=3, pady=2)\n\n        self._standby_flush_btn = self._btn(\n            adv_grid, \"\ud83c\udf0a Standby Flusher\", C[\"btn_chip\"],\n            lambda: self._ram_service_action_submit(\"standby_flusher\", self._flush_standby_list, self._standby_flush_btn)\n        )\n        self._standby_flush_btn.grid(row=1, column=0, sticky=\"ew\", padx=3, pady=2)\n\n        self._sysmain_toggle_btn = self._btn(\n            adv_grid, \"\ud83d\udee1 SysMain Toggle\", C[\"btn_chip\"],\n            lambda: self._ram_service_action_submit(\"sysmain_toggle\", self._toggle_sysmain_service, self._sysmain_toggle_btn)\n        )\n        self._sysmain_toggle_btn.grid(row=1, column=1, sticky=\"ew\", padx=3, pady=2)\n\n        # Auto RAM Free (every 15 minutes) \u2014 requested feature\n        row = tk.Frame(left, bg=C[\"card\"])\n        row.pack(fill=\"x\", padx=12, pady=(6, 2))\n        tk.Label(row, text=\"Interval:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ram_auto_interval_var = tk.StringVar(value=\"15\")\n        ttk.Combobox(row, values=[\"15\", \"30\", \"60\"], textvariable=self._ram_auto_interval_var,\n                     width=6, font=FONTS[\"small\"], state=\"readonly\").pack(side=\"left\", padx=6)\n        tk.Label(row, text=\"min\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ram_auto_btn = self._btn(left, \"\u23f1 Auto RAM Free (15 min): OFF\", C[\"btn_warn\"], self._ram_auto_toggle)\n        self._ram_auto_btn.pack(fill=\"x\", padx=12, pady=3)\n        right = tk.Frame(mid, bg=C[\"card\"])\n        right.grid(row=0, column=1, sticky=\"nsew\", padx=(6,0))\n        tk.Label(right, text=\"  Memory Log\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8,4), padx=8)\n        self.ram_log = self._scrolled_text(right, height=18)\n        self.ram_execution_log = self.ram_log\n        if not hasattr(self, \"_ram_auto_enabled\"):\n            self._ram_auto_enabled = False\n        if not hasattr(self, \"_ram_auto_after_id\"):\n            self._ram_auto_after_id = None\n        self._ram_update_stats()\n        return root\n\n    def _ram_update_stats(self):\n        try:\n            vm = psutil.virtual_memory()\n            self.ram_cards[\"total\"]._value_lbl.config(text=self._fmt_size(vm.total))\n            self.ram_cards[\"used\"]._value_lbl.config(text=f\"{vm.percent:.1f}%\")\n            self.ram_cards[\"used\"]._bar.config(value=vm.percent)\n            self.ram_cards[\"free\"]._value_lbl.config(text=self._fmt_size(vm.available))\n            self.ram_cards[\"cached\"]._value_lbl.config(text=self._fmt_size(getattr(vm, 'cached', 0) or 0))\n        except:\n            pass\n        self.after(3000, self._ram_update_stats)\n\n    def _ram_boost_with_confirm(self):\n        def before():\n            return f\"Free RAM before: {self._fmt_size(psutil.virtual_memory().available)}\"\n        def action():\n            self._do_ram_optimize(aggressive=True)\n        def after():\n            return f\"Free RAM after: {self._fmt_size(psutil.virtual_memory().available)}\"\n        self._confirm_and_launch_job(\"Aggressive RAM Boost\", \"This will aggressively free up RAM by trimming working sets and clearing caches.\\nMay cause slight lag for a moment.\",\n                                    before, \"ram_boost\", self._do_ram_optimize, True)\n\n    def _ram_empty_with_confirm(self):\n        def before():\n            return f\"Free RAM before: {self._fmt_size(psutil.virtual_memory().available)}\"\n        def action():\n            self._do_ram_optimize(aggressive=False)\n        def after():\n            return f\"Free RAM after: {self._fmt_size(psutil.virtual_memory().available)}\"\n        self._confirm_and_launch_job(\"Empty Working Sets\", \"This will safely empty working sets of all processes.\\nTypically frees RAM without harming performance.\",\n                                    before, \"ram_empty\", self._do_ram_optimize, False)\n\n    def _clear_standby_with_confirm(self):\n        def before():\n            return f\"Standby cache size before: {self._fmt_size(psutil.virtual_memory().available)}\"\n        def action():\n            self._purge_memory_lists()\n        def after():\n            return f\"Standby cache size after: {self._fmt_size(psutil.virtual_memory().available)}\"\n        self._confirm_and_launch_job(\"Clear Standby Cache\", \"This clears the standby memory list (cached RAM).\\nIt can free up RAM that is being held unnecessarily.\",\n                                    before, \"ram_clear_standby\", self._purge_memory_lists)\n\n    def _do_ram_optimize(self, aggressive=False):\n        if not hasattr(self, \"_ram_opt_lock\"):\n            self._ram_opt_lock = threading.Lock()\n        with self._ram_opt_lock:\n            if getattr(self, \"_ram_opt_running\", False):\n                self._append_log(self.ram_log, \"\u26a0\ufe0f RAM optimize already running \u2014 skipping\", C[\"warning\"])\n                return\n            self._ram_opt_running = True\n        try:\n            before = psutil.virtual_memory()\n            gc.collect()\n            kernel32 = ctypes.windll.kernel32\n            psapi = ctypes.windll.psapi\n\n            batch = {\n                \"phase\": \"ram_optimize\",\n                \"status_text\": \"Optimizing RAM...\",\n                \"progress_pct\": 0.0,\n                \"processes_scanned\": 0,\n                \"errors\": 0,\n                \"freed_mb\": 0,\n                \"predicted_free_mb\": int(before.available / (1024**2) * 0.05),\n                \"confidence_score\": min(95, max(30, int((before.percent / 100.0) * 90 + 10))),\n                \"delta_mb\": 0,\n            }\n            last_dispatch = time.time()\n\n            def dispatch_metrics(force=False):\n                try:\n                    batch[\"progress_pct\"] = min(100.0, (batch[\"processes_scanned\"] / max(1, psutil.cpu_count(logical=False) * 10)) * 100.0)\n                    batch[\"status_text\"] = f\"Optimizing RAM... {batch['processes_scanned']} processes scanned\"\n                    self._ram_service_emit_metrics(batch.copy(), force=force)\n                except Exception:\n                    pass\n\n            for proc in psutil.process_iter(['pid']):\n                batch[\"processes_scanned\"] += 1\n                pid = proc.info.get('pid')\n                if not pid or pid in (0, 4):\n                    continue\n                try:\n                    handle = kernel32.OpenProcess(0x0400 | 0x0100 | 0x0010, False, int(pid))\n                    if handle:\n                        try:\n                            try:\n                                psapi.EmptyWorkingSet(handle)\n                            except (PermissionError, psutil.AccessDenied):\n                                batch[\"errors\"] += 1\n                            except Exception:\n                                batch[\"errors\"] += 1\n                        finally:\n                            kernel32.CloseHandle(handle)\n                except (PermissionError, psutil.AccessDenied):\n                    batch[\"errors\"] += 1\n                except Exception:\n                    batch[\"errors\"] += 1\n                if time.time() - last_dispatch &gt;= 0.12:\n                    dispatch_metrics()\n                    last_dispatch = time.time()\n\n            self._purge_memory_lists()\n            if aggressive:\n                try:\n                    ctypes.windll.kernel32.SetSystemFileCacheSize(-1, -1, 0)\n                except Exception:\n                    pass\n\n            after = psutil.virtual_memory()\n            freed = after.available - before.available\n            batch[\"freed_mb\"] = int(freed / (1024**2))\n            batch[\"delta_mb\"] = int((after.available - before.available) / (1024**2))\n            batch[\"status_text\"] = f\"RAM optimize complete \u2014 freed {self._fmt_size(freed)}\"\n            batch[\"progress_pct\"] = 100.0\n            self._ram_service_emit_metrics(batch.copy(), force=True)\n\n            if freed &gt;= 0:\n                self._append_log(self.ram_log, f\"\u2705 RAM Freed: {self._fmt_size(freed)}\", C[\"success\"])\n            else:\n                self._append_log(self.ram_log, f\"\u2139 RAM change: {self._fmt_size(freed)} (cache re-allocated)\", C[\"warning\"])\n        except Exception as e:\n            self._append_log(self.ram_log, f\"RAM optimize failed: {e}\", C[\"error\"])\n        finally:\n            with self._ram_opt_lock:\n                self._ram_opt_running = False\n\n    def _kernel_working_set_trim(self):\n        before = self._snapshot_resource_state() or {}\n        batch = {\n            \"phase\": \"kernel_trim\",\n            \"status_text\": \"Kernel working set trim running...\",\n            \"progress_pct\": 0.0,\n            \"trimmed_processes\": 0,\n            \"errors\": 0,\n            \"delta_mb\": 0,\n        }\n        self._ram_service_emit_metrics(batch)\n        try:\n            kernel32 = ctypes.windll.kernel32\n            psapi = ctypes.windll.psapi\n            last_dispatch = time.monotonic()\n            for proc in psutil.process_iter(['pid', 'name']):\n                try:\n                    pid = int(proc.info.get('pid') or 0)\n                    if pid &lt;= 0 or pid == os.getpid():\n                        continue\n                    handle = kernel32.OpenProcess(0x001F0FFF, False, pid)\n                    if not handle:\n                        continue\n                    try:\n                        if psapi.EmptyWorkingSet(handle):\n                            batch[\"trimmed_processes\"] += 1\n                        try:\n                            kernel32.SetProcessWorkingSetSize(handle, -1, -1)\n                        except Exception:\n                            pass\n                    finally:\n                        kernel32.CloseHandle(handle)\n                except (PermissionError, psutil.AccessDenied):\n                    batch[\"errors\"] += 1\n                except Exception:\n                    batch[\"errors\"] += 1\n                if time.monotonic() - last_dispatch &gt;= 0.120:\n                    batch[\"status_text\"] = f\"Kernel trim active \u2014 {batch['trimmed_processes']} trimmed\"\n                    batch[\"progress_pct\"] = min(100.0, (batch[\"trimmed_processes\"] / max(1, psutil.cpu_count(logical=False) * 2)) * 100.0)\n                    self._ram_service_emit_metrics(batch.copy())\n                    last_dispatch = time.monotonic()\n            after = psutil.virtual_memory()\n            batch[\"delta_mb\"] = int((after.available - before.get(\"available_mb\", 0)) / 1024**2)\n            batch[\"status_text\"] = f\"Kernel trim complete \u2014 freed {self._fmt_size(batch['delta_mb'] * 1024**2)}\"\n            batch[\"progress_pct\"] = 100.0\n            self._ram_service_emit_metrics(batch.copy(), force=True)\n            self._append_log(self.ram_log, f\"\u2705 Kernel working set trim complete \u2014 freed {self._fmt_size(batch['delta_mb'] * 1024**2)}\", C[\"success\"])\n        except Exception as e:\n            self._append_log(self.ram_log, f\"Kernel trim failed: {e}\", C[\"error\"])\n\n    def _background_priority_demotion(self):\n        before = psutil.virtual_memory()\n        batch = {\n            \"phase\": \"priority_demotion\",\n            \"status_text\": \"Background process priority demotion running...\",\n            \"progress_pct\": 0.0,\n            \"scanned\": 0,\n            \"demoted\": 0,\n            \"errors\": 0,\n            \"delta_mb\": 0,\n        }\n        self._ram_service_emit_metrics(batch)\n        idle_class = getattr(psutil, 'IDLE_PRIORITY_CLASS', getattr(psutil, 'BELOW_NORMAL_PRIORITY_CLASS', 64))\n        keep_names = {\n            'explorer.exe', 'taskmgr.exe', 'chrome.exe', 'firefox.exe', 'msedge.exe',\n            'dwm.exe', 'svchost.exe', 'services.exe', 'lsass.exe', 'wininit.exe',\n            'winlogon.exe', 'csrss.exe', 'system', 'idle', 'spoolsv.exe', 'steam.exe',\n        }\n        last_dispatch = time.monotonic()\n        for proc in psutil.process_iter(['pid', 'name', 'username', 'nice']):\n            batch[\"scanned\"] += 1\n            try:\n                pid = int(proc.info.get('pid') or 0)\n                if pid &lt;= 0 or pid == os.getpid():\n                    continue\n                name = str(proc.info.get('name') or '').lower()\n                username = str(proc.info.get('username') or '').lower()\n                if name in keep_names or any(term in name for term in ('microsoft', 'windows', 'service', 'system', 'sql', 'svchost')):\n                    continue\n                if username in ('nt authority\\\\system', 'local service', 'network service'):\n                    continue\n                current = proc.info.get('nice')\n                if current == idle_class:\n                    continue\n                try:\n                    proc.nice(idle_class)\n                    batch[\"demoted\"] += 1\n                except (PermissionError, psutil.AccessDenied):\n                    batch[\"errors\"] += 1\n                except Exception:\n                    batch[\"errors\"] += 1\n            except (PermissionError, psutil.AccessDenied):\n                batch[\"errors\"] += 1\n            except Exception:\n                batch[\"errors\"] += 1\n            if time.monotonic() - last_dispatch &gt;= 0.120:\n                batch[\"status_text\"] = f\"Demoting background apps... {batch['demoted']} demoted\"\n                batch[\"progress_pct\"] = min(100.0, (batch[\"scanned\"] / max(1, psutil.cpu_count(logical=False) * 10)) * 100.0)\n                self._ram_service_emit_metrics(batch.copy())\n                last_dispatch = time.monotonic()\n        after = psutil.virtual_memory()\n        batch[\"delta_mb\"] = int((after.available - before.available) / 1024**2)\n        batch[\"status_text\"] = f\"Priority demotion complete \u2014 {batch['demoted']} apps demoted\"\n        batch[\"progress_pct\"] = 100.0\n        self._ram_service_emit_metrics(batch.copy(), force=True)\n        self._append_log(self.ram_log, f\"\u2705 Background priority demotion complete \u2014 {batch['demoted']} processes\", C[\"success\"])\n\n    def _flush_standby_list(self):\n        before = psutil.virtual_memory()\n        batch = {\n            \"phase\": \"standby_flush\",\n            \"status_text\": \"Standby list flush running...\",\n            \"progress_pct\": 0.0,\n            \"errors\": 0,\n            \"delta_mb\": 0,\n        }\n        self._ram_service_emit_metrics(batch)\n        try:\n            self._purge_memory_lists()\n            try:\n                ctypes.windll.kernel32.SetSystemFileCacheSize(-1, -1, 0)\n            except (PermissionError, psutil.AccessDenied):\n                batch[\"errors\"] += 1\n            except Exception:\n                pass\n            try:\n                kernel32 = ctypes.windll.kernel32\n                psapi = ctypes.windll.psapi\n                handle = kernel32.GetCurrentProcess()\n                psapi.EmptyWorkingSet(handle)\n            except Exception:\n                pass\n            after = psutil.virtual_memory()\n            batch[\"delta_mb\"] = int((after.available - before.available) / 1024**2)\n            batch[\"status_text\"] = f\"Standby flush complete \u2014 freed {self._fmt_size(batch['delta_mb'] * 1024**2)}\"\n            batch[\"progress_pct\"] = 100.0\n            self._ram_service_emit_metrics(batch.copy(), force=True)\n            self._append_log(self.ram_log, f\"\u2705 Standby list flushed \u2014 freed {self._fmt_size(batch['delta_mb'] * 1024**2)}\", C[\"success\"])\n        except Exception as e:\n            self._append_log(self.ram_log, f\"Standby flush failed: {e}\", C[\"error\"])\n\n    def _toggle_sysmain_service(self):\n        batch = {\n            \"phase\": \"sysmain_toggle\",\n            \"status_text\": \"SysMain toggle running...\",\n            \"progress_pct\": 0.0,\n            \"action\": \"pending\",\n        }\n        self._ram_service_emit_metrics(batch)\n        try:\n            svc = psutil.win_service_get(\"SysMain\")\n            status = svc.status().lower()\n            if status == \"running\":\n                try:\n                    svc.stop()\n                    svc.wait(15)\n                    batch[\"action\"] = \"stopped\"\n                except (PermissionError, psutil.AccessDenied):\n                    batch[\"action\"] = \"permission_denied\"\n                    batch[\"status_text\"] = \"SysMain stop denied\"\n                    batch[\"progress_pct\"] = 100.0\n                    self._ram_service_emit_metrics(batch.copy(), force=True)\n                    self._append_log(self.ram_log, \"\u26a0\ufe0f SysMain stop denied by permissions\", C[\"warning\"])\n                    return\n                except Exception:\n                    batch[\"action\"] = \"stop_failed\"\n            else:\n                try:\n                    svc.start()\n                    svc.wait(15)\n                    batch[\"action\"] = \"started\"\n                except (PermissionError, psutil.AccessDenied):\n                    batch[\"action\"] = \"permission_denied\"\n                    batch[\"status_text\"] = \"SysMain start denied\"\n                    batch[\"progress_pct\"] = 100.0\n                    self._ram_service_emit_metrics(batch.copy(), force=True)\n                    self._append_log(self.ram_log, \"\u26a0\ufe0f SysMain start denied by permissions\", C[\"warning\"])\n                    return\n                except Exception:\n                    batch[\"action\"] = \"start_failed\"\n            batch[\"status_text\"] = f\"SysMain {batch['action']}\"\n            batch[\"progress_pct\"] = 100.0\n            self._ram_service_emit_metrics(batch.copy(), force=True)\n            self._append_log(self.ram_log, f\"\u2705 SysMain {batch['action']}\", C[\"success\"])\n        except Exception as e:\n            self._append_log(self.ram_log, f\"SysMain toggle failed: {e}\", C[\"error\"])\n\n    def _ram_auto_toggle(self):\n        enabled = not bool(getattr(self, \"_ram_auto_enabled\", False))\n        self._ram_auto_enabled = enabled\n        try:\n            if hasattr(self, \"_ram_auto_btn\") and self._ram_auto_btn:\n                self._ram_auto_btn.config(\n                    text=(\"\u23f1 Auto RAM Free (15 min): ON\" if enabled else \"\u23f1 Auto RAM Free (15 min): OFF\"),\n                    bg=(C[\"btn_info\"] if enabled else C[\"btn_warn\"])\n                )\n        except Exception:\n            pass\n        if enabled:\n            mins = self._ram_auto_interval_minutes()\n            self._append_log(self.ram_log, f\"\u23f1 Auto RAM Free enabled \u2014 every {mins} minutes\", C[\"accent4\"])\n            self._ram_auto_schedule(immediate=False)\n        else:\n            self._append_log(self.ram_log, \"\u23f1 Auto RAM Free disabled\", C[\"warning\"])\n            self._ram_auto_cancel()\n\n    def _ram_auto_cancel(self):\n        try:\n            aid = getattr(self, \"_ram_auto_after_id\", None)\n            if aid:\n                self.after_cancel(aid)\n        except Exception:\n            pass\n        self._ram_auto_after_id = None\n\n    def _ram_auto_schedule(self, immediate=False):\n        self._ram_auto_cancel()\n        if not getattr(self, \"_ram_auto_enabled\", False):\n            return\n        mins = self._ram_auto_interval_minutes()\n        delay = 1000 if immediate else (mins * 60 * 1000)\n        self._ram_auto_after_id = self.after(delay, self._ram_auto_tick)\n\n    def _ram_auto_interval_minutes(self):\n        try:\n            v = int((getattr(self, \"_ram_auto_interval_var\", None).get() if hasattr(self, \"_ram_auto_interval_var\") else \"15\") or \"15\")\n            if v in (15, 30, 60):\n                return v\n        except Exception:\n            pass\n        return 15\n\n    def _ram_auto_tick(self):\n        if not getattr(self, \"_ram_auto_enabled\", False):\n            return\n        # Avoid lag when system is busy\n        try:\n            if psutil.cpu_percent(interval=0.1) &gt; 75:\n                self._append_log(self.ram_log, \"\u23f1 Auto RAM Free skipped (CPU high)\", C[\"warning\"])\n                self._ram_auto_schedule(immediate=False)\n                return\n        except Exception:\n            pass\n        self._submit_ram_service_job(\"ram_auto_boost\", self._do_ram_optimize, True)\n        self._ram_auto_schedule(immediate=False)\n\n    def _purge_memory_lists(self):\n        try:\n            ntdll = ctypes.windll.ntdll\n            cleared = False\n            for val in (2, 3, 4, 5):\n                try:\n                    # NtSetSystemInformation returns an NTSTATUS; failure raises in some contexts\n                    ntdll.NtSetSystemInformation(80, ctypes.byref(ctypes.c_int(val)), 4)\n                    cleared = True\n                except Exception:\n                    continue\n            if cleared:\n                try:\n                    self._append_log(self.ram_log, \"\u2705 Standby cleared\", C[\"success\"])\n                except Exception:\n                    pass\n                return True\n\n            # Fallback: try to reduce system file cache size\n            try:\n                ctypes.windll.kernel32.SetSystemFileCacheSize(-1, -1, 0)\n                try:\n                    self._append_log(self.ram_log, \"\u2705 Standby cleared via SetSystemFileCacheSize\", C[\"success\"])\n                except Exception:\n                    pass\n                return True\n            except Exception:\n                try:\n                    self._append_log(self.ram_log, \"\u26a0 Could not clear standby lists (insufficient permissions?)\", C[\"warning\"])\n                except Exception:\n                    pass\n                return False\n\n        except Exception as e:\n            try:\n                self._append_log(self.ram_log, f\"Standby clear failed: {e}\", C[\"error\"])\n            except Exception:\n                pass\n            return False\n\n    def _ram_show_heavy(self):\n        \"\"\"RAM heavy processes ko popup window mein dikhao with Kill/Stop buttons\"\"\"\n        win = tk.Toplevel(self)\n        win.title(\"\ud83d\udd34 RAM Heavy Processes \u2014 Kill / Stop\")\n        win.geometry(\"820x500\")\n        win.configure(bg=C[\"bg\"])\n        win.resizable(True, True)\n\n        tk.Label(win, text=\"\ud83d\udd34  RAM Heavy Processes\", font=FONTS[\"subhead\"],\n                 fg=C[\"error\"], bg=C[\"bg\"]).pack(anchor=\"w\", padx=16, pady=(12, 4))\n        tk.Label(win, text=\"Process select karo \u2192 Kill (force) ya Terminate (graceful)\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"]).pack(anchor=\"w\", padx=16)\n\n        # --- treeview ---\n        cols = (\"PID\", \"Name\", \"RAM (MB)\", \"CPU %\", \"Status\")\n        tree_frame = tk.Frame(win, bg=C[\"bg\"])\n        tree_frame.pack(fill=\"both\", expand=True, padx=16, pady=8)\n        tree = ttk.Treeview(tree_frame, columns=cols, show=\"headings\",\n                            height=14, style=\"Custom.Treeview\", selectmode=\"extended\")\n        for col, w in zip(cols, [70, 260, 90, 70, 90]):\n            tree.heading(col, text=col)\n            tree.column(col, width=w, anchor=\"w\")\n        vsb = ttk.Scrollbar(tree_frame, orient=\"vertical\", command=tree.yview)\n        tree.configure(yscrollcommand=vsb.set)\n        tree.pack(side=\"left\", fill=\"both\", expand=True)\n        vsb.pack(side=\"right\", fill=\"y\")\n\n        status_lbl = tk.Label(win, text=\"Loading\u2026\", font=FONTS[\"small\"],\n                              fg=C[\"text_dim\"], bg=C[\"bg\"])\n        status_lbl.pack(anchor=\"w\", padx=16)\n\n        # --- buttons ---\n        btn_row = tk.Frame(win, bg=C[\"bg\"])\n        btn_row.pack(fill=\"x\", padx=16, pady=(4, 12))\n\n        def _refresh():\n            tree.delete(*tree.get_children())\n            status_lbl.config(text=\"Refreshing\u2026\", fg=C[\"text_dim\"])\n            try:\n                procs = sorted(\n                    psutil.process_iter(['pid', 'name', 'memory_info', 'cpu_percent', 'status']),\n                    key=lambda p: (p.info.get('memory_info') or type('', (), {'rss': 0})()).rss,\n                    reverse=True\n                )\n                count = 0\n                for p in procs[:30]:\n                    try:\n                        mem = p.info.get('memory_info')\n                        mb = round(mem.rss / (1024 ** 2), 1) if mem else 0\n                        cpu = p.info.get('cpu_percent', 0.0) or 0.0\n                        st = p.info.get('status', '?') or '?'\n                        tree.insert(\"\", \"end\", iid=str(p.info['pid']),\n                                    values=(p.info['pid'], p.info.get('name', '?'), mb, f\"{cpu:.1f}\", st))\n                        count += 1\n                    except Exception:\n                        pass\n                status_lbl.config(text=f\"\u2705 {count} processes loaded \u2014 multiple select ke liye Ctrl+Click\",\n                                  fg=C[\"success\"])\n            except Exception as ex:\n                status_lbl.config(text=f\"\u274c Error: {ex}\", fg=C[\"error\"])\n\n        def _kill_selected(graceful=False):\n            selected = tree.selection()\n            if not selected:\n                messagebox.showwarning(\"Select karo\", \"Pehle ek ya zyada processes select karo\", parent=win)\n                return\n            names = [tree.item(s)[\"values\"][1] for s in selected]\n            action = \"Terminate (graceful)\" if graceful else \"Kill (force)\"\n            if not messagebox.askyesno(\n                f\"Confirm \u2014 {action}\",\n                f\"{len(selected)} process(es) {action} karna hai?\\n\\n\" +\n                \"\\n\".join(str(n) for n in names[:10]) +\n                (\"\\n...\" if len(names) &gt; 10 else \"\") +\n                \"\\n\\nUnsaved data loss ho sakta hai!\",\n                parent=win\n            ):\n                return\n            done = 0\n            errs = []\n            for iid in selected:\n                try:\n                    pid = int(iid)\n                    proc = psutil.Process(pid)\n                    if graceful:\n                        proc.terminate()\n                    else:\n                        proc.kill()\n                    tree.delete(iid)\n                    done += 1\n                except psutil.NoSuchProcess:\n                    tree.delete(iid)\n                    done += 1\n                except Exception as ex:\n                    errs.append(f\"PID {iid}: {ex}\")\n            msg = f\"\u2705 {done} process(es) {action} kiye\"\n            if errs:\n                msg += f\"\\n\u26a0\ufe0f {len(errs)} errors: \" + \"; \".join(errs[:3])\n            status_lbl.config(text=msg, fg=C[\"success\"] if not errs else C[\"warning\"])\n            self._append_log(self.ram_log, msg, C[\"success\"] if not errs else C[\"warning\"])\n\n        tk.Button(btn_row, text=\"\ud83d\udd04 Refresh\", font=FONTS[\"body\"],\n                  bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=12, pady=6,\n                  cursor=\"hand2\", command=_refresh).pack(side=\"left\", padx=(0, 6))\n        tk.Button(btn_row, text=\"\u26a1 Terminate (Graceful)\", font=FONTS[\"body\"],\n                  bg=C[\"warning\"], fg=C[\"bg\"], bd=0, padx=12, pady=6,\n                  cursor=\"hand2\", command=lambda: _kill_selected(graceful=True)).pack(side=\"left\", padx=(0, 6))\n        tk.Button(btn_row, text=\"\ud83d\udc80 Kill (Force)\", font=FONTS[\"body\"],\n                  bg=C[\"error\"], fg=C[\"text\"], bd=0, padx=12, pady=6,\n                  cursor=\"hand2\", command=lambda: _kill_selected(graceful=False)).pack(side=\"left\", padx=(0, 6))\n        tk.Button(btn_row, text=\"\u2716 Close\", font=FONTS[\"body\"],\n                  bg=C[\"card\"], fg=C[\"text\"], bd=0, padx=12, pady=6,\n                  cursor=\"hand2\", command=win.destroy).pack(side=\"right\")\n\n        win.after(100, _refresh)  # auto load on open\n\n    def _do_ram_show_heavy(self):\n        try:\n            procs = sorted(psutil.process_iter(['pid','name','memory_info']),\n                           key=lambda p: (p.info.get('memory_info') or type('',(),{'rss':0})()).rss,\n                           reverse=True)\n            self._append_log(self.ram_log, \"\ud83d\udd34 Top 10 RAM-heavy processes:\", C[\"accent\"])\n            for p in procs[:10]:\n                try:\n                    mem = p.info.get('memory_info')\n                    mb = round(mem.rss/(1024**2),1) if mem else 0\n                    self._append_log(self.ram_log, f\"  PID {p.info['pid']:6d}  {p.info['name']:&lt;30s}  {mb} MB\", C[\"text\"])\n                except Exception:\n                    pass\n        except Exception:\n            self._append_log(self.ram_log, \"\u26a0\ufe0f Unable to enumerate RAM-heavy processes right now.\", C[\"warning\"])\n\n    # ---------- STARTUP MANAGER (unchanged except confirm) ----------\n    def _build_startup(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\ude80 Startup Manager\", \"Manage startup programs\")\n        self._action_card_grid(frame, [\n            (\"\ud83d\udd0d\", \"Refresh\",          \"Startup entries reload karo\",          C[\"btn_info\"], self._refresh_startup),\n            (\"\u26d4\", \"Disable Selected\", \"Selected entries boot pe nahi chalenge\",C[\"btn_warn\"], lambda: self._with_confirm(\"Disable Startup\", \"Disable selected startup entries? They won't run on boot.\", self._disable_startup)),\n            (\"\u2705\", \"Enable Selected\",  \"Selected entries wapas enable karo\",   C[\"btn\"],      lambda: self._with_confirm(\"Enable Startup\", \"Enable selected startup entries?\", self._enable_startup)),\n            (\"\ud83d\udce4\", \"Export List\",      \"Startup entries export karo\",        C[\"btn_chip\"], self._export_startup_list),\n            (\"\ud83d\udd0e\", \"Find Orphans\",     \"Missing target files ke startup entries\", C[\"btn_warn\"], self._find_orphan_startup_entries),\n        ], cols=5)\n        self.startup_tree = ttk.Treeview(frame, columns=(\"Name\", \"Command\", \"Location\", \"Status\"), show=\"headings\", height=20, style=\"Custom.Treeview\")\n        for col, w in zip((\"Name\", \"Command\", \"Location\", \"Status\"), [200,300,150,80]):\n            self.startup_tree.heading(col, text=col)\n            self.startup_tree.column(col, width=w, anchor=\"w\")\n        vsb = ttk.Scrollbar(frame, orient=\"vertical\", command=self.startup_tree.yview)\n        self.startup_tree.configure(yscrollcommand=vsb.set)\n        self.startup_tree.pack(side=\"left\", fill=\"both\", expand=True, padx=16, pady=8)\n        vsb.pack(side=\"right\", fill=\"y\", pady=8, padx=(0,8))\n        return frame\n\n    def _collect_startup_entries(self):\n        disabled_prefix = \"__GodawariDisabled__\"\n        seen = set()\n        entries = []\n        reg_locations = [\n            (\"HKCU\", winreg.HKEY_CURRENT_USER, r\"Software\\Microsoft\\Windows\\CurrentVersion\\Run\"),\n            (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"Software\\Microsoft\\Windows\\CurrentVersion\\Run\"),\n            (\"HKCU\", winreg.HKEY_CURRENT_USER, r\"Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce\"),\n            (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce\"),\n            (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"Software\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Run\"),\n            (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"Software\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\RunOnce\"),\n        ]\n        for hive_name, hive, reg_path in reg_locations:\n            try:\n                key = winreg.OpenKey(hive, reg_path, 0, winreg.KEY_READ)\n                i = 0\n                while True:\n                    try:\n                        name, value, _ = winreg.EnumValue(key, i)\n                        status = \"Disabled\" if name.startswith(disabled_prefix) else \"Enabled\"\n                        shown_name = name.replace(disabled_prefix, \"\", 1)\n                        dedupe_key = (shown_name.lower(), str(value).lower(), f\"{hive_name}|REG|{reg_path}\")\n                        if dedupe_key not in seen:\n                            seen.add(dedupe_key)\n                            entries.append({\n                                \"display_name\": shown_name,\n                                \"raw_name\": name,\n                                \"command\": str(value),\n                                \"location\": f\"{hive_name}|REG|{reg_path}\",\n                                \"status\": status,\n                                \"kind\": \"registry\",\n                                \"hive\": hive,\n                                \"reg_path\": reg_path,\n                                \"value\": value,\n                            })\n                        i += 1\n                    except OSError:\n                        break\n                winreg.CloseKey(key)\n            except Exception:\n                pass\n\n        startup_folders = [\n            (os.path.join(os.environ.get(\"APPDATA\", \"\"), r\"Microsoft\\Windows\\Start Menu\\Programs\\Startup\"), \"User Startup\"),\n            (os.path.join(os.environ.get(\"PROGRAMDATA\", \"\"), r\"Microsoft\\Windows\\Start Menu\\Programs\\StartUp\"), \"Common Startup\"),\n        ]\n        for folder, label in startup_folders:\n            if not folder or not os.path.exists(folder):\n                continue\n            try:\n                for f in Path(folder).glob(\"*\"):\n                    if not f.is_file():\n                        continue\n                    status = \"Disabled\" if f.name.endswith(\".disabled\") else \"Enabled\"\n                    shown_name = f.name[:-9] if status == \"Disabled\" else f.name\n                    dedupe_key = (shown_name.lower(), str(f).lower(), f\"{label}|FOLDER|{folder}\")\n                    if dedupe_key in seen:\n                        continue\n                    seen.add(dedupe_key)\n                    entries.append({\n                        \"display_name\": shown_name,\n                        \"raw_name\": f.name,\n                        \"command\": str(f),\n                        \"location\": f\"{label}|FOLDER|{folder}\",\n                        \"status\": status,\n                        \"kind\": \"folder\",\n                        \"path\": str(f),\n                    })\n            except Exception:\n                pass\n        return entries\n\n    def _refresh_startup(self):\n        self.startup_tree.delete(*self.startup_tree.get_children())\n        for entry in self._collect_startup_entries():\n            self.startup_tree.insert(\"\", \"end\", values=(entry[\"display_name\"], entry[\"command\"], entry[\"location\"], entry[\"status\"]))\n\n    def _refresh_registry_startup(self):\n        if not hasattr(self, \"registry_startup_tree\"):\n            return\n        self.registry_startup_tree.delete(*self.registry_startup_tree.get_children())\n        self._registry_startup_items = {}\n        for entry in self._collect_startup_entries():\n            uid = f\"startup-{len(self._registry_startup_items) + 1}\"\n            self._registry_startup_items[uid] = entry\n            self.registry_startup_tree.insert(\"\", \"end\", iid=uid, values=(entry[\"display_name\"], entry[\"command\"], entry[\"location\"], entry[\"status\"]))\n\n    def _delete_startup_entry(self, entry):\n        if not entry:\n            return False\n        try:\n            if entry[\"kind\"] == \"registry\":\n                key = winreg.OpenKey(entry[\"hive\"], entry[\"reg_path\"], 0, winreg.KEY_SET_VALUE | winreg.KEY_READ)\n                try:\n                    winreg.DeleteValue(key, entry[\"raw_name\"])\n                finally:\n                    winreg.CloseKey(key)\n                return True\n            path = Path(entry.get(\"path\") or entry.get(\"command\") or \"\")\n            if not path.exists():\n                return False\n            if path.is_dir():\n                shutil.rmtree(path, ignore_errors=True)\n            else:\n                path.unlink()\n            return True\n        except Exception:\n            return False\n\n    def _delete_registry_startup_selected(self):\n        if not hasattr(self, \"registry_startup_tree\"):\n            return\n        selected = self.registry_startup_tree.selection()\n        if not selected:\n            messagebox.showwarning(\"Nothing Selected\", \"Delete karne ke liye startup item select karo.\")\n            return\n        if not messagebox.askyesno(\"Delete Selected Startup Items\", f\"{len(selected)} selected startup item(s) delete karein? This affects boot behavior.\"):\n            return\n        deleted = 0\n        failed = 0\n        for iid in selected:\n            entry = self._registry_startup_items.get(iid)\n            if self._delete_startup_entry(entry):\n                deleted += 1\n                self.registry_startup_tree.delete(iid)\n                self._append_log(self.reg_log, f\"\ud83d\uddd1 Deleted startup item: {entry['display_name']}\", C[\"success\"])\n            else:\n                failed += 1\n                self._append_log(self.reg_log, f\"\u26a0 Could not delete startup item: {entry['display_name']}\", C[\"warning\"])\n        if deleted:\n            self._append_log(self.reg_log, f\"\u2705 Deleted {deleted} startup item(s).\", C[\"success\"])\n        if failed:\n            self._append_log(self.reg_log, f\"\u26a0 Failed to delete {failed} startup item(s).\", C[\"warning\"])\n\n    def _disable_startup(self):\n        for item in self.startup_tree.selection():\n            vals = self.startup_tree.item(item, \"values\")\n            if len(vals) &lt; 4 or vals[3] == \"Disabled\":\n                continue\n            name, command, loc = vals[0], vals[1], vals[2]\n            parts = loc.split(\"|\", 2)\n            if len(parts) &gt;= 3 and parts[1] == \"REG\":\n                hive = winreg.HKEY_CURRENT_USER if parts[0] == \"HKCU\" else winreg.HKEY_LOCAL_MACHINE\n                key = winreg.OpenKey(hive, parts[2], 0, winreg.KEY_SET_VALUE | winreg.KEY_READ)\n                value, vtype = winreg.QueryValueEx(key, name)\n                winreg.SetValueEx(key, \"__GodawariDisabled__\" + name, 0, vtype, value)\n                winreg.DeleteValue(key, name)\n                winreg.CloseKey(key)\n            elif len(parts) &gt;= 3 and parts[1] == \"FOLDER\":\n                src = Path(command)\n                dest = src.with_name(src.name + \".disabled\")\n                if src.exists():\n                    if dest.exists():\n                        dest.unlink()\n                    src.rename(dest)\n        self._refresh_startup()\n\n    def _enable_startup(self):\n        for item in self.startup_tree.selection():\n            vals = self.startup_tree.item(item, \"values\")\n            if len(vals) &lt; 4 or vals[3] == \"Enabled\":\n                continue\n            name, command, loc = vals[0], vals[1], vals[2]\n            parts = loc.split(\"|\", 2)\n            if len(parts) &gt;= 3 and parts[1] == \"REG\":\n                hive = winreg.HKEY_CURRENT_USER if parts[0] == \"HKCU\" else winreg.HKEY_LOCAL_MACHINE\n                key = winreg.OpenKey(hive, parts[2], 0, winreg.KEY_SET_VALUE | winreg.KEY_READ)\n                value, vtype = winreg.QueryValueEx(key, \"__GodawariDisabled__\" + name)\n                winreg.SetValueEx(key, name, 0, vtype, value)\n                winreg.DeleteValue(key, \"__GodawariDisabled__\" + name)\n                winreg.CloseKey(key)\n            elif len(parts) &gt;= 3 and parts[1] == \"FOLDER\":\n                src = Path(command)\n                if src.name.endswith(\".disabled\") and src.exists():\n                    dest = src.with_name(src.name[:-9])\n                    if dest.exists():\n                        dest.unlink()\n                    src.rename(dest)\n        self._refresh_startup()\n\n    def _startup_command_to_path(self, command):\n        if not command:\n            return \"\"\n        command = command.strip()\n        m = re.match(r'^\"([^\"]+)\"', command)\n        if m:\n            return m.group(1)\n        m = re.match(r'^([^\\s]+)', command)\n        return m.group(1) if m else \"\"\n\n    def _export_startup_list(self):\n        items = []\n        for item in self.startup_tree.get_children():\n            vals = self.startup_tree.item(item, \"values\")\n            if len(vals) &lt; 4:\n                continue\n            items.append(vals)\n        if not items:\n            messagebox.showinfo(\"No Startup Entries\", \"Koi startup entry export karne ko nahin mila.\")\n            return\n        path = filedialog.asksaveasfilename(defaultextension=\".csv\",\n                                            filetypes=[(\"CSV files\", \"*.csv\")],\n                                            initialfile=\"Startup_Entries.csv\",\n                                            title=\"Save Startup List\")\n        if not path:\n            return\n        try:\n            import csv\n            with open(path, \"w\", newline=\"\", encoding=\"utf-8\") as f:\n                writer = csv.writer(f)\n                writer.writerow([\"Name\", \"Command\", \"Location\", \"Status\"])\n                writer.writerows(items)\n            messagebox.showinfo(\"Exported\", f\"Startup list saved to:\\n{path}\")\n            self._append_log(self.clean_log, f\"\ud83d\udcbe Startup list exported: {path}\", C[\"success\"])\n        except Exception as e:\n            messagebox.showerror(\"Export Failed\", str(e))\n            self._append_log(self.clean_log, f\"\u274c Startup export failed: {e}\", C[\"error\"])\n\n    def _find_orphan_startup_entries(self):\n        orphaned = 0\n        for iid in self.startup_tree.get_children():\n            vals = self.startup_tree.item(iid, \"values\")\n            if len(vals) &lt; 3:\n                continue\n            path = self._startup_command_to_path(vals[1])\n            exists = os.path.exists(path) if path else False\n            if path and not exists:\n                orphaned += 1\n                self.startup_tree.item(iid, tags=(\"orphan\",))\n            else:\n                self.startup_tree.item(iid, tags=())\n        self.startup_tree.tag_configure(\"orphan\", background=\"#3D1D1D\")\n        if orphaned:\n            messagebox.showinfo(\"Orphaned Startup Entries\", f\"{orphaned} orphaned startup entries found. Check the list for missing targets.\")\n            self._append_log(self.clean_log, f\"\ud83d\udd0e Found {orphaned} orphaned startup entries.\", C[\"warning\"])\n        else:\n            messagebox.showinfo(\"No Orphans\", \"No missing startup targets detected.\")\n            self._append_log(self.clean_log, \"\u2705 No orphaned startup entries found.\", C[\"success\"])\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  TASK SCHEDULER \u2014 Knowledge Base\n    #  cat: \"danger\"   = Kabhi disable mat karo \u2014 system toot jayega\n    #       \"caution\"  = Soch ke karo \u2014 Windows feature affected hoga\n    #       \"safe\"     = Safely disable \u2014 performance badhegi\n    #       \"telemetry\"= Microsoft ko data bhejta hai \u2014 disable karo\n    #       \"thirdparty\"= Software ka auto-update/check task\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    TASK_DB = {\n        # \u2500\u2500 DANGER \u2014 kabhi mat chhuo \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        r\"\\Microsoft\\Windows\\UpdateOrchestrator\\Schedule Scan\":\n            (\"danger\", False, \"Windows Update scan \u2014 disable karne se security patches nahi aayenge. Bahut zaroori hai.\"),\n        r\"\\Microsoft\\Windows\\WindowsUpdate\\Scheduled Start\":\n            (\"danger\", False, \"Windows Update start task \u2014 disable = updates nahi hoge, security risk.\"),\n        r\"\\Microsoft\\Windows\\Defrag\\ScheduledDefrag\":\n            (\"caution\", True, \"HDD defragmentation \u2014 SSD pe disable karo (SSD ko defrag ki zarurat nahi). HDD pe rakho.\"),\n        r\"\\Microsoft\\Windows\\Diagnosis\\Scheduled\":\n            (\"caution\", True, \"Windows auto-diagnosis \u2014 system problems detect karta hai. Home pe safe to disable.\"),\n        r\"\\Microsoft\\Windows\\Chkdsk\\ProactiveScan\":\n            (\"caution\", True, \"Disk error check \u2014 SSD pe disable karo. HDD pe useful hai.\"),\n        r\"\\Microsoft\\Windows\\MemoryDiagnostic\\ProcessMemoryDiagnosticEvents\":\n            (\"caution\", True, \"RAM diagnostic events \u2014 home use pe disable kar sakte ho.\"),\n        r\"\\Microsoft\\Windows\\MemoryDiagnostic\\RunFullMemoryDiagnostic\":\n            (\"caution\", True, \"Full RAM scan \u2014 randomly chalta hai, system slow karta hai. Disable safe hai.\"),\n        # \u2500\u2500 TELEMETRY \u2014 Microsoft ko data bhejta hai \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        r\"\\Microsoft\\Windows\\Application Experience\\Microsoft Compatibility Appraiser\":\n            (\"telemetry\", True, \"CompatTelRunner.exe \u2014 CPU 100% kar deta hai! Microsoft ko compatibility data bhejta hai. DISABLE KARO.\"),\n        r\"\\Microsoft\\Windows\\Application Experience\\ProgramDataUpdater\":\n            (\"telemetry\", True, \"Application Experience data Microsoft ko bhejta hai. Disable karo.\"),\n        r\"\\Microsoft\\Windows\\Application Experience\\StartupAppTask\":\n            (\"telemetry\", True, \"Startup apps track karta hai \u2014 disable safe hai.\"),\n        r\"\\Microsoft\\Windows\\Application Experience\\AitAgent\":\n            (\"telemetry\", True, \"Application Impact Telemetry \u2014 Microsoft ko usage data bhejta hai. Disable karo.\"),\n        r\"\\Microsoft\\Windows\\Autochk\\Proxy\":\n            (\"telemetry\", True, \"AutoChk telemetry proxy \u2014 Microsoft ko data bhejta hai. Disable karo.\"),\n        r\"\\Microsoft\\Windows\\Customer Experience Improvement Program\\Consolidator\":\n            (\"telemetry\", True, \"CEIP data collector \u2014 Microsoft ko aapka usage data bhejta hai. Disable karo.\"),\n        r\"\\Microsoft\\Windows\\Customer Experience Improvement Program\\KernelCeipTask\":\n            (\"telemetry\", True, \"Kernel level CEIP \u2014 system ke andar se data collect karta hai. Disable karo.\"),\n        r\"\\Microsoft\\Windows\\Customer Experience Improvement Program\\UsbCeip\":\n            (\"telemetry\", True, \"USB devices ka usage data bhejta hai Microsoft ko. Disable karo.\"),\n        r\"\\Microsoft\\Windows\\Customer Experience Improvement Program\\Uploader\":\n            (\"telemetry\", True, \"CEIP data upload task \u2014 internet bandwidth use karta hai. Disable karo.\"),\n        r\"\\Microsoft\\Windows\\DiskFootprint\\Diagnostics\":\n            (\"telemetry\", True, \"Disk usage diagnostics data bhejta hai. Disable karo.\"),\n        r\"\\Microsoft\\Windows\\Feedback\\Siuf\\DmClient\":\n            (\"telemetry\", True, \"Windows Feedback \u2014 aapke opinions collect karta hai Microsoft ke liye. Disable karo.\"),\n        r\"\\Microsoft\\Windows\\Feedback\\Siuf\\DmClientOnScenarioDownload\":\n            (\"telemetry\", True, \"Feedback scenario download \u2014 disable karo.\"),\n        r\"\\Microsoft\\Windows\\NetTrace\\GatherNetworkInfo\":\n            (\"telemetry\", True, \"Network diagnostics data collect karta hai. Disable karo.\"),\n        r\"\\Microsoft\\Windows\\Power Efficiency Diagnostics\\AnalyzeSystem\":\n            (\"telemetry\", True, \"Power usage analysis \u2014 battery/power data bhejta hai. Disable karo.\"),\n        r\"\\Microsoft\\Windows\\Shell\\FamilySafetyMonitor\":\n            (\"telemetry\", True, \"Family Safety monitoring \u2014 use nahi karte to disable karo.\"),\n        r\"\\Microsoft\\Windows\\Shell\\FamilySafetyRefresh\":\n            (\"telemetry\", True, \"Family Safety data refresh \u2014 disable karo.\"),\n        r\"\\Microsoft\\Windows\\WS\\WSTask\":\n            (\"telemetry\", True, \"Windows Store telemetry \u2014 disable karo.\"),\n        # \u2500\u2500 SAFE TO DISABLE \u2014 performance badhegi \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        r\"\\Microsoft\\Windows\\DiskCleanup\\SilentCleanup\":\n            (\"safe\", True, \"Background disk cleanup \u2014 randomly disk scan karta hai, disk I/O badh jaati hai. Disable karo, manual cleanup use karo.\"),\n        r\"\\Microsoft\\Windows\\Maintenance\\WinSAT\":\n            (\"safe\", True, \"Windows System Assessment Tool \u2014 PC benchmark \u2014 randomly chalta hai, resources waste karta hai. Disable karo.\"),\n        r\"\\Microsoft\\Windows\\Maps\\MapsUpdateTask\":\n            (\"safe\", True, \"Windows Maps offline update \u2014 maps use nahi karte to disable karo.\"),\n        r\"\\Microsoft\\Windows\\Maps\\MapsToastTask\":\n            (\"safe\", True, \"Maps toast notification \u2014 disable karo.\"),\n        r\"\\Microsoft\\Windows\\Offline Files\\Background Synchronization\":\n            (\"safe\", True, \"Offline file sync \u2014 network shared files use nahi karte to disable karo.\"),\n        r\"\\Microsoft\\Windows\\Offline Files\\Logon Synchronization\":\n            (\"safe\", True, \"Offline files login sync \u2014 home PC pe disable karo.\"),\n        r\"\\Microsoft\\Windows\\RemoteAssistance\\RemoteAssistanceTask\":\n            (\"safe\", True, \"Remote Assistance \u2014 koi aapke PC par remotely connect nahi karta to disable karo.\"),\n        r\"\\Microsoft\\Windows\\RetailDemo\\CleanupOfflineContent\":\n            (\"safe\", True, \"Retail Demo cleanup \u2014 shop display ke liye hai. Home PC pe immediately disable karo.\"),\n        r\"\\Microsoft\\Windows\\SettingSync\\BackgroundUploadTask\":\n            (\"safe\", True, \"Settings cloud sync \u2014 OneDrive/Microsoft account sync. Privacy ke liye disable karo.\"),\n        r\"\\Microsoft\\Windows\\SettingSync\\NetworkStateChangeTask\":\n            (\"safe\", True, \"Settings sync on network change \u2014 disable karo.\"),\n        r\"\\Microsoft\\Windows\\FileHistory\\File History (maintenance mode)\":\n            (\"safe\", True, \"File History maintenance \u2014 use nahi karte to disable karo.\"),\n        r\"\\Microsoft\\Windows\\Ras\\MobilityManager\":\n            (\"safe\", True, \"Mobile broadband manager \u2014 WiFi/ethernet use karte ho to disable karo.\"),\n        r\"\\Microsoft\\Windows\\Location\\Notifications\":\n            (\"safe\", True, \"Location notifications \u2014 privacy ke liye disable karo.\"),\n        r\"\\Microsoft\\Windows\\Location\\WindowsActionDialog\":\n            (\"safe\", True, \"Location access dialog \u2014 disable karo.\"),\n        r\"\\Microsoft\\Windows\\.NET Framework\\.NET Framework NGEN v4.0.30319\":\n            (\"safe\", True, \".NET optimization \u2014 ek baar chalta hai, phir dobara nahi chahiye. Disable karo.\"),\n        r\"\\Microsoft\\Windows\\.NET Framework\\.NET Framework NGEN v4.0.30319 64\":\n            (\"safe\", True, \".NET 64-bit optimization \u2014 disable karo.\"),\n        r\"\\Microsoft\\Windows\\WDI\\ResolutionHost\":\n            (\"safe\", True, \"Windows Diagnostic Infrastructure \u2014 resource heavy. Disable karo.\"),\n    }\n\n    TASK_CAT_COLOR = {\n        \"danger\":     \"#FF4444\",\n        \"caution\":    \"#FF9800\",\n        \"safe\":       \"#4CAF50\",\n        \"telemetry\":  \"#CE93D8\",\n        \"thirdparty\": \"#64B5F6\",\n    }\n    TASK_CAT_ICON = {\n        \"danger\":\"\ud83d\udd34\",\"caution\":\"\ud83d\udfe0\",\"safe\":\"\ud83d\udfe2\",\"telemetry\":\"\ud83d\udfe3\",\"thirdparty\":\"\ud83d\udd35\"\n    }\n\n    # \u2500\u2500 Preset packs \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    TASK_PRESETS = {\n        \"\u26a1 Telemetry Pack (Privacy)\": {\n            \"desc\": \"Saari Microsoft telemetry tasks disable ho jaayengi \u2014 privacy behtar hogi, CPU spikes khatam.\",\n            \"cats\": {\"telemetry\"}\n        },\n        \"\ud83d\ude80 Performance Pack\": {\n            \"desc\": \"Performance wali tasks disable \u2014 DiskCleanup, WinSAT, .NET NGEN, offline sync sab band.\",\n            \"cats\": {\"safe\"}\n        },\n        \"\u2622\ufe0f Full Nuke (Telemetry + Safe)\": {\n            \"desc\": \"Sabse aggressive \u2014 telemetry + safe tasks dono disable. Maximum performance.\",\n            \"cats\": {\"telemetry\",\"safe\"}\n        },\n    }\n\n    def _build_scheduler(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udcc5 Smart Task Scheduler\",\n                             \"Color-coded \u2014 Danger / Caution / Safe / Telemetry / 3rd Party\")\n\n        # \u2500\u2500 Compact top toolbar (1 row: buttons + filter + legend inline) \u2500\u2500\n        toolbar = tk.Frame(frame, bg=C[\"card\"])\n        toolbar.pack(fill=\"x\", padx=0, pady=0)\n\n        # Action buttons \u2014 inline, compact\n        btn_row = tk.Frame(toolbar, bg=C[\"card\"])\n        btn_row.pack(fill=\"x\", padx=10, pady=4)\n\n        for txt, color, cmd in [\n            (\"\ud83d\udd0d Scan Tasks\",      C[\"btn_info\"],   self._scan_tasks),\n            (\"\u26d4 Disable\",         C[\"btn_warn\"],   self._task_disable_safe),\n            (\"\u2705 Enable\",          C[\"btn\"],        lambda: self._with_confirm(\"Enable Tasks\",\"Enable selected tasks?\", self._enable_task)),\n            (\"\ud83d\uddd1 Delete\",          C[\"btn_danger\"], self._task_delete_safe),\n            (\"\ud83d\udcbe Backup\",          C[\"btn_chip\"],   self._backup_tasks),\n            (\"\ud83d\udd12 Telemetry Pack\",  C[\"btn_hw\"],     lambda: self._apply_task_preset(self.TASK_PRESETS[\"\u26a1 Telemetry Pack (Privacy)\"])),\n            (\"\ud83d\ude80 Perf Pack\",       C[\"btn_hw\"],     lambda: self._apply_task_preset(self.TASK_PRESETS[\"\ud83d\ude80 Performance Pack\"])),\n            (\"\u2622 Full Nuke\",        C[\"btn_hw\"],     lambda: self._apply_task_preset(self.TASK_PRESETS[\"\u2622\ufe0f Full Nuke (Telemetry + Safe)\"])),\n        ]:\n            tk.Button(btn_row, text=txt, font=FONTS[\"small\"], bg=color,\n                      fg=C[\"text\"], bd=0, padx=9, pady=4, cursor=\"hand2\",\n                      command=cmd).pack(side=\"left\", padx=2)\n\n        # \u2500\u2500 Compact: filter + stat counts + legend \u2014 single row \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        mid = tk.Frame(frame, bg=C[\"bg\"])\n        mid.pack(fill=\"x\", padx=10, pady=(2,0))\n\n        # Filter\n        tk.Label(mid, text=\"\ud83d\udd0e\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"]).pack(side=\"left\", padx=(4,2))\n        self.task_search = tk.Entry(mid, width=16, font=FONTS[\"small\"],\n                                    bg=C[\"card\"], fg=C[\"text\"],\n                                    insertbackground=C[\"text\"], relief=\"flat\", bd=3)\n        self.task_search.pack(side=\"left\", padx=(0,4))\n        self.task_search.bind(\"\", self._filter_tasks)\n\n        for lbl, val in [(\"All\",\"all\"),(\"\ud83d\udd34\",\"danger\"),(\"\ud83d\udfe0\",\"caution\"),\n                         (\"\ud83d\udfe2\",\"safe\"),(\"\ud83d\udfe3\",\"telemetry\"),(\"\ud83d\udd35\",\"thirdparty\"),(\"\u26a0\",\"highcpu\")]:\n            tk.Button(mid, text=lbl, font=FONTS[\"small\"],\n                      bg=C[\"card\"], fg=C[\"text\"], bd=0, padx=5, pady=2,\n                      cursor=\"hand2\",\n                      command=lambda v=val: self._filter_task_cat(v)).pack(side=\"left\", padx=1)\n\n        # Stat counts inline\n        tk.Frame(mid, bg=C[\"border\"], width=1).pack(side=\"left\", fill=\"y\", padx=6)\n        self.task_stat_vars = {}\n        for k, lbl, col in [\n            (\"danger\",\"\ud83d\udd34 Danger\",\"#FF4444\"),(\"caution\",\"\ud83d\udfe0 Caution\",\"#FF9800\"),\n            (\"safe\",\"\ud83d\udfe2 Safe\",\"#4CAF50\"),(\"telemetry\",\"\ud83d\udfe3 Telem\",\"#CE93D8\"),\n            (\"thirdparty\",\"\ud83d\udd35 3rd\",\"#64B5F6\"),(\"total\",\"Total\",C[\"accent\"]),\n        ]:\n            v = tk.StringVar(value=\"--\")\n            self.task_stat_vars[k] = v\n            f = tk.Frame(mid, bg=C[\"card\"], padx=5, pady=2)\n            f.pack(side=\"left\", padx=2)\n            tk.Label(f, text=lbl, font=(FONTS[\"small\"][0], 7), fg=col, bg=C[\"card\"]).pack()\n            tk.Label(f, textvariable=v, font=(FONTS[\"small\"][0], 9, \"bold\"), fg=col, bg=C[\"card\"]).pack()\n\n        self.task_count_lbl = tk.Label(mid, text=\"\", font=FONTS[\"small\"],\n                                        fg=C[\"accent\"], bg=C[\"bg\"])\n        self.task_count_lbl.pack(side=\"right\", padx=8)\n\n        # \u2500\u2500 Full-width task list \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        list_frame = tk.Frame(frame, bg=C[\"card\"])\n        list_frame.pack(fill=\"both\", expand=True, padx=16, pady=(4,0))\n        list_frame.rowconfigure(0, weight=1)\n        list_frame.columnconfigure(0, weight=1)\n\n        cols = (\"Cat\",\"Task Name\",\"Path\",\"Status\",\"Last Run\",\"Safe?\")\n        self.task_tree = ttk.Treeview(list_frame, columns=cols, show=\"headings\",\n                                      height=28, style=\"Custom.Treeview\",\n                                      selectmode=\"extended\")\n        widths = [28, 280, 340, 80, 120, 65]\n        for col, w in zip(cols, widths):\n            self.task_tree.heading(col, text=col,\n                                   command=lambda c=col: self._sort_tasks(c))\n            self.task_tree.column(col, width=w,\n                                  anchor=\"center\" if col in (\"Cat\",\"Status\",\"Safe?\") else \"w\")\n        for cat, color in self.TASK_CAT_COLOR.items():\n            self.task_tree.tag_configure(cat, foreground=color)\n        self.task_tree.tag_configure(\"highcpu\", background=\"#2A1500\")\n        vsb = ttk.Scrollbar(list_frame, orient=\"vertical\", command=self.task_tree.yview)\n        hsb = ttk.Scrollbar(list_frame, orient=\"horizontal\", command=self.task_tree.xview)\n        self.task_tree.configure(yscrollcommand=vsb.set, xscrollcommand=hsb.set)\n        self.task_tree.grid(row=0, column=0, sticky=\"nsew\", padx=(4,0), pady=(4,0))\n        vsb.grid(row=0, column=1, sticky=\"ns\", pady=(4,0))\n        hsb.grid(row=1, column=0, sticky=\"ew\", padx=(4,0))\n        self.task_tree.bind(\"&lt;&gt;\", self._on_task_select)\n\n        # \u2500\u2500 Bottom collapsible detail + action log strip \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        bot = tk.Frame(frame, bg=C[\"panel\"])\n        bot.pack(fill=\"x\", padx=16, pady=(2,8))\n        bot.columnconfigure(0, weight=3)\n        bot.columnconfigure(1, weight=1)\n\n        # Detail box (left-bottom)\n        detail_wrap = tk.Frame(bot, bg=C[\"card\"])\n        detail_wrap.grid(row=0, column=0, sticky=\"nsew\", padx=(0,4), pady=4)\n        detail_wrap.rowconfigure(1, weight=1)\n        detail_wrap.columnconfigure(0, weight=1)\n\n        hdr_d = tk.Frame(detail_wrap, bg=C[\"card\"])\n        hdr_d.grid(row=0, column=0, sticky=\"ew\", padx=6, pady=(4,2))\n        tk.Label(hdr_d, text=\"  \ud83d\udccb Task Detail &amp; Risk Info\",\n                 font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\")\n        tk.Label(hdr_d, text=\"(koi bhi task click karo \u2014 detail yahan dikhe gi)\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\", padx=6)\n\n        self.task_detail = scrolledtext.ScrolledText(\n            detail_wrap, font=(\"Consolas\", 9), bg=\"#0D1117\", fg=C[\"text\"],\n            height=8, bd=0, relief=\"flat\", state=\"disabled\", wrap=\"word\")\n        self.task_detail.grid(row=1, column=0, sticky=\"nsew\", padx=6, pady=(0,4))\n\n        # Action log (right-bottom)\n        log_wrap = tk.Frame(bot, bg=C[\"card\"])\n        log_wrap.grid(row=0, column=1, sticky=\"nsew\", padx=(4,0), pady=4)\n        log_wrap.rowconfigure(1, weight=1)\n        log_wrap.columnconfigure(0, weight=1)\n        tk.Label(log_wrap, text=\"  \ud83d\udcdd Action Log\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).grid(\n                 row=0, column=0, sticky=\"w\", padx=6, pady=(4,2))\n        self.task_action_log = scrolledtext.ScrolledText(\n            log_wrap, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"],\n            insertbackground=C[\"text\"], height=8, bd=0, wrap=\"word\",\n            relief=\"flat\", state=\"disabled\")\n        self.task_action_log.grid(row=1, column=0, sticky=\"nsew\", padx=6, pady=(0,4))\n\n        # Internal state\n        self._task_all_rows = []\n        self._task_cur_cat = \"all\"\n        self._task_sort_col = \"\"\n        self._task_sort_rev = False\n        return frame\n\n    def _scan_tasks(self):\n        self._set_status(\"Scanning scheduled tasks...\", C[\"accent4\"])\n        if hasattr(self, \"_task_scan_status\"):\n            self._task_scan_status.config(text=\"  \u23f3 Scan chal rahi hai...\", fg=C[\"accent4\"])\n        self._launch_job(\"scan_tasks\", self._do_scan_tasks)\n\n    def _do_scan_tasks_legacy(self):\n        self.after(0, lambda: [self.task_tree.delete(i) for i in self.task_tree.get_children()])\n\n        # schtasks /query /fo CSV /v \u2014 fastest method\n        out, _ = self._run_cmd('schtasks /query /fo CSV /v', timeout=25)\n\n        # Third-party path indicators\n        THIRD_PARTY_ROOTS = {\n            \"google\",\"mozilla\",\"adobe\",\"java\",\"dropbox\",\"spotify\",\"discord\",\n            \"steam\",\"nvidia\",\"amd\",\"intel\",\"realtek\",\"logitech\",\"corsair\",\n            \"razer\",\"zoom\",\"teams\",\"skype\",\"ccleaner\",\"iobit\",\"malwarebytes\",\n            \"avast\",\"avg\",\"kaspersky\",\"mcafee\",\"norton\",\"bitdefender\",\n        }\n\n        counts = {k:0 for k in (\"danger\",\"caution\",\"safe\",\"telemetry\",\"thirdparty\",\"total\")}\n        seen   = set()\n        rows   = []\n\n        for line in out.splitlines():\n            line = line.strip().replace('\"','')\n            parts = line.split(',')\n            if len(parts) &lt; 7 or parts[0] == \"TaskName\":\n                continue\n            task_full = parts[0].strip()\n            status    = parts[3].strip() if len(parts) &gt; 3 else \"\"\n            last_run  = parts[5].strip() if len(parts) &gt; 5 else \"\"\n            if not task_full or task_full in seen:\n                continue\n            seen.add(task_full)\n\n            # Path split\n            if \"\\\\\" in task_full:\n                tpath = task_full.rsplit(\"\\\\\",1)[0] + \"\\\\\"\n                tname = task_full.rsplit(\"\\\\\",1)[1]\n            else:\n                tpath = \"\\\\\"\n                tname = task_full\n\n            if not tname:\n                continue\n\n            # Lookup DB\n            if task_full in self.TASK_DB:\n                cat, safe, desc = self.TASK_DB[task_full]\n            else:\n                tpath_low = tpath.lower()\n                tname_low = tname.lower()\n                full_low  = task_full.lower()\n                is_third = any(tp in full_low for tp in THIRD_PARTY_ROOTS)\n                if is_third:\n                    cat  = \"thirdparty\"\n                    safe = True\n                    desc = (f\"'{tname}' \u2014 Third-party software task.\\n\"\n                            \"Agar woh software use karte ho: disable mat karo.\\n\"\n                            \"Agar uninstall ho gaya: disable kar sakte ho.\")\n                elif \"\\\\microsoft\\\\windows\\\\\" in full_low:\n                    # Skip system tasks not in DB \u2014 they're likely safe/necessary\n                    if status.lower() == \"disabled\":\n                        continue\n                    cat  = \"caution\"\n                    safe = False\n                    desc = (f\"'{tname}' \u2014 Windows system task (hamare database mein nahi).\\n\"\n                            \"Google karo pehle, phir decide karo.\")\n                else:\n                    cat  = \"safe\"\n                    safe = True\n                    desc = (f\"'{tname}' \u2014 Unknown task, root folder mein hai.\\n\"\n                            \"Likely kisi software ka task hai. Safe to disable if unrecognized.\")\n\n            if status.lower() == \"disabled\":\n                continue\n\n            icon = self.TASK_CAT_ICON.get(cat,\"\u26aa\")\n            safe_txt = \"\u2705\" if safe else \"\u274c\"\n            row = (icon, tname, tpath, status, last_run[:16], safe_txt)\n            meta = {\"cat\":cat,\"safe\":safe,\"desc\":desc,\n                    \"full\":task_full,\"name\":tname,\"path\":tpath,\"status\":status,\n                    \"last_run\":last_run[:16] if last_run else \"N/A\"}\n            rows.append((row, (cat,), meta))\n            if cat in counts:\n                counts[cat] += 1\n            counts[\"total\"] += 1\n\n        self._task_all_rows = rows\n\n        def insert():\n            self._render_task_rows(rows)\n            for k,v in counts.items():\n                if k in self.task_stat_vars:\n                    self.task_stat_vars[k].set(str(v))\n            self._set_status(\n                f\"Scan done \u2014 {counts['total']} tasks | \"\n                f\"\ud83d\udfe3{counts['telemetry']} Telemetry | \"\n                f\"\ud83d\udfe2{counts['safe']} Safe | \"\n                f\"\ud83d\udfe0{counts['caution']} Caution | \"\n                f\"\ud83d\udd35{counts['thirdparty']} 3rd-Party\",\n                C[\"success\"])\n            if hasattr(self, \"_task_scan_status\"):\n                self._task_scan_status.config(\n                    text=f\"  \u2705 {counts['total']} tasks mile \u2014 task pe click karo detail dekhne ke liye\",\n                    fg=C[\"success\"])\n        self.after(0, insert)\n\n    def _do_scan_tasks(self):\n        self.after(0, lambda: [self.task_tree.delete(i) for i in self.task_tree.get_children()])\n        out, _ = self._run_cmd('schtasks /query /fo CSV /v', timeout=25)\n        third_party_roots = {\n            \"google\",\"mozilla\",\"adobe\",\"java\",\"dropbox\",\"spotify\",\"discord\",\n            \"steam\",\"nvidia\",\"amd\",\"intel\",\"realtek\",\"logitech\",\"corsair\",\n            \"razer\",\"zoom\",\"teams\",\"skype\",\"ccleaner\",\"iobit\",\"malwarebytes\",\n            \"avast\",\"avg\",\"kaspersky\",\"mcafee\",\"norton\",\"bitdefender\",\n        }\n        counts = {k: 0 for k in (\"danger\",\"caution\",\"safe\",\"telemetry\",\"thirdparty\",\"total\")}\n        seen = set()\n        rows = []\n        for record in self._task_records_from_schtasks(out):\n            task_full = (record.get(\"TaskName\") or record.get(\"Task Name\") or \"\").strip()\n            scheduled_state = (record.get(\"Scheduled Task State\") or \"\").strip()\n            status = (record.get(\"Status\") or scheduled_state or \"\").strip()\n            last_run = (record.get(\"Last Run Time\") or record.get(\"LastRunTime\") or \"\").strip()\n            run_cmd = (record.get(\"Task To Run\") or \"\").strip()\n            if not task_full or task_full in seen:\n                continue\n            seen.add(task_full)\n            if \"\\\\\" in task_full:\n                tpath = task_full.rsplit(\"\\\\\", 1)[0] + \"\\\\\"\n                tname = task_full.rsplit(\"\\\\\", 1)[1]\n            else:\n                tpath = \"\\\\\"\n                tname = task_full\n            if not tname:\n                continue\n            if task_full in self.TASK_DB:\n                cat, safe, desc = self.TASK_DB[task_full]\n            else:\n                full_low = task_full.lower()\n                is_third = any(tp in full_low for tp in third_party_roots)\n                if is_third:\n                    cat = \"thirdparty\"\n                    safe = True\n                    desc = (f\"'{tname}' - Third-party software task.\\n\"\n                            \"Agar woh software use karte ho: disable mat karo.\\n\"\n                            \"Agar uninstall ho gaya: disable kar sakte ho.\")\n                elif \"\\\\microsoft\\\\windows\\\\\" in full_low:\n                    if status.lower() == \"disabled\" or scheduled_state.lower() == \"disabled\":\n                        continue\n                    cat = \"caution\"\n                    safe = False\n                    desc = (f\"'{tname}' - Windows system task (database mein nahi).\\n\"\n                            \"Google karo pehle, phir decide karo.\")\n                else:\n                    cat = \"safe\"\n                    safe = True\n                    desc = (f\"'{tname}' - Unknown task, root folder mein hai.\\n\"\n                            \"Likely kisi software ka task hai. Safe to disable if unrecognized.\")\n            if status.lower() == \"disabled\" or scheduled_state.lower() == \"disabled\":\n                continue\n            icon = self.TASK_CAT_ICON.get(cat, \"*\")\n            safe_txt = \"\u2705\" if safe else \"\u274c\"\n            row = (icon, tname, tpath, status, last_run[:16], safe_txt)\n            meta = {\"cat\": cat, \"safe\": safe, \"desc\": desc,\n                    \"full\": task_full, \"name\": tname, \"path\": tpath, \"status\": status,\n                    \"last_run\": last_run[:16] if last_run else \"N/A\",\n                    \"run_cmd\": run_cmd or \"N/A\",\n                    \"scheduled_state\": scheduled_state or \"N/A\"}\n            rows.append((row, (cat,), meta))\n            if cat in counts:\n                counts[cat] += 1\n            counts[\"total\"] += 1\n        self._task_all_rows = rows\n\n        def insert():\n            self._render_task_rows(rows)\n            for k, v in counts.items():\n                if k in self.task_stat_vars:\n                    self.task_stat_vars[k].set(str(v))\n            self._set_status(\n                f\"Scan done - {counts['total']} tasks | \"\n                f\"{counts['telemetry']} Telemetry | \"\n                f\"{counts['safe']} Safe | \"\n                f\"{counts['caution']} Caution | \"\n                f\"{counts['thirdparty']} 3rd-Party\",\n                C[\"success\"])\n            if hasattr(self, \"_task_scan_status\"):\n                self._task_scan_status.config(\n                    text=f\"  {counts['total']} tasks mile - task pe click karo detail dekhne ke liye\",\n                    fg=C[\"success\"])\n        self.after(0, insert)\n\n    def _render_task_rows(self, rows):\n        for i in self.task_tree.get_children():\n            self.task_tree.delete(i)\n        for row, tags, _ in rows:\n            self.task_tree.insert(\"\",\"end\", values=row, tags=tags)\n        self.task_count_lbl.config(text=f\"{len(rows)} tasks\")\n\n    def _filter_tasks(self, event=None):\n        txt = self.task_search.get().lower() if hasattr(self,\"task_search\") else \"\"\n        cat = self._task_cur_cat\n        filtered = [r for r in self._task_all_rows\n                    if (cat==\"all\" or cat in r[1])\n                    and (not txt or txt in r[2][\"name\"].lower()\n                         or txt in r[2][\"path\"].lower())]\n        self._render_task_rows(filtered)\n\n    def _filter_task_cat(self, cat):\n        self._task_cur_cat = cat\n        self._filter_tasks()\n\n    def _sort_tasks(self, col):\n        col_map = {\"Cat\":0,\"Task Name\":1,\"Path\":2,\"Status\":3,\"Last Run\":4,\"Safe?\":5}\n        idx = col_map.get(col,1)\n        if self._task_sort_col == col:\n            self._task_sort_rev = not self._task_sort_rev\n        else:\n            self._task_sort_col = col\n            self._task_sort_rev = False\n        self._task_all_rows.sort(key=lambda r: r[0][idx], reverse=self._task_sort_rev)\n        self._filter_tasks()\n\n    def _on_task_select(self, event=None):\n        sel = self.task_tree.selection()\n        if not sel:\n            return\n        iid = sel[0]\n        idx = self.task_tree.index(iid)\n        visible = self._get_visible_task_rows()\n        if idx &gt;= len(visible):\n            return\n        meta = visible[idx][2]\n        cat  = meta[\"cat\"]\n        safe = meta[\"safe\"]\n        desc = meta[\"desc\"]\n        icon = self.TASK_CAT_ICON.get(cat,\"\u26aa\")\n        col  = self.TASK_CAT_COLOR.get(cat, C[\"text\"])\n\n        cat_label = {\n            \"danger\":    \"\ud83d\udd34 DANGER \u2014 Kabhi disable mat karo\",\n            \"caution\":   \"\ud83d\udfe0 CAUTION \u2014 Soch ke disable karo\",\n            \"safe\":      \"\ud83d\udfe2 SAFE \u2014 Disable karne se performance badhegi\",\n            \"telemetry\": \"\ud83d\udfe3 TELEMETRY \u2014 Microsoft ko data bhejta hai\",\n            \"thirdparty\":\"\ud83d\udd35 THIRD-PARTY \u2014 Software ka task\",\n        }.get(cat,\"\u26aa Unknown\")\n\n        risk_box = {\n            \"danger\":   (\"\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\\n\"\n                         \"\u2551 \u26d4 DISABLE MAT KARO \u2014 SYSTEM TOOTEGA \u2551\\n\"\n                         \"\u255a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255d\\n\"),\n            \"caution\":  \"\u26a0\ufe0f  SAWDHAN \u2014 Pehle Google karo, phir disable karo.\\n\",\n            \"safe\":     \"\u2705 DISABLE KARO \u2014 Safe hai, performance badhegi.\\n\",\n            \"telemetry\":(\"\ud83d\udfe3 DISABLE KARO \u2014 Ye task Microsoft ko aapka data bhejta hai.\\n\"\n                         \"   Privacy aur CPU ke liye disable karna better hai.\\n\"),\n            \"thirdparty\":(\"\ud83d\udd35 THIRD-PARTY \u2014 Agar software use karte ho: chhodo.\\n\"\n                          \"   Agar software remove ho gaya: Disable karo.\\n\"),\n        }.get(cat,\"\")\n\n        lines = [\n            f\"Task Name  : {meta['name']}\",\n            f\"Full Path  : {meta['full']}\",\n            f\"Category   : {cat_label}\",\n            f\"Status     : {meta['status']}\",\n            f\"Process    : {meta.get('run_cmd', 'N/A')}\",\n            f\"Last Run   : {meta.get('last_run', 'N/A')}\",\n            f\"Safe Disable: {'\u2705 Haan' if safe else '\u274c Nahi'}\",\n            \"\", \"\u2500\"*52, \"\",\n            \"\ud83d\udcd6 DESCRIPTION:\",\n            desc,\n            \"\", \"\u2500\"*52, \"\",\n            \"\u26a0\ufe0f  DISABLE KARNE SE KYA HOGA:\",\n            risk_box,\n            \"\ud83d\udca1 TIP:\",\n            {\n                \"danger\":    \"Isko chhod do \u2014 Windows ke kaam ka hai.\",\n                \"caution\":   \"SSD pe defrag/chkdsk disable karo \u2014 warna safe mat karo.\",\n                \"safe\":      f\"schtasks /Change /TN \\\"{meta['full']}\\\" /Disable\",\n                \"telemetry\": f\"schtasks /Change /TN \\\"{meta['full']}\\\" /Disable\",\n                \"thirdparty\":\"Software se hi manage karo ya uninstall karo.\",\n            }.get(cat,\"\"),\n        ]\n\n        self.task_detail.config(state=\"normal\")\n        self.task_detail.delete(\"1.0\",\"end\")\n        self.task_detail.tag_configure(\"red\",    foreground=\"#FF4444\")\n        self.task_detail.tag_configure(\"orange\", foreground=\"#FF9800\")\n        self.task_detail.tag_configure(\"green\",  foreground=\"#4CAF50\")\n        self.task_detail.tag_configure(\"purple\", foreground=\"#CE93D8\")\n        self.task_detail.tag_configure(\"blue\",   foreground=\"#64B5F6\")\n        self.task_detail.tag_configure(\"dim\",    foreground=\"#A0B0C8\")\n        for line in lines:\n            tag = \"dim\"\n            if \"DISABLE MAT\" in line or \"\u26d4\" in line: tag = \"red\"\n            elif \"SAWDHAN\" in line or \"\u26a0\ufe0f\" in line:   tag = \"orange\"\n            elif \"\u2705\" in line and \"DISABLE KARO\" in line: tag = \"green\"\n            elif \"\ud83d\udfe3\" in line:                         tag = \"purple\"\n            elif \"\ud83d\udd35\" in line:                         tag = \"blue\"\n            elif line.startswith(\"\u2500\"):                 tag = \"dim\"\n            elif line.startswith(\"Task\") or line.startswith(\"Full\") or line.startswith(\"Status\"): tag = \"dim\"\n            self.task_detail.insert(\"end\", line+\"\\n\", tag)\n        self.task_detail.config(state=\"disabled\")\n\n    def _get_visible_task_rows(self):\n        cat = self._task_cur_cat\n        txt = self.task_search.get().lower() if hasattr(self,\"task_search\") else \"\"\n        rows = self._task_all_rows\n        if cat != \"all\":\n            rows = [r for r in rows if cat in r[1]]\n        if txt:\n            rows = [r for r in rows\n                    if txt in r[2][\"name\"].lower() or txt in r[2][\"path\"].lower()]\n        return rows\n\n    def _task_disable_safe(self):\n        sel = self.task_tree.selection()\n        if not sel:\n            messagebox.showinfo(\"No Selection\",\"Pehle ek task select karo.\")\n            return\n        visible = self._get_visible_task_rows()\n        block, warn, targets = [], [], []\n        for iid in sel:\n            idx = self.task_tree.index(iid)\n            if idx &gt;= len(visible): continue\n            meta = visible[idx][2]\n            if meta[\"cat\"] == \"danger\" and not meta[\"safe\"]:\n                block.append(f\"  \ud83d\udd34 {meta['name']} \u2014 DANGER!\")\n            elif meta[\"cat\"] == \"caution\":\n                warn.append(f\"  \ud83d\udfe0 {meta['name']} \u2014 Caution task\")\n            targets.append(meta)\n\n        if block:\n            messagebox.showerror(\"\u26d4 KHATARNAK!\",\n                \"Ye tasks KABHI disable mat karo \u2014 system crash ho sakta hai!\\n\\n\"\n                + \"\\n\".join(block) + \"\\n\\nDeselect karo aur dubara try karo.\")\n            return\n        msg = f\"Disable karne se ye {len(targets)} tasks band ho jaayenge:\\n\\n\"\n        msg += \"\\n\".join(f\"  {self.TASK_CAT_ICON.get(t['cat'],'\u2022')} {t['name']}\" for t in targets[:15])\n        if len(targets) &gt; 15:\n            msg += f\"\\n  ...aur {len(targets)-15} aur\"\n        if warn:\n            msg += \"\\n\\n\u26a0\ufe0f CAUTION tasks included:\\n\" + \"\\n\".join(warn)\n        msg += \"\\n\\nAage badhein?\"\n        if not messagebox.askyesno(\"Confirm Disable\", msg):\n            return\n        disabled = 0\n        for meta in targets:\n            out, rc = self._run_cmd(f'schtasks /Change /TN \"{meta[\"full\"]}\" /Disable')\n            if rc == 0:\n                disabled += 1\n                self._append_log(self.task_action_log, f\"\u2705 Disabled: {meta['name']}\", C[\"success\"])\n            else:\n                self._append_log(self.task_action_log, f\"\u274c Failed: {meta['name']} \u2014 {out[:60]}\", C[\"error\"])\n        self._set_status(f\"Disabled {disabled}/{len(targets)} tasks\", C[\"success\"])\n        self._scan_tasks()\n\n    def _enable_task(self):\n        visible = self._get_visible_task_rows()\n        for iid in self.task_tree.selection():\n            idx = self.task_tree.index(iid)\n            if idx &gt;= len(visible): continue\n            meta = visible[idx][2]\n            self._run_cmd(f'schtasks /Change /TN \"{meta[\"full\"]}\" /Enable')\n            self._append_log(self.task_action_log, f\"\u2705 Enabled: {meta['name']}\", C[\"success\"])\n        self._scan_tasks()\n\n    def _task_delete_safe(self):\n        sel = self.task_tree.selection()\n        if not sel:\n            messagebox.showinfo(\"No Selection\",\"Pehle task select karo.\")\n            return\n        visible = self._get_visible_task_rows()\n        block, targets = [], []\n        for iid in sel:\n            idx = self.task_tree.index(iid)\n            if idx &gt;= len(visible): continue\n            meta = visible[idx][2]\n            if meta[\"cat\"] == \"danger\":\n                block.append(f\"  \ud83d\udd34 {meta['name']}\")\n            else:\n                targets.append(meta)\n        if block:\n            messagebox.showerror(\"\u26d4 KHATARNAK!\",\n                \"Ye tasks DELETE NAHI karne chahiye:\\n\\n\" + \"\\n\".join(block))\n            return\n        if not targets:\n            return\n        if not messagebox.askyesno(\"Confirm DELETE\",\n                f\"Permanently delete {len(targets)} tasks?\\n\"\n                \"\u26a0\ufe0f Delete ke baad wapas nahi aayenge!\\n\\n\"\n                \"Pehle Backup Tasks karo.\"):\n            return\n        for meta in targets:\n            self._run_cmd(f'schtasks /Delete /TN \"{meta[\"full\"]}\" /F')\n            self._append_log(self.task_action_log, f\"\ud83d\uddd1 Deleted: {meta['name']}\", C[\"warning\"])\n        self._scan_tasks()\n\n    def _disable_task(self):\n        visible = self._get_visible_task_rows()\n        for iid in self.task_tree.selection():\n            idx = self.task_tree.index(iid)\n            if idx &gt;= len(visible): continue\n            meta = visible[idx][2]\n            self._run_cmd(f'schtasks /Change /TN \"{meta[\"full\"]}\" /Disable')\n        self._scan_tasks()\n\n    def _delete_task(self):\n        visible = self._get_visible_task_rows()\n        for iid in self.task_tree.selection():\n            idx = self.task_tree.index(iid)\n            if idx &gt;= len(visible): continue\n            meta = visible[idx][2]\n            self._run_cmd(f'schtasks /Delete /TN \"{meta[\"full\"]}\" /F')\n        self._scan_tasks()\n\n    def _apply_task_preset(self, pack):\n        if not self._task_all_rows:\n            messagebox.showinfo(\"Pehle Scan Karo\",\"Pehle 'Scan All Tasks' click karo.\")\n            return\n        cats   = pack[\"cats\"]\n        desc   = pack[\"desc\"]\n        targets = [r[2] for r in self._task_all_rows if r[2][\"cat\"] in cats and r[2][\"safe\"]]\n        if not targets:\n            messagebox.showinfo(\"Koi Task Nahi\",f\"Is preset ke liye koi task nahi mila.\\nPehle Scan karo.\")\n            return\n        msg = (f\"{desc}\\n\\n\"\n               f\"{len(targets)} tasks disable ho jaayengi:\\n\\n\"\n               + \"\\n\".join(f\"  {self.TASK_CAT_ICON.get(t['cat'],'\u2022')} {t['name']}\"\n                            for t in targets[:20])\n               + (f\"\\n  ...aur {len(targets)-20} aur\" if len(targets)&gt;20 else \"\")\n               + \"\\n\\nAage badhein?\")\n        if not messagebox.askyesno(\"Confirm Preset\", msg):\n            return\n        done = 0\n        for meta in targets:\n            out, rc = self._run_cmd(f'schtasks /Change /TN \"{meta[\"full\"]}\" /Disable')\n            if rc == 0:\n                done += 1\n                self._append_log(self.task_action_log, f\"\u2705 {meta['name']}\", C[\"success\"])\n        messagebox.showinfo(\"Done!\",\n            f\"\u2705 {done}/{len(targets)} tasks disable ho gayi!\\nRestart karo best results ke liye.\")\n        self._scan_tasks()\n\n    def _backup_tasks(self):\n        dest = filedialog.asksaveasfilename(\n            title=\"Save Task Backup Script\",\n            defaultextension=\".bat\",\n            filetypes=[(\"Batch File\",\"*.bat\"),(\"All Files\",\"*.*\")],\n            initialfile=\"task_backup_restore.bat\")\n        if not dest:\n            return\n        lines = [\"@echo off\",\"echo Restoring disabled tasks...\",\"\"]\n        for row, tags, meta in self._task_all_rows:\n            lines.append(f'schtasks /Change /TN \"{meta[\"full\"]}\" /Enable')\n        lines += [\"\",\"echo Done! All tasks re-enabled.\",\"pause\"]\n        try:\n            with open(dest,\"w\") as f:\n                f.write(\"\\n\".join(lines))\n            messagebox.showinfo(\"Backup Saved\",\n                f\"\u2705 Restore script saved to:\\n{dest}\\n\\n\"\n                \"Agar kuch galat ho jaaye, is .bat file ko Run as Administrator se chalao.\")\n        except Exception as e:\n            messagebox.showerror(\"Error\", str(e))\n\n    # ---------- REGISTRY TWEAKS (with confirm) ----------\n    def _build_registry(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udccb Registry Tweaks\", \"Safe performance tweaks\")\n        content = tk.Frame(frame, bg=C[\"bg\"])\n        content.pack(fill=\"both\", expand=True, padx=16, pady=10)\n        content.columnconfigure(0, weight=1)\n        content.columnconfigure(1, weight=2)\n        left = tk.Frame(content, bg=C[\"card\"])\n        left.grid(row=0, column=0, sticky=\"nsew\", padx=(0,6))\n        tk.Label(left, text=\"  Tweaks\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8,4), padx=8)\n        for k, label in [\n            (\"visual_fx\", \"Disable Visual Effects\"),\n            (\"menu_delay\", \"Reduce Menu Delay\"),\n            (\"search_idx\", \"Disable Search Indexing\"),\n            (\"telemetry\", \"Minimize Telemetry\"),\n            (\"ntfs_last\", \"Disable Last Access Timestamp\"),\n            (\"autorun\", \"Disable Autorun\"),\n            (\"shutdown_fast\", \"Fast Shutdown Speed\"),\n            (\"extreme_visual\", \"Extreme Visual Effects Off (Aero, Shadows, Animations)\"),\n        ]:\n            var = tk.BooleanVar(value=True)\n            self.reg_vars[k] = var\n            tk.Checkbutton(left, text=f\"  {label}\", variable=var, font=FONTS[\"body\"], fg=C[\"text\"], bg=C[\"card\"], activebackground=C[\"card\"], selectcolor=C[\"panel\"], bd=0).pack(anchor=\"w\", padx=12, pady=2)\n        btn_row = tk.Frame(left, bg=C[\"card\"])\n        btn_row.pack(fill=\"x\", padx=12, pady=10)\n        self._btn(btn_row, \"\u2705 Apply Selected Tweaks\", C[\"btn\"], self._apply_registry).pack(fill=\"x\", pady=2)\n        self._btn(btn_row, \"\ud83d\udcbe Export Backup\", C[\"btn_chip\"], self._export_registry_backup).pack(fill=\"x\", pady=2)\n        self._btn(btn_row, \"\u267b\ufe0f Import .reg\", C[\"btn_warn\"], self._import_registry_backup).pack(fill=\"x\", pady=2)\n        right = tk.Frame(content, bg=C[\"card\"])\n        right.grid(row=0, column=1, sticky=\"nsew\", padx=(6,0))\n        tk.Label(right, text=\"  Registry Dashboard\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8,4), padx=8)\n        self.reg_progress_var = tk.DoubleVar(value=0.0)\n        self.reg_progress_bar = ttk.Progressbar(right, variable=self.reg_progress_var, maximum=100, mode=\"determinate\")\n        self.reg_progress_bar.pack(fill=\"x\", padx=12, pady=(0,6))\n        self.reg_status_lbl = tk.Label(right, text=\"Ready for registry optimization\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"])\n        self.reg_status_lbl.pack(anchor=\"w\", padx=12, pady=(0,8))\n        metrics = tk.Frame(right, bg=C[\"card\"])\n        metrics.pack(fill=\"x\", padx=12, pady=(0,6))\n        self.reg_keys_changed_var = tk.StringVar(value=\"0\")\n        self.reg_predicted_impact_var = tk.StringVar(value=\"--\")\n        self.reg_confidence_var = tk.StringVar(value=\"--\")\n        for label, var, fg in [\n            (\"Keys Changed\", self.reg_keys_changed_var, C[\"accent4\"]),\n            (\"Impact Score\", self.reg_predicted_impact_var, C[\"success\"]),\n            (\"Confidence\", self.reg_confidence_var, C[\"warning\"]),\n        ]:\n            card = tk.Frame(metrics, bg=C[\"bg\"], padx=8, pady=8)\n            card.pack(side=\"left\", fill=\"x\", expand=True, padx=3)\n            tk.Label(card, text=label, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"]).pack(anchor=\"w\")\n            tk.Label(card, textvariable=var, font=(\"Segoe UI\", 14, \"bold\"), fg=fg, bg=C[\"bg\"]).pack(anchor=\"w\")\n        tk.Label(right, text=\"  Startup Audit\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8,4), padx=8)\n        startup_btn_row = tk.Frame(right, bg=C[\"card\"])\n        startup_btn_row.pack(fill=\"x\", padx=12, pady=(0,6))\n        self._btn(startup_btn_row, \"\ud83d\udd04 Refresh Audit\", C[\"btn_info\"], self._refresh_registry_startup).pack(side=\"left\", padx=(0,4))\n        self._btn(startup_btn_row, \"\ud83d\uddd1 Delete Selected\", C[\"btn_danger\"], self._delete_registry_startup_selected).pack(side=\"left\")\n        self.registry_startup_tree = ttk.Treeview(right, columns=(\"Name\", \"Command\", \"Location\", \"Status\"), show=\"headings\", height=8, style=\"Custom.Treeview\")\n        for col, w in ((\"Name\", 180), (\"Command\", 280), (\"Location\", 160), (\"Status\", 80)):\n            self.registry_startup_tree.heading(col, text=col)\n            self.registry_startup_tree.column(col, width=w, anchor=\"w\")\n        vsb = ttk.Scrollbar(right, orient=\"vertical\", command=self.registry_startup_tree.yview)\n        self.registry_startup_tree.configure(yscrollcommand=vsb.set)\n        self.registry_startup_tree.pack(side=\"left\", fill=\"both\", expand=True, padx=(12, 0), pady=(0,8))\n        vsb.pack(side=\"right\", fill=\"y\", padx=(0, 12), pady=(0,8))\n        self._registry_startup_items = {}\n        self._refresh_registry_startup()\n        tk.Label(right, text=\"  Execution Log\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8,4), padx=8)\n        self.reg_log = self._scrolled_text(right, height=16)\n        self.reg_exec_log = self.reg_log\n        return frame\n\n    def _apply_registry(self):\n        def before():\n            return \"Registry changes will be applied. A restore point can be created.\"\n        self._confirm_and_launch_job(\"Registry Tweaks\", \"This will apply selected registry tweaks to improve performance.\\nIt is recommended to create a restore point first (will ask).\",\n                                      before, \"registry_tweaks\", self._do_registry)\n        # Note: _do_registry contains the actual registry changes and also creates restore point inside it.\n\n    def _export_registry_backup(self):\n        folder = filedialog.askdirectory(title=\"Select folder for registry backup\")\n        if not folder:\n            return\n        keys = [\n            r\"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\VisualEffects\",\n            r\"HKCU\\Control Panel\\Desktop\",\n            r\"HKLM\\SOFTWARE\\Policies\\Microsoft\\Windows\\DataCollection\",\n            r\"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer\",\n            r\"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Multimedia\\SystemProfile\",\n        ]\n        try:\n            paths = []\n            for key in keys:\n                safe_key = re.sub(r'[:\\\\]', '_', key)\n                export_path = os.path.join(folder, f\"Godawari_Registry_Backup_{safe_key}.reg\")\n                out, rc = self._run_cmd(f'reg export \"{key}\" \"{export_path}\" /y', timeout=20)\n                if rc != 0:\n                    raise RuntimeError(out.strip() or f\"reg export failed for {key}\")\n                paths.append(export_path)\n            messagebox.showinfo(\"Saved\", f\"Registry backup files exported to:\\n{folder}\")\n            self._append_log(self.reg_log, f\"\ud83d\udcbe Registry backup exported: {', '.join(paths)}\", C[\"success\"])\n        except Exception as e:\n            messagebox.showerror(\"Export Failed\", str(e))\n            self._append_log(self.reg_log, f\"\u274c Registry backup failed: {e}\", C[\"error\"])\n\n    def _import_registry_backup(self):\n        path = filedialog.askopenfilename(filetypes=[(\"Registry files\", \"*.reg\")], title=\"Open Registry Backup\")\n        if not path:\n            return\n        if not messagebox.askyesno(\"Import Registry Backup\", f\"Import registry file? This may change system settings.\\n{path}\"):\n            return\n        out, rc = self._run_cmd(f'reg import \"{path}\"', timeout=30)\n        if rc == 0:\n            messagebox.showinfo(\"Imported\", \"Registry backup imported successfully. Restart recommended.\")\n            self._append_log(self.reg_log, f\"\u2705 Imported registry backup: {path}\", C[\"success\"])\n        else:\n            messagebox.showerror(\"Import Failed\", out[:1000] or \"Unknown error\")\n            self._append_log(self.reg_log, f\"\u274c Registry import failed: {out[:200]}\", C[\"error\"])\n\n    def _do_registry_legacy(self):\n        v = self.reg_vars\n        if v[\"menu_delay\"].get():\n            self._reg_set(winreg.HKEY_CURRENT_USER, r\"Control Panel\\Desktop\", \"MenuShowDelay\", \"0\", winreg.REG_SZ)\n            self._append_log(self.reg_log, \"\u2705 Menu delay 0ms\", C[\"success\"])\n        if v[\"visual_fx\"].get():\n            self._reg_set(winreg.HKEY_CURRENT_USER, r\"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\VisualEffects\", \"VisualFXSetting\", 2, winreg.REG_DWORD)\n            self._append_log(self.reg_log, \"\u2705 Visual effects disabled\", C[\"success\"])\n        if v[\"search_idx\"].get():\n            self._run_cmd('sc config \"WSearch\" start= disabled')\n            self._run_cmd('sc stop \"WSearch\"')\n            self._append_log(self.reg_log, \"\u2705 Search indexing disabled\", C[\"success\"])\n        if v[\"telemetry\"].get():\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Policies\\Microsoft\\Windows\\DataCollection\", \"AllowTelemetry\", 0, winreg.REG_DWORD)\n            self._append_log(self.reg_log, \"\u2705 Telemetry minimized\", C[\"success\"])\n        if v[\"ntfs_last\"].get():\n            self._run_cmd(\"fsutil behavior set disablelastaccess 1\")\n            self._append_log(self.reg_log, \"\u2705 NTFS timestamp disabled\", C[\"success\"])\n        if v[\"autorun\"].get():\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer\", \"NoDriveTypeAutoRun\", 255, winreg.REG_DWORD)\n            self._append_log(self.reg_log, \"\u2705 Autorun disabled\", C[\"success\"])\n        if v.get(\"extreme_visual\") and v[\"extreme_visual\"].get():\n            self._reg_set(winreg.HKEY_CURRENT_USER, r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\VisualEffects\", \"VisualFXSetting\", 2, winreg.REG_DWORD)\n            try:\n                self._reg_set(winreg.HKEY_CURRENT_USER, r\"Control Panel\\Desktop\", \"UserPreferencesMask\", b'\\x9e\\x3e\\x07\\x80\\x12\\x00\\x00\\x00', winreg.REG_BINARY)\n                self._reg_set(winreg.HKEY_CURRENT_USER, r\"Control Panel\\Desktop\", \"MinAnimate\", \"0\", winreg.REG_SZ)\n            except:\n                pass\n            self._append_log(self.reg_log, \"\u2705 Extreme visual effects disabled (Aero, shadows, animations)\", C[\"success\"])\n        self._append_log(self.reg_log, \"\ud83c\udf89 Tweaks applied! Restart recommended.\", C[\"accent\"])\n\n    # ---------- GROUP POLICY (with confirm) ----------\n    def _build_grouppolicy(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udd12 Group Policy Optimizer\", \"Performance policies\")\n        content = tk.Frame(frame, bg=C[\"bg\"])\n        content.pack(fill=\"both\", expand=True, padx=16, pady=10)\n        content.columnconfigure(0, weight=1)\n        content.columnconfigure(1, weight=2)\n        left = tk.Frame(content, bg=C[\"card\"])\n        left.grid(row=0, column=0, sticky=\"nsew\", padx=(0,6))\n        tk.Label(left, text=\"  Policies\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8,4), padx=8)\n        for k, label in [(\"cortana\",\"Disable Cortana\"), (\"ads\",\"Disable Advertising ID\"), (\"consumer\",\"Disable Consumer Features\"), (\"remote\",\"Disable Remote Assistance\")]:\n            var = tk.BooleanVar(value=True)\n            self.gp_vars[k] = var\n            tk.Checkbutton(left, text=f\"  {label}\", variable=var, font=FONTS[\"body\"], fg=C[\"text\"], bg=C[\"card\"], activebackground=C[\"card\"], selectcolor=C[\"panel\"], bd=0).pack(anchor=\"w\", padx=12, pady=2)\n        profile_options = get_group_policy_profiles()\n        self.gp_profile_hint_var = tk.StringVar(value=profile_options[\"Balanced\"][\"summary\"])\n        tk.Label(left, text=\"Quick presets:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=12, pady=(4, 2))\n        profile_bar = tk.Frame(left, bg=C[\"card\"])\n        profile_bar.pack(fill=\"x\", padx=12, pady=(0, 2))\n        for profile_name in profile_options:\n            self._btn(profile_bar, profile_name, C[\"btn_chip\"], lambda name=profile_name: self._apply_gp_profile(name)).pack(fill=\"x\", pady=1)\n        tk.Label(left, textvariable=self.gp_profile_hint_var, font=FONTS[\"xsmall\"], fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=280, justify=\"left\").pack(anchor=\"w\", padx=12, pady=(0, 8))\n        self._btn(left, \"\u2705 Apply Selected Policies\", C[\"btn\"], self._apply_gp).pack(padx=12, pady=(4, 2), fill=\"x\")\n        self._btn(left, \"\ud83d\udcbe Backup GP\", C[\"btn_chip\"], self._gp_backup).pack(fill=\"x\", padx=12, pady=2)\n        self._btn(left, \"\u267b Restore GP\", C[\"btn_info\"], self._gp_restore).pack(fill=\"x\", padx=12, pady=(2, 10))\n        right = tk.Frame(content, bg=C[\"card\"])\n        right.grid(row=0, column=1, sticky=\"nsew\", padx=(6,0))\n        tk.Label(right, text=\"  Policy Dashboard\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8,4), padx=8)\n        self.gp_progress_var = tk.DoubleVar(value=0.0)\n        self.gp_progress_bar = ttk.Progressbar(right, variable=self.gp_progress_var, maximum=100, mode=\"determinate\")\n        self.gp_progress_bar.pack(fill=\"x\", padx=12, pady=(0,6))\n        self.gp_status_lbl = tk.Label(right, text=\"Ready for group policy optimization\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"])\n        self.gp_status_lbl.pack(anchor=\"w\", padx=12, pady=(0,8))\n        metrics = tk.Frame(right, bg=C[\"card\"])\n        metrics.pack(fill=\"x\", padx=12, pady=(0,6))\n        self.gp_action_count_var = tk.StringVar(value=\"0\")\n        self.gp_policy_score_var = tk.StringVar(value=\"--\")\n        self.gp_restart_risk_var = tk.StringVar(value=\"Low\")\n        for label, var, fg in [\n            (\"Actions\", self.gp_action_count_var, C[\"accent4\"]),\n            (\"Policy Score\", self.gp_policy_score_var, C[\"success\"]),\n            (\"Restart Risk\", self.gp_restart_risk_var, C[\"warning\"]),\n        ]:\n            card = tk.Frame(metrics, bg=C[\"bg\"], padx=8, pady=8)\n            card.pack(side=\"left\", fill=\"x\", expand=True, padx=3)\n            tk.Label(card, text=label, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"]).pack(anchor=\"w\")\n            tk.Label(card, textvariable=var, font=(\"Segoe UI\", 14, \"bold\"), fg=fg, bg=C[\"bg\"]).pack(anchor=\"w\")\n        tk.Label(right, text=\"  Execution Log\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8,4), padx=8)\n        self.gp_log = self._scrolled_text(right, height=16)\n        self.gp_action_log = self.gp_log\n        return frame\n\n    def _gp_backup(self):\n        path = filedialog.asksaveasfilename(defaultextension=\".json\", filetypes=[(\"JSON\",\"*.json\")],\n                                            initialfile=\"gp_backup.json\", title=\"Save GP Backup\")\n        if not path:\n            return\n        try:\n            data = {\n                \"ts\": datetime.datetime.now().isoformat(timespec=\"seconds\"),\n                \"values\": {\n                    \"cortana\": self._reg_get(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Policies\\Microsoft\\Windows\\Windows Search\", \"AllowCortana\"),\n                    \"ads\": self._reg_get(winreg.HKEY_CURRENT_USER, r\"Software\\Microsoft\\Windows\\CurrentVersion\\AdvertisingInfo\", \"Enabled\"),\n                    \"consumer\": self._reg_get(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Policies\\Microsoft\\Windows\\CloudContent\", \"DisableWindowsConsumerFeatures\"),\n                    \"remote\": self._reg_get(winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Control\\Remote Assistance\", \"fAllowToGetHelp\"),\n                },\n                \"gp_vars\": {k: bool(v.get()) for k, v in getattr(self, \"gp_vars\", {}).items()},\n            }\n            with open(path, \"w\", encoding=\"utf-8\") as f:\n                json.dump(data, f, ensure_ascii=False, indent=2, default=str)\n            self._append_log(self.gp_log, f\"\u2705 GP backup saved: {path}\", C[\"success\"])\n            messagebox.showinfo(\"Saved\", f\"\u2705 Backup saved:\\n{path}\")\n        except Exception as e:\n            messagebox.showerror(\"Backup Error\", str(e))\n\n    def _gp_restore(self):\n        path = filedialog.askopenfilename(filetypes=[(\"JSON\",\"*.json\")], title=\"Open GP Backup\")\n        if not path:\n            return\n        if not messagebox.askyesno(\"Restore GP\", \"Backup file se Group Policy values restore karein?\"):\n            return\n        try:\n            with open(path, \"r\", encoding=\"utf-8\") as f:\n                data = json.load(f)\n            vals = (data or {}).get(\"values\", {})\n        except Exception as e:\n            messagebox.showerror(\"Restore Error\", str(e))\n            return\n        results = []\n        try:\n            # Each stored value is tuple: (exists, current, type)\n            def apply_reg(key, hive, reg_path, name, default_val, vtype):\n                triple = vals.get(key)\n                if isinstance(triple, list) and len(triple) == 3:\n                    exists, cur, typ = triple\n                    if exists:\n                        return self._reg_set_checked(hive, reg_path, name, cur, typ, f\"Restore {key}\", self.gp_log)\n                return self._reg_set_checked(hive, reg_path, name, default_val, vtype, f\"Restore {key} default\", self.gp_log)\n            results.append(apply_reg(\"cortana\", winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Policies\\Microsoft\\Windows\\Windows Search\", \"AllowCortana\", 1, winreg.REG_DWORD))\n            results.append(apply_reg(\"ads\", winreg.HKEY_CURRENT_USER, r\"Software\\Microsoft\\Windows\\CurrentVersion\\AdvertisingInfo\", \"Enabled\", 1, winreg.REG_DWORD))\n            results.append(apply_reg(\"consumer\", winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Policies\\Microsoft\\Windows\\CloudContent\", \"DisableWindowsConsumerFeatures\", 0, winreg.REG_DWORD))\n            results.append(apply_reg(\"remote\", winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Control\\Remote Assistance\", \"fAllowToGetHelp\", 1, winreg.REG_DWORD))\n        except Exception as e:\n            self._append_log(self.gp_log, f\"\u26a0 Restore apply failed: {e}\", C[\"warning\"])\n        # Refresh policy\n        out, rc = self._run_cmd(\"gpupdate /force\")\n        results.append({\"state\": \"changed\" if rc == 0 else \"failed\", \"label\": \"Group Policy refresh\", \"error\": out[:300] if rc != 0 else \"\"})\n        summary = self._action_summary(\"GP Restore\", results)\n        self._append_log(self.gp_log, summary[\"message\"], C[\"accent\"])\n        messagebox.showinfo(\"Restore Result\", summary[\"message\"])\n\n    def _apply_gp_profile(self, profile_name):\n        profiles = get_group_policy_profiles()\n        profile = profiles.get(profile_name) or profiles.get(\"Balanced\")\n        for key in self.gp_vars:\n            self.gp_vars[key].set(key in profile[\"keys\"])\n        self.gp_profile_hint_var.set(profile[\"summary\"])\n        self._append_log(self.gp_log, f\"\ud83c\udfaf Group Policy preset applied: {profile_name} \u2014 {profile['summary']}\", C[\"success\"])\n\n    def _apply_gp(self):\n        def before():\n            return \"Group Policy changes will be applied.\"\n        self._confirm_and_launch_job(\"Group Policy Optimizer\", \"Apply selected group policy tweaks?\\nSome may require a restart.\",\n                                      before, \"group_policy_optimize\", self._do_gp)\n\n    def _do_gp_legacy(self):\n        v = self.gp_vars\n        if v[\"cortana\"].get():\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Policies\\Microsoft\\Windows\\Windows Search\", \"AllowCortana\", 0, winreg.REG_DWORD)\n            self._append_log(self.gp_log, \"\u2705 Cortana disabled\", C[\"success\"])\n        if v[\"ads\"].get():\n            self._reg_set(winreg.HKEY_CURRENT_USER, r\"Software\\Microsoft\\Windows\\CurrentVersion\\AdvertisingInfo\", \"Enabled\", 0, winreg.REG_DWORD)\n            self._append_log(self.gp_log, \"\u2705 Ad ID disabled\", C[\"success\"])\n        if v[\"consumer\"].get():\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Policies\\Microsoft\\Windows\\CloudContent\", \"DisableWindowsConsumerFeatures\", 1, winreg.REG_DWORD)\n            self._append_log(self.gp_log, \"\u2705 Consumer features disabled\", C[\"success\"])\n        if v[\"remote\"].get():\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Control\\Remote Assistance\", \"fAllowToGetHelp\", 0, winreg.REG_DWORD)\n            self._append_log(self.gp_log, \"\u2705 Remote Assistance disabled\", C[\"success\"])\n        self._run_cmd(\"gpupdate /force\")\n        self._append_log(self.gp_log, \"\u2705 GP Updated\", C[\"success\"])\n\n    def _do_registry(self):\n        v = self.reg_vars\n        selected_actions = [name for name, var in v.items() if var.get()]\n        total_actions = max(1, len(selected_actions))\n        batch = {\n            \"phase\": \"registry\",\n            \"status_text\": \"Initializing registry optimization...\",\n            \"progress_pct\": 0.0,\n            \"actions_total\": total_actions,\n            \"actions_done\": 0,\n            \"keys_changed\": 0,\n            \"errors\": 0,\n            \"predicted_impact\": min(95, 15 + total_actions * 12),\n            \"confidence_score\": min(98, max(30, 20 + total_actions * 10)),\n        }\n        last_dispatch = time.time()\n\n        def dispatch_metrics():\n            nonlocal last_dispatch\n            try:\n                batch[\"progress_pct\"] = min(100.0, (batch[\"actions_done\"] / batch[\"actions_total\"]) * 100.0)\n                batch[\"status_text\"] = f\"Applying registry tweaks ({batch['actions_done']}/{batch['actions_total']})\"\n                self._registry_gp_metrics_queue.put(batch.copy())\n            except Exception:\n                pass\n            last_dispatch = time.time()\n\n        def track(result):\n            try:\n                batch[\"actions_done\"] += 1\n                if isinstance(result, dict) and result.get(\"state\") == \"changed\":\n                    batch[\"keys_changed\"] += 1\n                if isinstance(result, dict) and result.get(\"state\") == \"failed\":\n                    batch[\"errors\"] += 1\n                if time.time() - last_dispatch &gt;= 0.12:\n                    dispatch_metrics()\n            except Exception:\n                pass\n            return result\n\n        results = []\n        try:\n            if v[\"menu_delay\"].get():\n                results.append(track(self._reg_set_checked(winreg.HKEY_CURRENT_USER, r\"Control Panel\\Desktop\", \"MenuShowDelay\", \"0\", winreg.REG_SZ, \"Menu delay 0ms\", self.reg_log)))\n            if v[\"visual_fx\"].get():\n                results.append(track(self._reg_set_checked(winreg.HKEY_CURRENT_USER, r\"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\VisualEffects\", \"VisualFXSetting\", 2, winreg.REG_DWORD, \"Visual effects disabled\", self.reg_log)))\n            if v[\"search_idx\"].get():\n                results.append(track(self._service_config_checked(\"WSearch\", \"disabled\", \"Search indexing service\", self.reg_log)))\n                results.append(track(self._service_stop_checked(\"WSearch\", \"Search indexing service\", self.reg_log)))\n            if v[\"telemetry\"].get():\n                results.append(track(self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Policies\\Microsoft\\Windows\\DataCollection\", \"AllowTelemetry\", 0, winreg.REG_DWORD, \"Telemetry minimized\", self.reg_log)))\n            if v[\"ntfs_last\"].get():\n                results.append(track(self._fsutil_last_access_checked(self.reg_log)))\n            if v[\"autorun\"].get():\n                results.append(track(self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer\", \"NoDriveTypeAutoRun\", 255, winreg.REG_DWORD, \"Autorun disabled\", self.reg_log)))\n            if v.get(\"shutdown_fast\") and v[\"shutdown_fast\"].get():\n                results.append(track(self._reg_set_checked(winreg.HKEY_CURRENT_USER, r\"Control Panel\\Desktop\", \"AutoEndTasks\", \"1\", winreg.REG_SZ, \"AutoEndTasks enabled\", self.reg_log)))\n                results.append(track(self._reg_set_checked(winreg.HKEY_CURRENT_USER, r\"Control Panel\\Desktop\", \"HungAppTimeout\", \"2000\", winreg.REG_SZ, \"HungAppTimeout 2s\", self.reg_log)))\n                results.append(track(self._reg_set_checked(winreg.HKEY_CURRENT_USER, r\"Control Panel\\Desktop\", \"WaitToKillAppTimeout\", \"2000\", winreg.REG_SZ, \"WaitToKillAppTimeout 2s\", self.reg_log)))\n                results.append(track(self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Control\", \"WaitToKillServiceTimeout\", \"2000\", winreg.REG_SZ, \"WaitToKillServiceTimeout 2s\", self.reg_log)))\n            if v.get(\"extreme_visual\") and v[\"extreme_visual\"].get():\n                results.append(track(self._reg_set_checked(winreg.HKEY_CURRENT_USER, r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\VisualEffects\", \"VisualFXSetting\", 2, winreg.REG_DWORD, \"Extreme visual effects base\", self.reg_log)))\n                results.append(track(self._reg_set_checked(winreg.HKEY_CURRENT_USER, r\"Control Panel\\Desktop\", \"UserPreferencesMask\", b'\\x9e\\x3e\\x07\\x80\\x12\\x00\\x00\\x00', winreg.REG_BINARY, \"Extreme visual effects mask\", self.reg_log)))\n                results.append(track(self._reg_set_checked(winreg.HKEY_CURRENT_USER, r\"Control Panel\\Desktop\", \"MinAnimate\", \"0\", winreg.REG_SZ, \"Window animation off\", self.reg_log)))\n        except Exception as e:\n            self._append_log(self.reg_log, f\"\u26a0 Registry optimization failed: {e}\", C[\"error\"])\n            batch[\"errors\"] += 1\n        dispatch_metrics()\n        try:\n            summary = self._action_summary(\"Registry Tweaks\", results)\n            self._append_log(self.reg_log, summary[\"message\"], C[\"accent\"])\n        except Exception as e:\n            self._append_log(self.reg_log, f\"\u26a0 Registry summary failed: {e}\", C[\"error\"])\n            summary = {\"message\": \"Registry completed with issues.\"}\n        batch[\"status_text\"] = \"Registry optimization complete\"\n        batch[\"progress_pct\"] = 100.0\n        batch[\"confidence_score\"] = min(100, batch[\"confidence_score\"] + (batch[\"actions_done\"] * 2))\n        self._registry_gp_metrics_queue.put(batch.copy())\n        return summary\n\n    def _do_gp(self):\n        v = self.gp_vars\n        selected_actions = [name for name, var in v.items() if var.get()]\n        total_actions = max(1, len(selected_actions))\n        batch = {\n            \"phase\": \"grouppolicy\",\n            \"status_text\": \"Initializing group policy optimizer...\",\n            \"progress_pct\": 0.0,\n            \"actions_total\": total_actions,\n            \"actions_done\": 0,\n            \"policy_score\": min(90, 10 + total_actions * 18),\n            \"restart_risk\": \"Low\",\n            \"errors\": 0,\n        }\n        last_dispatch = time.time()\n\n        def dispatch_metrics():\n            nonlocal last_dispatch\n            try:\n                batch[\"progress_pct\"] = min(100.0, (batch[\"actions_done\"] / batch[\"actions_total\"]) * 100.0)\n                batch[\"status_text\"] = f\"Applying group policy ({batch['actions_done']}/{batch['actions_total']})\"\n                self._registry_gp_metrics_queue.put(batch.copy())\n            except Exception:\n                pass\n            last_dispatch = time.time()\n\n        def track(result):\n            try:\n                batch[\"actions_done\"] += 1\n                if isinstance(result, dict) and result.get(\"state\") == \"changed\":\n                    batch[\"policy_score\"] = min(100, batch[\"policy_score\"] + 8)\n                if isinstance(result, dict) and result.get(\"state\") == \"failed\":\n                    batch[\"errors\"] += 1\n                    batch[\"restart_risk\"] = \"Medium\"\n                if time.time() - last_dispatch &gt;= 0.12:\n                    dispatch_metrics()\n            except Exception:\n                pass\n            return result\n\n        results = []\n        try:\n            if v[\"cortana\"].get():\n                results.append(track(self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Policies\\Microsoft\\Windows\\Windows Search\", \"AllowCortana\", 0, winreg.REG_DWORD, \"Cortana disabled\", self.gp_log)))\n            if v[\"ads\"].get():\n                results.append(track(self._reg_set_checked(winreg.HKEY_CURRENT_USER, r\"Software\\Microsoft\\Windows\\CurrentVersion\\AdvertisingInfo\", \"Enabled\", 0, winreg.REG_DWORD, \"Advertising ID disabled\", self.gp_log)))\n            if v[\"consumer\"].get():\n                results.append(track(self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Policies\\Microsoft\\Windows\\CloudContent\", \"DisableWindowsConsumerFeatures\", 1, winreg.REG_DWORD, \"Consumer features disabled\", self.gp_log)))\n            if v[\"remote\"].get():\n                results.append(track(self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Control\\Remote Assistance\", \"fAllowToGetHelp\", 0, winreg.REG_DWORD, \"Remote Assistance disabled\", self.gp_log)))\n            if any(r.get(\"state\") == \"changed\" for r in results):\n                out, rc = self._run_cmd(\"gpupdate /force\")\n                results.append(track({\"state\": \"changed\" if rc == 0 else \"failed\", \"label\": \"Group Policy refresh\", \"error\": out[:300] if rc != 0 else \"\"}))\n                self._append_log(self.gp_log, \"GP Updated\" if rc == 0 else f\"GP update failed: {out[:120]}\", C[\"success\"] if rc == 0 else C[\"error\"])\n                if rc != 0:\n                    batch[\"restart_risk\"] = \"High\"\n            else:\n                self._append_log(self.gp_log, \"Already done: GP update skipped\", C[\"warning\"])\n        except Exception as e:\n            self._append_log(self.gp_log, f\"\u26a0 Group Policy optimization failed: {e}\", C[\"error\"])\n            batch[\"errors\"] += 1\n            batch[\"restart_risk\"] = \"Medium\"\n        dispatch_metrics()\n        try:\n            summary = self._action_summary(\"Group Policy\", results)\n            self._append_log(self.gp_log, summary[\"message\"], C[\"accent\"])\n        except Exception as e:\n            self._append_log(self.gp_log, f\"\u26a0 Group Policy summary failed: {e}\", C[\"error\"])\n            summary = {\"message\": \"Group Policy completed with issues.\"}\n        batch[\"status_text\"] = \"Group Policy optimizer complete\"\n        batch[\"progress_pct\"] = 100.0\n        self._registry_gp_metrics_queue.put(batch.copy())\n        return summary\n\n    # ---------- NETWORK OPTIMIZER (with confirm) ----------\n    def _build_network(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"Network Optimizer\", \"TCP/IP, DNS, cache and bandwidth repair\")\n        self.network_health_status = tk.Label(\n            frame,\n            text=\"Connectivity status: idle\",\n            font=FONTS[\"small\"],\n            fg=C[\"text_dim\"],\n            bg=C[\"bg\"],\n            anchor=\"w\",\n        )\n        self.network_health_status.pack(fill=\"x\", padx=16, pady=(0, 4))\n        body = self._scrollable_section_body(frame)\n        self._action_card_grid(body, [\n            (\"TCP\", \"TCP Optimizations\",          \"TCP/IP tweaks apply karo\",            C[\"btn_info\"],   self._apply_tcp),\n            (\"DNS\", \"Flush DNS\",                  \"DNS cache saaf karo\",                 C[\"btn\"],        self._flush_dns),\n            (\"RST\", \"Reset TCP/IP\",               \"TCP/IP stack reset karo\",             C[\"btn_warn\"],   self._reset_tcpip),\n            (\"CLR\", \"Browser/Office Cache Clear\", \"Browser aur Office cache delete karo\",C[\"btn_danger\"], self._browser_office_cache_clear),\n            (\"NET\", \"Disable Net Throttling\",     \"Network speed limit hatao\",           C[\"btn_chip\"],   self._disable_network_throttling),\n            (\"P2P\", \"Disable Delivery Optim.\",    \"Windows Update bandwidth free karo\",  C[\"btn_warn\"],   self._disable_delivery_optimization),\n            (\"DNS+\", \"Optimize DNS\",              \"Cloudflare + Google DNS lagao\",       C[\"btn_info\"],   self._optimize_dns),\n            (\"ADPT\", \"Adapter-wise DNS\",          \"WiFi / Ethernet DNS alag set karo\",   C[\"btn_info\"],   self._dns_by_adapter_dialog),\n            (\"PING\", \"Ping Internet\",             \"Ping Cloudflare for latency\",        C[\"btn_chip\"],   self._network_ping_test),\n            (\"CHK\", \"Connectivity Audit\",         \"Ping + adapter summary report\",       C[\"btn_chip\"],   self._run_network_health_check),\n            (\"SPD\", \"Speedtest Hook\",             \"Run configured speedtest command\",   C[\"btn_info\"],   self._run_speedtest_hook),\n            (\"SAV\", \"Save Last Audit\",            \"Save latest audit as text\",           C[\"btn\"],        self._export_last_network_audit),\n            (\"RPT\", \"Export Net Report\",          \"Save network config + route report\",  C[\"btn\"],        self._export_network_report),\n        ], cols=4)\n        content = tk.Frame(body, bg=C[\"card\"])\n        content.pack(fill=\"both\", expand=True, padx=16, pady=(8, 12))\n        tk.Label(content, text=\"  Network log\", font=FONTS[\"subhead\"],\n                 fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8, 4), padx=8)\n        self.network_log = self._scrolled_text(content, height=14)\n        return frame\n\n    def _dns_by_adapter_dialog(self):\n        # Best-effort: list adapters and ask for adapter name\n        out, rc = self._run_cmd('powershell -Command \"Get-NetAdapter | Where-Object {$_.Status -eq \\'Up\\'} | Select-Object -ExpandProperty Name\"', timeout=10)\n        adapters = [a.strip() for a in out.splitlines() if a.strip()] if rc == 0 else []\n        if not adapters:\n            messagebox.showwarning(\"Adapters\", \"No active adapters found (or PowerShell blocked).\")\n            return\n        try:\n            import tkinter.simpledialog as simpledialog\n            choice = simpledialog.askstring(\"Adapter Name\",\n                                            \"Active adapters:\\n\" + \"\\n\".join(adapters[:10]) +\n                                            (\"\\n...\" if len(adapters) &gt; 10 else \"\") +\n                                            \"\\n\\nType exact adapter name (Wi-Fi/Ethernet):\")\n        except Exception:\n            choice = None\n        if not choice:\n            return\n        adapter = choice.strip()\n        if not adapter:\n            return\n        if not messagebox.askyesno(\"Set DNS\",\n                                   f\"Adapter: {adapter}\\nDNS: 1.1.1.1 + 8.8.8.8\\n\\nApply?\"):\n            return\n        # Use PowerShell for reliable adapter name handling\n        cmd = (\n            'powershell -Command \"'\n            f'Set-DnsClientServerAddress -InterfaceAlias \\'{adapter}\\' -ServerAddresses (\\'1.1.1.1\\',\\'8.8.8.8\\')\"'\n        )\n        out2, rc2 = self._run_cmd(cmd, timeout=20)\n        if rc2 == 0:\n            self._append_log(self.network_log, f\"\u2705 DNS applied on '{adapter}'\", C[\"success\"])\n        else:\n            self._append_log(self.network_log, f\"\u274c DNS set failed: {out2[:200]}\", C[\"error\"])\n\n    def _run_speedtest_hook(self):\n        \"\"\"\n        Optional hook: set env var GODAWARI_SPEEDTEST_CMD to a command that prints results.\n        Example: setx GODAWARI_SPEEDTEST_CMD \"speedtest --accept-license --accept-gdpr\"\n        \"\"\"\n        cmd = os.environ.get(\"GODAWARI_SPEEDTEST_CMD\", \"\").strip()\n        if not cmd:\n            messagebox.showinfo(\"Speedtest Hook\",\n                                \"Speedtest hook set nahi hai.\\n\\n\"\n                                \"Env var set karo:\\n\"\n                                \"GODAWARI_SPEEDTEST_CMD = \\n\\n\"\n                                \"Example:\\n\"\n                                \"speedtest --accept-license --accept-gdpr\")\n            return\n        self._append_log(self.network_log, f\"\u23f1 Speedtest running: {cmd}\", C[\"accent4\"])\n        out, rc = self._run_cmd(cmd, timeout=120)\n        if rc == 0:\n            self._append_log(self.network_log, out[:1200] if out else \"\u2705 Speedtest done\", C[\"success\"])\n        else:\n            self._append_log(self.network_log, f\"\u274c Speedtest failed (rc={rc}): {out[:300]}\", C[\"error\"])\n\n    def _apply_tcp(self):\n        if messagebox.askyesno(\"TCP Optimizations\", \"Apply TCP tuning for better network performance?\"):\n            for cmd in ['netsh int tcp set global autotuninglevel=normal', 'netsh int tcp set global rss=enabled']:\n                self._run_cmd(cmd)\n            self._append_log(self.network_log, \"\u2705 TCP optimizations applied\", C[\"success\"])\n\n    def _flush_dns(self):\n        if messagebox.askyesno(\"Flush DNS\", \"Flush DNS cache? This can resolve connectivity issues.\"):\n            self._run_cmd('ipconfig /flushdns')\n            self._append_log(self.network_log, \"\u2705 DNS flushed\", C[\"success\"])\n\n    def _reset_tcpip(self):\n        if messagebox.askyesno(\"Reset TCP/IP\", \"This will reset Winsock and TCP/IP stack. A restart will be needed.\"):\n            self._run_cmd('netsh int ip reset')\n            self._append_log(self.network_log, \"\u2705 TCP/IP reset. Restart required.\", C[\"warning\"])\n\n    def _browser_office_cache_clear(self):\n        if messagebox.askyesno(\"Clear Browser/Office Cache\", \"Clear caches for Chrome, Edge, and Office?\\nBrowsers will be closed.\"):\n            self._launch_job(\"browser_clear\", self._do_browser_clear)\n\n    def _do_browser_clear(self):\n        for exe in [\"chrome\",\"msedge\",\"firefox\"]:\n            self._run_cmd(f'taskkill /IM {exe}.exe /F')\n        total = 0\n        local = os.environ.get(\"LOCALAPPDATA\",\"\")\n        for p in [os.path.join(local,\"Google\\\\Chrome\\\\User Data\\\\Default\\\\Cache\"),\n                  os.path.join(local,\"Microsoft\\\\Edge\\\\User Data\\\\Default\\\\Cache\"),\n                  os.path.join(local,\"Microsoft\\\\Office\\\\16.0\\\\OfficeFileCache\")]:\n            if os.path.exists(p):\n                total += self._delete_folder_contents(p)\n        self._append_log(self.network_log, f\"\u2705 Cleared {self._fmt_size(total)} cache\", C[\"success\"])\n\n    def _disable_network_throttling(self):\n        if messagebox.askyesno(\"Disable Network Throttling\", \"This can improve network throughput for multimedia apps.\"):\n            result = self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Multimedia\\SystemProfile\", \"NetworkThrottlingIndex\", 0xffffffff, winreg.REG_DWORD, \"Network throttling disabled\", self.network_log)\n            if result[\"state\"] == \"already\":\n                messagebox.showinfo(\"Already Done\", \"Network throttling already disabled.\")\n\n    def _disable_delivery_optimization(self):\n        if messagebox.askyesno(\"Disable Delivery Optimization\", \"Disable Windows Update P2P sharing? Saves bandwidth.\"):\n            results = [\n                self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\DeliveryOptimization\\Config\", \"DODownloadMode\", 0, winreg.REG_DWORD, \"Delivery Optimization P2P off\", self.network_log),\n                self._service_stop_checked(\"DoSvc\", \"Delivery Optimization service\", self.network_log),\n                self._service_config_checked(\"DoSvc\", \"disabled\", \"Delivery Optimization service\", self.network_log),\n            ]\n            summary = self._action_summary(\"Delivery Optimization\", results)\n            if summary[\"already_done\"]:\n                messagebox.showinfo(\"Already Done\", \"Delivery Optimization already disabled.\")\n\n    def _network_ping_test(self):\n        if not messagebox.askyesno(\"Ping Test\", \"Ping 1.1.1.1 and 8.8.8.8 to check internet latency?\"):\n            return\n        targets = [\"1.1.1.1\", \"8.8.8.8\"]\n        for target in targets:\n            out, rc = self._run_cmd(f\"ping -n 4 {target}\", timeout=20)\n            if rc == 0:\n                self._append_log(self.network_log, f\"\u2705 Ping {target} OK:\\n{out.strip()[:400]}\", C[\"success\"])\n            else:\n                self._append_log(self.network_log, f\"\u274c Ping {target} failed (rc={rc}): {out.strip()[:400]}\", C[\"error\"])\n        self._set_status(\"Ping test complete\", C[\"success\"])\n\n    def _export_network_report(self):\n        path = filedialog.asksaveasfilename(defaultextension=\".txt\",\n                                            filetypes=[(\"Text files\",\"*.txt\")],\n                                            initialfile=\"Network_Report.txt\",\n                                            title=\"Save Network Report\")\n        if not path:\n            return\n        report = []\n        for cmd, label in [\n            (\"ipconfig /all\", \"IP Configuration\"),\n            (\"route print\", \"Route Table\"),\n            (\"netsh interface ipv4 show config\", \"IPv4 Adapter Config\"),\n            (\"netsh interface ipv6 show config\", \"IPv6 Adapter Config\"),\n            (\"netsh interface show interface\", \"Interface Status\"),\n        ]:\n            out, rc = self._run_cmd(cmd, timeout=30)\n            report.append(f\"=== {label} ===\\n\")\n            report.append(out if out else f\"[command failed rc={rc}]\\n\")\n        try:\n            with open(path, \"w\", encoding=\"utf-8\") as f:\n                f.write(\"\\n\".join(report))\n            messagebox.showinfo(\"Saved\", f\"Network report saved to:\\n{path}\")\n            self._append_log(self.network_log, f\"\ud83d\udcbe Network report saved: {path}\", C[\"success\"])\n        except Exception as e:\n            messagebox.showerror(\"Error\", str(e))\n            self._append_log(self.network_log, f\"\u274c Report save failed: {e}\", C[\"error\"])\n\n    def _run_network_health_check(self):\n        if not messagebox.askyesno(\"Connectivity Audit\", \"Run a quick ping + adapter audit now?\"):\n            return\n        self.network_health_status.config(text=\"Connectivity status: running audit\", fg=C[\"accent4\"])\n        self._append_log(self.network_log, \"\ud83d\udd0d Running connectivity audit...\", C[\"accent4\"])\n\n        ping_out, ping_rc = self._run_cmd(\"ping -n 2 1.1.1.1\", timeout=20)\n        ip_out, ip_rc = self._run_cmd(\"ipconfig /all\", timeout=20)\n        route_out, route_rc = self._run_cmd(\"route print\", timeout=20)\n\n        summary_lines = [\n            f\"Ping 1.1.1.1: {'OK' if ping_rc == 0 else 'FAIL'}\",\n            f\"ipconfig /all: {'OK' if ip_rc == 0 else 'FAIL'}\",\n            f\"route print: {'OK' if route_rc == 0 else 'FAIL'}\",\n        ]\n        if ping_rc == 0:\n            self._append_log(self.network_log, f\"\u2705 Ping check passed\\n{ping_out[:300]}\", C[\"success\"])\n        else:\n            self._append_log(self.network_log, f\"\u274c Ping check failed\\n{ping_out[:300]}\", C[\"error\"])\n\n        adapter_lines = [line for line in ip_out.splitlines() if \"DNS Servers\" in line or \"IPv4 Address\" in line or \"Description\" in line or \"Physical Address\" in line]\n        if adapter_lines:\n            self._append_log(self.network_log, \"\ud83d\udce1 Adapter summary:\\n\" + \"\\n\".join(adapter_lines[:20]), C[\"text\"])\n        else:\n            self._append_log(self.network_log, \"\ud83d\udce1 No adapter details captured from ipconfig output.\", C[\"warning\"])\n\n        self._append_log(self.network_log, \"\ud83d\udee3 Route summary:\\n\" + (route_out[:700] if route_out else \"route print unavailable\"), C[\"text\"])\n        self._append_log(self.network_log, \"\u2705 Connectivity audit complete. \" + \" | \".join(summary_lines), C[\"success\"])\n\n        self._last_network_audit = {\n            \"timestamp\": datetime.datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\"),\n            \"ping_rc\": ping_rc,\n            \"ip_rc\": ip_rc,\n            \"route_rc\": route_rc,\n            \"ping_output\": ping_out,\n            \"ip_output\": ip_out,\n            \"route_output\": route_out,\n        }\n        self.network_health_status.config(\n            text=f\"Connectivity status: audit complete at {self._last_network_audit['timestamp']}\",\n            fg=C[\"success\"],\n        )\n        self._set_status(\"Connectivity audit complete\", C[\"success\"])\n\n    def _export_last_network_audit(self):\n        audit = getattr(self, \"_last_network_audit\", None)\n        if not audit:\n            messagebox.showinfo(\"No Audit\", \"Pehle Connectivity Audit run karo.\")\n            return\n        path = filedialog.asksaveasfilename(\n            defaultextension=\".txt\",\n            filetypes=[(\"Text files\", \"*.txt\")],\n            initialfile=f\"Network_Audit_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.txt\",\n            title=\"Save Last Network Audit\",\n        )\n        if not path:\n            return\n        try:\n            lines = [\n                f\"Godawari Network Audit\",\n                f\"Timestamp: {audit['timestamp']}\",\n                f\"Ping rc: {audit['ping_rc']}\",\n                f\"ipconfig rc: {audit['ip_rc']}\",\n                f\"route print rc: {audit['route_rc']}\",\n                \"\",\n                \"--- Ping Output ---\",\n                audit.get(\"ping_output\", \"\"),\n                \"\",\n                \"--- ipconfig Output ---\",\n                audit.get(\"ip_output\", \"\"),\n                \"\",\n                \"--- route print Output ---\",\n                audit.get(\"route_output\", \"\"),\n            ]\n            with open(path, \"w\", encoding=\"utf-8\") as fh:\n                fh.write(\"\\n\".join(lines))\n            self._append_log(self.network_log, f\"\ud83d\udcbe Saved last audit: {path}\", C[\"success\"])\n            messagebox.showinfo(\"Saved\", f\"Last network audit saved to:\\n{path}\")\n        except Exception as e:\n            messagebox.showerror(\"Save Failed\", str(e))\n            self._append_log(self.network_log, f\"\u274c Failed to save audit: {e}\", C[\"error\"])\n\n    def _optimize_dns(self):\n        if messagebox.askyesno(\"Optimize DNS\", \"Set DNS to Cloudflare (1.1.1.1) and Google (8.8.8.8) for faster browsing?\"):\n            out, _ = self._run_cmd('wmic nic where \"NetEnabled=True\" get Index /format:csv')\n            lines = out.splitlines()\n            for line in lines[1:]:\n                if line.strip():\n                    idx = line.split(',')[1].strip()\n                    self._run_cmd(f'netsh interface ip set dns name={idx} static 1.1.1.1 primary')\n                    self._run_cmd(f'netsh interface ip add dns name={idx} 8.8.8.8 index=2')\n            self._append_log(self.network_log, \"\u2705 DNS set to Cloudflare (1.1.1.1) and Google (8.8.8.8)\", C[\"success\"])\n\n    # ---------- TROUBLESHOOTER &amp; POWER PLAN (shortened for length) ----------\n    # I'll include the essential parts. The rest methods are similar structure.\n\n    def _build_troubleshooter(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"System Repair\", \"Guided SFC, DISM, network, crash and driver diagnostics\")\n        body = self._scrollable_section_body(frame)\n\n        guide = tk.Frame(body, bg=C[\"card\"], highlightbackground=C[\"accent2\"], highlightthickness=1)\n        guide.pack(fill=\"x\", padx=16, pady=(10, 6))\n        tk.Label(guide, text=\"Recommended flow\", font=FONTS[\"subhead\"],\n                 fg=C[\"accent2\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=12, pady=(8, 2))\n        tk.Label(\n            guide,\n            text=\"Start with Repair Verification or Network Reset. Use advanced crash, boot, driver and security reports when the basic repair does not explain the issue.\",\n            font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], anchor=\"w\",\n            justify=\"left\", wraplength=self._dpi_px(980)\n        ).pack(fill=\"x\", padx=12, pady=(0, 8))\n\n        self._action_card_grid(body, [\n            (\"NET\", \"Network Reset\",            \"TCP/IP, Winsock and DNS reset\",       C[\"btn_info\"],   self._full_network_reset),\n            (\"SFC\", \"SFC /SCANNOW\",             \"System files scan and repair\",        C[\"btn\"],        self._run_sfc),\n            (\"DISM\", \"DISM RestoreHealth\",      \"Windows image repair\",                C[\"btn_warn\"],   self._run_dism),\n            (\"ALL\", \"Run All Repairs\",          \"Restore point, DISM, SFC and network\",C[\"accent4\"],    self._run_all_repairs),\n            (\"BSOD\", \"BSoD Deep Diagnose\",      \"Stop code, WHEA, driver and dump check\", C[\"accent3\"], self._bsod_deep_diagnose),\n            (\"DMP\", \"Enable Minidump\",          \"Capture future crash proof logs\",     C[\"btn_chip\"],   self._enable_bsod_minidump),\n            (\"DLL\", \"Kernel32/Rundll32 Check\",  \"WER, startup and DLL crash diagnose\", C[\"btn_info\"],   self._rundll32_error_diagnose),\n            (\"DBG\", \"WinDbg Dump Analyze\",      \"Minidump !analyze automation\",        C[\"accent4\"],    self._windbg_dump_analyze),\n            (\"EVT\", \"Event Correlation\",        \"Crash timeline root-cause summary\",   C[\"btn\"],        self._event_correlation_report),\n            (\"DRV\", \"Driver Diagnostics\",       \"Unsigned, recent and outdated drivers\", C[\"btn_warn\"], self._driver_diagnostics_report),\n            (\"HW\", \"Hardware Health\",           \"SMART, NVMe and RAM warning report\",  C[\"hw_accent\"],  self._hardware_health_report),\n            (\"CHK\", \"Repair Verification\",      \"SFC, DISM and event re-check report\", C[\"accent2\"],    self._repair_verification_report),\n            (\"BOOT\", \"Boot Status + BCD\",       \"EFI/BCD analysis and backup\",         C[\"btn_chip\"],   self._boot_status_bcd_backup),\n            (\"OFF\", \"Offline SFC/DISM\",         \"Mounted Windows repair commands\",     C[\"btn_info\"],   self._offline_repair_dialog),\n            (\"SEC\", \"Security Autoruns\",        \"AppInit, hosts and startup risk scan\", C[\"btn_warn\"],  self._security_startup_report),\n            (\"ZIP\", \"Diagnostic ZIP\",           \"HTML, JSON and TXT package export\",   C[\"accent\"],     self._diagnostic_zip_package),\n            (\"WU\", \"Disable Windows Update\",    \"Advanced blocker with warning\",       C[\"btn_danger\"], self._disable_windows_update),\n            (\"STOP\", \"Stop Repair\",             \"Stop the running repair command\",     C[\"btn_danger\"], self._stop_repairs),\n            (\"SAVE\", \"Export Repair Report\",    \"Save the current repair log\",         C[\"btn_chip\"],   self._export_repair_report),\n        ], cols=4)\n\n        content = tk.Frame(body, bg=C[\"card\"])\n        content.pack(fill=\"both\", expand=True, padx=16, pady=(8, 12))\n        tk.Label(content, text=\"  Live repair log\", font=FONTS[\"subhead\"],\n                 fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8, 4), padx=8)\n        self.trouble_log = self._scrolled_text(content, height=12)\n        return frame\n\n    def _stop_repairs(self):\n        self._repair_stop_flag = True\n        try:\n            p = getattr(self, \"_repair_proc\", None)\n            if p and p.poll() is None:\n                try:\n                    p.terminate()\n                except Exception:\n                    pass\n        except Exception:\n            pass\n        self._append_log(self.trouble_log, \"\u23f9 Stop requested for running repair command.\", C[\"warning\"])\n        self._set_status(\"Stop requested...\", C[\"warning\"])\n\n    def _export_repair_report(self):\n        path = filedialog.asksaveasfilename(defaultextension=\".txt\", filetypes=[(\"Text\",\"*.txt\")],\n                                            initialfile=\"SystemRepair_Report.txt\",\n                                            title=\"Save Repair Report\")\n        if not path:\n            return\n        try:\n            txt = \"\"\n            try:\n                txt = self.trouble_log.get(\"1.0\", \"end\")\n            except Exception:\n                txt = \"\"\n            with open(path, \"w\", encoding=\"utf-8\") as f:\n                f.write(txt)\n            messagebox.showinfo(\"Saved\", f\"\u2705 Report saved:\\n{path}\")\n        except Exception as e:\n            messagebox.showerror(\"Error\", str(e))\n\n    def _full_network_reset(self):\n        if messagebox.askyesno(\"Network Reset\", \"Reset Winsock and TCP/IP? Restart required.\"):\n            for cmd in ([\"netsh\", \"winsock\", \"reset\"], [\"netsh\", \"int\", \"ip\", \"reset\"], [\"ipconfig\", \"/flushdns\"]):\n                self._run_cmd(cmd)\n            self._append_log(self.trouble_log, \"\u2705 Network reset complete. Restart.\", C[\"success\"])\n\n    def _run_sfc(self):\n        if messagebox.askyesno(\"System File Checker\", \"Run SFC /SCANNOW? This may take a while.\"):\n            self._append_log(self.trouble_log, \"Running SFC...\", C[\"accent\"])\n            self._launch_job(\"sfc_scan\", self._run_cmd_cancelable, [\"sfc\", \"/scannow\"], 1200)\n\n    def _run_dism(self):\n        if messagebox.askyesno(\"DISM\", \"Run DISM RestoreHealth? This may take a while.\"):\n            self._append_log(self.trouble_log, \"Running DISM...\", C[\"accent\"])\n            self._launch_job(\"dism_restorehealth\", self._run_cmd_cancelable, [\"dism\", \"/online\", \"/cleanup-image\", \"/restorehealth\"], 2400)\n\n    def _run_cmd_cancelable(self, cmd, timeout_s=1800):\n        self._repair_stop_flag = False\n        try:\n            self._repair_proc = subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True,\n                                                 encoding=\"utf-8\", errors=\"replace\")\n            start = time.time()\n            out_lines = []\n            for line in self._repair_proc.stdout:\n                out_lines.append(line.rstrip(\"\\n\"))\n                if len(out_lines) % 25 == 0:\n                    tail = \"\\n\".join(out_lines[-10:])\n                    self.after(0, lambda t=tail: self._append_log(self.trouble_log, t, C[\"text_dim\"]))\n                if getattr(self, \"_repair_stop_flag\", False):\n                    try:\n                        self._repair_proc.terminate()\n                    except Exception:\n                        pass\n                    break\n                if timeout_s and (time.time() - start) &gt; timeout_s:\n                    try:\n                        self._repair_proc.terminate()\n                    except Exception:\n                        pass\n                    break\n            try:\n                rc = self._repair_proc.wait(timeout=5)\n            except Exception:\n                rc = -1\n            tail = \"\\n\".join(out_lines[-30:]) if out_lines else \"\"\n            if getattr(self, \"_repair_stop_flag\", False):\n                self.after(0, lambda: self._append_log(self.trouble_log, \"\u23f9 Repair stopped by user.\", C[\"warning\"]))\n                self.after(0, lambda: self._set_status(\"Repair stopped\", C[\"warning\"]))\n            elif timeout_s and (time.time() - start) &gt; timeout_s:\n                self.after(0, lambda: self._append_log(self.trouble_log, \"\u26a0 Repair timed out.\", C[\"warning\"]))\n                self.after(0, lambda: self._set_status(\"Repair timed out\", C[\"warning\"]))\n            else:\n                self.after(0, lambda: self._append_log(self.trouble_log, f\"\u2705 Command done (rc={rc}).\", C[\"success\"]))\n                if tail:\n                    self.after(0, lambda t=tail: self._append_log(self.trouble_log, t, C[\"text\"]))\n                self.after(0, lambda: self._set_status(\"Repair complete\", C[\"success\"]))\n        except Exception as e:\n            self.after(0, lambda: self._append_log(self.trouble_log, f\"\u274c Repair failed: {e}\", C[\"error\"]))\n        finally:\n            self._repair_proc = None\n\n    def _run_all_repairs(self):\n        if self._create_restore_point(\"Full Repair\"):\n            self._launch_job(\"full_repairs\", lambda: (self._run_dism(), self._run_sfc(), self._full_network_reset()))\n\n    def _disable_windows_update_legacy(self):\n        if messagebox.askyesno(\"Windows Update Blocker\", \"Disable Windows Update services? (Not recommended for security, but boosts performance)\"):\n            self._run_cmd('sc config \"wuauserv\" start= disabled')\n            self._run_cmd('sc stop \"wuauserv\"')\n            self._run_cmd('sc config \"UsoSvc\" start= disabled')\n            self._run_cmd('sc stop \"UsoSvc\"')\n            self._append_log(self.trouble_log, \"\u26a0\ufe0f Windows Update services disabled (Reboot required)\", C[\"warning\"])\n\n    def _disable_windows_update(self):\n        if messagebox.askyesno(\"Windows Update Blocker\", \"Disable Windows Update services? (Not recommended for security, but boosts performance)\"):\n            results = [\n                self._service_config_checked(\"wuauserv\", \"disabled\", \"Windows Update\", self.trouble_log),\n                self._service_stop_checked(\"wuauserv\", \"Windows Update\", self.trouble_log),\n                self._service_config_checked(\"UsoSvc\", \"disabled\", \"Update Orchestrator\", self.trouble_log),\n                self._service_stop_checked(\"UsoSvc\", \"Update Orchestrator\", self.trouble_log),\n            ]\n            summary = self._action_summary(\"Windows Update Blocker\", results)\n            self._append_log(self.trouble_log, summary[\"message\"], C[\"warning\"] if summary[\"already_done\"] else C[\"success\"])\n            messagebox.showinfo(\"Already Done\" if summary[\"already_done\"] else \"Done\", summary[\"message\"])\n\n    def _json_items_from_output(self, output):\n        raw = (output or \"\").strip()\n        if not raw:\n            return []\n        starts = [i for i in (raw.find(\"[\"), raw.find(\"{\")) if i &gt;= 0]\n        if starts:\n            raw = raw[min(starts):]\n        ends = [i for i in (raw.rfind(\"]\"), raw.rfind(\"}\")) if i &gt;= 0]\n        if ends:\n            raw = raw[:max(ends) + 1]\n        try:\n            data = json.loads(raw)\n            if isinstance(data, list):\n                return data\n            if isinstance(data, dict):\n                return [data]\n        except Exception:\n            pass\n        return []\n\n    def _crash_control_values(self):\n        names = [\n            \"CrashDumpEnabled\", \"MinidumpDir\", \"DumpFile\", \"LogEvent\",\n            \"AutoReboot\", \"Overwrite\", \"AlwaysKeepMemoryDump\",\n        ]\n        values = {}\n        for name in names:\n            exists, value, _ = self._reg_get(\n                winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\CrashControl\",\n                name\n            )\n            if exists:\n                values[name] = value\n        return values\n\n    def _bsod_dump_files(self):\n        files = []\n        targets = [\n            (r\"C:\\Windows\\Minidump\", \"*.dmp\", False),\n            (r\"C:\\Windows\\LiveKernelReports\", \"*.dmp\", True),\n        ]\n        for folder, pattern, recursive in targets:\n            try:\n                base = Path(folder)\n                if not base.exists():\n                    continue\n                iterator = base.rglob(pattern) if recursive else base.glob(pattern)\n                for path in iterator:\n                    try:\n                        st = path.stat()\n                        files.append({\n                            \"path\": str(path),\n                            \"name\": path.name,\n                            \"size_kb\": int(st.st_size / 1024),\n                            \"mtime\": datetime.datetime.fromtimestamp(st.st_mtime).strftime(\"%Y-%m-%d %H:%M\"),\n                        })\n                    except Exception:\n                        pass\n            except Exception:\n                pass\n        try:\n            memory_dump = Path(r\"C:\\Windows\\MEMORY.DMP\")\n            if memory_dump.exists():\n                st = memory_dump.stat()\n                files.append({\n                    \"path\": str(memory_dump),\n                    \"name\": memory_dump.name,\n                    \"size_kb\": int(st.st_size / 1024),\n                    \"mtime\": datetime.datetime.fromtimestamp(st.st_mtime).strftime(\"%Y-%m-%d %H:%M\"),\n                })\n        except Exception:\n            pass\n        files.sort(key=lambda item: item.get(\"mtime\", \"\"), reverse=True)\n        return files[:12]\n\n    def _bsod_stop_code_details(self, code):\n        try:\n            number = int(str(code).strip(), 16)\n            key = f\"0x{number:08X}\"\n        except Exception:\n            key = str(code).upper()\n        stop_map = {\n            \"0x0000000A\": (\"IRQL_NOT_LESS_OR_EQUAL\", \"Driver ne galat memory address access kiya.\", \"Recent driver rollback/update karo, RAM test chalao, overclock off rakho.\"),\n            \"0x0000001A\": (\"MEMORY_MANAGEMENT\", \"RAM, pagefile, driver memory leak ya memory corruption.\", \"Windows Memory Diagnostic/MemTest run karo, RAM reseat karo, SFC/DISM run karo.\"),\n            \"0x00000024\": (\"NTFS_FILE_SYSTEM\", \"File system, disk, bad sector ya storage driver issue.\", \"Important data backup karo, SMART check aur chkdsk /f /r run karo.\"),\n            \"0x0000003B\": (\"SYSTEM_SERVICE_EXCEPTION\", \"Driver/system service crash, aksar graphics/security software se.\", \"GPU/network/security driver clean reinstall karo, Windows update complete karo.\"),\n            \"0x00000050\": (\"PAGE_FAULT_IN_NONPAGED_AREA\", \"Bad RAM, bad driver, antivirus filter, ya disk/pagefile issue.\", \"RAM test, driver verifier status check, antivirus/storage driver update karo.\"),\n            \"0x0000007B\": (\"INACCESSIBLE_BOOT_DEVICE\", \"Windows boot disk/controller access nahi kar pa raha.\", \"BIOS SATA mode, storage driver, boot files, chkdsk aur startup repair check karo.\"),\n            \"0x0000007E\": (\"SYSTEM_THREAD_EXCEPTION_NOT_HANDLED\", \"Kernel driver exception handle nahi hui.\", \"Latest installed driver identify karke rollback/update karo; Safe Mode se test karo.\"),\n            \"0x0000007F\": (\"UNEXPECTED_KERNEL_MODE_TRAP\", \"CPU/RAM hardware fault, overheating, ya low-level driver issue.\", \"Temperature, RAM, CPU overclock, BIOS/chipset update check karo.\"),\n            \"0x0000009F\": (\"DRIVER_POWER_STATE_FAILURE\", \"Sleep/shutdown/resume me driver power state atak gaya.\", \"Power management, chipset, Wi-Fi, Bluetooth, GPU drivers update/rollback karo.\"),\n            \"0x000000C2\": (\"BAD_POOL_CALLER\", \"Driver ne memory pool galat tarah use kiya.\", \"Recent driver/app uninstall karo, Driver Verifier culprit ke liye use karo.\"),\n            \"0x000000D1\": (\"DRIVER_IRQL_NOT_LESS_OR_EQUAL\", \"Network/storage/GPU driver ne invalid memory access kiya.\", \"Culprit driver update/rollback karo; dump file WinDbg me analyze karo.\"),\n            \"0x000000EA\": (\"THREAD_STUCK_IN_DEVICE_DRIVER\", \"GPU/display driver loop me phans gaya.\", \"GPU driver clean reinstall, GPU temperature/power check, hardware acceleration test karo.\"),\n            \"0x000000ED\": (\"UNMOUNTABLE_BOOT_VOLUME\", \"Boot volume mount nahi hua; file system/disk problem.\", \"WinRE se chkdsk /f /r, boot repair, disk health check karo.\"),\n            \"0x000000EF\": (\"CRITICAL_PROCESS_DIED\", \"Important Windows process crash ho gaya.\", \"SFC/DISM, malware scan, recent update/driver rollback, disk health check karo.\"),\n            \"0x00000109\": (\"CRITICAL_STRUCTURE_CORRUPTION\", \"Kernel structure corrupt; driver, RAM, malware, overclock possible.\", \"Overclock off, RAM test, malware scan, unsigned drivers check karo.\"),\n            \"0x00000116\": (\"VIDEO_TDR_FAILURE\", \"GPU driver/hardware timeout.\", \"Display driver DDU se clean install, GPU temperature/PSU check, hardware acceleration off test karo.\"),\n            \"0x00000117\": (\"VIDEO_TDR_TIMEOUT_DETECTED\", \"GPU driver ne time par response nahi diya.\", \"Graphics driver update/rollback, temperature/power check karo.\"),\n            \"0x00000124\": (\"WHEA_UNCORRECTABLE_ERROR\", \"Hardware error: CPU, RAM, PCIe, GPU, SSD, PSU ya overheating.\", \"Temps, RAM, SMART, BIOS/chipset update, overclock off, hardware stress test karo.\"),\n            \"0x00000133\": (\"DPC_WATCHDOG_VIOLATION\", \"Driver/SSD controller ne response time exceed kiya.\", \"Storage/NVMe/chipset driver update, SSD firmware, external devices remove test karo.\"),\n            \"0x00000139\": (\"KERNEL_SECURITY_CHECK_FAILURE\", \"Driver/memory corruption ya incompatible software.\", \"Recent driver/app rollback, SFC/DISM, RAM test, malware scan karo.\"),\n        }\n        return key, stop_map.get(key, (\"Unknown stop code\", \"Exact cause dump analysis ke bina confirm nahi hota.\", \"Minidump ko WinDbg/WhoCrashed se analyze karo, phir culprit driver fix karo.\"))\n\n    def _collect_bsod_events(self):\n        script = r\"\"\"\n$ids = @(41,1001,161,6008,17,18,19,1,7,11,51,55,129,153,4101,1101,1102,1201,1202)\n$events = @()\ntry {\n    $events = Get-WinEvent -LogName System -MaxEvents 900 -ErrorAction SilentlyContinue |\n        Where-Object {\n            ($ids -contains $_.Id) -or\n            ($_.ProviderName -match 'BugCheck|Kernel-Power|WHEA|Display|Disk|Ntfs|volmgr|storahci|storport|iaStor|MemoryDiagnostics')\n        } |\n        Select-Object -First 35 `\n            @{n='TimeCreated';e={$_.TimeCreated.ToString('s')}},\n            ProviderName,Id,LevelDisplayName,\n            @{n='Message';e={$_.Message}}\n} catch {}\n$events | ConvertTo-Json -Depth 4\n\"\"\"\n        out, _ = self._run_powershell(script, timeout=60)\n        return self._json_items_from_output(out)\n\n    def _collect_recent_third_party_drivers(self):\n        script = r\"\"\"\n$drivers = @()\ntry {\n    $drivers = Get-CimInstance Win32_PnPSignedDriver -ErrorAction SilentlyContinue |\n        Where-Object { $_.DriverProviderName -and $_.DriverProviderName -notmatch '^Microsoft' } |\n        Sort-Object DriverDate -Descending |\n        Select-Object -First 12 DeviceName,DriverProviderName,DriverVersion,DriverDate\n} catch {}\n$drivers | ConvertTo-Json -Depth 4\n\"\"\"\n        out, _ = self._run_powershell(script, timeout=60)\n        return self._json_items_from_output(out)\n\n    def _build_bsod_deep_report(self):\n        dumps = self._bsod_dump_files()\n        crash_values = self._crash_control_values()\n        events = self._collect_bsod_events()\n        drivers = self._collect_recent_third_party_drivers()\n        verifier_out, _ = self._run_cmd(\"verifier /querysettings\", timeout=25)\n        pagefile_out, _ = self._run_cmd(\"wmic pagefileset get Name,InitialSize,MaximumSize /format:list\", timeout=20)\n\n        findings = []\n        solutions = []\n        stop_codes = []\n\n        for ev in events:\n            msg = str(ev.get(\"Message\", \"\") or \"\")\n            src = str(ev.get(\"ProviderName\", \"\") or \"\")\n            eid = str(ev.get(\"Id\", \"\") or \"\")\n            low = f\"{src} {eid} {msg}\".lower()\n\n            if \"bugcheck\" in low or eid == \"1001\":\n                for found in re.findall(r\"0x[0-9a-fA-F]{1,16}\", msg):\n                    key, (name, reason, solution) = self._bsod_stop_code_details(found)\n                    if key not in [x[0] for x in stop_codes]:\n                        stop_codes.append((key, name, reason, solution))\n                if not re.search(r\"0x[0-9a-fA-F]{1,16}\", msg):\n                    findings.append(\"BugCheck event mila, lekin stop code message me clear nahi tha.\")\n\n            if \"kernel-power\" in low and eid == \"41\":\n                findings.append(\"Kernel-Power 41 mila: PC clean shutdown ke bina restart hua.\")\n                solutions.append(\"Power loss/SMPS/overheating/BSOD path check karo. Agar saath me BugCheck code hai to driver/hardware cause follow karo.\")\n            if \"whea\" in low:\n                findings.append(\"WHEA hardware error event mila: CPU/RAM/PCIe/GPU/SSD side hardware warning possible.\")\n                solutions.append(\"Overclock off, temperature check, BIOS/chipset update, RAM test, SSD SMART, GPU/PCIe seating check karo.\")\n            if \"display\" in low or \"tdr\" in low or eid == \"4101\":\n                findings.append(\"Display/GPU driver reset event mila.\")\n                solutions.append(\"GPU driver clean reinstall/rollback, GPU temperature aur PSU power check karo.\")\n            if any(x in low for x in [\"disk\", \"ntfs\", \"storahci\", \"storport\", \"iastor\"]) or eid in {\"7\", \"11\", \"51\", \"55\", \"129\", \"153\"}:\n                findings.append(\"Disk/storage event mila: storage timeout, NTFS corruption ya bad sector possible.\")\n                solutions.append(\"Important data backup, SMART report, cable/port check, chkdsk /f /r, storage/NVMe driver update karo.\")\n            if \"volmgr\" in low and eid == \"161\":\n                findings.append(\"volmgr 161 mila: crash dump create nahi ho paya.\")\n                solutions.append(\"C: drive free space/pagefile/dump settings check karo; system managed pagefile aur minidump enable karo.\")\n            if \"memorydiagnostics\" in low and (\"hardware problems\" in low or \"detected\" in low):\n                findings.append(\"Memory Diagnostic ne memory problem indicate ki.\")\n                solutions.append(\"RAM sticks reseat karo, single-stick test, MemTest86 4-pass, faulty RAM replace karo.\")\n\n        for key, name, reason, solution in stop_codes:\n            findings.append(f\"Stop Code {key} ({name}): {reason}\")\n            solutions.append(solution)\n\n        dump_enabled = int(crash_values.get(\"CrashDumpEnabled\", -1) or -1)\n        if dump_enabled == 0:\n            findings.append(\"Crash dump disabled hai, isliye future BSOD proof file save nahi hogi.\")\n            solutions.append(\"Enable Minidump button run karo: CrashDumpEnabled=3, MinidumpDir set, AutoReboot off.\")\n        elif dump_enabled not in (1, 2, 3, 7):\n            findings.append(\"Crash dump setting unclear hai; dump capture verify karna chahiye.\")\n\n        if str(crash_values.get(\"AutoReboot\", \"\")).strip() == \"1\":\n            solutions.append(\"AutoReboot off rakhna useful hai, warna blue screen turant restart ho jati hai aur user stop code nahi dekh pata.\")\n\n        if verifier_out and \"No settings\" not in verifier_out and \"not currently enabled\" not in verifier_out:\n            findings.append(\"Driver Verifier active lag raha hai; ye intentionally bad drivers ko BSOD kara sakta hai.\")\n            solutions.append(\"Agar PC boot loop me hai to Safe Mode me `verifier /reset` run karke reboot karo.\")\n\n        lines = []\n        lines.append(\"BSoD Deep Troubleshooting Report (Hinglish)\")\n        lines.append(f\"Generated: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\")\n        lines.append(\"\")\n        lines.append(\"Troubleshoot kya kiya:\")\n        lines.append(\"- C:\\\\Windows\\\\Minidump aur LiveKernelReports me dump files check ki.\")\n        lines.append(\"- Event Viewer me BugCheck, Kernel-Power, WHEA, Display, Disk, NTFS, volmgr events check kiye.\")\n        lines.append(\"- Crash dump registry settings, pagefile setting, Driver Verifier status check kiya.\")\n        lines.append(\"- Recent third-party drivers list kiye, kyunki BSOD ka common cause driver hota hai.\")\n        lines.append(\"\")\n        lines.append(\"Dump files:\")\n        if dumps:\n            for item in dumps[:8]:\n                lines.append(f\"- {item['path']} | {item['mtime']} | {item['size_kb']} KB\")\n        else:\n            lines.append(\"- No dump file found. Ya to recent BSOD nahi hua, ya dump setting/pagefile issue hai.\")\n        lines.append(\"\")\n        lines.append(\"Crash dump settings:\")\n        if crash_values:\n            for key in sorted(crash_values):\n                lines.append(f\"- {key}: {crash_values.get(key)}\")\n        else:\n            lines.append(\"- CrashControl registry read nahi hua. Admin rights required ho sakte hain.\")\n        if pagefile_out.strip():\n            lines.append(\"\")\n            lines.append(\"Pagefile:\")\n            lines.append(pagefile_out.strip()[:900])\n        lines.append(\"\")\n        lines.append(\"Result / likely karan:\")\n        if findings:\n            for item in list(dict.fromkeys(findings))[:14]:\n                lines.append(f\"- {item}\")\n        else:\n            lines.append(\"- Strong BSOD root-cause event nahi mila. Agar issue repeat hota hai to minidump enable karke next crash capture karein.\")\n        lines.append(\"\")\n        lines.append(\"Solution:\")\n        if solutions:\n            for item in list(dict.fromkeys(solutions))[:14]:\n                lines.append(f\"- {item}\")\n        else:\n            lines.append(\"- Windows update complete karo, SFC/DISM run karo, RAM/disk health check karo, aur next dump ko WinDbg/WhoCrashed me analyze karo.\")\n        lines.append(\"\")\n        lines.append(\"Recent matching events:\")\n        if events:\n            for ev in events[:10]:\n                msg = \" \".join(str(ev.get(\"Message\", \"\") or \"\").split())[:240]\n                lines.append(f\"- {ev.get('TimeCreated','')} | {ev.get('ProviderName','')} | ID {ev.get('Id','')} | {msg}\")\n        else:\n            lines.append(\"- No matching Event Viewer data found.\")\n        lines.append(\"\")\n        lines.append(\"Recent non-Microsoft drivers:\")\n        if drivers:\n            for d in drivers[:10]:\n                lines.append(f\"- {d.get('DeviceName','')} | {d.get('DriverProviderName','')} | {d.get('DriverVersion','')} | {d.get('DriverDate','')}\")\n        else:\n            lines.append(\"- Third-party driver list empty/blocked.\")\n        lines.append(\"\")\n        lines.append(\"Customer ko simple explain:\")\n        lines.append(\"Blue screen ka matlab Windows kernel level par serious crash hua. Is report me humne stop code, crash dump, hardware WHEA, disk/NTFS, GPU/display aur driver clues check kiye. Jo clue mila hai uske hisaab se driver update/rollback, RAM/disk test, GPU/storage driver repair, ya minidump enable karna next best step hai.\")\n\n        severity = \"warning\" if findings or dumps else \"success\"\n        return \"\\n\".join(lines), severity, len(findings)\n\n    def _bsod_deep_diagnose(self):\n        if not messagebox.askyesno(\n            \"BSoD Deep Diagnose\",\n            \"Blue screen root-cause diagnosis run karein?\\n\\n\"\n            \"Ye sirf logs/settings check karega. Koi destructive change nahi karega.\"\n        ):\n            return\n        self._append_log(self.trouble_log, \"BSoD Deep Diagnose started...\", C[\"accent3\"])\n        self._set_status(\"BSoD diagnosis running...\", C[\"accent3\"])\n        self._launch_job(\"bsod_deep_diagnose\", self._do_bsod_deep_diagnose)\n\n    def _do_bsod_deep_diagnose(self):\n        try:\n            report, severity, count = self._build_bsod_deep_report()\n            color = C[\"warning\"] if severity == \"warning\" else C[\"success\"]\n            self._append_log(self.trouble_log, \"\\n\" + report + \"\\n\", color)\n            title = \"BSoD Clues Found\" if count else \"BSoD Diagnosis Complete\"\n            msg = (\n                f\"{count} clue(s) found. Full Hinglish report System Repair log me hai.\"\n                if count else\n                \"Strong BSOD clue nahi mila. Full report System Repair log me hai.\"\n            )\n            self.after(0, lambda: messagebox.showwarning(title, msg) if count else messagebox.showinfo(title, msg))\n            self.after(0, lambda: self._set_status(\"BSoD diagnosis complete\", color))\n        except Exception as e:\n            self._append_log(self.trouble_log, f\"BSoD diagnosis failed: {e}\", C[\"error\"])\n            self.after(0, lambda: self._set_status(\"BSoD diagnosis failed\", C[\"error\"]))\n\n    def _enable_bsod_minidump(self):\n        if not messagebox.askyesno(\n            \"Enable Minidump\",\n            \"Future Blue Screen ke proof logs enable karein?\\n\\n\"\n            \"Changes:\\n\"\n            \"- Small memory dump enable\\n\"\n            \"- C:\\\\Windows\\\\Minidump path set\\n\"\n            \"- Event log enable\\n\"\n            \"- Auto restart off, taaki stop code dikhe\\n\\n\"\n            \"Admin rights required.\"\n        ):\n            return\n        self._append_log(self.trouble_log, \"Enabling BSOD minidump settings...\", C[\"accent3\"])\n        try:\n            try:\n                os.makedirs(r\"C:\\Windows\\Minidump\", exist_ok=True)\n            except Exception as e:\n                self._append_log(self.trouble_log, f\"Minidump folder create warning: {e}\", C[\"warning\"])\n            results = [\n                self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Control\\CrashControl\", \"CrashDumpEnabled\", 3, winreg.REG_DWORD, \"Small memory dump enabled\", self.trouble_log),\n                self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Control\\CrashControl\", \"MinidumpDir\", r\"%SystemRoot%\\Minidump\", winreg.REG_EXPAND_SZ, \"Minidump directory set\", self.trouble_log),\n                self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Control\\CrashControl\", \"LogEvent\", 1, winreg.REG_DWORD, \"Crash event logging enabled\", self.trouble_log),\n                self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Control\\CrashControl\", \"AutoReboot\", 0, winreg.REG_DWORD, \"Auto restart after BSOD disabled\", self.trouble_log),\n                self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Control\\CrashControl\", \"Overwrite\", 1, winreg.REG_DWORD, \"Overwrite old dump enabled\", self.trouble_log),\n            ]\n            summary = self._action_summary(\"BSOD Minidump Setup\", results)\n            note = summary[\"message\"] + \"\\n\\nNote: Pagefile system managed hona chahiye, warna dump create fail ho sakta hai.\"\n            self._append_log(self.trouble_log, note, C[\"success\"] if not summary[\"failed\"] else C[\"warning\"])\n            messagebox.showinfo(\"Minidump Setup\", note)\n        except Exception as e:\n            self._append_log(self.trouble_log, f\"Minidump setup failed: {e}\", C[\"error\"])\n            messagebox.showerror(\"Error\", str(e))\n\n    def _collect_rundll32_details(self):\n        sig_script = r\"\"\"\n$paths = @(\"$env:windir\\System32\\rundll32.exe\", \"$env:windir\\SysWOW64\\rundll32.exe\")\n$items = foreach($p in $paths) {\n    $exists = Test-Path $p\n    $sig = $null\n    $file = $null\n    if($exists) {\n        $sig = Get-AuthenticodeSignature $p -ErrorAction SilentlyContinue\n        $file = Get-Item $p -ErrorAction SilentlyContinue\n    }\n    [pscustomobject]@{\n        Path=$p\n        Exists=$exists\n        Length=if($file){$file.Length}else{$null}\n        LastWriteTime=if($file){$file.LastWriteTime.ToString('s')}else{$null}\n        SignatureStatus=if($sig){[string]$sig.Status}else{\"Missing\"}\n        Signer=if($sig -and $sig.SignerCertificate){$sig.SignerCertificate.Subject}else{\"\"}\n    }\n}\n$items | ConvertTo-Json -Depth 4\n\"\"\"\n        startup_script = r\"\"\"\n$items = @()\n$keys = @(\n    'HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Run',\n    'HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce',\n    'HKLM:\\Software\\Microsoft\\Windows\\CurrentVersion\\Run',\n    'HKLM:\\Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce',\n    'HKLM:\\Software\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Run',\n    'HKLM:\\Software\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\RunOnce'\n)\nforeach($k in $keys) {\n    if(Test-Path $k) {\n        $props = Get-ItemProperty $k -ErrorAction SilentlyContinue\n        foreach($p in $props.PSObject.Properties) {\n            if($p.Name -match '^PS') { continue }\n            $v = [string]$p.Value\n            if($v -match 'rundll32|rundell32|rundll32\\.dll|rundell32\\.dll') {\n                $items += [pscustomobject]@{Location=$k;Name=$p.Name;Command=$v}\n            }\n        }\n    }\n}\n$items | ConvertTo-Json -Depth 4\n\"\"\"\n        task_script = r\"\"\"\n$items = @()\ntry {\n    $items = Get-ScheduledTask -ErrorAction SilentlyContinue |\n        Where-Object { ($_.Actions | Out-String) -match 'rundll32|rundell32|rundll32\\.dll|rundell32\\.dll' } |\n        Select-Object -First 30 TaskPath,TaskName,State,@{n='Action';e={($_.Actions | Out-String).Trim()}}\n} catch {}\n$items | ConvertTo-Json -Depth 4\n\"\"\"\n        event_script = r\"\"\"\n$items = @()\nforeach($log in @('Application','System')) {\n    try {\n        $items += Get-WinEvent -LogName $log -MaxEvents 900 -ErrorAction SilentlyContinue |\n            Where-Object {\n                ($_.Message -match 'rundll32|rundell32|rundll32\\.dll|rundell32\\.dll|kernel32\\.dll') -or\n                ($_.ProviderName -match 'SideBySide|Application Error' -and $_.Message -match '\\.dll|module|activation context|kernel32')\n            } |\n            Select-Object -First 25 @{n='Log';e={$log}},@{n='TimeCreated';e={$_.TimeCreated.ToString('s')}},ProviderName,Id,LevelDisplayName,@{n='Message';e={$_.Message}}\n    } catch {}\n}\n$items | Select-Object -First 35 | ConvertTo-Json -Depth 4\n\"\"\"\n        wer_script = r\"\"\"\n$roots = @(\"$env:ProgramData\\Microsoft\\Windows\\WER\\ReportArchive\", \"$env:ProgramData\\Microsoft\\Windows\\WER\\ReportQueue\", \"$env:LOCALAPPDATA\\Microsoft\\Windows\\WER\")\n$items = @()\nforeach($r in $roots) {\n    if(Test-Path $r) {\n        try {\n            $items += Get-ChildItem $r -Recurse -Filter Report.wer -ErrorAction SilentlyContinue |\n                Select-Object -First 80 |\n                ForEach-Object {\n                    $txt = Get-Content $_.FullName -Raw -ErrorAction SilentlyContinue\n                    if($txt -match 'rundll32|rundell32|kernel32\\.dll|Fault Module Name|AppName') {\n                        [pscustomobject]@{Path=$_.FullName;LastWriteTime=$_.LastWriteTime.ToString('s');Text=($txt.Substring(0, [Math]::Min($txt.Length, 2500)))}\n                    }\n                }\n        } catch {}\n    }\n}\n$items | Select-Object -First 30 | ConvertTo-Json -Depth 4\n\"\"\"\n        suspicious_file_script = r\"\"\"\n$paths = @(\n    \"$env:windir\\rundell32.dll\",\n    \"$env:windir\\rundll32.dll\",\n    \"$env:windir\\System32\\rundell32.dll\",\n    \"$env:windir\\System32\\rundll32.dll\",\n    \"$env:windir\\SysWOW64\\rundell32.dll\",\n    \"$env:windir\\SysWOW64\\rundll32.dll\"\n)\n$items = foreach($p in $paths) {\n    if(Test-Path $p) {\n        $f = Get-Item $p -ErrorAction SilentlyContinue\n        [pscustomobject]@{Path=$p;Length=$f.Length;LastWriteTime=$f.LastWriteTime.ToString('s')}\n    }\n}\n$items | ConvertTo-Json -Depth 4\n\"\"\"\n        sig_out, _ = self._run_powershell(sig_script, timeout=35)\n        startup_out, _ = self._run_powershell(startup_script, timeout=35)\n        task_out, _ = self._run_powershell(task_script, timeout=60)\n        event_out, _ = self._run_powershell(event_script, timeout=60)\n        suspicious_file_out, _ = self._run_powershell(suspicious_file_script, timeout=30)\n        wer_out, _ = self._run_powershell(wer_script, timeout=80)\n        where_out, _ = self._run_cmd(\"where rundll32\", timeout=15)\n        return {\n            \"files\": self._json_items_from_output(sig_out),\n            \"startup\": self._json_items_from_output(startup_out),\n            \"tasks\": self._json_items_from_output(task_out),\n            \"events\": self._json_items_from_output(event_out),\n            \"fake\": self._json_items_from_output(suspicious_file_out),\n            \"wer\": self._json_items_from_output(wer_out),\n            \"where\": where_out.strip(),\n        }\n\n    def _build_rundll32_report(self):\n        data = self._collect_rundll32_details()\n        findings = []\n        solutions = []\n\n        for item in data[\"files\"]:\n            path = str(item.get(\"Path\", \"\"))\n            exists = bool(item.get(\"Exists\"))\n            sig = str(item.get(\"SignatureStatus\", \"\"))\n            signer = str(item.get(\"Signer\", \"\"))\n            if not exists:\n                findings.append(f\"{path} missing hai.\")\n                solutions.append(\"System file missing/corrupt ho sakti hai: DISM RestoreHealth aur SFC /SCANNOW run karo.\")\n            elif sig.lower() != \"valid\" or \"microsoft\" not in signer.lower():\n                findings.append(f\"{path} signature suspicious hai: Status={sig}, Signer={signer}\")\n                solutions.append(\"Malware/tampering possible: Defender Offline Scan run karo, phir SFC/DISM se system file repair karo.\")\n\n        if data[\"fake\"]:\n            findings.append(\"rundll32.dll/rundell32.dll naam ki suspicious file mili. Windows ka real file rundll32.exe hota hai.\")\n            solutions.append(\"Suspicious DLL ko direct open/delete na karein. Pehle Defender Offline Scan, then autoruns/startup check karke source remove karein.\")\n\n        typo_hits = []\n        for group in (\"startup\", \"tasks\", \"events\"):\n            for item in data[group]:\n                text = \" \".join(str(v) for v in item.values()).lower()\n                if \"rundell32\" in text or \"rundll32.dll\" in text or \"rundell32.dll\" in text:\n                    typo_hits.append(item)\n        if typo_hits:\n            findings.append(\"rundell32/rundll32.dll typo reference mila. Ye aksar malware ya broken startup entry hoti hai.\")\n            solutions.append(\"Startup/Task Scheduler me us entry ko disable/remove karo, related unknown app uninstall karo, malware scan run karo.\")\n\n        if data[\"startup\"]:\n            findings.append(f\"{len(data['startup'])} startup Run entry rundll32 use kar rahi hai.\")\n            solutions.append(\"Agar error startup par aata hai to listed Run entry ka DLL path check karo; missing DLL ho to entry disable karo ya app reinstall/uninstall karo.\")\n        if data[\"tasks\"]:\n            findings.append(f\"{len(data['tasks'])} scheduled task rundll32 use kar raha hai.\")\n            solutions.append(\"Task Scheduler me listed task ka action verify karo; unknown/publisher-less task disable karke reboot test karo.\")\n\n        for ev in data[\"events\"]:\n            msg = str(ev.get(\"Message\", \"\") or \"\").lower()\n            src = str(ev.get(\"ProviderName\", \"\") or \"\").lower()\n            if \"kernel32.dll\" in msg:\n                findings.append(\"kernel32.dll faulting module event mila.\")\n                solutions.append(\"kernel32.dll aksar victim module hota hai. Real culprit app/plugin/runtime hota hai: affected app repair/reinstall, VC++ runtime repair, SFC/DISM run karo.\")\n            if \"specified module could not be found\" in msg or \"module could not be found\" in msg:\n                findings.append(\"Event log me 'specified module could not be found' mila.\")\n                solutions.append(\"Karan: Windows rundll32.exe se ek DLL load kar raha tha, par DLL missing hai. Solution: startup/task entry remove karo ya related app reinstall karo.\")\n            if \"sidebyside\" in src or \"activation context\" in msg:\n                findings.append(\"SideBySide/activation context DLL error mila.\")\n                solutions.append(\"Karan: app runtime/VC++ dependency mismatch. Solution: affected app reinstall karo aur Microsoft Visual C++ Redistributables repair/install karo.\")\n            if \"faulting application name: rundll32.exe\" in msg:\n                findings.append(\"rundll32.exe crash event mila.\")\n                solutions.append(\"Karan usually loaded DLL/plugin hota hai, rundll32.exe khud nahi. Event message me faulting module/app identify karke us app/driver ko repair karo.\")\n        for wer in data.get(\"wer\", []):\n            text = str(wer.get(\"Text\", \"\") or \"\").lower()\n            if \"kernel32.dll\" in text or \"rundll32\" in text or \"rundell32\" in text:\n                findings.append(\"WER crash report me kernel32/rundll32 related crash evidence mila.\")\n                solutions.append(\"WER report me AppName/Fault Module dekho; us affected app ko repair/reinstall karo aur dependency/runtime issue fix karo.\")\n\n        lines = []\n        lines.append(\"Kernel32 + Rundll32 / Rundell32 DLL Error Troubleshooting Report (Hinglish)\")\n        lines.append(f\"Generated: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\")\n        lines.append(\"\")\n        lines.append(\"Important clarification:\")\n        lines.append(\"- Windows ka real component rundll32.exe hota hai, rundell32.dll nahi.\")\n        lines.append(\"- Error usually tab aata hai jab startup/task/app rundll32.exe ke through ek DLL load karna chahta hai, par DLL missing/corrupt/incompatible hoti hai.\")\n        lines.append(\"\")\n        lines.append(\"Troubleshoot kya kiya:\")\n        lines.append(\"- System32 aur SysWOW64 me rundll32.exe file existence/signature check ki.\")\n        lines.append(\"- where rundll32 se PATH hijack check kiya.\")\n        lines.append(\"- Registry Run/RunOnce startup entries me rundll32/rundell32 references dhoonde.\")\n        lines.append(\"- Scheduled Tasks me rundll32 actions check kiye.\")\n        lines.append(\"- Event Viewer me rundll32, rundell32, kernel32, SideBySide, module/DLL errors check kiye.\")\n        lines.append(\"- WER ReportArchive/ReportQueue me faulting module crash reports check kiye.\")\n        lines.append(\"- Fake/suspicious rundll32.dll/rundell32.dll files common Windows folders me check ki.\")\n        lines.append(\"\")\n        lines.append(\"File status:\")\n        if data[\"files\"]:\n            for item in data[\"files\"]:\n                lines.append(f\"- {item.get('Path','')} | Exists={item.get('Exists')} | Signature={item.get('SignatureStatus')} | Signer={item.get('Signer','')}\")\n        else:\n            lines.append(\"- File signature data read nahi hua.\")\n        lines.append(\"\")\n        lines.append(\"where rundll32:\")\n        lines.append(data[\"where\"] or \"No PATH result.\")\n        lines.append(\"\")\n        lines.append(\"Result / likely karan:\")\n        if findings:\n            for item in list(dict.fromkeys(findings))[:14]:\n                lines.append(f\"- {item}\")\n        else:\n            lines.append(\"- rundll32 related strong problem nahi mila. Agar popup aa raha hai, exact popup text/DLL name note karke startup/task me search karein.\")\n        lines.append(\"\")\n        lines.append(\"Solution:\")\n        if solutions:\n            for item in list(dict.fromkeys(solutions))[:14]:\n                lines.append(f\"- {item}\")\n        else:\n            lines.append(\"- SFC/DISM run karo, unknown startup entries disable karo, affected app reinstall/uninstall karo, malware scan run karo.\")\n        lines.append(\"\")\n        lines.append(\"Startup entries:\")\n        if data[\"startup\"]:\n            for item in data[\"startup\"][:12]:\n                lines.append(f\"- {item.get('Location','')} | {item.get('Name','')} | {item.get('Command','')}\")\n        else:\n            lines.append(\"- No rundll32 startup entry found.\")\n        lines.append(\"\")\n        lines.append(\"Scheduled tasks:\")\n        if data[\"tasks\"]:\n            for item in data[\"tasks\"][:12]:\n                action = \" \".join(str(item.get(\"Action\", \"\")).split())[:260]\n                lines.append(f\"- {item.get('TaskPath','')}{item.get('TaskName','')} | {item.get('State','')} | {action}\")\n        else:\n            lines.append(\"- No rundll32 scheduled task found.\")\n        lines.append(\"\")\n        lines.append(\"Recent related events:\")\n        if data[\"events\"]:\n            for ev in data[\"events\"][:10]:\n                msg = \" \".join(str(ev.get(\"Message\", \"\") or \"\").split())[:260]\n                lines.append(f\"- {ev.get('TimeCreated','')} | {ev.get('ProviderName','')} | ID {ev.get('Id','')} | {msg}\")\n        else:\n            lines.append(\"- No recent related Event Viewer error found.\")\n        lines.append(\"\")\n        lines.append(\"WER reports:\")\n        if data.get(\"wer\"):\n            for wer in data[\"wer\"][:8]:\n                sample = \" \".join(str(wer.get(\"Text\", \"\") or \"\").split())[:260]\n                lines.append(f\"- {wer.get('LastWriteTime','')} | {wer.get('Path','')} | {sample}\")\n        else:\n            lines.append(\"- No related WER crash reports found.\")\n        lines.append(\"\")\n        lines.append(\"Customer ko simple explain:\")\n        lines.append(\"Rundll32.exe Windows ka loader hai aur kernel32.dll core Windows library hai. Popup/crash me inka naam aane ka matlab aksar ye hota hai ki koi app, startup entry, shell extension, driver, ya missing DLL inke through fail ho raha hai. Humne file signature, startup, scheduled task, Event Viewer aur WER crash reports check kiye. Jo entry/app/module culprit ho usko reinstall/uninstall/disable karein, malware scan plus SFC/DISM run karein.\")\n\n        return \"\\n\".join(lines), (\"warning\" if findings else \"success\"), len(findings)\n\n    def _rundll32_error_diagnose(self):\n        if not messagebox.askyesno(\n            \"Rundll32 Error Check\",\n            \"rundll32/rundell32 DLL error diagnosis run karein?\\n\\n\"\n            \"Ye logs, startup entries aur file signature check karega. Koi entry delete nahi karega.\"\n        ):\n            return\n        self._append_log(self.trouble_log, \"Rundll32 Error Check started...\", C[\"btn_info\"])\n        self._set_status(\"Rundll32 diagnosis running...\", C[\"btn_info\"])\n        self._launch_job(\"rundll32_error_diagnose\", self._do_rundll32_error_diagnose)\n\n    def _do_rundll32_error_diagnose(self):\n        try:\n            report, severity, count = self._build_rundll32_report()\n            color = C[\"warning\"] if severity == \"warning\" else C[\"success\"]\n            self._append_log(self.trouble_log, \"\\n\" + report + \"\\n\", color)\n            title = \"Rundll32 Clues Found\" if count else \"Rundll32 Check Complete\"\n            msg = (\n                f\"{count} clue(s) found. Full Hinglish report System Repair log me hai.\"\n                if count else\n                \"Strong rundll32 problem nahi mila. Full report System Repair log me hai.\"\n            )\n            self.after(0, lambda: messagebox.showwarning(title, msg) if count else messagebox.showinfo(title, msg))\n            self.after(0, lambda: self._set_status(\"Rundll32 diagnosis complete\", color))\n        except Exception as e:\n            self._append_log(self.trouble_log, f\"Rundll32 diagnosis failed: {e}\", C[\"error\"])\n            self.after(0, lambda: self._set_status(\"Rundll32 diagnosis failed\", C[\"error\"]))\n\n    def _show_text_report_window(self, title, text):\n        win = tk.Toplevel(self)\n        win.title(title)\n        win.geometry(\"1050x700\")\n        win.configure(bg=C[\"bg\"])\n        viewer = scrolledtext.ScrolledText(\n            win, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"],\n            insertbackground=C[\"text\"], wrap=\"word\"\n        )\n        viewer.pack(fill=\"both\", expand=True, padx=10, pady=10)\n        viewer.insert(\"1.0\", self._fix_text(text))\n        viewer.config(state=\"disabled\")\n\n    def _find_debugger_engine(self):\n        candidates = []\n        for exe in (\"cdb.exe\", \"kd.exe\", \"windbg.exe\"):\n            path = shutil.which(exe)\n            if path:\n                candidates.append(path)\n        roots = [\n            os.environ.get(\"ProgramFiles\", r\"C:\\Program Files\"),\n            os.environ.get(\"ProgramFiles(x86)\", r\"C:\\Program Files (x86)\"),\n        ]\n        rels = [\n            r\"Windows Kits\\10\\Debuggers\\x64\\cdb.exe\",\n            r\"Windows Kits\\10\\Debuggers\\x86\\cdb.exe\",\n            r\"Windows Kits\\10\\Debuggers\\x64\\kd.exe\",\n            r\"Windows Kits\\10\\Debuggers\\x64\\windbg.exe\",\n        ]\n        for root in roots:\n            if not root:\n                continue\n            for rel in rels:\n                p = os.path.join(root, rel)\n                if os.path.exists(p):\n                    candidates.append(p)\n        seen = set()\n        for p in candidates:\n            key = p.lower()\n            if key not in seen:\n                seen.add(key)\n                return p\n        return \"\"\n\n    def _parse_windbg_analysis(self, text):\n        data = {}\n        patterns = {\n            \"bugcheck\": r\"BUGCHECK_CODE:\\s+([^\\r\\n]+)\",\n            \"exception_code\": r\"EXCEPTION_CODE:\\s+\\(?([^\\s\\)]+)\",\n            \"probably_caused_by\": r\"Probably caused by\\s+:\\s+([^\\r\\n]+)\",\n            \"module_name\": r\"MODULE_NAME:\\s+([^\\r\\n]+)\",\n            \"image_name\": r\"IMAGE_NAME:\\s+([^\\r\\n]+)\",\n            \"failure_bucket\": r\"FAILURE_BUCKET_ID:\\s+([^\\r\\n]+)\",\n            \"process_name\": r\"PROCESS_NAME:\\s+([^\\r\\n]+)\",\n        }\n        for key, pat in patterns.items():\n            m = re.search(pat, text, re.I)\n            if m:\n                data[key] = m.group(1).strip()\n        stack = []\n        capture = False\n        for ln in text.splitlines():\n            if ln.strip().upper().startswith(\"STACK_TEXT\"):\n                capture = True\n                continue\n            if capture:\n                if not ln.strip():\n                    if stack:\n                        break\n                    continue\n                if len(stack) &lt; 18:\n                    stack.append(ln.rstrip())\n        data[\"stack\"] = stack\n        return data\n\n    def _build_windbg_report(self, dump_path):\n        dbg = self._find_debugger_engine()\n        if not dbg:\n            return (\n                \"WinDbg automation unavailable.\\n\\n\"\n                \"Debugging Tools for Windows/cdb.exe system me nahi mila.\\n\"\n                \"Install Windows SDK Debugging Tools, phir ye button !analyze -v automation run karega.\\n\\n\"\n                f\"Dump selected: {dump_path}\",\n                \"warning\"\n            )\n        cmd_script = \".symfix;.reload;!analyze -v;lm;k;q\"\n        cmd = f'\"{dbg}\" -z \"{dump_path}\" -c \"{cmd_script}\"'\n        out, rc = self._run_cmd(cmd, timeout=900)\n        parsed = self._parse_windbg_analysis(out)\n        lines = [\n            \"WinDbg Automated Crash Analysis\",\n            f\"Generated: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\",\n            f\"Debugger: {dbg}\",\n            f\"Dump: {dump_path}\",\n            f\"Return code: {rc}\",\n            \"\",\n            \"Commands executed:\",\n            \".symfix\",\n            \".reload\",\n            \"!analyze -v\",\n            \"lm\",\n            \"k\",\n            \"\",\n            \"Parsed result:\",\n        ]\n        if parsed:\n            for k in (\"bugcheck\", \"exception_code\", \"probably_caused_by\", \"module_name\", \"image_name\", \"failure_bucket\", \"process_name\"):\n                if parsed.get(k):\n                    lines.append(f\"- {k}: {parsed[k]}\")\n            if parsed.get(\"bugcheck\"):\n                key, detail = self._bsod_stop_code_details(parsed[\"bugcheck\"])\n                lines.append(f\"- stop code explain: {key} {detail[0]} | {detail[1]}\")\n                lines.append(f\"- solution: {detail[2]}\")\n            if parsed.get(\"probably_caused_by\"):\n                lines.append(\"\")\n                lines.append(\"Suspected driver/app:\")\n                lines.append(f\"- {parsed['probably_caused_by']}\")\n                lines.append(\"- Is driver/app ko update, rollback, ya clean reinstall karke retest karein.\")\n            if parsed.get(\"stack\"):\n                lines.append(\"\")\n                lines.append(\"Stack trace sample:\")\n                lines.extend(parsed[\"stack\"])\n        else:\n            lines.append(\"- WinDbg output parse nahi hua. Raw output neeche diya hai.\")\n        lines.append(\"\")\n        lines.append(\"Raw WinDbg output tail:\")\n        lines.append(out[-6000:] if out else \"No output\")\n        return \"\\n\".join(lines), (\"warning\" if parsed else \"success\")\n\n    def _windbg_dump_analyze(self):\n        dumps = self._bsod_dump_files()\n        if not dumps:\n            messagebox.showinfo(\"No Dump\", \"C:\\\\Windows\\\\Minidump ya MEMORY.DMP me dump file nahi mili.\")\n            return\n        latest = dumps[0][\"path\"]\n        if not messagebox.askyesno(\n            \"WinDbg Dump Analyze\",\n            f\"Latest dump analyze karein?\\n\\n{latest}\\n\\n\"\n            \"Ye WinDbg/cdb.exe available hone par symbols load karke !analyze -v run karega.\"\n        ):\n            return\n        self._append_log(self.trouble_log, f\"WinDbg analysis started: {latest}\", C[\"accent4\"])\n        self._set_status(\"WinDbg dump analysis running...\", C[\"accent4\"])\n        self._launch_job(\"windbg_dump_analyze\", self._do_windbg_dump_analyze, latest)\n\n    def _do_windbg_dump_analyze(self, dump_path):\n        try:\n            report, severity = self._build_windbg_report(dump_path)\n            color = C[\"warning\"] if severity == \"warning\" else C[\"success\"]\n            self._append_log(self.trouble_log, \"\\n\" + report + \"\\n\", color)\n            self.after(0, lambda: self._show_text_report_window(\"WinDbg Dump Analysis\", report))\n            self.after(0, lambda: self._set_status(\"WinDbg analysis complete\", color))\n        except Exception as e:\n            self._append_log(self.trouble_log, f\"WinDbg analysis failed: {e}\", C[\"error\"])\n            self.after(0, lambda: self._set_status(\"WinDbg analysis failed\", C[\"error\"]))\n\n    def _collect_correlation_events(self):\n        script = r\"\"\"\n$ids = @(41,1001,6008,7031,7034,7000,7001,7,11,51,55,129,153,161,17,18,19,4101,1000,1002)\n$all = @()\nforeach($log in @('System','Application')) {\n    try {\n        $all += Get-WinEvent -LogName $log -MaxEvents 700 -ErrorAction SilentlyContinue |\n            Where-Object { ($ids -contains $_.Id) -or $_.LevelDisplayName -match 'Critical|Error' } |\n            Select-Object @{n='Log';e={$log}},@{n='TimeCreated';e={$_.TimeCreated.ToString('s')}},\n                ProviderName,Id,LevelDisplayName,@{n='Message';e={$_.Message}}\n    } catch {}\n}\n$all | Sort-Object TimeCreated -Descending | Select-Object -First 120 | ConvertTo-Json -Depth 4\n\"\"\"\n        out, _ = self._run_powershell(script, timeout=80)\n        return self._json_items_from_output(out)\n\n    def _build_event_correlation_report(self):\n        events = self._collect_correlation_events()\n        categories = {\n            \"Kernel-Power / dirty shutdown\": [],\n            \"BugCheck / BSOD\": [],\n            \"Service crashes\": [],\n            \"Disk / NTFS / storage\": [],\n            \"WHEA hardware\": [],\n            \"Application crashes\": [],\n        }\n        for ev in events:\n            text = f\"{ev.get('ProviderName','')} {ev.get('Id','')} {ev.get('Message','')}\".lower()\n            eid = str(ev.get(\"Id\", \"\"))\n            if \"kernel-power\" in text or eid == \"6008\":\n                categories[\"Kernel-Power / dirty shutdown\"].append(ev)\n            if \"bugcheck\" in text or eid == \"1001\":\n                categories[\"BugCheck / BSOD\"].append(ev)\n            if \"service control manager\" in text or eid in {\"7031\", \"7034\", \"7000\", \"7001\"}:\n                categories[\"Service crashes\"].append(ev)\n            if any(x in text for x in (\"disk\", \"ntfs\", \"storahci\", \"storport\", \"volmgr\")) or eid in {\"7\", \"11\", \"51\", \"55\", \"129\", \"153\", \"161\"}:\n                categories[\"Disk / NTFS / storage\"].append(ev)\n            if \"whea\" in text or eid in {\"17\", \"18\", \"19\"}:\n                categories[\"WHEA hardware\"].append(ev)\n            if \"application error\" in text or eid in {\"1000\", \"1002\"}:\n                categories[\"Application crashes\"].append(ev)\n        lines = [\n            \"Event Correlation Report\",\n            f\"Generated: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\",\n            \"\",\n            \"Troubleshoot kya kiya:\",\n            \"- System/Application logs se critical/error events collect kiye.\",\n            \"- Kernel-Power, BugCheck, service crash, disk/NTFS, WHEA, application crash ko timeline me correlate kiya.\",\n            \"\",\n            \"Root-cause summary:\",\n        ]\n        for name, items in categories.items():\n            lines.append(f\"- {name}: {len(items)} event(s)\")\n        if categories[\"BugCheck / BSOD\"] and categories[\"Kernel-Power / dirty shutdown\"]:\n            lines.append(\"- Probable: dirty shutdown Kernel-Power ke peeche actual BugCheck/BSOD ho sakta hai.\")\n        if categories[\"WHEA hardware\"]:\n            lines.append(\"- Probable: hardware/thermal/PCIe/RAM/SSD issue BSOD ya restart ka source ho sakta hai.\")\n        if categories[\"Disk / NTFS / storage\"]:\n            lines.append(\"- Probable: disk/storage timeout ya NTFS corruption system freeze/BSOD trigger kar sakta hai.\")\n        if categories[\"Service crashes\"] and not categories[\"BugCheck / BSOD\"]:\n            lines.append(\"- Probable: Windows service/app instability hai; service dependencies aur recent updates check karo.\")\n        lines.append(\"\")\n        lines.append(\"Chronological events (latest first):\")\n        for ev in events[:35]:\n            msg = \" \".join(str(ev.get(\"Message\", \"\") or \"\").split())[:220]\n            lines.append(f\"- {ev.get('TimeCreated','')} | {ev.get('Log','')} | {ev.get('ProviderName','')} | ID {ev.get('Id','')} | {msg}\")\n        return \"\\n\".join(lines), (\"warning\" if events else \"success\")\n\n    def _event_correlation_report(self):\n        self._append_log(self.trouble_log, \"Event correlation started...\", C[\"btn\"])\n        self._set_status(\"Event correlation running...\", C[\"btn\"])\n        self._launch_job(\"event_correlation_report\", self._do_event_correlation_report)\n\n    def _do_event_correlation_report(self):\n        try:\n            report, severity = self._build_event_correlation_report()\n            color = C[\"warning\"] if severity == \"warning\" else C[\"success\"]\n            self._append_log(self.trouble_log, \"\\n\" + report + \"\\n\", color)\n            self.after(0, lambda: self._show_text_report_window(\"Event Correlation Report\", report))\n            self.after(0, lambda: self._set_status(\"Event correlation complete\", color))\n        except Exception as e:\n            self._append_log(self.trouble_log, f\"Event correlation failed: {e}\", C[\"error\"])\n\n    def _build_driver_diagnostics_report(self):\n        driverquery_out, _ = self._run_cmd(\"driverquery /v /fo csv\", timeout=80)\n        script = r\"\"\"\n$drivers = @()\ntry {\n    $drivers = Get-CimInstance Win32_PnPSignedDriver -ErrorAction SilentlyContinue |\n        Select-Object DeviceName,DriverProviderName,DriverVersion,DriverDate,InfName,IsSigned |\n        Sort-Object DriverDate -Descending\n} catch {}\n$sys = @()\ntry {\n    $sys = Get-ChildItem \"$env:windir\\System32\\drivers\\*.sys\" -ErrorAction SilentlyContinue |\n        Sort-Object LastWriteTime -Descending |\n        Select-Object -First 80 FullName,Length,LastWriteTime,@{n='Signature';e={(Get-AuthenticodeSignature $_.FullName -ErrorAction SilentlyContinue).Status}}\n} catch {}\n[pscustomobject]@{PnP=$drivers;SysFiles=$sys} | ConvertTo-Json -Depth 5\n\"\"\"\n        out, _ = self._run_powershell(script, timeout=120)\n        items = self._json_items_from_output(out)\n        payload = items[0] if items else {}\n        pnp = payload.get(\"PnP\", []) if isinstance(payload, dict) else []\n        sysfiles = payload.get(\"SysFiles\", []) if isinstance(payload, dict) else []\n        if isinstance(pnp, dict):\n            pnp = [pnp]\n        if isinstance(sysfiles, dict):\n            sysfiles = [sysfiles]\n\n        unsigned = []\n        old = []\n        recent = []\n        now = datetime.datetime.now()\n        for d in pnp:\n            signed = str(d.get(\"IsSigned\", \"\")).lower()\n            provider = str(d.get(\"DriverProviderName\", \"\") or \"\")\n            date_s = str(d.get(\"DriverDate\", \"\") or \"\")\n            if signed in {\"false\", \"0\"}:\n                unsigned.append(d)\n            if provider and \"microsoft\" not in provider.lower():\n                recent.append(d)\n            try:\n                dt = datetime.datetime.fromisoformat(date_s[:19])\n                if (now - dt).days &gt; 1460 and \"microsoft\" not in provider.lower():\n                    old.append(d)\n            except Exception:\n                pass\n        bad_sig = [x for x in sysfiles if str(x.get(\"Signature\", \"\")).lower() not in {\"valid\"}]\n\n        lines = [\n            \"Driver Diagnostics Report\",\n            f\"Generated: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\",\n            \"\",\n            \"Troubleshoot kya kiya:\",\n            \"- driverquery /v output collect kiya.\",\n            \"- Win32_PnPSignedDriver se provider/date/version check kiya.\",\n            \"- .sys driver file signatures check kiye.\",\n            \"\",\n            \"Summary:\",\n            f\"- PnP drivers read: {len(pnp)}\",\n            f\"- Unsigned PnP drivers: {len(unsigned)}\",\n            f\"- Old third-party drivers (&gt;4 years): {len(old)}\",\n            f\"- Suspicious/invalid .sys signatures: {len(bad_sig)}\",\n            \"\",\n            \"Likely BSOD driver clues:\",\n        ]\n        if unsigned:\n            lines.append(\"- Unsigned drivers kernel crash ka risk badhate hain.\")\n        if old:\n            lines.append(\"- Bahut purane third-party drivers Windows update ke baad BSOD de sakte hain.\")\n        if bad_sig:\n            lines.append(\"- Invalid signature .sys file malware/tampering/corruption ka clue ho sakta hai.\")\n        if not (unsigned or old or bad_sig):\n            lines.append(\"- Strong driver risk nahi mila; recent driver changes still verify karein.\")\n        lines.append(\"\")\n        lines.append(\"Unsigned drivers:\")\n        for d in unsigned[:20]:\n            lines.append(f\"- {d.get('DeviceName','')} | {d.get('DriverProviderName','')} | {d.get('DriverVersion','')} | {d.get('InfName','')}\")\n        if not unsigned:\n            lines.append(\"- None detected.\")\n        lines.append(\"\")\n        lines.append(\"Recent third-party drivers:\")\n        for d in recent[:20]:\n            lines.append(f\"- {d.get('DriverDate','')} | {d.get('DeviceName','')} | {d.get('DriverProviderName','')} | {d.get('DriverVersion','')}\")\n        lines.append(\"\")\n        lines.append(\"Driver file signature warnings:\")\n        for f in bad_sig[:20]:\n            lines.append(f\"- {f.get('Signature','')} | {f.get('LastWriteTime','')} | {f.get('FullName','')}\")\n        if not bad_sig:\n            lines.append(\"- None detected.\")\n        lines.append(\"\")\n        lines.append(\"driverquery sample:\")\n        lines.append(driverquery_out[:2500] if driverquery_out else \"driverquery output empty.\")\n        return \"\\n\".join(lines), (\"warning\" if unsigned or old or bad_sig else \"success\")\n\n    def _driver_diagnostics_report(self):\n        self._append_log(self.trouble_log, \"Driver diagnostics started...\", C[\"btn_warn\"])\n        self._launch_job(\"driver_diagnostics_report\", self._do_driver_diagnostics_report)\n\n    def _do_driver_diagnostics_report(self):\n        try:\n            report, severity = self._build_driver_diagnostics_report()\n            color = C[\"warning\"] if severity == \"warning\" else C[\"success\"]\n            self._append_log(self.trouble_log, \"\\n\" + report + \"\\n\", color)\n            self.after(0, lambda: self._show_text_report_window(\"Driver Diagnostics\", report))\n            self.after(0, lambda: self._set_status(\"Driver diagnostics complete\", color))\n        except Exception as e:\n            self._append_log(self.trouble_log, f\"Driver diagnostics failed: {e}\", C[\"error\"])\n\n    def _build_hardware_health_report(self):\n        script = r\"\"\"\n$phys = @()\n$reli = @()\n$disk = @()\n$mem = @()\ntry { $phys = Get-PhysicalDisk | Select FriendlyName,MediaType,HealthStatus,OperationalStatus,Size } catch {}\ntry { $reli = Get-PhysicalDisk | Get-StorageReliabilityCounter | Select DeviceId,Temperature,ReadErrorsTotal,WriteErrorsTotal,Wear,PowerOnHours } catch {}\ntry { $disk = Get-Disk | Select Number,FriendlyName,HealthStatus,OperationalStatus,PartitionStyle,Size } catch {}\ntry {\n    $mem = Get-WinEvent -LogName System -MaxEvents 300 -ErrorAction SilentlyContinue |\n        Where-Object { $_.ProviderName -match 'MemoryDiagnostics|WHEA' } |\n        Select-Object -First 25 @{n='TimeCreated';e={$_.TimeCreated.ToString('s')}},ProviderName,Id,LevelDisplayName,@{n='Message';e={$_.Message}}\n} catch {}\n[pscustomobject]@{PhysicalDisk=$phys;Reliability=$reli;Disk=$disk;HardwareEvents=$mem} | ConvertTo-Json -Depth 5\n\"\"\"\n        out, _ = self._run_powershell(script, timeout=90)\n        wmic_out, _ = self._run_cmd(\"wmic diskdrive get Caption,Model,Status,MediaType,Size /format:list\", timeout=25)\n        smartctl_path = shutil.which(\"smartctl.exe\") or shutil.which(\"smartctl\")\n        smartctl_out = \"\"\n        if smartctl_path:\n            scan, _ = self._run_cmd(f'\"{smartctl_path}\" --scan', timeout=20)\n            smartctl_out += scan + \"\\n\"\n            for ln in scan.splitlines()[:4]:\n                dev = ln.split()[0] if ln.strip() else \"\"\n                if dev:\n                    detail, _ = self._run_cmd(f'\"{smartctl_path}\" -H -A \"{dev}\"', timeout=45)\n                    smartctl_out += f\"\\n--- {dev} ---\\n{detail[:2500]}\\n\"\n        items = self._json_items_from_output(out)\n        payload = items[0] if items else {}\n        warnings = []\n        text_blob = json.dumps(payload, default=str).lower() + \"\\n\" + wmic_out.lower() + \"\\n\" + smartctl_out.lower()\n        for word, msg in [\n            (\"unhealthy\", \"Disk health unhealthy report hua.\"),\n            (\"warning\", \"Disk/hardware warning status mila.\"),\n            (\"pred fail\", \"SMART predicted failure ka clue mila.\"),\n            (\"readerror\", \"Read errors storage surface/controller issue dikha sakte hain.\"),\n            (\"writeerror\", \"Write errors storage media/controller issue dikha sakte hain.\"),\n            (\"whea\", \"WHEA hardware event mila.\"),\n            (\"memorydiagnostics\", \"Memory diagnostic event mila.\"),\n        ]:\n            if word in text_blob:\n                warnings.append(msg)\n        lines = [\n            \"SMART + Hardware Health Report\",\n            f\"Generated: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\",\n            \"\",\n            \"Troubleshoot kya kiya:\",\n            \"- Get-PhysicalDisk, Get-Disk, StorageReliabilityCounter check kiya.\",\n            \"- WMIC diskdrive status collect kiya.\",\n            \"- smartctl available ho to SMART health/attributes read kiye.\",\n            \"- WHEA/MemoryDiagnostics events check kiye.\",\n            \"\",\n            \"Result / warnings:\",\n        ]\n        if warnings:\n            for item in list(dict.fromkeys(warnings)):\n                lines.append(f\"- {item}\")\n        else:\n            lines.append(\"- Strong hardware warning nahi mila, lekin full SMART vendor attributes manually bhi verify karein.\")\n        lines.append(\"\")\n        lines.append(\"PowerShell hardware data:\")\n        lines.append(json.dumps(payload, ensure_ascii=False, indent=2, default=str)[:7000])\n        lines.append(\"\")\n        lines.append(\"WMIC disk status:\")\n        lines.append(wmic_out or \"WMIC output empty.\")\n        lines.append(\"\")\n        lines.append(\"smartctl:\")\n        lines.append(smartctl_out if smartctl_out else \"smartctl installed nahi mila. Install ho to detailed SMART attributes milenge.\")\n        return \"\\n\".join(lines), (\"warning\" if warnings else \"success\")\n\n    def _hardware_health_report(self):\n        self._append_log(self.trouble_log, \"Hardware health report started...\", C[\"hw_accent\"])\n        self._launch_job(\"hardware_health_report\", self._do_hardware_health_report)\n\n    def _do_hardware_health_report(self):\n        try:\n            report, severity = self._build_hardware_health_report()\n            color = C[\"warning\"] if severity == \"warning\" else C[\"success\"]\n            self._append_log(self.trouble_log, \"\\n\" + report + \"\\n\", color)\n            self.after(0, lambda: self._show_text_report_window(\"Hardware Health Report\", report))\n            self.after(0, lambda: self._set_status(\"Hardware health complete\", color))\n        except Exception as e:\n            self._append_log(self.trouble_log, f\"Hardware health failed: {e}\", C[\"error\"])\n\n    def _repair_verification_report(self):\n        if not messagebox.askyesno(\n            \"Repair Verification\",\n            \"Repair verification run karein?\\n\\n\"\n            \"Ye SFC /VERIFYONLY, DISM /ScanHealth aur recent error logs check karega. Time lag sakta hai.\"\n        ):\n            return\n        self._append_log(self.trouble_log, \"Repair verification started...\", C[\"accent2\"])\n        self._set_status(\"Repair verification running...\", C[\"accent2\"])\n        self._launch_job(\"repair_verification_report\", self._do_repair_verification_report)\n\n    def _do_repair_verification_report(self):\n        try:\n            lines = [\n                \"Repair Verification Report\",\n                f\"Generated: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\",\n                \"\",\n                \"Step 1: SFC /VERIFYONLY\",\n            ]\n            sfc, rc_sfc, to_sfc, stop_sfc = self._stream_cmd_to_log([\"sfc\", \"/verifyonly\"], self.trouble_log, timeout_s=1200)\n            lines.append(f\"SFC rc={rc_sfc}, timeout={to_sfc}, stopped={stop_sfc}\")\n            if \"no integrity violations\" in sfc.lower():\n                lines.append(\"SFC Result: Windows protected files clean.\")\n            elif \"integrity violations\" in sfc.lower():\n                lines.append(\"SFC Result: Corruption/violations detected. Run SFC /SCANNOW + DISM RestoreHealth.\")\n            else:\n                lines.append(\"SFC Result: Output manually review karein.\")\n            lines.append(\"\")\n            lines.append(\"Step 2: DISM /ScanHealth\")\n            dism, rc_dism, to_dism, stop_dism = self._stream_cmd_to_log(\n                [\"DISM\", \"/Online\", \"/Cleanup-Image\", \"/ScanHealth\"], self.trouble_log, timeout_s=1800\n            )\n            lines.append(f\"DISM rc={rc_dism}, timeout={to_dism}, stopped={stop_dism}\")\n            if \"no component store corruption detected\" in dism.lower():\n                lines.append(\"DISM Result: Component store clean.\")\n            elif \"repairable\" in dism.lower() or \"corruption\" in dism.lower():\n                lines.append(\"DISM Result: Component store issue detected. RestoreHealth run karein.\")\n            else:\n                lines.append(\"DISM Result: Output manually review karein.\")\n            lines.append(\"\")\n            lines.append(\"Step 3: Recent repair-related events\")\n            events = self._collect_correlation_events()\n            for ev in events[:20]:\n                msg = \" \".join(str(ev.get(\"Message\", \"\") or \"\").split())[:220]\n                lines.append(f\"- {ev.get('TimeCreated','')} | {ev.get('ProviderName','')} | ID {ev.get('Id','')} | {msg}\")\n            report = \"\\n\".join(lines)\n            color = C[\"warning\"] if (\"detected\" in report.lower() and \"clean\" not in report.lower()) else C[\"success\"]\n            self._append_log(self.trouble_log, \"\\n\" + report + \"\\n\", color)\n            self.after(0, lambda: self._show_text_report_window(\"Repair Verification\", report))\n            self.after(0, lambda: self._set_status(\"Repair verification complete\", color))\n        except Exception as e:\n            self._append_log(self.trouble_log, f\"Repair verification failed: {e}\", C[\"error\"])\n            self.after(0, lambda: self._set_status(\"Repair verification failed\", C[\"error\"]))\n\n    def _boot_status_bcd_backup(self):\n        if not messagebox.askyesno(\n            \"Boot Status + BCD Backup\",\n            \"Boot status analyze aur BCD backup create karein?\\n\\n\"\n            \"Ye destructive repair nahi karega. Sirf BCD export + EFI/boot info report banayega.\"\n        ):\n            return\n        self._append_log(self.trouble_log, \"Boot status + BCD backup started...\", C[\"btn_chip\"])\n        self._launch_job(\"boot_status_bcd_backup\", self._do_boot_status_bcd_backup)\n\n    def _do_boot_status_bcd_backup(self):\n        try:\n            os.makedirs(getattr(self, \"backup_dir\", os.getcwd()), exist_ok=True)\n            ts = datetime.datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n            bcd_path = os.path.join(self.backup_dir, f\"BCD_Backup_{ts}.bcd\")\n            enum_out, _ = self._run_cmd([\"bcdedit\", \"/enum\", \"all\"], timeout=40)\n            export_out, rc_export = self._run_cmd([\"bcdedit\", \"/export\", bcd_path], timeout=40)\n            ps = r\"\"\"\n$efi = @()\ntry { $efi = Get-Partition | Where-Object {$_.GptType -match 'c12a7328'} | Select DiskNumber,PartitionNumber,DriveLetter,Size,GptType } catch {}\n$firm = $env:firmware_type\n[pscustomobject]@{Firmware=$firm;EfiPartitions=$efi} | ConvertTo-Json -Depth 4\n\"\"\"\n            efi_out, _ = self._run_powershell(ps, timeout=30)\n            lines = [\n                \"Boot Status + BCD Backup Report\",\n                f\"Generated: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\",\n                f\"BCD backup: {bcd_path if rc_export == 0 else 'FAILED'}\",\n                f\"bcdedit export rc={rc_export}\",\n                \"\",\n                \"EFI / firmware info:\",\n                efi_out.strip() or \"EFI info unavailable.\",\n                \"\",\n                \"bcdedit /enum all:\",\n                enum_out[:9000] if enum_out else \"bcdedit output empty.\",\n                \"\",\n                \"Solution guidance:\",\n                \"- Agar boot fail hai aur BCD corrupt lag raha hai, WinRE me bootrec/bcdboot use karein.\",\n                \"- EFI system me bcdboot C:\\\\Windows /s : /f UEFI carefully use hota hai.\",\n                \"- Advanced boot repair se pehle backup aur exact Windows/EFI drive letters verify karein.\",\n            ]\n            report = \"\\n\".join(lines)\n            self._append_log(self.trouble_log, \"\\n\" + report + \"\\n\", C[\"success\"] if rc_export == 0 else C[\"warning\"])\n            self.after(0, lambda: self._show_text_report_window(\"Boot Status + BCD Backup\", report))\n            self.after(0, lambda: self._set_status(\"Boot status complete\", C[\"success\"] if rc_export == 0 else C[\"warning\"]))\n        except Exception as e:\n            self._append_log(self.trouble_log, f\"Boot status failed: {e}\", C[\"error\"])\n\n    def _offline_repair_dialog(self):\n        win_dir = filedialog.askdirectory(title=\"Offline Windows folder select karo (example: D:\\\\Windows)\")\n        if not win_dir:\n            return\n        if os.path.basename(win_dir).lower() != \"windows\":\n            if not messagebox.askyesno(\"Confirm Folder\", f\"Selected folder Windows naam ka nahi hai:\\n{win_dir}\\n\\nContinue?\"):\n                return\n        image_root = os.path.dirname(win_dir.rstrip(\"\\\\/\"))\n        boot_dir = os.path.splitdrive(image_root)[0] + \"\\\\\"\n        if not messagebox.askyesno(\n            \"Offline SFC/DISM\",\n            f\"Offline repair commands run karein?\\n\\n\"\n            f\"Offbootdir: {boot_dir}\\n\"\n            f\"Offwindir: {win_dir}\\n\"\n            f\"DISM Image: {image_root}\\n\\n\"\n            \"Mounted/offline Windows path galat hua to command fail ho sakti hai.\"\n        ):\n            return\n        self._append_log(self.trouble_log, f\"Offline repair started: {win_dir}\", C[\"btn_info\"])\n        self._launch_job(\"offline_repair\", self._do_offline_repair, boot_dir, win_dir, image_root)\n\n    def _do_offline_repair(self, boot_dir, win_dir, image_root):\n        try:\n            cmds = [\n                [\"sfc\", \"/scannow\", f\"/offbootdir={boot_dir}\", f\"/offwindir={win_dir}\"],\n                [\"DISM\", f\"/Image:{image_root}\", \"/Cleanup-Image\", \"/ScanHealth\"],\n                [\"DISM\", f\"/Image:{image_root}\", \"/Cleanup-Image\", \"/RestoreHealth\"],\n            ]\n            lines = [\"Offline Repair Report\", f\"Generated: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\"]\n            for cmd in cmds:\n                lines.append(\"\")\n                lines.append(f\"Command: {subprocess.list2cmdline(cmd)}\")\n                out, rc, timed_out, stopped = self._stream_cmd_to_log(cmd, self.trouble_log, timeout_s=3600)\n                lines.append(f\"rc={rc}, timeout={timed_out}, stopped={stopped}\")\n                lines.append(out[-1200:] if out else \"No output\")\n            report = \"\\n\".join(lines)\n            self._append_log(self.trouble_log, \"\\n\" + report + \"\\n\", C[\"success\"])\n            self.after(0, lambda: self._show_text_report_window(\"Offline Repair Report\", report))\n            self.after(0, lambda: self._set_status(\"Offline repair complete\", C[\"success\"]))\n        except Exception as e:\n            self._append_log(self.trouble_log, f\"Offline repair failed: {e}\", C[\"error\"])\n\n    def _build_security_startup_report(self):\n        script = r\"\"\"\n$items = @()\n$keys = @(\n 'HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Run',\n 'HKLM:\\Software\\Microsoft\\Windows\\CurrentVersion\\Run',\n 'HKLM:\\Software\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Run',\n 'HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows',\n 'HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon',\n 'HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\AppCertDlls',\n 'HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options'\n)\nforeach($k in $keys) {\n if(Test-Path $k) {\n   try {\n     $props = Get-ItemProperty $k -ErrorAction SilentlyContinue\n     foreach($p in $props.PSObject.Properties) {\n       if($p.Name -match '^PS') { continue }\n       $items += [pscustomobject]@{Location=$k;Name=$p.Name;Value=[string]$p.Value}\n     }\n   } catch {}\n }\n}\n$tasks = @()\ntry {\n $tasks = Get-ScheduledTask -ErrorAction SilentlyContinue |\n   Where-Object { ($_.TaskPath -notmatch '\\\\Microsoft\\\\Windows\\\\') -or (($_.Actions | Out-String) -match 'AppData|Temp|rundll32|powershell|wscript|cscript') } |\n   Select-Object -First 80 TaskPath,TaskName,State,@{n='Action';e={($_.Actions | Out-String).Trim()}}\n} catch {}\n[pscustomobject]@{Registry=$items;Tasks=$tasks} | ConvertTo-Json -Depth 5\n\"\"\"\n        out, _ = self._run_powershell(script, timeout=80)\n        hosts = \"\"\n        try:\n            hosts_path = r\"C:\\Windows\\System32\\drivers\\etc\\hosts\"\n            if os.path.exists(hosts_path):\n                with open(hosts_path, \"r\", encoding=\"utf-8\", errors=\"replace\") as f:\n                    hosts = f.read()[:6000]\n        except Exception as e:\n            hosts = f\"hosts read failed: {e}\"\n        items = self._json_items_from_output(out)\n        payload = items[0] if items else {}\n        reg = payload.get(\"Registry\", []) if isinstance(payload, dict) else []\n        tasks = payload.get(\"Tasks\", []) if isinstance(payload, dict) else []\n        if isinstance(reg, dict):\n            reg = [reg]\n        if isinstance(tasks, dict):\n            tasks = [tasks]\n        risky = []\n        for row in reg:\n            val = str(row.get(\"Value\", \"\"))\n            loc = str(row.get(\"Location\", \"\"))\n            name = str(row.get(\"Name\", \"\"))\n            low = f\"{loc} {name} {val}\".lower()\n            if any(x in low for x in [\"appinit_dlls\", \"debugger\", \"appdata\", \"\\\\temp\\\\\", \"rundll32\", \"powershell\", \"wscript\", \"cscript\", \".dll\"]):\n                risky.append(row)\n        lines = [\n            \"Security + Startup Analysis Report\",\n            f\"Generated: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\",\n            \"\",\n            \"Troubleshoot kya kiya:\",\n            \"- Run/RunOnce, AppInit_DLLs, Winlogon, IFEO Debugger keys inspect ki.\",\n            \"- Non-Microsoft/suspicious Scheduled Tasks check kiye.\",\n            \"- hosts file inspect kiya.\",\n            \"\",\n            \"Summary:\",\n            f\"- Registry autorun items: {len(reg)}\",\n            f\"- Risky autorun indicators: {len(risky)}\",\n            f\"- Scheduled task indicators: {len(tasks)}\",\n            \"\",\n            \"Risky registry indicators:\",\n        ]\n        for r in risky[:30]:\n            lines.append(f\"- {r.get('Location','')} | {r.get('Name','')} | {r.get('Value','')}\")\n        if not risky:\n            lines.append(\"- None detected.\")\n        lines.append(\"\")\n        lines.append(\"Scheduled task indicators:\")\n        for t in tasks[:25]:\n            action = \" \".join(str(t.get(\"Action\", \"\")).split())[:220]\n            lines.append(f\"- {t.get('TaskPath','')}{t.get('TaskName','')} | {t.get('State','')} | {action}\")\n        if not tasks:\n            lines.append(\"- None detected.\")\n        lines.append(\"\")\n        lines.append(\"hosts file sample:\")\n        lines.append(hosts if hosts else \"hosts empty/unavailable.\")\n        lines.append(\"\")\n        lines.append(\"Solution:\")\n        lines.append(\"- Unknown AppData/Temp/rundll32/powershell startup entries ko disable karke reboot test karo.\")\n        lines.append(\"- IFEO Debugger/AppInit_DLLs entries malware persistence ka strong clue ho sakte hain.\")\n        lines.append(\"- Defender Offline Scan + SFC/DISM run karo agar suspicious injection indicator mile.\")\n        return \"\\n\".join(lines), (\"warning\" if risky or tasks else \"success\")\n\n    def _security_startup_report(self):\n        self._append_log(self.trouble_log, \"Security autorun analysis started...\", C[\"btn_warn\"])\n        self._launch_job(\"security_startup_report\", self._do_security_startup_report)\n\n    def _do_security_startup_report(self):\n        try:\n            report, severity = self._build_security_startup_report()\n            color = C[\"warning\"] if severity == \"warning\" else C[\"success\"]\n            self._append_log(self.trouble_log, \"\\n\" + report + \"\\n\", color)\n            self.after(0, lambda: self._show_text_report_window(\"Security Startup Analysis\", report))\n            self.after(0, lambda: self._set_status(\"Security analysis complete\", color))\n        except Exception as e:\n            self._append_log(self.trouble_log, f\"Security analysis failed: {e}\", C[\"error\"])\n\n    def _diagnostic_zip_package(self):\n        path = filedialog.asksaveasfilename(\n            defaultextension=\".zip\",\n            filetypes=[(\"ZIP package\", \"*.zip\")],\n            initialfile=\"Godawari_Diagnostic_Package.zip\",\n            title=\"Save diagnostic package\"\n        )\n        if not path:\n            return\n        if not messagebox.askyesno(\"Diagnostic ZIP\", \"HTML/JSON/TXT diagnostic package generate karein? Kuch checks time le sakte hain.\"):\n            return\n        self._append_log(self.trouble_log, \"Diagnostic ZIP generation started...\", C[\"accent\"])\n        self._launch_job(\"diagnostic_zip_package\", self._do_diagnostic_zip_package, path)\n\n    def _do_diagnostic_zip_package(self, zip_path):\n        try:\n            reports = {}\n            builders = [\n                (\"bsod_report\", self._build_bsod_deep_report),\n                (\"rundll32_kernel32_report\", self._build_rundll32_report),\n                (\"event_correlation\", self._build_event_correlation_report),\n                (\"driver_diagnostics\", self._build_driver_diagnostics_report),\n                (\"hardware_health\", self._build_hardware_health_report),\n                (\"security_startup\", self._build_security_startup_report),\n            ]\n            for name, fn in builders:\n                try:\n                    result = fn()\n                    reports[name] = result[0] if isinstance(result, tuple) else str(result)\n                    self._append_log(self.trouble_log, f\"Report built: {name}\", C[\"text_dim\"])\n                except Exception as e:\n                    reports[name] = f\"FAILED: {e}\"\n            payload = {\n                \"generated\": datetime.datetime.now().isoformat(timespec=\"seconds\"),\n                \"computer\": platform.node(),\n                \"reports\": reports,\n            }\n            html_body = \"Godawari Diagnostic Package\"\n            html_body += \"\nGodawari Diagnostic Package\"\n            for name, text in reports.items():\n                html_body += f\"\n{html.escape(name)}\n{html.escape(text)}\"\n            html_body += \"\"\n            with zipfile.ZipFile(zip_path, \"w\", zipfile.ZIP_DEFLATED) as z:\n                z.writestr(\"diagnostics.json\", json.dumps(payload, ensure_ascii=False, indent=2, default=str))\n                z.writestr(\"diagnostics.html\", html_body)\n                for name, text in reports.items():\n                    z.writestr(f\"{name}.txt\", text)\n                try:\n                    z.writestr(\"current_repair_log.txt\", self.trouble_log.get(\"1.0\", \"end\"))\n                except Exception:\n                    pass\n            self._append_log(self.trouble_log, f\"Diagnostic ZIP saved: {zip_path}\", C[\"success\"])\n            self.after(0, lambda: messagebox.showinfo(\"Diagnostic ZIP\", f\"Saved:\\n{zip_path}\"))\n        except Exception as e:\n            self._append_log(self.trouble_log, f\"Diagnostic ZIP failed: {e}\", C[\"error\"])\n\n    def _build_power(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\u26a1 Power Plan\", \"Change power scheme + Hibernate\")\n        self._action_card_grid(frame, [\n            (\"\ud83d\udd0b\", \"High Performance\",           \"Max speed, zyada bijli\",              C[\"btn_danger\"], lambda: self._set_power(\"8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c\")),\n            (\"\u26a1\", \"Balanced\",                   \"Speed aur battery balance\",           C[\"btn_info\"],   lambda: self._set_power(\"381b4222-f694-41f0-9685-ff5bb260df2e\")),\n            (\"\ud83c\udf3f\", \"Power Saver\",                \"Battery bachao, speed kam\",           C[\"btn\"],        lambda: self._set_power(\"a1841308-3541-4fab-bc81-f71556f20b4a\")),\n            (\"\ud83c\udf19\", \"Disable Hibernate\",          \"Hibernate + Fast Startup band karo\",  C[\"btn_warn\"],   self._disable_hibernate),\n        ], cols=4)\n        content = tk.Frame(frame, bg=C[\"card\"])\n        content.pack(fill=\"x\", padx=16, pady=(4, 10))\n        self.power_status = tk.Label(content, text=\"\", font=FONTS[\"body\"], fg=C[\"accent2\"], bg=C[\"card\"])\n        self.power_status.pack(pady=10)\n        self._refresh_power_status()\n        return frame\n\n    def _refresh_power_status(self):\n        out, _ = self._run_cmd('powercfg /getactivescheme')\n        self.power_status.config(text=f\"Current: {out.strip() if out else 'Unknown'}\")\n        self.after(5000, self._refresh_power_status)\n\n    def _set_power(self, guid):\n        if messagebox.askyesno(\"Set Power Plan\", f\"Set active power plan to {guid}?\"):\n            self._run_cmd(f'powercfg /setactive {guid}')\n            self._refresh_power_status()\n\n    def _disable_hibernate(self):\n        if messagebox.askyesno(\"Disable Hibernate\", \"Turn off hibernate and fast startup? This frees disk space but makes boot slightly slower.\"):\n            self._run_cmd('powercfg -h off')\n            self._append_log(self.power_status.master, \"\u2705 Hibernate disabled + hiberfil.sys removed\", C[\"success\"])\n            self._run_cmd('REG ADD \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Session Manager\\\\Power\" /v HiberbootEnabled /t REG_DWORD /d 0 /f')\n            self._append_log(self.power_status.master, \"\u2705 Fast Startup disabled\", C[\"success\"])\n\n    # ---------- FILE RECOVERY ----------\n    def _build_recovery_safe(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n\n        # \u2500\u2500 Fixed header (outside scroll) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        self._section_header(\n            frame, \"\ud83d\udcc2 File Search &amp; Recovery\",\n            \"Zone A = maujood files dhundo | Zone B = deleted files sector se recover karo\")\n\n        # \u2500\u2500 Scrollable body \u2014 app ka built-in method use karo \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        # _scrollable_section_body returns an inner frame with canvas+scrollbar+\n        # scoped mousewheel already wired \u2014 no conflict with other menus.\n        frame_scroll = self._scrollable_section_body(frame)\n\n        zone_a = tk.Frame(frame_scroll, bg=C[\"card\"], highlightbackground=C[\"accent2\"], highlightthickness=2)\n        zone_a.pack(fill=\"x\", padx=16, pady=(4, 6))\n        tk.Label(zone_a, text=\"\ud83d\udd0d Zone A \u2014 Search Existing Files\",\n                 font=FONTS[\"subhead\"], fg=C[\"accent2\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=12, pady=(8, 2))\n        tk.Label(zone_a,\n                 text=\"Drive pe jo files abhi bhi maujood hain unhe dhundta hai (fast, no admin needed).\\n\"\n                      \"Deleted files ke liye Zone B use karo.\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\").pack(anchor=\"w\", padx=12, pady=(0, 6))\n\n        row_inputs = tk.Frame(zone_a, bg=C[\"card\"])\n        row_inputs.pack(fill=\"x\", padx=8, pady=4)\n        tk.Label(row_inputs, text=\"Drive:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\", padx=(0, 4))\n        drive_values = [f\"{d}\\\\\" for d in \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\" if os.path.exists(f\"{d}:\\\\\")]\n        drive_values += [\"Android\"]\n        self.rec_drive = ttk.Combobox(row_inputs, values=drive_values, width=10, font=FONTS[\"body\"], state=\"readonly\")\n        self.rec_drive.set(\"C:\\\\\")\n        self.rec_drive.pack(side=\"left\", padx=4)\n        tk.Label(row_inputs, text=\"File Types:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\", padx=(8, 4))\n        self.rec_ext = tk.Entry(row_inputs, width=30, font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"],\n                                insertbackground=C[\"text\"])\n        self.rec_ext.insert(0, \"jpg,png,pdf,docx\")\n        self.rec_ext.pack(side=\"left\", padx=4)\n        tk.Label(row_inputs, text=\"Quick:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\", padx=(8, 2))\n        for label, exts in [(\"Photos\", \"jpg,jpeg,png,bmp,gif\"), (\"Docs\", \"pdf,docx,xlsx,pptx,txt\"),\n                            (\"Videos\", \"mp4,avi,mkv,mov\"), (\"All\", \"jpg,png,pdf,docx,mp4,xlsx\")]:\n            tk.Button(row_inputs, text=label, font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text_dim\"],\n                      bd=0, padx=6, pady=2, cursor=\"hand2\",\n                      command=lambda e=exts: (self.rec_ext.delete(0, \"end\"), self.rec_ext.insert(0, e))).pack(side=\"left\", padx=2)\n\n        row_actions = tk.Frame(zone_a, bg=C[\"card\"])\n        row_actions.pack(fill=\"x\", padx=8, pady=(4, 4))\n        tk.Button(row_actions, text=\"\ud83d\udd0d Search Drive\",\n                  font=(\"Segoe UI\", 10, \"bold\"), bg=C[\"accent2\"], fg=\"#000\",\n                  bd=0, padx=16, pady=6, cursor=\"hand2\",\n                  command=self._start_file_recovery).pack(side=\"left\", padx=4)\n        self._rec_stop_btn = tk.Button(row_actions, text=\"\u23f9 Stop\", font=FONTS[\"body\"],\n            bg=C[\"btn_danger\"], fg=C[\"text\"], bd=0, padx=10, pady=5,\n            cursor=\"hand2\", state=\"disabled\", command=self._stop_file_recovery)\n        self._rec_stop_btn.pack(side=\"left\", padx=4)\n        self._rec_pause_btn = tk.Button(row_actions, text=\"\u23f8 Pause\", font=FONTS[\"body\"],\n            bg=C[\"btn_warn\"], fg=C[\"text\"], bd=0, padx=10, pady=5,\n            cursor=\"hand2\", state=\"disabled\", command=self._pause_resume_file_recovery)\n        self._rec_pause_btn.pack(side=\"left\", padx=4)\n\n        row_android = tk.Frame(zone_a, bg=C[\"card\"])\n        row_android.pack(fill=\"x\", padx=8, pady=(0, 8))\n        tk.Label(row_android, text=\"\ud83d\udcf1 Android:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\", padx=(0, 6))\n        tk.Button(row_android, text=\"DCIM Photos Backup\", font=FONTS[\"small\"],\n                  bg=C[\"btn_chip\"], fg=C[\"text\"], bd=0, padx=10, pady=4, cursor=\"hand2\",\n                  command=lambda: self._android_media_preset(\"dcim\")).pack(side=\"left\", padx=3)\n        tk.Button(row_android, text=\"WhatsApp Media\", font=FONTS[\"small\"],\n                  bg=C[\"btn_chip\"], fg=C[\"text\"], bd=0, padx=10, pady=4, cursor=\"hand2\",\n                  command=lambda: self._android_media_preset(\"whatsapp\")).pack(side=\"left\", padx=3)\n        self.adb_status_label = tk.Label(row_android, text=\"ADB Status: Checking...\",\n                                         font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"])\n        self.adb_status_label.pack(side=\"right\", padx=8)\n        tk.Button(row_android, text=\"ADB Refresh\", font=FONTS[\"small\"],\n                  bg=C[\"btn\"], fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=self._refresh_adb_status_label).pack(side=\"right\", padx=3)\n        self.after(150, self._refresh_adb_status_label)\n\n        zone_b = tk.Frame(frame_scroll, bg=C[\"card\"], highlightbackground=C[\"warning\"], highlightthickness=2)\n        zone_b.pack(fill=\"x\", padx=16, pady=(0, 6))\n        tk.Label(zone_b, text=\"\u26a1 Zone B \u2014 Recover Deleted Files (Admin Required)\",\n                 font=FONTS[\"subhead\"], fg=C[\"warning\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=12, pady=(8, 2))\n        tk.Label(zone_b,\n                 text=\"Disk ke sectors seedha scan karta hai. Formatted ya deleted files wapas la sakta hai.\\n\"\n                      \"Admin rights mandatory hain. Recovered data ALAG drive pe save karo.\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\").pack(anchor=\"w\", padx=12, pady=(0, 6))\n\n        row_source = tk.Frame(zone_b, bg=C[\"card\"])\n        row_source.pack(fill=\"x\", padx=8, pady=(0, 4))\n        tk.Label(row_source, text=\"Raw Source:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\", padx=4)\n        raw_values = [DEFAULT_RAW_DISK] + [\"\\\\\\\\.\\\\\" + d + \":\" for d in \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\" if os.path.exists(d + \":\\\\\")]\n        self.raw_disk_var = tk.StringVar(value=DEFAULT_RAW_DISK)\n        self.raw_disk_combo = ttk.Combobox(row_source, values=raw_values, textvariable=self.raw_disk_var, width=22, font=FONTS[\"body\"], state=\"readonly\")\n        self.raw_disk_combo.pack(side=\"left\", padx=4)\n        self.raw_source_badge = tk.Label(row_source, text=\"RAW DEVICE\", font=FONTS[\"small\"], fg=C[\"warning\"], bg=C[\"card\"])\n        self.raw_source_badge.pack(side=\"left\", padx=6)\n        self.raw_disk_combo.bind(\"&lt;&gt;\", lambda e: self._update_raw_source_badge())\n        self.raw_disk_combo.bind(\"\", lambda e: self._update_raw_source_badge())\n        tk.Label(row_source, text=\"Scan MB (0=Full):\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\", padx=(8, 2))\n        self.raw_scan_mb = tk.Entry(row_source, width=6, font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"])\n        self.raw_scan_mb.insert(0, \"0\")\n        self.raw_scan_mb.pack(side=\"left\", padx=2)\n        tk.Label(row_source, text=\"Start Sector:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\", padx=(8, 2))\n        self.raw_sector_num = tk.Entry(row_source, width=8, font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"])\n        self.raw_sector_num.insert(0, \"0\")\n        self.raw_sector_num.pack(side=\"left\", padx=2)\n\n        row_primary = tk.Frame(zone_b, bg=C[\"card\"])\n        row_primary.pack(fill=\"x\", padx=8, pady=(4, 2))\n        for label, color, cmd in [\n            (\"\u2705 AUTO Recovery (Recommended)\", C[\"accent2\"], self._start_auto_raw_recovery),\n            (\"\u26a1 Raw Signature Scan\", C[\"btn_danger\"], self._start_raw_signature_scan),\n            (\"\ud83d\udd0e PhotoRec Deep Scan\", C[\"btn_hw\"], self._start_photorec_deep_scan),\n        ]:\n            tk.Button(row_primary, text=label, font=FONTS[\"small\"], bg=color,\n                      fg=C[\"bg\"] if color == C[\"accent2\"] else C[\"text\"],\n                      bd=0, padx=12, pady=6, cursor=\"hand2\", command=cmd).pack(side=\"left\", padx=3, pady=2)\n\n        tk.Label(zone_b, text=\"Advanced forensic tools:\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=12, pady=(4, 0))\n        row_advanced = tk.Frame(zone_b, bg=C[\"card\"])\n        row_advanced.pack(fill=\"x\", padx=8, pady=(2, 8))\n        for label, color, cmd in [\n            (\"DMDE\", C[\"btn_info\"], self._start_dmde_recovery),\n            (\"Create IMG\", C[\"btn_warn\"], self._create_img_dialog),\n            (\"Import IMG\", C[\"btn_info\"], self._select_img_source),\n            (\"Hex Viewer\", C[\"btn_chip\"], self._show_raw_hex_dialog),\n            (\"Shadow Copies\", C[\"accent2\"], self._shadow_copy_recovery_report),\n            (\"Hash+Verify\", C[\"btn_warn\"], self._forensic_hash_verify_dialog),\n            (\"Session Save\", C[\"btn_chip\"], self._recovery_session_db_save),\n        ]:\n            tk.Button(row_advanced, text=label, font=FONTS[\"small\"], bg=color, fg=C[\"text\"],\n                      bd=0, padx=8, pady=4, cursor=\"hand2\", command=cmd).pack(side=\"left\", padx=3, pady=2)\n\n        prog = tk.Frame(frame_scroll, bg=C[\"card\"], highlightbackground=C[\"border\"], highlightthickness=1)\n        prog.pack(fill=\"x\", padx=16, pady=(0, 6))\n        self.scan_mode_label = tk.Label(prog, text=\"Mode: \u2014\",\n            font=FONTS[\"small\"], fg=C[\"accent4\"], bg=C[\"card\"])\n        self.scan_mode_label.pack(fill=\"x\", padx=12, pady=(10, 2))\n        self.raw_progress_label = tk.Label(prog, text=\"Ready \u2014 scan shuru karo\",\n                                           font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], anchor=\"w\")\n        self.raw_progress_label.pack(fill=\"x\", padx=12, pady=(0, 2))\n        self.hdd_resource_delta_lbl = tk.Label(prog, text=\"Memory Delta: --\",\n                                               font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], anchor=\"w\")\n        self.hdd_resource_delta_lbl.pack(fill=\"x\", padx=12, pady=(0, 2))\n        self.raw_progress_var = tk.DoubleVar(value=0)\n        self.raw_progress_bar = ttk.Progressbar(prog, variable=self.raw_progress_var, maximum=100, mode=\"determinate\")\n        self.raw_progress_bar.pack(fill=\"x\", padx=12, pady=(0, 4))\n        self.raw_progress_log = scrolledtext.ScrolledText(prog, height=5, font=FONTS[\"mono\"],\n                                                           bg=C[\"bg\"], fg=C[\"text\"],\n                                                           insertbackground=C[\"text\"], wrap=\"word\",\n                                                           state=\"disabled\", bd=0)\n        self.raw_progress_log.pack(fill=\"x\", padx=12, pady=(0, 4))\n        prog_btns = tk.Frame(prog, bg=C[\"card\"])\n        prog_btns.pack(fill=\"x\", padx=12, pady=(0, 10))\n        tk.Button(prog_btns, text=\"\ud83d\uddd1 Clear Log\", font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text_dim\"],\n                  bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=self._clear_recovery_progress_log).pack(side=\"left\")\n\n        results_outer = tk.Frame(frame_scroll, bg=C[\"card\"], highlightbackground=C[\"border\"], highlightthickness=1)\n        results_outer.pack(fill=\"x\", padx=16, pady=(0, 10))\n        results_hdr = tk.Frame(results_outer, bg=C[\"card\"])\n        results_hdr.pack(fill=\"x\", padx=12, pady=(10, 4))\n        tk.Label(results_hdr, text=\"\u2463 Milne wali / Recovered files:\",\n                 font=FONTS[\"small\"], fg=C[\"accent2\"], bg=C[\"card\"]).pack(side=\"left\")\n        self.rec_stats_label = tk.Label(results_hdr, text=\"0 files found | 0 selected\",\n            font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"])\n        self.rec_stats_label.pack(side=\"right\")\n\n        tree_wrap = tk.Frame(results_outer, bg=C[\"card\"])\n        tree_wrap.pack(fill=\"both\", expand=True, padx=12, pady=(0, 4))\n        rec_cols = (\"Filename\", \"Type\", \"Size\", \"Status\", \"Location\", \"Integrity\")\n        col_heads = (\"File Name\", \"Type\", \"Size\", \"Status\", \"Location / Sector\", \"Integrity\")\n        self.rec_tree = ttk.Treeview(tree_wrap, columns=rec_cols, show=\"headings\", height=14, style=\"Custom.Treeview\")\n        for col, head, w in zip(rec_cols, col_heads, (230, 55, 90, 145, 230, 75)):\n            self.rec_tree.heading(col, text=head)\n            self.rec_tree.column(col, width=w, anchor=\"w\")\n        self.rec_tree.tag_configure(\"recovered\", foreground=C[\"success\"])\n        self.rec_tree.tag_configure(\"partial\", foreground=C[\"warning\"])\n        self.rec_tree.tag_configure(\"found\", foreground=C[\"text\"])\n        yscroll = ttk.Scrollbar(tree_wrap, orient=\"vertical\", command=self.rec_tree.yview)\n        xscroll = ttk.Scrollbar(tree_wrap, orient=\"horizontal\", command=self.rec_tree.xview)\n        self.rec_tree.configure(yscrollcommand=yscroll.set, xscrollcommand=xscroll.set)\n        self.rec_tree.grid(row=0, column=0, sticky=\"nsew\")\n        yscroll.grid(row=0, column=1, sticky=\"ns\")\n        xscroll.grid(row=1, column=0, sticky=\"ew\")\n        tree_wrap.grid_rowconfigure(0, weight=1)\n        tree_wrap.grid_columnconfigure(0, weight=1)\n        self.rec_tree.bind(\"&lt;&gt;\", self._on_rec_select)\n\n        results_bar = tk.Frame(results_outer, bg=C[\"card\"])\n        results_bar.pack(fill=\"x\", padx=12, pady=(0, 10))\n        self._rec_recover_btn = tk.Button(results_bar, text=\"\ud83d\udcbe Recover Selected\",\n                  font=FONTS[\"body\"], bg=C[\"btn_info\"], fg=C[\"text\"],\n                  bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=self._recover_selected_files)\n        self._rec_recover_btn.pack(side=\"left\", padx=(0, 8))\n        tk.Button(results_bar, text=\"\ud83d\udccb Select All\", font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text\"],\n                  bd=0, padx=10, pady=5, cursor=\"hand2\",\n                  command=lambda: self.rec_tree.selection_set(self.rec_tree.get_children())).pack(side=\"left\", padx=(0, 8))\n        tk.Button(results_bar, text=\"\ud83d\uddd1 Clear List\", font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text_dim\"],\n                  bd=0, padx=10, pady=5, cursor=\"hand2\",\n                  command=self._clear_recovery_results).pack(side=\"left\")\n\n        self.rec_found_files = {}\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # \u2500\u2500 ZONE C \u2500\u2500 Batch Integrity Verifier (NEW FEATURE #1) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        # Real SHA256 hash computation on recovered/existing files.\n        # Runs fully in background thread, 0 fake logic, real OS file reads.\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        zone_c = tk.Frame(frame_scroll, bg=C[\"card\"],\n                          highlightbackground=C.get(\"accent4\", \"#9b59b6\"),\n                          highlightthickness=2)\n        zone_c.pack(fill=\"x\", padx=16, pady=(0, 6))\n        tk.Label(zone_c, text=\"\ud83d\udd10 Zone C \u2014 Batch Integrity Verifier  (SHA256 real-time)\",\n                 font=FONTS[\"subhead\"], fg=C.get(\"accent4\", \"#9b59b6\"), bg=C[\"card\"]\n                 ).pack(anchor=\"w\", padx=12, pady=(8, 2))\n        tk.Label(zone_c,\n                 text=\"Recovered ya kisi bhi folder ki files ko real SHA256 hash se verify karta hai.\\n\"\n                      \"Corrupt / 0-byte / truncated files automatically flag ho jaate hain.\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\"\n                 ).pack(anchor=\"w\", padx=12, pady=(0, 6))\n\n        zc_row1 = tk.Frame(zone_c, bg=C[\"card\"]); zc_row1.pack(fill=\"x\", padx=8, pady=4)\n        tk.Label(zc_row1, text=\"Folder:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\", padx=(0,4))\n        self._integ_dir_var = tk.StringVar()\n        tk.Entry(zc_row1, textvariable=self._integ_dir_var, width=42,\n                 font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"],\n                 insertbackground=C[\"text\"]).pack(side=\"left\", padx=4)\n        tk.Button(zc_row1, text=\"\ud83d\udcc1 Browse\", font=FONTS[\"small\"],\n                  bg=C[\"panel\"], fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=lambda: self._integ_dir_var.set(\n                      filedialog.askdirectory(title=\"Verify karne ka folder\")\n                  )).pack(side=\"left\", padx=4)\n        tk.Button(zc_row1, text=\"\ud83d\udcc2 Use Recovery Dest\", font=FONTS[\"small\"],\n                  bg=C[\"btn_chip\"], fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=lambda: self._integ_use_rec_dest()).pack(side=\"left\", padx=4)\n\n        zc_row2 = tk.Frame(zone_c, bg=C[\"card\"]); zc_row2.pack(fill=\"x\", padx=8, pady=(0,4))\n        self._integ_recurse_var = tk.BooleanVar(value=True)\n        tk.Checkbutton(zc_row2, text=\"Subfolders include\", variable=self._integ_recurse_var,\n                       font=FONTS[\"small\"], bg=C[\"card\"], fg=C[\"text\"],\n                       selectcolor=C[\"bg\"], activebackground=C[\"card\"]).pack(side=\"left\", padx=4)\n        self._integ_export_var = tk.BooleanVar(value=True)\n        tk.Checkbutton(zc_row2, text=\"CSV report export\", variable=self._integ_export_var,\n                       font=FONTS[\"small\"], bg=C[\"card\"], fg=C[\"text\"],\n                       selectcolor=C[\"bg\"], activebackground=C[\"card\"]).pack(side=\"left\", padx=4)\n\n        zc_stats_row = tk.Frame(zone_c, bg=C[\"card\"]); zc_stats_row.pack(fill=\"x\", padx=8)\n        self._integ_stat_lbl = tk.Label(zc_stats_row, text=\"\u2014 Ready \u2014\",\n                                        font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], anchor=\"w\")\n        self._integ_stat_lbl.pack(side=\"left\", fill=\"x\", expand=True)\n        self._integ_prog_var = tk.DoubleVar(value=0)\n        zc_pb = ttk.Progressbar(zone_c, variable=self._integ_prog_var, maximum=100, mode=\"determinate\")\n        zc_pb.pack(fill=\"x\", padx=12, pady=(2, 2))\n        self._integ_prog_bar = zc_pb\n\n        # Scrollable log sub-frame inside Zone C (Phase 2 requirement)\n        self._integ_log = scrolledtext.ScrolledText(zone_c, height=4, font=FONTS[\"mono\"],\n                                                    bg=C[\"bg\"], fg=C[\"text\"],\n                                                    insertbackground=C[\"text\"], wrap=\"word\",\n                                                    state=\"disabled\", bd=0)\n        self._integ_log.pack(fill=\"x\", padx=12, pady=(0, 4))\n\n        zc_btn_row = tk.Frame(zone_c, bg=C[\"card\"]); zc_btn_row.pack(fill=\"x\", padx=8, pady=(0,8))\n        self._integ_run_btn = tk.Button(\n            zc_btn_row, text=\"\ud83d\udd10 Run Integrity Check\",\n            font=(\"Segoe UI\", 10, \"bold\"),\n            bg=C.get(\"accent4\", \"#9b59b6\"), fg=C[\"text\"],\n            bd=0, padx=16, pady=6, cursor=\"hand2\",\n            command=self._start_integrity_verifier)\n        self._integ_run_btn.pack(side=\"left\", padx=4)\n        tk.Button(zc_btn_row, text=\"\ud83d\uddd1 Clear Log\", font=FONTS[\"small\"],\n                  bg=C[\"panel\"], fg=C[\"text_dim\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=lambda: (\n                      self._integ_log.config(state=\"normal\"),\n                      self._integ_log.delete(\"1.0\", \"end\"),\n                      self._integ_log.config(state=\"disabled\"),\n                      self._integ_stat_lbl.config(text=\"\u2014 Cleared \u2014\"),\n                      self._integ_prog_var.set(0),\n                  )).pack(side=\"left\", padx=4)\n\n        return frame\n\n    def _build_recovery_fixed(self, parent):\n        return self._build_recovery_safe(parent)\n\n    def _show_rescue_center(self):\n        try:\n            self._launch_job(\"refresh_rescue_status\", self._refresh_rescue_dashboard_status)\n        except Exception:\n            pass\n\n    def _build_rescue_recovery_center(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(\n            frame,\n            \"\ud83d\udea8 RESCUE &amp; RECOVERY CENTER\",\n            \"Technician-grade Windows rescue workspace with diagnostics, boot repair, media creation and restore safety.\",\n        )\n        tk.Label(frame, text=\"Designed for professional recovery workflows: WinRE checks, boot diagnostics, BitLocker visibility and restore point tracking.\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"], justify=\"left\").pack(fill=\"x\", padx=16, pady=(0, 6))\n\n        notebook = ttk.Notebook(frame)\n        notebook.pack(fill=\"both\", expand=True, padx=16, pady=(4, 12))\n        tabs = [\n            (\"Recovery Dashboard\", self._build_rescue_dashboard_tab),\n            (\"Windows Recovery\", self._build_windows_recovery_tab),\n            (\"Boot Repair\", self._build_boot_repair_tab),\n            (\"Rescue Media\", self._build_rescue_media_creator_tab),\n            (\"Offline Tools\", self._build_offline_recovery_tools_tab),\n            (\"Password Assistant\", self._build_password_recovery_assistant_tab),\n            (\"Recovery Console\", self._build_advanced_recovery_console_tab),\n            (\"Technician Toolkit\", self._build_technician_toolkit_tab),\n        ]\n        for title, builder in tabs:\n            tab = tk.Frame(notebook, bg=C[\"bg\"])\n            notebook.add(tab, text=title)\n            builder(tab)\n\n        self.after(200, self._show_rescue_center)\n        return frame\n\n    def _build_rescue_dashboard_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        status_frame = tk.Frame(body, bg=C[\"card\"])\n        status_frame.pack(fill=\"x\", padx=14, pady=10)\n\n        self.rescue_winre_status = tk.StringVar(value=\"Unknown\")\n        self.rescue_bitlocker_status = tk.StringVar(value=\"Unknown\")\n        self.rescue_restore_status = tk.StringVar(value=\"Unknown\")\n        self.rescue_readiness_status = tk.StringVar(value=\"Pending\")\n        self.rescue_last_sync = tk.StringVar(value=\"Never\")\n\n        for title, var, color in [\n            (\"WinRE Status\", self.rescue_winre_status, C[\"accent\"]),\n            (\"BitLocker Status\", self.rescue_bitlocker_status, C[\"warning\"]),\n            (\"Restore Point\", self.rescue_restore_status, C[\"success\"]),\n            (\"Recovery Readiness\", self.rescue_readiness_status, C[\"accent4\"]),\n            (\"Last Refresh\", self.rescue_last_sync, C[\"text_dim\"]),\n        ]:\n            card = tk.Frame(status_frame, bg=C[\"bg\"], bd=1, relief=\"solid\")\n            card.pack(side=\"left\", expand=True, fill=\"x\", padx=6, pady=6)\n            tk.Label(card, text=title, font=FONTS[\"small\"], fg=color, bg=C[\"bg\"]).pack(anchor=\"w\", padx=8, pady=(8, 2))\n            tk.Label(card, textvariable=var, font=FONTS[\"body\"], fg=C[\"text\"], bg=C[\"bg\"]).pack(anchor=\"w\", padx=8, pady=(0, 8))\n\n        tk.Label(body, text=\"Visible help: Refresh status and create a restore point before risky recovery actions.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=900, justify=\"left\").pack(fill=\"x\", padx=14, pady=(0, 8))\n        btn_row = tk.Frame(body, bg=C[\"bg\"])\n        btn_row.pack(fill=\"x\", padx=14, pady=(0, 10))\n        refresh_btn = tk.Button(btn_row, text=\"\ud83d\udd04 Refresh Dashboard\", font=FONTS[\"small\"], bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=12, pady=8, cursor=\"hand2\",\n              command=lambda: self._launch_job(\"refresh_rescue_status\", self._refresh_rescue_dashboard_status))\n        refresh_btn.pack(side=\"left\", padx=4)\n        self._create_tooltip(refresh_btn, \"Refresh Rescue Dashboard status, WinRE and restore point readiness before running recovery actions.\")\n        restore_btn = tk.Button(btn_row, text=\"\ud83d\udee1 Create Restore Point\", font=FONTS[\"small\"], bg=C[\"btn_hw\"], fg=C[\"text\"], bd=0, padx=12, pady=8, cursor=\"hand2\",\n              command=lambda: self._confirm_and_launch_job(\"Create Restore Point\", \"Create a verified restore point before critical recovery actions.\", None, \"restore_point_rescue\", self._collect_restore_point))\n        restore_btn.pack(side=\"left\", padx=4)\n        self._create_tooltip(restore_btn, \"Create a Windows restore point so you can roll back system changes if recovery actions cause issues.\")\n\n        history_frame = tk.LabelFrame(body, text=\"Recent Rescue Actions &amp; Restore Points\", font=FONTS[\"subhead\"], fg=C[\"accent2\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        history_frame.pack(fill=\"both\", expand=True, padx=14, pady=(0, 10))\n        self.rescue_history_tree = ttk.Treeview(history_frame, columns=(\"ts\", \"event\", \"detail\"), show=\"headings\", height=8, style=\"Custom.Treeview\")\n        for col, width in [(\"ts\", 160), (\"event\", 220), (\"detail\", 420)]:\n            self.rescue_history_tree.heading(col, text=col.title())\n            self.rescue_history_tree.column(col, width=width, anchor=\"w\")\n        self.rescue_history_tree.pack(fill=\"both\", expand=True, padx=8, pady=8)\n        return body\n\n    def _build_windows_recovery_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        lead = tk.Label(body, text=\"WinRE inspection, repair and readiness validation.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\")\n        lead.pack(fill=\"x\", padx=14, pady=(10, 8))\n        tk.Label(body, text=\"Visible help: Check WinRE first; repair only if WinRE is disabled or broken.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=900, justify=\"left\").pack(fill=\"x\", padx=14, pady=(0, 10))\n\n        self.winre_info_text = self._scrolled_text(body, height=14)\n        winre_check_btn = tk.Button(body, text=\"\ud83d\udd0d Check WinRE Status\", font=FONTS[\"small\"], bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=14, pady=8, cursor=\"hand2\",\n              command=lambda: self._confirm_and_launch_job(\"Check WinRE Status\", \"Inspect the Windows Recovery Environment.\", None, \"winre_status\", self._run_winre_status))\n        winre_check_btn.pack(pady=(0, 6), padx=14, anchor=\"w\")\n        self._create_tooltip(winre_check_btn, \"Check whether Windows Recovery Environment is enabled and correctly configured.\")\n        winre_repair_btn = tk.Button(body, text=\"\u2699 Repair WinRE\", font=FONTS[\"small\"], bg=C[\"btn_warn\"], fg=C[\"text\"], bd=0, padx=14, pady=8, cursor=\"hand2\",\n              command=lambda: self._confirm_and_launch_job(\"Repair WinRE\", \"Repair or enable Windows Recovery Environment.\", None, \"winre_repair\", self._run_winre_repair))\n        winre_repair_btn.pack(pady=(0, 14), padx=14, anchor=\"w\")\n        self._create_tooltip(winre_repair_btn, \"Repair or enable WinRE. Only use this if WinRE is missing or broken.\")\n        return body\n\n    def _build_boot_repair_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        desc = tk.Label(body, text=\"Boot diagnostics, BCD recovery and bootloader repair.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\")\n        desc.pack(fill=\"x\", padx=14, pady=(10, 8))\n        tk.Label(body, text=\"Visible help: Collect diagnostics first; repair MBR or rebuild BCD only if diagnostics indicate corruption.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=900, justify=\"left\").pack(fill=\"x\", padx=14, pady=(0, 10))\n        self.boot_repair_log = self._scrolled_text(body, height=16)\n\n        actions = tk.Frame(body, bg=C[\"card\"])\n        actions.pack(fill=\"x\", padx=14, pady=(10, 6))\n        for label, title, target, tip in [\n            (\"\ud83d\udd0d\", \"Collect Boot Diagnostics\", self._run_boot_diagnostics, \"Collect BCD and boot diagnostics to inspect startup configuration without making changes.\"),\n            (\"\ud83d\udee0\", \"Fix MBR\", self._run_boot_fix_mbr, \"Repair the Master Boot Record. Use only when diagnostics indicate MBR corruption.\"),\n            (\"\ud83e\udde9\", \"Rebuild BCD\", self._run_boot_rebuild_bcd, \"Rebuild the Boot Configuration Data store for Windows startup recovery.\"),\n        ]:\n            btn = tk.Button(actions, text=f\"{label} {title}\", font=FONTS[\"small\"], bg=C[\"btn_chip\"], fg=C[\"text\"], bd=0, padx=12, pady=8, cursor=\"hand2\",\n                      command=lambda t=target, n=title: self._confirm_and_launch_job(n, f\"{title} will perform safe boot diagnostics or repair.\", None, f\"boot_{title.replace(' ', '_').lower()}\", t))\n            btn.pack(side=\"left\", padx=4)\n            self._create_tooltip(btn, tip)\n        return body\n\n    def _build_rescue_media_creator_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        tk.Label(body, text=\"Rescue media readiness and removable drive validation.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\").pack(fill=\"x\", padx=14, pady=(10, 8))\n        tk.Label(body, text=\"Visible help: Probe removable drives and validate your target before building a rescue USB.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=900, justify=\"left\").pack(fill=\"x\", padx=14, pady=(0, 10))\n        self.rescue_media_status = self._scrolled_text(body, height=16)\n        probe_btn = tk.Button(body, text=\"\ud83d\udce6 Probe Rescue Media\", font=FONTS[\"small\"], bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=14, pady=8, cursor=\"hand2\",\n              command=lambda: self._confirm_and_launch_job(\"Probe Rescue Media\", \"Scan for removable rescue media targets.\", None, \"probe_rescue_media\", self._run_probe_rescue_media))\n        probe_btn.pack(pady=(0, 6), padx=14, anchor=\"w\")\n        self._create_tooltip(probe_btn, \"Scan removable drives and rescue media readiness before creating or using a bootable USB.\")\n        build_btn = tk.Button(body, text=\"\ud83d\udcbf Build Rescue USB\", font=FONTS[\"small\"], bg=C[\"btn_hw\"], fg=C[\"text\"], bd=0, padx=14, pady=8, cursor=\"hand2\",\n              command=lambda: self._confirm_and_launch_job(\"Build Rescue USB\", \"Create a rescue USB if WinPE tools are available.\", None, \"build_rescue_media\", self._run_build_rescue_media))\n        build_btn.pack(pady=(0, 14), padx=14, anchor=\"w\")\n        self._create_tooltip(build_btn, \"Create a rescue USB drive for offline repair when the system cannot boot.\")\n        return body\n\n    def _build_offline_recovery_tools_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        tk.Label(body, text=\"Offline recovery diagnostics without changing system state.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\").pack(fill=\"x\", padx=14, pady=(10, 8))\n        tk.Label(body, text=\"Visible help: Use offline captures to preserve evidence; avoid writing to the live system.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=900, justify=\"left\").pack(fill=\"x\", padx=14, pady=(0, 10))\n        self.offline_recovery_log = self._scrolled_text(body, height=16)\n        actions = tk.Frame(body, bg=C[\"card\"])\n        actions.pack(fill=\"x\", padx=14, pady=(0, 10))\n        for title, target, tip in [\n            (\"Capture Offline Snapshot\", self._run_offline_snapshot, \"Collect offline snapshot metadata for safe recovery investigations without changing live system state.\"),\n            (\"Collect Offline Registry\", self._run_offline_registry_collect, \"Export SYSTEM registry data for offline recovery analysis and evidence preservation.\"),\n        ]:\n            btn = tk.Button(actions, text=title, font=FONTS[\"small\"], bg=C[\"btn_chip\"], fg=C[\"text\"], bd=0, padx=12, pady=8, cursor=\"hand2\",\n                      command=lambda t=target, n=title: self._confirm_and_launch_job(n, f\"{title} will gather offline recovery artifacts.\", None, f\"offline_{title.replace(' ', '_').lower()}\", t))\n            btn.pack(side=\"left\", padx=4)\n            self._create_tooltip(btn, tip)\n        return body\n\n    def _build_password_recovery_assistant_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        tk.Label(body, text=\"Account diagnostics, SAM backup and BitLocker insight.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\").pack(fill=\"x\", padx=14, pady=(10, 8))\n        tk.Label(body, text=\"Visible help: Collect account and encryption diagnostics before performing password recovery.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=900, justify=\"left\").pack(fill=\"x\", padx=14, pady=(0, 10))\n        self.password_recovery_log = self._scrolled_text(body, height=16)\n        actions = tk.Frame(body, bg=C[\"card\"])\n        actions.pack(fill=\"x\", padx=14, pady=(0, 10))\n        for title, target, tip in [\n            (\"Account Diagnostics\", self._run_account_diagnostics, \"Inspect local user accounts and password recovery options for troubleshooting locked systems.\"),\n            (\"SAM + SYSTEM Backup\", self._run_sam_system_backup, \"Backup SAM and SYSTEM registry hives for password recovery and forensic analysis.\"),\n            (\"BitLocker Info\", self._run_bitlocker_info, \"View BitLocker encryption status for the system drive before recovery operations.\"),\n        ]:\n            btn = tk.Button(actions, text=title, font=FONTS[\"small\"], bg=C[\"btn_chip\"], fg=C[\"text\"], bd=0, padx=12, pady=8, cursor=\"hand2\",\n                      command=lambda t=target, n=title: self._confirm_and_launch_job(n, f\"{title} will gather recovery-sensitive diagnostics.\", None, f\"password_{title.replace(' ', '_').lower()}\", t))\n            btn.pack(side=\"left\", padx=4)\n            self._create_tooltip(btn, tip)\n        return body\n\n    def _build_advanced_recovery_console_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        tk.Label(body, text=\"Recovery console diagnostics, BCD dump and event correlation.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\").pack(fill=\"x\", padx=14, pady=(10, 8))\n        tk.Label(body, text=\"Visible help: Collect configuration and event diagnostics before making low-level recovery changes.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=900, justify=\"left\").pack(fill=\"x\", padx=14, pady=(0, 10))\n        self.recovery_console_log = self._scrolled_text(body, height=16)\n        actions = tk.Frame(body, bg=C[\"card\"])\n        actions.pack(fill=\"x\", padx=14, pady=(0, 10))\n        for title, target, tip in [\n            (\"Dump BCD Configuration\", self._run_bcd_dump, \"Export current BCD configuration for diagnostics before making boot repairs.\"),\n            (\"Collect Event Correlation\", self._run_event_correlation, \"Collect event logs to correlate boot and system errors during recovery.\"),\n            (\"Open Recovery Shell\", self._run_recovery_shell, \"Open a safe recovery shell capture for low-level troubleshooting.\"),\n        ]:\n            btn = tk.Button(actions, text=title, font=FONTS[\"small\"], bg=C[\"btn_chip\"], fg=C[\"text\"], bd=0, padx=12, pady=8, cursor=\"hand2\",\n                      command=lambda t=target, n=title: self._confirm_and_launch_job(n, f\"{title} will collect recovery console diagnostics.\", None, f\"console_{title.replace(' ', '_').lower()}\", t))\n            btn.pack(side=\"left\", padx=4)\n            self._create_tooltip(btn, tip)\n        return body\n\n    def _build_technician_toolkit_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        tk.Label(body, text=\"Technician tools for health checks, log capture and readiness validation.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\").pack(fill=\"x\", padx=14, pady=(10, 8))\n        tk.Label(body, text=\"Visible help: Run health checks and validate restore points before attempting repairs.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=900, justify=\"left\").pack(fill=\"x\", padx=14, pady=(0, 10))\n        self.technician_toolkit_log = self._scrolled_text(body, height=16)\n        actions = tk.Frame(body, bg=C[\"card\"])\n        actions.pack(fill=\"x\", padx=14, pady=(0, 10))\n        for title, target, tip in [\n            (\"Run Health Check\", self._run_technician_health_check, \"Run a system health check to gather recovery readiness diagnostics.\"),\n            (\"Collect System Logs\", self._run_collect_system_logs, \"Collect system event logs for technician troubleshooting.\"),\n            (\"Validate Recovery Readiness\", self._run_recovery_readiness_check, \"Check restore point and recovery safety readiness before repair actions.\"),\n        ]:\n            btn = tk.Button(actions, text=title, font=FONTS[\"small\"], bg=C[\"btn_chip\"], fg=C[\"text\"], bd=0, padx=12, pady=8, cursor=\"hand2\",\n                      command=lambda t=target, n=title: self._confirm_and_launch_job(n, f\"{title} will inspect recovery readiness and capture diagnostics.\", None, f\"tech_{title.replace(' ', '_').lower()}\", t))\n            btn.pack(side=\"left\", padx=4)\n            self._create_tooltip(btn, tip)\n        return body\n\n    def _refresh_rescue_dashboard_status(self):\n        data = {\"winre\": \"Unavailable\", \"bitlocker\": \"Unavailable\", \"restore\": \"Unavailable\", \"readiness\": \"Pending\", \"restore_points\": []}\n        try:\n            out, rc = self._run_cmd(\"reagentc /info\", timeout=18)\n            data[\"winre\"] = out.strip() if rc == 0 else f\"Error ({rc})\"\n        except Exception as e:\n            data[\"winre\"] = f\"Failed: {e}\"\n        try:\n            out, rc = self._run_cmd(\"manage-bde -status C:\", timeout=20)\n            data[\"bitlocker\"] = out.strip() if rc == 0 else f\"Error ({rc})\"\n        except Exception as e:\n            data[\"bitlocker\"] = f\"Failed: {e}\"\n        try:\n            if hasattr(self, \"restore_point_manager\"):\n                recent = self.restore_point_manager.list_recent(3) or []\n                data[\"restore_points\"] = recent\n                data[\"restore\"] = f\"{len(recent)} recent restore point(s)\"\n        except Exception:\n            data[\"restore\"] = \"Failed to enumerate\"\n        try:\n            if any(not v for v in (data[\"winre\"], data[\"bitlocker\"], data[\"restore\"])):\n                data[\"readiness\"] = \"Attention required\"\n            else:\n                data[\"readiness\"] = \"Ready\"\n        except Exception:\n            data[\"readiness\"] = \"Partial\"\n        data[\"ts\"] = datetime.datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\")\n        self.after(0, lambda: self._apply_rescue_dashboard_data(data))\n\n    def _apply_rescue_dashboard_data(self, data):\n        try:\n            self.rescue_winre_status.set(data.get(\"winre\", \"Unknown\"))\n            self.rescue_bitlocker_status.set(data.get(\"bitlocker\", \"Unknown\"))\n            self.rescue_restore_status.set(data.get(\"restore\", \"Unknown\"))\n            self.rescue_readiness_status.set(data.get(\"readiness\", \"Pending\"))\n            self.rescue_last_sync.set(data.get(\"ts\", \"Never\"))\n            if hasattr(self, \"rescue_history_tree\"):\n                self.rescue_history_tree.delete(*self.rescue_history_tree.get_children())\n                for item in data.get(\"restore_points\", []):\n                    self.rescue_history_tree.insert(\"\", \"end\", values=(item.get(\"Created\"), item.get(\"Description\"), item.get(\"SequenceNumber\")))\n        except Exception:\n            pass\n\n    def _collect_restore_point(self):\n        try:\n            if getattr(self, \"change_coordinator\", None):\n                info = self.change_coordinator.create_restore_point(\"Rescue Center checkpoint\")\n                return {\"ok\": bool(info.get(\"ok\")), \"message\": \"Restore point created.\" if info.get(\"ok\") else \"Restore point failed.\"}\n            if getattr(self, \"restore_point_manager\", None):\n                ok = self.restore_point_manager.create(\"Rescue Center checkpoint\", force=True)\n                return {\"ok\": ok, \"message\": \"Restore point created.\" if ok else \"Restore point failed.\"}\n        except Exception as e:\n            return {\"ok\": False, \"message\": str(e)}\n        return {\"ok\": False, \"message\": \"No restore manager available.\"}\n\n    def _run_winre_status(self):\n        out, rc = self._run_cmd(\"reagentc /info\", timeout=18)\n        self._append_log(self.winre_info_text, out or f\"Command failed ({rc})\", C[\"text\"])\n\n    def _run_winre_repair(self):\n        out, rc = self._run_cmd(\"reagentc /enable\", timeout=30)\n        self._append_log(self.winre_info_text, out or f\"Command failed ({rc})\", C[\"success\"] if rc == 0 else C[\"error\"])\n        if getattr(self, \"structured_logger\", None):\n            self.structured_logger.event(\"recovery_center\", \"winre_repair\", rc=rc)\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.winre_repair\", {\"rc\": rc})\n\n    def _run_boot_diagnostics(self):\n        self._append_log(self.boot_repair_log, \"Collecting BCD and boot diagnostics...\", C[\"accent4\"])\n        out, rc = self._run_cmd(\"bcdedit /enum all\", timeout=25)\n        self._append_log(self.boot_repair_log, out or f\"Command failed ({rc})\", C[\"text\"])\n        out2, rc2 = self._run_cmd(\"bootrec /scanos\", timeout=25)\n        self._append_log(self.boot_repair_log, out2 or f\"Command failed ({rc2})\", C[\"text\"])\n        if getattr(self, \"structured_logger\", None):\n            self.structured_logger.event(\"recovery_center\", \"boot_diagnostics\", rc1=rc, rc2=rc2)\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.boot_diagnostics\", {\"rc1\": rc, \"rc2\": rc2})\n\n    def _run_boot_fix_mbr(self):\n        out, rc = self._run_cmd(\"bootrec /fixmbr\", timeout=30)\n        self._append_log(self.boot_repair_log, out or f\"Command failed ({rc})\", C[\"success\"] if rc == 0 else C[\"error\"])\n        if getattr(self, \"structured_logger\", None):\n            self.structured_logger.event(\"recovery_center\", \"boot_fix_mbr\", rc=rc)\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.boot_fix_mbr\", {\"rc\": rc})\n\n    def _run_boot_rebuild_bcd(self):\n        out, rc = self._run_cmd(\"bootrec /rebuildbcd\", timeout=40)\n        self._append_log(self.boot_repair_log, out or f\"Command failed ({rc})\", C[\"success\"] if rc == 0 else C[\"error\"])\n        if getattr(self, \"structured_logger\", None):\n            self.structured_logger.event(\"recovery_center\", \"boot_rebuild_bcd\", rc=rc)\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.boot_rebuild_bcd\", {\"rc\": rc})\n\n    def _run_probe_rescue_media(self):\n        self._append_log(self.rescue_media_status, \"Probing removable drives and rescue media readiness...\", C[\"accent4\"])\n        out, rc = self._run_cmd(\"powershell -NoProfile -Command \\\"Get-Disk | Where-Object MediaType -eq 'Removable' | Select Number,FriendlyName,Size | ConvertTo-Json\\\"\", timeout=25)\n        self._append_log(self.rescue_media_status, out or f\"Command failed ({rc})\", C[\"text\"])\n        if getattr(self, \"structured_logger\", None):\n            self.structured_logger.event(\"recovery_center\", \"probe_rescue_media\", rc=rc)\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.probe_rescue_media\", {\"rc\": rc})\n\n    def _run_build_rescue_media(self):\n        self._append_log(self.rescue_media_status, \"Attempting rescue media build...\", C[\"accent4\"])\n        out, rc = self._run_cmd(\"powershell -NoProfile -Command \\\"if (Get-Command copype -ErrorAction SilentlyContinue) { Write-Output 'WinPE toolchain available' } else { Write-Error 'WinPE toolchain not found' }\\\"\", timeout=20)\n        self._append_log(self.rescue_media_status, out or f\"Command failed ({rc})\", C[\"text\"])\n        if getattr(self, \"structured_logger\", None):\n            self.structured_logger.event(\"recovery_center\", \"build_rescue_media\", rc=rc)\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.build_rescue_media\", {\"rc\": rc})\n\n    def _run_offline_snapshot(self):\n        self._append_log(self.offline_recovery_log, \"Collecting offline snapshot metadata...\", C[\"accent4\"])\n        out, rc = self._run_cmd(\"powershell -NoProfile -Command \\\"Get-ComputerInfo | Select CsName,WindowsVersion,OsBuildNumber,WindowsInstallationType | ConvertTo-Json\\\"\", timeout=25)\n        self._append_log(self.offline_recovery_log, out or f\"Command failed ({rc})\", C[\"text\"])\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.offline_snapshot\", {\"rc\": rc})\n\n    def _run_offline_registry_collect(self):\n        self._append_log(self.offline_recovery_log, \"Collecting offline registry artifacts...\", C[\"accent4\"])\n        out, rc = self._run_cmd(\"reg save HKLM\\\\SYSTEM %TEMP%\\\\SYSTEM_hive_backup /y\", timeout=30)\n        self._append_log(self.offline_recovery_log, out or f\"Command failed ({rc})\", C[\"success\"] if rc == 0 else C[\"error\"])\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.offline_registry_collect\", {\"rc\": rc})\n\n    def _run_account_diagnostics(self):\n        self._append_log(self.password_recovery_log, \"Gathering account diagnostics...\", C[\"accent4\"])\n        out, rc = self._run_cmd(\"net user\", timeout=20)\n        self._append_log(self.password_recovery_log, out or f\"Command failed ({rc})\", C[\"text\"])\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.account_diagnostics\", {\"rc\": rc})\n\n    def _run_sam_system_backup(self):\n        self._append_log(self.password_recovery_log, \"Backing up SAM and SYSTEM hives...\", C[\"accent4\"])\n        backup_dir = os.path.join(os.environ.get(\"TEMP\", \"C:\\\\Temp\"), \"sam_backup\")\n        try:\n            os.makedirs(backup_dir, exist_ok=True)\n        except Exception:\n            pass\n        for hive in [\"SAM\", \"SYSTEM\"]:\n            out, rc = self._run_cmd(f\"reg save HKLM\\\\{hive} {backup_dir}\\\\{hive}.hiv /y\", timeout=30)\n            self._append_log(self.password_recovery_log, out or f\"{hive} save failed ({rc})\", C[\"success\"] if rc == 0 else C[\"error\"])\n            if getattr(self, \"telemetry_store\", None):\n                self.telemetry_store.append(\"recovery.sam_backup\", {\"hive\": hive, \"rc\": rc})\n        if getattr(self, \"structured_logger\", None):\n            self.structured_logger.event(\"recovery_center\", \"sam_system_backup\", path=backup_dir)\n\n    def _run_bitlocker_info(self):\n        self._append_log(self.password_recovery_log, \"Collecting BitLocker status...\", C[\"accent4\"])\n        out, rc = self._run_cmd(\"manage-bde -status C:\", timeout=20)\n        self._append_log(self.password_recovery_log, out or f\"Command failed ({rc})\", C[\"text\"])\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.bitlocker_info\", {\"rc\": rc})\n\n    def _run_bcd_dump(self):\n        self._append_log(self.recovery_console_log, \"Dumping BCD configuration...\", C[\"accent4\"])\n        out, rc = self._run_cmd(\"bcdedit /enum all\", timeout=30)\n        self._append_log(self.recovery_console_log, out or f\"Command failed ({rc})\", C[\"text\"])\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.bcd_dump\", {\"rc\": rc})\n\n    def _run_event_correlation(self):\n        self._append_log(self.recovery_console_log, \"Collecting event correlation data...\", C[\"accent4\"])\n        out, rc = self._run_cmd(\"wevtutil qe System /c:50 /f:text\", timeout=25)\n        self._append_log(self.recovery_console_log, out or f\"Command failed ({rc})\", C[\"text\"])\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.event_correlation\", {\"rc\": rc})\n\n    def _run_recovery_shell(self):\n        self._append_log(self.recovery_console_log, \"Launching safe recovery shell capture...\", C[\"accent4\"])\n        out, rc = self._run_cmd(\"cmd /c echo Recovery shell initialized\", timeout=10)\n        self._append_log(self.recovery_console_log, out or f\"Command failed ({rc})\", C[\"text\"])\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.recovery_shell\", {\"rc\": rc})\n\n    def _run_technician_health_check(self):\n        self._append_log(self.technician_toolkit_log, \"Running technician health check...\", C[\"accent4\"])\n        out, rc = self._run_cmd(\"systeminfo\", timeout=40)\n        self._append_log(self.technician_toolkit_log, out or f\"Command failed ({rc})\", C[\"text\"])\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.health_check\", {\"rc\": rc})\n\n    def _run_collect_system_logs(self):\n        self._append_log(self.technician_toolkit_log, \"Collecting system logs...\", C[\"accent4\"])\n        out, rc = self._run_cmd(\"wevtutil qe System /c:30 /f:text\", timeout=25)\n        self._append_log(self.technician_toolkit_log, out or f\"Command failed ({rc})\", C[\"text\"])\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.collect_system_logs\", {\"rc\": rc})\n\n    def _run_recovery_readiness_check(self):\n        self._append_log(self.technician_toolkit_log, \"Validating recovery readiness...\", C[\"accent4\"])\n        out, rc = self._run_cmd(\"reagentc /info\", timeout=18)\n        self._append_log(self.technician_toolkit_log, out or f\"Command failed ({rc})\", C[\"text\"])\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.readiness_check\", {\"rc\": rc})\n\n    def _build_recovery_modern(self, parent):\n        return self._build_recovery_safe(parent)\n\n    def _on_recovery_task_update(self, task):\n        self._ui_queue.put((\"recovery_queue\", None))\n        self._ui_queue.put((\"recovery_refresh\", None))\n        self._ui_queue.put((\"recovery_log\", f\"[{task.label}] {task.status.upper()} - {task.message or 'No details'}\"))\n        if task.status == \"running\":\n            self._ui_queue.put((\"status\", (f\"Recovery task running: {task.label}\", C[\"accent4\"])))\n        elif task.status == \"completed\":\n            self._ui_queue.put((\"status\", (f\"Recovery task completed: {task.label}\", C[\"success\"])))\n        elif task.status == \"failed\":\n            self._ui_queue.put((\"status\", (f\"Recovery task failed: {task.label}\", C[\"error\"])))\n        elif task.status == \"cancelled\":\n            self._ui_queue.put((\"status\", (f\"Recovery task cancelled: {task.label}\", C[\"warning\"])))\n\n    def _append_recovery_log(self, msg):\n        if not hasattr(self, \"recovery_log_text\"):\n            return\n        try:\n            self.recovery_log_text.config(state=\"normal\")\n            self.recovery_log_text.insert(\"end\", self._fix_text(str(msg)) + \"\\n\")\n            lines = float(self.recovery_log_text.index(\"end-1c\").split(\".\")[0])\n            if lines &gt; 500:\n                self.recovery_log_text.delete(\"1.0\", \"100.0\")\n            self.recovery_log_text.see(\"end\")\n            self.recovery_log_text.config(state=\"disabled\")\n        except Exception:\n            pass\n\n    def _refresh_recovery_tree(self, tree, category=None):\n        if tree is None:\n            return\n        try:\n            for iid in tree.get_children():\n                tree.delete(iid)\n            for item in self.recovery_results.all():\n                if category and item.category != category:\n                    continue\n                tag = \"recovered\" if item.recoverability_score &gt;= 75 else \"partial\" if item.recoverability_score &gt;= 40 else \"failed\"\n                tree.insert(\"\", \"end\", values=(\n                    item.file_name,\n                    item.file_type,\n                    self._fmt_size(item.size_bytes),\n                    item.status,\n                    item.path,\n                    f\"{item.recoverability_score}%\",\n                ), tags=(tag,))\n        except Exception:\n            pass\n\n    def _refresh_recovery_queue_tree(self):\n        tree = getattr(self, \"recovery_queue_tree\", None)\n        if tree is None:\n            return\n        try:\n            for iid in tree.get_children():\n                tree.delete(iid)\n            for task in self.recovery_manager.list_tasks():\n                tree.insert(\"\", \"end\", iid=task.task_id, values=(\n                    task.label,\n                    task.status,\n                    f\"{int(task.progress)}%\",\n                    task.message or \"\",\n                ))\n        except Exception:\n            pass\n\n    def _get_recovery_disk_values(self):\n        drives = [f\"{d}:\\\\\" for d in \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\" if os.path.exists(f\"{d}:\\\\\")]\n        raw_values = [DEFAULT_RAW_DISK] + [f\"\\\\\\\\.\\\\{d}:\" for d in \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\" if os.path.exists(f\"{d}:\\\\\")]\n        return raw_values + drives\n\n    def _resolve_disk_path(self, val):\n        \"\"\"Resolve a displayed combobox value to an actual device path.\n\n        If the value matches an entry in _recovery_disk_map, return the mapped path,\n        otherwise return the raw value or DEFAULT_RAW_DISK.\n        \"\"\"\n        try:\n            if not val:\n                return DEFAULT_RAW_DISK\n            if hasattr(self, \"_recovery_disk_map\") and isinstance(val, str) and val in self._recovery_disk_map:\n                return self._recovery_disk_map.get(val)\n            return val or DEFAULT_RAW_DISK\n        except Exception:\n            return DEFAULT_RAW_DISK\n\n    def _populate_recovery_disks(self):\n        \"\"\"Populate available physical disk display values and map them to device paths.\n\n        Uses PowerShell Get-Disk for friendly names; falls back to basic listing.\n        Updates any recovery combobox widgets if present.\n        \"\"\"\n        try:\n            script = \"Get-Disk | Select-Object Number,FriendlyName,Size,MediaType | ConvertTo-Json -Depth 2\"\n            out, rc = self._run_powershell(script, timeout=6)\n            disks = []\n            if out and out.strip() and out.strip() != \"[]\":\n                try:\n                    payload = json.loads(out)\n                    if isinstance(payload, dict):\n                        payload = [payload]\n                    for d in payload:\n                        num = d.get(\"Number\")\n                        name = d.get(\"FriendlyName\") or d.get(\"Model\") or \"Disk\"\n                        size = int(d.get(\"Size\") or 0)\n                        human = self._fmt_size(size)\n                        label = f\"PhysicalDrive{num} - {name} ({human})\"\n                        path = f\"\\\\\\\\.\\\\PhysicalDrive{num}\"\n                        disks.append((label, path))\n                except Exception:\n                    disks = []\n\n            if not disks:\n                # Fallback: use simple raw device list + letters\n                raw_vals = [DEFAULT_RAW_DISK]\n                for d in \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\":\n                    if os.path.exists(f\"{d}:\\\\\"):\n                        raw_vals.append(f\"\\\\\\\\.\\\\{d}:\")\n                disks = [(v, v) for v in raw_vals]\n\n            # Build map and display values\n            self._recovery_disk_map = {label: path for label, path in disks}\n            display_values = [label for label, _ in disks]\n\n            # Update known comboboxes if they exist\n            try:\n                if hasattr(self, \"partition_source_combo\"):\n                    self.partition_source_combo.configure(values=display_values)\n                if hasattr(self, \"deep_recovery_source_combo\"):\n                    self.deep_recovery_source_combo.configure(values=display_values)\n                if hasattr(self, \"raw_carve_source_combo\"):\n                    self.raw_carve_source_combo.configure(values=display_values)\n                if hasattr(self, \"nand_source_combo\"):\n                    self.nand_source_combo.configure(values=display_values)\n                if hasattr(self, \"dashboard_disk_combo\"):\n                    self.dashboard_disk_combo.configure(values=display_values)\n                if hasattr(self, \"photorec_source_combo\"):\n                    self.photorec_source_combo.configure(values=display_values)\n                if hasattr(self, \"mft_source_combo\"):\n                    self.mft_source_combo.configure(values=display_values)\n                if hasattr(self, \"raw_disk_combo\"):\n                    # raw_disk_combo expects raw/paths; extend with display labels too\n                    try:\n                        cur = list(self.raw_disk_combo.cget(\"values\"))\n                        combined = display_values + [v for v in cur if v not in display_values]\n                        self.raw_disk_combo.configure(values=combined)\n                    except Exception:\n                        pass\n                # Also populate detected disks tree if present\n                try:\n                    if hasattr(self, \"detected_disks_tree\") and self.detected_disks_tree is not None:\n                        try:\n                            for iid in self.detected_disks_tree.get_children():\n                                self.detected_disks_tree.delete(iid)\n                            for label, path in disks:\n                                # extract index from path if PhysicalDrive\n                                m = re.match(r\"\\\\\\\\.\\\\PhysicalDrive(\\d+)\", path)\n                                idx = int(m.group(1)) if m else -1\n                                size = \"\"\n                                try:\n                                    # try to get size by path\n                                    sz = _disk_source_size(path)\n                                    size = self._fmt_size(sz)\n                                except Exception:\n                                    size = \"N/A\"\n                                self.detected_disks_tree.insert(\"\", \"end\", iid=path, values=(idx if idx&gt;=0 else \"-\", label, size))\n                        except Exception:\n                            pass\n                except Exception:\n                    pass\n            except Exception:\n                pass\n        except Exception:\n            pass\n\n    def _emit_recovery_scan_stats(self, stats: dict):\n        try:\n            self._ui_queue.put((\"recovery_scan_stats\", stats))\n        except Exception:\n            pass\n\n    def _apply_recovery_scan_stats(self, stats):\n        if not isinstance(stats, dict):\n            return\n        tab = stats.get(\"tab\", \"global\")\n        pct = float(stats.get(\"pct\", 0) or 0)\n        files = int(stats.get(\"files_found\", 0) or 0)\n        folders = int(stats.get(\"folders_scanned\", 0) or 0)\n        msg = str(stats.get(\"message\", \"\") or \"\")\n        self._recovery_live_stats[tab] = stats\n        panel = self._recovery_progress_panels.get(tab) or self._recovery_progress_panels.get(\"global\")\n        if panel:\n            try:\n                panel[\"pct_var\"].set(max(0.0, min(100.0, pct)))\n                panel[\"bar\"].configure(mode=\"determinate\")\n            except Exception:\n                pass\n            try:\n                panel[\"stats_label\"].config(\n                    text=f\"\ud83d\udcc1 Files: {files:,}  |  \ud83d\udcc2 Folders: {folders:,}  |  {pct:.0f}%\"\n                )\n            except Exception:\n                pass\n            if msg and panel.get(\"status_label\"):\n                panel[\"status_label\"].config(text=msg[:220])\n        if tab == \"deep\" and hasattr(self, \"deep_recovery_status\"):\n            self.deep_recovery_status.config(text=f\"{pct:.0f}% \u2014 {files:,} signatures | {msg[:80]}\", fg=C[\"accent4\"])\n        if tab == \"photorec\" and hasattr(self, \"photorec_status_label\"):\n            rec = int(stats.get(\"files_recovered\", files) or 0)\n            self.photorec_status_label.config(\n                text=f\"PhotoRec: {pct:.0f}% | Recovered: {rec:,} | Found: {files:,}\", fg=C[\"accent2\"])\n        if tab == \"mft\" and hasattr(self, \"mft_status_label\"):\n            self.mft_status_label.config(\n                text=f\"MFT: {pct:.0f}% | Deleted: {files:,} | Recovered: {int(stats.get('files_recovered', 0)):,}\",\n                fg=C[\"accent2\"],\n            )\n        if hasattr(self, \"rec_stats_label\") and tab in (\"photorec\", \"deep\", \"mft\", \"raw\"):\n            self.rec_stats_label.config(text=f\"{files:,} items | Live scan {pct:.0f}%\")\n\n    def _build_recovery_progress_strip(self, parent, tab_key, title=\"Scan Progress\"):\n        strip = tk.LabelFrame(parent, text=title, font=FONTS[\"small\"], fg=C[\"accent2\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        strip.pack(fill=\"x\", padx=10, pady=(6, 8))\n        status_label = tk.Label(strip, text=\"\u0924\u0948\u092f\u093e\u0930 \u2014 scan \u0936\u0941\u0930\u0942 \u0915\u0930\u0947\u0902\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], anchor=\"w\")\n        status_label.pack(fill=\"x\", padx=10, pady=(8, 2))\n        stats_label = tk.Label(strip, text=\"\ud83d\udcc1 Files: 0  |  \ud83d\udcc2 Folders: 0  |  0%\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"], anchor=\"w\")\n        stats_label.pack(fill=\"x\", padx=10, pady=(0, 4))\n        pct_var = tk.DoubleVar(value=0.0)\n        bar = ttk.Progressbar(strip, variable=pct_var, maximum=100.0, mode=\"determinate\")\n        bar.pack(fill=\"x\", padx=10, pady=(0, 10))\n        self._recovery_progress_panels[tab_key] = {\n            \"pct_var\": pct_var,\n            \"bar\": bar,\n            \"stats_label\": stats_label,\n            \"status_label\": status_label,\n        }\n        return strip\n\n    def _reset_recovery_progress(self, tab_key, message=\"Scan \u0936\u0941\u0930\u0942 \u0939\u094b \u0930\u0939\u093e \u0939\u0948...\"):\n        panel = self._recovery_progress_panels.get(tab_key)\n        if panel:\n            panel[\"pct_var\"].set(0)\n            panel[\"status_label\"].config(text=message)\n            panel[\"stats_label\"].config(text=\"\ud83d\udcc1 Files: 0  |  \ud83d\udcc2 Folders: 0  |  0%\")\n\n    def _show_recovery_center(self):\n        if hasattr(self, \"recovery_queue_tree\"):\n            self._refresh_recovery_queue_tree()\n        try:\n            self._launch_job(\"populate_recovery_disks\", self._populate_recovery_disks)\n        except Exception:\n            pass\n\n    def _build_recovery_center(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(\n            frame,\n            \"\ud83d\udcc2 Professional File Recovery\",\n            \"Recuva / EaseUS style workflow \u2014 live progress, PhotoRec carving, NTFS MFT deleted recovery.\",\n        )\n\n        global_strip = tk.Frame(frame, bg=C[\"card\"], highlightbackground=C[\"accent2\"], highlightthickness=2)\n        global_strip.pack(fill=\"x\", padx=16, pady=(4, 8))\n        tk.Label(global_strip, text=\"\ud83d\udda5\ufe0f Live Recovery Status\", font=FONTS[\"subhead\"], fg=C[\"accent2\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=12, pady=(8, 2))\n        self._build_recovery_progress_strip(global_strip, \"global\", \"Overall Progress\")\n\n        notebook = ttk.Notebook(frame)\n        notebook.pack(fill=\"both\", expand=True, padx=16, pady=(4, 12))\n\n        tabs = [\n            (\"\ud83c\udfe0 Dashboard\", self._build_recovery_dashboard_tab),\n            (\"\u26a1 Quick Scan\", self._build_recovery_quick_tab),\n            (\"\ud83d\udd0e Deep / Raw Scan\", self._build_recovery_deep_tab),\n            (\"\ud83e\udde9 PhotoRec Pro\", self._build_recovery_photorec_tab),\n            (\"\ud83d\uddc2\ufe0f MFT Deleted Files\", self._build_recovery_mft_tab),\n            (\"\ud83d\udcbe Partition\", self._build_recovery_partitions_tab),\n            (\"\u26a1 NAND Flash\", self._build_recovery_nand_tab),\n            (\"\ud83d\udccc Queue\", self._build_recovery_queue_tab),\n            (\"\ud83d\udccb Logs\", self._build_recovery_logs_tab),\n            (\"\ud83d\udd58 History\", self._build_recovery_history_tab),\n        ]\n        for title, builder in tabs:\n            tab = tk.Frame(notebook, bg=C[\"bg\"])\n            notebook.add(tab, text=title)\n            builder(tab)\n\n        return frame\n\n    def _build_recovery_dashboard_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        card = tk.LabelFrame(body, text=\"Recovery Dashboard \u2014 Disk select karein\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        card.pack(fill=\"x\", padx=14, pady=10)\n\n        row = tk.Frame(card, bg=C[\"card\"])\n        row.pack(fill=\"x\", padx=10, pady=10)\n        tk.Label(row, text=\"Target Disk:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=0, column=0, sticky=\"w\")\n        self.dashboard_disk_var = tk.StringVar(value=\"\")\n        self.dashboard_disk_combo = ttk.Combobox(row, textvariable=self.dashboard_disk_var, width=42, state=\"readonly\")\n        self.dashboard_disk_combo.grid(row=0, column=1, padx=8, sticky=\"w\")\n        tk.Button(row, text=\"\ud83d\udd04 Refresh Disks\", font=FONTS[\"small\"], bg=C[\"btn\"], fg=C[\"text\"], bd=0, padx=10, pady=6, cursor=\"hand2\",\n              command=lambda: self._launch_job(\"populate_recovery_disks\", self._populate_recovery_disks)).grid(row=0, column=2, padx=4)\n\n        tk.Label(row, text=\"Output Folder:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=1, column=0, sticky=\"w\", pady=(10, 0))\n        self.dashboard_output_var = tk.StringVar(value=os.path.join(os.path.expanduser(\"~\"), \"Desktop\", \"Godawari_Recovery\"))\n        tk.Entry(row, textvariable=self.dashboard_output_var, width=48, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).grid(row=1, column=1, padx=8, pady=(10, 0), sticky=\"w\")\n        tk.Button(row, text=\"Browse\", font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text\"], bd=0, padx=10, pady=6, cursor=\"hand2\",\n                  command=lambda: self._browse_recovery_output(self.dashboard_output_var)).grid(row=1, column=2, padx=4, pady=(10, 0))\n\n        modes = tk.Frame(card, bg=C[\"card\"])\n        modes.pack(fill=\"x\", padx=10, pady=(8, 12))\n        tk.Label(modes, text=\"Scan Mode (professional tools jaisa):\", font=FONTS[\"body\"], fg=C[\"accent2\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(0, 6))\n        btn_row = tk.Frame(modes, bg=C[\"card\"])\n        btn_row.pack(fill=\"x\")\n        for label, color, cmd in [\n            (\"\ud83d\udd0d Quick Scan (Existing Files)\", C[\"accent2\"], self._dashboard_start_quick),\n            (\"\ud83d\udd0e Deep Signature Scan\", C[\"btn_warn\"], self._dashboard_start_deep),\n            (\"\ud83e\udde9 PhotoRec Multi-Pass\", C[\"btn_hw\"], self._dashboard_start_photorec),\n            (\"\ud83d\uddc2\ufe0f MFT Deleted Recovery\", C[\"btn_info\"], self._dashboard_start_mft),\n        ]:\n            tk.Button(btn_row, text=label, font=FONTS[\"small\"], bg=color, fg=C[\"text\"] if color != C[\"accent2\"] else \"#000\",\n                      bd=0, padx=12, pady=10, cursor=\"hand2\", command=cmd).pack(side=\"left\", padx=4, pady=4)\n\n        hint = tk.Label(card,\n            text=\"\ud83d\udca1 Tip: Deleted files ke liye MFT \u092f\u093e PhotoRec use \u0915\u0930\u0947\u0902\u0964 Live progress bar \u0928\u0940\u091a\u0947 \u0939\u0930 tab \u092e\u0947\u0902 \u0926\u093f\u0916\u0947\u0917\u093e\u0964 Output \u0939\u092e\u0947\u0936\u093e \u0905\u0932\u0917 drive \u092a\u0930 \u0930\u0916\u0947\u0902\u0964\",\n            font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\", wraplength=900)\n        hint.pack(fill=\"x\", padx=12, pady=(0, 10))\n        return body\n\n    def _browse_recovery_output(self, var):\n        path = filedialog.askdirectory(title=\"Recovery output folder\")\n        if path:\n            var.set(path)\n\n    def _sync_dashboard_disk_to_tabs(self):\n        disk = self.dashboard_disk_var.get().strip()\n        if not disk:\n            return\n        path = getattr(self, \"_recovery_disk_map\", {}).get(disk, disk)\n        for attr in (\n            \"deep_recovery_source_var\", \"photorec_source_var\", \"mft_source_var\",\n            \"raw_carve_source_var\", \"partition_source_var\", \"nand_source_var\",\n        ):\n            if hasattr(self, attr):\n                getattr(self, attr).set(path if path.startswith(\"\\\\\\\\.\\\\\") else disk)\n\n    def _dashboard_start_quick(self):\n        self._sync_dashboard_disk_to_tabs()\n        if hasattr(self, \"quick_recovery_drive_var\"):\n            d = self.dashboard_disk_var.get()\n            if d and \":\" in d:\n                self.quick_recovery_drive_var.set(d.split(\" - \")[0] if \" - \" in d else d[:3] + \"\\\\\")\n            if hasattr(self, \"quick_recovery_dest_var\"):\n                self.quick_recovery_dest_var.set(self.dashboard_output_var.get())\n        self._start_quick_recovery()\n\n    def _dashboard_start_deep(self):\n        self._sync_dashboard_disk_to_tabs()\n        if hasattr(self, \"deep_recovery_source_var\"):\n            self.deep_recovery_source_var.set(self.dashboard_disk_var.get())\n        self._start_deep_recovery()\n\n    def _dashboard_start_photorec(self):\n        self._sync_dashboard_disk_to_tabs()\n        if hasattr(self, \"photorec_source_var\"):\n            self.photorec_source_var.set(self.dashboard_disk_var.get())\n        if hasattr(self, \"photorec_output_var\"):\n            self.photorec_output_var.set(self.dashboard_output_var.get())\n        self._start_photorec_tab_scan()\n\n    def _dashboard_start_mft(self):\n        self._sync_dashboard_disk_to_tabs()\n        if hasattr(self, \"mft_source_var\"):\n            self.mft_source_var.set(self.dashboard_disk_var.get())\n        if hasattr(self, \"mft_output_var\"):\n            self.mft_output_var.set(os.path.join(self.dashboard_output_var.get(), \"MFT_Recovered\"))\n        self._start_mft_deleted_recovery()\n\n    def _build_recovery_quick_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        self._build_recovery_progress_strip(body, \"quick\", \"Quick Scan \u2014 Live Progress\")\n        card = tk.LabelFrame(body, text=\"\ud83d\udccb Quick Recovery (Existing Files)\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        card.pack(fill=\"x\", padx=14, pady=10)\n\n        drive_values = [f\"{d}:\\\\\" for d in \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\" if os.path.exists(f\"{d}:\\\\\")]\n        self.quick_recovery_drive_var = tk.StringVar(value=drive_values[0] if drive_values else \"C:\\\\\")\n        self.quick_recovery_types_var = tk.StringVar(value=\"jpg,png,pdf,docx,mp4\")\n        self.quick_recovery_dest_var = tk.StringVar(value=os.path.join(os.path.expanduser(\"~\"), \"Desktop\", \"Godawari_Quick_Recovery\"))\n\n        row = tk.Frame(card, bg=C[\"card\"])\n        row.pack(fill=\"x\", padx=10, pady=(10, 8))\n        tk.Label(row, text=\"Drive:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=0, column=0, sticky=\"w\")\n        ttk.Combobox(row, textvariable=self.quick_recovery_drive_var, values=drive_values, width=14, state=\"readonly\").grid(row=0, column=1, padx=6)\n        tk.Label(row, text=\"File Types:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=0, column=2, padx=(14, 4), sticky=\"w\")\n        tk.Entry(row, textvariable=self.quick_recovery_types_var, width=28, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).grid(row=0, column=3, padx=6)\n        tk.Label(row, text=\"Destination:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=1, column=0, pady=(8, 0), sticky=\"w\")\n        tk.Entry(row, textvariable=self.quick_recovery_dest_var, width=60, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).grid(row=1, column=1, columnspan=3, padx=6, pady=(8, 0), sticky=\"w\")\n\n        action_row = tk.Frame(card, bg=C[\"card\"])\n        action_row.pack(fill=\"x\", padx=10, pady=(0, 10))\n        tk.Button(action_row, text=\"\ud83d\udd0d Start Scan\", font=FONTS[\"small\"], bg=C[\"accent2\"], fg=\"#000\", bd=0, padx=14, pady=8, cursor=\"hand2\", command=self._start_quick_recovery).pack(side=\"left\")\n        tk.Button(action_row, text=\"\ud83e\uddf9 Clear Results\", font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text\"], bd=0, padx=14, pady=8, cursor=\"hand2\", command=lambda: (self.recovery_results.clear(), self._refresh_recovery_tree(self.quick_recovery_tree, category=\"Quick Recovery\"))).pack(side=\"left\", padx=8)\n\n        self.quick_recovery_status = tk.Label(card, text=\"Ready for quick recovery scan.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"])\n        self.quick_recovery_status.pack(fill=\"x\", padx=10, pady=(0, 6))\n\n        results_outer = tk.LabelFrame(body, text=\"\ud83d\udcc1 Quick Recovery Results\", font=FONTS[\"subhead\"], fg=C[\"accent2\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        results_outer.pack(fill=\"both\", expand=True, padx=14, pady=(0, 14))\n        cols = (\"Filename\", \"Type\", \"Size\", \"Status\", \"Location\", \"Integrity\")\n        self.quick_recovery_tree = ttk.Treeview(results_outer, columns=cols, show=\"headings\", height=12, style=\"Custom.Treeview\")\n        for col, width in zip(cols, (220, 70, 90, 120, 280, 90)):\n            self.quick_recovery_tree.heading(col, text=col)\n            self.quick_recovery_tree.column(col, width=width, anchor=\"w\")\n        self.quick_recovery_tree.tag_configure(\"recovered\", foreground=C[\"success\"])\n        self.quick_recovery_tree.tag_configure(\"partial\", foreground=C[\"warning\"])\n        self.quick_recovery_tree.tag_configure(\"failed\", foreground=C[\"error\"])\n        self.quick_recovery_tree.pack(fill=\"both\", expand=True, padx=8, pady=8)\n        self.quick_recovery_tree.bind(\"&lt;&gt;\", self._on_quick_recovery_select)\n\n        self.quick_recovery_preview = scrolledtext.ScrolledText(body, height=6, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], wrap=\"word\", bd=0, relief=\"flat\")\n        self.quick_recovery_preview.pack(fill=\"x\", padx=14, pady=(0, 10))\n        self.quick_recovery_preview.config(state=\"disabled\")\n\n        return body\n\n    def _start_quick_recovery(self):\n        drive = self.quick_recovery_drive_var.get().strip()\n        if not drive or not os.path.exists(drive):\n            messagebox.showwarning(\"Drive Missing\", \"Valid drive select karo.\")\n            return\n        exts = [e.strip().lstrip(\".\").lower() for e in self.quick_recovery_types_var.get().split(\",\") if e.strip()]\n        dest = self.quick_recovery_dest_var.get().strip() or os.path.join(os.path.expanduser(\"~\"), \"Desktop\", \"Godawari_Quick_Recovery\")\n        try:\n            dest = get_recovery_safety(getattr(self, \"app_config\", None)).validate_output_dir(dest, drive)\n        except Exception as exc:\n            messagebox.showerror(\"Recovery Safety\", str(exc))\n            return\n        self.recovery_results.clear()\n        self._refresh_recovery_tree(self.quick_recovery_tree, category=\"Quick Recovery\")\n        self.recovery_manager.submit_task(\"Quick Recovery\", self._task_quick_recovery, drive, exts, dest)\n        self.quick_recovery_status.config(text=\"Queued quick recovery task...\", fg=C[\"accent4\"])\n\n    def _task_quick_recovery(self, task, drive, exts, dest):\n        found = 0\n        folders = 0\n        self._ui_queue.put((\"recovery_log\", f\"[Quick Recovery] Scanning {drive} for {', '.join(exts) or 'all file types'}\"))\n        for root, _, files in os.walk(drive):\n            folders += 1\n            task.wait_if_paused()\n            if task.is_cancelled():\n                raise InterruptedError(\"Quick recovery cancelled\")\n            for name in files:\n                task.wait_if_paused()\n                if task.is_cancelled():\n                    raise InterruptedError(\"Quick recovery cancelled\")\n                ext = os.path.splitext(name)[1].lstrip(\".\").lower()\n                if exts and ext not in exts:\n                    continue\n                path = os.path.join(root, name)\n                try:\n                    size = os.path.getsize(path)\n                except Exception:\n                    size = 0\n                score = 90 if size &gt; 0 else 20\n                item = RecoveryResultItem(\n                    item_id=f\"quick-{uuid.uuid4()}\",\n                    source=drive,\n                    category=\"Quick Recovery\",\n                    file_name=name,\n                    file_type=ext or \"unknown\",\n                    size_bytes=size,\n                    recoverability_score=score,\n                    status=\"found\",\n                    path=path,\n                    metadata={\"root\": root},\n                )\n                self.recovery_results.add(item)\n                found += 1\n                if found % 20 == 0:\n                    self._emit_recovery_scan_stats({\n                        \"tab\": \"quick\",\n                        \"pct\": min(95, found // 15),\n                        \"files_found\": found,\n                        \"folders_scanned\": folders,\n                        \"message\": f\"Scanning... {found:,} files in {folders:,} folders\",\n                    })\n                if score &gt;= 75 and dest:\n                    try:\n                        safe_dest = get_recovery_safety(getattr(self, \"app_config\", None)).validate_output_dir(dest, drive)\n                        rel = os.path.relpath(path, drive)\n                        out_path = os.path.join(safe_dest, rel)\n                        os.makedirs(os.path.dirname(out_path), exist_ok=True)\n                        if not os.path.exists(out_path):\n                            shutil.copy2(path, out_path)\n                            item.metadata[\"exported_to\"] = out_path\n                    except Exception:\n                        pass\n                if found % 25 == 0:\n                    self._ui_queue.put((\"recovery_queue\", None))\n                    self._ui_queue.put((\"recovery_log\", f\"[Quick Recovery] {found} items found\"))\n                if found &gt;= 1500:\n                    self._ui_queue.put((\"recovery_log\", \"[Quick Recovery] Limit reached (1500 items)\"))\n                    return\n        self._emit_recovery_scan_stats({\n            \"tab\": \"quick\", \"pct\": 100, \"files_found\": found, \"folders_scanned\": folders,\n            \"message\": f\"Complete \u2014 {found:,} files\",\n        })\n        self._ui_queue.put((\"recovery_queue\", None))\n        self._ui_queue.put((\"recovery_refresh\", None))\n        self._ui_queue.put((\"recovery_log\", f\"[Quick Recovery] Completed, {found} items found.\"))\n\n    def _on_quick_recovery_select(self, event=None):\n        sel = self.quick_recovery_tree.selection()\n        if not sel:\n            return\n        values = self.quick_recovery_tree.item(sel[0], \"values\")\n        if not values or len(values) &lt; 6:\n            return\n        path = values[4]\n        preview = [f\"Path: {path}\", f\"Type: {values[1]}\", f\"Size: {values[2]}\", f\"Status: {values[3]}\", f\"Integrity: {values[5]}\", \"\"]\n        try:\n            if os.path.exists(path) and os.path.isfile(path):\n                with open(path, \"rb\") as fh:\n                    data = fh.read(512)\n                preview.append(data[:512].hex(\" \"))\n        except Exception as exc:\n            preview.append(f\"Preview failed: {exc}\")\n        self.quick_recovery_preview.config(state=\"normal\")\n        self.quick_recovery_preview.delete(\"1.0\", \"end\")\n        self.quick_recovery_preview.insert(\"end\", \"\\n\".join(preview))\n        self.quick_recovery_preview.config(state=\"disabled\")\n\n    def _build_recovery_deep_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        self._build_recovery_progress_strip(body, \"deep\", \"Deep / Raw Scan \u2014 Live Progress\")\n        card = tk.LabelFrame(body, text=\"\ud83d\udd0e Deep / Raw Signature Scan\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        card.pack(fill=\"x\", padx=14, pady=10)\n\n        self.deep_recovery_source_var = tk.StringVar(value=DEFAULT_RAW_DISK)\n        self.deep_recovery_types_var = tk.StringVar(value=\"jpg,png,pdf,zip,exe\")\n        self.deep_recovery_scan_mb_var = tk.StringVar(value=\"0\")\n        self.deep_recovery_start_var = tk.StringVar(value=\"0\")\n\n        row = tk.Frame(card, bg=C[\"card\"])\n        row.pack(fill=\"x\", padx=10, pady=10)\n        tk.Label(row, text=\"Source:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=0, column=0, sticky=\"w\")\n        self.deep_recovery_source_combo = ttk.Combobox(row, textvariable=self.deep_recovery_source_var, values=self._get_recovery_disk_values(), width=34, state=\"readonly\")\n        self.deep_recovery_source_combo.grid(row=0, column=1, padx=4)\n        tk.Label(row, text=\"Types:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=1, column=0, sticky=\"w\", pady=(8,0))\n        tk.Entry(row, textvariable=self.deep_recovery_types_var, width=34, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).grid(row=1, column=1, padx=4, pady=(8,0))\n        tk.Label(row, text=\"Scan MB:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=0, column=2, padx=(18,4), sticky=\"w\")\n        tk.Entry(row, textvariable=self.deep_recovery_scan_mb_var, width=8, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).grid(row=0, column=3, padx=4)\n        tk.Label(row, text=\"Start Sector:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=1, column=2, padx=(18,4), sticky=\"w\", pady=(8,0))\n        tk.Entry(row, textvariable=self.deep_recovery_start_var, width=10, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).grid(row=1, column=3, padx=4, pady=(8,0))\n\n        action_row = tk.Frame(card, bg=C[\"card\"])\n        action_row.pack(fill=\"x\", padx=10, pady=(0, 8))\n        tk.Button(action_row, text=\"\u26a1 Scan Raw Source\", font=FONTS[\"small\"], bg=C[\"btn_warn\"], fg=C[\"text\"], bd=0, padx=14, pady=8, cursor=\"hand2\", command=self._start_deep_recovery).pack(side=\"left\")\n        tk.Button(action_row, text=\"\ud83e\uddf9 Clear\", font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text\"], bd=0, padx=14, pady=8, cursor=\"hand2\", command=lambda: (self.recovery_results.clear(), self._refresh_recovery_tree(self.deep_recovery_tree, category=\"Deep Recovery\"))).pack(side=\"left\", padx=8)\n\n        self.deep_recovery_status = tk.Label(card, text=\"Raw signature scan ready.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"])\n        self.deep_recovery_status.pack(fill=\"x\", padx=10, pady=(0, 6))\n\n        results_outer = tk.LabelFrame(body, text=\"\ud83d\udce6 Deep Recovery Results\", font=FONTS[\"subhead\"], fg=C[\"accent2\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        results_outer.pack(fill=\"both\", expand=True, padx=14, pady=(0, 14))\n        cols = (\"Signature\", \"Type\", \"Sector\", \"Confidence\", \"Source\", \"Path\")\n        self.deep_recovery_tree = ttk.Treeview(results_outer, columns=cols, show=\"headings\", height=12, style=\"Custom.Treeview\")\n        for col, width in zip(cols, (180, 80, 120, 90, 220, 200)):\n            self.deep_recovery_tree.heading(col, text=col)\n            self.deep_recovery_tree.column(col, width=width, anchor=\"w\")\n        self.deep_recovery_tree.tag_configure(\"recovered\", foreground=C[\"success\"])\n        self.deep_recovery_tree.tag_configure(\"partial\", foreground=C[\"warning\"])\n        self.deep_recovery_tree.tag_configure(\"failed\", foreground=C[\"error\"])\n        self.deep_recovery_tree.pack(fill=\"both\", expand=True, padx=8, pady=8)\n\n        self.deep_recovery_preview = scrolledtext.ScrolledText(body, height=6, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], wrap=\"word\", bd=0, relief=\"flat\")\n        self.deep_recovery_preview.pack(fill=\"x\", padx=14, pady=(0, 10))\n        self.deep_recovery_preview.config(state=\"disabled\")\n\n        return body\n\n    def _start_deep_recovery(self):\n        source = self._resolve_disk_path(self.deep_recovery_source_var.get().strip() or DEFAULT_RAW_DISK)\n        if not source:\n            messagebox.showwarning(\"Source Missing\", \"Raw source disk/image select karein.\")\n            return\n        file_types = [e.strip().lstrip(\".\").upper() for e in self.deep_recovery_types_var.get().split(\",\") if e.strip()]\n        max_mb = self.deep_recovery_scan_mb_var.get().strip()\n        start_sector = self.deep_recovery_start_var.get().strip()\n        try:\n            max_bytes = int(max_mb) * 1024 * 1024 if max_mb and int(max_mb) &gt; 0 else None\n        except Exception:\n            max_bytes = None\n        try:\n            start_offset = int(start_sector) * SECTOR_SIZE if start_sector and int(start_sector) &gt; 0 else 0\n        except Exception:\n            start_offset = 0\n        self.recovery_results.clear()\n        self._refresh_recovery_tree(self.deep_recovery_tree, category=\"Deep Recovery\")\n        self._reset_recovery_progress(\"deep\", \"Deep scan queue \u092e\u0947\u0902 \u0939\u0948...\")\n        self.recovery_manager.submit_task(\"Deep Recovery\", self._task_deep_recovery, source, file_types, max_bytes, start_offset)\n        self.deep_recovery_status.config(text=\"Queued raw recovery scan...\", fg=C[\"accent4\"])\n\n    def _task_deep_recovery(self, task, source, file_types, max_bytes, start_offset):\n        self._ui_queue.put((\"recovery_log\", f\"[Deep Recovery] Scanning {source} from offset {start_offset} for {', '.join(file_types)}\"))\n        if _is_raw_device_path(source) and not is_admin():\n            raise PermissionError(\"Administrator rights required for raw disk scan.\")\n        def stats_cb(st):\n            st[\"tab\"] = \"deep\"\n            self._emit_recovery_scan_stats(st)\n        prog = make_progress_callback(lambda s: self._emit_recovery_scan_stats({**s, \"tab\": \"deep\"}), \"deep\")\n        def find_callback(msg):\n            self._ui_queue.put((\"recovery_log\", f\"[Deep Recovery] {msg}\"))\n            prog(msg)\n        hits = scan_disk_for_files(\n            source, max_bytes=max_bytes, start_offset=start_offset, file_types=file_types,\n            progress_callback=find_callback, stats_callback=stats_cb,\n        )\n        live_count = 0\n        for hit in hits:\n            score = 80 if hit.get(\"confidence\") == \"high\" else 55\n            try:\n                sample = self._forensic_read_at(source, int(hit.get(\"offset\", 0)), 4096)\n                conf = validate_recovered_file(sample, hit.get(\"file_type\", \"\"))\n                score = conf.score\n            except Exception:\n                pass\n            item = RecoveryResultItem(\n                item_id=f\"deep-{uuid.uuid4()}\",\n                source=source,\n                category=\"Deep Recovery\",\n                file_name=f\"{hit.get('file_type','UNKNOWN')} @ {hit.get('offset',0)}\",\n                file_type=hit.get(\"file_type\", \"RAW\"),\n                size_bytes=0,\n                recoverability_score=score,\n                status=\"signature\",\n                path=f\"{hit.get('disk_path', source)}:{hit.get('offset', 0)}\",\n                metadata=hit,\n            )\n            self.recovery_results.add(item)\n            live_count += 1\n            if live_count % 10 == 0:\n                self._emit_recovery_scan_stats({\n                    \"tab\": \"deep\", \"pct\": 90, \"files_found\": live_count,\n                    \"message\": f\"Indexing results... {live_count}/{len(hits)}\",\n                })\n        self._emit_recovery_scan_stats({\n            \"tab\": \"deep\", \"pct\": 100, \"files_found\": len(hits),\n            \"message\": f\"Complete \u2014 {len(hits)} signatures\",\n        })\n        self._ui_queue.put((\"recovery_queue\", None))\n        self._ui_queue.put((\"recovery_refresh\", None))\n        self._ui_queue.put((\"recovery_log\", f\"[Deep Recovery] Completed, {len(hits)} signatures discovered.\"))\n\n    def _build_recovery_photorec_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        self._build_recovery_progress_strip(body, \"photorec\", \"PhotoRec Pro \u2014 Live Carving Progress\")\n        card = tk.LabelFrame(body, text=\"\ud83e\udde9 PhotoRec Pro (Multi-Pass Carving)\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        card.pack(fill=\"x\", padx=14, pady=10)\n\n        self.photorec_source_var = tk.StringVar(value=\"\")\n        self.photorec_output_var = tk.StringVar(value=os.path.join(os.path.expanduser(\"~\"), \"Desktop\", \"Godawari_PhotoRec\"))\n        row = tk.Frame(card, bg=C[\"card\"])\n        row.pack(fill=\"x\", padx=10, pady=10)\n        tk.Label(row, text=\"Source Disk:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=0, column=0, sticky=\"w\")\n        self.photorec_source_combo = ttk.Combobox(row, textvariable=self.photorec_source_var, width=40, state=\"readonly\")\n        self.photorec_source_combo.grid(row=0, column=1, padx=6)\n        tk.Label(row, text=\"Output:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=1, column=0, sticky=\"w\", pady=(8, 0))\n        tk.Entry(row, textvariable=self.photorec_output_var, width=50, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).grid(row=1, column=1, padx=6, pady=(8, 0), sticky=\"w\")\n        tk.Button(row, text=\"Browse\", font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text\"], bd=0, padx=8, pady=6, cursor=\"hand2\",\n                  command=lambda: self._browse_recovery_output(self.photorec_output_var)).grid(row=1, column=2, pady=(8, 0))\n\n        info = tk.Label(card,\n            text=\"PhotoRec \u091c\u0948\u0938\u093e workflow:\\n\"\n                 \"\u2460 Auto block size  \u2461 Pass 1 aligned carving  \u2462 Pass 2 unaligned  \u2463 Validation\\n\"\n                 \"Har recovered file live list \u092e\u0947\u0902 \u0926\u093f\u0916\u0947\u0917\u0940 \u2014 progress bar real-time update \u0939\u094b\u0917\u093e\u0964\",\n            font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\")\n        info.pack(fill=\"x\", padx=12, pady=(0, 8))\n\n        action = tk.Frame(card, bg=C[\"card\"])\n        action.pack(fill=\"x\", padx=10, pady=(0, 10))\n        tk.Button(action, text=\"\u25b6 Start PhotoRec Scan\", font=(\"Segoe UI\", 10, \"bold\"), bg=C[\"btn_hw\"], fg=C[\"text\"],\n                  bd=0, padx=16, pady=10, cursor=\"hand2\", command=self._start_photorec_tab_scan).pack(side=\"left\")\n        tk.Button(action, text=\"\u23f9 Stop\", font=FONTS[\"small\"], bg=C[\"btn_danger\"], fg=C[\"text\"], bd=0, padx=12, pady=8, cursor=\"hand2\",\n                  command=self._stop_file_recovery).pack(side=\"left\", padx=8)\n\n        self.photorec_status_label = tk.Label(card, text=\"PhotoRec Pro ready.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"])\n        self.photorec_status_label.pack(fill=\"x\", padx=10, pady=(0, 8))\n\n        results = tk.LabelFrame(body, text=\"\ud83d\udce6 Live Recovered Files (PhotoRec)\", font=FONTS[\"subhead\"], fg=C[\"accent2\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        results.pack(fill=\"both\", expand=True, padx=14, pady=(0, 14))\n        cols = (\"File\", \"Type\", \"Size\", \"Pass\", \"Offset\", \"Path\")\n        self.photorec_tree = ttk.Treeview(results, columns=cols, show=\"headings\", height=14, style=\"Custom.Treeview\")\n        for col, w in zip(cols, (220, 60, 80, 50, 120, 280)):\n            self.photorec_tree.heading(col, text=col)\n            self.photorec_tree.column(col, width=w, anchor=\"w\")\n        self.photorec_tree.pack(fill=\"both\", expand=True, padx=8, pady=8)\n        return body\n\n    def _start_photorec_tab_scan(self):\n        label = self.photorec_source_var.get().strip()\n        source = self._resolve_disk_path(getattr(self, \"_recovery_disk_map\", {}).get(label, label))\n        if not source:\n            messagebox.showwarning(\"Source\", \"Disk/image select karein.\")\n            return\n        if not self._ensure_admin_for_raw_recovery(source):\n            return\n        output_dir = self.photorec_output_var.get().strip() or filedialog.askdirectory(title=\"PhotoRec output\")\n        if not output_dir:\n            return\n        try:\n            output_dir = get_recovery_safety(getattr(self, \"app_config\", None)).validate_output_dir(output_dir, source)\n        except Exception as exc:\n            messagebox.showerror(\"Safety\", str(exc))\n            return\n        if not messagebox.askyesno(\"PhotoRec Pro\", f\"Source: {source}\\nOutput: {output_dir}\\n\\nMulti-pass carving start?\"):\n            return\n        self.photorec_tree.delete(*self.photorec_tree.get_children())\n        self._reset_recovery_progress(\"photorec\", \"PhotoRec Pass 1 \u0936\u0941\u0930\u0942...\")\n        self._set_recovery_scan_mode(\"Mode: PhotoRec Pro Multi-Pass\", C[\"warning\"])\n        self.recovery_manager.submit_task(\"PhotoRec Pro\", self._task_photorec_tab_scan, source, output_dir)\n\n    def _task_photorec_tab_scan(self, task, source, output_dir):\n        files_live = [0]\n\n        def on_progress(msg):\n            prog = make_progress_callback(lambda s: self._emit_recovery_scan_stats({**s, \"tab\": \"photorec\"}), \"photorec\")\n            prog(msg)\n            self._ui_queue.put((\"recovery_log\", f\"[PhotoRec] {msg}\"))\n            m = re.search(r\"Pass\\s+\\d+:\\s+recovered\\s+(.+)\", str(msg), re.I)\n            if m:\n                fn = m.group(1).strip()\n                files_live[0] += 1\n                self._emit_recovery_scan_stats({\n                    \"tab\": \"photorec\", \"files_found\": files_live[0], \"files_recovered\": files_live[0],\n                    \"message\": f\"Recovered: {fn}\",\n                })\n                row = (fn, os.path.splitext(fn)[1].lstrip(\".\").upper() or \"?\", \"\u2014\", \"\u2014\", \"\u2014\", fn)\n                self._ui_queue.put((\"photorec_tree_row\", row))\n\n        result = multi_pass_recovery(source, output_dir, progress_callback=on_progress)\n        for item in result.get(\"files\", []):\n            row = (\n                os.path.basename(item[\"path\"]),\n                item.get(\"file_type\", \"?\"),\n                self._fmt_size(item.get(\"bytes\", 0)),\n                str(item.get(\"pass\", \"?\")),\n                f\"0x{item.get('offset', 0):X}\",\n                item[\"path\"],\n            )\n            self._ui_queue.put((\"photorec_tree_row\", row))\n        self._emit_recovery_scan_stats({\n            \"tab\": \"photorec\", \"pct\": 100,\n            \"files_found\": len(result.get(\"files\", [])),\n            \"files_recovered\": len(result.get(\"files\", [])),\n            \"message\": f\"Done \u2014 {result.get('recup_dir', output_dir)}\",\n        })\n        self._ui_queue.put((\"recovery_log\", f\"[PhotoRec] Complete: {len(result.get('files', []))} files\"))\n\n    def _build_recovery_mft_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        self._build_recovery_progress_strip(body, \"mft\", \"MFT Deleted Recovery \u2014 Live Progress\")\n        card = tk.LabelFrame(body, text=\"\ud83d\uddc2\ufe0f NTFS MFT Deleted File Recovery\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        card.pack(fill=\"x\", padx=14, pady=10)\n\n        self.mft_source_var = tk.StringVar(value=\"\")\n        self.mft_output_var = tk.StringVar(value=os.path.join(os.path.expanduser(\"~\"), \"Desktop\", \"Godawari_MFT_Recovery\"))\n        self.mft_max_records_var = tk.StringVar(value=\"8192\")\n        row = tk.Frame(card, bg=C[\"card\"])\n        row.pack(fill=\"x\", padx=10, pady=10)\n        tk.Label(row, text=\"NTFS Volume:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=0, column=0, sticky=\"w\")\n        self.mft_source_combo = ttk.Combobox(row, textvariable=self.mft_source_var, width=40, state=\"readonly\")\n        self.mft_source_combo.grid(row=0, column=1, padx=6)\n        tk.Label(row, text=\"Output:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=1, column=0, sticky=\"w\", pady=(8, 0))\n        tk.Entry(row, textvariable=self.mft_output_var, width=50, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).grid(row=1, column=1, padx=6, pady=(8, 0), sticky=\"w\")\n        tk.Button(row, text=\"Browse\", font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text\"], bd=0, padx=8, pady=6, cursor=\"hand2\",\n                  command=lambda: self._browse_recovery_output(self.mft_output_var)).grid(row=1, column=2, pady=(8, 0))\n        tk.Label(row, text=\"Max MFT Records:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=2, column=0, sticky=\"w\", pady=(8, 0))\n        tk.Entry(row, textvariable=self.mft_max_records_var, width=10, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).grid(row=2, column=1, padx=6, pady=(8, 0), sticky=\"w\")\n\n        tk.Label(card,\n                 text=\"\u092f\u0939 tab $MFT \u0938\u0947 deleted files \u0915\u0940 actual bytes recover \u0915\u0930\u0924\u0940 \u0939\u0948 (DATA runs \u2192 clusters).\\n\"\n                      \"Sirf NTFS volume \u092a\u0930 \u0915\u093e\u092e \u0915\u0930\u0947\u0917\u093e \u2014 partition/image source select \u0915\u0930\u0947\u0902\u0964\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\").pack(fill=\"x\", padx=12, pady=(0, 8))\n\n        action = tk.Frame(card, bg=C[\"card\"])\n        action.pack(fill=\"x\", padx=10, pady=(0, 10))\n        tk.Button(action, text=\"\u25b6 Recover Deleted (MFT)\", font=(\"Segoe UI\", 10, \"bold\"), bg=C[\"btn_info\"], fg=C[\"text\"],\n                  bd=0, padx=16, pady=10, cursor=\"hand2\", command=self._start_mft_deleted_recovery).pack(side=\"left\")\n\n        self.mft_status_label = tk.Label(card, text=\"MFT recovery ready.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"])\n        self.mft_status_label.pack(fill=\"x\", padx=10, pady=(0, 8))\n\n        results = tk.LabelFrame(body, text=\"\ud83d\udcc1 Recovered Deleted Files\", font=FONTS[\"subhead\"], fg=C[\"accent2\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        results.pack(fill=\"both\", expand=True, padx=14, pady=(0, 14))\n        cols = (\"File\", \"Size\", \"Status\", \"Fragmented\", \"Path\")\n        self.mft_tree = ttk.Treeview(results, columns=cols, show=\"headings\", height=14, style=\"Custom.Treeview\")\n        for col, w in zip(cols, (220, 90, 100, 80, 340)):\n            self.mft_tree.heading(col, text=col)\n            self.mft_tree.column(col, width=w, anchor=\"w\")\n        self.mft_tree.pack(fill=\"both\", expand=True, padx=8, pady=8)\n        return body\n\n    def _start_mft_deleted_recovery(self):\n        label = self.mft_source_var.get().strip()\n        source = self._resolve_disk_path(getattr(self, \"_recovery_disk_map\", {}).get(label, label))\n        if not source:\n            messagebox.showwarning(\"Source\", \"NTFS volume select karein (C: \u092f\u093e partition image).\")\n            return\n        if not self._ensure_admin_for_raw_recovery(source):\n            return\n        output_dir = self.mft_output_var.get().strip()\n        if not output_dir:\n            messagebox.showwarning(\"Output\", \"Output folder set karein.\")\n            return\n        try:\n            output_dir = get_recovery_safety(getattr(self, \"app_config\", None)).validate_output_dir(output_dir, source)\n        except Exception as exc:\n            messagebox.showerror(\"Safety\", str(exc))\n            return\n        try:\n            max_records = max(512, int(self.mft_max_records_var.get().strip()))\n        except Exception:\n            max_records = 8192\n        if not messagebox.askyesno(\"MFT Recovery\", f\"Deleted files recover karein?\\n\\nSource: {source}\\nOutput: {output_dir}\\nRecords: {max_records}\"):\n            return\n        self.mft_tree.delete(*self.mft_tree.get_children())\n        self._reset_recovery_progress(\"mft\", \"MFT scan \u0936\u0941\u0930\u0942...\")\n        self.recovery_manager.submit_task(\"MFT Deleted Recovery\", self._task_mft_deleted_recovery, source, output_dir, max_records)\n\n    def _task_mft_deleted_recovery(self, task, source, output_dir, max_records):\n        partition_offset = 0\n        if hasattr(self, \"_parse_mbr_partitions\"):\n            try:\n                sector = self._forensic_read_at(source, 0, 512)\n                parts = self._parse_mbr_partitions(sector)\n                if parts:\n                    partition_offset = int(parts[0].get(\"start_lba\", 0)) * SECTOR_SIZE\n            except Exception:\n                pass\n\n        def read_fn(offset, length):\n            task.wait_if_paused()\n            if task.is_cancelled():\n                raise InterruptedError(\"MFT recovery cancelled\")\n            return self._forensic_read_at(source, offset, length)\n\n        boot = read_fn(partition_offset, 512)\n\n        def progress_cb(st):\n            st[\"tab\"] = \"mft\"\n            self._emit_recovery_scan_stats(st)\n\n        result = recover_deleted_mft_files(\n            read_fn, partition_offset, boot, output_dir,\n            max_records=max_records, max_recover=500,\n            progress_callback=progress_cb,\n            cancel_check=task.is_cancelled,\n        )\n        for item in result.get(\"results\", []):\n            if not item.ok:\n                continue\n            row = (\n                item.file_name,\n                self._fmt_size(item.size_bytes),\n                \"\u2705 Recovered\" if item.ok else \"Failed\",\n                \"Yes\" if item.fragmented else \"No\",\n                item.output_path,\n            )\n            self._ui_queue.put((\"mft_tree_row\", row))\n            rec_item = RecoveryResultItem(\n                item_id=f\"mft-{uuid.uuid4()}\",\n                source=source,\n                category=\"MFT Deleted\",\n                file_name=item.file_name,\n                file_type=os.path.splitext(item.file_name)[1].lstrip(\".\") or \"file\",\n                size_bytes=item.size_bytes,\n                recoverability_score=85 if item.ok else 20,\n                status=\"recovered\" if item.ok else \"failed\",\n                path=item.output_path,\n                metadata={\"deleted\": item.deleted, \"fragmented\": item.fragmented},\n            )\n            self.recovery_results.add(rec_item)\n        self._emit_recovery_scan_stats({\n            \"tab\": \"mft\", \"pct\": 100,\n            \"files_found\": result.get(\"deleted_candidates\", 0),\n            \"files_recovered\": result.get(\"recovered_count\", 0),\n            \"message\": f\"MFT done \u2014 {result.get('recovered_count', 0)} files saved\",\n        })\n        self._ui_queue.put((\"recovery_queue\", None))\n        self._ui_queue.put((\"recovery_refresh\", None))\n        self._ui_queue.put((\"recovery_log\",\n            f\"[MFT] Deleted candidates: {result.get('deleted_candidates', 0)}, \"\n            f\"Recovered: {result.get('recovered_count', 0)} \u2192 {output_dir}\"))\n\n    def _build_recovery_raw_carve_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        card = tk.LabelFrame(body, text=\"\ud83e\udde9 RAW Carving\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        card.pack(fill=\"x\", padx=14, pady=10)\n\n        self.raw_carve_source_var = tk.StringVar(value=DEFAULT_RAW_DISK)\n        self.raw_carve_offset_var = tk.StringVar(value=\"0\")\n        self.raw_carve_length_var = tk.StringVar(value=\"65536\")\n\n        row = tk.Frame(card, bg=C[\"card\"])\n        row.pack(fill=\"x\", padx=10, pady=10)\n        tk.Label(row, text=\"Source:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=0, column=0, sticky=\"w\")\n        self.raw_carve_source_combo = ttk.Combobox(row, textvariable=self.raw_carve_source_var, values=self._get_recovery_disk_values(), width=36, state=\"readonly\")\n        self.raw_carve_source_combo.grid(row=0, column=1, padx=4)\n        tk.Label(row, text=\"Offset:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=1, column=0, pady=(8,0), sticky=\"w\")\n        tk.Entry(row, textvariable=self.raw_carve_offset_var, width=16, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).grid(row=1, column=1, padx=4, pady=(8,0), sticky=\"w\")\n        tk.Label(row, text=\"Length:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=1, column=2, padx=(18,4), pady=(8,0), sticky=\"w\")\n        tk.Entry(row, textvariable=self.raw_carve_length_var, width=12, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).grid(row=1, column=3, padx=4, pady=(8,0), sticky=\"w\")\n\n        action_row = tk.Frame(card, bg=C[\"card\"])\n        action_row.pack(fill=\"x\", padx=10, pady=(0, 6))\n        tk.Button(action_row, text=\"\ud83e\uddea Analyze Range\", font=FONTS[\"small\"], bg=C[\"btn_chip\"], fg=C[\"text\"], bd=0, padx=14, pady=8, cursor=\"hand2\", command=self._run_raw_carve).pack(side=\"left\")\n        tk.Button(action_row, text=\"\ud83e\uddf9 Clear\", font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text\"], bd=0, padx=14, pady=8, cursor=\"hand2\", command=lambda: self.raw_carve_output.config(state=\"normal\") or self.raw_carve_output.delete(\"1.0\",\"end\") or self.raw_carve_output.config(state=\"disabled\")).pack(side=\"left\", padx=8)\n\n        self.raw_carve_output = scrolledtext.ScrolledText(body, height=12, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], wrap=\"word\", bd=0, relief=\"flat\")\n        self.raw_carve_output.pack(fill=\"both\", expand=True, padx=14, pady=(0, 14))\n        self.raw_carve_output.config(state=\"disabled\")\n        return body\n\n    def _run_raw_carve(self):\n        source = self._resolve_disk_path(self.raw_carve_source_var.get().strip() or DEFAULT_RAW_DISK)\n        try:\n            offset = int(self.raw_carve_offset_var.get().strip())\n            length = max(4096, int(self.raw_carve_length_var.get().strip()))\n        except Exception:\n            messagebox.showwarning(\"Invalid Range\", \"Offset aur length numeric hone chahiye.\")\n            return\n        try:\n            data = self._forensic_read_at(source, offset, length)\n            if not data:\n                raise IOError(\"No data read from raw source\")\n            analysis = [f\"Source: {source}\", f\"Offset: {offset}\", f\"Length: {len(data)} bytes\", \"\"]\n            patterns = {\n                \"JPEG\": b\"\\xff\\xd8\\xff\",\n                \"PNG\": b\"\\x89PNG\\r\\n\\x1a\\n\",\n                \"PDF\": b\"%PDF\",\n                \"PE\": b\"MZ\",\n                \"ZIP\": b\"PK\",\n            }\n            for name, sig in patterns.items():\n                idx = data.find(sig)\n                if idx &gt;= 0:\n                    analysis.append(f\"Found {name} signature at offset {offset + idx}\")\n            if len(analysis) == 4:\n                analysis.append(\"No known signatures found in the selected region.\")\n            analysis.append(\"\\nPreview (first 256 bytes):\")\n            analysis.append(data[:256].hex(\" \"))\n            self.raw_carve_output.config(state=\"normal\")\n            self.raw_carve_output.delete(\"1.0\", \"end\")\n            self.raw_carve_output.insert(\"end\", \"\\n\".join(analysis))\n            self.raw_carve_output.config(state=\"disabled\")\n            self._ui_queue.put((\"recovery_log\", f\"[RAW Carving] Analyzed {length} bytes from {source}@{offset}\"))\n        except Exception as exc:\n            messagebox.showerror(\"Raw Carve Error\", str(exc))\n            self._ui_queue.put((\"recovery_log\", f\"[RAW Carving] Error: {exc}\"))\n\n    def _build_recovery_partitions_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        card = tk.LabelFrame(body, text=\"\ud83e\udded Partition Recovery\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        card.pack(fill=\"x\", padx=14, pady=10)\n        self.partition_source_var = tk.StringVar(value=DEFAULT_RAW_DISK)\n\n        top_row = tk.Frame(card, bg=C[\"card\"])\n        top_row.pack(fill=\"x\", padx=4, pady=(6,4))\n\n        # Left: Detected disks list\n        left = tk.Frame(top_row, bg=C[\"card\"])\n        left.pack(side=\"left\", fill=\"y\", padx=(6,8))\n        tk.Label(left, text=\"Detected Disks:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\")\n        cols = (\"#\", \"Name\", \"Size\")\n        self.detected_disks_tree = ttk.Treeview(left, columns=cols, show=\"headings\", height=6, style=\"Custom.Treeview\")\n        for col, w in zip(cols, (40, 320, 120)):\n            self.detected_disks_tree.heading(col, text=col)\n            self.detected_disks_tree.column(col, width=w, anchor=\"w\")\n        self.detected_disks_tree.pack(fill=\"both\", expand=False)\n        self.detected_disks_tree.bind(\"&lt;&gt;\", lambda e: None)\n        tk.Button(left, text=\"\ud83d\udd04 Refresh\", font=FONTS[\"small\"], bg=C[\"btn\"], fg=C[\"text\"], bd=0, padx=8, pady=6, cursor=\"hand2\", command=lambda: self._launch_job(\"recovery_populate_disks\", self._populate_recovery_disks)).pack(pady=6)\n\n        # Middle: actions\n        mid = tk.Frame(top_row, bg=C[\"card\"])\n        mid.pack(side=\"left\", fill=\"y\", padx=(4,8))\n        tk.Label(mid, text=\"Actions:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\")\n        tk.Button(mid, text=\"\ud83e\udde0 Scan Selected Disk\", font=FONTS[\"small\"], bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=10, pady=8, cursor=\"hand2\", command=self._start_scan_partitions).pack(fill=\"x\", pady=4)\n        tk.Button(mid, text=\"\ud83d\uddc2 Recover Selected Partition\", font=FONTS[\"small\"], bg=C[\"btn_warn\"], fg=C[\"text\"], bd=0, padx=10, pady=8, cursor=\"hand2\", command=self._start_recover_partition).pack(fill=\"x\", pady=4)\n\n        # Right: progress + partition details\n        right = tk.Frame(top_row, bg=C[\"card\"])\n        right.pack(side=\"left\", fill=\"both\", expand=True, padx=(4,6))\n        self.partition_progress_var = tk.DoubleVar(value=0.0)\n        self.partition_progress_bar = ttk.Progressbar(right, variable=self.partition_progress_var, maximum=100.0, mode=\"determinate\")\n        self.partition_progress_bar.pack(fill=\"x\", pady=(4,6))\n        self.partition_status_label = tk.Label(right, text=\"Ready\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"])\n        self.partition_status_label.pack(anchor=\"w\")\n\n        self.partition_info_text = scrolledtext.ScrolledText(right, height=12, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], wrap=\"word\", bd=0, relief=\"flat\")\n        self.partition_info_text.pack(fill=\"both\", expand=True, padx=4, pady=(6,4))\n        self.partition_info_text.config(state=\"disabled\")\n\n        # Partition results tree (below)\n        results_frame = tk.LabelFrame(body, text=\"Partitions / Results\", font=FONTS[\"subhead\"], fg=C[\"accent2\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        results_frame.pack(fill=\"both\", expand=True, padx=14, pady=(6, 12))\n        pcols = (\"Index\", \"Type\", \"Start LBA\", \"Sectors\", \"Size\")\n        self.partition_tree = ttk.Treeview(results_frame, columns=pcols, show=\"headings\", height=8, style=\"Custom.Treeview\")\n        for col, w in zip(pcols, (60, 120, 120, 120, 120)):\n            self.partition_tree.heading(col, text=col)\n            self.partition_tree.column(col, width=w, anchor=\"w\")\n        self.partition_tree.pack(fill=\"both\", expand=True, padx=8, pady=8)\n\n        # Ensure disks enumerated at build time\n        try:\n            self._launch_job(\"populate_recovery_disks\", self._populate_recovery_disks)\n        except Exception:\n            pass\n\n        return body\n\n    def _refresh_recovery_partitions(self):\n        source = self._resolve_disk_path(self.partition_source_var.get().strip() or DEFAULT_RAW_DISK)\n        try:\n            sector = self._forensic_read_at(source, 0, 512)\n            parts = self._parse_mbr_partitions(sector)\n            gpt = self._parse_gpt_entries(source)\n            lines = [f\"Source: {source}\", f\"MBR partitions: {len(parts)}\"]\n            for part in parts:\n                lines.append(f\"  #{part['index']} type={part['type']} start={part['start_lba']} sectors={part['sectors']} size={self._fmt_size(part['size'])}\")\n            if gpt:\n                lines.append(f\"GPT entries: {len(gpt.get('partitions', []))}\")\n                for part in gpt.get('partitions', []):\n                    lines.append(f\"  #{part['index']} name={part['name']} first={part['first_lba']} last={part['last_lba']} size={self._fmt_size(part['size'])}\")\n            if not parts and not gpt:\n                lines.append(\"No valid MBR/GPT partition table detected.\")\n        except Exception as exc:\n            lines = [f\"Partition parse failed: {exc}\"]\n        self.partition_info_text.config(state=\"normal\")\n        self.partition_info_text.delete(\"1.0\", \"end\")\n        self.partition_info_text.insert(\"end\", \"\\n\".join(lines))\n        self.partition_info_text.config(state=\"disabled\")\n        self._ui_queue.put((\"recovery_log\", f\"[Partition Recovery] Parsed partitions for {source}\"))\n\n    def _start_scan_partitions(self):\n        try:\n            sel = self.detected_disks_tree.selection()\n            if not sel:\n                messagebox.showwarning(\"Select Disk\", \"Koi disk select nahi hua. Pehle disk select karo.\")\n                return\n            disk_path = sel[0]\n            self.partition_source_var.set(disk_path)\n            self.partition_status_label.config(text=f\"Queued scan for {disk_path}\")\n            self.recovery_manager.submit_task(\"Scan Partitions\", self._task_scan_partitions, disk_path)\n        except Exception as e:\n            self._ui_queue.put((\"recovery_log\", f\"[Partition Recovery] Scan start failed: {e}\"))\n\n    def _task_scan_partitions(self, task, source):\n        try:\n            self._ui_queue.put((\"recovery_log\", f\"[Partition Recovery] Scanning partitions on {source}\"))\n            self._ui_queue.put((\"clone_progress\", (0, f\"Scanning {source}\", \"partition\")))\n            # Read and parse\n            sector = self._forensic_read_at(source, 0, 512)\n            parts = self._parse_mbr_partitions(sector)\n            gpt = self._parse_gpt_entries(source)\n            # Update partition tree in UI thread\n            def _update_tree():\n                try:\n                    self.partition_tree.delete(*self.partition_tree.get_children())\n                except Exception:\n                    pass\n                try:\n                    for part in parts:\n                        self.partition_tree.insert(\"\", \"end\", values=(part.get('index'), part.get('type'), part.get('start_lba'), part.get('sectors'), self._fmt_size(part.get('size'))))\n                    if gpt:\n                        for part in gpt.get('partitions', []):\n                            self.partition_tree.insert(\"\", \"end\", values=(part.get('index'), part.get('type','GPT'), part.get('first_lba'), part.get('last_lba') - part.get('first_lba') + 1, self._fmt_size(part.get('size'))))\n                except Exception:\n                    pass\n            self.after(0, _update_tree)\n            self._ui_queue.put((\"recovery_log\", f\"[Partition Recovery] Scan complete: {len(parts) + (len(gpt.get('partitions', [])) if gpt else 0)} partitions found\"))\n            self._ui_queue.put((\"clone_progress\", (100, \"Partition scan complete\", \"partition\")))\n        except Exception as exc:\n            self._ui_queue.put((\"recovery_log\", f\"[Partition Recovery] Scan failed: {exc}\"))\n            self._ui_queue.put((\"clone_progress\", (0, f\"Scan failed: {exc}\", \"partition\")))\n            raise\n\n    def _start_recover_partition(self):\n        try:\n            sel = self.partition_tree.selection()\n            if not sel:\n                messagebox.showwarning(\"Select Partition\", \"Koi partition select nahi hua. Pehle partition select karo.\")\n                return\n            vals = self.partition_tree.item(sel[0], 'values')\n            if not vals or len(vals) &lt; 4:\n                messagebox.showwarning(\"Invalid\", \"Selected partition data invalid.\")\n                return\n            start_lba = int(vals[2])\n            sectors = int(vals[3])\n            source = self.partition_source_var.get().strip() or DEFAULT_RAW_DISK\n            target = filedialog.asksaveasfilename(title=\"Save partition image as\", defaultextension=\".img\", filetypes=[(\"IMG\", \"*.img *.dd *.raw\"),(\"All\",\"*.*\")])\n            if not target:\n                return\n            if not messagebox.askyesno(\"Recover Partition\", f\"Recover partition start={start_lba} sectors={sectors} to:\\n{target}?\\nProceed?\"):\n                return\n            try:\n                get_recovery_safety(getattr(self, \"app_config\", None)).validate_write_path(target, source)\n            except Exception as exc:\n                messagebox.showerror(\"Recovery Safety\", str(exc))\n                return\n            max_bytes = sectors * SECTOR_SIZE\n            start_offset = start_lba * SECTOR_SIZE\n            self.recovery_manager.submit_task(\"Recover Partition\", self._task_recover_partition, source, start_offset, max_bytes, target)\n            self._ui_queue.put((\"recovery_log\", f\"[Partition Recovery] Queued partition recovery: {source} @ {start_lba}\"))\n        except Exception as e:\n            self._ui_queue.put((\"recovery_log\", f\"[Partition Recovery] Recover start failed: {e}\"))\n\n    def _task_recover_partition(self, task, source, start_offset, max_bytes, target_path):\n        try:\n            self._ui_queue.put((\"recovery_log\", f\"[Partition Recovery] Recovering {source}@{start_offset} -&gt; {target_path}\"))\n            def progress_cb(msg):\n                try:\n                    text = str(msg or \"\")\n                    m = re.search(r\"(\\d{1,3})%\", text)\n                    pct = int(m.group(1)) if m else 0\n                    self._ui_queue.put((\"clone_progress\", (pct, text, \"partition\")))\n                    self._ui_queue.put((\"recovery_log\", f\"[Partition Recovery] {text}\"))\n                except Exception:\n                    pass\n            copy_disk_range_to_img(source, target_path, start_offset=start_offset, max_bytes=max_bytes, progress_callback=progress_cb)\n            self._ui_queue.put((\"clone_progress\", (100, f\"Recovered: {target_path}\", \"partition\")))\n            self._ui_queue.put((\"recovery_log\", f\"[Partition Recovery] Recovery complete: {target_path}\"))\n        except Exception as e:\n            self._ui_queue.put((\"recovery_log\", f\"[Partition Recovery] Recovery failed: {e}\"))\n            self._ui_queue.put((\"clone_progress\", (0, f\"Recover failed: {e}\", \"partition\")))\n            raise\n\n    def _clone_selected_disk(self):\n        try:\n            source = self._resolve_disk_path(self.partition_source_var.get().strip() or DEFAULT_RAW_DISK)\n            path = filedialog.asksaveasfilename(\n                title=\"Save disk image as\",\n                defaultextension=\".img\",\n                filetypes=[(\"Disk image\", \"*.img *.dd *.raw\"), (\"All files\", \"*.*\")],\n                initialfile=f\"disk_clone_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.img\",\n            )\n            if not path:\n                return\n            if not messagebox.askyesno(\"Clone Disk\", f\"Clone {source} to:\\n{path}?\\n\\nProceed?\"):\n                return\n            if hasattr(self, \"clone_status_label\"):\n                self.clone_status_label.config(text=f\"\ud83d\udd04 Cloning {os.path.basename(source)} \u2192 {os.path.basename(path)}...\")\n            if hasattr(self, \"clone_progress_var\"):\n                try:\n                    self.clone_progress_var.set(0.0)\n                except Exception:\n                    pass\n            self.recovery_manager.submit_task(\"Clone Disk\", self._task_clone_disk, source, path)\n            self._ui_queue.put((\"recovery_log\", f\"[Clone Disk] Queued clone: {source} -&gt; {path}\"))\n        except Exception as e:\n            self._ui_queue.put((\"recovery_log\", f\"[Clone Disk] Error queuing clone: {e}\"))\n\n    def _task_clone_disk(self, task, source, img_path):\n        try:\n            self._ui_queue.put((\"recovery_log\", f\"[Clone Disk] Starting clone {source} -&gt; {img_path}\"))\n            def progress_cb(msg):\n                try:\n                    text = str(msg or \"\")\n                    # Send log line\n                    self._ui_queue.put((\"recovery_log\", f\"[Clone Disk] {text}\"))\n                    # Extract percentage if present\n                    m = re.search(r\"(\\d{1,3})%\", text)\n                    if m:\n                        try:\n                            pct = int(m.group(1))\n                        except Exception:\n                            pct = 0\n                        self._ui_queue.put((\"clone_progress\", (pct, text, \"clone\")))\n                    else:\n                        # If no percent, send text-only update\n                        self._ui_queue.put((\"clone_progress\", (0, text, \"clone\")))\n                except Exception:\n                    pass\n            # Use existing create_disk_image helper\n            # Reset UI\n            self._ui_queue.put((\"clone_progress\", (0, \"Starting clone...\", \"clone\")))\n            create_disk_image(source, img_path, max_bytes=None, progress_callback=progress_cb)\n            self._ui_queue.put((\"clone_progress\", (100, f\"Completed: {img_path}\", \"clone\")))\n            self._ui_queue.put((\"recovery_log\", f\"[Clone Disk] Completed: {img_path}\"))\n            self._ui_queue.put((\"recovery_queue\", None))\n        except Exception as e:\n            self._ui_queue.put((\"recovery_log\", f\"[Clone Disk] Failed: {e}\"))\n            try:\n                self._ui_queue.put((\"clone_progress\", (0, f\"Failed: {e}\", \"clone\")))\n            except Exception:\n                pass\n            raise\n\n    def _build_recovery_nand_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        card = tk.LabelFrame(body, text=\"\u26a1 NAND / Flash Analysis\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        card.pack(fill=\"x\", padx=14, pady=10)\n\n        self.nand_source_var = tk.StringVar(value=DEFAULT_RAW_DISK)\n        self.nand_sample_var = tk.StringVar(value=\"16\")\n\n        row = tk.Frame(card, bg=C[\"card\"])\n        row.pack(fill=\"x\", padx=10, pady=10)\n        tk.Label(row, text=\"Source:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=0, column=0, sticky=\"w\")\n        self.nand_source_combo = ttk.Combobox(row, textvariable=self.nand_source_var, values=self._get_recovery_disk_values(), width=40, state=\"readonly\")\n        self.nand_source_combo.grid(row=0, column=1, padx=4)\n        tk.Label(row, text=\"Sample MB:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=0, column=2, padx=(14,4), sticky=\"w\")\n        tk.Entry(row, textvariable=self.nand_sample_var, width=6, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).grid(row=0, column=3, padx=4)\n        tk.Button(row, text=\"Analyze NAND\", font=FONTS[\"small\"], bg=C[\"btn_warn\"], fg=C[\"text\"], bd=0, padx=14, pady=8, cursor=\"hand2\", command=self._start_nand_analysis).grid(row=0, column=4, padx=(14,0))\n\n        self.nand_analysis_output = scrolledtext.ScrolledText(body, height=14, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], wrap=\"word\", bd=0, relief=\"flat\")\n        self.nand_analysis_output.pack(fill=\"both\", expand=True, padx=14, pady=(0, 14))\n        self.nand_analysis_output.config(state=\"disabled\")\n        return body\n\n    def _start_nand_analysis(self):\n        source = self._resolve_disk_path(self.nand_source_var.get().strip() or DEFAULT_RAW_DISK)\n        try:\n            sample_mb = max(1, int(self.nand_sample_var.get().strip()))\n        except Exception:\n            sample_mb = 16\n        self.recovery_manager.submit_task(\"NAND Analysis\", self._task_nand_analysis, source, sample_mb)\n        self._ui_queue.put((\"recovery_log\", f\"[NAND Analysis] Queued analysis for {source}\"))\n\n    def _task_nand_analysis(self, task, source, sample_mb):\n        self._ui_queue.put((\"recovery_log\", f\"[NAND Analysis] Sampling {sample_mb} MB from {source}\"))\n        try:\n            max_bytes = sample_mb * 1024 * 1024\n            sample_len = min(max_bytes, 4 * 1024 * 1024)\n            data = self._forensic_read_at(source, 0, sample_len)\n            if is_forensic_engine_available():\n                max_chunks = max(1, sample_mb // 4)\n                entropy_chunks = scan_disk_entropy(source, chunk_size=4 * 1024 * 1024, max_chunks=max_chunks)\n                erase_state = detect_nand_erase_state(data or b\"\")\n                headers = validate_media_headers(data or b\"\")\n                avg_entropy = (\n                    sum(e for _, e in entropy_chunks) / len(entropy_chunks) if entropy_chunks else 0.0\n                )\n                output = [\n                    f\"Source: {source}\",\n                    f\"Sample bytes: {len(data or b'')}\",\n                    f\"Avg entropy (chunks): {avg_entropy:.3f}\",\n                    f\"Entropy chunks: {len(entropy_chunks)}\",\n                    f\"Erase state: {erase_state}\",\n                    f\"Header validation: {headers}\",\n                ]\n            else:\n                entropy = self._shannon_entropy(data or b\"\")\n                erase_state = detect_nand_erase_state(data or b\"\")\n                output = [\n                    f\"Source: {source}\",\n                    f\"Forensic engine unavailable. Fallback entropy: {entropy:.2f}\",\n                    f\"Erase state: {erase_state}\",\n                ]\n            self.after(0, lambda out=\"\\n\".join(output): self._display_nand_output(out))\n            self._ui_queue.put((\"recovery_log\", f\"[NAND Analysis] Completed for {source}\"))\n        except Exception as exc:\n            self._ui_queue.put((\"recovery_log\", f\"[NAND Analysis] Error: {exc}\"))\n            raise\n\n    def _display_nand_output(self, text):\n        if not hasattr(self, \"nand_analysis_output\"):\n            return\n        self.nand_analysis_output.config(state=\"normal\")\n        self.nand_analysis_output.delete(\"1.0\", \"end\")\n        self.nand_analysis_output.insert(\"end\", text)\n        self.nand_analysis_output.config(state=\"disabled\")\n\n    def _build_recovery_queue_tab(self, parent):\n        body = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(body, \"\ud83d\udccc Recovery Queue\", \"Queued forensic and recovery tasks with cancel/pause control.\")\n        control_row = tk.Frame(body, bg=C[\"bg\"])\n        control_row.pack(fill=\"x\", padx=16, pady=(8, 2))\n        tk.Button(control_row, text=\"\u26d4 Cancel Selected\", font=FONTS[\"small\"], bg=C[\"btn_danger\"], fg=C[\"text\"], bd=0, padx=12, pady=6, cursor=\"hand2\", command=self._recovery_cancel_selected).pack(side=\"left\", padx=4)\n        tk.Button(control_row, text=\"\u23f8 Pause Selected\", font=FONTS[\"small\"], bg=C[\"btn_warn\"], fg=C[\"text\"], bd=0, padx=12, pady=6, cursor=\"hand2\", command=self._recovery_pause_selected).pack(side=\"left\", padx=4)\n        tk.Button(control_row, text=\"\u25b6 Resume Selected\", font=FONTS[\"small\"], bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=12, pady=6, cursor=\"hand2\", command=self._recovery_resume_selected).pack(side=\"left\", padx=4)\n\n        tree_frame = tk.Frame(body, bg=C[\"card\"])\n        tree_frame.pack(fill=\"both\", expand=True, padx=16, pady=10)\n        cols = (\"Task\", \"Status\", \"Progress\", \"Message\")\n        self.recovery_queue_tree = ttk.Treeview(tree_frame, columns=cols, show=\"headings\", style=\"Custom.Treeview\")\n        for col, width in zip(cols, (260, 120, 100, 420)):\n            self.recovery_queue_tree.heading(col, text=col)\n            self.recovery_queue_tree.column(col, width=width, anchor=\"w\")\n        self.recovery_queue_tree.pack(fill=\"both\", expand=True, side=\"left\")\n        yscroll = ttk.Scrollbar(tree_frame, orient=\"vertical\", command=self.recovery_queue_tree.yview)\n        yscroll.pack(side=\"right\", fill=\"y\")\n        self.recovery_queue_tree.configure(yscrollcommand=yscroll.set)\n        return body\n\n    def _recovery_cancel_selected(self):\n        sel = self.recovery_queue_tree.selection()\n        if not sel:\n            messagebox.showinfo(\"Select Task\", \"Ek task select karo.\")\n            return\n        for iid in sel:\n            self.recovery_manager.cancel_task(iid)\n        self._refresh_recovery_queue_tree()\n\n    def _recovery_pause_selected(self):\n        sel = self.recovery_queue_tree.selection()\n        if not sel:\n            messagebox.showinfo(\"Select Task\", \"Ek task select karo.\")\n            return\n        for iid in sel:\n            self.recovery_manager.pause_task(iid)\n        self._refresh_recovery_queue_tree()\n\n    def _recovery_resume_selected(self):\n        sel = self.recovery_queue_tree.selection()\n        if not sel:\n            messagebox.showinfo(\"Select Task\", \"Ek task select karo.\")\n            return\n        for iid in sel:\n            self.recovery_manager.resume_task(iid)\n        self._refresh_recovery_queue_tree()\n\n    def _build_recovery_logs_tab(self, parent):\n        body = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(body, \"\ud83d\udcda Recovery Logs\", \"Centralized log stream for recovery operations.\")\n        self.recovery_log_text = scrolledtext.ScrolledText(body, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], wrap=\"word\", bd=0, relief=\"flat\")\n        self.recovery_log_text.pack(fill=\"both\", expand=True, padx=16, pady=(10, 10))\n        self.recovery_log_text.config(state=\"disabled\")\n        btn_row = tk.Frame(body, bg=C[\"bg\"])\n        btn_row.pack(fill=\"x\", padx=16, pady=(0, 10))\n        tk.Button(btn_row, text=\"\ud83d\uddd1 Clear Log\", font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text\"], bd=0, padx=12, pady=6, cursor=\"hand2\", command=lambda: (self.recovery_log_text.config(state=\"normal\"), self.recovery_log_text.delete(\"1.0\",\"end\"), self.recovery_log_text.config(state=\"disabled\"))).pack(side=\"left\", padx=4)\n        tk.Button(btn_row, text=\"\ud83d\udcbe Save Log\", font=FONTS[\"small\"], bg=C[\"accent2\"], fg=\"#000\", bd=0, padx=12, pady=6, cursor=\"hand2\", command=self._save_recovery_log).pack(side=\"left\", padx=4)\n        return body\n\n    def _save_recovery_log(self):\n        try:\n            data = self.recovery_log_text.get(\"1.0\", \"end\").strip()\n            if not data:\n                messagebox.showinfo(\"No Log\", \"Recovery log empty hai.\")\n                return\n            path = os.path.join(os.path.expanduser(\"~\"), \"Desktop\", f\"Godawari_Recovery_Log_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.txt\")\n            with open(path, \"w\", encoding=\"utf-8\") as f:\n                f.write(data)\n            messagebox.showinfo(\"Saved\", f\"Log saved to Desktop:\\n{path}\")\n        except Exception as exc:\n            messagebox.showerror(\"Save Failed\", str(exc))\n\n    def _build_recovery_history_tab(self, parent):\n        body = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(body, \"\ud83d\uddc4\ufe0f Recovery History\", \"Session history and recovered object timeline.\")\n        btn_row = tk.Frame(body, bg=C[\"bg\"])\n        btn_row.pack(fill=\"x\", padx=16, pady=(8, 4))\n        tk.Button(btn_row, text=\"\ud83d\udd04 Refresh\", font=FONTS[\"small\"], bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=12, pady=6, cursor=\"hand2\", command=self._refresh_recovery_history).pack(side=\"left\")\n        self.recovery_history_tree = ttk.Treeview(body, columns=(\"Session\", \"Date\", \"Files\", \"Location\"), show=\"headings\", style=\"Custom.Treeview\")\n        for col, width in zip((\"Session\", \"Date\", \"Files\", \"Location\"), (220, 140, 90, 420)):\n            self.recovery_history_tree.heading(col, text=col)\n            self.recovery_history_tree.column(col, width=width, anchor=\"w\")\n        self.recovery_history_tree.pack(fill=\"both\", expand=True, padx=16, pady=(8, 12))\n        self._refresh_recovery_history()\n        return body\n\n    def _refresh_recovery_history(self):\n        tree = getattr(self, \"recovery_history_tree\", None)\n        if tree is None:\n            return\n        try:\n            for iid in tree.get_children():\n                tree.delete(iid)\n            base = getattr(self, \"recovery_sessions_dir\", os.path.join(os.path.expanduser(\"~\"), \"Desktop\"))\n            if not os.path.exists(base):\n                os.makedirs(base, exist_ok=True)\n            entries = []\n            for root, _, files in os.walk(base):\n                for fn in files:\n                    if fn.lower().endswith(\".json\") or fn.lower().endswith(\".log\"):\n                        path = os.path.join(root, fn)\n                        entries.append((fn, datetime.datetime.fromtimestamp(os.path.getmtime(path)).strftime(\"%Y-%m-%d %H:%M:%S\"), \"1\", root))\n            for row in sorted(entries, key=lambda x: x[1], reverse=True)[:80]:\n                tree.insert(\"\", \"end\", values=row)\n        except Exception:\n            pass\n\n    def _shannon_entropy(self, data: bytes) -&gt; float:\n        if not data:\n            return 0.0\n        freq = {}\n        for byte in data:\n            freq[byte] = freq.get(byte, 0) + 1\n        entropy = 0.0\n        length = len(data)\n        for count in freq.values():\n            p = count / length\n            entropy -= p * (0 if p &lt;= 0 else math.log2(p))\n        return entropy\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # ZONE C BACKEND \u2014 Batch Integrity Verifier\n    # Real SHA256 file hashing, fully threaded, queue-throttled UI updates\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _integ_log_write(self, msg):\n        \"\"\"Thread-safe write into Zone C log via after().\"\"\"\n        def _w():\n            try:\n                self._integ_log.config(state=\"normal\")\n                self._integ_log.insert(\"end\", msg + \"\\n\")\n                self._integ_log.see(\"end\")\n                self._integ_log.config(state=\"disabled\")\n            except Exception:\n                pass\n        self.after(0, _w)\n\n    def _integ_use_rec_dest(self):\n        \"\"\"Populate integrity folder from last known recovery destination.\"\"\"\n        d = getattr(self, \"_last_recovery_dest\", \"\")\n        if d and os.path.isdir(d):\n            self._integ_dir_var.set(d)\n        else:\n            messagebox.showinfo(\"No Dest\", \"Pehle Zone A/B se files recover karo, folder auto-fill ho jayega.\")\n\n    def _start_integrity_verifier(self):\n        \"\"\"Atomic-guarded launcher for Zone C background thread.\"\"\"\n        with self._rec_integrity_lock:\n            if self._recovery_is_processing:\n                messagebox.showwarning(\"Busy\", \"Ek operation pehle se chal raha hai. Wait karo.\")\n                return\n            folder = self._integ_dir_var.get().strip()\n            if not folder or not os.path.isdir(folder):\n                messagebox.showwarning(\"Folder\", \"Valid folder select karo.\")\n                return\n            self._recovery_is_processing = True\n            self._integ_run_btn.config(state=\"disabled\")\n\n        self._launch_job(\n            \"integrity_verify\",\n            self._do_integrity_verify,\n            folder,\n            self._integ_recurse_var.get(),\n            self._integ_export_var.get()\n        )\n\n    def _do_integrity_verify(self, folder, recurse, export_csv):\n        \"\"\"\n        Background worker \u2014 Zone C.\n        Walks folder, computes real SHA256 of every file, checks size / readability.\n        UI updates throttled to once per 120 ms via time.monotonic() guard.\n        No time.sleep() fakes. Every byte read is real OS I/O.\n        \"\"\"\n        results = []          # (path, size_bytes, sha256, status)\n        total_files  = 0\n        ok_files     = 0\n        corrupt_files = 0\n        zero_files   = 0\n        last_ui      = time.monotonic()\n\n        try:\n            # \u2500\u2500 collect files \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            all_files = []\n            if recurse:\n                for root_d, _, fnames in os.walk(folder):\n                    for fn in fnames:\n                        all_files.append(os.path.join(root_d, fn))\n            else:\n                for fn in os.listdir(folder):\n                    fp = os.path.join(folder, fn)\n                    if os.path.isfile(fp):\n                        all_files.append(fp)\n\n            total_files = len(all_files)\n            self._integ_log_write(f\"\u25b6 {total_files} files mili \u2014 SHA256 verification shuru\u2026\")\n\n            def _ui_update(idx, msg, pct):\n                now = time.monotonic()\n                if now - last_ui &gt;= 0.120:\n                    def _upd(m=msg, p=pct):\n                        try:\n                            self._integ_stat_lbl.config(text=m)\n                            self._integ_prog_var.set(p)\n                        except Exception:\n                            pass\n                    self.after(0, _upd)\n                    return now\n                return last_ui\n\n            for idx, fp in enumerate(all_files):\n                try:\n                    fsize = os.path.getsize(fp)\n                    if fsize == 0:\n                        status = \"ZERO_BYTE\"\n                        sha = \"\u2014\"\n                        zero_files += 1\n                    else:\n                        h = hashlib.sha256()\n                        try:\n                            with open(fp, \"rb\") as fh:\n                                for chunk in iter(lambda: fh.read(65536), b\"\"):\n                                    h.update(chunk)\n                            sha = h.hexdigest()\n                            status = \"OK\"\n                            ok_files += 1\n                        except (PermissionError, OSError) as read_err:\n                            sha = \"READ_ERROR\"\n                            status = f\"CORRUPT ({read_err.__class__.__name__})\"\n                            corrupt_files += 1\n                    results.append((fp, fsize, sha, status))\n                    pct = round((idx + 1) / max(total_files, 1) * 100, 1)\n                    msg_txt = (f\"\ud83d\udd10 Verifying {idx+1}/{total_files} | \u2705{ok_files} OK \"\n                               f\"| \u26a0{corrupt_files} Corrupt | 0\ufe0f\u20e3{zero_files} Zero\")\n                    last_ui = _ui_update(idx, msg_txt, pct)\n\n                    if status != \"OK\":\n                        self._integ_log_write(f\"  [{status}] {os.path.basename(fp)}\")\n\n                except Exception as file_err:\n                    results.append((fp, 0, \"ERROR\", str(file_err)))\n                    corrupt_files += 1\n                    self._integ_log_write(f\"  \u274c {os.path.basename(fp)}: {file_err}\")\n\n            # \u2500\u2500 final UI \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            final_msg = (f\"\u2705 Verification complete \u2014 {ok_files} OK | \"\n                         f\"{corrupt_files} Corrupt/Unreadable | {zero_files} Zero-byte\")\n            self.after(0, lambda: self._integ_stat_lbl.config(text=final_msg))\n            self.after(0, lambda: self._integ_prog_var.set(100))\n            self._integ_log_write(final_msg)\n\n            # \u2500\u2500 CSV export \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            if export_csv and results:\n                out_path = os.path.join(folder, f\"integrity_report_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.csv\")\n                try:\n                    with open(out_path, \"w\", newline=\"\", encoding=\"utf-8-sig\") as cf:\n                        w = csv.writer(cf)\n                        w.writerow([\"Path\", \"Size_Bytes\", \"SHA256\", \"Status\"])\n                        w.writerows(results)\n                    self._integ_log_write(f\"\ud83d\udce5 CSV saved: {out_path}\")\n                    self.after(0, lambda p=out_path: messagebox.showinfo(\n                        \"Report Saved\", f\"\u2705 Integrity CSV saved:\\n{p}\"))\n                except Exception as csv_err:\n                    self._integ_log_write(f\"\u274c CSV export failed: {csv_err}\")\n\n        except Exception as ex:\n            self._integ_log_write(f\"\u274c Fatal error: {ex}\")\n            self.after(0, lambda: self._integ_stat_lbl.config(text=f\"\u274c Error: {ex}\"))\n        finally:\n            # \u2500\u2500 strict resource cleanup \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            results.clear()\n            gc.collect()\n            with self._rec_integrity_lock:\n                self._recovery_is_processing = False\n            self.after(0, lambda: self._integ_run_btn.config(state=\"normal\"))\n\n    def _ensure_admin_for_raw_recovery(self, disk_path=None):\n        if disk_path and not _is_raw_device_path(disk_path):\n            return True\n        if is_admin():\n            return True\n        if messagebox.askyesno(\n            \"Admin Required\",\n            \"Raw disk recovery ke liye Administrator rights mandatory hain.\\n\\n\"\n            \"App ko admin mode me restart karein?\"\n        ):\n            run_as_admin()\n        return False\n\n    def _raw_disk_path(self):\n        return (self.raw_disk_var.get() if hasattr(self, \"raw_disk_var\") else DEFAULT_RAW_DISK).strip() or DEFAULT_RAW_DISK\n\n    def _forensic_read_at(self, source, offset, length):\n        if source and os.path.exists(source) and not _is_raw_device_path(source):\n            with open(source, \"rb\") as f:\n                f.seek(offset)\n                return f.read(length)\n        return _read_raw_at(source, offset, length)\n\n    def _parse_mbr_partitions(self, sector):\n        parts = []\n        if len(sector) &lt; 512 or sector[510:512] != b\"\\x55\\xAA\":\n            return parts\n        for idx in range(4):\n            off = 446 + idx * 16\n            ent = sector[off:off + 16]\n            if len(ent) &lt; 16:\n                continue\n            ptype = ent[4]\n            start = struct.unpack_from(\" 512:\n                    tail = self._forensic_read_at(source, max(0, size - 512), 512)\n            except Exception:\n                pass\n            if head.startswith(b\"vhdxfile\"):\n                return \"VHDX\"\n            if tail[0:8] == b\"conectix\":\n                return \"VHD\"\n            if head.startswith(b\"EVF\\x09\") or head.startswith(b\"LVF\\x09\"):\n                return \"E01\"\n            return ext.lstrip(\".\").upper() or \"RAW_FILE\"\n        except Exception:\n            return \"UNKNOWN\"\n\n    def _parse_gpt_entries(self, source):\n        try:\n            header = self._forensic_read_at(source, 512, 512)\n            if len(header) &lt; 92 or header[:8] != b\"EFI PART\":\n                return None\n            entry_lba = struct.unpack_from(\"= first_lba else 0,\n                    \"size\": ((last_lba - first_lba + 1) * SECTOR_SIZE) if last_lba &gt;= first_lba else 0,\n                    \"name\": name or \"(no name)\",\n                    \"attrs\": attrs,\n                    \"type_guid\": str(uuid.UUID(bytes_le=ent[:16])),\n                    \"part_guid\": str(uuid.UUID(bytes_le=ent[16:32])),\n                })\n            return {\n                \"disk_guid\": str(uuid.UUID(bytes_le=disk_guid_raw)),\n                \"entry_lba\": entry_lba,\n                \"entry_count\": entry_count,\n                \"entry_size\": entry_size,\n                \"partitions\": parts,\n            }\n        except Exception:\n            return None\n\n    def _parse_ntfs_runlist(self, data):\n        runs = []\n        i = 0\n        current_lcn = 0\n        while i &lt; len(data):\n            header = data[i]\n            i += 1\n            if header == 0:\n                break\n            len_size = header &amp; 0x0F\n            off_size = (header &gt;&gt; 4) &amp; 0x0F\n            if i + len_size + off_size &gt; len(data):\n                break\n            run_len = int.from_bytes(data[i:i + len_size], \"little\", signed=False)\n            i += len_size\n            run_off = int.from_bytes(data[i:i + off_size], \"little\", signed=True)\n            i += off_size\n            current_lcn += run_off\n            runs.append((current_lcn, run_len))\n        return runs\n\n    def _parse_ntfs_data_runs(self, rec):\n        if len(rec) &lt; 64 or rec[:4] != b\"FILE\":\n            return []\n        used = struct.unpack_from(\" len(rec):\n                break\n            nonresident = rec[pos + 8]\n            name_len = rec[pos + 9]\n            name_off = struct.unpack_from(\" len(rec):\n                    break\n                nonresident = rec[pos + 8]\n                if atype == 0x30 and not nonresident:\n                    vlen = struct.unpack_from(\"= 66:\n                        parent = struct.unpack_from(\" 1 else (\"contiguous\" if run_count == 1 else \"resident/unknown\")\n                lines.append(\n                    f\"- #{item.get('record')} [{state}/{kind}] {item.get('name')} | path={path_text} | \"\n                    f\"size={item.get('real_size','')} | modified={item.get('modified','')} | parent={item.get('parent_ref','')} | runs={run_count} {frag}\"\n                )\n            lines.append(\"\")\n            lines.append(\"Special NTFS metadata records:\")\n            for key in [\"$mft\", \"$mftmirr\", \"$bitmap\", \"$logfile\", \"$usnjrnl\"]:\n                if key in special:\n                    item = special[key]\n                    lines.append(f\"- {key}: record #{item.get('record')} path={self._reconstruct_ntfs_path(item, name_map)}\")\n                else:\n                    lines.append(f\"- {key}: sample range me not observed\")\n            lines.append(\"\")\n            lines.append(\"Professional note:\")\n            lines.append(\"- Ye sample parser original filename, deleted flag, timestamps, parent references aur best-effort path reconstruction prove karta hai.\")\n            lines.append(\"- Non-resident DATA runs parse kiye gaye hain; multiple runs fragmented file ka strong clue dete hain.\")\n            lines.append(\"- $Bitmap / $LogFile / $UsnJrnl presence recovery confidence aur filesystem timeline analysis me useful hoti hai.\")\n            report = \"\\n\".join(lines)\n            self._raw_recovery_progress(\"NTFS MFT sample complete.\")\n            self.after(0, lambda: self._open_raw_hex_window(0, report))\n        except Exception as e:\n            err = str(e)\n            self._raw_recovery_progress(f\"MFT sample failed: {err}\")\n            self.after(0, lambda err=err: messagebox.showerror(\"MFT Parser Error\", err))\n\n    def _shadow_copy_recovery_report(self):\n        self._reset_raw_progress(\"Shadow Copy enumeration...\")\n        self._launch_job(\"shadow_copy_report\", self._do_shadow_copy_recovery_report)\n\n    def _do_shadow_copy_recovery_report(self):\n        try:\n            out1, _ = self._run_cmd(\"vssadmin list shadows\", timeout=60)\n            out2, _ = self._run_cmd(\"wmic shadowcopy get ID,InstallDate,OriginatingMachine,VolumeName /format:list\", timeout=60)\n            report = (\n                \"Shadow Copy Recovery Report\\n\"\n                f\"Generated: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\\n\\n\"\n                \"Troubleshoot kya kiya:\\n\"\n                \"- vssadmin list shadows run kiya.\\n\"\n                \"- WMIC shadowcopy inventory collect ki.\\n\\n\"\n                \"Recovery guidance:\\n\"\n                \"- Shadow copy available ho to deleted files previous snapshot se copy kiye ja sakte hain.\\n\"\n                \"- Evidence-safe workflow: source snapshot read-only mount/copy, original disk par write mat karo.\\n\\n\"\n                f\"vssadmin output:\\n{out1 or 'No shadows or access denied.'}\\n\\n\"\n                f\"WMIC output:\\n{out2 or 'No WMIC shadow data.'}\\n\"\n            )\n            self._raw_recovery_progress(\"Shadow Copy report complete.\")\n            self.after(0, lambda: self._open_raw_hex_window(0, report))\n        except Exception as e:\n            err = str(e)\n            self._raw_recovery_progress(f\"Shadow Copy report failed: {err}\")\n\n    def _score_recovered_file(self, path):\n        try:\n            size = os.path.getsize(path)\n            with open(path, \"rb\") as f:\n                head = f.read(4096)\n                if size &gt; 4096:\n                    f.seek(max(0, size - 4096))\n                    tail = f.read(4096)\n                else:\n                    tail = head\n            ext = Path(path).suffix.lower().lstrip(\".\")\n            score = \"Partial (55)\"\n            reason = \"Header/footer unknown.\"\n            checks = {\n                \"jpg\": (head.startswith(b\"\\xff\\xd8\\xff\"), tail.rstrip().endswith(b\"\\xff\\xd9\")),\n                \"jpeg\": (head.startswith(b\"\\xff\\xd8\\xff\"), tail.rstrip().endswith(b\"\\xff\\xd9\")),\n                \"png\": (head.startswith(b\"\\x89PNG\\r\\n\\x1a\\n\"), b\"IEND\" in tail),\n                \"pdf\": (head.startswith(b\"%PDF\"), b\"%%EOF\" in tail),\n                \"zip\": (head.startswith(b\"PK\\x03\\x04\"), b\"PK\\x05\\x06\" in tail or b\"PK\\x06\\x06\" in tail),\n                \"docx\": (head.startswith(b\"PK\\x03\\x04\"), b\"PK\\x05\\x06\" in tail or b\"PK\\x06\\x06\" in tail),\n                \"xlsx\": (head.startswith(b\"PK\\x03\\x04\"), b\"PK\\x05\\x06\" in tail or b\"PK\\x06\\x06\" in tail),\n                \"pptx\": (head.startswith(b\"PK\\x03\\x04\"), b\"PK\\x05\\x06\" in tail or b\"PK\\x06\\x06\" in tail),\n            }\n            if ext in checks:\n                h_ok, f_ok = checks[ext]\n                if h_ok and f_ok:\n                    score, reason = \"Excellent (95)\", \"Header aur footer dono valid.\"\n                elif h_ok:\n                    score, reason = \"Partial (65)\", \"Header valid, footer missing/fragmented.\"\n                else:\n                    score, reason = \"Corrupted (20)\", \"Expected header missing.\"\n            if size == 0:\n                score, reason = \"Corrupted (0)\", \"Zero-byte recovered file.\"\n            return score, reason\n        except Exception as e:\n            return \"Unknown\", str(e)\n\n    def _forensic_hash_verify_dialog(self):\n        folder = filedialog.askdirectory(title=\"Recovered files folder select karo\")\n        if not folder:\n            return\n        self._reset_raw_progress(\"Hash + forensic verification running...\")\n        self._launch_job(\"forensic_hash_verify\", self._do_forensic_hash_verify, folder)\n\n    def _do_forensic_hash_verify(self, folder):\n        try:\n            rows = []\n            by_sha256 = {}\n            count = 0\n            for root, dirs, files in os.walk(folder):\n                for name in files:\n                    if getattr(self, \"_recovery_stop_flag\", False):\n                        break\n                    path = os.path.join(root, name)\n                    try:\n                        md5 = hashlib.md5()\n                        sha1 = hashlib.sha1()\n                        sha256 = hashlib.sha256()\n                        with open(path, \"rb\") as f:\n                            for chunk in iter(lambda: f.read(1024 * 1024), b\"\"):\n                                md5.update(chunk); sha1.update(chunk); sha256.update(chunk)\n                        score, reason = self._score_recovered_file(path)\n                        item = {\n                            \"path\": path,\n                            \"size\": os.path.getsize(path),\n                            \"md5\": md5.hexdigest(),\n                            \"sha1\": sha1.hexdigest(),\n                            \"sha256\": sha256.hexdigest(),\n                            \"score\": score,\n                            \"reason\": reason,\n                        }\n                        rows.append(item)\n                        by_sha256.setdefault(item[\"sha256\"], []).append(path)\n                        count += 1\n                        if count % 50 == 0:\n                            self._raw_recovery_progress(f\"Hashed {count} files...\")\n                    except Exception as e:\n                        rows.append({\"path\": path, \"error\": str(e)})\n            dups = {h: ps for h, ps in by_sha256.items() if len(ps) &gt; 1}\n            report_path = os.path.join(folder, \"Godawari_Forensic_Hash_Report.csv\")\n            with open(report_path, \"w\", newline=\"\", encoding=\"utf-8\") as f:\n                writer = csv.DictWriter(f, fieldnames=[\"path\", \"size\", \"md5\", \"sha1\", \"sha256\", \"score\", \"reason\", \"error\"])\n                writer.writeheader()\n                for row in rows:\n                    writer.writerow({k: row.get(k, \"\") for k in writer.fieldnames})\n            lines = [\n                \"Hash + Forensic Verification Report\",\n                f\"Folder: {folder}\",\n                f\"Files processed: {len(rows)}\",\n                f\"Duplicate SHA256 groups: {len(dups)}\",\n                f\"CSV report: {report_path}\",\n                \"\",\n                \"Recoverability scoring:\",\n                \"- Excellent: header/footer valid\",\n                \"- Partial: header valid but footer missing/fragmented\",\n                \"- Corrupted: expected header missing\",\n                \"\",\n                \"Duplicate groups:\",\n            ]\n            for h, ps in list(dups.items())[:20]:\n                lines.append(f\"- {h}: {len(ps)} files\")\n                lines.extend(f\"  {p}\" for p in ps[:5])\n            report = \"\\n\".join(lines)\n            self._raw_recovery_progress(\"Hash verification complete.\")\n            self.after(0, lambda: self._open_raw_hex_window(0, report))\n        except Exception as e:\n            err = str(e)\n            self._raw_recovery_progress(f\"Hash verification failed: {err}\")\n\n    def _recovery_session_db_path(self):\n        return os.path.join(getattr(self, \"backup_dir\", os.getcwd()), \"recovery_sessions.sqlite3\")\n\n    def _recovery_session_db_save(self):\n        try:\n            items = []\n            if hasattr(self, \"rec_tree\"):\n                for iid in self.rec_tree.get_children():\n                    vals = self.rec_tree.item(iid, \"values\")\n                    items.append(tuple(vals))\n            if not items and hasattr(self, \"rec_found_files\"):\n                for entry in self.rec_found_files.values():\n                    if isinstance(entry, str):\n                        p = entry\n                    elif isinstance(entry, dict):\n                        p = entry.get(\"path\") or \"\"\n                    else:\n                        continue\n                    if p:\n                        items.append((os.path.basename(str(p)), Path(str(p)).suffix.lstrip(\".\"), \"\", str(p)))\n            if not items:\n                messagebox.showinfo(\"No Session\", \"Recovery result list empty hai.\")\n                return\n            db_path = self._recovery_session_db_path()\n            os.makedirs(os.path.dirname(db_path), exist_ok=True)\n            con = sqlite3.connect(db_path)\n            try:\n                cur = con.cursor()\n                cur.execute(\"CREATE TABLE IF NOT EXISTS sessions(id INTEGER PRIMARY KEY, ts TEXT, source TEXT, note TEXT)\")\n                cur.execute(\"CREATE TABLE IF NOT EXISTS files(session_id INTEGER, filename TEXT, ext TEXT, size TEXT, path TEXT)\")\n                source = self._raw_disk_path() if hasattr(self, \"raw_disk_var\") else \"\"\n                cur.execute(\"INSERT INTO sessions(ts, source, note) VALUES(?,?,?)\", (datetime.datetime.now().isoformat(timespec=\"seconds\"), source, \"GUI recovery session\"))\n                sid = cur.lastrowid\n                cur.executemany(\"INSERT INTO files(session_id, filename, ext, size, path) VALUES(?,?,?,?,?)\", [(sid,) + tuple(x[:4]) for x in items])\n                con.commit()\n            finally:\n                con.close()\n            msg = f\"Recovery session saved: {db_path}\\nSession items: {len(items)}\"\n            self._raw_recovery_progress(msg)\n            messagebox.showinfo(\"Session Saved\", msg)\n        except Exception as e:\n            messagebox.showerror(\"Session DB Error\", str(e))\n\n    def _begin_recovery_operation(self, label):\n        if getattr(self, \"_recovery_active\", False):\n            raise RuntimeError(\"Ek recovery task already chal raha hai. Pehle usko complete/stop hone dein.\")\n        self._recovery_stop_flag = False\n        self._recovery_pause_flag = False\n        self._recovery_active = True\n        self._active_recovery_session_id = None\n        try:\n            mgr = getattr(self, \"recovery_session_manager\", None)\n            if mgr:\n                self._active_recovery_session_id = mgr.start(\n                    \"file_recovery\", {\"label\": str(label)})\n        except Exception:\n            pass\n        if hasattr(self, \"_rec_stop_btn\"):\n            self._rec_stop_btn.config(state=\"normal\")\n        if hasattr(self, \"_rec_pause_btn\"):\n            self._rec_pause_btn.config(state=\"normal\", text=\"\u23f8 Pause\")\n        self._set_status(label, C[\"warning\"])\n\n    def _finish_recovery_operation(self):\n        sid = getattr(self, \"_active_recovery_session_id\", None)\n        if sid:\n            try:\n                status = \"stopped\" if getattr(self, \"_recovery_stop_flag\", False) else \"completed\"\n                self.recovery_session_manager.complete(sid, status=status)\n            except Exception:\n                pass\n            self._active_recovery_session_id = None\n        self._recovery_active = False\n        self._recovery_pause_flag = False\n        if hasattr(self, \"_rec_stop_btn\"):\n            self._rec_stop_btn.config(state=\"disabled\")\n        if hasattr(self, \"_rec_pause_btn\"):\n            self._rec_pause_btn.config(state=\"disabled\", text=\"\u23f8 Pause\")\n\n    def _is_mobile_source(self, drive_text):\n        d = (drive_text or \"\").strip().lower()\n        return d in {\"mobile\", \"android\", \"phone\", \"mobile_deep\", \"android_deep\"} or d.startswith(\"android\")\n\n    def _android_media_preset(self, preset):\n        # Force Android mode + set exts presets; roots override used by mobile finder\n        try:\n            self.rec_drive.set(\"Android\")\n        except Exception:\n            pass\n        if preset == \"whatsapp\":\n            self.rec_ext.delete(0, \"end\")\n            self.rec_ext.insert(0, \"jpg,jpeg,png,mp4\")\n            self._mobile_roots_override = [\"/sdcard/WhatsApp/Media\", \"/sdcard/Android/media\"]\n        else:\n            self.rec_ext.delete(0, \"end\")\n            self.rec_ext.insert(0, \"jpg,jpeg,png,mp4\")\n            self._mobile_roots_override = [\"/sdcard/DCIM\", \"/sdcard/Pictures\", \"/sdcard/Movies\"]\n        self._start_file_recovery()\n\n    def _mobile_bridge_help(self):\n        cmd = os.environ.get(\"GODAWARI_MOBILE_BRIDGE_CMD\", \"\").strip()\n        messagebox.showinfo(\n            \"Mobile Bridge\",\n            \"Advanced mobile recovery ke liye optional bridge available hai.\\n\\n\"\n            \"Env var set karo:\\n\"\n            \"GODAWARI_MOBILE_BRIDGE_CMD = \\n\\n\"\n            \"Bridge command JSON list output kare:\\n\"\n            \"[\\\"/sdcard/path/file1.jpg\\\", \\\"...\\\" ]\\n\\n\"\n            f\"Current: {cmd if cmd else '(not set)'}\"\n        )\n\n    def _mobile_bridge_candidates(self, exts):\n        \"\"\"\n        Optional external bridge for advanced mobile recovery.\n        Set env var GODAWARI_MOBILE_BRIDGE_CMD to a command that outputs JSON list of paths.\n        \"\"\"\n        cmd = os.environ.get(\"GODAWARI_MOBILE_BRIDGE_CMD\", \"\").strip()\n        if not cmd:\n            return []\n        exts_arg = \",\".join(sorted({e.lower().strip(\".\") for e in exts if e.strip()}))\n        out, rc = self._run_cmd(f'{cmd} --ext \"{exts_arg}\"', timeout=180)\n        if rc != 0 or not out.strip():\n            return []\n        try:\n            data = json.loads(out)\n            if isinstance(data, list):\n                return [str(x) for x in data if str(x).strip()]\n        except Exception:\n            return []\n        return []\n\n    def _mobile_adb_available(self):\n        out, rc = self._run_cmd(self._adb_args(\"version\"), timeout=10)\n        return rc == 0 and \"android debug bridge\" in out.lower()\n\n    def _mobile_device_ready(self):\n        out, rc = self._run_cmd(self._adb_args(\"devices\"), timeout=10)\n        if rc != 0:\n            return False\n        for ln in out.splitlines()[1:]:\n            parts = ln.strip().split()\n            if len(parts) &gt;= 2 and parts[1].strip().lower() == \"device\":\n                return True\n        return False\n\n    def _find_adb_exe(self):\n        cached = getattr(self, \"_adb_exe_cache\", None)\n        if cached and os.path.isfile(cached):\n            return cached\n        candidates = []\n        env_direct = os.environ.get(\"ADB_PATH\", \"\").strip().strip('\"')\n        if env_direct:\n            candidates.append(env_direct)\n        for name in (\"adb.exe\", \"adb\"):\n            found = shutil.which(name)\n            if found:\n                candidates.append(found)\n        local_appdata = os.environ.get(\"LOCALAPPDATA\", \"\")\n        user_profile = os.environ.get(\"USERPROFILE\", \"\")\n        common_roots = [\n            os.getcwd(),\n            os.path.dirname(os.path.abspath(sys.argv[0])),\n            local_appdata,\n            user_profile,\n            os.path.join(local_appdata, \"Android\"),\n            os.path.join(local_appdata, \"Android\", \"Sdk\"),\n            os.path.join(user_profile, \"AppData\", \"Local\", \"Android\", \"Sdk\"),\n            os.path.join(user_profile, \"Downloads\"),\n            os.path.join(user_profile, \"Desktop\"),\n        ]\n        rels = [\n            \"platform-tools\\\\adb.exe\",\n            \"Android\\\\Sdk\\\\platform-tools\\\\adb.exe\",\n            \"sdk\\\\platform-tools\\\\adb.exe\",\n            \"tools\\\\platform-tools\\\\adb.exe\",\n        ]\n        for root in common_roots:\n            if not root:\n                continue\n            for rel in rels:\n                candidates.append(os.path.join(root, rel))\n        seen = set()\n        for path in candidates:\n            try:\n                norm = os.path.normcase(os.path.abspath(path))\n            except Exception:\n                norm = os.path.normcase(str(path))\n            if norm in seen:\n                continue\n            seen.add(norm)\n            if os.path.isfile(path):\n                self._adb_exe_cache = path\n                return path\n        return \"\"\n\n    def _adb_cmd(self, args):\n        adb_exe = self._find_adb_exe() or \"adb\"\n        return f'\"{adb_exe}\" {args}'.strip()\n\n    def _adb_args(self, *args):\n        adb_exe = self._find_adb_exe() or \"adb\"\n        return [adb_exe, *[str(a) for a in args]]\n\n    def _show_adb_help(self):\n        detected = self._find_adb_exe()\n        hint = detected if detected else \"Not detected\"\n        messagebox.showinfo(\n            \"ADB Required\",\n            \"Mobile recovery ke liye Android Platform Tools required hain.\\n\\n\"\n            f\"Detected ADB: {hint}\\n\\n\"\n            \"Setup:\\n\"\n            \"1. Android phone me USB debugging ON karo\\n\"\n            \"2. Platform Tools install/unzip karo\\n\"\n            \"3. adb.exe ko PATH me add karo ya ADB_PATH env var set karo\\n\"\n            \"4. Phone ko authorize karke retry karo\"\n        )\n\n    def _refresh_adb_status_label(self):\n        if not hasattr(self, \"adb_status_label\"):\n            return\n        adb_exe = self._find_adb_exe()\n        if not adb_exe:\n            text = \"ADB Status: Not Found\"\n            color = C[\"error\"]\n        elif self._mobile_device_ready():\n            text = \"ADB Status: Device Authorized\"\n            color = C[\"success\"]\n        else:\n            text = \"ADB Status: Found, device not authorized\"\n            color = C[\"warning\"]\n        self.adb_status_label.config(text=text, fg=color)\n\n    def _mobile_find_candidates(self, exts):\n        exts = [e.lower().strip(\".\") for e in exts if e.strip()]\n        roots = getattr(self, \"_mobile_roots_override\", None) or [\n            \"/sdcard/DCIM\", \"/sdcard/Download\", \"/sdcard/Pictures\", \"/sdcard/Movies\",\n            \"/sdcard/WhatsApp/Media\", \"/sdcard/Android/media\", \"/storage/emulated/0\",\n        ]\n        found = []\n        seen = set()\n        # Build a filtered find expression to reduce output volume\n        patterns = []\n        for ext in sorted({e for e in exts if e}):\n            # Use -iname for case-insensitive match\n            patterns.append(f\"-iname '*.{ext}'\")\n        expr = \"\"\n        if patterns:\n            expr = \"\\\\( \" + \" -o \".join(patterns[:20]) + \" \\\\)\"\n        for root in roots:\n            if getattr(self, \"_recovery_stop_flag\", False):\n                break\n            while getattr(self, \"_recovery_pause_flag\", False):\n                if getattr(self, \"_recovery_stop_flag\", False):\n                    break\n                time.sleep(0.2)\n            shell_script = \"if [ -d '\" + root + \"' ]; then find '\" + root + \"' -type f \"\n            if expr:\n                shell_script += expr + \" \"\n            shell_script += \"2&gt;/dev/null; fi\"\n            proc = subprocess.Popen(self._adb_args(\"shell\", shell_script), shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, encoding=\"utf-8\", errors=\"replace\")\n            try:\n                for line in proc.stdout:\n                    if getattr(self, \"_recovery_stop_flag\", False):\n                        proc.terminate()\n                        break\n                    while getattr(self, \"_recovery_pause_flag\", False):\n                        if getattr(self, \"_recovery_stop_flag\", False):\n                            proc.terminate()\n                            break\n                        time.sleep(0.2)\n                    p = line.strip()\n                    if not p:\n                        continue\n                    low = p.lower()\n                    if (not exts or any(low.endswith(\".\" + ext) for ext in exts)) and low not in seen:\n                        seen.add(low)\n                        found.append(p)\n                        if len(found) % 100 == 0:\n                            self._raw_recovery_progress(f\"MOBILE scan: {len(found)} files matched...\")\n            finally:\n                try:\n                    proc.wait(timeout=2)\n                except Exception:\n                    pass\n        # Extra recovery hint: media scanner cache can include recently indexed files.\n        try:\n            cmd = self._adb_args(\"shell\", \"find /sdcard -name .thumbnails -o -name LOST.DIR 2&gt;/dev/null\")\n            out, rc = self._run_cmd(cmd, timeout=25)\n            if rc == 0 and out.strip():\n                self._raw_recovery_progress(\"MOBILE hint: thumbnail/LOST.DIR folders bhi detect hui hain.\")\n        except Exception:\n            pass\n        bridge_items = self._mobile_bridge_candidates(exts)\n        if bridge_items:\n            for p in bridge_items:\n                low = p.lower()\n                if low not in seen:\n                    seen.add(low)\n                    found.append(p)\n            self._raw_recovery_progress(f\"MOBILE bridge added {len(bridge_items)} candidate(s)\")\n        return found\n\n    def _recovery_checkpoint_path(self, mode):\n        safe = re.sub(r\"[^a-zA-Z0-9_.-]+\", \"_\", str(mode or \"default\"))\n        return os.path.join(getattr(self, \"backup_dir\", os.getcwd()), f\"recovery_checkpoint_{safe}.json\")\n\n    def _save_recovery_checkpoint(self, mode, data):\n        try:\n            path = self._recovery_checkpoint_path(mode)\n            payload = {\n                \"ts\": datetime.datetime.now().isoformat(timespec=\"seconds\"),\n                \"mode\": mode,\n                \"data\": data,\n            }\n            with open(path, \"w\", encoding=\"utf-8\") as f:\n                json.dump(payload, f, ensure_ascii=False)\n        except Exception:\n            pass\n\n    def _load_recovery_checkpoint(self, mode):\n        try:\n            path = self._recovery_checkpoint_path(mode)\n            if not os.path.exists(path):\n                return None\n            with open(path, \"r\", encoding=\"utf-8\") as f:\n                payload = json.load(f)\n            if payload.get(\"mode\") != mode:\n                return None\n            return payload.get(\"data\")\n        except Exception:\n            return None\n\n    def _clear_recovery_checkpoint(self, mode):\n        try:\n            path = self._recovery_checkpoint_path(mode)\n            if os.path.exists(path):\n                os.remove(path)\n        except Exception:\n            pass\n\n    def _sha256_file(self, path):\n        h = hashlib.sha256()\n        with open(path, \"rb\") as f:\n            while True:\n                chunk = f.read(1024 * 1024)\n                if not chunk:\n                    break\n                h.update(chunk)\n        return h.hexdigest()\n\n    def _mobile_pull_with_retry(self, src, dst):\n        out = \"\"\n        for _ in range(3):\n            out, rc = self._run_cmd(self._adb_args(\"pull\", src, dst), timeout=300)\n            if rc == 0 and os.path.exists(dst):\n                return True, out\n            time.sleep(0.4)\n        return False, out\n\n    def _integrity_score(self, path, file_type_hint=\"\"):\n        try:\n            size = os.path.getsize(path)\n            if size &lt;= 0:\n                return 0, \"empty file\"\n            score = 40\n            reason = [\"file exists\"]\n            ext = (file_type_hint or os.path.splitext(path)[1].lstrip(\".\")).lower()\n            if size &gt; 1024:\n                score += 20\n                reason.append(\"size&gt;1KB\")\n            if size &gt; 1024 * 1024:\n                score += 10\n                reason.append(\"size&gt;1MB\")\n            if ext in (\"jpg\", \"jpeg\", \"png\", \"pdf\", \"zip\", \"mp4\", \"exe\"):\n                with open(path, \"rb\") as f:\n                    data = f.read(min(size, 8 * 1024 * 1024))\n                if ext in (\"jpg\", \"jpeg\") and data.startswith(b\"\\xFF\\xD8\"):\n                    score += 15\n                    reason.append(\"jpeg header ok\")\n                elif ext == \"png\" and data.startswith(b\"\\x89PNG\\r\\n\\x1A\\n\"):\n                    score += 15\n                    reason.append(\"png header ok\")\n                elif ext == \"pdf\" and data.startswith(b\"%PDF\"):\n                    score += 15\n                    reason.append(\"pdf header ok\")\n                elif ext == \"zip\" and data.startswith(b\"PK\\x03\\x04\"):\n                    score += 15\n                    reason.append(\"zip header ok\")\n                elif ext == \"mp4\" and b\"ftyp\" in data[:128]:\n                    score += 15\n                    reason.append(\"mp4 ftyp ok\")\n                elif ext == \"exe\" and data.startswith(b\"MZ\"):\n                    score += 15\n                    reason.append(\"mz header ok\")\n            return max(0, min(100, score)), \", \".join(reason)\n        except Exception as e:\n            return 20, f\"basic only ({e})\"\n\n    def _check_recovery_control(self):\n        if getattr(self, \"_recovery_stop_flag\", False):\n            raise InterruptedError(\"Recovery stopped by user.\")\n        paused_notice = False\n        while getattr(self, \"_recovery_pause_flag\", False):\n            if not paused_notice:\n                paused_notice = True\n                self.after(0, lambda: self._set_status(\"Recovery paused - Resume dabao\", C[\"warning\"]))\n            time.sleep(0.25)\n            if getattr(self, \"_recovery_stop_flag\", False):\n                raise InterruptedError(\"Recovery stopped by user.\")\n\n    def _update_raw_source_badge(self):\n        if not hasattr(self, \"raw_source_badge\"):\n            return\n        src = self._raw_disk_path()\n        if _is_raw_device_path(src):\n            self.raw_source_badge.config(text=\"RAW DEVICE - admin required\", fg=C[\"warning\"])\n        elif os.path.isfile(src):\n            self.raw_source_badge.config(text=\"IMG FILE - scan without admin\", fg=C[\"success\"])\n        else:\n            self.raw_source_badge.config(text=\"SOURCE NOT FOUND\", fg=C[\"error\"])\n\n    def _reset_raw_progress(self, message=\"Ready\"):\n        if hasattr(self, \"raw_progress_var\"):\n            self.raw_progress_var.set(0)\n        if hasattr(self, \"raw_progress_bar\"):\n            try:\n                self.raw_progress_bar.stop()\n            except Exception:\n                pass\n            self.raw_progress_bar.config(mode=\"determinate\")\n        if hasattr(self, \"raw_progress_label\"):\n            self.raw_progress_label.config(text=message)\n        if hasattr(self, \"raw_progress_log\"):\n            try:\n                self.raw_progress_log.config(state=\"normal\")\n                self.raw_progress_log.delete(\"1.0\", \"end\")\n                self.raw_progress_log.insert(\"end\", message + \"\\n\")\n                self.raw_progress_log.config(state=\"disabled\")\n            except Exception:\n                pass\n\n    def _append_log_line(self, text):\n        if hasattr(self, \"raw_progress_log\"):\n            try:\n                self.raw_progress_log.config(state=\"normal\")\n                self.raw_progress_log.insert(\"end\", text + \"\\n\")\n                self.raw_progress_log.see(\"end\")\n                self.raw_progress_log.config(state=\"disabled\")\n            except Exception:\n                pass\n\n    def _recovery_reset_ui_batch(self):\n        self._rec_pending_rows = []\n        self._rec_pending_progress = None\n        self._rec_pending_log = None\n        self._rec_flush_scheduled = False\n        if not hasattr(self, \"_rec_batch_lock\"):\n            self._rec_batch_lock = threading.Lock()\n\n    def _recovery_schedule_flush(self):\n        with self._rec_batch_lock:\n            if self._rec_flush_scheduled:\n                return\n            self._rec_flush_scheduled = True\n        self.after(80, self._recovery_flush_ui_batch)\n\n    def _recovery_queue_row(self, row, entry):\n        \"\"\"\n        Thread-safe row enqueue. Routes through _ui_queue so the main thread\n        can batch-insert rows without any direct widget access from threads.\n        \"\"\"\n        self._q_tree_row(row, entry)\n\n    def _recovery_set_drive_progress(self, scanned, file_count, dirpath):\n        \"\"\"\n        Thread-safe progress update. Enqueues label+log via _ui_queue.\n        Can be called from any thread.\n        \"\"\"\n        folder_tail = dirpath[-65:] if len(dirpath) &gt; 65 else dirpath\n        label_text = (\n            f\"\ud83d\udd0d Scanning...  {scanned:,} folders  |  {file_count:,} files mili  |  ...{folder_tail}\")\n        self._q(\"progress_label\", label_text)\n        self._q_log(dirpath)\n\n    def _recovery_flush_ui_batch(self):\n        \"\"\"\n        Drain any tree-row messages still sitting in the UI queue (main-thread only).\n        Called at the end of a scan to ensure no rows are left unrendered.\n        The heavy lifting is now done by _poll_ui_queue() every 50 ms.\n        \"\"\"\n        # Drain up to 500 pending tree_row messages from the queue\n        MAX_FLUSH = 500\n        processed = 0\n        try:\n            while processed &lt; MAX_FLUSH:\n                msg_type, payload = self._ui_queue.get_nowait()\n                processed += 1\n                if msg_type == \"tree_row\" and hasattr(self, \"rec_tree\"):\n                    row, entry = payload\n                    try:\n                        iid = self.rec_tree.insert(\"\", \"end\", values=row, tags=(\"found\",))\n                        if not isinstance(getattr(self, \"rec_found_files\", None), dict):\n                            self.rec_found_files = {}\n                        self.rec_found_files[iid] = entry\n                    except Exception:\n                        pass\n                elif msg_type == \"progress_label\" and hasattr(self, \"raw_progress_label\"):\n                    self.raw_progress_label.config(text=str(payload)[:200])\n                elif msg_type == \"log_line\":\n                    self._append_log_line(str(payload))\n        except _queue_module.Empty:\n            pass\n        self._on_rec_select()\n    def _prep_drive_scan_progress_ui(self):\n        self._recovery_reset_ui_batch()\n        if hasattr(self, \"raw_progress_bar\"):\n            try:\n                self.raw_progress_bar.stop()\n            except Exception:\n                pass\n            self.raw_progress_bar.config(mode=\"indeterminate\")\n            self.raw_progress_bar.start(10)\n        if hasattr(self, \"raw_progress_var\"):\n            self.raw_progress_var.set(0)\n\n    def _prep_raw_scan_progress_ui(self):\n        if hasattr(self, \"raw_progress_bar\"):\n            try:\n                self.raw_progress_bar.stop()\n            except Exception:\n                pass\n            self.raw_progress_bar.config(mode=\"indeterminate\")\n            try:\n                self.raw_progress_bar.start(5)\n            except Exception:\n                pass\n        if hasattr(self, \"raw_progress_var\"):\n            self.raw_progress_var.set(0)\n\n    def _on_rec_select(self, event=None):\n        total = len(self.rec_tree.get_children()) if hasattr(self, \"rec_tree\") else 0\n        sel = len(self.rec_tree.selection()) if hasattr(self, \"rec_tree\") else 0\n        if hasattr(self, \"rec_stats_label\"):\n            self.rec_stats_label.config(text=f\"{total:,} files | {sel} selected\")\n\n    def _make_recovery_progress_callback(self):\n        def cb(msg):\n            self._raw_recovery_progress(msg)\n            m = re.match(r\"Pass \\d+: recovered (.+)\", msg, re.I)\n            if m and hasattr(self, \"rec_tree\"):\n                filename = m.group(1).strip()\n                ext = os.path.splitext(filename)[1].lstrip(\".\").upper() or \"?\"\n                row = (filename, ext, \"\u2014\", \"Recovered \u2014 verifying...\", \"Raw Scan\", \"--\")\n\n                def _ins(r=row, fn=filename):\n                    iid = self.rec_tree.insert(\"\", \"end\", values=r, tags=(\"found\",))\n                    self.rec_found_files[iid] = {\"kind\": \"photorec_live\", \"path\": fn, \"filename\": fn}\n\n                self.after(0, _ins)\n        return cb\n\n    def _clear_recovery_progress_log(self):\n        if hasattr(self, \"raw_progress_log\"):\n            try:\n                self.raw_progress_log.config(state=\"normal\")\n                self.raw_progress_log.delete(\"1.0\", \"end\")\n                self.raw_progress_log.config(state=\"disabled\")\n            except Exception:\n                pass\n\n    def _set_recovery_scan_mode(self, text, fg=None):\n        if hasattr(self, \"scan_mode_label\"):\n            self.scan_mode_label.config(text=text, fg=fg or C[\"accent4\"])\n\n    def _update_rec_stats(self):\n        if not hasattr(self, \"rec_stats_label\"):\n            return\n        n = len(self.rec_tree.get_children()) if hasattr(self, \"rec_tree\") else 0\n        sel = len(self.rec_tree.selection()) if hasattr(self, \"rec_tree\") else 0\n        self.rec_stats_label.config(text=f\"{n:,} files | {sel:,} selected\")\n\n    def _clear_recovery_results(self):\n        if hasattr(self, \"rec_tree\"):\n            self.rec_tree.delete(*self.rec_tree.get_children())\n        self.rec_found_files = {}\n        if hasattr(self, \"raw_progress_var\"):\n            self.raw_progress_var.set(0)\n        if hasattr(self, \"raw_progress_label\"):\n            self.raw_progress_label.config(text=\"List saaf kar di gayi.\")\n        self._update_rec_stats()\n\n    def _raw_limit_bytes(self):\n        try:\n            raw_value = (self.raw_scan_mb.get() or \"\").strip()\n            if not raw_value:\n                return None\n            mb = int(raw_value)\n            if mb &lt;= 0:\n                return None\n            return mb * 1024 * 1024\n        except Exception:\n            return None\n\n    def _raw_file_types_from_entry(self):\n        mapping = {\n            \"JPG\": \"JPG\", \"JPEG\": \"JPG\",\n            \"PDF\": \"PDF\",\n            \"MP4\": \"MP4\", \"M4V\": \"MP4\", \"MOV\": \"MP4\",\n            \"ZIP\": \"ZIP\", \"DOCX\": \"ZIP\", \"XLSX\": \"ZIP\", \"PPTX\": \"ZIP\",\n            \"EXE\": \"EXE\",\n        }\n        types = []\n        for part in self.rec_ext.get().split(\",\"):\n            key = part.strip().strip(\".\").upper()\n            if key in mapping and mapping[key] not in types:\n                types.append(mapping[key])\n        return types or list(SIGNATURES.keys())\n\n    def _insert_raw_results(self, disk_path, results):\n        self.rec_tree.delete(*self.rec_tree.get_children())\n        self.rec_found_files = {}\n        for counter, item in enumerate(results, start=1):\n            file_type = item[\"file_type\"]\n            ext = item.get(\"extension\") or SIGNATURES.get(file_type, {}).get(\"ext\", \"\")\n            offset = item[\"offset\"]\n            display_name = f\"{file_type}_{counter:04d}{ext}\"\n            max_sz = SIGNATURES.get(file_type, {}).get(\"max_size\", 0)\n            est_size = f\"~{_human_size(max(max_sz // 8, SECTOR_SIZE))} est.\" if max_sz else \"\u2014\"\n            conf = str(item.get(\"confidence\", \"medium\"))\n            location = f\"Sector {item['sector']:,}  |  {conf.title()}\"\n            iid = self.rec_tree.insert(\"\", \"end\", values=(\n                display_name, file_type, est_size,\n                \"Found \u2014 Recover dabao \u25b6\", location, \"--\"), tags=(\"found\",))\n            self.rec_found_files[iid] = {\n                \"kind\": \"raw\",\n                \"disk_path\": disk_path,\n                \"offset\": offset,\n                \"file_type\": file_type,\n                \"display_name\": display_name,\n            }\n        self.after(0, self._on_rec_select)\n\n    def _raw_recovery_progress(self, msg):\n        self._check_recovery_control()\n        def _do(m=msg):\n            display = m if len(m) &lt;= 140 else (m[:137] + \"...\")\n            if hasattr(self, \"raw_progress_label\"):\n                self.raw_progress_label.config(text=display)\n            if hasattr(self, \"raw_progress_log\"):\n                try:\n                    self.raw_progress_log.config(state=\"normal\")\n                    self.raw_progress_log.insert(\"end\", self._fix_text(m) + \"\\n\")\n                    if float(self.raw_progress_log.index(\"end-1c\").split(\".\")[0]) &gt; 200:\n                        self.raw_progress_log.delete(\"1.0\", \"50.0\")\n                    self.raw_progress_log.see(\"end\")\n                    self.raw_progress_log.config(state=\"disabled\")\n                except Exception:\n                    pass\n            if hasattr(self, \"raw_progress_var\"):\n                pct = None\n                match = re.search(r\"Pass\\s+([12])\\s*:\\s*(\\d{1,3})%\", m, re.I)\n                if match:\n                    pass_num = int(match.group(1))\n                    pass_pct = max(0, min(100, int(match.group(2))))\n                    pct = (pass_pct * 0.45) if pass_num == 1 else 45 + (pass_pct * 0.45)\n                else:\n                    generic = re.search(r\"(\\d{1,3})%\\s*complete\", m, re.I)\n                    if generic:\n                        pct = max(0, min(100, int(generic.group(1))))\n                if pct is None:\n                    m2 = re.search(r\"(\\d{1,3})%\\s*complete\", m, re.I)\n                    if m2:\n                        pct = max(0, min(100, int(m2.group(1))))\n                if pct is None and \"AUTO 1/4\" in m:\n                    pct = 5\n                elif pct is None and \"AUTO 2/4\" in m:\n                    pct = 20\n                elif pct is None and \"AUTO 3/4\" in m:\n                    pct = max(float(self.raw_progress_var.get()), 25)\n                elif pct is None and \"AUTO 4/4\" in m:\n                    pct = 95\n                elif pct is None and (\"complete\" in m.lower() or \"done\" in m.lower()):\n                    pct = 100\n                elif pct is None and (\"start\" in m.lower() or \"start ho\" in m.lower()):\n                    pct = 1\n                if pct is not None and hasattr(self, \"raw_progress_bar\"):\n                    try:\n                        self.raw_progress_bar.stop()\n                    except Exception:\n                        pass\n                    self.raw_progress_bar.config(mode=\"determinate\")\n                    self.raw_progress_var.set(max(0, min(100, pct)))\n                elif hasattr(self, \"raw_progress_bar\"):\n                    try:\n                        self.raw_progress_bar.config(mode=\"indeterminate\")\n                        self.raw_progress_bar.start(5)\n                    except Exception:\n                        pass\n        self.after(0, _do)\n\n    def _start_raw_signature_scan(self):\n        disk_path = self._raw_disk_path()\n        self._update_raw_source_badge()\n        if not self._ensure_admin_for_raw_recovery(disk_path):\n            return\n        limit = self._raw_limit_bytes()\n        file_types = self._raw_file_types_from_entry()\n        limit_text = \"FULL DISK\" if limit is None else self._fmt_size(limit)\n        if not messagebox.askyesno(\n            \"Raw Signature Scan\",\n            f\"Raw disk scan start karein?\\n\\n\"\n            f\"Disk: {disk_path}\\n\"\n            f\"Limit: {limit_text}\\n\"\n            f\"Types: {', '.join(file_types)}\\n\\n\"\n            \"Yeh read-only scan hai, lekin time lag sakta hai.\"\n        ):\n            return\n        self.rec_tree.delete(*self.rec_tree.get_children())\n        self.rec_found_files = {}\n        self._set_recovery_scan_mode(\"Mode: Zone B \u2014 Raw Sector Recovery (Admin)\", C[\"warning\"])\n        self._clear_recovery_progress_log()\n        self._prep_raw_scan_progress_ui()\n        self._reset_raw_progress(\"Raw signature scan start ho raha hai...\")\n        try:\n            self._begin_recovery_operation(\"Raw signature scan start ho raha hai...\")\n        except Exception as e:\n            messagebox.showwarning(\"Recovery Busy\", str(e))\n            return\n        if not self._hdd_action_submit(\"raw_signature_scan\", self._do_raw_signature_scan, disk_path, limit, file_types):\n            self._set_status(\"Recovery action already running; wait for completion.\", C[\"warning\"])\n\n    def _do_raw_signature_scan(self, disk_path, limit, file_types):\n        try:\n            results = scan_disk_for_files(\n                disk_path,\n                max_bytes=limit,\n                file_types=file_types,\n                progress_callback=self._make_recovery_progress_callback(),\n            )\n\n            def _populate():\n                self._insert_raw_results(disk_path, results)\n                self._set_status(f\"Raw scan complete: {len(results)} signatures mile\", C[\"success\"])\n\n            self.after(0, _populate)\n        except InterruptedError as e:\n            msg = str(e)\n            self.after(0, lambda msg=msg: self._set_status(msg, C[\"warning\"]))\n        except Exception as e:\n            err = str(e)\n            self.after(0, lambda err=err: self._set_status(\"Raw scan failed: \" + err, C[\"error\"]))\n            self.after(0, lambda err=err: messagebox.showerror(\"Raw Scan Error\", err))\n        finally:\n            self.after(0, self._finish_recovery_operation)\n\n    def _create_img_dialog(self):\n        disk_path = self._raw_disk_path()\n        self._update_raw_source_badge()\n        if not self._ensure_admin_for_raw_recovery(disk_path):\n            return\n        limit = self._raw_limit_bytes()\n        img_path = filedialog.asksaveasfilename(\n            title=\"IMG file save location\",\n            defaultextension=\".img\",\n            filetypes=[(\"Disk image\", \"*.img\"), (\"All files\", \"*.*\")]\n        )\n        if not img_path:\n            return\n        limit_text = \"FULL DISK\" if limit is None else self._fmt_size(limit)\n        if not messagebox.askyesno(\n            \"Create Disk Image\",\n            f\"IMG backup banani hai?\\n\\nDisk: {disk_path}\\nOutput: {img_path}\\nSize: {limit_text}\\n\\n\"\n            \"Note: Full disk image bahut badi ho sakti hai.\"\n        ):\n            return\n        self._reset_raw_progress(\"IMG creation start ho rahi hai...\")\n        try:\n            self._begin_recovery_operation(\"IMG creation start ho rahi hai...\")\n        except Exception as e:\n            messagebox.showwarning(\"Recovery Busy\", str(e))\n            return\n        if not self._hdd_action_submit(\"raw_create_img\", self._do_create_img, disk_path, img_path, limit):\n            self._set_status(\"Recovery action already running; wait for completion.\", C[\"warning\"])\n\n    def _do_create_img(self, disk_path, img_path, limit):\n        try:\n            result = create_disk_image(disk_path, img_path, max_bytes=limit, progress_callback=self._raw_recovery_progress)\n            self.after(0, lambda: self._set_status(f\"IMG complete: {self._fmt_size(result['bytes'])}\", C[\"success\"]))\n            self.after(0, lambda: messagebox.showinfo(\"IMG Complete\", f\"IMG ban gayi:\\n{result['img_path']}\\n\\nSize: {self._fmt_size(result['bytes'])}\"))\n        except InterruptedError as e:\n            msg = str(e)\n            self.after(0, lambda msg=msg: self._set_status(msg, C[\"warning\"]))\n        except Exception as e:\n            err = str(e)\n            self.after(0, lambda err=err: self._set_status(\"IMG failed: \" + err, C[\"error\"]))\n            self.after(0, lambda err=err: messagebox.showerror(\"IMG Error\", err))\n        finally:\n            self.after(0, self._finish_recovery_operation)\n\n    def _start_auto_raw_recovery(self):\n        disk_path = self._raw_disk_path()\n        self._update_raw_source_badge()\n        if not self._ensure_admin_for_raw_recovery(disk_path):\n            return\n        limit = self._raw_limit_bytes()\n        file_types = self._raw_file_types_from_entry()\n        output_dir = filedialog.askdirectory(title=\"Recovered data save karne ke liye folder select karo\")\n        if not output_dir:\n            return\n        limit_text = \"FULL DISK\" if limit is None else self._fmt_size(limit)\n        if not messagebox.askyesno(\n            \"AUTO All Process\",\n            f\"Auto recovery workflow start karein?\\n\\n\"\n            f\"1. IMG backup banegi\\n\"\n            f\"2. Raw signature scan hoga\\n\"\n            f\"3. Found files auto extract hongi\\n\"\n            f\"4. Real hex preview show hoga\\n\\n\"\n            f\"Disk: {disk_path}\\n\"\n            f\"Scan/Image Size: {limit_text}\\n\"\n            f\"Types: {', '.join(file_types)}\\n\"\n            f\"Output: {output_dir}\\n\\n\"\n            \"Note: Large scan size se time aur storage dono lagenge.\"\n        ):\n            return\n        self.rec_tree.delete(*self.rec_tree.get_children())\n        self.rec_found_files = {}\n        self._set_recovery_scan_mode(\"Mode: Zone B \u2014 Raw Sector Recovery (Admin)\", C[\"warning\"])\n        self._clear_recovery_progress_log()\n        self._reset_raw_progress(\"AUTO recovery start ho rahi hai...\")\n        try:\n            self._begin_recovery_operation(\"AUTO recovery start ho rahi hai...\")\n        except Exception as e:\n            messagebox.showwarning(\"Recovery Busy\", str(e))\n            return\n        if not self._hdd_action_submit(\"auto_raw_recovery\", self._do_auto_raw_recovery, disk_path, limit, file_types, output_dir):\n            self._set_status(\"Recovery action already running; wait for completion.\", C[\"warning\"])\n\n    def _do_auto_raw_recovery(self, disk_path, limit, file_types, output_dir):\n        recovered = []\n        warnings = []\n        img_result = None\n        try:\n            stamp = datetime.datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n            img_path = os.path.join(output_dir, f\"raw_backup_{stamp}.img\")\n            self._raw_recovery_progress(\"AUTO 1/4: IMG backup ban rahi hai...\")\n            img_result = create_disk_image(disk_path, img_path, max_bytes=limit, progress_callback=self._raw_recovery_progress)\n\n            source_for_scan = img_result[\"img_path\"] if img_result and img_result.get(\"bytes\", 0) &gt; 0 else disk_path\n            self._raw_recovery_progress(\"AUTO 2/4: IMG import/source ready ho gaya...\")\n            self.after(0, lambda src=source_for_scan: self.raw_disk_var.set(src))\n\n            self._raw_recovery_progress(\"AUTO 3/4: PhotoRec multi-pass recovery chal rahi hai...\")\n            photo_result = multi_pass_recovery(\n                source_for_scan, output_dir,\n                progress_callback=self._make_recovery_progress_callback())\n            recovered = photo_result[\"files\"]\n\n            self._raw_recovery_progress(\"AUTO 4/4: Real hex preview read ho raha hai...\")\n            first_sector = recovered[0][\"offset\"] // SECTOR_SIZE if recovered else 0\n            hex_text = raw_hex_viewer(first_sector, disk_path=source_for_scan)\n\n            def _finish():\n                self._set_status(f\"AUTO complete: {len(recovered)} files recovered\", C[\"success\"])\n                file_map = {os.path.basename(f[\"path\"]): f for f in recovered}\n                seen_basenames = set()\n                for iid in list(self.rec_tree.get_children()):\n                    vals = list(self.rec_tree.item(iid, \"values\"))\n                    if not vals:\n                        continue\n                    bn = vals[0]\n                    seen_basenames.add(bn)\n                    if bn in file_map:\n                        item = file_map[bn]\n                        loc = item[\"path\"][-60:] if len(item[\"path\"]) &gt; 60 else item[\"path\"]\n                        self.rec_tree.item(iid, values=(\n                            bn, item[\"file_type\"], self._fmt_size(item[\"bytes\"]),\n                            \"\u2705 Recovered\", loc, \"--\"), tags=(\"recovered\",))\n                        self.rec_found_files[iid] = item[\"path\"]\n                for item in recovered:\n                    bn = os.path.basename(item[\"path\"])\n                    if bn in seen_basenames:\n                        continue\n                    loc = item[\"path\"][-60:] if len(item[\"path\"]) &gt; 60 else item[\"path\"]\n                    iid = self.rec_tree.insert(\"\", \"end\", values=(\n                        bn, item[\"file_type\"], self._fmt_size(item[\"bytes\"]),\n                        \"\u2705 Recovered\", loc, \"--\"), tags=(\"recovered\",))\n                    self.rec_found_files[iid] = item[\"path\"]\n                self._on_rec_select()\n                self._show_auto_recovery_result(output_dir, img_result, photo_result, recovered, warnings, hex_text)\n\n            self.after(0, _finish)\n        except InterruptedError as e:\n            msg = str(e)\n            self.after(0, lambda msg=msg: self._set_status(msg, C[\"warning\"]))\n        except Exception as e:\n            err = str(e)\n            self.after(0, lambda err=err: self._set_status(\"AUTO recovery failed: \" + err, C[\"error\"]))\n            self.after(0, lambda err=err: messagebox.showerror(\"AUTO Recovery Error\", err))\n        finally:\n            self.after(0, self._finish_recovery_operation)\n\n    def _show_auto_recovery_result(self, output_dir, img_result, results, recovered, warnings, hex_text):\n        win = tk.Toplevel(self)\n        win.title(\"AUTO Recovery Result\")\n        win.geometry(\"1100x720\")\n        win.configure(bg=C[\"bg\"])\n        if isinstance(results, dict):\n            found_count = len(results.get(\"files\", []))\n            recup_dir = results.get(\"recup_dir\", output_dir)\n            block_size = results.get(\"block_size\", \"N/A\")\n        else:\n            found_count = len(results)\n            recup_dir = output_dir\n            block_size = \"N/A\"\n        summary = (\n            f\"AUTO RECOVERY COMPLETE\\n\"\n            f\"Output Folder: {output_dir}\\n\"\n            f\"recup_dir: {recup_dir}\\n\"\n            f\"Block size: {block_size}\\n\"\n            f\"IMG: {(img_result or {}).get('img_path', 'N/A')}\\n\"\n            f\"IMG Size: {self._fmt_size((img_result or {}).get('bytes', 0))}\\n\"\n            f\"Signatures/Files Found: {found_count}\\n\"\n            f\"Files Recovered: {len(recovered)}\\n\"\n            f\"Warnings: {len(warnings)}\\n\"\n            f\"\\nRecovered Files:\\n\"\n        )\n        if recovered:\n            summary += \"\\n\".join(f\"- {item['path']} ({self._fmt_size(item['bytes'])})\" for item in recovered[:80])\n            if len(recovered) &gt; 80:\n                summary += f\"\\n... aur {len(recovered) - 80} files\"\n        else:\n            summary += \"Koi file extract nahi hui.\"\n        if warnings:\n            summary += \"\\n\\nWarnings:\\n\" + \"\\n\".join(warnings[:40])\n        summary += \"\\n\\nREAL HEX PREVIEW:\\n\" + hex_text\n        viewer = scrolledtext.ScrolledText(win, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], wrap=\"none\")\n        viewer.pack(fill=\"both\", expand=True, padx=10, pady=10)\n        viewer.insert(\"1.0\", summary)\n        viewer.config(state=\"disabled\")\n        messagebox.showinfo(\n            \"AUTO Recovery Complete\",\n            f\"{len(recovered)} files recover hui.\\n\\nOutput folder:\\n{output_dir}\\n\\nDetails result window me show ho rahe hain.\"\n        )\n\n    def _select_img_source(self):\n        img_path = filedialog.askopenfilename(\n            title=\"IMG/DD/raw disk image import karo\",\n            filetypes=[(\"Disk images\", \"*.img *.dd *.raw *.bin\"), (\"All files\", \"*.*\")]\n        )\n        if not img_path:\n            return\n        self.raw_disk_var.set(img_path)\n        try:\n            values = list(self.raw_disk_combo.cget(\"values\"))\n            if img_path not in values:\n                values.insert(0, img_path)\n                self.raw_disk_combo.configure(values=values)\n        except Exception:\n            pass\n        self._update_raw_source_badge()\n        self._set_status(f\"IMG source selected: {img_path}\", C[\"success\"])\n\n    def _export_hex_sector_img(self):\n        try:\n            sector = int((self.raw_sector_num.get() or \"0\").strip())\n            start_offset = sector * SECTOR_SIZE\n            limit = self._raw_limit_bytes()\n            disk_path = self._raw_disk_path()\n            self._update_raw_source_badge()\n            if not self._ensure_admin_for_raw_recovery(disk_path):\n                return\n        except Exception as e:\n            messagebox.showerror(\"Sector IMG Error\", str(e))\n            return\n        img_path = filedialog.asksaveasfilename(\n            title=\"Sector range ko IMG me save karo\",\n            defaultextension=\".img\",\n            filetypes=[(\"Disk image\", \"*.img\"), (\"All files\", \"*.*\")]\n        )\n        if not img_path:\n            return\n        size_text = \"source ke end tak\" if limit is None else self._fmt_size(limit)\n        if not messagebox.askyesno(\n            \"Sector to IMG\",\n            f\"Hex/Sector range ko IMG me export karein?\\n\\n\"\n            f\"Source: {disk_path}\\n\"\n            f\"Start sector: {sector}\\n\"\n            f\"Start offset: 0x{start_offset:X}\\n\"\n            f\"Size: {size_text}\\n\"\n            f\"Output: {img_path}\\n\\n\"\n            \"Is IMG ko Import IMG button se scan kar sakte hain.\"\n        ):\n            return\n        self._reset_raw_progress(\"Sector IMG export start ho raha hai...\")\n        try:\n            self._begin_recovery_operation(\"Sector IMG export start ho raha hai...\")\n        except Exception as e:\n            messagebox.showwarning(\"Recovery Busy\", str(e))\n            return\n        if not self._hdd_action_submit(\"sector_img_export\", self._do_export_hex_sector_img, disk_path, img_path, start_offset, limit):\n            self._set_status(\"Recovery action already running; wait for completion.\", C[\"warning\"])\n\n    def _do_export_hex_sector_img(self, disk_path, img_path, start_offset, limit):\n        try:\n            result = copy_disk_range_to_img(disk_path, img_path, start_offset=start_offset, max_bytes=limit, progress_callback=self._raw_recovery_progress)\n            def _finish():\n                self._set_status(f\"Sector IMG complete: {self._fmt_size(result['bytes'])}\", C[\"success\"])\n                self.raw_disk_var.set(result[\"img_path\"])\n                messagebox.showinfo(\n                    \"Sector IMG Complete\",\n                    f\"IMG ban gayi:\\n{result['img_path']}\\n\\n\"\n                    f\"Size: {self._fmt_size(result['bytes'])}\\n\\n\"\n                    \"Ab yahi IMG source select ho gayi hai; PhotoRec Deep Scan/AUTO se scan kar sakte hain.\"\n                )\n            self.after(0, _finish)\n        except InterruptedError as e:\n            msg = str(e)\n            self.after(0, lambda msg=msg: self._set_status(msg, C[\"warning\"]))\n        except Exception as e:\n            err = str(e)\n            self.after(0, lambda err=err: self._set_status(\"Sector IMG failed: \" + err, C[\"error\"]))\n            self.after(0, lambda err=err: messagebox.showerror(\"Sector IMG Error\", err))\n        finally:\n            self.after(0, self._finish_recovery_operation)\n\n    def _candidate_dmde_paths(self):\n        candidates = []\n        env_path = os.environ.get(\"GODAWARI_DMDE_PATH\", \"\").strip().strip('\"')\n        if env_path:\n            candidates.append(env_path)\n        for exe_name in (\"dmde.exe\", \"dmde64.exe\", \"dmde32.exe\"):\n            found = shutil.which(exe_name)\n            if found:\n                candidates.append(found)\n        base_dirs = [\n            os.getcwd(),\n            os.path.dirname(os.path.abspath(sys.argv[0])),\n            os.environ.get(\"ProgramFiles\", \"\"),\n            os.environ.get(\"ProgramFiles(x86)\", \"\"),\n            os.environ.get(\"LOCALAPPDATA\", \"\"),\n        ]\n        rels = [\n            \"DMDE\\\\dmde.exe\",\n            \"DMDE\\\\dmde64.exe\",\n            \"dmde\\\\dmde.exe\",\n            \"tools\\\\dmde\\\\dmde.exe\",\n            \"assets\\\\tools\\\\dmde\\\\dmde.exe\",\n        ]\n        for base in base_dirs:\n            if not base:\n                continue\n            for rel in rels:\n                candidates.append(os.path.join(base, rel))\n        seen = set()\n        result = []\n        for path in candidates:\n            norm = os.path.normcase(os.path.abspath(path))\n            if norm in seen:\n                continue\n            seen.add(norm)\n            if os.path.isfile(path):\n                result.append(path)\n        return result\n\n    def _find_dmde_exe(self):\n        candidates = self._candidate_dmde_paths()\n        if candidates:\n            return candidates[0]\n        return \"\"\n\n    def _ask_dmde_exe(self):\n        exe = filedialog.askopenfilename(\n            title=\"DMDE executable select karo (dmde.exe)\",\n            filetypes=[(\"DMDE executable\", \"dmde*.exe\"), (\"Executable\", \"*.exe\"), (\"All files\", \"*.*\")]\n        )\n        if exe and os.path.isfile(exe):\n            os.environ[\"GODAWARI_DMDE_PATH\"] = exe\n            return exe\n        return \"\"\n\n    def _start_dmde_recovery(self):\n        disk_path = self._raw_disk_path()\n        self._update_raw_source_badge()\n        if not self._ensure_admin_for_raw_recovery(disk_path):\n            return\n\n        dmde_exe = self._find_dmde_exe()\n        if not dmde_exe:\n            self._set_status(\"DMDE available nahi mila. Auto-detect only mode active hai.\", C[\"warning\"])\n            messagebox.showinfo(\n                \"DMDE Not Available\",\n                \"DMDE executable auto-detect nahi hua.\\n\\n\"\n                \"Ab yeh tool manual .exe browse nahi maangega.\\n\"\n                \"Agar DMDE use karna ho to usse standard location me install/put karo,\\n\"\n                \"ya GODAWARI_DMDE_PATH env var set karo.\"\n            )\n            return\n\n        source_kind = \"IMG/file source\" if os.path.isfile(disk_path) else \"raw disk/device\"\n        if not messagebox.askyesno(\n            \"DMDE Recovery\",\n            f\"DMDE recovery console launch karein?\\n\\n\"\n            f\"DMDE: {dmde_exe}\\n\"\n            f\"Source: {disk_path}\\n\"\n            f\"Type: {source_kind}\\n\\n\"\n            \"Forensic safety:\\n\"\n            \"- Source disk par kuch write mat karein.\\n\"\n            \"- Recovered data hamesha dusre drive/folder me save karein.\\n\"\n            \"- DMDE ke write/repair options sirf verified clone/IMG par use karein.\"\n        ):\n            return\n\n        self._reset_raw_progress(\"DMDE Recovery launch ho raha hai...\")\n        try:\n            self._begin_recovery_operation(\"DMDE Recovery launch ho raha hai...\")\n        except Exception as e:\n            messagebox.showwarning(\"Recovery Busy\", str(e))\n            return\n        if not self._hdd_action_submit(\"dmde_recovery\", self._do_dmde_recovery, dmde_exe, disk_path):\n            self._set_status(\"Recovery action already running; wait for completion.\", C[\"warning\"])\n\n    def _do_dmde_recovery(self, dmde_exe, disk_path):\n        proc = None\n        try:\n            report_dir = getattr(self, \"backup_dir\", os.getcwd())\n            os.makedirs(report_dir, exist_ok=True)\n            report_path = os.path.join(report_dir, \"dmde_recovery_launch.log\")\n            cmd = [dmde_exe, disk_path]\n            self._raw_recovery_progress(\"DMDE subprocess start: \" + subprocess.list2cmdline(cmd))\n            proc = subprocess.Popen(\n                cmd,\n                cwd=os.path.dirname(dmde_exe) or None,\n                stdout=subprocess.PIPE,\n                stderr=subprocess.STDOUT,\n                text=True,\n                encoding=\"utf-8\",\n                errors=\"replace\",\n            )\n            self._dmde_proc = proc\n            started = datetime.datetime.now().isoformat(timespec=\"seconds\")\n            with open(report_path, \"a\", encoding=\"utf-8\") as f:\n                f.write(f\"[{started}] DMDE launched\\n\")\n                f.write(\"Command: \" + subprocess.list2cmdline(cmd) + \"\\n\")\n                f.write(\"Source: \" + disk_path + \"\\n\")\n            self._audit_event(\"dmde_recovery_started\", {\n                \"dmde\": dmde_exe,\n                \"source\": disk_path,\n                \"pid\": proc.pid,\n                \"report\": report_path,\n            })\n            self.after(0, lambda: self._set_status(f\"DMDE running (PID {proc.pid})\", C[\"success\"]))\n\n            output_tail = []\n            if proc.stdout:\n                while proc.poll() is None:\n                    line = proc.stdout.readline()\n                    if line:\n                        clean = line.strip()\n                        if clean:\n                            output_tail.append(clean)\n                            output_tail = output_tail[-40:]\n                            self._raw_recovery_progress(\"DMDE: \" + clean[:180])\n                    else:\n                        time.sleep(0.25)\n                for line in proc.stdout.readlines():\n                    clean = line.strip()\n                    if clean:\n                        output_tail.append(clean)\n            rc = proc.wait(timeout=5)\n            ended = datetime.datetime.now().isoformat(timespec=\"seconds\")\n            with open(report_path, \"a\", encoding=\"utf-8\") as f:\n                f.write(f\"[{ended}] DMDE exited rc={rc}\\n\")\n                if output_tail:\n                    f.write(\"Output tail:\\n\" + \"\\n\".join(output_tail[-40:]) + \"\\n\")\n                f.write(\"\\n\")\n            self._audit_event(\"dmde_recovery_finished\", {\"rc\": rc, \"report\": report_path})\n            self.after(0, lambda rc=rc, report_path=report_path: self._set_status(f\"DMDE closed (rc={rc}) - log saved\", C[\"success\"] if rc == 0 else C[\"warning\"]))\n            self.after(0, lambda report_path=report_path: messagebox.showinfo(\"DMDE Recovery\", f\"DMDE session closed.\\n\\nLog:\\n{report_path}\"))\n        except FileNotFoundError:\n            self.after(0, lambda: messagebox.showerror(\"DMDE Missing\", \"DMDE executable nahi mila. dmde.exe path dobara select karein.\"))\n        except InterruptedError as e:\n            msg = str(e)\n            self.after(0, lambda msg=msg: self._set_status(msg, C[\"warning\"]))\n        except Exception as e:\n            err = str(e)\n            self.after(0, lambda err=err: self._set_status(\"DMDE launch failed: \" + err, C[\"error\"]))\n            self.after(0, lambda err=err: messagebox.showerror(\"DMDE Recovery Error\", err))\n        finally:\n            if getattr(self, \"_dmde_proc\", None) is proc:\n                self._dmde_proc = None\n            self.after(0, self._finish_recovery_operation)\n\n    def _start_photorec_deep_scan(self):\n        disk_path = self._raw_disk_path()\n        self._update_raw_source_badge()\n        if not self._ensure_admin_for_raw_recovery(disk_path):\n            return\n        output_dir = filedialog.askdirectory(title=\"PhotoRec recovered output folder select karo\")\n        if not output_dir:\n            return\n        if not messagebox.askyesno(\n            \"PhotoRec Deep Scan\",\n            f\"PhotoRec-style deep scan start karein?\\n\\n\"\n            f\"Source: {disk_path}\\n\"\n            f\"Output: {output_dir}\\\\recup_dir.N\\n\\n\"\n            \"Process:\\n\"\n            \"1. Auto block/cluster size detect\\n\"\n            \"2. Pass 1 block-aligned carving\\n\"\n            \"3. Pass 2 unaligned signature scan\\n\"\n            \"4. Validation + best-effort fragment reassembly\\n\\n\"\n            \"No size limit rakha gaya hai, isliye full disk scan bahut time le sakta hai.\"\n        ):\n            return\n        self.rec_tree.delete(*self.rec_tree.get_children())\n        self.rec_found_files = {}\n        self._set_recovery_scan_mode(\"Mode: Zone B \u2014 Raw Sector Recovery (Admin)\", C[\"warning\"])\n        self._clear_recovery_progress_log()\n        self._prep_raw_scan_progress_ui()\n        self._reset_raw_progress(\"PhotoRec Deep Scan start ho rahi hai...\")\n        try:\n            self._begin_recovery_operation(\"PhotoRec Deep Scan start ho rahi hai...\")\n        except Exception as e:\n            messagebox.showwarning(\"Recovery Busy\", str(e))\n            return\n        if not self._hdd_action_submit(\"photorec_deep_scan\", self._do_photorec_deep_scan, disk_path, output_dir):\n            self._set_status(\"Recovery action already running; wait for completion.\", C[\"warning\"])\n\n    def _do_photorec_deep_scan(self, disk_path, output_dir):\n        try:\n            result = multi_pass_recovery(\n                disk_path, output_dir,\n                progress_callback=self._make_recovery_progress_callback())\n            def _finish():\n                file_map = {os.path.basename(f[\"path\"]): f for f in result.get(\"files\", [])}\n                seen_basenames = set()\n                for iid in list(self.rec_tree.get_children()):\n                    vals = list(self.rec_tree.item(iid, \"values\"))\n                    if not vals:\n                        continue\n                    bn = vals[0]\n                    seen_basenames.add(bn)\n                    if bn in file_map:\n                        item = file_map[bn]\n                        loc = item[\"path\"][-60:] if len(item[\"path\"]) &gt; 60 else item[\"path\"]\n                        self.rec_tree.item(iid, values=(\n                            bn, item[\"file_type\"], self._fmt_size(item[\"bytes\"]),\n                            \"\u2705 Recovered\", loc, \"--\"), tags=(\"recovered\",))\n                        self.rec_found_files[iid] = item[\"path\"]\n                for item in result.get(\"files\", []):\n                    bn = os.path.basename(item[\"path\"])\n                    if bn in seen_basenames:\n                        continue\n                    loc = item[\"path\"][-60:] if len(item[\"path\"]) &gt; 60 else item[\"path\"]\n                    iid = self.rec_tree.insert(\"\", \"end\", values=(\n                        bn, item[\"file_type\"], self._fmt_size(item[\"bytes\"]),\n                        \"\u2705 Recovered\", loc, \"--\"), tags=(\"recovered\",))\n                    self.rec_found_files[iid] = item[\"path\"]\n                self._on_rec_select()\n                self._set_status(f\"PhotoRec scan complete: {len(result.get('files', []))} files\", C[\"success\"])\n                self._show_photorec_result(result)\n            self.after(0, _finish)\n        except InterruptedError as e:\n            msg = str(e)\n            self.after(0, lambda msg=msg: self._set_status(msg, C[\"warning\"]))\n        except Exception as e:\n            err = str(e)\n            self.after(0, lambda err=err: self._set_status(\"PhotoRec scan failed: \" + err, C[\"error\"]))\n            self.after(0, lambda err=err: messagebox.showerror(\"PhotoRec Deep Scan Error\", err))\n        finally:\n            self.after(0, self._finish_recovery_operation)\n\n    def _show_photorec_result(self, result):\n        win = tk.Toplevel(self)\n        win.title(\"PhotoRec Deep Scan Result\")\n        win.geometry(\"980x620\")\n        win.configure(bg=C[\"bg\"])\n        text = (\n            f\"PHOTOREC-STYLE DEEP SCAN COMPLETE\\n\"\n            f\"recup_dir: {result['recup_dir']}\\n\"\n            f\"Block size: {result['block_size']} bytes\\n\"\n            f\"Recovered files: {len(result['files'])}\\n\\n\"\n        )\n        for item in result[\"files\"][:300]:\n            text += f\"Pass {item['pass']} | 0x{item['offset']:X} | {item['file_type']} | {self._fmt_size(item['bytes'])} | {item['path']}\\n\"\n        if len(result[\"files\"]) &gt; 300:\n            text += f\"\\n... aur {len(result['files']) - 300} files tree me available hain.\"\n        viewer = scrolledtext.ScrolledText(win, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], wrap=\"none\")\n        viewer.pack(fill=\"both\", expand=True, padx=10, pady=10)\n        viewer.insert(\"1.0\", text)\n        viewer.config(state=\"disabled\")\n        messagebox.showinfo(\"PhotoRec Deep Scan\", f\"{len(result['files'])} files recover hui.\\n\\nFolder:\\n{result['recup_dir']}\")\n\n    def _show_raw_hex_dialog(self):\n        try:\n            sector = int((self.raw_sector_num.get() or \"0\").strip())\n            disk_path = self._raw_disk_path()\n            self._update_raw_source_badge()\n            if not self._ensure_admin_for_raw_recovery(disk_path):\n                return\n        except Exception as e:\n            messagebox.showerror(\"Hex Viewer Error\", str(e))\n            return\n        self._reset_raw_progress(f\"Hex viewer sector {sector} read ho raha hai...\")\n        try:\n            self._begin_recovery_operation(f\"Hex viewer sector {sector} read ho raha hai...\")\n        except Exception as e:\n            messagebox.showwarning(\"Recovery Busy\", str(e))\n            return\n        if not self._hdd_action_submit(\"raw_hex_view\", self._do_show_raw_hex_dialog, disk_path, sector):\n            self._set_status(\"Recovery action already running; wait for completion.\", C[\"warning\"])\n\n    def _do_show_raw_hex_dialog(self, disk_path, sector):\n        try:\n            self._raw_recovery_progress(f\"Hex viewer: reading {disk_path} sector {sector}\")\n            text = raw_hex_viewer(sector, disk_path=disk_path)\n            self.after(0, lambda: self._open_raw_hex_window(sector, text))\n            self.after(0, lambda: self._set_status(f\"Hex viewer ready: sector {sector}\", C[\"success\"]))\n        except InterruptedError as e:\n            msg = str(e)\n            self.after(0, lambda msg=msg: self._set_status(msg, C[\"warning\"]))\n        except Exception as e:\n            err = str(e)\n            self.after(0, lambda err=err: self._set_status(\"Hex viewer failed: \" + err, C[\"error\"]))\n            self.after(0, lambda err=err: messagebox.showerror(\"Hex Viewer Error\", err))\n        finally:\n            self.after(0, self._finish_recovery_operation)\n\n    def _open_raw_hex_window(self, sector, text):\n        win = tk.Toplevel(self)\n        win.title(f\"Raw Hex Viewer - Sector {sector}\")\n        win.geometry(\"980x620\")\n        win.configure(bg=C[\"bg\"])\n        viewer = scrolledtext.ScrolledText(win, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], wrap=\"none\")\n        viewer.pack(fill=\"both\", expand=True, padx=10, pady=10)\n        viewer.insert(\"1.0\", text)\n        viewer.config(state=\"disabled\")\n\n    def _start_file_recovery(self):\n        drive = self.rec_drive.get().replace(\"\\\\\", \"\").rstrip(\"\\\\\")\n        exts = [e.strip().lstrip(\".\") for e in self.rec_ext.get().split(\",\") if e.strip()]\n        if not drive or not exts:\n            messagebox.showwarning(\"Input\", \"Drive aur extensions fill karo.\")\n            return\n        if self._is_mobile_source(drive):\n            if not self._mobile_adb_available():\n                self._show_adb_help()\n                return\n            if not self._mobile_device_ready():\n                messagebox.showerror(\"Device Not Ready\", \"ADB mila, lekin phone connected/authorized nahi hai.\\nUSB debugging enable karke phone par Allow dabao, phir retry karo.\")\n                return\n        ext_str = \", \".join(exts)\n        if not messagebox.askyesno(\"File Search\",\n            f\"{'Mobile (ADB)' if self._is_mobile_source(drive) else f'Drive {drive}:'} pe yeh files dhundega:\\n{ext_str}\\n\\n\"\n            f\"Note: Yeh ZONE A scan hai \u2014 drive pe maujood accessible files dhundta hai.\\n\"\n            f\"Deleted files ke liye ZONE B \u2192 Raw Signature Scan use karo (Admin required).\\n\\nProceed?\"):\n            return\n        # Reset control flags\n        try:\n            self._begin_recovery_operation(f\"Searching {drive} for {ext_str}...\")\n        except Exception as e:\n            messagebox.showwarning(\"Recovery Busy\", str(e))\n            return\n        self._set_recovery_scan_mode(\"Mode: Zone A \u2014 File Search (Drive Scan)\", C[\"accent2\"])\n        self._clear_recovery_progress_log()\n        self._prep_drive_scan_progress_ui()\n        if hasattr(self, \"raw_progress_label\"):\n            self.raw_progress_label.config(text=f\"Searching {drive}: for {ext_str}...\")\n        if hasattr(self, \"raw_progress_var\"):\n            self.raw_progress_var.set(0)\n        # Update control buttons\n        if hasattr(self, \"_rec_stop_btn\"):\n            self._rec_stop_btn.config(state=\"normal\")\n        if hasattr(self, \"_rec_pause_btn\"):\n            self._rec_pause_btn.config(state=\"normal\", text=\"\u23f8 Pause\")\n        if not self._hdd_action_submit(\"file_search\", self._do_file_recovery, drive, exts):\n            self._set_status(\"Recovery action already running; wait for completion.\", C[\"warning\"])\n\n    def _stop_file_recovery(self):\n        # Set BOTH the legacy flag and the threading.Event so the background\n        # scan loop detects the stop signal at its very next check (&lt; 50 ms).\n        self._recovery_stop_flag = True\n        self._recovery_pause_flag = False\n        if hasattr(self, \"_scan_stop_event\"):\n            self._scan_stop_event.set()  # unblocks any time.sleep() pause too\n        self._set_status(\"\u23f9 Recovery roka ja raha hai...\", C[\"warning\"])\n        if hasattr(self, \"_rec_stop_btn\"):\n            self._rec_stop_btn.config(state=\"disabled\")\n        if hasattr(self, \"_rec_pause_btn\"):\n            self._rec_pause_btn.config(state=\"disabled\", text=\"\u23f8 Pause\")\n\n    def _pause_resume_file_recovery(self):\n        if not hasattr(self, \"_recovery_pause_flag\"):\n            return\n        self._recovery_pause_flag = not self._recovery_pause_flag\n        if self._recovery_pause_flag:\n            self._set_status(\"\u23f8 Recovery paused \u2014 Resume dabao jab taiyar ho\", C[\"warning\"])\n            if hasattr(self, \"_rec_pause_btn\"):\n                self._rec_pause_btn.config(text=\"\u25b6 Resume\")\n        else:\n            self._set_status(\"\u25b6 Recovery resume ho gayi...\", C[\"accent4\"])\n            if hasattr(self, \"_rec_pause_btn\"):\n                self._rec_pause_btn.config(text=\"\u23f8 Pause\")\n\n    def _do_file_recovery(self, drive, exts):\n        \"\"\"\n        Background thread worker for Zone-A file search.\n\n        ALL GUI updates go through self._ui_queue (via self._q*() helpers).\n        The main thread drains the queue every 50 ms in _poll_ui_queue().\n        This keeps the GUI fully responsive and the progress bar smooth.\n        \"\"\"\n        # \u2500\u2500 1. Reset UI on main thread \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        def _scan_start_ui():\n            try:\n                for i in self.rec_tree.get_children():\n                    self.rec_tree.delete(i)\n                self.rec_found_files = {}\n                self._recovery_reset_ui_batch()\n                self._on_rec_select()\n                if hasattr(self, \"raw_progress_log\"):\n                    self.raw_progress_log.config(state=\"normal\")\n                    self.raw_progress_log.delete(\"1.0\", \"end\")\n                    self.raw_progress_log.config(state=\"disabled\")\n                # Switch progress bar to indeterminate (animated bounce)\n                if hasattr(self, \"raw_progress_bar\"):\n                    try:\n                        self.raw_progress_bar.stop()\n                    except Exception:\n                        pass\n                    self.raw_progress_bar.config(mode=\"indeterminate\")\n                    self.raw_progress_bar.start(12)\n                if hasattr(self, \"raw_progress_label\"):\n                    self.raw_progress_label.config(text=f\"Scan shuru ho raha hai \u2014 {drive}:\\\\ ...\")\n            except Exception:\n                pass\n        self.after(0, _scan_start_ui)\n\n        # Clear the stop event so a previous stop does not block a fresh scan\n        self._scan_stop_event.clear()\n        self._recovery_stop_flag = False   # also reset the legacy flag\n        before_state = self._snapshot_resource_state() or {}\n\n        file_count   = 0\n        scanned      = 0\n        local_matches = []   # accumulate for checkpoint saves\n\n        try:\n            ext_set  = {(\".\" + e.lower().strip(\".\")) for e in exts if e.strip()}\n            mode_key = f\"search_{drive.lower()}\"\n\n            # \u2500\u2500 2. Resume checkpoint \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            cp = self._load_recovery_checkpoint(mode_key) or {}\n            cp_exts = set(cp.get(\"exts\", [])) if isinstance(cp, dict) else set()\n            resume_ok = (\n                bool(cp)\n                and cp.get(\"drive\", \"\").lower() == drive.lower()\n                and cp_exts == {e.lower().strip(\".\") for e in exts}\n            )\n            processed_dirs = set(cp.get(\"processed_dirs\", [])) if resume_ok else set()\n            saved_matches  = cp.get(\"matches\", []) if resume_ok else []\n\n            if resume_ok and saved_matches:\n                for p in saved_matches:\n                    if self._scan_stop_event.is_set():\n                        break\n                    try:\n                        nm  = os.path.basename(p)\n                        ex  = os.path.splitext(nm)[1].lstrip(\".\") or \"?\"\n                        sz  = self._fmt_size(os.path.getsize(p)) if os.path.exists(p) else \"?\"\n                        loc = p[-60:] if len(p) &gt; 60 else p\n                        row = (nm, ex, sz, \"Found \u2014 Recover dabao \u25b6\", loc, \"--\")\n                        # \u25b6 Queue the tree row \u2014 do NOT touch rec_tree from background thread\n                        self._q_tree_row(row, p)\n                        file_count += 1\n                        local_matches.append(p)\n                    except Exception:\n                        pass\n                self._q_log(f\"Resume checkpoint: {len(saved_matches)} previous matches loaded\")\n\n            # \u2500\u2500 3. Mobile or local drive scan \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            if self._is_mobile_source(drive):\n                mobile_paths = self._mobile_find_candidates(exts)\n                for p in mobile_paths:\n                    if self._scan_stop_event.is_set():\n                        break\n                    name = os.path.basename(p)\n                    ext  = os.path.splitext(name)[1].lstrip(\".\") or \"?\"\n                    loc  = p[-60:] if len(p) &gt; 60 else p\n                    row  = (name, ext, \"Mobile\", \"Found \u2014 Recover dabao \u25b6\", loc, \"--\")\n                    entry = {\"kind\": \"mobile\", \"path\": p}\n                    self._q_tree_row(row, entry)\n                    file_count += 1\n                    local_matches.append(p)\n\n                self._save_recovery_checkpoint(mode_key, {\n                    \"drive\": drive,\n                    \"exts\": [e.lower().strip(\".\") for e in exts],\n                    \"matches\": [m for m in local_matches][-3000:],\n                    \"processed_dirs\": [],\n                })\n\n            else:\n                # \u2500\u2500 Local drive walk \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n                root_path = drive + \":\\\\\"\n                _PROGRESS_INTERVAL   = 5    # update label every N dirs\n                _LOG_INTERVAL        = 25   # log path every N dirs\n                _CHECKPOINT_INTERVAL = 250  # save checkpoint every N dirs\n                last_progress_time = time.monotonic()\n\n                for dirpath, _, filenames in os.walk(root_path):\n                    # \u2500\u2500 Instant stop check \u2014 no Tk access, thread-safe \u2500\u2500\u2500\n                    if self._scan_stop_event.is_set() or getattr(self, \"_recovery_stop_flag\", False):\n                        self._scan_stop_event.set()\n                        break\n\n                    if dirpath in processed_dirs:\n                        continue\n\n                    # \u2500\u2500 Pause: tight sleep loop \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n                    while getattr(self, \"_recovery_pause_flag\", False):\n                        if self._scan_stop_event.is_set() or getattr(self, \"_recovery_stop_flag\", False):\n                            self._scan_stop_event.set()\n                            break\n                        time.sleep(0.15)\n\n                    # \u2500\u2500 Scan files in this directory \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n                    for fn in filenames:\n                        if self._scan_stop_event.is_set():\n                            break\n                        low_ext = os.path.splitext(fn)[1].lower()\n                        if low_ext not in ext_set:\n                            continue\n                        full = os.path.join(dirpath, fn)\n                        try:\n                            sz = self._fmt_size(os.path.getsize(full))\n                        except Exception:\n                            sz = \"?\"\n                        type_lbl = low_ext.lstrip(\".\") or \"?\"\n                        loc = dirpath[-60:] if len(dirpath) &gt; 60 else dirpath\n                        row = (fn, type_lbl, sz, \"Found \u2014 Recover dabao \u25b6\", loc, \"--\")\n                        # \u25b6 Thread-safe: put into queue, NOT self.after(0,...)\n                        self._q_tree_row(row, full)\n                        file_count += 1\n                        local_matches.append(full)\n\n                    scanned += 1\n                    processed_dirs.add(dirpath)\n\n                    # \u2500\u2500 Yield briefly so the UI thread can run often \u2500\u2500\u2500\u2500\u2500\n                    time.sleep(0.001)\n\n                    # \u2500\u2500 Real-time progress label update (via queue) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\n                    now = time.monotonic()\n                    if scanned == 1 or now - last_progress_time &gt;= 0.100:\n                        folder_tail = dirpath[-65:] if len(dirpath) &gt; 65 else dirpath\n                        label_text  = (\n                            f\"\ud83d\udd0d Scanning...  {scanned:,} folders scanned  |  \"\n                            f\"{file_count:,} files mili  |  ...{folder_tail}\"\n                        )\n                        self._q(\"progress_label\", label_text)\n                        self._hdd_recovery_emit_metrics({\n                            \"phase\": \"file_search\",\n                            \"status_text\": label_text,\n                            \"scan_mode\": \"Mode: Zone A \u2014 File Search (Drive Scan)\",\n                            \"progress_pct\": None,\n                            \"files_found\": file_count,\n                            \"scanned_dirs\": scanned,\n                            \"resource_before_mb\": before_state.get(\"available_mb\", 0),\n                            \"resource_after_mb\": int(psutil.virtual_memory().available / 1024**2) if psutil else 0,\n                            \"delta_mb\": int(psutil.virtual_memory().available / 1024**2) - int(before_state.get(\"available_mb\", 0)),\n                        })\n                        if scanned % _LOG_INTERVAL == 0 or file_count % 10 == 0:\n                            self._q_log(dirpath)\n                        last_progress_time = now\n\n                    # \u2500\u2500 Periodic checkpoint save \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n                    if scanned % _CHECKPOINT_INTERVAL == 0:\n                        self._save_recovery_checkpoint(mode_key, {\n                            \"drive\": drive,\n                            \"exts\": [e.lower().strip(\".\") for e in exts],\n                            \"matches\": local_matches[-3000:],\n                            \"processed_dirs\": list(processed_dirs)[-15000:],\n                        })\n\n            # \u2500\u2500 4. Scan done \u2014 final UI update via after() \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            stopped       = self._scan_stop_event.is_set() or getattr(self, \"_recovery_stop_flag\", False)\n            n             = file_count\n            folders_final = scanned\n\n            def _done():\n                \"\"\"Runs on main thread via self.after(0, ...).\"\"\"\n                # Stop indeterminate animation and switch to determinate\n                if hasattr(self, \"raw_progress_bar\"):\n                    try:\n                        self.raw_progress_bar.stop()\n                    except Exception:\n                        pass\n                    self.raw_progress_bar.config(mode=\"determinate\")\n\n                # Flush any leftover queued tree rows\n                self._recovery_flush_ui_batch()\n                self._on_rec_select()\n\n                color      = C[\"success\"] if n &gt; 0 else C[\"warning\"]\n                status_msg = f\"{'\u23f9 Stopped \u2014 ' if stopped else ''}Search complete: {n} files found on {drive}\"\n                self._set_status(status_msg, color)\n\n                if hasattr(self, \"raw_progress_var\"):\n                    self.raw_progress_var.set(100 if not stopped else 50)\n                if hasattr(self, \"raw_progress_label\"):\n                    if stopped:\n                        self.raw_progress_label.config(\n                            text=f\"\u23f9 Stopped | {n:,} files found | Drive {drive}\")\n                    else:\n                        self.raw_progress_label.config(\n                            text=(f\"\u2705 Scan complete \u2014 {n:,} files found on {drive}: | \"\n                                  f\"{folders_final:,} folders scanned\"))\n\n                if hasattr(self, \"_rec_stop_btn\"):\n                    self._rec_stop_btn.config(state=\"disabled\")\n                if hasattr(self, \"_rec_pause_btn\"):\n                    self._rec_pause_btn.config(state=\"disabled\", text=\"\u23f8 Pause\")\n                self._recovery_active = False\n\n                if not stopped:\n                    self._clear_recovery_checkpoint(mode_key)\n                if n == 0 and not stopped:\n                    messagebox.showinfo(\n                        \"No Files Found\",\n                        f\"Drive {drive}: pe koi file nahi mili.\\n\\n\"\n                        \"Deleted files ke liye Zone B \u2192 Raw Signature Scan use karo (admin required).\")\n                elif stopped and n &gt; 0:\n                    messagebox.showinfo(\n                        \"Search Stopped\",\n                        f\"\u23f9 Search rok di gayi.\\n{n} files abhi tak mili hain.\\n\\n\"\n                        \"In files ko select karke recover kar sakte ho.\")\n\n            self.after(0, _done)\n\n        except Exception as e:\n            err = str(e)\n            self.after(0, lambda err=err: self._set_status(\"Search failed: \" + err, C[\"error\"]))\n        finally:\n            self.after(0, self._finish_recovery_operation)\n\n    def _recover_selected_files(self):\n        dest = filedialog.askdirectory(title=\"Recovered files save karne ke liye folder choose karo\")\n        if not dest:\n            return\n        selected = self.rec_tree.selection()\n        if not selected:\n            messagebox.showwarning(\"Select Files\", \"Pehle list mein files select karo.\")\n            return\n        try:\n            self._begin_recovery_operation(\"Extracting selected files...\")\n        except Exception as e:\n            messagebox.showwarning(\"Busy\", str(e))\n            return\n        if hasattr(self, \"_rec_recover_btn\"):\n            self._rec_recover_btn.config(state=\"disabled\")\n        if not self._hdd_action_submit(\"recover_selected_files\", self._do_recover_selected_files, dest, list(selected)):\n            self._set_status(\"Recovery action already running; wait for completion.\", C[\"warning\"])\n\n    def _do_recover_selected_files(self, dest, selected_iids):\n        before_state = self._snapshot_resource_state() or {}\n        count = 0\n        errors = []\n        seen_hashes = set()\n        try:\n            for iid in selected_iids:\n                entry = self.rec_found_files.get(iid)\n                if entry is None:\n                    continue\n                if isinstance(entry, dict) and entry.get(\"kind\") == \"raw\":\n                    try:\n                        extract_limit = SIGNATURES[entry[\"file_type\"]][\"max_size\"]\n                        ui_limit = self._raw_limit_bytes()\n                        if ui_limit is not None and entry[\"offset\"] &lt; ui_limit:\n                            extract_limit = max(SECTOR_SIZE, min(extract_limit, ui_limit - entry[\"offset\"]))\n                        result = extract_file_at_offset(\n                            entry[\"disk_path\"],\n                            entry[\"offset\"],\n                            entry[\"file_type\"],\n                            output_dir=dest,\n                            max_bytes=extract_limit,\n                            progress_callback=self._raw_recovery_progress,\n                        )\n                        complete = result.get(\"complete_boundary\", True)\n                        if not complete:\n                            errors.append(f\"{os.path.basename(result['path'])}: boundary incomplete, file fragmented/truncated ho sakti hai\")\n                        try:\n                            h = self._sha256_file(result[\"path\"])\n                            if h in seen_hashes:\n                                os.remove(result[\"path\"])\n                                errors.append(f\"Duplicate removed: {os.path.basename(result['path'])}\")\n                            else:\n                                seen_hashes.add(h)\n                                score, _reason = self._integrity_score(result[\"path\"], entry.get(\"file_type\", \"\"))\n                                actual_size = self._fmt_size(result.get(\"bytes\") or os.path.getsize(result[\"path\"]))\n                                score_text = f\"{score}/100 {'\u2705' if score &gt;= 60 else '\u26a0 check'}\"\n                                status_txt = \"\u2705 Recovered\" if complete else \"\u26a0 May be corrupt\"\n                                tag = \"recovered\" if complete else \"partial\"\n                                def _upd_row(i=iid, s=actual_size, st=status_txt, sc=score_text, tg=tag):\n                                    vals = list(self.rec_tree.item(i, \"values\"))\n                                    if len(vals) &gt;= 6:\n                                        self.rec_tree.item(i, values=(vals[0], vals[1], s, st, vals[4], sc), tags=(tg,))\n                                    self._on_rec_select()\n                                self.after(0, _upd_row)\n                                count += 1\n                        except Exception as e:\n                            errors.append(f\"Hash/score failed: {e}\")\n                            count += 1\n                    except Exception as e:\n                        errors.append(str(e))\n                elif isinstance(entry, dict) and entry.get(\"kind\") == \"mobile\":\n                    try:\n                        src = entry.get(\"path\", \"\")\n                        if not src:\n                            continue\n                        dst = os.path.join(dest, os.path.basename(src))\n                        ok, out = self._mobile_pull_with_retry(src, dst)\n                        if ok:\n                            try:\n                                h = self._sha256_file(dst)\n                                if h in seen_hashes:\n                                    os.remove(dst)\n                                    errors.append(f\"Duplicate mobile file skipped: {os.path.basename(dst)}\")\n                                    continue\n                                seen_hashes.add(h)\n                                score, _reason = self._integrity_score(dst, os.path.splitext(dst)[1].lstrip(\".\"))\n                                actual_size = self._fmt_size(os.path.getsize(dst))\n                                score_text = f\"{score}/100 {'\u2705' if score &gt;= 60 else '\u26a0 check'}\"\n                                def _upd_mob(i=iid, s=actual_size, sc=score_text):\n                                    vals = list(self.rec_tree.item(i, \"values\"))\n                                    if len(vals) &gt;= 6:\n                                        self.rec_tree.item(i, values=(vals[0], vals[1], s, \"\u2705 Recovered\", vals[4], sc), tags=(\"recovered\",))\n                                    self._on_rec_select()\n                                self.after(0, _upd_mob)\n                            except Exception as e:\n                                errors.append(f\"Mobile hash/score failed: {e}\")\n                            count += 1\n                        else:\n                            errors.append(f\"Mobile pull failed: {src} | {out[:140]}\")\n                    except Exception as e:\n                        errors.append(str(e))\n                else:\n                    path = entry if isinstance(entry, str) else entry.get(\"path\", \"\")\n                    if path and os.path.exists(path):\n                        try:\n                            dst = os.path.join(dest, os.path.basename(path))\n                            shutil.copy2(path, dst)\n                            try:\n                                h = self._sha256_file(dst)\n                                if h in seen_hashes:\n                                    os.remove(dst)\n                                    errors.append(f\"Duplicate local file skipped: {os.path.basename(dst)}\")\n                                    continue\n                                seen_hashes.add(h)\n                                score, _reason = self._integrity_score(dst, os.path.splitext(dst)[1].lstrip(\".\"))\n                                actual_size = self._fmt_size(os.path.getsize(dst))\n                                score_text = f\"{score}/100 {'\u2705' if score &gt;= 60 else '\u26a0 check'}\"\n                                def _upd_loc(i=iid, s=actual_size, sc=score_text):\n                                    vals = list(self.rec_tree.item(i, \"values\"))\n                                    if len(vals) &gt;= 6:\n                                        self.rec_tree.item(i, values=(vals[0], vals[1], s, \"\u2705 Recovered\", vals[4], sc), tags=(\"recovered\",))\n                                    self._on_rec_select()\n                                self.after(0, _upd_loc)\n                            except Exception as e:\n                                errors.append(f\"Local hash/score failed: {e}\")\n                            count += 1\n                        except Exception as e:\n                            errors.append(str(e))\n        finally:\n            def _finish():\n                if hasattr(self, \"_rec_recover_btn\"):\n                    self._rec_recover_btn.config(state=\"normal\")\n                summary = f\"\u2705 {count} files recovered to {dest}\"\n                if errors:\n                    summary += f\" | \u26a0 {len(errors)} errors\"\n                self._set_status(summary, C[\"success\"] if not errors else C[\"warning\"])\n                after_state = self._snapshot_resource_state() or {}\n                self._hdd_recovery_emit_metrics({\n                    \"phase\": \"recovery_extract\",\n                    \"status_text\": summary,\n                    \"progress_pct\": 100.0,\n                    \"files_found\": count,\n                    \"resource_before_mb\": before_state.get(\"available_mb\", 0),\n                    \"resource_after_mb\": after_state.get(\"available_mb\", 0),\n                    \"delta_mb\": after_state.get(\"available_mb\", 0) - before_state.get(\"available_mb\", 0),\n                })\n            self.after(0, _finish)\n            self.after(0, self._finish_recovery_operation)\n            gc.collect()\n\n    # ---------- LIVE TEMPERATURE (unchanged) ----------\n    def _build_live_temps(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83c\udf21\ufe0f Live Temperature Monitor\", \"Real CPU/GPU thermal readings\", hw=True)\n        self._action_card_grid(frame, [\n            (\"\ud83c\udf21\", \"Refresh Temps\", \"CPU + GPU temperature readings\", C[\"btn_chip\"], self._scan_temps),\n        ], cols=1)\n        stats = tk.Frame(frame, bg=C[\"bg\"])\n        stats.pack(fill=\"x\", padx=16, pady=8)\n        self.temp_cards = {}\n        for i, (k, lbl, color) in enumerate([(\"cpu_t\",\"CPU Temp\",C[\"error\"]), (\"gpu_t\",\"GPU Temp\",C[\"accent4\"])]):\n            card = self._stat_card(stats, lbl, \"--\", color)\n            card.grid(row=0, column=i, padx=6, sticky=\"ew\")\n            stats.columnconfigure(i, weight=1)\n            self.temp_cards[k] = card\n        self.temp_log = self._scrolled_text(frame, 18)\n        return frame\n\n    def _scan_temps(self):\n        self._launch_job(\"scan_temps\", self._do_scan_temps)\n\n    def _do_scan_temps(self):\n        self._append_log(self.temp_log, \"Querying WMI thermal zones...\", C[\"text\"])\n        out, _ = self._run_powershell(\n            \"Get-WmiObject -Namespace root\\\\wmi \"\n            \"-Class MSAcpi_ThermalZoneTemperature | \"\n            \"Select-Object -ExpandProperty CurrentTemperature\", timeout=15)\n        temps = []\n        for line in out.splitlines():\n            stripped = line.strip()\n            if stripped.replace('.', '').isdigit():\n                try:\n                    temps.append(float(stripped))\n                except:\n                    pass\n        if temps:\n            cpu_c = (temps[0] / 10.0) - 273.15\n            self.temp_cards[\"cpu_t\"]._value_lbl.config(text=f\"{cpu_c:.1f} \u00b0C\")\n            self.temp_cards[\"cpu_t\"]._bar.config(value=min(cpu_c, 100))\n            self._append_log(self.temp_log, f\"CPU Temp: {cpu_c:.1f} \u00b0C\", C[\"success\"] if cpu_c &lt; 75 else C[\"error\"])\n            if len(temps) &gt; 1:\n                gpu_c = (temps[1] / 10.0) - 273.15\n                self.temp_cards[\"gpu_t\"]._value_lbl.config(text=f\"{gpu_c:.1f} \u00b0C\")\n                self.temp_cards[\"gpu_t\"]._bar.config(value=min(gpu_c, 100))\n                self._append_log(self.temp_log, f\"GPU Temp: {gpu_c:.1f} \u00b0C\", C[\"success\"] if gpu_c &lt; 85 else C[\"error\"])\n        else:\n            self._append_log(self.temp_log, \"\u26a0 Native WMI thermal probes not found on this hardware.\", C[\"warning\"])\n            self._append_log(self.temp_log, \"Note: Requires laptop sensors or specific desktop motherboards.\", C[\"text_dim\"])\n        self._append_log(self.temp_log, \"\u2705 Temp scan complete.\", C[\"success\"])\n        self._set_status(\"Temp scan complete\", C[\"success\"])\n\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  REVO-STYLE BATCH UNINSTALLER  v2.0  \u2014  Deep Forced Removal\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _build_uninstaller(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"Professional Uninstall Center\",\n                             \"Safe uninstall, force removal, leftover scan and audit-ready cleanup\")\n\n        guide = tk.Frame(frame, bg=C[\"card\"], highlightbackground=C[\"accent2\"], highlightthickness=1)\n        guide.pack(fill=\"x\", padx=16, pady=(8, 4))\n        tk.Label(guide, text=\"Beginner-safe workflow\", font=FONTS[\"subhead\"],\n                 fg=C[\"accent2\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=12, pady=(8, 2))\n        tk.Label(\n            guide,\n            text=\"1. Scan Programs.  2. Select an app.  3. Use Safe Uninstall first.  4. Scan Leftovers.  5. Clean only reviewed items. Force Uninstall is for broken uninstallers only.\",\n            font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], anchor=\"w\",\n            justify=\"left\", wraplength=self._dpi_px(1040)\n        ).pack(fill=\"x\", padx=12, pady=(0, 8))\n\n        uninst_actions = [\n            (\"Scan Programs\", C[\"btn_info\"], self._scan_installed),\n            (\"Safe Uninstall\", C[\"btn_warn\"], self._uninst_standard),\n            (\"Force Uninstall\", C[\"btn_danger\"], self._uninst_force),\n            (\"Deep Leftover Scan\", C[\"btn_info\"], self._scan_leftovers),\n            (\"Clean Reviewed\", C[\"btn_danger\"], self._clean_leftovers),\n            (\"Unlock Locked File\", C[\"btn_chip\"], self._unlock_file_dialog),\n            (\"Deep Folder Cleanup\", C[\"btn_danger\"], self._deep_cleanup_folder_dialog),\n        ]\n\n        sf = tk.Frame(frame, bg=C[\"bg\"])\n        sf.pack(fill=\"x\", padx=16, pady=(6,2))\n        tk.Label(sf, text=\"\ud83d\udd0d Search:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"]).pack(side=\"left\")\n        self.uninst_search = tk.Entry(sf, width=30, font=FONTS[\"body\"], bg=C[\"card\"],\n                                      fg=C[\"text\"], insertbackground=C[\"text\"], relief=\"flat\", bd=4)\n        self.uninst_search.pack(side=\"left\", padx=8)\n        self.uninst_search.bind(\"\", self._filter_uninst)\n        self.uninst_count_lbl = tk.Label(sf, text=\"\", font=FONTS[\"small\"], fg=C[\"accent\"], bg=C[\"bg\"])\n        self.uninst_count_lbl.pack(side=\"left\", padx=12)\n        self.uninst_pause_btn = self._btn(sf, \"Pause Scan\", C[\"btn_chip\"], self._pause_resume_uninst_scan)\n        self.uninst_pause_btn.pack(side=\"right\", padx=4)\n        self._btn(sf, \"Stop Scan\", C[\"btn_danger\"], self._stop_uninst_scan).pack(side=\"right\", padx=4)\n\n        self.uninst_progress_var = tk.DoubleVar(value=0)\n        ttk.Progressbar(frame, variable=self.uninst_progress_var, maximum=100, mode=\"determinate\").pack(\n            fill=\"x\", padx=16, pady=(2, 4)\n        )\n        self.uninst_timing_lbl = tk.Label(frame, text=\"Elapsed: 00:00 | Left: -- | Total: --\",\n                                          font=FONTS[\"small\"], fg=C[\"text_dim\"],\n                                          bg=C[\"bg\"], anchor=\"w\")\n        self.uninst_timing_lbl.pack(fill=\"x\", padx=16, pady=(0, 4))\n\n        summary = tk.Frame(frame, bg=C[\"bg\"])\n        summary.pack(fill=\"x\", padx=16, pady=(0, 4))\n        self.uninst_summary_vars = {}\n        for key, label, color in [\n            (\"programs\", \"Programs\", C[\"accent\"]),\n            (\"leftovers\", \"Leftovers\", C[\"warning\"]),\n            (\"risky\", \"Risky\", C[\"accent3\"]),\n            (\"safe\", \"Safe\", C[\"accent2\"]),\n        ]:\n            box = tk.Frame(summary, bg=C[\"card\"], highlightbackground=C[\"border\"], highlightthickness=1)\n            box.pack(side=\"left\", padx=(0, 6), fill=\"x\", expand=True)\n            tk.Label(box, text=label, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=8, pady=(5, 0))\n            var = tk.StringVar(value=\"0\")\n            self.uninst_summary_vars[key] = var\n            tk.Label(box, textvariable=var, font=FONTS[\"heading\"], fg=color, bg=C[\"card\"]).pack(anchor=\"w\", padx=8, pady=(0, 5))\n\n        # \u2500\u2500 Paned layout \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        paned = tk.Frame(frame, bg=C[\"bg\"])\n        paned.pack(fill=\"both\", expand=True, padx=16, pady=6)\n        paned.columnconfigure(0, weight=5)\n        paned.columnconfigure(1, weight=3)\n        paned.rowconfigure(0, weight=1)\n\n        # Left: program list\n        left = tk.Frame(paned, bg=C[\"card\"])\n        left.grid(row=0, column=0, sticky=\"nsew\", padx=(0,6))\n        left.rowconfigure(1, weight=1)\n        left.columnconfigure(0, weight=1)\n        tk.Label(left, text=\"  Installed Programs\", font=FONTS[\"subhead\"],\n                 fg=C[\"accent\"], bg=C[\"card\"]).grid(row=0, column=0, columnspan=3, sticky=\"w\", pady=(8,4), padx=8)\n        cols = (\"Software\",\"Version\",\"Size\",\"Date\",\"Publisher\")\n        self.uninst_tree = ttk.Treeview(left, columns=cols, show=\"headings\",\n                                        height=24, style=\"Custom.Treeview\")\n        for col, w in zip(cols, [260, 90, 80, 90, 170]):\n            self.uninst_tree.heading(col, text=col,\n                                     command=lambda c=col: self._sort_uninst(c))\n            self.uninst_tree.column(col, width=w, anchor=\"w\")\n        vsb = ttk.Scrollbar(left, orient=\"vertical\", command=self.uninst_tree.yview)\n        hsb = ttk.Scrollbar(left, orient=\"horizontal\", command=self.uninst_tree.xview)\n        self.uninst_tree.configure(yscrollcommand=vsb.set, xscrollcommand=hsb.set)\n        self.uninst_tree.grid(row=1, column=0, sticky=\"nsew\", padx=(8,0), pady=(0,0))\n        vsb.grid(row=1, column=1, sticky=\"ns\", pady=(0,0), padx=(0,8))\n        hsb.grid(row=2, column=0, sticky=\"ew\", padx=(8,0), pady=(0,8))\n        self._bind_tree_responsive_columns(self.uninst_tree, [\n            (\"Software\", 280, 5), (\"Version\", 90, 1), (\"Size\", 80, 1), (\"Date\", 90, 1), (\"Publisher\", 180, 3)\n        ])\n        self.uninst_tree.bind(\"&lt;&gt;\", self._on_uninst_select)\n\n        # Right: detail + leftover panel\n        right = tk.Frame(paned, bg=C[\"card\"])\n        right.grid(row=0, column=1, sticky=\"nsew\", padx=(6,0))\n        right.rowconfigure(3, weight=1)\n        right.rowconfigure(5, weight=2)\n        right.columnconfigure(0, weight=1)\n\n        tk.Label(right, text=\"  Actions\", font=FONTS[\"subhead\"],\n                 fg=C[\"accent\"], bg=C[\"card\"]).grid(row=0, column=0, columnspan=2,\n                 sticky=\"w\", padx=8, pady=(8,2))\n        action_box = tk.Frame(right, bg=C[\"card\"])\n        action_box.grid(row=1, column=0, columnspan=2, sticky=\"ew\", padx=4, pady=(0,4))\n        self._compact_action_grid(action_box, uninst_actions, cols=2)\n\n        tk.Label(right, text=\"  App Details\", font=FONTS[\"subhead\"],\n                 fg=C[\"accent\"], bg=C[\"card\"]).grid(row=2, column=0, columnspan=2,\n                 sticky=\"w\", padx=8, pady=(8,4))\n        self.uninst_detail = scrolledtext.ScrolledText(\n            right, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"],\n            height=5, bd=0, relief=\"flat\", state=\"disabled\", wrap=\"word\")\n        self.uninst_detail.grid(row=3, column=0, columnspan=2,\n                                sticky=\"nsew\", padx=8, pady=(0,4))\n\n        tk.Label(right, text=\"  Leftover Files / Registry / Folders\",\n                 font=FONTS[\"subhead\"], fg=C[\"warning\"], bg=C[\"card\"]).grid(\n                 row=4, column=0, sticky=\"w\", padx=8, pady=(4,4))\n        self.leftover_tree = ttk.Treeview(right, columns=(\"Type\",\"Risk\",\"Confidence\",\"Path\"),\n                                          show=\"headings\", height=10,\n                                          style=\"Custom.Treeview\")\n        self.leftover_tree.heading(\"Type\", text=\"Type\")\n        self.leftover_tree.column(\"Type\", width=80, anchor=\"center\")\n        self.leftover_tree.heading(\"Risk\", text=\"Risk\")\n        self.leftover_tree.column(\"Risk\", width=70, anchor=\"center\")\n        self.leftover_tree.heading(\"Confidence\", text=\"Score\")\n        self.leftover_tree.column(\"Confidence\", width=70, anchor=\"center\")\n        self.leftover_tree.heading(\"Path\", text=\"Path / Registry Key\")\n        self.leftover_tree.column(\"Path\", width=330, anchor=\"w\")\n        self.leftover_tree.tag_configure(\"file\", foreground=C[\"warning\"])\n        self.leftover_tree.tag_configure(\"reg\",  foreground=C[\"accent3\"])\n        self.leftover_tree.tag_configure(\"safe\", foreground=C[\"success\"])\n        self.leftover_tree.tag_configure(\"risky\", foreground=C[\"accent3\"])\n        lvsb = ttk.Scrollbar(right, orient=\"vertical\", command=self.leftover_tree.yview)\n        self.leftover_tree.configure(yscrollcommand=lvsb.set)\n        self.leftover_tree.grid(row=5, column=0, sticky=\"nsew\", padx=(8,0), pady=(0,8))\n        lvsb.grid(row=5, column=1, sticky=\"ns\", pady=(0,8), padx=(0,4))\n        self._bind_tree_responsive_columns(self.leftover_tree, [\n            (\"Type\", 80, 0), (\"Risk\", 70, 0), (\"Confidence\", 70, 0), (\"Path\", 330, 4)\n        ])\n\n        self.uninst_status = tk.Label(frame, text=\"  Ready \u2014 Scan programs to begin\",\n                                      font=FONTS[\"small\"], fg=C[\"accent2\"],\n                                      bg=C[\"bg\"], anchor=\"w\")\n        self.uninst_status.pack(fill=\"x\", padx=16, pady=(0,6))\n\n        # Internal state\n        self.uninst_data     = []\n        self.uninst_filtered = []\n        self.leftover_items  = []\n        self.uninst_sort_col = \"\"\n        self.uninst_sort_rev = False\n        self._uninst_cancel_flag = False\n        self._uninst_pause_flag = False\n        self._set_uninst_progress(0, \"Ready - Scan Programs to begin\", C[\"accent2\"])\n        return frame\n\n    def _build_event_viewer(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udcdc Event Viewer (Simple Explain)\",\n                             \"System/Application errors ka simple reason + solution\")\n\n        top = tk.Frame(frame, bg=C[\"panel\"])\n        top.pack(fill=\"x\", padx=16, pady=(8, 6))\n\n        tk.Label(top, text=\"Log:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"left\", padx=(8, 4))\n        self.ev_log_var = tk.StringVar(value=\"System\")\n        self.ev_log_combo = ttk.Combobox(top, textvariable=self.ev_log_var, values=[\"System\", \"Application\"], width=12, state=\"readonly\")\n        self.ev_log_combo.pack(side=\"left\", padx=4, pady=8)\n\n        tk.Label(top, text=\"Level:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"left\", padx=(10, 4))\n        self.ev_level_var = tk.StringVar(value=\"Error,Critical\")\n        self.ev_level_combo = ttk.Combobox(top, textvariable=self.ev_level_var, values=[\"Error,Critical\", \"Error\", \"Warning,Error,Critical\"], width=20, state=\"readonly\")\n        self.ev_level_combo.pack(side=\"left\", padx=4, pady=8)\n\n        tk.Label(top, text=\"Count:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"left\", padx=(10, 4))\n        self.ev_count_entry = tk.Entry(top, width=6, font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"])\n        self.ev_count_entry.insert(0, \"80\")\n        self.ev_count_entry.pack(side=\"left\", padx=4, pady=8)\n\n        self._btn(top, \"\ud83d\udd04 Fetch Events\", C[\"btn_info\"], self._eventviewer_fetch).pack(side=\"left\", padx=(12, 4), pady=8)\n        self._btn(top, \"\ud83e\udde0 Explain Selected\", C[\"btn_warn\"], self._eventviewer_explain_selected).pack(side=\"left\", padx=4, pady=8)\n\n        body = tk.Frame(frame, bg=C[\"bg\"])\n        body.pack(fill=\"both\", expand=True, padx=16, pady=(0, 8))\n        body.columnconfigure(0, weight=3)\n        body.columnconfigure(1, weight=2)\n        body.rowconfigure(0, weight=1)\n\n        left = tk.Frame(body, bg=C[\"card\"])\n        left.grid(row=0, column=0, sticky=\"nsew\", padx=(0, 6))\n        tk.Label(left, text=\"  Recent Windows Events\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8, 4), padx=8)\n\n        cols = (\"Time\", \"Source\", \"EventID\", \"Level\", \"Message\")\n        self.ev_tree = ttk.Treeview(left, columns=cols, show=\"headings\", height=18, style=\"Custom.Treeview\")\n        widths = [160, 180, 80, 90, 600]\n        for col, w in zip(cols, widths):\n            self.ev_tree.heading(col, text=col)\n            self.ev_tree.column(col, width=w, anchor=\"w\")\n        evsb = ttk.Scrollbar(left, orient=\"vertical\", command=self.ev_tree.yview)\n        self.ev_tree.configure(yscrollcommand=evsb.set)\n        self.ev_tree.pack(side=\"left\", fill=\"both\", expand=True, padx=(8, 0), pady=(0, 8))\n        evsb.pack(side=\"right\", fill=\"y\", pady=(0, 8), padx=(0, 4))\n        self.ev_tree.bind(\"&lt;&gt;\", self._eventviewer_explain_selected)\n\n        right = tk.Frame(body, bg=C[\"card\"])\n        right.grid(row=0, column=1, sticky=\"nsew\", padx=(6, 0))\n        tk.Label(right, text=\"  Simple Explanation\", font=FONTS[\"subhead\"], fg=C[\"warning\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8, 4), padx=8)\n        self.ev_explain = scrolledtext.ScrolledText(\n            right, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"],\n            height=22, bd=0, relief=\"flat\", state=\"disabled\", wrap=\"word\"\n        )\n        self.ev_explain.pack(fill=\"both\", expand=True, padx=8, pady=(0, 8))\n\n        self.ev_status = tk.Label(frame, text=\"  Ready - Fetch Events dabao\", font=FONTS[\"small\"],\n                                  fg=C[\"accent2\"], bg=C[\"bg\"], anchor=\"w\")\n        self.ev_status.pack(fill=\"x\", padx=16, pady=(0, 6))\n        self.ev_items = []\n        return frame\n\n    def _eventviewer_fetch(self):\n        log_name = (self.ev_log_var.get() if hasattr(self, \"ev_log_var\") else \"System\").strip() or \"System\"\n        level_csv = (self.ev_level_var.get() if hasattr(self, \"ev_level_var\") else \"Error,Critical\").strip()\n        count = 80\n        try:\n            count = max(10, min(300, int((self.ev_count_entry.get() or \"80\").strip())))\n        except Exception:\n            count = 80\n        self.ev_status.config(text=f\"  Fetching {log_name} events...\", fg=C[\"accent4\"])\n        self._launch_job(\"eventviewer_fetch\", self._do_eventviewer_fetch, log_name, level_csv, count)\n\n    def _do_eventviewer_fetch(self, log_name, level_csv, count):\n        levels = [x.strip().lower() for x in str(level_csv).split(\",\") if x.strip()]\n        level_map = {\"critical\": 1, \"error\": 2, \"warning\": 3, \"information\": 4, \"verbose\": 5}\n        lvl_ids = [str(level_map[x]) for x in levels if x in level_map]\n        if not lvl_ids:\n            lvl_ids = [\"1\", \"2\"]\n        level_expr = \",\".join(lvl_ids)\n\n        ps_script = (\n            f\"$f=@{{LogName='{log_name}'; Level={level_expr}}}; \"\n            f\"Get-WinEvent -FilterHashtable $f -MaxEvents {int(count)} -ErrorAction SilentlyContinue | \"\n            f\"Select-Object TimeCreated,ProviderName,Id,LevelDisplayName,Message | ConvertTo-Json -Depth 4\"\n        )\n        cmd = f'powershell -NoProfile -ExecutionPolicy Bypass -Command \"{ps_script}\"'\n        out, rc = self._run_cmd(cmd, timeout=60)\n        if rc != 0 or not out.strip():\n            self.after(0, lambda: self.ev_status.config(text=\"  Event fetch failed. Run as Admin and retry.\", fg=C[\"error\"]))\n            return\n        try:\n            data = json.loads(out)\n            if isinstance(data, dict):\n                data = [data]\n            if not isinstance(data, list):\n                data = []\n        except Exception:\n            data = []\n        self.ev_items = data\n        self.after(0, self._populate_eventviewer_tree)\n\n    def _populate_eventviewer_tree(self):\n        self.ev_tree.delete(*self.ev_tree.get_children())\n        for ev in self.ev_items:\n            try:\n                t = str(ev.get(\"TimeCreated\", \"\"))[:19].replace(\"T\", \" \")\n                src = str(ev.get(\"ProviderName\", \"\") or \"\")\n                eid = str(ev.get(\"Id\", \"\") or \"\")\n                lvl = str(ev.get(\"LevelDisplayName\", \"\") or \"\")\n                msg = \" \".join(str(ev.get(\"Message\", \"\") or \"\").split())\n                if len(msg) &gt; 220:\n                    msg = msg[:220] + \"...\"\n                self.ev_tree.insert(\"\", \"end\", values=(t, src, eid, lvl, msg))\n            except Exception:\n                pass\n        c = len(self.ev_items)\n        color = C[\"warning\"] if c else C[\"success\"]\n        self.ev_status.config(text=f\"  Loaded {c} event(s). Select one for simple explanation.\", fg=color)\n        if c:\n            first = self.ev_tree.get_children()\n            if first:\n                self.ev_tree.selection_set(first[0])\n                self._eventviewer_explain_selected()\n\n    def _eventviewer_explain_selected(self, event=None):\n        if not hasattr(self, \"ev_tree\"):\n            return\n        sel = self.ev_tree.selection()\n        if not sel:\n            return\n        idx = self.ev_tree.index(sel[0])\n        if idx &lt; 0 or idx &gt;= len(self.ev_items):\n            return\n        ev = self.ev_items[idx]\n        text = self._eventviewer_make_simple_explain(ev)\n        self.ev_explain.config(state=\"normal\")\n        self.ev_explain.delete(\"1.0\", \"end\")\n        self.ev_explain.insert(\"1.0\", text)\n        self.ev_explain.config(state=\"disabled\")\n\n    def _eventviewer_make_simple_explain(self, ev):\n        eid = str(ev.get(\"Id\", \"\") or \"\")\n        source = str(ev.get(\"ProviderName\", \"\") or \"Unknown\")\n        level = str(ev.get(\"LevelDisplayName\", \"\") or \"Unknown\")\n        t = str(ev.get(\"TimeCreated\", \"\") or \"\").replace(\"T\", \" \")\n        msg_full = str(ev.get(\"Message\", \"\") or \"\").strip()\n        msg_low = msg_full.lower()\n\n        reason = \"System me operation fail hua ya expected service response nahi mili.\"\n        solution = \"System restart karo, latest updates lagao, phir issue ko dubara reproduce karke check karo.\"\n\n        known = {\n            (\"Kernel-Power\", \"41\"): (\n                \"PC proper shutdown ke bina restart hua (power cut, crash, force restart).\",\n                \"Power cable/SMPS check karo, overheating test karo, RAM test chalao, aur sudden power loss avoid karo.\"\n            ),\n            (\"Microsoft-Windows-Kernel-Power\", \"41\"): (\n                \"PC proper shutdown ke bina restart hua. Ye BSOD, power cut, overheating ya force shutdown se aa sakta hai.\",\n                \"BugCheck/WHEA/Disk events ke saath compare karo. PSU, temperature, RAM, driver aur disk health check karo.\"\n            ),\n            (\"Microsoft-Windows-WER-SystemErrorReporting\", \"1001\"): (\n                \"Windows ne BugCheck/Blue Screen report log kiya.\",\n                \"Stop code note karo, C:\\\\Windows\\\\Minidump file analyze karo, phir culprit driver/hardware fix karo.\"\n            ),\n            (\"Microsoft-Windows-WHEA-Logger\", \"17\"): (\n                \"Corrected hardware error detect hua; system bach gaya par hardware path warning de raha hai.\",\n                \"BIOS/chipset update, overclock off, RAM/SSD/GPU/PCIe health aur temperature check karo.\"\n            ),\n            (\"Microsoft-Windows-WHEA-Logger\", \"18\"): (\n                \"Fatal hardware error detect hua; ye BSOD ka strong hardware clue hai.\",\n                \"RAM test, CPU/GPU temperature, PSU, SSD SMART, BIOS/chipset update aur overclock reset karo.\"\n            ),\n            (\"Microsoft-Windows-WHEA-Logger\", \"19\"): (\n                \"Corrected hardware error repeat ho sakta hai.\",\n                \"Event details me component dekho, phir related driver/firmware/hardware check karo.\"\n            ),\n            (\"volmgr\", \"161\"): (\n                \"Crash dump create nahi ho paya, isliye BSOD proof file missing ho sakti hai.\",\n                \"C: drive free space, pagefile aur CrashControl minidump settings enable karo.\"\n            ),\n            (\"Display\", \"4101\"): (\n                \"Display/GPU driver ne respond karna band kiya aur recover hua.\",\n                \"GPU driver clean reinstall/rollback, GPU temperature, power cable/PSU aur hardware acceleration test karo.\"\n            ),\n            (\"Application Error\", \"1000\"): (\n                \"Kisi application/module ne crash kiya.\",\n                \"Faulting application/module name dekho. Agar rundll32.exe hai to loaded DLL/app culprit hota hai; us app/driver ko repair karo.\"\n            ),\n            (\"SideBySide\", \"33\"): (\n                \"App runtime/VC++ dependency mismatch ya missing manifest issue.\",\n                \"Affected app reinstall/repair karo aur Microsoft Visual C++ Redistributables repair/install karo.\"\n            ),\n            (\"Service Control Manager\", \"7000\"): (\n                \"Koi service startup pe start nahi ho payi.\",\n                \"Services menu me jaake service dependencies check karo, startup type sahi set karo, phir reboot karo.\"\n            ),\n            (\"Service Control Manager\", \"7001\"): (\n                \"Service dependency chain me issue hai, required service pehle start nahi hui.\",\n                \"Related dependent services ko Automatic pe set karo aur start order verify karo.\"\n            ),\n            (\"Disk\", \"7\"): (\n                \"Disk read/write hardware level problem detect hui.\",\n                \"SMART scan chalao, cable/port check karo, data backup lo, aur disk health verify karo.\"\n            ),\n            (\"Ntfs\", \"55\"): (\n                \"File system me corruption detect hua.\",\n                \"Admin CMD me `chkdsk /f` run karo (boot drive ke liye restart required).\"\n            ),\n            (\"DistributedCOM\", \"10016\"): (\n                \"DCOM permission mismatch log hua; mostly harmless hota hai.\",\n                \"Agar app crash nahi ho rahi to ignore kar sakte ho; otherwise specific app permissions tune karo.\"\n            ),\n        }\n        if (source, eid) in known:\n            reason, solution = known[(source, eid)]\n        else:\n            if \"access is denied\" in msg_low or \"access denied\" in msg_low:\n                reason = \"Permission issue ki wajah se operation block hua.\"\n                solution = \"Tool/Admin rights ke saath run karo, folder/service permissions verify karo.\"\n            elif \"bugcheck\" in msg_low or \"blue screen\" in msg_low:\n                reason = \"Windows kernel crash/BSOD report log hua.\"\n                solution = \"BSoD Deep Diagnose run karo, stop code aur minidump check karo, phir driver/RAM/disk/GPU cause fix karo.\"\n            elif \"rundll32\" in msg_low or \"rundell32\" in msg_low:\n                reason = \"rundll32.exe se DLL load/crash issue lag raha hai. Real Windows file rundll32.exe hota hai, rundell32.dll nahi.\"\n                solution = \"Rundll32 Error Check run karo; startup/task me missing DLL entry disable karo, affected app reinstall/uninstall karo, SFC/DISM aur malware scan chalao.\"\n            elif \"specified module could not be found\" in msg_low or \"module could not be found\" in msg_low:\n                reason = \"Koi startup/app ek DLL load kar raha tha jo ab missing hai.\"\n                solution = \"Startup Apps, Task Scheduler aur registry Run entries me missing DLL reference dhoondh kar disable/remove karo ya related app reinstall karo.\"\n            elif \"side-by-side\" in msg_low or \"activation context\" in msg_low:\n                reason = \"App runtime/VC++ dependency mismatch detect hua.\"\n                solution = \"Affected app repair/reinstall karo aur Microsoft Visual C++ Redistributables repair/install karo.\"\n            elif \"whea\" in msg_low or \"hardware error\" in msg_low:\n                reason = \"Hardware layer se error signal mila.\"\n                solution = \"Temperature, RAM, SSD SMART, GPU/PCIe, PSU, BIOS/chipset driver aur overclock settings check karo.\"\n            elif \"timeout\" in msg_low or \"timed out\" in msg_low:\n                reason = \"Operation ko required response time me reply nahi mila.\"\n                solution = \"Heavy load kam karo, related service restart karo, network/disk responsiveness check karo.\"\n            elif \"driver\" in msg_low:\n                reason = \"Driver related compatibility ya corruption issue lag raha hai.\"\n                solution = \"Driver Checker se current driver version check karke stable version reinstall/update karo.\"\n            elif \"dns\" in msg_low or \"network\" in msg_low:\n                reason = \"Network stack ya DNS resolution me issue detect hua.\"\n                solution = \"Network Optimizer me DNS flush + TCP reset chalao, phir reconnect test karo.\"\n\n        if len(msg_full) &gt; 1200:\n            msg_full = msg_full[:1200] + \"\\n... (message truncated)\"\n\n        return (\n            f\"Event Time: {t}\\n\"\n            f\"Source: {source}\\n\"\n            f\"Error Code / Event ID: {eid}\\n\"\n            f\"Level: {level}\\n\\n\"\n            f\"1) Ye error code kya hai?\\n\"\n            f\"   Event ID {eid} ({source}) system ka diagnostic code hai jo issue category batata hai.\\n\\n\"\n            f\"2) Ye kyun aaya?\\n\"\n            f\"   {reason}\\n\\n\"\n            f\"3) Iska solution kya ho sakta hai?\\n\"\n            f\"   {solution}\\n\\n\"\n            f\"Original Windows Message:\\n{msg_full or 'N/A'}\\n\"\n        )\n\n    # \u2500\u2500 Scan all installed programs \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _threadsafe_confirm(self, title, message):\n        text = str(message)\n        if len(text) &gt; 5000:\n            text = text[:5000] + \"\\n\\n...list lambi hai, baaki items log me dekhein.\"\n        if threading.current_thread() is threading.main_thread():\n            return messagebox.askyesno(title, text)\n        done = threading.Event()\n        result = {\"yes\": False}\n\n        def _ask():\n            try:\n                result[\"yes\"] = messagebox.askyesno(title, text)\n            finally:\n                done.set()\n\n        self.after(0, _ask)\n        done.wait()\n        return result[\"yes\"]\n\n    def _tool_log(self, msg, level=\"INFO\"):\n        self.after(0, lambda: self._log(msg, level))\n\n    def _unlock_file_dialog(self):\n        path = filedialog.askopenfilename(title=\"Locked file select karo\")\n        if not path:\n            return\n        self.uninst_status.config(text=\"Locked file scan chal raha hai...\", fg=C[\"accent4\"])\n\n        def _run():\n            result = unlock_file_if_locked(\n                path,\n                confirm_callback=self._threadsafe_confirm,\n                log_callback=lambda msg: self._tool_log(msg, \"INFO\"),\n            )\n\n            def _finish():\n                color = C[\"success\"] if result.get(\"ok\") else C[\"warning\"]\n                self.uninst_status.config(text=result.get(\"message\", \"Unlock complete\"), fg=color)\n                details = result.get(\"message\", \"\")\n                if result.get(\"terminated\"):\n                    details += \"\\n\\nTerminated PID(s): \" + \", \".join(map(str, result[\"terminated\"]))\n                if result.get(\"errors\"):\n                    details += \"\\n\\nErrors:\\n\" + \"\\n\".join(result[\"errors\"])\n                if result.get(\"ok\"):\n                    messagebox.showinfo(\"Unlock Result\", details)\n                else:\n                    messagebox.showwarning(\"Unlock Result\", details)\n\n            self.after(0, _finish)\n\n        self._launch_job(\"unlock_app\", _run)\n\n    def _deep_cleanup_folder_dialog(self):\n        folder = filedialog.askdirectory(title=\"Program folder select karo\")\n        if not folder:\n            return\n        self.uninst_status.config(text=\"Deep cleanup scan chal raha hai...\", fg=C[\"accent4\"])\n\n        def _run():\n            result = deep_cleanup_program(\n                folder,\n                confirm_callback=self._threadsafe_confirm,\n                log_callback=lambda msg: self._tool_log(msg, \"INFO\"),\n            )\n\n            def _finish():\n                color = C[\"success\"] if result.get(\"ok\") else C[\"warning\"]\n                self.uninst_status.config(text=result.get(\"message\", \"Deep cleanup complete\"), fg=color)\n                details = result.get(\"message\", \"\")\n                if result.get(\"ok\"):\n                    details += (\n                        f\"\\n\\nFiles: {result.get('files', 0)}\"\n                        f\"\\nFolders: {result.get('dirs', 0)}\"\n                        f\"\\nRegistry clues listed: {len(result.get('registry_entries', []))}\"\n                    )\n                    messagebox.showinfo(\"Deep Cleanup Result\", details)\n                    self._scan_installed()\n                else:\n                    if result.get(\"errors\"):\n                        details += \"\\n\\nErrors:\\n\" + \"\\n\".join(result[\"errors\"])\n                    messagebox.showwarning(\"Deep Cleanup Result\", details)\n\n            self.after(0, _finish)\n\n        self._launch_job(\"deep_cleanup\", _run)\n\n    def _scan_installed(self):\n        self.uninst_tree.delete(*self.uninst_tree.get_children())\n        self.uninst_data = []\n        self.uninst_filtered = []\n        self._uninst_cancel_flag = False\n        self._uninst_pause_flag = False\n        if hasattr(self, \"uninst_pause_btn\"):\n            self.uninst_pause_btn.config(text=\"Pause Scan\")\n        self._set_uninst_progress(5, \"Scanning installed programs...\", C[\"accent4\"])\n        self._audit_event(\"uninstall_scan_started\", {\"scope\": \"installed_programs\"})\n        self._launch_job(\"scan_installed_programs\", self._do_scan_installed)\n\n    def _do_scan_installed(self):\n        regs = [\n            (winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\"),\n            (winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\"),\n            (winreg.HKEY_CURRENT_USER,  r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\"),\n        ]\n        found = []\n        try:\n            for reg_idx, (hive, path) in enumerate(regs, start=1):\n                self._check_uninst_control()\n                self._set_uninst_progress(10 + reg_idx * 18, f\"Reading uninstall registry hive {reg_idx}/{len(regs)}...\", C[\"accent4\"])\n                try:\n                    key = winreg.OpenKey(hive, path, 0, winreg.KEY_READ)\n                    i = 0\n                    while True:\n                        self._check_uninst_control()\n                        try:\n                            sub_name = winreg.EnumKey(key, i); i += 1\n                            subkey = winreg.OpenKey(key, sub_name, 0, winreg.KEY_READ)\n                            name      = self._reg_read_str(subkey, \"DisplayName\")\n                            version   = self._reg_read_str(subkey, \"DisplayVersion\")\n                            size_kb   = self._reg_read_str(subkey, \"EstimatedSize\")\n                            date      = self._reg_read_str(subkey, \"InstallDate\")\n                            uninst_s  = self._reg_read_str(subkey, \"UninstallString\")\n                            quiet_s   = self._reg_read_str(subkey, \"QuietUninstallString\")\n                            publisher = self._reg_read_str(subkey, \"Publisher\")\n                            inst_loc  = self._reg_read_str(subkey, \"InstallLocation\")\n                            winreg.CloseKey(subkey)\n                            if not name: continue\n                            skip_words = [\"KB\",\"Security Update\",\"Hotfix\",\"Service Pack\",\"Update for\"]\n                            if any(x in name for x in skip_words): continue\n                            try: sz = int(size_kb)*1024 if size_kb and size_kb.isdigit() else 0\n                            except: sz = 0\n                            found.append({\n                                \"name\": name, \"version\": version, \"size\": sz,\n                                \"date\": date[:8] if date and len(date) &gt;= 8 else \"--\",\n                                \"publisher\": publisher, \"uninst\": uninst_s,\n                                \"quiet\": quiet_s, \"install_loc\": inst_loc,\n                                \"has_uninstall\": bool(uninst_s or quiet_s),\n                                \"reg_key\": path + \"\\\\\" + sub_name,\n                                \"reg_hive\": \"HKLM\" if hive == winreg.HKEY_LOCAL_MACHINE else \"HKCU\",\n                            })\n                        except OSError: break\n                    winreg.CloseKey(key)\n                except Exception:\n                    pass\n        except InterruptedError:\n            self._audit_event(\"uninstall_scan_cancelled\", {\"scope\": \"installed_programs\", \"found\": len(found)})\n            self._set_uninst_progress(0, \"Installed-program scan cancelled.\", C[\"warning\"])\n            return\n        found.sort(key=lambda x: x[\"name\"].lower())\n        self.uninst_data     = found\n        self.uninst_filtered = found[:]\n        self.after(0, self._populate_uninst_tree)\n        self._set_uninst_progress(100, f\"Found {len(found)} programs\", C[\"success\"])\n        self._audit_event(\"uninstall_scan_finished\", {\"scope\": \"installed_programs\", \"count\": len(found)})\n        self.after(0, lambda: self._set_status(f\"Found {len(found)} installed programs\", C[\"success\"]))\n\n    def _populate_uninst_tree(self):\n        self.uninst_tree.delete(*self.uninst_tree.get_children())\n        for item in self.uninst_filtered:\n            self.uninst_tree.insert(\"\", \"end\", values=(\n                item[\"name\"], item[\"version\"],\n                self._fmt_size(item[\"size\"]), item[\"date\"], item[\"publisher\"]))\n        self.uninst_count_lbl.config(text=f\"{len(self.uninst_filtered)} programs\")\n        if hasattr(self, \"uninst_summary_vars\"):\n            self.uninst_summary_vars[\"programs\"].set(str(len(self.uninst_filtered)))\n\n    def _filter_uninst(self, event=None):\n        q = self.uninst_search.get().strip().lower()\n        self.uninst_filtered = (\n            self.uninst_data[:] if not q else\n            [x for x in self.uninst_data\n             if q in x[\"name\"].lower() or q in x[\"publisher\"].lower()])\n        self._populate_uninst_tree()\n\n    def _sort_uninst(self, col):\n        col_map = {\"Software\":\"name\",\"Version\":\"version\",\"Size\":\"size\",\"Date\":\"date\",\"Publisher\":\"publisher\"}\n        key = col_map.get(col, \"name\")\n        self.uninst_sort_rev = (not self.uninst_sort_rev) if self.uninst_sort_col == col else False\n        self.uninst_sort_col = col\n        self.uninst_filtered.sort(key=lambda x: str(x.get(key,\"\")), reverse=self.uninst_sort_rev)\n        self._populate_uninst_tree()\n\n    def _on_uninst_select(self, event=None):\n        sel = self.uninst_tree.selection()\n        if not sel: return\n        idx = self.uninst_tree.index(sel[0])\n        if idx &gt;= len(self.uninst_filtered): return\n        it = self.uninst_filtered[idx]\n        if not it.get(\"has_uninstall\"):\n            self.uninst_status.config(\n                text=\"Is program ka uninstall command nahi mila. \"\n                     \"Force Uninstall ya manual removal use karo.\",\n                fg=C[\"warning\"])\n        detail = (\n            f\"Name         : {it['name']}\\n\"\n            f\"Version      : {it['version'] or 'N/A'}\\n\"\n            f\"Publisher    : {it['publisher'] or 'N/A'}\\n\"\n            f\"Size         : {self._fmt_size(it['size'])}\\n\"\n            f\"Install Date : {it['date']}\\n\"\n            f\"Install Path : {it['install_loc'] or 'N/A'}\\n\"\n            f\"Registry Key : {it['reg_hive']}\\\\{it['reg_key']}\\n\"\n            f\"Has Uninstall: {'Yes' if it.get('has_uninstall') else 'No \u2014 use Force/manual'}\\n\"\n            f\"Uninstall    : {(it['uninst'] or 'N/A')[:100]}\\n\"\n            f\"Quiet Uninst : {(it['quiet'] or 'N/A')[:100]}\"\n        )\n        self.uninst_detail.config(state=\"normal\")\n        self.uninst_detail.delete(\"1.0\",\"end\")\n        self.uninst_detail.insert(\"1.0\", detail)\n        self.uninst_detail.config(state=\"disabled\")\n\n    def _get_sel_uninst(self):\n        items = []\n        for iid in self.uninst_tree.selection():\n            idx = self.uninst_tree.index(iid)\n            if idx &lt; len(self.uninst_filtered):\n                items.append(self.uninst_filtered[idx])\n        return items\n\n    def _uninst_is_protected(self, item):\n        \"\"\"\n        Publisher allowlist / protection guard.\n        Blocks uninstall for drivers/security/OS components by default.\n        \"\"\"\n        pub = (item.get(\"publisher\") or \"\").strip().lower()\n        name = (item.get(\"name\") or \"\").strip().lower()\n        protected_publishers = {\n            \"microsoft\", \"intel\", \"nvidia\", \"advanced micro devices\", \"amd\", \"realtek\",\n            \"qualcomm\", \"broadcom\", \"hewlett-packard\", \"hp\", \"dell\", \"lenovo\", \"asus\",\n            \"acer\", \"canon\", \"epson\", \"brother\", \"samsung\",\n        }\n        protected_keywords = {\n            \"driver\", \"chipset\", \"bluetooth\", \"wifi\", \"wireless\", \"lan\", \"ethernet\",\n            \"graphics\", \"display\", \"audio\", \"realtek\", \"nvidia\", \"intel\", \"amd\",\n            \"security update\", \"visual c++\", \"redistributable\", \"runtime\",\n        }\n        if any(p in pub for p in protected_publishers) or any(k in name for k in protected_keywords):\n            return True, f\"Protected publisher/app: {item.get('publisher') or 'N/A'}\"\n        return False, \"\"\n\n    def _uninst_verify_removed(self, item):\n        try:\n            hive = item.get(\"reg_hive\")\n            key_path = item.get(\"reg_key\")\n            if not hive or not key_path:\n                return True\n            # reg_hive stored as string in item; map it\n            hive_obj = winreg.HKEY_LOCAL_MACHINE if \"HKEY_LOCAL_MACHINE\" in hive or hive == \"HKLM\" else winreg.HKEY_CURRENT_USER\n            try:\n                k = winreg.OpenKey(hive_obj, key_path, 0, winreg.KEY_READ)\n                winreg.CloseKey(k)\n                return False\n            except Exception:\n                return True\n        except Exception:\n            return True\n\n    # \u2500\u2500 Standard Uninstall \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _uninst_standard(self):\n        items = self._get_sel_uninst()\n        if not items:\n            messagebox.showinfo(\"No Selection\",\"Select programs to uninstall.\"); return\n        no_cmd = [it for it in items if not it.get(\"has_uninstall\")]\n        if no_cmd:\n            self.uninst_status.config(\n                text=\"Is program ka uninstall command nahi mila. \"\n                     \"Force Uninstall ya manual removal use karo.\",\n                fg=C[\"warning\"])\n            messagebox.showwarning(\n                \"No Uninstall Command\",\n                \"In programs ke paas official uninstall command nahi hai:\\n\\n\"\n                + \"\\n\".join(x[\"name\"] for x in no_cmd[:12])\n                + (\"\\n...\" if len(no_cmd) &gt; 12 else \"\")\n                + \"\\n\\nSafe Uninstall skip hoga. Force Uninstall ya manual removal try karo.\")\n            items = [it for it in items if it.get(\"has_uninstall\")]\n            if not items:\n                return\n        protected = []\n        safe_items = []\n        for it in items:\n            ok, reason = self._uninst_is_protected(it)\n            if ok:\n                protected.append(f\"{it['name']} ({reason})\")\n            else:\n                safe_items.append(it)\n        if protected:\n            messagebox.showwarning(\"Protected Apps Skipped\",\n                                   \"Ye programs protected hain (drivers/system/security).\\n\"\n                                   \"Inko uninstall skip kiya ja raha hai:\\n\\n\" + \"\\n\".join(protected[:12]) +\n                                   (\"\\n...\" if len(protected) &gt; 12 else \"\"))\n        if not safe_items:\n            return\n        names = \"\\n\".join(it[\"name\"] for it in safe_items)\n        if not messagebox.askyesno(\"Safe Uninstall\",\n            f\"Run the official uninstaller for:\\n\\n{names}\\n\\n\"\n            \"A restore point is recommended. Silent mode is used only when the app provides it.\"): return\n        if not self._create_restore_point(\"Before Safe Uninstall\"):\n            return\n        self._audit_event(\"safe_uninstall_requested\", {\"items\": [x.get(\"name\") for x in safe_items]})\n        self._set_uninst_progress(10, f\"Safe uninstall queued for {len(safe_items)} program(s)\", C[\"accent4\"])\n        self._launch_job(\"safe_uninstall_batch\", self._run_uninst_batch_standard, safe_items)\n\n    def _run_uninst_batch_standard(self, items):\n        batch_leftovers = {}\n        total = len(items)\n        for idx, item in enumerate(items, start=1):\n            name = item[\"name\"]\n            self.after(0, lambda i=idx, t=total, n=name: self.uninst_status.config(\n                text=f\"[{i}/{t}] Uninstalling: {n}...\", fg=C[\"accent4\"]))\n            # Uninstall karo\n            cmd  = self._normalize_uninstall_command(item, quiet=True)\n            if cmd:\n                self._audit_event(\"safe_uninstall_command\", {\"name\": name, \"cmd\": cmd[:300]})\n                out, rc = self._run_cmd(cmd, timeout=300)\n                if rc == 0:\n                    self._log(f\"Uninstalled OK: {name}\", \"OK\")\n                else:\n                    self._log(f\"Uninstall issue: {name} (rc={rc})\", \"WARN\")\n            # \u2500\u2500 REVO STYLE: Uninstall ke turant baad leftover scan \u2500\u2500\u2500\u2500\u2500\n            self.after(0, lambda i=idx, t=total, n=name: self.uninst_status.config(\n                text=f\"[{i}/{t}] Scanning leftovers: {n}...\", fg=C[\"warning\"]))\n            try:\n                leftovers = self._scan_leftovers_for_item(item)\n            except InterruptedError:\n                self._set_uninst_progress(0, \"Safe uninstall leftover scan cancelled.\", C[\"warning\"])\n                self._audit_event(\"safe_uninstall_cancelled\", {\"completed\": idx - 1, \"total\": total})\n                break\n            batch_leftovers[name] = leftovers\n            # Leftover tree mein live update karo\n            if leftovers:\n                self.after(0, lambda n=name, lft=leftovers: self._append_batch_leftovers_to_tree(n, lft))\n            self.after(0, lambda i=idx, t=total, n=name, lc=len(leftovers): self.uninst_status.config(\n                text=f\"[{i}/{t}] Done: {n} | Leftovers: {lc}\",\n                fg=C[\"warning\"] if lc else C[\"success\"]))\n            self._set_uninst_progress(20 + (idx / max(total, 1)) * 75, f\"[{idx}/{total}] Safe uninstall scan complete: {name}\", C[\"warning\"] if leftovers else C[\"success\"])\n        self.after(500, self._scan_installed)\n        self.after(0, lambda: self._show_batch_leftover_preview(batch_leftovers))\n\n    def _append_batch_leftovers_to_tree(self, app_name, leftovers):\n        \"\"\"Batch uninstall ke baad leftovers turant right panel mein dikhao.\"\"\"\n        try:\n            # Section header\n            self.leftover_tree.insert(\"\", \"end\", values=(\"APP\", \"Info\", \"\", f\"--- {app_name} ---\"),\n                                      tags=(\"reg\",))\n            for item in leftovers:\n                ftype, path, risk, confidence, _meta = self._leftover_parts(item)\n                tag = \"risky\" if risk.lower() == \"risky\" else \"safe\"\n                self.leftover_tree.insert(\"\", \"end\", values=(ftype, risk, confidence, path), tags=(tag,))\n            # Auto-scroll\n            children = self.leftover_tree.get_children()\n            if children:\n                self.leftover_tree.see(children[-1])\n        except Exception:\n            pass\n\n    def _show_batch_leftover_preview(self, batch_leftovers):\n        apps_with_leftovers = {k: v for k, v in (batch_leftovers or {}).items() if v}\n        if not apps_with_leftovers:\n            self.uninst_status.config(text=\"Batch uninstall complete. No leftovers detected.\", fg=C[\"success\"])\n            messagebox.showinfo(\"Batch Uninstall Complete\",\n                                \"Selected programs uninstall ho gaye.\\n\\nNo obvious leftovers detected.\")\n            return\n\n        lines = []\n        for app_name, items in apps_with_leftovers.items():\n            risky = sum(1 for x in items if self._leftover_parts(x)[2].lower() == \"risky\")\n            lines.append(f\"* {app_name}  -&gt;  {len(items)} leftover(s), {risky} risky\")\n            for item in items[:8]:\n                ftype, path, risk, confidence, _meta = self._leftover_parts(item)\n                lines.append(f\"    [{ftype} | {risk} | {confidence}%] {path}\")\n            if len(items) &gt; 8:\n                lines.append(f\"    ... +{len(items)-8} more\")\n        preview = \"\\n\".join(lines)\n        if len(preview) &gt; 4500:\n            preview = preview[:4500] + \"\\n\\n...list truncated.\"\n\n        messagebox.showinfo(\n            \"Revo-style Leftovers Found\",\n            \"Uninstall ke baad ye leftovers detect hue:\\n\\n\"\n            f\"{preview}\\n\\n\"\n            \"Tip: Program select karke 'Scan Leftovers' aur phir 'Clean Leftovers' use karein.\"\n        )\n        self.uninst_status.config(\n            text=f\"Batch uninstall complete. Leftovers found in {len(apps_with_leftovers)} app(s).\",\n            fg=C[\"warning\"]\n        )\n\n    def _run_uninst_cmd(self, item, batch_leftovers=None):\n        name = item[\"name\"]\n        cmd  = self._normalize_uninstall_command(item, quiet=True)\n        if not cmd: return\n        self.after(0, lambda: self.uninst_status.config(\n            text=f\"Uninstalling: {name}...\", fg=C[\"accent4\"]))\n        self._log(f\"Uninstalling: {name}\", \"INFO\")\n        self._audit_event(\"safe_uninstall_command\", {\"name\": name, \"cmd\": cmd[:300]})\n        out, rc = self._run_cmd(cmd, timeout=300)\n        if rc == 0:\n            self._log(f\"Uninstalled OK: {name}\", \"OK\")\n            if not self._uninst_verify_removed(item):\n                self._log(f\"Verify WARN: {name} still present in registry list\", \"WARN\")\n            leftovers = self._scan_leftovers_for_item(item)\n            if batch_leftovers is not None:\n                batch_leftovers[name] = leftovers\n            self.after(0, lambda: self.uninst_status.config(\n                text=(f\"Uninstalled: {name} | Leftovers: {len(leftovers)}\"),\n                fg=(C[\"warning\"] if leftovers else C[\"success\"])))\n            if leftovers and batch_leftovers is None:\n                self.leftover_items = leftovers\n                self.after(0, self._populate_leftover_tree)\n                self.after(0, lambda: messagebox.showinfo(\n                    \"Leftovers Detected\",\n                    f\"{name} uninstall complete.\\n\\n\"\n                    f\"{len(leftovers)} leftover(s) detect hue.\\n\"\n                    \"Preview right panel me show ho raha hai.\"\n                ))\n            if batch_leftovers is None:\n                self.after(2000, self._scan_installed)\n        else:\n            self._log(f\"Uninstall issue: {name} (rc={rc})\", \"WARN\")\n            def ask_force():\n                if messagebox.askyesno(\"Uninstall Issue\",\n                    f\"Standard uninstall may have failed for:\\n{name}\\n\\n\"\n                    \"Run Force Remove to clean all leftovers?\"):\n                    self._launch_job(\"force_remove_item\", self._force_remove_item, item)\n            self.after(0, ask_force)\n\n    # \u2500\u2500 Force Remove (Revo-style deep clean) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _uninst_force(self):\n        items = self._get_sel_uninst()\n        if not items:\n            messagebox.showinfo(\"No Selection\",\"Select programs to force remove.\"); return\n        no_cmd = [it for it in items if not it.get(\"has_uninstall\")]\n        if no_cmd:\n            self.uninst_status.config(\n                text=\"Kuch programs mein uninstall command nahi \u2014 Force mode install path/registry se hataega.\",\n                fg=C[\"warning\"])\n            if not messagebox.askyesno(\n                \"No Uninstall Command\",\n                \"Ye programs mein official uninstall string nahi hai \u2014 Force mode registry/folders se hataega:\\n\\n\"\n                + \"\\n\".join(x[\"name\"] for x in no_cmd[:12])\n                + (\"\\n...\" if len(no_cmd) &gt; 12 else \"\")\n                + \"\\n\\nContinue with Force Uninstall?\"\n            ):\n                return\n        protected = []\n        safe_items = []\n        for it in items:\n            ok, reason = self._uninst_is_protected(it)\n            if ok:\n                protected.append(f\"{it['name']} ({reason})\")\n            else:\n                safe_items.append(it)\n        if protected:\n            messagebox.showwarning(\"Protected Apps Skipped\",\n                                   \"Force remove me bhi drivers/system apps skip kiye ja rahe hain:\\n\\n\" +\n                                   \"\\n\".join(protected[:12]) + (\"\\n...\" if len(protected) &gt; 12 else \"\"))\n        if not safe_items:\n            return\n        names = \"\\n\".join(it[\"name\"] for it in safe_items)\n        if not messagebox.askyesno(\"Force Uninstall\",\n            f\"Use Force Uninstall only for broken uninstallers or partially deleted apps.\\n\\n\"\n            f\"It will:\\n\"\n            f\" 1. Try the official uninstaller first\\n\"\n            f\" 2. Stop matching app processes\\n\"\n            f\" 3. Scan install folders, AppData, shortcuts, startup, services and registry\\n\"\n            f\" 4. Remove only matched leftovers after restore-point confirmation\\n\\n\"\n            f\"Programs:\\n{names}\\n\\nThis is permanent. Continue?\"\n        ): return\n        if not self._create_restore_point(f\"Force Remove: {safe_items[0]['name']}\"):\n            return\n        self._audit_event(\"force_uninstall_requested\", {\"items\": [x.get(\"name\") for x in safe_items]})\n        self._set_uninst_progress(5, f\"Force uninstall queued for {len(safe_items)} program(s)\", C[\"warning\"])\n        self._launch_job(\"force_uninstall\", self._run_force_remove_batch, safe_items)\n\n    def _run_force_remove_batch(self, items):\n        total = len(items)\n        try:\n            for idx, item in enumerate(items, start=1):\n                self._check_uninst_control()\n                self._set_uninst_progress(10 + ((idx - 1) / max(total, 1)) * 85, f\"[{idx}/{total}] Force uninstall: {item.get('name','')}\", C[\"warning\"])\n                self._force_remove_item(item, show_message=False)\n        except InterruptedError:\n            self._set_uninst_progress(0, \"Force uninstall cancelled at a safe checkpoint.\", C[\"warning\"])\n            self._audit_event(\"force_uninstall_cancelled\", {\"total\": total})\n            return\n        self._set_uninst_progress(100, \"Force uninstall batch complete. Restart is recommended.\", C[\"success\"])\n        self.after(0, lambda: messagebox.showinfo(\"Force Uninstall Complete\", \"Force uninstall batch complete.\\n\\nRestart is recommended to finish locked-file cleanup.\"))\n        self.after(2000, self._scan_installed)\n\n    def _app_keywords(self, name):\n        import re\n        words = re.split(r\"[ _\\-]+\", name.lower())\n        return [w for w in words if len(w) &gt; 3 and w not in\n                {\"microsoft\",\"windows\",\"update\",\"version\",\"setup\",\"install\",\n                 \"corp\",\"inc\",\"ltd\",\"llc\",\"software\",\"system\",\"service\"}]\n\n    def _force_remove_item(self, item, show_message=True):\n        name   = item[\"name\"]\n        words  = self._app_keywords(name)\n        removed = []\n        self.after(0, lambda: self.uninst_status.config(\n            text=f\"Force removing: {name}...\", fg=C[\"warning\"]))\n        self._log(f\"=== Force Remove START: {name} ===\", \"WARN\")\n\n        # 1. Run uninstaller silently\n        cmd = self._normalize_uninstall_command(item, quiet=True)\n        if cmd:\n            self._log(f\"[1] Uninstall cmd: {cmd[:100]}\", \"INFO\")\n            self._audit_event(\"force_uninstall_command\", {\"name\": name, \"cmd\": cmd[:300]})\n            self._run_cmd(cmd, timeout=180)\n            removed.append(\"Ran uninstaller\")\n        time.sleep(1)\n\n        # 2. Kill running processes\n        for proc in psutil.process_iter([\"pid\",\"name\",\"exe\"]):\n            try:\n                pname = (proc.info.get(\"name\") or \"\").lower()\n                pexe  = (proc.info.get(\"exe\")  or \"\").lower()\n                if any(w in pname or w in pexe for w in words):\n                    proc.kill()\n                    removed.append(f\"Killed process: {pname}\")\n                    self._log(f\"[2] Killed: {pname}\", \"OK\")\n            except: pass\n        time.sleep(1)\n\n        # 3. Delete install folder\n        inst_loc = item.get(\"install_loc\",\"\").strip()\n        candidate_dirs = []\n        if inst_loc and os.path.isdir(inst_loc):\n            candidate_dirs.append(inst_loc)\n        for base in [os.environ.get(\"ProgramFiles\",\"\"),\n                     os.environ.get(\"ProgramFiles(x86)\",\"\"),\n                     os.environ.get(\"LOCALAPPDATA\",\"\"),\n                     os.environ.get(\"APPDATA\",\"\")]:\n            if not base: continue\n            try:\n                for entry in Path(base).iterdir():\n                    if entry.is_dir() and any(w in entry.name.lower() for w in words):\n                        if str(entry) not in candidate_dirs:\n                            candidate_dirs.append(str(entry))\n            except: pass\n        for d in candidate_dirs:\n            try:\n                self._delete_leftover_path(d, \"FOLDER\")\n                removed.append(f\"Deleted folder: {d}\")\n                self._log(f\"[3] Deleted folder: {d}\", \"OK\")\n            except Exception as e:\n                self._log(f\"[3] Folder skipped: {d} ({e})\", \"WARN\")\n\n        # 4. Registry cleanup\n        reg_roots = [\n            (winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\"),\n            (winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\WOW6432Node\"),\n            (winreg.HKEY_CURRENT_USER,  r\"SOFTWARE\"),\n            (winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Services\"),\n            (winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\"),\n            (winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\"),\n            (winreg.HKEY_CURRENT_USER,  r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\"),\n        ]\n        for hive, root_path in reg_roots:\n            try:\n                root = winreg.OpenKey(hive, root_path, 0, winreg.KEY_READ)\n                to_del = []\n                i = 0\n                while True:\n                    try: sub = winreg.EnumKey(root, i); i += 1\n                    except OSError: break\n                    if any(w in sub.lower() for w in words):\n                        to_del.append(sub)\n                winreg.CloseKey(root)\n                for sub in to_del:\n                    full = root_path + \"\\\\\" + sub\n                    if root_path.lower().endswith(r\"currentcontrolset\\services\"):\n                        ok, err = self._native_delete_service(sub)\n                        if not ok:\n                            self._log(f\"[4] DeleteService fallback for {sub}: {err}\", \"WARN\")\n                            self._reg_delete_tree(hive, full)\n                    else:\n                        self._reg_delete_tree(hive, full)\n                    removed.append(f\"Reg: {full}\")\n                    self._log(f\"[4] Deleted reg: {full}\", \"OK\")\n            except: pass\n        # Also delete the specific stored key\n        try:\n            hive_map = {\"HKLM\": winreg.HKEY_LOCAL_MACHINE,\n                        \"HKCU\": winreg.HKEY_CURRENT_USER}\n            h = hive_map.get(item.get(\"reg_hive\",\"HKLM\"), winreg.HKEY_LOCAL_MACHINE)\n            self._reg_delete_tree(h, item.get(\"reg_key\",\"\"))\n        except: pass\n\n        # 5. AppData leftovers\n        for base in [os.environ.get(\"APPDATA\",\"\"), os.environ.get(\"LOCALAPPDATA\",\"\")]:\n            if not base: continue\n            try:\n                for entry in Path(base).iterdir():\n                    try:\n                        if any(w in entry.name.lower() for w in words):\n                            if entry.is_dir():\n                                self._delete_leftover_path(str(entry), \"FOLDER\")\n                            else:\n                                self._delete_leftover_path(str(entry), \"FILE\")\n                            removed.append(f\"AppData: {entry.name}\")\n                            self._log(f\"[5] AppData removed: {entry.name}\", \"OK\")\n                    except: pass\n            except: pass\n\n        # 6. Start Menu + Desktop shortcuts\n        for sm_base in [os.environ.get(\"APPDATA\",\"\"), os.environ.get(\"ProgramData\",\"\")]:\n            sm = Path(sm_base) / \"Microsoft\" / \"Windows\" / \"Start Menu\" / \"Programs\"\n            if sm.exists():\n                for entry in sm.rglob(\"*\"):\n                    try:\n                        if any(w in str(entry).lower() for w in words):\n                            if entry.is_file():\n                                self._delete_leftover_path(str(entry), \"SHORTCUT\")\n                            elif entry.is_dir():\n                                self._delete_leftover_path(str(entry), \"FOLDER\")\n                            removed.append(f\"StartMenu: {entry.name}\")\n                            self._log(f\"[6] StartMenu removed: {entry.name}\", \"OK\")\n                    except: pass\n        desktop = Path(os.path.expanduser(\"~\")) / \"Desktop\"\n        if desktop.exists():\n            for lnk in desktop.glob(\"*.lnk\"):\n                try:\n                    if any(w in lnk.stem.lower() for w in words):\n                        self._delete_leftover_path(str(lnk), \"SHORTCUT\")\n                        removed.append(f\"Desktop shortcut: {lnk.name}\")\n                        self._log(f\"[6] Desktop shortcut: {lnk.name}\", \"OK\")\n                except: pass\n\n        # 7. Temp folder\n        temp = os.environ.get(\"TEMP\",\"\")\n        if temp:\n            try:\n                for entry in Path(temp).iterdir():\n                    try:\n                        if any(w in str(entry).lower() for w in words):\n                            if entry.is_dir():\n                                self._delete_leftover_path(str(entry), \"FOLDER\")\n                            else:\n                                self._delete_leftover_path(str(entry), \"FILE\")\n                            removed.append(f\"Temp: {entry.name}\")\n                    except: pass\n            except: pass\n\n        # Done\n        summary = f\"Force remove complete: {name} \u2014 {len(removed)} items removed\"\n        self._log(f\"=== Force Remove DONE: {name} ({len(removed)} items) ===\", \"OK\")\n        self._audit_event(\"force_uninstall_finished\", {\"name\": name, \"removed_count\": len(removed)})\n        self.after(0, lambda: self.uninst_status.config(text=summary, fg=C[\"success\"]))\n        if show_message:\n            self.after(0, lambda: messagebox.showinfo(\n                \"Force Remove Complete\",\n                f\"Removed {len(removed)} items for:\\n{name}\\n\\n\"\n                \"Restart recommended to complete cleanup.\"))\n            self.after(2000, self._scan_installed)\n\n    def _reg_delete_tree(self, hive, path):\n        if not path: return\n        try:\n            key = winreg.OpenKey(hive, path, 0, winreg.KEY_READ)\n            subkeys = []\n            i = 0\n            while True:\n                try: subkeys.append(winreg.EnumKey(key, i)); i += 1\n                except OSError: break\n            winreg.CloseKey(key)\n            for sub in subkeys:\n                self._reg_delete_tree(hive, path + \"\\\\\" + sub)\n            winreg.DeleteKey(hive, path)\n        except: pass\n\n    # \u2500\u2500 Scan Leftovers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _scan_leftovers(self):\n        items = self._get_sel_uninst()\n        if not items:\n            messagebox.showinfo(\"No Selection\",\"Select a program to scan leftovers.\"); return\n        item = items[0]\n        self.leftover_tree.delete(*self.leftover_tree.get_children())\n        self.leftover_items = []\n        self._uninst_cancel_flag = False\n        self._uninst_pause_flag = False\n        if hasattr(self, \"uninst_pause_btn\"):\n            self.uninst_pause_btn.config(text=\"Pause Scan\")\n        self._set_uninst_progress(5, f\"Deep leftover scan for: {item['name']}...\", C[\"accent4\"])\n        self._audit_event(\"leftover_scan_started\", {\"name\": item.get(\"name\"), \"publisher\": item.get(\"publisher\")})\n        self._launch_job(\"scan_leftovers\", self._do_scan_leftovers, item)\n\n    def _do_scan_leftovers(self, item):\n        name = item[\"name\"]\n        try:\n            found = self._scan_leftovers_for_item(item, progress=True)\n        except InterruptedError:\n            self._audit_event(\"leftover_scan_cancelled\", {\"name\": name})\n            self._set_uninst_progress(0, f\"Leftover scan cancelled for: {name}\", C[\"warning\"])\n            return\n        self.leftover_items = found\n        self.after(0, self._populate_leftover_tree)\n        count = len(found)\n        risky = sum(1 for x in found if self._leftover_parts(x)[2].lower() == \"risky\")\n        safe = max(0, count - risky)\n        color = C[\"warning\"] if count else C[\"success\"]\n        self._set_uninst_progress(100, f\"{count} leftover(s) found for: {name}\", color)\n        if hasattr(self, \"uninst_summary_vars\"):\n            self.after(0, lambda: self.uninst_summary_vars[\"leftovers\"].set(str(count)))\n            self.after(0, lambda: self.uninst_summary_vars[\"risky\"].set(str(risky)))\n            self.after(0, lambda: self.uninst_summary_vars[\"safe\"].set(str(safe)))\n        self._audit_event(\"leftover_scan_finished\", {\"name\": name, \"count\": count, \"risky\": risky, \"safe\": safe})\n\n    def _scan_leftovers_for_item(self, item, progress=False):\n        name = item.get(\"name\", \"\")\n        words = self._app_keywords(name)\n        if not words:\n            fallback = re.sub(r\"[^a-z0-9]+\", \" \", name.lower()).strip().split()\n            words = [w for w in fallback if len(w) &gt;= 3][:3]\n        if not words:\n            return []\n\n        found = []\n        seen = set()\n\n        def add_item(ftype, path, confidence=70, risk=None, source=\"\", action=\"delete\", meta=None):\n            self._add_leftover_item(found, seen, ftype, path, confidence, risk, source, action, meta)\n\n        def word_hit(text):\n            low = str(text or \"\").lower()\n            return any(w in low for w in words)\n\n        def progress_step(pct, text):\n            if progress:\n                self._set_uninst_progress(pct, text, C[\"accent4\"])\n\n        install_loc = (item.get(\"install_loc\") or \"\").strip().strip('\"')\n        if install_loc and os.path.exists(install_loc):\n            add_item(\"FOLDER\", install_loc, 95, \"Risky\", \"InstallLocation\")\n\n        progress_step(12, \"Scanning registry residue...\")\n        reg_roots = [\n            (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\", 2),\n            (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\WOW6432Node\", 2),\n            (\"HKCU\", winreg.HKEY_CURRENT_USER,  r\"SOFTWARE\", 2),\n            (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Services\", 1),\n            (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\", 1),\n            (\"HKCU\", winreg.HKEY_CURRENT_USER,  r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\", 1),\n        ]\n        scanned = [0]\n        deadline = time.time() + 25\n\n        def scan_reg_level(hive_name, hive, root_path, depth):\n            self._check_uninst_control()\n            if scanned[0] &gt; 5000 or time.time() &gt; deadline:\n                return\n            try:\n                root = winreg.OpenKey(hive, root_path, 0, winreg.KEY_READ)\n            except Exception:\n                return\n            try:\n                try:\n                    value_text = _registry_value_text(root)\n                    if word_hit(root_path) or word_hit(value_text):\n                        add_item(\"REG\", f\"{hive_name}\\\\{root_path}\", 78, \"Risky\", \"Registry values\")\n                except Exception:\n                    pass\n                i = 0\n                while True:\n                    self._check_uninst_control()\n                    try:\n                        sub = winreg.EnumKey(root, i)\n                        i += 1\n                    except OSError:\n                        break\n                    scanned[0] += 1\n                    child_path = root_path + \"\\\\\" + sub\n                    if word_hit(sub):\n                        add_item(\"REG\", f\"{hive_name}\\\\{child_path}\", 88 if \"uninstall\" in root_path.lower() else 74, \"Risky\", \"Registry key\")\n                    if depth &gt; 0 and scanned[0] &lt; 5000 and time.time() &lt;= deadline:\n                        scan_reg_level(hive_name, hive, child_path, depth - 1)\n            finally:\n                try:\n                    winreg.CloseKey(root)\n                except Exception:\n                    pass\n\n        for hive_name, hive, root_path, depth in reg_roots:\n            scan_reg_level(hive_name, hive, root_path, depth)\n\n        progress_step(38, \"Scanning install folders, AppData and shortcuts...\")\n        search_bases = [\n            os.environ.get(\"ProgramFiles\",\"\"),\n            os.environ.get(\"ProgramFiles(x86)\",\"\"),\n            os.environ.get(\"ProgramData\",\"\"),\n            os.environ.get(\"APPDATA\",\"\"),\n            os.environ.get(\"LOCALAPPDATA\",\"\"),\n            os.environ.get(\"TEMP\",\"\"),\n            str(Path(os.path.expanduser(\"~\")) / \"Desktop\"),\n        ]\n        for base in search_bases:\n            self._check_uninst_control()\n            if not base:\n                continue\n            try:\n                for entry in Path(base).iterdir():\n                    self._check_uninst_control()\n                    try:\n                        if word_hit(entry.name):\n                            add_item(\"FOLDER\" if entry.is_dir() else \"FILE\", str(entry), 72, None, \"Filesystem\")\n                    except Exception:\n                        pass\n            except Exception:\n                pass\n\n        for sm_base in [os.environ.get(\"APPDATA\",\"\"), os.environ.get(\"ProgramData\",\"\")]:\n            self._check_uninst_control()\n            sm = Path(sm_base) / \"Microsoft\" / \"Windows\" / \"Start Menu\" / \"Programs\"\n            if sm.exists():\n                try:\n                    for idx, entry in enumerate(sm.rglob(\"*.lnk\")):\n                        if idx % 50 == 0:\n                            self._check_uninst_control()\n                        if word_hit(str(entry)):\n                            add_item(\"SHORTCUT\", str(entry), 68, \"Safe\", \"Start Menu shortcut\")\n                except Exception:\n                    pass\n\n        progress_step(58, \"Scanning startup entries...\")\n        run_roots = [\n            (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\"),\n            (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Run\"),\n            (\"HKCU\", winreg.HKEY_CURRENT_USER,  r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\"),\n            (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce\"),\n            (\"HKCU\", winreg.HKEY_CURRENT_USER,  r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce\"),\n        ]\n        for hive_name, hive, run_path in run_roots:\n            self._check_uninst_control()\n            try:\n                key = winreg.OpenKey(hive, run_path, 0, winreg.KEY_READ)\n                i = 0\n                while True:\n                    try:\n                        value_name, value, _vtype = winreg.EnumValue(key, i)\n                        i += 1\n                    except OSError:\n                        break\n                    if word_hit(value_name) or word_hit(value):\n                        display = f\"{hive_name}\\\\{run_path}\\\\{value_name}\"\n                        add_item(\"STARTUP\", display, 76, \"Risky\", \"Registry startup\",\n                                 meta={\"hive\": hive_name, \"path\": run_path, \"value\": value_name})\n                winreg.CloseKey(key)\n            except Exception:\n                pass\n\n        progress_step(70, \"Scanning Windows services...\")\n        try:\n            for svc in psutil.win_service_iter():\n                self._check_uninst_control()\n                try:\n                    info = svc.as_dict()\n                    svc_name = info.get(\"name\", \"\") or \"\"\n                    disp = info.get(\"display_name\", \"\") or \"\"\n                    bin_path = info.get(\"binpath\", \"\") or \"\"\n                    if word_hit(svc_name) or word_hit(disp) or word_hit(bin_path):\n                        add_item(\"SERVICE\", svc_name, 72, \"Risky\", \"Windows service\",\n                                 meta={\"service\": svc_name, \"display\": disp, \"binpath\": bin_path})\n                except Exception:\n                    pass\n        except Exception:\n            pass\n\n        progress_step(82, \"Scanning scheduled tasks...\")\n        try:\n            ps_terms = \"@(\" + \",\".join(_ps_single_quote(w) for w in words[:6]) + \")\"\n            script = f\"\"\"\n$terms = {ps_terms}\n$items = @()\ntry {{\n    $items = Get-ScheduledTask -ErrorAction SilentlyContinue | Where-Object {{\n        $txt = ($_.TaskName + ' ' + $_.TaskPath + ' ' + $_.URI).ToLower()\n        foreach($t in $terms) {{ if($txt.Contains($t.ToLower())) {{ return $true }} }}\n        return $false\n    }} | Select-Object -First 80 TaskName,TaskPath,State\n}} catch {{}}\n$items | ConvertTo-Json -Depth 3\n\"\"\"\n            out, _ = self._run_powershell(script, timeout=35)\n            for task in self._json_items_from_output(out):\n                self._check_uninst_control()\n                task_name = str(task.get(\"TaskName\", \"\") or \"\")\n                task_path = str(task.get(\"TaskPath\", \"\\\\\") or \"\\\\\")\n                full = (task_path.rstrip(\"\\\\\") + \"\\\\\" + task_name).replace(\"\\\\\\\\\", \"\\\\\")\n                add_item(\"TASK\", full, 66, \"Risky\", \"Scheduled Task\",\n                         meta={\"task\": full, \"state\": task.get(\"State\", \"\")})\n        except Exception:\n            pass\n\n        found.sort(key=lambda rec: (self._leftover_parts(rec)[0], -self._leftover_parts(rec)[3], self._leftover_parts(rec)[1].lower()))\n        return found[:2000]\n\n    def _populate_leftover_tree(self):\n        self.leftover_tree.delete(*self.leftover_tree.get_children())\n        risky = 0\n        safe = 0\n        for item in self.leftover_items:\n            ftype, path, risk, confidence, _meta = self._leftover_parts(item)\n            if risk.lower() == \"risky\":\n                risky += 1\n                tag = \"risky\"\n            else:\n                safe += 1\n                tag = \"safe\"\n            self.leftover_tree.insert(\"\", \"end\", tags=(tag,),\n                                      values=(ftype, risk, confidence, path))\n        if hasattr(self, \"uninst_summary_vars\"):\n            self.uninst_summary_vars[\"leftovers\"].set(str(len(self.leftover_items)))\n            self.uninst_summary_vars[\"risky\"].set(str(risky))\n            self.uninst_summary_vars[\"safe\"].set(str(safe))\n\n    # \u2500\u2500 Clean Leftovers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _clean_leftovers(self):\n        if not self.leftover_items:\n            messagebox.showinfo(\"Nothing\",\"Scan leftovers first.\"); return\n        n = len(self.leftover_items)\n        risky = sum(1 for x in self.leftover_items if self._leftover_parts(x)[2].lower() == \"risky\")\n        if not messagebox.askyesno(\"Clean Reviewed Leftovers\",\n            f\"Permanently clean {n} reviewed leftover item(s)?\\n\\n\"\n            f\"Risky items: {risky}\\n\"\n            \"This can remove files, folders, registry keys, services, startup entries and scheduled tasks.\\n\\n\"\n            \"Create/allow a restore point before continuing.\"): return\n        if not self._create_restore_point(\"Before Leftover Cleanup\"):\n            return\n        self._audit_event(\"leftover_cleanup_requested\", {\"count\": n, \"risky\": risky})\n        self._set_uninst_progress(5, f\"Cleaning {n} reviewed leftover item(s)...\", C[\"warning\"])\n        self._launch_job(\"clean_leftovers\", self._do_clean_leftovers)\n\n    def _do_clean_leftovers(self):\n        cleaned = 0; errors = 0\n        total = len(self.leftover_items)\n        for idx, item in enumerate(list(self.leftover_items), start=1):\n            ftype, path, _risk, _confidence, meta = self._leftover_parts(item)\n            try:\n                self._check_uninst_control()\n                if ftype == \"REG\":\n                    parts = path.split(\"\\\\\", 2)\n                    if len(parts) &lt; 3: continue\n                    hmap = {\"HKLM\": winreg.HKEY_LOCAL_MACHINE,\n                            \"HKCU\": winreg.HKEY_CURRENT_USER}\n                    h = hmap.get(parts[0])\n                    if not h: continue\n                    self._reg_delete_tree(h, parts[1] + \"\\\\\" + parts[2])\n                    cleaned += 1\n                elif ftype in (\"FOLDER\", \"FILE\", \"SHORTCUT\"):\n                    if os.path.exists(path):\n                        self._delete_leftover_path(path, ftype); cleaned += 1\n                elif ftype == \"SERVICE\":\n                    svc = meta.get(\"service\") or path\n                    ok, err = self._native_delete_service(svc)\n                    if not ok:\n                        raise RuntimeError(err or \"DeleteService failed\")\n                    cleaned += 1\n                elif ftype == \"STARTUP\":\n                    hive_name = meta.get(\"hive\", \"\")\n                    run_path = meta.get(\"path\", \"\")\n                    value_name = meta.get(\"value\", \"\")\n                    hmap = {\"HKLM\": winreg.HKEY_LOCAL_MACHINE,\n                            \"HKCU\": winreg.HKEY_CURRENT_USER}\n                    h = hmap.get(hive_name)\n                    if h and run_path and value_name:\n                        key = winreg.OpenKey(h, run_path, 0, winreg.KEY_SET_VALUE)\n                        try:\n                            winreg.DeleteValue(key, value_name)\n                        finally:\n                            winreg.CloseKey(key)\n                        cleaned += 1\n                elif ftype == \"TASK\":\n                    task_name = meta.get(\"task\") or path\n                    out, rc = self._run_cmd(f'schtasks /Delete /TN \"{task_name}\" /F', timeout=45)\n                    if rc != 0:\n                        raise RuntimeError(out[-300:] if out else \"schtasks delete failed\")\n                    cleaned += 1\n                self._set_uninst_progress(5 + (idx / max(total, 1)) * 90, f\"Cleaning leftovers [{idx}/{total}]...\", C[\"warning\"])\n            except InterruptedError:\n                self._set_uninst_progress(0, \"Leftover cleanup cancelled.\", C[\"warning\"])\n                self._audit_event(\"leftover_cleanup_cancelled\", {\"cleaned\": cleaned, \"errors\": errors})\n                return\n            except Exception as e:\n                errors += 1\n                self._audit_event(\"leftover_cleanup_error\", {\"type\": ftype, \"path\": path, \"error\": str(e)})\n        summary = f\"Cleaned {cleaned} leftover(s). Errors: {errors}\"\n        self._set_uninst_progress(100, summary, C[\"success\"] if errors == 0 else C[\"warning\"])\n        self._log(summary, \"OK\")\n        self._audit_event(\"leftover_cleanup_finished\", {\"cleaned\": cleaned, \"errors\": errors})\n        self.leftover_items = []\n        self.after(0, self._populate_leftover_tree)\n\n    def _reg_read_str(self, key, value_name):\n        try:\n            val, _ = winreg.QueryValueEx(key, value_name)\n            return str(val)\n        except:\n            return \"\"\n\n    def _uninstall_selected_with_confirm(self):\n        \"\"\"Legacy compatibility \u2014 calls standard uninstall\"\"\"\n        self._uninst_standard()\n\n\n        # ---------- HARDWARE, PRINTER, DRIVER, BACKUP, REPORT, LOG (unchanged, but confirm added where needed) ----------\n    def _build_hardware(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udda5\ufe0f Hardware Health\", \"Real stats\", hw=True)\n        self._action_card_grid(frame, [\n            (\"\ud83d\udd0d\", \"Scan Hardware\", \"CPU, GPU, RAM, Disk info scan karo\", C[\"btn_hw\"], self._scan_hw),\n        ], cols=1)\n        content = tk.Frame(frame, bg=C[\"card\"])\n        content.pack(fill=\"both\", expand=True, padx=16, pady=10)\n        self.hw_log = self._scrolled_text(content, height=22)\n        return frame\n\n    def _scan_hw(self):\n        self._launch_job(\"scan_hw\", self._do_scan_hw)\n\n    def _do_scan_hw(self):\n        self._append_log(self.hw_log, \"\u2550\"*50, C[\"border\"])\n        out, _ = self._run_cmd(\"wmic cpu get Name,LoadPercentage /format:list\")\n        self._append_log(self.hw_log, \"-- CPU --\", C[\"hw_accent\"])\n        for l in out.splitlines():\n            if \"=\" in l:\n                self._append_log(self.hw_log, l, C[\"text\"])\n        out, _ = self._run_cmd(\"wmic path win32_VideoController get Name,AdapterRAM,DriverVersion /format:list\")\n        self._append_log(self.hw_log, \"-- GPU --\", C[\"hw_accent\"])\n        for l in out.splitlines():\n            if \"=\" in l and l.split(\"=\")[1].strip():\n                if \"AdapterRAM\" in l:\n                    try:\n                        l = f\"VRAM={self._fmt_size(int(l.split('=')[1]))}\"\n                    except:\n                        pass\n                self._append_log(self.hw_log, l, C[\"text\"])\n        self._append_log(self.hw_log, \"\u2705 Hardware scan complete\", C[\"success\"])\n\n    def _build_printer(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udda8\ufe0f Advanced Printer Fixer\",\n                             \"Spooler reset, stuck jobs, driver repair, network printer \u2014 sab kuch\")\n\n        self._printer_action_buttons = []\n        printer_actions = [\n            (\"\ud83d\udd0d\", \"Detect Printers\",       \"System pe printers dhundho\",           C[\"btn_info\"],   self._printer_detect),\n            (\"\ud83d\udd01\", \"Reset Spooler\",         \"Print Spooler service restart karo\",   C[\"btn_warn\"],   self._printer_reset_spooler),\n            (\"\ud83d\uddd1\",  \"Clear Stuck Jobs\",     \"Atkaye hue print jobs saaf karo\",       C[\"btn_danger\"], self._printer_clear_jobs),\n            (\"\ud83d\udd27\", \"Full Auto-Repair\",      \"Spooler + jobs + driver full fix\",     C[\"btn_hw\"],     self._printer_full_repair),\n            (\"\ud83e\uddf9\", \"Driver Purge/Reinstall\",\"Printer driver saaf karo + reinstall\", C[\"btn_danger\"], self._printer_driver_purge_flow),\n            (\"\ud83d\udda5\",  \"Set as Default\",       \"Selected printer default set karo\",    C[\"btn_chip\"],   self._printer_set_default),\n            (\"\u274c\", \"Remove Printer\",        \"Selected printer hata do\",             C[\"btn_danger\"], self._printer_remove),\n            (\"\ud83c\udf10\", \"Network Printer Setup\", \"Network printer add karo\",             C[\"btn_info\"],   self._printer_network_setup),\n        ]\n        printer_toolbar = tk.Frame(frame, bg=C[\"bg\"])\n        printer_toolbar.pack(fill=\"x\", padx=12, pady=(4, 2))\n        for col in range(4):\n            printer_toolbar.columnconfigure(col, weight=1)\n        for idx, (_icon, title, _subtitle, color, cmd_func) in enumerate(printer_actions):\n            btn = tk.Button(printer_toolbar, text=title, font=FONTS[\"small\"],\n                            bg=color, fg=C[\"text\"], bd=0, padx=8, pady=4,\n                            cursor=\"hand2\", command=cmd_func)\n            btn.grid(row=idx // 4, column=idx % 4, sticky=\"ew\", padx=3, pady=2)\n            self._printer_action_buttons.append(btn)\n\n        # \u2500\u2500 Tab Notebook \u2014 Tab1: Printer Fixer, Tab2: Sharing Center \u2500\u2500\n        nb = ttk.Notebook(frame)\n        nb.pack(fill=\"both\", expand=True, padx=8, pady=(4,8))\n\n        # Tab 1 \u2014 Printer Fixer\n        tab1 = tk.Frame(nb, bg=C[\"bg\"])\n        nb.add(tab1, text=\"  \ud83d\udda8  Printer Fixer  \")\n\n        paned = tk.Frame(tab1, bg=C[\"bg\"])\n        paned.pack(fill=\"both\", expand=True, padx=8, pady=(4,8))\n        paned.columnconfigure(0, weight=2)\n        paned.columnconfigure(1, weight=3)\n        paned.rowconfigure(0, weight=1)\n\n        # Left \u2014 printer list + status cards\n        left = tk.Frame(paned, bg=C[\"card\"])\n        left.grid(row=0, column=0, sticky=\"nsew\", padx=(0,6))\n        left.rowconfigure(1, weight=1)\n\n        # Status cards\n        cards = tk.Frame(left, bg=C[\"card\"])\n        cards.pack(fill=\"x\", pady=(8,4), padx=8)\n        self.printer_stat_vars = {}\n        for i,(k,lbl,col) in enumerate([\n            (\"total\",   \"Total Printers\", C[\"accent\"]),\n            (\"online\",  \"Online\",         C[\"success\"]),\n            (\"offline\", \"Offline\",        C[\"error\"]),\n            (\"default\", \"Default\",        C[\"accent2\"]),\n        ]):\n            cards.columnconfigure(i, weight=1)\n            c = tk.Frame(cards, bg=C[\"bg\"], padx=8, pady=6)\n            c.grid(row=0, column=i, padx=3, sticky=\"ew\")\n            tk.Label(c, text=lbl, font=FONTS[\"small\"], fg=col, bg=C[\"bg\"]).pack(anchor=\"w\")\n            v = tk.StringVar(value=\"--\")\n            self.printer_stat_vars[k] = v\n            tk.Label(c, textvariable=v, font=(\"Segoe UI\",14,\"bold\"),\n                     fg=col, bg=C[\"bg\"]).pack(anchor=\"w\")\n\n        # Printer list\n        tk.Label(left, text=\"  Detected Printers\", font=FONTS[\"subhead\"],\n                 fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=8, pady=(4,2))\n        cols = (\"Name\",\"Status\",\"Default\",\"Jobs\")\n        self.printer_tree = ttk.Treeview(left, columns=cols, show=\"headings\",\n                                          height=12, style=\"Custom.Treeview\",\n                                          selectmode=\"browse\")\n        for col, w in zip(cols, [200,90,70,50]):\n            self.printer_tree.heading(col, text=col)\n            self.printer_tree.column(col, width=w, anchor=\"center\")\n        self.printer_tree.tag_configure(\"online\",  foreground=C[\"success\"])\n        self.printer_tree.tag_configure(\"offline\", foreground=C[\"error\"])\n        self.printer_tree.tag_configure(\"default\", foreground=C[\"warning\"])\n        psb = ttk.Scrollbar(left, orient=\"vertical\", command=self.printer_tree.yview)\n        self.printer_tree.configure(yscrollcommand=psb.set)\n        self.printer_tree.pack(side=\"left\", fill=\"both\", expand=True, padx=(8,0), pady=(0,8))\n        psb.pack(side=\"right\", fill=\"y\", pady=(0,8), padx=(0,4))\n        self.printer_tree.bind(\"&lt;&gt;\", self._on_printer_select)\n        self._printer_data = []\n\n        # Right \u2014 action log + diagnostics\n        right = tk.Frame(paned, bg=C[\"card\"])\n        right.grid(row=0, column=1, sticky=\"nsew\")\n        right.rowconfigure(1, weight=1)\n\n        # Quick action buttons\n        qa = tk.Frame(right, bg=C[\"card\"])\n        qa.pack(fill=\"x\", padx=8, pady=(8,4))\n        tk.Label(qa, text=\"Quick Fixes:\", font=FONTS[\"small\"],\n                 fg=C[\"text_dim\"], bg=C[\"card\"]).grid(row=0, column=0, sticky=\"w\", padx=(0,6), pady=(0,3))\n        quick_grid = tk.Frame(qa, bg=C[\"card\"])\n        quick_grid.grid(row=1, column=0, sticky=\"ew\")\n        qa.columnconfigure(0, weight=1)\n        for idx, (lbl, fn) in enumerate([\n            (\"Restart Spooler\",       self._printer_reset_spooler),\n            (\"SFC /scannow\",          self._printer_sfc),\n            (\"PrintNightmare Fix\",    self._printer_printnightmare),\n            (\"Run Troubleshooter\",    self._printer_troubleshooter),\n            (\"Open Print Queue\",      self._printer_open_queue),\n            (\"Driver Audit\",          self._printer_driver_signature_audit),\n            (\"Spooler Snapshot\",      self._printer_spooler_snapshot),\n        ]):\n            row, col = divmod(idx, 3)\n            quick_grid.columnconfigure(col, weight=1)\n            btn = tk.Button(quick_grid, text=lbl, font=FONTS[\"small\"],\n                            bg=C[\"btn_info\"], fg=\"white\", bd=0, padx=8, pady=3,\n                            cursor=\"hand2\", command=fn)\n            btn.grid(row=row, column=col, sticky=\"ew\", padx=3, pady=2)\n            self._printer_action_buttons.append(btn)\n\n        status_panel = tk.Frame(right, bg=C[\"card\"])\n        status_panel.pack(fill=\"x\", padx=8, pady=(0,4))\n        tk.Label(status_panel, text=\"Execution:\", font=FONTS[\"small\"],\n                 fg=C[\"text_dim\"], bg=C[\"card\"]).grid(row=0, column=0, sticky=\"w\", padx=(0,6))\n        self.printer_exec_status_lbl = tk.Label(status_panel, text=\"Ready\",\n                                                font=FONTS[\"small\"], fg=C[\"text_dim\"],\n                                                bg=C[\"card\"])\n        self.printer_exec_status_lbl.grid(row=0, column=1, sticky=\"w\")\n        self.printer_exec_time_lbl = tk.Label(status_panel, text=\"Elapsed: 00:00 | ETA: --\",\n                                              font=FONTS[\"small\"], fg=C[\"text_dim\"],\n                                              bg=C[\"card\"])\n        self.printer_exec_time_lbl.grid(row=1, column=0, columnspan=2, sticky=\"w\", pady=(2, 0))\n        status_panel.columnconfigure(1, weight=1)\n\n        tk.Label(right, text=\"  \ud83d\udcdd Repair Log\",\n                 font=FONTS[\"subhead\"], fg=C[\"accent2\"], bg=C[\"card\"]).pack(\n                 anchor=\"w\", padx=8, pady=(4,2))\n        self.printer_log = self._scrolled_text(right, height=12)\n        tk.Label(right, text=\"  \ud83d\udd0e Execution Trace\",\n                 font=FONTS[\"subhead\"], fg=C[\"accent2\"], bg=C[\"card\"]).pack(\n                 anchor=\"w\", padx=8, pady=(4,2))\n        self.printer_trace_log = self._scrolled_text(right, height=4)\n\n        # Spooler status indicator\n        bot = tk.Frame(right, bg=C[\"card\"])\n        bot.pack(fill=\"x\", padx=8, pady=(4,8))\n        tk.Label(bot, text=\"Spooler:\", font=FONTS[\"small\"],\n                 fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self.spooler_status_lbl = tk.Label(bot, text=\"Unknown\",\n                                            font=FONTS[\"small\"], fg=C[\"warning\"],\n                                            bg=C[\"card\"])\n        self.spooler_status_lbl.pack(side=\"left\", padx=6)\n        self._btn(bot, \"\u21bb Refresh Status\", C[\"btn_chip\"],\n                  self._refresh_spooler_status).pack(side=\"left\", padx=6)\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # \ud83d\udd17 TAB 2 \u2014 PRINTER SHARING CENTER\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        tab2 = tk.Frame(nb, bg=C[\"bg\"])\n        nb.add(tab2, text=\"  \ud83d\udd17  Sharing Center (Host &amp; Client)  \")\n\n        # Header inside tab2\n        share_hdr = tk.Frame(tab2, bg=C[\"panel\"])\n        share_hdr.pack(fill=\"x\")\n        tk.Label(share_hdr, text=\"  \ud83d\udd17 Printer Sharing Center\",\n                 font=FONTS[\"heading\"], fg=C[\"accent4\"], bg=C[\"panel\"]).pack(side=\"left\", pady=8, padx=8)\n        tk.Label(share_hdr,\n                 text=\"Har port, service, security alag-alag kholo \u2014 Host &amp; Client dono ke liye\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"left\", pady=8)\n        self._btn(share_hdr, \"\ud83d\udd0e Check Sharing Status\", C[\"btn_chip\"],\n                  self._check_sharing_status).pack(side=\"right\", padx=10, pady=6)\n\n        # Scrollable area inside tab2\n        sc_outer = tk.Frame(tab2, bg=C[\"bg\"])\n        sc_outer.pack(fill=\"both\", expand=True, padx=0, pady=0)\n        sc_canvas = tk.Canvas(sc_outer, bg=C[\"bg\"], highlightthickness=0)\n        sc_sb = ttk.Scrollbar(sc_outer, orient=\"vertical\", command=sc_canvas.yview)\n        sc_canvas.configure(yscrollcommand=sc_sb.set)\n        sc_sb.pack(side=\"right\", fill=\"y\")\n        sc_canvas.pack(side=\"left\", fill=\"both\", expand=True)\n        share_body = tk.Frame(sc_canvas, bg=C[\"bg\"])\n        sc_win = sc_canvas.create_window((0,0), window=share_body, anchor=\"nw\")\n        def _sc_resize(e):\n            sc_canvas.configure(scrollregion=sc_canvas.bbox(\"all\"))\n            sc_canvas.itemconfig(sc_win, width=sc_canvas.winfo_width())\n        share_body.bind(\"\", _sc_resize)\n        def _sc_canvas_configure(e):\n            sc_canvas.itemconfig(sc_win, width=e.width)\n            sc_canvas.configure(scrollregion=sc_canvas.bbox(\"all\"))\n        sc_canvas.bind(\"\", _sc_canvas_configure)\n        self._bind_scoped_mousewheel(share_body, sc_canvas)\n\n        share_body.columnconfigure(0, weight=1)\n        share_body.columnconfigure(1, weight=1)\n\n        def _section_card(parent, title, subtitle, bg_hdr, fg_title, col):\n            \"\"\"Card with header for HOST or CLIENT sections.\"\"\"\n            frm = tk.Frame(parent, bg=C[\"card\"], bd=0)\n            hdr = tk.Frame(frm, bg=bg_hdr)\n            hdr.pack(fill=\"x\")\n            tk.Label(hdr, text=title, font=FONTS[\"subhead\"], fg=fg_title, bg=bg_hdr).pack(anchor=\"w\", padx=10, pady=6)\n            tk.Label(hdr, text=subtitle, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=bg_hdr).pack(anchor=\"w\", padx=10, pady=(0,6))\n            return frm\n\n        def _grp_label(parent, text, bg=None):\n            bg = bg or C[\"card\"]\n            tk.Label(parent, text=text, font=FONTS[\"small\"],\n                     fg=C[\"accent4\"], bg=bg, anchor=\"w\").pack(fill=\"x\", padx=10, pady=(8,2))\n            tk.Frame(parent, bg=C[\"border\"], height=1).pack(fill=\"x\", padx=10)\n\n        def _ibtn(parent, text, color, cmd, desc=\"\"):\n            row = tk.Frame(parent, bg=C[\"card\"])\n            row.pack(fill=\"x\", padx=8, pady=2)\n            tk.Button(row, text=text, font=FONTS[\"body\"],\n                      bg=color, fg=C[\"bg\"] if color in (C[\"accent\"],C[\"success\"]) else C[\"text\"],\n                      bd=0, padx=10, pady=6, cursor=\"hand2\", anchor=\"w\",\n                      command=cmd).pack(side=\"left\", fill=\"x\", expand=True)\n            if desc:\n                tk.Label(row, text=desc, font=(\"Consolas\",8),\n                         fg=C[\"text_dim\"], bg=C[\"card\"], anchor=\"w\", wraplength=260).pack(side=\"left\", padx=(6,4))\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # \ud83d\udda5 HOST COMPUTER COLUMN\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        host_frame = _section_card(share_body,\n            \"\ud83d\udda5  HOST COMPUTER  \u2014  Jis PC pe printer laga hai\",\n            \"Yahan printer physically connected hai (USB/LPT)\",\n            \"#1A3A2A\", C[\"accent\"], 0)\n        host_frame.grid(row=0, column=0, sticky=\"nsew\", padx=(8,4), pady=6)\n\n        # \u2500\u2500 HOST: PORTS \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(host_frame, \"\ud83d\udd0c  PORTS \u2014 Firewall mein open karo (IN + OUT)\")\n        _ibtn(host_frame, \"\u25b6 Port 445 TCP+UDP  \u2014  SMB File &amp; Printer Sharing\",\n              C[\"btn_chip\"], lambda: self._open_single_port_host(445,\"TCP+UDP\",\"SMB-Printer-Sharing\"),\n              \"Printer sharing ka main port\")\n        _ibtn(host_frame, \"\u25b6 Port 139 TCP  \u2014  NetBIOS Session Service\",\n              C[\"btn_chip\"], lambda: self._open_single_port_host(139,\"TCP\",\"NetBIOS-Session\"),\n              \"Purane Windows me sharing ke liye\")\n        _ibtn(host_frame, \"\u25b6 Port 137 UDP  \u2014  NetBIOS Name Service\",\n              C[\"btn_chip\"], lambda: self._open_single_port_host(137,\"UDP\",\"NetBIOS-Name\"),\n              \"Network name resolution\")\n        _ibtn(host_frame, \"\u25b6 Port 138 UDP  \u2014  NetBIOS Datagram Service\",\n              C[\"btn_chip\"], lambda: self._open_single_port_host(138,\"UDP\",\"NetBIOS-Datagram\"),\n              \"NetBIOS broadcast messages\")\n        _ibtn(host_frame, \"\u25b6 Port 135 TCP  \u2014  RPC Endpoint Mapper\",\n              C[\"btn_chip\"], lambda: self._open_single_port_host(135,\"TCP\",\"RPC-Endpoint\"),\n              \"Windows Remote Procedure Call\")\n        _ibtn(host_frame, \"\u25b6 Port 9100 TCP  \u2014  RAW Print / JetDirect\",\n              C[\"btn_chip\"], lambda: self._open_single_port_host(9100,\"TCP\",\"RAW-Print-JetDirect\"),\n              \"Network printer direct print port\")\n        _ibtn(host_frame, \"\u25b6 Port 631 TCP  \u2014  IPP Internet Printing Protocol\",\n              C[\"btn_chip\"], lambda: self._open_single_port_host(631,\"TCP\",\"IPP-Printing\"),\n              \"Internet Printing Protocol (IPP)\")\n        _ibtn(host_frame, \"\u25b6 Port 515 TCP  \u2014  LPD/LPR Line Printer Daemon\",\n              C[\"btn_chip\"], lambda: self._open_single_port_host(515,\"TCP\",\"LPD-LPR-Printer\"),\n              \"Legacy Unix/Linux print protocol\")\n        _ibtn(host_frame, \"\u2705 Sabhi Printer Ports Ek Saath Kholo  (445+139+137+138+135+9100+631+515)\",\n              C[\"btn_warn\"], self._host_open_ports,\n              \"Saare ports ek click mein\")\n\n        # \u2500\u2500 HOST: SECURITY / FIREWALL \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(host_frame, \"\ud83d\udd12  SECURITY &amp; FIREWALL SETTINGS\")\n        _ibtn(host_frame, \"\u25b6 Network Discovery  \u2192  Enable (Private)\",\n              C[\"btn_info\"], lambda: self._host_single_security(\"network_discovery\"),\n              \"Doosre computers network mein dikh sakein\")\n        _ibtn(host_frame, \"\u25b6 File &amp; Printer Sharing Rules  \u2192  ON (All Profiles)\",\n              C[\"btn_info\"], lambda: self._host_single_security(\"fp_sharing_rules\"),\n              \"Windows Firewall built-in sharing rules\")\n        _ibtn(host_frame, \"\u25b6 Network Profile  \u2192  Private\",\n              C[\"btn_info\"], lambda: self._host_single_security(\"network_private\"),\n              \"Public profile pe sharing band hoti hai\")\n        _ibtn(host_frame, \"\u25b6 Password Protected Sharing  \u2192  OFF\",\n              C[\"btn_info\"], lambda: self._host_single_security(\"pwd_sharing_off\"),\n              \"Bina password ke client connect kar sake\")\n        _ibtn(host_frame, \"\u25b6 SMB Signing  \u2192  Optional (Not Required)\",\n              C[\"btn_info\"], lambda: self._host_single_security(\"smb_sign_optional\"),\n              \"HKLM/.../LanmanServer: RequireSecuritySignature=0\")\n        _ibtn(host_frame, \"\u25b6 Windows Defender Firewall  \u2192  Private Network OFF\",\n              C[\"btn_info\"], lambda: self._host_single_security(\"fw_private_off\"),\n              \"Private profile firewall band karo (trusted LAN)\")\n        _ibtn(host_frame, \"\u25b6 ICMPv4 Ping  \u2192  Allow (Firewall)\",\n              C[\"btn_info\"], lambda: self._host_single_security(\"allow_ping\"),\n              \"Client se ping ka jawab aaye\")\n        _ibtn(host_frame, \"\u2705 Saari Security Settings Ek Saath\",\n              C[\"btn_warn\"], self._host_security_fix,\n              \"Network Discovery + F&amp;P Rules + Private + SMB\")\n\n        # \u2500\u2500 HOST: REGISTRY \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(host_frame, \"\ud83d\udddd  REGISTRY CHANGES\")\n        _ibtn(host_frame, \"\u25b6 AutoShareServer = 1  (Admin shares C$, D$ enable)\",\n              C[\"btn_hw\"], lambda: self._host_single_reg(\"AutoShareServer\"),\n              \"HKLM/.../LanmanServer/Parameters\")\n        _ibtn(host_frame, \"\u25b6 AutoShareWks = 1  (Workstation shares enable)\",\n              C[\"btn_hw\"], lambda: self._host_single_reg(\"AutoShareWks\"),\n              \"HKLM/.../LanmanServer/Parameters\")\n        _ibtn(host_frame, \"\u25b6 IRPStackSize = 20  (Large network packets fix)\",\n              C[\"btn_hw\"], lambda: self._host_single_reg(\"IRPStackSize\"),\n              \"HKLM/.../LanmanServer/Parameters\")\n        _ibtn(host_frame, \"\u25b6 LimitBlankPasswordUse = 0  (Blank password allow)\",\n              C[\"btn_hw\"], lambda: self._host_single_reg(\"LimitBlankPasswordUse\"),\n              \"HKLM/.../Control/Lsa\")\n        _ibtn(host_frame, \"\u25b6 DisableWebPrinting = 0  (Web printing enable)\",\n              C[\"btn_hw\"], lambda: self._host_single_reg(\"DisableWebPrinting\"),\n              \"HKLM/.../Control/Print\")\n        _ibtn(host_frame, \"\u25b6 SMB1 Protocol  \u2192  Enable  (XP/Win7 clients ke liye)\",\n              C[\"btn_hw\"], lambda: self._host_single_reg(\"EnableSMB1\"),\n              \"\u26a0 Security risk \u2014 sirf trusted LAN pe karo\")\n        _ibtn(host_frame, \"\u2705 Saare Registry Changes Ek Saath\",\n              C[\"btn_warn\"], self._host_registry_fix,\n              \"AutoShare + IRPStack + LimitBlank + DisableWeb\")\n\n        # \u2500\u2500 HOST: SERVICES \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(host_frame, \"\u2699\ufe0f  SERVICES \u2014 Start/Enable karo\")\n        _ibtn(host_frame, \"\u25b6 Print Spooler  \u2192  Auto + Start\",\n              C[\"accent2\"], lambda: self._host_single_svc(\"Spooler\"),\n              \"Printer ka main service \u2014 shuruaat yahan se\")\n        _ibtn(host_frame, \"\u25b6 Server (LanmanServer)  \u2192  Auto + Start\",\n              C[\"accent2\"], lambda: self._host_single_svc(\"LanmanServer\"),\n              \"File &amp; Printer Sharing ka core service\")\n        _ibtn(host_frame, \"\u25b6 Workstation (LanmanWorkstation)  \u2192  Auto + Start\",\n              C[\"accent2\"], lambda: self._host_single_svc(\"LanmanWorkstation\"),\n              \"Network client redirector service\")\n        _ibtn(host_frame, \"\u25b6 TCP/IP NetBIOS Helper  \u2192  Auto + Start\",\n              C[\"accent2\"], lambda: self._host_single_svc(\"lmhosts\"),\n              \"NetBIOS over TCP/IP naam resolution\")\n        _ibtn(host_frame, \"\u25b6 Function Discovery Provider Host  \u2192  Auto + Start\",\n              C[\"accent2\"], lambda: self._host_single_svc(\"fdPHost\"),\n              \"Network discovery ke liye zaroori\")\n        _ibtn(host_frame, \"\u25b6 Function Discovery Resource Publication  \u2192  Auto + Start\",\n              C[\"accent2\"], lambda: self._host_single_svc(\"FDResPub\"),\n              \"Computer ko network mein publish karta hai\")\n        _ibtn(host_frame, \"\u25b6 SSDP Discovery  \u2192  Auto + Start\",\n              C[\"accent2\"], lambda: self._host_single_svc(\"SSDPSRV\"),\n              \"UPnP devices discovery\")\n        _ibtn(host_frame, \"\u2705 Saari Services Ek Saath Enable karo\",\n              C[\"btn_warn\"], self._host_enable_services,\n              \"Spooler + Server + Workstation + NetBIOS + FD\")\n\n        # \u2500\u2500 HOST: PRINTER SHARE \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(host_frame, \"\ud83d\udce4  PRINTER SHARE KARO\")\n        _ibtn(host_frame, \"\ud83d\udce4  Selected Printer Share Karo  (Auto Confirm)\",\n              C[\"accent\"], self._host_auto_share,\n              \"Upar list mein printer select karo, phir click\")\n\n        # \u2500\u2500 HOST: ERROR 0x0000709 FIX \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(host_frame, \"\ud83d\udd34  ERROR 0x0000709 \u2014 Default Printer Cannot Be Set\")\n        _ibtn(host_frame, \"\ud83d\udd27 Auto-Fix Error 0x0000709  (HOST \u2014 Ek Click Mein)\",\n              C[\"error\"], self._fix_error_709_host,\n              \"Default printer set nahi ho raha \u2014 registry + spooler + RPC fix\")\n\n        # \u2500\u2500 HOST: ERROR 0x0000011b FIX \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(host_frame, \"\ud83d\udd34  ERROR 0x0000011b \u2014 Network Printer Connect Fail\")\n        _ibtn(host_frame, \"\ud83d\udd27 Auto-Fix Error 0x0000011b  (HOST \u2014 Ek Click Mein)\",\n              C[\"error\"], self._fix_error_11b_host,\n              \"Windows Update KB5005565+ ke baad network printer connect nahi \u2014 CVE-2021-1678 patch rollback\")\n\n        # \u2500\u2500 HOST: ONE-CLICK MEGA FIX \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(host_frame, \"\u26a1  MEGA AUTO-FIX \u2014 HOST KI SAARI SETTINGS EK SAATH\")\n        _ibtn(host_frame, \"\ud83d\ude80  HOST: SABKUCH AUTO-FIX  (Ports + Security + Registry + Services + Share + 709 + 11b)\",\n              \"#FF6600\", self._host_mega_auto_fix,\n              \"Ek click mein HOST ka poora printer sharing setup complete \u2014 seedha ready to share\")\n        tk.Frame(host_frame, bg=C[\"bg\"], height=8).pack()\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # \ud83d\udcbb CLIENT COMPUTER COLUMN\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        client_frame = _section_card(share_body,\n            \"\ud83d\udcbb  CLIENT COMPUTER  \u2014  Jo shared printer use karega\",\n            \"Yahan printer nahi laga, network se use karna hai\",\n            \"#1A2A3A\", C[\"accent2\"], 1)\n        client_frame.grid(row=0, column=1, sticky=\"nsew\", padx=(4,8), pady=6)\n\n        # \u2500\u2500 CLIENT: PORTS \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(client_frame, \"\ud83d\udd0c  PORTS \u2014 Firewall mein open karo (IN + OUT)\")\n        _ibtn(client_frame, \"\u25b6 Port 445 TCP+UDP  \u2014  SMB Client Access\",\n              C[\"btn_chip\"], lambda: self._open_single_port_client(445,\"TCP+UDP\",\"SMB-Client-Access\"),\n              \"Host se SMB connection ke liye\")\n        _ibtn(client_frame, \"\u25b6 Port 139 TCP  \u2014  NetBIOS Session (Client)\",\n              C[\"btn_chip\"], lambda: self._open_single_port_client(139,\"TCP\",\"NetBIOS-Session-Client\"),\n              \"NetBIOS session connect karne ke liye\")\n        _ibtn(client_frame, \"\u25b6 Port 137 UDP  \u2014  NetBIOS Name (Client)\",\n              C[\"btn_chip\"], lambda: self._open_single_port_client(137,\"UDP\",\"NetBIOS-Name-Client\"),\n              \"Naam se IP resolve karne ke liye\")\n        _ibtn(client_frame, \"\u25b6 Port 138 UDP  \u2014  NetBIOS Datagram (Client)\",\n              C[\"btn_chip\"], lambda: self._open_single_port_client(138,\"UDP\",\"NetBIOS-Datagram-Client\"),\n              \"NetBIOS broadcast receive karne ke liye\")\n        _ibtn(client_frame, \"\u25b6 Port 135 TCP  \u2014  RPC Client\",\n              C[\"btn_chip\"], lambda: self._open_single_port_client(135,\"TCP\",\"RPC-Client\"),\n              \"Remote Procedure Call \u2014 Windows core\")\n        _ibtn(client_frame, \"\u25b6 Port 9100 TCP  \u2014  RAW Print (Client Side)\",\n              C[\"btn_chip\"], lambda: self._open_single_port_client(9100,\"TCP\",\"RAW-Print-Client\"),\n              \"Direct raw print access client pe\")\n        _ibtn(client_frame, \"\u25b6 Port 631 TCP  \u2014  IPP Client\",\n              C[\"btn_chip\"], lambda: self._open_single_port_client(631,\"TCP\",\"IPP-Client\"),\n              \"Internet Printing Protocol client\")\n        _ibtn(client_frame, \"\u25b6 Port 515 TCP  \u2014  LPD/LPR Client\",\n              C[\"btn_chip\"], lambda: self._open_single_port_client(515,\"TCP\",\"LPD-LPR-Client\"),\n              \"Legacy print protocol client\")\n        _ibtn(client_frame, \"\u2705 Sabhi Client Ports Ek Saath  (445+139+137+138+135+9100+631+515)\",\n              C[\"btn_warn\"], self._client_open_ports,\n              \"Saare ports ek click mein\")\n\n        # \u2500\u2500 CLIENT: SECURITY \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(client_frame, \"\ud83d\udd12  SECURITY &amp; FIREWALL SETTINGS\")\n        _ibtn(client_frame, \"\u25b6 Network Discovery  \u2192  Enable (Client)\",\n              C[\"btn_info\"], lambda: self._client_single_security(\"network_discovery\"),\n              \"Host PC ko network mein dhundh sake\")\n        _ibtn(client_frame, \"\u25b6 File &amp; Printer Sharing Rules  \u2192  ON (Client)\",\n              C[\"btn_info\"], lambda: self._client_single_security(\"fp_sharing_rules\"),\n              \"Windows Firewall F&amp;P rules enable\")\n        _ibtn(client_frame, \"\u25b6 Network Profile  \u2192  Private (Client)\",\n              C[\"btn_info\"], lambda: self._client_single_security(\"network_private\"),\n              \"Public profile pe sharing accessible nahi hoti\")\n        _ibtn(client_frame, \"\u25b6 SMB Client Signing  \u2192  Optional\",\n              C[\"btn_info\"], lambda: self._client_single_security(\"smb_sign_optional\"),\n              \"HKLM/.../LanmanWorkstation: RequireSecuritySignature=0\")\n        _ibtn(client_frame, \"\u25b6 Point &amp; Print  \u2192  No Warning / No Elevation\",\n              C[\"btn_info\"], lambda: self._client_single_security(\"point_print\"),\n              \"Driver install bina UAC prompt ke\")\n        _ibtn(client_frame, \"\u25b6 Windows Defender Firewall  \u2192  Private Network OFF\",\n              C[\"btn_info\"], lambda: self._client_single_security(\"fw_private_off\"),\n              \"Client pe private firewall temporarily off\")\n        _ibtn(client_frame, \"\u25b6 ICMPv4 Ping  \u2192  Allow (Client Firewall)\",\n              C[\"btn_info\"], lambda: self._client_single_security(\"allow_ping\"),\n              \"Host ko ping se dhundh sake\")\n        _ibtn(client_frame, \"\u2705 Saari Client Security Settings Ek Saath\",\n              C[\"btn_warn\"], self._client_security_fix,\n              \"Discovery + F&amp;P Rules + Private + SMB + PnP\")\n\n        # \u2500\u2500 CLIENT: REGISTRY \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(client_frame, \"\ud83d\udddd  REGISTRY CHANGES\")\n        _ibtn(client_frame, \"\u25b6 AllowInsecureGuestAuth = 1  (Guest share access)\",\n              C[\"btn_hw\"], lambda: self._client_single_reg(\"AllowInsecureGuestAuth\"),\n              \"HKLM/.../LanmanWorkstation/Parameters\")\n        _ibtn(client_frame, \"\u25b6 LimitBlankPasswordUse = 0  (Blank password connect)\",\n              C[\"btn_hw\"], lambda: self._client_single_reg(\"LimitBlankPasswordUse\"),\n              \"HKLM/.../Control/Lsa\")\n        _ibtn(client_frame, \"\u25b6 RequireSecuritySignature = 0  (SMB signing optional)\",\n              C[\"btn_hw\"], lambda: self._client_single_reg(\"RequireSecuritySignature\"),\n              \"HKLM/.../LanmanWorkstation/Parameters\")\n        _ibtn(client_frame, \"\u25b6 Point &amp; Print: NoWarningNoElevationOnInstall = 1\",\n              C[\"btn_hw\"], lambda: self._client_single_reg(\"PnP_NoWarning\"),\n              \"HKLM/SOFTWARE/Policies/.../PointAndPrint\")\n        _ibtn(client_frame, \"\u25b6 Point &amp; Print: UpdatePromptSettings = 2\",\n              C[\"btn_hw\"], lambda: self._client_single_reg(\"PnP_UpdatePrompt\"),\n              \"HKLM/SOFTWARE/Policies/.../PointAndPrint\")\n        _ibtn(client_frame, \"\u25b6 Point &amp; Print: RestrictDriverInstall = 0\",\n              C[\"btn_hw\"], lambda: self._client_single_reg(\"PnP_RestrictDriver\"),\n              \"HKLM/SOFTWARE/Policies/.../PointAndPrint\")\n        _ibtn(client_frame, \"\u2705 Saare Client Registry Changes Ek Saath\",\n              C[\"btn_warn\"], self._client_registry_fix,\n              \"GuestAuth + LimitBlank + SMB + Point&amp;Print\")\n\n        # \u2500\u2500 CLIENT: SERVICES \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(client_frame, \"\u2699\ufe0f  SERVICES \u2014 Start/Enable karo (Client)\")\n        _ibtn(client_frame, \"\u25b6 Print Spooler  \u2192  Auto + Start\",\n              C[\"accent2\"], lambda: self._host_single_svc(\"Spooler\"),\n              \"Client pe bhi spooler chahiye\")\n        _ibtn(client_frame, \"\u25b6 Workstation (LanmanWorkstation)  \u2192  Auto + Start\",\n              C[\"accent2\"], lambda: self._host_single_svc(\"LanmanWorkstation\"),\n              \"Network redirector \u2014 sharing ke liye zaroori\")\n        _ibtn(client_frame, \"\u25b6 TCP/IP NetBIOS Helper  \u2192  Auto + Start\",\n              C[\"accent2\"], lambda: self._host_single_svc(\"lmhosts\"),\n              \"NetBIOS naam resolution client side\")\n        _ibtn(client_frame, \"\u25b6 Function Discovery Provider Host  \u2192  Auto + Start\",\n              C[\"accent2\"], lambda: self._host_single_svc(\"fdPHost\"),\n              \"Network mein host PC dhundh sake\")\n        _ibtn(client_frame, \"\u25b6 SSDP Discovery  \u2192  Auto + Start\",\n              C[\"accent2\"], lambda: self._host_single_svc(\"SSDPSRV\"),\n              \"UPnP / network device discovery\")\n\n        # \u2500\u2500 CLIENT: CONNECT \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(client_frame, \"\ud83d\udda8  HOST SE CONNECT KARO\")\n        _ibtn(client_frame, \"\ud83d\udda8  Host ke Shared Printer se Connect Karo\",\n              C[\"accent\"], self._client_connect_printer,\n              \"Host IP + Share Name daal ke connect\")\n\n        # \u2500\u2500 CLIENT: ERROR 0x0000709 FIX \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(client_frame, \"\ud83d\udd34  ERROR 0x0000709 \u2014 Default Printer Cannot Be Set\")\n        _ibtn(client_frame, \"\ud83d\udd27 Auto-Fix Error 0x0000709  (CLIENT \u2014 Ek Click Mein)\",\n              C[\"error\"], self._fix_error_709_client,\n              \"Default printer set nahi ho raha \u2014 registry + spooler + UserSelectedDefault fix\")\n\n        # \u2500\u2500 CLIENT: ERROR 0x0000011b FIX \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(client_frame, \"\ud83d\udd34  ERROR 0x0000011b \u2014 Network Printer Connect Fail\")\n        _ibtn(client_frame, \"\ud83d\udd27 Auto-Fix Error 0x0000011b  (CLIENT \u2014 Ek Click Mein)\",\n              C[\"error\"], self._fix_error_11b_client,\n              \"Network printer connect nahi \u2014 RPC encryption + LanmanWorkstation fix\")\n\n        # \u2500\u2500 CLIENT: ONE-CLICK MEGA FIX \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(client_frame, \"\u26a1  MEGA AUTO-FIX \u2014 CLIENT KI SAARI SETTINGS EK SAATH\")\n        _ibtn(client_frame, \"\ud83d\ude80  CLIENT: SABKUCH AUTO-FIX  (Ports + Security + Registry + Services + 709 + 11b + Connect)\",\n              \"#FF6600\", self._client_mega_auto_fix,\n              \"Ek click mein CLIENT ka poora printer connect setup \u2014 seedha print karo\")\n        tk.Frame(client_frame, bg=C[\"bg\"], height=8).pack()\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # \ud83d\udcdd SHARING LOG \u2014 tab2 ke andar\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        share_log_outer = tk.Frame(tab2, bg=C[\"card\"])\n        share_log_outer.pack(fill=\"x\", padx=8, pady=(2,8))\n        tk.Label(share_log_outer, text=\"  \ud83d\udcdd Sharing Center Log\",\n                 font=FONTS[\"subhead\"], fg=C[\"accent4\"], bg=C[\"card\"]).pack(\n                 anchor=\"w\", padx=8, pady=(6,2))\n        self.sharing_log = self._scrolled_text(share_log_outer, height=6)\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # \ud83d\udd27 TAB 3 \u2014 ADVANCED ERROR FIX GUIDE (0x0000709 + 0x0000011b)\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        tab3 = tk.Frame(nb, bg=C[\"bg\"])\n        nb.add(tab3, text=\"  \ud83d\udd34  Error Fix Guide (709 &amp; 11b)  \")\n\n        # \u2500\u2500 Tab3 Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        t3_hdr = tk.Frame(tab3, bg=C[\"panel\"])\n        t3_hdr.pack(fill=\"x\")\n        tk.Label(t3_hdr, text=\"  \ud83d\udd34 Printer Error Fix Guide \u2014 0x0000709 &amp; 0x0000011b\",\n                 font=FONTS[\"heading\"], fg=C[\"error\"], bg=C[\"panel\"]).pack(side=\"left\", pady=8, padx=8)\n        tk.Label(t3_hdr,\n                 text=\"In-app auto-fix buttons + manual steps \u2014 dono tarike ek jagah\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"left\")\n\n        # \u2500\u2500 Tab3 Scrollable Canvas \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        t3_outer = tk.Frame(tab3, bg=C[\"bg\"])\n        t3_outer.pack(fill=\"both\", expand=True)\n        t3_canvas = tk.Canvas(t3_outer, bg=C[\"bg\"], highlightthickness=0)\n        t3_sb = ttk.Scrollbar(t3_outer, orient=\"vertical\", command=t3_canvas.yview)\n        t3_canvas.configure(yscrollcommand=t3_sb.set)\n        t3_sb.pack(side=\"right\", fill=\"y\")\n        t3_canvas.pack(side=\"left\", fill=\"both\", expand=True)\n        t3_body = tk.Frame(t3_canvas, bg=C[\"bg\"])\n        t3_win = t3_canvas.create_window((0,0), window=t3_body, anchor=\"nw\")\n        def _t3_resize(e):\n            t3_canvas.configure(scrollregion=t3_canvas.bbox(\"all\"))\n            t3_canvas.itemconfig(t3_win, width=t3_canvas.winfo_width())\n        t3_body.bind(\"\", _t3_resize)\n        def _t3_canvas_configure(e):\n            t3_canvas.itemconfig(t3_win, width=e.width)\n            t3_canvas.configure(scrollregion=t3_canvas.bbox(\"all\"))\n        t3_canvas.bind(\"\", _t3_canvas_configure)\n        self._bind_scoped_mousewheel(t3_body, t3_canvas)\n\n        # \u2500\u2500 Helper functions for Tab3 layout \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        def _t3_section(title, subtitle, color):\n            frm = tk.Frame(t3_body, bg=C[\"card\"], bd=0)\n            frm.pack(fill=\"x\", padx=12, pady=(8,0))\n            hdr = tk.Frame(frm, bg=color)\n            hdr.pack(fill=\"x\")\n            tk.Label(hdr, text=title, font=FONTS[\"subhead\"], fg=C[\"text\"],\n                     bg=color, anchor=\"w\").pack(anchor=\"w\", padx=12, pady=(8,2))\n            tk.Label(hdr, text=subtitle, font=FONTS[\"small\"], fg=C[\"text_dim\"],\n                     bg=color, anchor=\"w\").pack(anchor=\"w\", padx=12, pady=(0,6))\n            return frm\n\n        def _t3_step(parent, num, title, detail, cmd_text=\"\"):\n            \"\"\"Numbered step row with optional command display.\"\"\"\n            row = tk.Frame(parent, bg=C[\"card\"])\n            row.pack(fill=\"x\", padx=8, pady=3)\n            # Step number badge\n            badge = tk.Label(row, text=f\" {num} \", font=(\"Consolas\",10,\"bold\"),\n                             fg=C[\"bg\"], bg=C[\"accent4\"], padx=4, pady=2)\n            badge.pack(side=\"left\", padx=(6,8), pady=4, anchor=\"n\")\n            # Content\n            content = tk.Frame(row, bg=C[\"card\"])\n            content.pack(side=\"left\", fill=\"x\", expand=True, pady=4)\n            tk.Label(content, text=title, font=FONTS[\"body\"], fg=C[\"text\"],\n                     bg=C[\"card\"], anchor=\"w\").pack(anchor=\"w\")\n            if detail:\n                tk.Label(content, text=detail, font=FONTS[\"small\"], fg=C[\"text_dim\"],\n                         bg=C[\"card\"], anchor=\"w\", wraplength=700, justify=\"left\").pack(anchor=\"w\")\n            if cmd_text:\n                cmd_row = tk.Frame(content, bg=\"#0D0D1A\")\n                cmd_row.pack(fill=\"x\", pady=(3,0))\n                tk.Label(cmd_row, text=f\"  {cmd_text}\", font=(\"Consolas\",9),\n                         fg=C[\"accent2\"], bg=\"#0D0D1A\", anchor=\"w\").pack(side=\"left\", padx=4, pady=3)\n                def _copy(t=cmd_text):\n                    self.clipboard_clear()\n                    self.clipboard_append(t)\n                    messagebox.showinfo(\"Copied!\", f\"Copied:\\n{t}\", parent=self)\n                tk.Button(cmd_row, text=\"\ud83d\udccb Copy\", font=(\"Consolas\",8),\n                          bg=C[\"btn_chip\"], fg=C[\"text\"], bd=0, padx=6, pady=2,\n                          cursor=\"hand2\", command=_copy).pack(side=\"right\", padx=4)\n\n        def _t3_auto_btn(parent, text, color, cmd, note=\"\"):\n            row = tk.Frame(parent, bg=C[\"card\"])\n            row.pack(fill=\"x\", padx=8, pady=(4,2))\n            tk.Button(row, text=text, font=FONTS[\"body\"], bg=color, fg=C[\"text\"],\n                      bd=0, padx=14, pady=8, cursor=\"hand2\", anchor=\"w\",\n                      command=cmd).pack(side=\"left\")\n            if note:\n                tk.Label(row, text=note, font=FONTS[\"small\"], fg=C[\"text_dim\"],\n                         bg=C[\"card\"], anchor=\"w\").pack(side=\"left\", padx=10)\n\n        def _t3_divider(parent):\n            tk.Frame(parent, bg=C[\"border\"], height=1).pack(fill=\"x\", padx=12, pady=4)\n\n        def _t3_info_box(parent, text, bg=\"#1A1A2A\", fg=None):\n            fg = fg or C[\"accent4\"]\n            bx = tk.Frame(parent, bg=bg, bd=0)\n            bx.pack(fill=\"x\", padx=20, pady=(4,0))\n            tk.Label(bx, text=text, font=FONTS[\"small\"], fg=fg, bg=bg,\n                     anchor=\"w\", wraplength=820, justify=\"left\",\n                     padx=10, pady=8).pack(fill=\"x\")\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # SECTION 1 \u2014 QUICK DECISION (Kaunsa error hai?)\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        s0 = _t3_section(\"\ud83e\udd14  Pehle Pehchano \u2014 Kaunsa Error Hai?\",\n                         \"Error code dekho aur us section mein jaao\", \"#1A2A1A\")\n        _t3_info_box(s0,\n            \"0x0000709  \u2192  'Operation could not be completed. Cannot set default printer.'\\n\"\n            \"              Matlab: Windows ko default printer set karna nahi aa raha \u2014 mostly registry/spooler issue.\\n\\n\"\n            \"0x0000011b \u2192  'Windows cannot connect to the printer. Operation failed with error 0x0000011b.'\\n\"\n            \"              Matlab: Network/shared printer se connection nahi ho raha \u2014 mostly Windows Update (KB5005565) ne RPC strict kar diya.\",\n            bg=\"#0D1A0D\", fg=C[\"text\"])\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # SECTION 2 \u2014 ERROR 0x0000709 FULL GUIDE\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        s1 = _t3_section(\"\ud83d\udd34  Error 0x0000709 \u2014 Default Printer Cannot Be Set\",\n                         \"HOST aur CLIENT dono pe ye steps karo\", \"#2A1A1A\")\n\n        _t3_info_box(s1,\n            \"\u26a1 SABSE PEHLE \u2014 Neeche ka Auto-Fix button dabaao. Manually karne ki zaroorat nahi padegi.\",\n            bg=\"#1A0D0D\", fg=C[\"warning\"])\n\n        _t3_auto_btn(s1, \"\ud83d\udd27 AUTO-FIX 0x0000709 \u2014 HOST (Ek Click)\",  C[\"error\"],\n                     self._fix_error_709_host, \"\u2190 HOST PC pe run karo (jisme printer laga hai)\")\n        _t3_auto_btn(s1, \"\ud83d\udd27 AUTO-FIX 0x0000709 \u2014 CLIENT (Ek Click)\", C[\"error\"],\n                     self._fix_error_709_client, \"\u2190 CLIENT PC pe run karo (jo print karna chahta hai)\")\n\n        _t3_divider(s1)\n        tk.Label(s1, text=\"  \ud83d\udccb Manual Steps (agar auto-fix kaam na kare):\",\n                 font=FONTS[\"body\"], fg=C[\"accent4\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=10, pady=(6,2))\n\n        _t3_step(s1, \"1\", \"Group Policy se RPC Settings fix karo  (Windows Pro/Enterprise only)\",\n                 \"Windows Key + R \u2192 gpedit.msc \u2192 Computer Configuration \u2192 Administrative Templates \u2192 Printers\\n\"\n                 \"\u2192 'Configure RPC connection settings' \u2192 Enabled \u2192 Dropdown: 'RPC over named pipes' \u2192 Apply \u2192 OK\",\n                 \"gpedit.msc\")\n        _t3_auto_btn(s1,\n            \"\u2699 Auto-Fix: gpedit.msc Setting  \u2014 Configure RPC \u2192 Named Pipes (Windows Pro/Enterprise)\",\n            C[\"btn_hw\"], self._auto_gpedit_rpc_709,\n            \"\u2190 Ek click: Group Policy RPC setting auto set\")\n\n        _t3_step(s1, \"2\", \"Registry se RpcAuthnLevelPrivacyEnabled = 0 set karo  (Windows Home ke liye bhi kaam karta hai)\",\n                 \"Windows Key + R \u2192 regedit \u2192 HKEY_LOCAL_MACHINE\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\\n\"\n                 \"\u2192 Right-click \u2192 New \u2192 DWORD (32-bit) \u2192 Name: RpcAuthnLevelPrivacyEnabled \u2192 Value: 0\",\n                 r\"HKLM\\SYSTEM\\CurrentControlSet\\Control\\Print  \u2192  RpcAuthnLevelPrivacyEnabled = 0\")\n        _t3_auto_btn(s1,\n            \"\ud83d\udddd Auto-Fix: Registry Setting  \u2014 RpcAuthnLevelPrivacyEnabled = 0  (Home + Pro dono)\",\n            C[\"btn_hw\"], self._auto_reg_rpcauth_0,\n            \"\u2190 Ek click: Registry me value seedha set ho jaayegi\")\n\n        _t3_step(s1, \"3\", \"LegacyDefaultPrinterMode = 1 set karo  (Windows auto printer manage feature band karo)\",\n                 \"HKEY_CURRENT_USER\\\\SOFTWARE\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\Windows\\n\"\n                 \"\u2192 New DWORD \u2192 LegacyDefaultPrinterMode \u2192 Value: 1\",\n                 r\"HKCU\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows  \u2192  LegacyDefaultPrinterMode = 1\")\n        _t3_auto_btn(s1,\n            \"\ud83d\udddd Auto-Fix: Registry Setting  \u2014 LegacyDefaultPrinterMode = 1  (Windows auto-manage OFF)\",\n            C[\"btn_hw\"], self._auto_reg_legacy_default,\n            \"\u2190 Ek click: HKCU registry value auto set\")\n\n        _t3_step(s1, \"4\", \"Print Spooler Service Restart karo\",\n                 \"Windows Key + R \u2192 services.msc \u2192 Print Spooler \u2192 Right-click \u2192 Restart\",\n                 \"services.msc\")\n        _t3_auto_btn(s1,\n            \"\ud83d\udd01 Auto-Fix: Print Spooler Restart\",\n            C[\"btn_chip\"], self._printer_reset_spooler,\n            \"\u2190 Ek click: Spooler stop + start\")\n\n        _t3_step(s1, \"5\", \"UserSelectedDefault registry value delete karo  (stale default clear)\",\n                 \"HKEY_CURRENT_USER\\\\SOFTWARE\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\Windows\\n\"\n                 \"\u2192 'UserSelectedDefault' value ko delete karo (agar hai to)\", \"\")\n        _t3_auto_btn(s1,\n            \"\ud83d\udddd Auto-Fix: Registry Setting  \u2014 UserSelectedDefault Delete  (stale default clear)\",\n            C[\"btn_hw\"], self._auto_reg_delete_userselected,\n            \"\u2190 Ek click: Purana default printer entry hata do\")\n\n        _t3_step(s1, \"6\", \"Reboot karo\",\n                 \"Saari changes ke baad computer restart karo \u2014 registry changes tabhi full effect mein aati hain.\", \"\")\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # SECTION 3 \u2014 ERROR 0x0000011b FULL GUIDE\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        s2 = _t3_section(\"\ud83d\udd34  Error 0x0000011b \u2014 Network Printer Cannot Connect\",\n                         \"Ye error Windows Update KB5005565/KB5005566 ke baad aata hai \u2014 HOST + CLIENT dono fix karo\",\n                         \"#2A1A2A\")\n\n        _t3_info_box(s2,\n            \"Root Cause: Microsoft ne October 2021 update (KB5005565) mein RPC encryption strict kar di.\\n\"\n            \"Fix: RpcAuthnLevelPrivacyEnabled = 0 dono PCs pe \u2014 HOST aur CLIENT dono pe karna ZAROORI hai.\",\n            bg=\"#1A0D1A\", fg=C[\"warning\"])\n\n        _t3_auto_btn(s2, \"\ud83d\udd27 AUTO-FIX 0x0000011b \u2014 HOST (Ek Click)\",  C[\"error\"],\n                     self._fix_error_11b_host, \"\u2190 HOST PC pe pehle run karo\")\n        _t3_auto_btn(s2, \"\ud83d\udd27 AUTO-FIX 0x0000011b \u2014 CLIENT (Ek Click)\", C[\"error\"],\n                     self._fix_error_11b_client, \"\u2190 CLIENT PC pe run karo\")\n\n        _t3_divider(s2)\n        tk.Label(s2, text=\"  \ud83d\udccb Manual Steps (agar auto-fix kaam na kare):\",\n                 font=FONTS[\"body\"], fg=C[\"accent4\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=10, pady=(6,2))\n\n        _t3_step(s2, \"1\", \"Group Policy se RPC Settings fix karo \u2014 DONO PCs pe  (Windows Pro/Enterprise)\",\n                 \"Windows Key + R \u2192 gpedit.msc \u2192 Computer Configuration \u2192 Administrative Templates \u2192 Printers\\n\"\n                 \"\u2192 'Configure RPC connection settings' \u2192 Enabled \u2192 'RPC over named pipes' \u2192 Apply \u2192 OK\\n\"\n                 \"\u26a0 DONO COMPUTERS pe \u2014 HOST aur CLIENT dono pe ye setting karo\",\n                 \"gpedit.msc\")\n        _t3_auto_btn(s2,\n            \"\u2699 Auto-Fix: gpedit.msc Setting  \u2014 Configure RPC \u2192 Named Pipes  (Windows Pro/Enterprise)\",\n            C[\"btn_hw\"], self._auto_gpedit_rpc_11b,\n            \"\u2190 Ek click: Group Policy RPC + Printer settings auto set (dono computers pe alag-alag chalao)\")\n\n        _t3_step(s2, \"2\", \"Registry mein RpcAuthnLevelPrivacyEnabled = 0 set karo \u2014 DONO PCs pe\",\n                 \"Ye Windows Home ke liye bhi kaam karta hai (jahan gpedit nahi hota)\\n\"\n                 \"Path: HKEY_LOCAL_MACHINE\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\\n\"\n                 \"\u2192 New DWORD (32-bit) \u2192 Name: RpcAuthnLevelPrivacyEnabled \u2192 Value data: 0 \u2192 OK\",\n                 r\"reg add HKLM\\SYSTEM\\CurrentControlSet\\Control\\Print /v RpcAuthnLevelPrivacyEnabled /t REG_DWORD /d 0 /f\")\n        _t3_auto_btn(s2,\n            \"\ud83d\udddd Auto-Fix: Registry Setting  \u2014 RpcAuthnLevelPrivacyEnabled = 0  (Home + Pro dono)\",\n            C[\"btn_hw\"], self._auto_reg_rpcauth_0,\n            \"\u2190 Ek click: Registry me value seedha set \u2014 DONO PCs pe alag-alag chalao\")\n\n        _t3_step(s2, \"3\", \"Windows Credentials mein Password save karo  (Client PC pe)\",\n                 \"Client PC pe: Windows Search \u2192 Credential Manager \u2192 Windows Credentials\\n\"\n                 \"\u2192 'Add a Windows credential'\\n\"\n                 \"\u2192 Internet/network address: HOST PC ka naam ya IP (jaise: \\\\\\\\Main-PC ya 192.168.1.15)\\n\"\n                 \"\u2192 Username + Password: HOST PC ka login credentials \u2192 OK\",\n                 \"control /name Microsoft.CredentialManager\")\n        _t3_step(s2, \"4\", \"Print Spooler Restart karo \u2014 DONO PCs pe\",\n                 \"Windows Key + R \u2192 services.msc \u2192 Print Spooler \u2192 Right-click \u2192 Restart\\n\"\n                 \"Ya neeche ka button dabaao:\",\n                 \"net stop spooler &amp;&amp; net start spooler\")\n        _t3_auto_btn(s2,\n            \"\ud83d\udd01 Auto-Fix: Print Spooler Restart\",\n            C[\"btn_chip\"], self._printer_reset_spooler,\n            \"\u2190 Ek click: Spooler stop + start\")\n\n        _t3_step(s2, \"5\", \"DONO Computers Restart karo\",\n                 \"Registry changes full effect tab aati hain \u2014 restart zaroori hai.\", \"\")\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # SECTION 4 \u2014 CREDENTIAL MANAGER (Windows Credentials Save)\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        s3 = _t3_section(\"\ud83d\udd11  Windows Credentials Manager \u2014 Auto Save / Open\",\n                         \"PC-to-PC sharing mein authentication fail hoti hai \u2014 yahan credentials save karo\",\n                         \"#1A1A2A\")\n\n        _t3_info_box(s3,\n            \"Jab HOST PC password-protected ho aur CLIENT bina password ke connect karne ki koshish kare\\n\"\n            \"to error aata hai. Solution: CLIENT pe HOST ke credentials Credential Manager mein save karo.\",\n            bg=\"#0D0D1A\", fg=C[\"text_dim\"])\n\n        cred_frame = tk.Frame(s3, bg=C[\"card\"])\n        cred_frame.pack(fill=\"x\", padx=8, pady=8)\n        cred_cols = tk.Frame(cred_frame, bg=C[\"card\"])\n        cred_cols.pack(fill=\"x\", padx=4)\n\n        # Input fields for credential manager\n        tk.Label(cred_cols, text=\"  HOST PC ka IP / Name:\", font=FONTS[\"body\"],\n                 fg=C[\"text\"], bg=C[\"card\"]).grid(row=0, column=0, sticky=\"w\", padx=6, pady=4)\n        self._cred_host_var = tk.StringVar(value=\"192.168.1.x  ya  PC-Name\")\n        cred_host_e = tk.Entry(cred_cols, textvariable=self._cred_host_var,\n                               font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"],\n                               insertbackground=C[\"text\"], relief=\"flat\", bd=4, width=30)\n        cred_host_e.grid(row=0, column=1, padx=6, pady=4)\n        cred_host_e.bind(\"\",\n            lambda e: cred_host_e.delete(0,\"end\") if \"ya\" in cred_host_e.get() or \"x\" in cred_host_e.get() else None)\n\n        tk.Label(cred_cols, text=\"  Username:\", font=FONTS[\"body\"],\n                 fg=C[\"text\"], bg=C[\"card\"]).grid(row=1, column=0, sticky=\"w\", padx=6, pady=4)\n        self._cred_user_var = tk.StringVar(value=\"\")\n        tk.Entry(cred_cols, textvariable=self._cred_user_var, font=FONTS[\"body\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"],\n                 relief=\"flat\", bd=4, width=30).grid(row=1, column=1, padx=6, pady=4)\n\n        tk.Label(cred_cols, text=\"  Password:\", font=FONTS[\"body\"],\n                 fg=C[\"text\"], bg=C[\"card\"]).grid(row=2, column=0, sticky=\"w\", padx=6, pady=4)\n        self._cred_pwd_var = tk.StringVar(value=\"\")\n        tk.Entry(cred_cols, textvariable=self._cred_pwd_var, font=FONTS[\"body\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"],\n                 relief=\"flat\", bd=4, width=30, show=\"*\").grid(row=2, column=1, padx=6, pady=4)\n\n        cred_btn_row = tk.Frame(cred_frame, bg=C[\"card\"])\n        cred_btn_row.pack(fill=\"x\", padx=8, pady=(4,8))\n\n        def _auto_save_cred():\n            host = self._cred_host_var.get().strip()\n            user = self._cred_user_var.get().strip()\n            pwd  = self._cred_pwd_var.get().strip()\n            if not host or \"ya\" in host or \"x\" in host:\n                messagebox.showwarning(\"Host Missing\", \"HOST PC ka naam ya IP dalo.\")\n                return\n            if not user:\n                messagebox.showwarning(\"Username Missing\", \"Username dalo.\")\n                return\n            # Build cmdkey command\n            unc = host if host.startswith(\"\\\\\\\\\") else f\"\\\\\\\\{host}\"\n            cmd = f'cmdkey /add:{unc} /user:{user} /pass:{pwd if pwd else \"\"}'\n            out, rc = self._run_cmd(cmd, timeout=10)\n            if rc == 0:\n                self._sharing_log(f\"\u2705 Credential saved for {unc} (user: {user})\", C[\"success\"])\n                messagebox.showinfo(\"\u2705 Done!\", f\"Credential saved!\\nHost: {unc}\\nUser: {user}\\n\\nAb printer connect karo.\")\n            else:\n                self._sharing_log(f\"\u26a0 cmdkey failed rc={rc}: {out}\", C[\"warning\"])\n                messagebox.showerror(\"Error\", f\"Credential save nahi hua:\\n{out}\")\n\n        def _open_cred_manager():\n            self._run_cmd(\"control /name Microsoft.CredentialManager\")\n            self._sharing_log(\"\u2705 Credential Manager khola gaya.\", C[\"success\"])\n\n        def _list_creds():\n            out, _ = self._run_cmd(\"cmdkey /list\", timeout=10)\n            messagebox.showinfo(\"Saved Credentials\", out or \"Koi saved credential nahi mila.\")\n\n        def _delete_cred():\n            host = self._cred_host_var.get().strip()\n            if not host or \"ya\" in host:\n                messagebox.showwarning(\"\", \"Pehle HOST ka naam/IP dalo.\")\n                return\n            unc = host if host.startswith(\"\\\\\\\\\") else f\"\\\\\\\\{host}\"\n            out, rc = self._run_cmd(f'cmdkey /delete:{unc}', timeout=10)\n            msg = f\"\u2705 Credential deleted: {unc}\" if rc == 0 else f\"\u26a0 Delete failed: {out}\"\n            self._sharing_log(msg, C[\"success\"] if rc == 0 else C[\"warning\"])\n            messagebox.showinfo(\"Result\", msg)\n\n        tk.Button(cred_btn_row, text=\"\ud83d\udcbe Auto-Save Credential (cmdkey)\", font=FONTS[\"body\"],\n                  bg=C[\"accent\"], fg=C[\"bg\"], bd=0, padx=12, pady=7, cursor=\"hand2\",\n                  command=_auto_save_cred).pack(side=\"left\", padx=(0,6))\n        tk.Button(cred_btn_row, text=\"\ud83d\udcc2 Open Credential Manager\", font=FONTS[\"body\"],\n                  bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=10, pady=7, cursor=\"hand2\",\n                  command=_open_cred_manager).pack(side=\"left\", padx=(0,6))\n        tk.Button(cred_btn_row, text=\"\ud83d\udccb List Credentials\", font=FONTS[\"body\"],\n                  bg=C[\"btn_chip\"], fg=C[\"text\"], bd=0, padx=10, pady=7, cursor=\"hand2\",\n                  command=_list_creds).pack(side=\"left\", padx=(0,6))\n        tk.Button(cred_btn_row, text=\"\ud83d\uddd1 Delete Credential\", font=FONTS[\"body\"],\n                  bg=C[\"error\"], fg=C[\"text\"], bd=0, padx=10, pady=7, cursor=\"hand2\",\n                  command=_delete_cred).pack(side=\"left\")\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # SECTION 5 \u2014 QUICK ACTIONS (all-in-one shortcuts)\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        s4 = _t3_section(\"\u26a1  Quick Actions \u2014 Ek Click Tools\",\n                         \"Frequently needed tools seedha yahan se\",\n                         \"#1A2A2A\")\n\n        def _t3_quick(parent, label, cmd_str, note=\"\"):\n            row = tk.Frame(parent, bg=C[\"card\"])\n            row.pack(fill=\"x\", padx=8, pady=2)\n            def _run():\n                self._run_cmd(cmd_str, timeout=10)\n                self._sharing_log(f\"\u25b6 Ran: {cmd_str}\", C[\"text_dim\"])\n            tk.Button(row, text=label, font=FONTS[\"body\"],\n                      bg=C[\"btn_hw\"], fg=C[\"text\"], bd=0, padx=12, pady=6,\n                      cursor=\"hand2\", anchor=\"w\", command=_run).pack(side=\"left\", fill=\"x\", expand=True)\n            if note:\n                tk.Label(row, text=note, font=(\"Consolas\",8), fg=C[\"text_dim\"],\n                         bg=C[\"card\"]).pack(side=\"left\", padx=6)\n\n        _t3_quick(s4, \"\ud83d\udd01 Spooler Restart\",\n                  \"net stop spooler /y &amp; net start spooler\",\n                  \"Print queue hang fix\")\n        _t3_quick(s4, \"\ud83d\uddc2 Open Printers &amp; Scanners\",\n                  \"control printers\",\n                  \"Windows printers settings\")\n        _t3_quick(s4, \"\ud83d\udd11 Open Credential Manager\",\n                  \"control /name Microsoft.CredentialManager\",\n                  \"Saved network passwords\")\n        _t3_quick(s4, \"\u2699 Open Group Policy Editor\",\n                  \"gpedit.msc\",\n                  \"RPC settings (Pro/Enterprise only)\")\n        _t3_quick(s4, \"\ud83d\udcdd Open Registry Editor\",\n                  \"regedit\",\n                  \"Manual registry changes\")\n        _t3_quick(s4, \"\ud83d\udd27 Open Services\",\n                  \"services.msc\",\n                  \"Start/Stop/Restart services\")\n        _t3_quick(s4, \"\ud83c\udf10 Open Network &amp; Sharing Center\",\n                  \"control.exe /name Microsoft.NetworkAndSharingCenter\",\n                  \"Network profile + sharing settings\")\n        _t3_quick(s4, \"\ud83d\udda5 Open Computer Name / Workgroup Settings\",\n                  \"SystemPropertiesComputerName.exe\",\n                  \"Workgroup mismatch fix\")\n        _t3_quick(s4, \"\ud83d\udce1 IPConfig \u2014 IP Address Check\",\n                  \"cmd /k ipconfig /all\",\n                  \"Apna IP janno\")\n        _t3_quick(s4, \"\ud83d\udd0d SFC Scannow \u2014 System File Check\",\n                  \"cmd /k sfc /scannow\",\n                  \"Corrupted Windows files repair\")\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # SECTION 6 \u2014 DECISION TREE (Home vs Pro, IP vs Name)\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        s5 = _t3_section(\"\ud83d\uddfa  Windows Edition &amp; Connection Type \u2014 Kya Use Karo?\",\n                         \"Aapka Windows version aur connection method fix decide karta hai\",\n                         \"#1A2A3A\")\n\n        _t3_info_box(s5,\n            \"Windows HOME (jaise HP/Dell pe usually hota hai)\\n\"\n            \"  \u2192 gpedit.msc NAHI khulega\\n\"\n            \"  \u2192 Registry method use karo: RpcAuthnLevelPrivacyEnabled = 0\\n\"\n            \"  \u2192 Ya neeche Auto-Fix button seedha kaam karega\\n\\n\"\n            \"Windows PRO / ENTERPRISE (office machines usually)\\n\"\n            \"  \u2192 gpedit.msc bhi use kar sakte ho (Group Policy method)\\n\"\n            \"  \u2192 Registry method bhi kaam karta hai\\n\\n\"\n            \"IP Address se connect karna  (jaise \\\\\\\\192.168.1.15\\\\ShareName)\\n\"\n            \"  \u2192 Zyada reliable \u2014 naam resolution ki zaroorat nahi\\n\"\n            \"  \u2192 Credential Manager mein IP save karo\\n\\n\"\n            \"PC Name se connect karna  (jaise \\\\\\\\OFFICPC\\\\ShareName)\\n\"\n            \"  \u2192 NetBIOS naam resolution chahiye (lmhosts service)\\n\"\n            \"  \u2192 Agar naam se nahi ho raha to IP se try karo\",\n            bg=\"#0D1A2A\", fg=C[\"text\"])\n\n        # Windows Edition Check Button\n        def _check_win_edition():\n            out, _ = self._run_cmd(\n                'powershell -Command \"(Get-WmiObject -Class Win32_OperatingSystem).Caption\"',\n                timeout=10)\n            edition = out.strip() or \"Unknown\"\n            is_home = \"home\" in edition.lower()\n            msg = (\n                f\"Windows Edition: {edition}\\n\\n\"\n                + (\"\u26a0 HOME edition hai \u2014 gpedit.msc nahi khulega.\\n\"\n                   \"   Registry method ya Auto-Fix button use karo.\"\n                   if is_home else\n                   \"\u2705 Pro/Enterprise edition hai \u2014 gpedit.msc available hai.\\n\"\n                   \"   Group Policy ya Registry dono methods kaam karenge.\")\n            )\n            messagebox.showinfo(\"Windows Edition Check\", msg)\n            self._sharing_log(f\"\u2139 Windows: {edition}\", C[\"text_dim\"])\n\n        btn_row_s5 = tk.Frame(s5, bg=C[\"card\"])\n        btn_row_s5.pack(fill=\"x\", padx=8, pady=6)\n        tk.Button(btn_row_s5, text=\"\ud83d\udd0d Check Windows Edition\", font=FONTS[\"body\"],\n                  bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=14, pady=7, cursor=\"hand2\",\n                  command=_check_win_edition).pack(side=\"left\", padx=(0,8))\n        tk.Button(btn_row_s5, text=\"\ud83d\ude80 HOST Mega Auto-Fix\", font=FONTS[\"body\"],\n                  bg=\"#FF6600\", fg=C[\"text\"], bd=0, padx=14, pady=7, cursor=\"hand2\",\n                  command=self._host_mega_auto_fix).pack(side=\"left\", padx=(0,8))\n        tk.Button(btn_row_s5, text=\"\ud83d\ude80 CLIENT Mega Auto-Fix\", font=FONTS[\"body\"],\n                  bg=\"#FF6600\", fg=C[\"text\"], bd=0, padx=14, pady=7, cursor=\"hand2\",\n                  command=self._client_mega_auto_fix).pack(side=\"left\")\n\n        tk.Frame(t3_body, bg=C[\"bg\"], height=20).pack()  # bottom padding\n\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # \ud83d\udd34 TAB 4 \u2014 ENTERPRISE PRINTER RECOVERY CENTER\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        tab4 = tk.Frame(nb, bg=C[\"bg\"])\n        nb.add(tab4, text=\"  \ud83d\udd34  Network Printer Recovery  \")\n\n        # \u2500\u2500 Tab4 Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        t4_hdr = tk.Frame(tab4, bg=\"#1A0A0A\")\n        t4_hdr.pack(fill=\"x\")\n        tk.Label(t4_hdr, text=\"  \ud83d\udd34 Enterprise Network Printer Recovery Center\",\n                 font=FONTS[\"subhead\"], fg=\"#FF4444\", bg=\"#1A0A0A\").pack(side=\"left\", pady=4, padx=8)\n        tk.Label(t4_hdr,\n                 text=\"\\\"Windows Couldn't connect to the printer\\\" \u2014 Auto Diagnose &amp; Repair\",\n                 font=FONTS[\"xsmall\"], fg=C[\"text_dim\"], bg=\"#1A0A0A\").pack(side=\"left\", pady=4)\n\n        # \u2500\u2500 FULL AUTO FIX MEGA BUTTON \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        mega_frame = tk.Frame(tab4, bg=\"#2A0A0A\", pady=2)\n        mega_frame.pack(fill=\"x\", padx=8, pady=(3, 2))\n        tk.Label(mega_frame,\n                 text=\"  \u26a1 ONE-CLICK ENTERPRISE RECOVERY \u2014 Diagnose + Repair Everything Automatically\",\n                 font=FONTS[\"xsmall\"], fg=\"#FF9800\", bg=\"#2A0A0A\").pack(anchor=\"w\", padx=8, pady=(2,1))\n        self._epr_full_auto_btn = tk.Button(\n            mega_frame,\n            text=\"\ud83d\ude80  FULL AUTO FIX  \u2014  \\\"Windows Couldn't Connect to Printer\\\"  (All 18 Steps)\",\n            font=(\"Segoe UI\", 10, \"bold\"),\n            bg=\"#C62828\", fg=\"#FFFFFF\",\n            bd=0, padx=12, pady=6,\n            cursor=\"hand2\",\n            command=self._epr_full_auto_fix,\n            activebackground=\"#B71C1C\",\n            activeforeground=\"#FFFFFF\",\n            relief=\"flat\"\n        )\n        self._epr_full_auto_btn.pack(fill=\"x\", padx=8, pady=(1, 3))\n\n        # \u2500\u2500 Progress &amp; Status Bar \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        prog_frame = tk.Frame(tab4, bg=C[\"card\"])\n        prog_frame.pack(fill=\"x\", padx=8, pady=(0, 2))\n        prog_inner = tk.Frame(prog_frame, bg=C[\"card\"])\n        prog_inner.pack(fill=\"x\", padx=8, pady=2)\n        tk.Label(prog_inner, text=\"Status:\", font=FONTS[\"small\"],\n                 fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self.epr_status_lbl = tk.Label(prog_inner, text=\"Ready \u2014 Click FULL AUTO FIX to begin\",\n                                        font=FONTS[\"small\"], fg=C[\"accent4\"], bg=C[\"card\"])\n        self.epr_status_lbl.pack(side=\"left\", padx=6)\n        self.epr_progress = ttk.Progressbar(prog_frame, mode=\"indeterminate\", length=200)\n        self.epr_progress.pack(fill=\"x\", padx=8, pady=(0, 3))\n\n        # \u2500\u2500 Main body: 3-column layout \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        t4_body_outer = tk.Frame(tab4, bg=C[\"bg\"])\n        t4_body_outer.pack(fill=\"both\", expand=True, padx=8, pady=(0, 8))\n        t4_canvas = tk.Canvas(t4_body_outer, bg=C[\"bg\"], highlightthickness=0)\n        t4_vsb = ttk.Scrollbar(t4_body_outer, orient=\"vertical\", command=t4_canvas.yview)\n        t4_canvas.configure(yscrollcommand=t4_vsb.set)\n        t4_vsb.pack(side=\"right\", fill=\"y\")\n        t4_canvas.pack(side=\"left\", fill=\"both\", expand=True)\n        t4_body = tk.Frame(t4_canvas, bg=C[\"bg\"])\n        t4_win = t4_canvas.create_window((0, 0), window=t4_body, anchor=\"nw\")\n\n        def _t4_sc_resize(e):\n            t4_canvas.configure(scrollregion=t4_canvas.bbox(\"all\"))\n            t4_canvas.itemconfig(t4_win, width=t4_canvas.winfo_width())\n        t4_body.bind(\"\", _t4_sc_resize)\n        def _t4_canvas_configure(e):\n            t4_canvas.itemconfig(t4_win, width=e.width)\n            t4_canvas.configure(scrollregion=t4_canvas.bbox(\"all\"))\n        t4_canvas.bind(\"\", _t4_canvas_configure)\n        self._bind_scoped_mousewheel(t4_body, t4_canvas)\n\n        t4_body.columnconfigure(0, weight=1)\n        t4_body.columnconfigure(1, weight=1)\n        t4_body.columnconfigure(2, weight=1)\n\n        # \u2500\u2500 Helper functions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        def _t4_card(parent, title, color_hdr=\"#1A1A2E\"):\n            f = tk.Frame(parent, bg=C[\"card\"], bd=0)\n            h = tk.Frame(f, bg=color_hdr)\n            h.pack(fill=\"x\")\n            tk.Label(h, text=title, font=FONTS[\"subhead\"],\n                     fg=C[\"accent4\"], bg=color_hdr).pack(anchor=\"w\", padx=10, pady=6)\n            return f\n\n        def _t4_btn(parent, text, color, cmd, desc=\"\"):\n            row = tk.Frame(parent, bg=C[\"card\"])\n            row.pack(fill=\"x\", padx=6, pady=2)\n            tk.Button(row, text=text, font=FONTS[\"small\"],\n                      bg=color, fg=C[\"text\"], bd=0, padx=8, pady=5,\n                      cursor=\"hand2\", anchor=\"w\",\n                      command=cmd).pack(side=\"left\", fill=\"x\", expand=True)\n            if desc:\n                tk.Label(row, text=desc, font=(\"Consolas\", 8),\n                         fg=C[\"text_dim\"], bg=C[\"card\"],\n                         anchor=\"w\", wraplength=150).pack(side=\"left\", padx=(4, 2))\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # LEFT COLUMN \u2014 Connectivity &amp; Network\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        left_col = tk.Frame(t4_body, bg=C[\"bg\"])\n        left_col.grid(row=0, column=0, sticky=\"nsew\", padx=(0, 4), pady=4)\n\n        # \u2014 Tester / Validator Card \u2014\n        tester_card = _t4_card(left_col, \"\ud83d\udd0d  Printer Connection Tester\", \"#0D1B2A\")\n        tester_card.pack(fill=\"x\", pady=(0, 6))\n        tester_inner = tk.Frame(tester_card, bg=C[\"card\"])\n        tester_inner.pack(fill=\"x\", padx=8, pady=(4, 2))\n        tk.Label(tester_inner, text=\"Host IP / Name:\", font=FONTS[\"small\"],\n                 fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\")\n        self.epr_host_var = tk.StringVar(value=\"\")\n        tk.Entry(tester_inner, textvariable=self.epr_host_var,\n                 font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"],\n                 insertbackground=C[\"text\"], width=28).pack(fill=\"x\", pady=2)\n        tk.Label(tester_inner, text=\"Share Name:\", font=FONTS[\"small\"],\n                 fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(4, 0))\n        self.epr_share_var = tk.StringVar(value=\"\")\n        tk.Entry(tester_inner, textvariable=self.epr_share_var,\n                 font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"],\n                 insertbackground=C[\"text\"], width=28).pack(fill=\"x\", pady=2)\n        tk.Frame(tester_card, bg=C[\"border\"], height=1).pack(fill=\"x\", padx=8, pady=4)\n        _t4_btn(tester_card, \"\ud83d\udd0c  Ping Host PC\",           C[\"btn_chip\"], self._epr_ping_host,        \"ICMP ping test\")\n        _t4_btn(tester_card, \"\ud83d\uddc2  Test SMB Share Access\",  C[\"btn_chip\"], self._epr_test_smb,         \"\\\\\\\\host\\\\share reachability\")\n        _t4_btn(tester_card, \"\ud83d\udda8  Validate Printer Path\",  C[\"btn_chip\"], self._epr_validate_printer, \"UNC printer reachability\")\n        _t4_btn(tester_card, \"\ud83d\udd0c  Reconnect Shared Printer\", C[\"btn_info\"], self._epr_reconnect_shared, \"Auto reconnect + re-install\")\n        tk.Frame(tester_card, bg=C[\"bg\"], height=6).pack()\n\n        # \u2014 Network Share Validator \u2014\n        ns_card = _t4_card(left_col, \"\ud83c\udf10  Network Share Validator\", \"#0A1A1A\")\n        ns_card.pack(fill=\"x\", pady=(0, 6))\n        _t4_btn(ns_card, \"\ud83c\udf10  Network Share Validator\",    C[\"btn_info\"],  self._epr_net_share_validator, \"Validate share existence\")\n        _t4_btn(ns_card, \"\ud83d\udce1  Network Discovery Enable\",   C[\"btn_info\"],  self._epr_enable_netdiscovery, \"Private profile + FD services\")\n        _t4_btn(ns_card, \"\ud83d\udd25  Firewall Sharing Rules Fix\", C[\"btn_warn\"],  self._epr_firewall_fix,        \"F&amp;P sharing rules ON\")\n        tk.Frame(ns_card, bg=C[\"bg\"], height=6).pack()\n\n        # \u2014 Auto-Detection Status Area \u2014\n        det_card = _t4_card(left_col, \"\ud83d\udcca  Auto-Detection Status\", \"#1A2A0A\")\n        det_card.pack(fill=\"x\", pady=(0, 6))\n        self.epr_detect_log = self._scrolled_text(det_card, height=7)\n        _t4_btn(det_card, \"\ud83d\udd0d  Run Auto-Detection\",        C[\"btn_info\"],  self._epr_auto_detect, \"Diagnose root cause\")\n        tk.Frame(det_card, bg=C[\"bg\"], height=6).pack()\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # MIDDLE COLUMN \u2014 Repair Buttons\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        mid_col = tk.Frame(t4_body, bg=C[\"bg\"])\n        mid_col.grid(row=0, column=1, sticky=\"nsew\", padx=(4, 4), pady=4)\n\n        # \u2014 Spooler &amp; RPC \u2014\n        spool_card = _t4_card(mid_col, \"\u2699\ufe0f  Spooler &amp; RPC Repair\", \"#1A0A2E\")\n        spool_card.pack(fill=\"x\", pady=(0, 6))\n        _t4_btn(spool_card, \"\u26a1  Smart Spooler Recovery\",    C[\"btn_hw\"],    self._epr_smart_spooler,    \"Deep spooler + DLL repair\")\n        _t4_btn(spool_card, \"\ud83d\udd27  RPC + SMB Repair\",          C[\"btn_hw\"],    self._epr_rpc_smb_repair,   \"RpcAuthnLevel + SMB fix\")\n        _t4_btn(spool_card, \"\ud83d\uddd1  Printer Cache Cleaner\",      C[\"btn_danger\"], self._epr_cache_cleaner,   \"Corrupted mappings removal\")\n        _t4_btn(spool_card, \"\ud83d\udd04  Full Printer Reset\",         C[\"btn_danger\"], self._epr_full_reset,      \"Nuclear reset + reinstall\")\n        tk.Frame(spool_card, bg=C[\"bg\"], height=6).pack()\n\n        # \u2014 Permissions &amp; Drivers \u2014\n        perm_card = _t4_card(mid_col, \"\ud83d\udd11  Permissions &amp; Drivers\", \"#1A1A0A\")\n        perm_card.pack(fill=\"x\", pady=(0, 6))\n        _t4_btn(perm_card, \"\ud83d\udd11  Shared Printer Permission Repair\", C[\"btn_warn\"], self._epr_permission_repair, \"ACL + GPO permissions\")\n        _t4_btn(perm_card, \"\ud83d\udda8  Point &amp; Print Repair\",             C[\"btn_warn\"], self._epr_point_print_repair, \"NoWarning + restriction fix\")\n        _t4_btn(perm_card, \"\ud83d\udd27  Driver Compatibility Repair\",      C[\"btn_chip\"], self._epr_driver_compat,     \"x86/x64 mismatch fix\")\n        _t4_btn(perm_card, \"\ud83d\udce1  Canon Printer Compatibility Fix\",  C[\"btn_chip\"], self._epr_canon_fix,         \"CNUSB + Canon-specific fix\")\n        tk.Frame(perm_card, bg=C[\"bg\"], height=6).pack()\n\n        # \u2014 Error-Specific Fixes \u2014\n        err_card = _t4_card(mid_col, \"\ud83d\udd34  Error-Specific Repairs\", \"#2A0A0A\")\n        err_card.pack(fill=\"x\", pady=(0, 6))\n        for err_code, err_desc, err_fn in [\n            (\"0x0000011b\", \"RPC Encryption / KB5005565\",   self._epr_fix_11b),\n            (\"0x0000007c\", \"Printer Driver Corrupt\",        self._epr_fix_7c),\n            (\"0x00000709\", \"Default Printer Cannot Set\",    self._epr_fix_709),\n            (\"Access Denied\", \"Printer ACL / Auth Fail\",   self._epr_fix_access_denied),\n            (\"RPC Unavailable\", \"RPC Server Unavailable\",  self._epr_fix_rpc_unavail),\n            (\"Driver Missing\", \"Driver Not Found / Bad\",   self._epr_fix_driver_missing),\n            (\"Path Not Found\", \"Network Path Not Found\",   self._epr_fix_path_not_found),\n        ]:\n            row = tk.Frame(err_card, bg=C[\"card\"])\n            row.pack(fill=\"x\", padx=6, pady=2)\n            tk.Label(row, text=err_code, font=(\"Consolas\", 9, \"bold\"),\n                     fg=C[\"error\"], bg=C[\"card\"], width=14, anchor=\"w\").pack(side=\"left\", padx=(4, 0))\n            tk.Label(row, text=err_desc, font=FONTS[\"small\"],\n                     fg=C[\"text_dim\"], bg=C[\"card\"], anchor=\"w\").pack(side=\"left\", padx=(4, 4))\n            tk.Button(row, text=\"Fix\", font=FONTS[\"small\"],\n                      bg=C[\"btn_danger\"], fg=C[\"text\"], bd=0, padx=10, pady=3,\n                      cursor=\"hand2\", command=err_fn).pack(side=\"right\", padx=4)\n        tk.Frame(err_card, bg=C[\"bg\"], height=6).pack()\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # RIGHT COLUMN \u2014 Live Diagnostics + Repair Log + Summary\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        right_col = tk.Frame(t4_body, bg=C[\"bg\"])\n        right_col.grid(row=0, column=2, sticky=\"nsew\", padx=(4, 0), pady=4)\n\n        # \u2014 Live Diagnostics Panel \u2014\n        diag_card = _t4_card(right_col, \"\ud83d\udce1  Live Diagnostics Panel\", \"#0D2A1A\")\n        diag_card.pack(fill=\"x\", pady=(0, 4))\n        self.epr_diag_log = self._scrolled_text(diag_card, height=8)\n\n        # \u2014 Repair Log Viewer \u2014\n        replog_card = _t4_card(right_col, \"\ud83d\udcdd  Repair Log\", \"#2A1A0A\")\n        replog_card.pack(fill=\"x\", pady=(0, 4))\n        self.epr_repair_log = self._scrolled_text(replog_card, height=6)\n\n        # \u2014 Recovery Summary Viewer \u2014\n        summ_card = _t4_card(right_col, \"\ud83d\udccb  Recovery Summary\", \"#0A1A2A\")\n        summ_card.pack(fill=\"x\", pady=(0, 4))\n        self.epr_summary_log = self._scrolled_text(summ_card, height=4)\n\n        # \u2014 RPC Smart Switcher Panel \u2014\n        rpc_panel = tk.Frame(right_col, bg=\"#1E1A00\")\n        rpc_panel.pack(fill=\"x\", padx=0, pady=(0, 4))\n        hdr_rpc = tk.Frame(rpc_panel, bg=\"#2A2200\")\n        hdr_rpc.pack(fill=\"x\")\n        tk.Label(hdr_rpc, text=\"  \u26a1 Smart RPC Privacy Switcher\",\n                 font=FONTS[\"subhead\"], fg=\"#FFCC00\", bg=\"#2A2200\").pack(side=\"left\", padx=8, pady=6)\n        rpc_info = tk.Frame(rpc_panel, bg=\"#1E1A00\")\n        rpc_info.pack(fill=\"x\", padx=8, pady=4)\n        self.epr_rpc_status_lbl = tk.Label(rpc_info,\n            text=\"RpcAuthnLevelPrivacyEnabled: Checking...\",\n            font=FONTS[\"small\"], fg=C[\"warning\"], bg=\"#1E1A00\")\n        self.epr_rpc_status_lbl.pack(anchor=\"w\")\n        btn_rpc_row = tk.Frame(rpc_panel, bg=\"#1E1A00\")\n        btn_rpc_row.pack(fill=\"x\", padx=8, pady=(0, 6))\n        tk.Button(btn_rpc_row, text=\"\ud83d\udd0d Check RPC Setting\",\n                  font=FONTS[\"small\"], bg=C[\"btn_chip\"], fg=C[\"text\"],\n                  bd=0, padx=10, pady=5, cursor=\"hand2\",\n                  command=self._epr_check_rpc_setting).pack(side=\"left\", padx=(0, 6))\n        tk.Button(btn_rpc_row, text=\"\ud83d\udd27 Smart RPC Fix (Auto Validate + Rollback)\",\n                  font=FONTS[\"small\"], bg=C[\"btn_warn\"], fg=C[\"text\"],\n                  bd=0, padx=10, pady=5, cursor=\"hand2\",\n                  command=self._epr_smart_rpc_fix).pack(side=\"left\")\n        tk.Frame(right_col, bg=C[\"bg\"], height=90).pack(fill=\"x\")\n        self.after(250, lambda c=t4_canvas: c.configure(scrollregion=c.bbox(\"all\")))\n\n\n        return frame\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \u2699 AUTO-FIX: gpedit.msc RPC Setting \u2014 Error 709\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _auto_gpedit_rpc_709(self):\n        \"\"\"Group Policy: Configure RPC \u2192 Named Pipes (for 709 fix).\"\"\"\n        if not messagebox.askyesno(\"\u2699 Auto-Fix: gpedit RPC Setting (Error 709)\",\n                \"Ye setting Group Policy mein auto set hogi:\\n\\n\"\n                \"Path: Computer Config \u2192 Admin Templates \u2192 Printers\\n\"\n                \"Setting: Configure RPC connection settings\\n\"\n                \"Value: Enabled, Protocol: RPC over named pipes\\n\\n\"\n                \"\u26a0 Windows Pro/Enterprise pe hi kaam karta hai.\\n\"\n                \"Windows Home me bhi try karega \u2014 Registry fallback bhi chalega.\\n\\n\"\n                \"Continue karein?\"):\n            return\n        self._sharing_log(\"\u2699 [gpedit] RPC setting fix chal raha hai (Error 709)...\", C[\"accent4\"])\n        self._launch_job(\"gpedit_rpc_fix\", self._do_auto_gpedit_rpc)\n\n    def _auto_gpedit_rpc_11b(self):\n        \"\"\"Group Policy: Configure RPC \u2192 Named Pipes (for 11b fix).\"\"\"\n        if not messagebox.askyesno(\"\u2699 Auto-Fix: gpedit RPC Setting (Error 0x0000011b)\",\n                \"Ye setting Group Policy mein auto set hogi:\\n\\n\"\n                \"Path: Computer Config \u2192 Admin Templates \u2192 Printers\\n\"\n                \"Setting: Configure RPC connection settings\\n\"\n                \"Value: Enabled, Protocol: RPC over named pipes\\n\\n\"\n                \"\u26a0 DONO PCs pe alag-alag run karo \u2014 HOST aur CLIENT dono pe!\\n\"\n                \"Windows Home me bhi try karega \u2014 Registry fallback bhi chalega.\\n\\n\"\n                \"Continue karein?\"):\n            return\n        self._sharing_log(\"\u2699 [gpedit] RPC setting fix chal raha hai (Error 11b)...\", C[\"accent4\"])\n        self._launch_job(\"gpedit_rpc_fix\", self._do_auto_gpedit_rpc)\n\n    def _do_auto_gpedit_rpc(self):\n        \"\"\"\n        Internally Group Policy ki 'Configure RPC connection settings' wali setting\n        Registry ke through set karta hai \u2014 gpedit.msc open kiye bina.\n        HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Printers\\\\RPC\n        RpcUseNamedPipeProtocol = 1  (Named Pipes force karo)\n        ForceKerberosForRpc     = 0  (Kerberos RPC strict band)\n        RpcTcpPort              = 0  (TCP port: 0 = any)\n        AllowEncryptedPrinterRPC= 0  (Encrypted RPC: off)\n        \"\"\"\n        log = self._sharing_log\n        L = C\n        reg_path = r\"SOFTWARE\\Policies\\Microsoft\\Windows NT\\Printers\\RPC\"\n\n        log(\"  [gpedit-auto 1/4] RpcUseNamedPipeProtocol = 1 (Named Pipes)...\", L[\"accent4\"])\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE, reg_path,\n                          \"RpcUseNamedPipeProtocol\", 1, winreg.REG_DWORD)\n            log(\"  \u2705 RpcUseNamedPipeProtocol = 1\", L[\"success\"])\n        except Exception as e:\n            self._run_cmd(f'reg add \"HKLM\\\\{reg_path}\" /v RpcUseNamedPipeProtocol /t REG_DWORD /d 1 /f')\n            log(f\"  \u2705 RpcUseNamedPipeProtocol = 1 (reg cmd, {e})\", L[\"success\"])\n\n        log(\"  [gpedit-auto 2/4] ForceKerberosForRpc = 0 (Kerberos strict band)...\", L[\"accent4\"])\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE, reg_path,\n                          \"ForceKerberosForRpc\", 0, winreg.REG_DWORD)\n            log(\"  \u2705 ForceKerberosForRpc = 0\", L[\"success\"])\n        except Exception as e:\n            self._run_cmd(f'reg add \"HKLM\\\\{reg_path}\" /v ForceKerberosForRpc /t REG_DWORD /d 0 /f')\n            log(f\"  \u2705 ForceKerberosForRpc = 0 (reg cmd)\", L[\"success\"])\n\n        log(\"  [gpedit-auto 3/4] AllowEncryptedPrinterRPC = 0 (Encrypted RPC off)...\", L[\"accent4\"])\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE, reg_path,\n                          \"AllowEncryptedPrinterRPC\", 0, winreg.REG_DWORD)\n            log(\"  \u2705 AllowEncryptedPrinterRPC = 0\", L[\"success\"])\n        except Exception as e:\n            self._run_cmd(f'reg add \"HKLM\\\\{reg_path}\" /v AllowEncryptedPrinterRPC /t REG_DWORD /d 0 /f')\n            log(f\"  \u2705 AllowEncryptedPrinterRPC = 0 (reg cmd)\", L[\"success\"])\n\n        log(\"  [gpedit-auto 4/4] RpcAuthnLevelPrivacyEnabled = 0 (main fix)...\", L[\"accent4\"])\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                          r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                          \"RpcAuthnLevelPrivacyEnabled\", 0, winreg.REG_DWORD)\n            log(\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0\", L[\"success\"])\n        except Exception as e:\n            self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\" /v RpcAuthnLevelPrivacyEnabled /t REG_DWORD /d 0 /f')\n            log(f\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0 (reg cmd)\", L[\"success\"])\n\n        log(\"\u2705 gpedit RPC settings \u2014 auto apply ho gayi!\", L[\"success\"])\n        log(\"   \u25ba Computer restart karo for Group Policy to take full effect.\", L[\"text_dim\"])\n        self.after(0, lambda: messagebox.showinfo(\n            \"\u2705 gpedit Auto-Fix Done!\",\n            \"Group Policy RPC settings apply ho gayi:\\n\\n\"\n            \"  \u2705 RpcUseNamedPipeProtocol = 1  (Named Pipes)\\n\"\n            \"  \u2705 ForceKerberosForRpc     = 0\\n\"\n            \"  \u2705 AllowEncryptedPrinterRPC = 0\\n\"\n            \"  \u2705 RpcAuthnLevelPrivacyEnabled = 0\\n\\n\"\n            \"\u26a0 Agar dono PCs hain to DONO pe run karo.\\n\"\n            \"Computer restart karo for full effect.\"))\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \ud83d\udddd AUTO-FIX: Registry \u2014 RpcAuthnLevelPrivacyEnabled = 0\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _auto_reg_rpcauth_0(self):\n        \"\"\"Registry: HKLM\\\\...\\\\Control\\\\Print \u2192 RpcAuthnLevelPrivacyEnabled = 0\"\"\"\n        self._sharing_log(\"\ud83d\udddd [Registry] RpcAuthnLevelPrivacyEnabled = 0 set kar raha hoon...\", C[\"accent4\"])\n        def _r():\n            try:\n                self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                              r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                              \"RpcAuthnLevelPrivacyEnabled\", 0, winreg.REG_DWORD)\n                self._sharing_log(\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0  \u2190 DONE\", C[\"success\"])\n                self.after(0, lambda: messagebox.showinfo(\n                    \"\u2705 Registry Fix Done!\",\n                    \"Registry set ho gayi:\\n\\n\"\n                    \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\\n\"\n                    \"  RpcAuthnLevelPrivacyEnabled = 0\\n\\n\"\n                    \"\u26a0 DONO PCs pe alag-alag run karo (HOST + CLIENT).\\n\"\n                    \"Phir Spooler restart karo \u2014 button neeche hai.\"))\n            except Exception as e:\n                # cmd fallback\n                out, rc = self._run_cmd(\n                    'reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\" '\n                    '/v RpcAuthnLevelPrivacyEnabled /t REG_DWORD /d 0 /f')\n                if rc == 0:\n                    self._sharing_log(\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0 (reg cmd fallback)\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"\u2705 Done!\", \"Registry fix ho gayi!\\nSpooler restart karo.\"))\n                else:\n                    self._sharing_log(f\"  \u274c Registry set failed: {e} | rc={rc}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", f\"Registry set nahi hua:\\n{e}\\n\\nAdmin mode mein run karo.\"))\n        self._launch_job(\"auto_reg_rpcauth\", _r)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \ud83d\udddd AUTO-FIX: Registry \u2014 LegacyDefaultPrinterMode = 1\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _auto_reg_legacy_default(self):\n        \"\"\"Registry: HKCU\\\\...\\\\Windows \u2192 LegacyDefaultPrinterMode = 1\"\"\"\n        self._sharing_log(\"\ud83d\udddd [Registry] LegacyDefaultPrinterMode = 1 set kar raha hoon...\", C[\"accent4\"])\n        def _r():\n            try:\n                key = winreg.OpenKey(\n                    winreg.HKEY_CURRENT_USER,\n                    r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows\",\n                    0, winreg.KEY_SET_VALUE)\n                winreg.SetValueEx(key, \"LegacyDefaultPrinterMode\", 0, winreg.REG_DWORD, 1)\n                winreg.CloseKey(key)\n                self._sharing_log(\"  \u2705 LegacyDefaultPrinterMode = 1  \u2190 DONE\", C[\"success\"])\n                self.after(0, lambda: messagebox.showinfo(\n                    \"\u2705 Registry Fix Done!\",\n                    \"Registry set ho gayi:\\n\\n\"\n                    \"HKCU\\\\SOFTWARE\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\Windows\\n\"\n                    \"  LegacyDefaultPrinterMode = 1\\n\\n\"\n                    \"Windows ab printer default automatically change nahi karega.\\n\"\n                    \"Spooler restart karo \u2014 button neeche hai.\"))\n            except Exception as e:\n                out, rc = self._run_cmd(\n                    'reg add \"HKCU\\\\SOFTWARE\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\Windows\" '\n                    '/v LegacyDefaultPrinterMode /t REG_DWORD /d 1 /f')\n                if rc == 0:\n                    self._sharing_log(\"  \u2705 LegacyDefaultPrinterMode = 1 (reg cmd fallback)\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"\u2705 Done!\", \"Registry fix ho gayi!\"))\n                else:\n                    self._sharing_log(f\"  \u274c Failed: {e}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", f\"Registry set nahi hua:\\n{e}\"))\n        self._launch_job(\"auto_reg_legacy_default\", _r)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \ud83d\udddd AUTO-FIX: Registry \u2014 UserSelectedDefault DELETE\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _auto_reg_delete_userselected(self):\n        \"\"\"Registry: HKCU\\\\...\\\\Windows \u2192 Delete UserSelectedDefault\"\"\"\n        self._sharing_log(\"\ud83d\udddd [Registry] UserSelectedDefault delete kar raha hoon...\", C[\"accent4\"])\n        def _r():\n            try:\n                key = winreg.OpenKey(\n                    winreg.HKEY_CURRENT_USER,\n                    r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows\",\n                    0, winreg.KEY_SET_VALUE | winreg.KEY_READ)\n                try:\n                    winreg.DeleteValue(key, \"UserSelectedDefault\")\n                    self._sharing_log(\"  \u2705 UserSelectedDefault deleted \u2014 Windows fresh default set karega\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\n                        \"\u2705 Done!\",\n                        \"UserSelectedDefault registry value delete ho gayi!\\n\\n\"\n                        \"Windows ab apne aap fresh default printer set karega.\\n\"\n                        \"Spooler restart karo ya reboot karo.\"))\n                except FileNotFoundError:\n                    self._sharing_log(\"  \u2139 UserSelectedDefault nahi mili \u2014 already clean hai\", C[\"text_dim\"])\n                    self.after(0, lambda: messagebox.showinfo(\"\u2139 Info\",\n                        \"UserSelectedDefault value nahi mili.\\n\"\n                        \"Already clean hai \u2014 koi action zaruri nahi.\"))\n                winreg.CloseKey(key)\n            except Exception as e:\n                self._sharing_log(f\"  \u274c Delete failed: {e}\", C[\"error\"])\n                self.after(0, lambda: messagebox.showerror(\"Error\", f\"Delete nahi hua:\\n{e}\"))\n        self._launch_job(\"auto_reg_delete_userselected\", _r)\n\n    def _printer_detect(self):\n        self._set_status(\"Detecting printers...\", C[\"accent4\"])\n        self._printer_action_submit(\"printer_detect\", self._do_printer_detect)\n\n    def _do_printer_detect(self):\n        out, _ = self._run_cmd(\n            'powershell -Command \"Get-Printer | Select-Object Name,PrinterStatus,Default,JobCount | ConvertTo-Csv -NoTypeInformation\"',\n            timeout=15)\n        rows = []\n        counts = {\"total\":0,\"online\":0,\"offline\":0,\"default\":\"\u2014\"}\n        for line in out.splitlines()[1:]:\n            line = line.strip().replace('\"','')\n            parts = line.split(',')\n            if len(parts) &lt; 4:\n                continue\n            name    = parts[0].strip()\n            status  = parts[1].strip()\n            default = parts[2].strip()\n            jobs    = parts[3].strip()\n            if not name:\n                continue\n            is_online  = status.lower() in (\"normal\",\"0\",\"idle\")\n            is_default = default.lower() == \"true\"\n            status_txt = \"\ud83d\udfe2 Online\" if is_online else \"\ud83d\udd34 Offline\"\n            def_txt    = \"\u2705 Yes\" if is_default else \"\"\n            tag = \"default\" if is_default else (\"online\" if is_online else \"offline\")\n            rows.append(((name, status_txt, def_txt, jobs or \"0\"), tag,\n                         {\"name\":name,\"online\":is_online,\"default\":is_default}))\n            counts[\"total\"] += 1\n            if is_online:\n                counts[\"online\"] += 1\n            else:\n                counts[\"offline\"] += 1\n            if is_default:\n                counts[\"default\"] = name[:18]\n\n        self._printer_data = rows\n\n        def insert():\n            for i in self.printer_tree.get_children():\n                self.printer_tree.delete(i)\n            for row, tag, _ in rows:\n                self.printer_tree.insert(\"\",\"end\", values=row, tags=(tag,))\n            for k,v in counts.items():\n                if k in self.printer_stat_vars:\n                    self.printer_stat_vars[k].set(str(v))\n            self._set_status(f\"Found {counts['total']} printers \u2014 {counts['online']} online, {counts['offline']} offline\", C[\"success\"])\n            self._refresh_spooler_status()\n            self._append_log(self.printer_log, f\"\u2705 Scan complete \u2014 {counts['total']} printers detected\", C[\"success\"])\n        self.after(0, insert)\n\n    def _on_printer_select(self, event=None):\n        sel = self.printer_tree.selection()\n        if not sel or not self._printer_data:\n            return\n        idx = self.printer_tree.index(sel[0])\n        if idx &gt;= len(self._printer_data):\n            return\n        meta = self._printer_data[idx][2]\n        self._append_log(self.printer_log,\n            f\"\u2139 Selected: {meta['name']} \u2014 {'Online' if meta['online'] else 'OFFLINE'}{'  [DEFAULT]' if meta['default'] else ''}\",\n            C[\"accent2\"])\n\n    def _refresh_spooler_status(self):\n        out, _ = self._run_cmd('sc query Spooler', timeout=5)\n        if \"RUNNING\" in out:\n            self.spooler_status_lbl.config(text=\"\u2705 Running\", fg=C[\"success\"])\n        elif \"STOPPED\" in out:\n            self.spooler_status_lbl.config(text=\"\u274c STOPPED\", fg=C[\"error\"])\n        else:\n            self.spooler_status_lbl.config(text=\"\u26a0 Unknown\", fg=C[\"warning\"])\n\n    def _printer_reset_spooler(self):\n        self._printer_action_submit(\"printer_reset_spooler\", self._do_reset_spooler)\n\n    def _do_reset_spooler(self):\n        self._printer_log(\"\u2501\"*50, C[\"border\"])\n        self._printer_log(\"\ud83d\udd01 Spooler restart ho raha hai...\", C[\"accent4\"])\n        # Stop spooler\n        self._run_cmd('net stop spooler /y')\n        self._printer_log(\"  \u23f9 Spooler stopped\", C[\"warning\"])\n        # Also stop dependent services\n        self._run_cmd('net stop \"Print Spooler\" /y')\n        time.sleep(1)\n        # Start spooler\n        self._run_cmd('net start spooler')\n        self._printer_log(\"  \u25b6 Spooler started\", C[\"success\"])\n        # Verify\n        out, _ = self._run_cmd('sc query Spooler')\n        if \"RUNNING\" in out:\n            self._printer_log(\"\u2705 Spooler successfully restarted!\", C[\"success\"])\n        else:\n            self._printer_log(\"\u274c Spooler start nahi hua \u2014 Full Repair try karo.\", C[\"error\"])\n        self.after(0, self._refresh_spooler_status)\n\n    def _printer_clear_jobs(self):\n        if not messagebox.askyesno(\"Clear Print Jobs\",\n                \"Saare stuck print jobs delete ho jaayenge.\\n\"\n                \"Spooler restart hoga.\\nAage badhein?\"):\n            return\n        self._printer_action_submit(\"printer_clear_jobs\", self._do_clear_jobs)\n\n    def _do_clear_jobs(self):\n        self._printer_log(\"\u2501\"*50, C[\"border\"])\n        self._printer_log(\"\ud83d\uddd1 Print jobs clear ho rahe hain...\", C[\"accent4\"])\n        # Stop spooler\n        self._run_cmd('net stop spooler /y')\n        self._printer_log(\"  \u23f9 Spooler stopped\", C[\"warning\"])\n        time.sleep(1)\n        # Delete spool files\n        spool_dir = os.path.join(os.environ.get(\"SYSTEMROOT\",\"C:\\\\Windows\"),\n                                  \"System32\",\"spool\",\"PRINTERS\")\n        deleted = 0\n        if os.path.exists(spool_dir):\n            for f in Path(spool_dir).glob(\"*\"):\n                try:\n                    f.unlink()\n                    deleted += 1\n                except: pass\n        self._printer_log(f\"  \ud83d\uddd1 {deleted} spool files deleted from {spool_dir}\", C[\"warning\"])\n        # Restart spooler\n        self._run_cmd('net start spooler')\n        self._printer_log(\"  \u25b6 Spooler restarted\", C[\"success\"])\n        self._printer_log(\"\u2705 Print queue cleared! Ab print karo.\", C[\"success\"])\n        self.after(0, self._refresh_spooler_status)\n\n    def _printer_full_repair(self):\n        if not messagebox.askyesno(\"\ud83d\udd27 Full Printer Auto-Repair\",\n                \"Ye steps perform hoge:\\n\"\n                \"1. Spooler stop + restart\\n\"\n                \"2. Stuck jobs delete\\n\"\n                \"3. Spooler DLL re-register\\n\"\n                \"4. Firewall rules check\\n\"\n                \"5. Registry default path verify\\n\"\n                \"6. Spooler auto startup set\\n\\n\"\n                \"Aage badhein?\"):\n            return\n        self._printer_action_submit(\"printer_full_repair\", self._do_full_repair)\n\n    def _printer_driver_purge_flow(self):\n        sel = self.printer_tree.selection()\n        if not sel or not self._printer_data:\n            messagebox.showinfo(\"Select Printer\", \"Pehle printer select karo.\")\n            return\n        idx = self.printer_tree.index(sel[0])\n        if idx &gt;= len(self._printer_data):\n            return\n        name = self._printer_data[idx][2][\"name\"]\n        if not messagebox.askyesno(\"Driver Purge/Reinstall\",\n                                   f\"Selected printer:\\n{name}\\n\\n\"\n                                   \"Steps:\\n\"\n                                   \"1) Remove printer\\n\"\n                                   \"2) Remove printer driver\\n\"\n                                   \"3) pnputil cleanup (best-effort)\\n\\n\"\n                                   \"Proceed? (Admin recommended)\"):\n            return\n        self._printer_action_submit(\"printer_driver_purge\", self._do_printer_driver_purge, name)\n\n    def _do_printer_driver_purge(self, printer_name):\n        self._printer_log(\"\u2550\"*52, C[\"border\"])\n        self._printer_log(f\"\ud83e\uddf9 Driver purge starting for: {printer_name}\", C[\"accent4\"])\n        # Detect driver name\n        drv = \"\"\n        out, rc = self._run_cmd(\n            f'powershell -Command \"(Get-Printer -Name \\'{printer_name}\\' -ErrorAction SilentlyContinue).DriverName\"',\n            timeout=15\n        )\n        if rc == 0:\n            drv = (out or \"\").strip().splitlines()[-1].strip()\n        self._printer_log(f\"Driver detected: {drv if drv else 'Unknown'}\", C[\"text_dim\"])\n        # Remove printer\n        out2, rc2 = self._run_cmd(\n            f'powershell -Command \"Remove-Printer -Name \\'{printer_name}\\' -ErrorAction SilentlyContinue\"',\n            timeout=20\n        )\n        self._printer_log(\"\u2705 Printer removed\" if rc2 == 0 else f\"\u26a0 Remove printer rc={rc2}: {out2[:200]}\", C[\"success\"] if rc2 == 0 else C[\"warning\"])\n        # Remove driver\n        if drv:\n            out3, rc3 = self._run_cmd(\n                f'powershell -Command \"Remove-PrinterDriver -Name \\'{drv}\\' -ErrorAction SilentlyContinue\"',\n                timeout=25\n            )\n            self._printer_log(\"\u2705 Driver removed\" if rc3 == 0 else f\"\u26a0 Remove driver rc={rc3}: {out3[:200]}\", C[\"success\"] if rc3 == 0 else C[\"warning\"])\n        # pnputil cleanup (best-effort)\n        out4, rc4 = self._run_cmd('pnputil /enum-drivers', timeout=25)\n        if rc4 == 0 and drv:\n            self._printer_log(\"\u2139 pnputil listed drivers (manual cleanup if needed).\", C[\"text_dim\"])\n        self._printer_log(\"\u2705 Driver purge flow complete. Now reinstall printer driver and add printer again.\", C[\"success\"])\n        self.after(0, self._printer_detect)\n\n    def _do_full_repair(self):\n        self._printer_log(\"\u2550\"*52, C[\"border\"])\n        self._printer_log(\"  \ud83d\udd27 FULL PRINTER AUTO-REPAIR STARTING\", C[\"hw_accent\"])\n        self._printer_log(\"\u2550\"*52, C[\"border\"])\n\n        # Step 1 \u2014 Stop spooler\n        self._printer_log(\"\\n[1/6] Spooler band kar raha hoon...\", C[\"accent4\"])\n        try:\n            self._service_config_checked(\"Spooler\", \"auto\", \"Spooler startup=auto\", self.printer_log)\n        except Exception:\n            pass\n        try:\n            self._service_stop_checked(\"Spooler\", \"Print Spooler\", self.printer_log)\n        except Exception:\n            self._run_cmd('net stop spooler /y')\n        self._printer_log(\"  \u2705 Spooler stopped, startup=auto set\", C[\"success\"])\n\n        # Step 2 \u2014 Clear spool folder\n        self._printer_log(\"\\n[2/6] Stuck print jobs delete kar raha hoon...\", C[\"accent4\"])\n        spool_dir = os.path.join(os.environ.get(\"SYSTEMROOT\",\"C:\\\\Windows\"),\n                                  \"System32\",\"spool\",\"PRINTERS\")\n        deleted = 0\n        for f in Path(spool_dir).glob(\"*\"):\n            try: f.unlink(); deleted += 1\n            except: pass\n        self._printer_log(f\"  \u2705 {deleted} stuck jobs deleted\", C[\"success\"])\n\n        # Step 3 \u2014 Re-register spooler DLLs\n        self._printer_log(\"\\n[3/6] Spooler DLLs re-register kar raha hoon...\", C[\"accent4\"])\n        sys32 = os.path.join(os.environ.get(\"SYSTEMROOT\",\"C:\\\\Windows\"), \"System32\")\n        for dll in [\"spoolsv.exe\",\"localspl.dll\",\"spoolss.dll\",\"win32spl.dll\"]:\n            path = os.path.join(sys32, dll)\n            if os.path.exists(path) and dll.endswith(\".dll\"):\n                self._run_cmd(f'regsvr32 /s \"{path}\"')\n                self._printer_log(f\"  \u2705 Registered: {dll}\", C[\"success\"])\n            elif os.path.exists(path):\n                self._printer_log(f\"  \u2705 Found: {dll}\", C[\"success\"])\n            else:\n                self._printer_log(f\"  \u274c Missing: {dll} \u2014 SFC /scannow try karo\", C[\"error\"])\n\n        # Step 4 \u2014 Firewall rules for printing\n        self._printer_log(\"\\n[4/6] Printer firewall rules check kar raha hoon...\", C[\"accent4\"])\n        for port, proto, name in [\n            (135,\"TCP\",\"RPC\"),\n            (445,\"TCP\",\"SMB\"),\n            (9100,\"TCP\",\"RAW Print\"),\n            (631,\"TCP\",\"IPP Print\"),\n        ]:\n            self._run_cmd(f'netsh advfirewall firewall add rule name=\"GodawariPrint_{name}\" '\n                          f'dir=in action=allow protocol={proto} localport={port} '\n                          f'profile=private,domain')\n            self._printer_log(f\"  \u2705 Port {port}/{proto} ({name}) open\", C[\"success\"])\n\n        # Step 5 \u2014 Registry spool path verify\n        self._printer_log(\"\\n[5/6] Registry spool path verify kar raha hoon...\", C[\"accent4\"])\n        default_spool = spool_dir\n        try:\n            key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,\n                                  r\"SYSTEM\\CurrentControlSet\\Control\\Print\\Printers\",\n                                  0, winreg.KEY_SET_VALUE | winreg.KEY_READ)\n            try:\n                current, _ = winreg.QueryValueEx(key, \"DefaultSpoolDirectory\")\n                if not os.path.exists(current):\n                    winreg.SetValueEx(key, \"DefaultSpoolDirectory\", 0,\n                                      winreg.REG_SZ, default_spool)\n                    self._printer_log(f\"  \u2705 Spool path fixed: {default_spool}\", C[\"success\"])\n                else:\n                    self._printer_log(f\"  \u2705 Spool path OK: {current}\", C[\"success\"])\n            except:\n                self._printer_log(\"  \u2139 Spool path entry not found \u2014 using default\", C[\"text_dim\"])\n            winreg.CloseKey(key)\n        except Exception as e:\n            self._printer_log(f\"  \u26a0 Registry check failed: {e}\", C[\"warning\"])\n\n        # Step 6 \u2014 PrintNightmare mitigation\n        self._printer_log(\"\\n[6/6] PrintNightmare security fix kar raha hoon...\", C[\"accent4\"])\n        self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                      r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                      \"RpcAuthnLevelPrivacyEnabled\", 1, winreg.REG_DWORD)\n        self._printer_log(\"  \u2705 RPC auth level hardened\", C[\"success\"])\n\n        # Start spooler\n        try:\n            self._service_start_checked(\"Spooler\", \"Print Spooler\", self.printer_log)\n        except Exception:\n            self._run_cmd('net start spooler')\n        self._printer_log(\"\\n\u2550\"*52, C[\"border\"])\n        self._printer_log(\"\u2705 FULL REPAIR COMPLETE! Ab printer test karo.\", C[\"success\"])\n        self._printer_log(\"   Agar abhi bhi problem hai \u2014 Driver reinstall karo.\", C[\"text_dim\"])\n        self.after(0, self._refresh_spooler_status)\n\n    def _printer_sfc(self):\n        if not messagebox.askyesno(\"SFC Scan\",\n                \"System File Checker chalega \u2014 Windows files repair karega.\\n\"\n                \"10-15 minute lag sakte hain.\\nAage badhein?\"):\n            return\n        self._printer_log(\"\ud83d\udd0d SFC /scannow chal raha hai...\", C[\"accent4\"])\n        self._printer_action_submit(\"printer_sfc\", self._do_printer_sfc)\n\n    def _do_printer_sfc(self):\n        out, _ = self._run_cmd('sfc /scannow', timeout=900)\n        self._printer_log(out[-300:] if isinstance(out, str) else \"SFC completed.\", C[\"text\"])\n        self._printer_log(\"\u2705 SFC complete\", C[\"success\"])\n\n    def _printer_printnightmare(self):\n        if not messagebox.askyesno(\"PrintNightmare Fix\",\n                \"PrintNightmare vulnerability fix karega:\\n\"\n                \"\u2022 Remote access restrict karega\\n\"\n                \"\u2022 Point and Print disable karega\\n\"\n                \"\u2022 RPC auth harden karega\\nAage badhein?\"):\n            return\n        self._printer_action_submit(\"printer_printnightmare\", self._do_printer_printnightmare)\n\n    def _do_printer_printnightmare(self):\n        self._printer_log(\"\ud83d\udd12 Applying PrintNightmare mitigations...\", C[\"accent4\"])\n        self._run_cmd('reg add \"HKLM/SOFTWARE/Policies/Microsoft/Windows NT/Printers/PointAndPrint\" /v RestrictDriverInstallationToAdministrators /t REG_DWORD /d 1 /f')\n        self._run_cmd('reg add \"HKLM/SOFTWARE/Policies/Microsoft/Windows NT/Printers/PointAndPrint\" /v NoWarningNoElevationOnInstall /t REG_DWORD /d 0 /f')\n        self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                      r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                      \"RpcAuthnLevelPrivacyEnabled\", 1, winreg.REG_DWORD)\n        self._printer_log(\"\u2705 PrintNightmare vulnerability patched!\", C[\"success\"])\n\n    def _printer_troubleshooter(self):\n        self._printer_log(\"\ud83d\udd0d Windows Printer Troubleshooter chal raha hai...\", C[\"accent4\"])\n        self._printer_action_submit(\"printer_troubleshooter\", self._do_printer_troubleshooter)\n\n    def _do_printer_troubleshooter(self):\n        self._run_cmd('msdt.exe /id PrinterDiagnostic')\n        self._printer_log(\"\u2139 Troubleshooter window open hua.\", C[\"text_dim\"])\n\n    def _printer_open_queue(self):\n        sel = self.printer_tree.selection()\n        if sel and self._printer_data:\n            idx = self.printer_tree.index(sel[0])\n            if idx &lt; len(self._printer_data):\n                name = self._printer_data[idx][2][\"name\"]\n                self._run_cmd(f'rundll32 printui.dll,PrintUIEntry /o /n \"{name}\"')\n                return\n        # Open printers &amp; scanners settings\n        self._run_cmd('control printers')\n\n    def _printer_set_default(self):\n        sel = self.printer_tree.selection()\n        if not sel or not self._printer_data:\n            messagebox.showinfo(\"Select Printer\",\"Pehle printer select karo.\")\n            return\n        idx = self.printer_tree.index(sel[0])\n        if idx &gt;= len(self._printer_data):\n            return\n        name = self._printer_data[idx][2][\"name\"]\n        self._printer_action_submit(\"printer_set_default\", self._do_printer_set_default, printer_name=name)\n\n    def _do_printer_set_default(self, printer_name):\n        out, rc = self._run_cmd(\n            f'powershell -Command \"Set-Printer -Name \\'{printer_name}\\' -IsDefault $true\"',\n            timeout=10)\n        if rc == 0:\n            self._printer_log(f\"\u2705 '{printer_name}' default printer set ho gaya!\", C[\"success\"])\n        else:\n            self._run_cmd(f'rundll32 printui.dll,PrintUIEntry /y /n \"{printer_name}\"')\n            self._printer_log(f\"\u2705 '{printer_name}' default set (legacy method)\", C[\"success\"])\n        self._printer_detect()\n\n    def _printer_remove(self):\n        sel = self.printer_tree.selection()\n        if not sel or not self._printer_data:\n            messagebox.showinfo(\"Select Printer\",\"Pehle printer select karo.\")\n            return\n        idx = self.printer_tree.index(sel[0])\n        if idx &gt;= len(self._printer_data):\n            return\n        name = self._printer_data[idx][2][\"name\"]\n        if not messagebox.askyesno(\"Remove Printer\",\n                f\"'{name}' printer remove ho jaayega.\\nAage badhein?\"):\n            return\n        self._printer_action_submit(\"printer_remove\", self._do_printer_remove, printer_name=name)\n\n    def _do_printer_remove(self, printer_name):\n        out, rc = self._run_cmd(\n            f'powershell -Command \"Remove-Printer -Name \\'{printer_name}\\'\"', timeout=10)\n        if rc == 0:\n            self._printer_log(f\"\u2705 '{printer_name}' removed!\", C[\"success\"])\n        else:\n            self._run_cmd(f'rundll32 printui.dll,PrintUIEntry /dl /n \"{printer_name}\"')\n            self._printer_log(f\"\u2705 '{printer_name}' removed (legacy method)\", C[\"success\"])\n        self._printer_detect()\n\n    def _printer_driver_signature_audit(self):\n        self._printer_action_submit(\"printer_driver_signature_audit\", self._do_printer_driver_signature_audit)\n\n    def _do_printer_driver_signature_audit(self):\n        self._printer_log(\"\ud83d\udd0d Collecting printer driver metadata...\", C[\"accent4\"])\n        output, rc = self._run_cmd(\n            'powershell -Command \"Get-PrinterDriver | Select-Object Name,Manufacturer,InfName,Version | ConvertTo-Csv -NoTypeInformation\"',\n            timeout=12)\n        if rc != 0 or not output:\n            self._printer_log(\"\u26a0 Driver audit failed or returned no data.\", C[\"warning\"])\n            return\n        lines = [line.strip() for line in output.splitlines() if line.strip()]\n        self._printer_log(f\"\u2705 {len(lines)-1} driver entries found\", C[\"success\"]) if len(lines) &gt; 1 else self._printer_log(\"\u26a0 No drivers discovered.\", C[\"warning\"])\n        for row in lines[:12]:\n            self._printer_trace(row, C[\"text_dim\"])\n        if len(lines) &gt; 12:\n            self._printer_trace(f\"... and {len(lines)-1-11} more driver records\", C[\"text_dim\"])\n\n    def _printer_spooler_snapshot(self):\n        self._printer_action_submit(\"printer_spooler_snapshot\", self._do_printer_spooler_snapshot)\n\n    def _do_printer_spooler_snapshot(self):\n        self._printer_log(\"\ud83d\udcf8 Capturing spooler and driver snapshot...\", C[\"accent4\"])\n        cfg, rc1 = self._run_cmd('sc qc spooler', timeout=10)\n        self._printer_trace(cfg or \"Unable to read spooler service config.\", C[\"text\"]) \n        driver_info, rc2 = self._run_cmd('pnputil /enum-drivers', timeout=20)\n        drivers = [line for line in (driver_info or \"\").splitlines() if line.strip()]\n        self._printer_log(f\"\u2705 Spooler snapshot captured \u2014 {len(drivers)} driver lines\", C[\"success\"])\n        for line in drivers[:8]:\n            self._printer_trace(line, C[\"text_dim\"])\n        if len(drivers) &gt; 8:\n            self._printer_trace(f\"... and {len(drivers)-8} more lines\", C[\"text_dim\"])\n\n    def _printer_network_setup(self):\n        dlg = tk.Toplevel(self)\n        dlg.title(\"Network Printer Setup\")\n        dlg.geometry(\"480x340\")\n        dlg.configure(bg=C[\"bg\"])\n        dlg.grab_set()\n\n        tk.Label(dlg, text=\"\ud83c\udf10 Network / Shared Printer Setup\",\n                 font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"bg\"]).pack(pady=(16,4))\n\n        info = tk.Frame(dlg, bg=C[\"card\"])\n        info.pack(fill=\"x\", padx=20, pady=6)\n\n        fields = {}\n        for lbl, key, placeholder in [\n            (\"Printer IP / Hostname:\", \"ip\",   \"e.g. 192.168.1.100\"),\n            (\"Share Name (optional):\", \"share\",\"e.g. HP_LaserJet\"),\n            (\"Port Name:\",             \"port\", \"e.g. IP_192.168.1.100\"),\n        ]:\n            row = tk.Frame(info, bg=C[\"card\"])\n            row.pack(fill=\"x\", pady=4)\n            tk.Label(row, text=lbl, font=FONTS[\"body\"], fg=C[\"text\"],\n                     bg=C[\"card\"], width=22, anchor=\"w\").pack(side=\"left\")\n            e = tk.Entry(row, font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"],\n                         insertbackground=C[\"text\"], relief=\"flat\", bd=4, width=24)\n            e.insert(0, placeholder)\n            e.bind(\"\",  lambda ev,p=placeholder,en=e: en.delete(0,\"end\") if en.get()==p else None)\n            e.bind(\"\", lambda ev,p=placeholder,en=e: en.insert(0,p) if not en.get() else None)\n            e.pack(side=\"left\", padx=4)\n            fields[key] = e\n\n        log = scrolledtext.ScrolledText(dlg, height=6, font=FONTS[\"mono\"],\n                                         bg=C[\"bg\"], fg=C[\"text\"], bd=0, state=\"disabled\")\n        log.pack(fill=\"both\", expand=True, padx=20, pady=4)\n\n        def _do_add():\n            ip    = fields[\"ip\"].get().strip()\n            share = fields[\"share\"].get().strip()\n            port  = fields[\"port\"].get().strip() or f\"IP_{ip}\"\n            if not ip or ip.startswith(\"e.g\"):\n                messagebox.showwarning(\"IP Missing\",\"Printer IP enter karo.\", parent=dlg)\n                return\n\n            def _run():\n                def _log(msg, col=C[\"text\"]):\n                    log.config(state=\"normal\")\n                    log.insert(\"end\", msg+\"\\n\")\n                    log.see(\"end\")\n                    log.config(state=\"disabled\")\n\n                _log(f\"Connecting to {ip}...\")\n                # Add TCP/IP port\n                self._run_cmd(\n                    f'powershell -Command \"Add-PrinterPort -Name \\'{port}\\' -PrinterHostAddress \\'{ip}\\'\"',\n                    timeout=10)\n                _log(f\"\u2705 Port {port} added\")\n                # Add printer\n                if share:\n                    cmd = (f'powershell -Command \"Add-Printer -Name \\'Network_{ip}\\' '\n                           f'-DriverName \\'Microsoft Print To PDF\\' -PortName \\'{port}\\'\"')\n                else:\n                    cmd = (f'net use LPT1: \\\\\\\\{ip}\\\\{share} /persistent:yes')\n                out, rc = self._run_cmd(cmd, timeout=15)\n                if rc == 0:\n                    _log(f\"\u2705 Printer added! IP: {ip}\")\n                else:\n                    _log(f\"\u26a0 Auto-add failed. Manually karo:\\n  Control Panel \u2192 Devices \u2192 Add Printer \u2192 Manual \u2192 TCP/IP \u2192 {ip}\")\n                _log(\"Done!\")\n                self.after(0, self._printer_detect)\n\n            self._launch_job(\"printer_add\", _run)\n\n        btn_frame = tk.Frame(dlg, bg=C[\"bg\"])\n        btn_frame.pack(pady=8)\n        self._btn(btn_frame, \"\ud83c\udf10 Add Network Printer\", C[\"btn_info\"], _do_add).pack(side=\"left\", padx=6)\n        self._btn(btn_frame, \"\ud83d\udd0d Ping Printer IP\",     C[\"btn_chip\"],\n                  lambda ip=fields[\"ip\"].get(): self._launch_job(\"printer_ping\", lambda: self._append_log(log, self._run_cmd(f'ping -n 2 {ip}')[0], C[\"text\"])) ).pack(side=\"left\", padx=6)\n        self._btn(btn_frame, \"Close\", C[\"btn_warn\"], dlg.destroy).pack(side=\"left\", padx=6)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \ud83d\udd17 PRINTER SHARING CENTER \u2014 HELPER &amp; STATUS\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _get_hostname(self):\n        try:\n            return platform.node()\n        except:\n            return \"YourHostPC\"\n\n    def _sharing_log(self, msg, col=None):\n        \"\"\"Safe append to sharing_log widget.\"\"\"\n        if col is None:\n            col = C[\"text\"]\n        try:\n            self._append_log(self.sharing_log, msg, col)\n        except Exception:\n            pass\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # INDIVIDUAL PORT OPENERS \u2014 HOST\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _open_single_port_host(self, port, proto_str, name):\n        \"\"\"Open a single port on HOST firewall (IN + OUT).\"\"\"\n        self._sharing_log(f\"\ud83d\udd0c [HOST] Port {port}/{proto_str} ({name}) khol raha hoon...\", C[\"accent4\"])\n        def _r():\n            protos = [\"TCP\",\"UDP\"] if proto_str == \"TCP+UDP\" else [proto_str]\n            for proto in protos:\n                for dirn in [\"in\",\"out\"]:\n                    rule = f\"GodawariHost_{name}_{dirn.upper()}\"\n                    cmd = (f'netsh advfirewall firewall add rule '\n                           f'name=\"{rule}\" dir={dirn} action=allow '\n                           f'protocol={proto} localport={port} profile=any')\n                    _, rc = self._run_cmd(cmd)\n                    self._sharing_log(\n                        f\"  {'\u2705' if rc==0 else '\u26a0'} {port}/{proto} {dirn.upper()} \u2192 {'OK' if rc==0 else 'Already exists / Error'}\",\n                        C[\"success\"] if rc==0 else C[\"warning\"])\n            self._sharing_log(f\"\u2705 Port {port}/{proto_str} ({name}) \u2192 Done!\", C[\"success\"])\n        self._launch_job(f\"open_port_host_{port}_{name}\", _r)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # INDIVIDUAL PORT OPENERS \u2014 CLIENT\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _open_single_port_client(self, port, proto_str, name):\n        \"\"\"Open a single port on CLIENT firewall (IN + OUT).\"\"\"\n        self._sharing_log(f\"\ud83d\udd0c [CLIENT] Port {port}/{proto_str} ({name}) khol raha hoon...\", C[\"accent2\"])\n        def _r():\n            protos = [\"TCP\",\"UDP\"] if proto_str == \"TCP+UDP\" else [proto_str]\n            for proto in protos:\n                for dirn in [\"in\",\"out\"]:\n                    rule = f\"GodawariClient_{name}_{dirn.upper()}\"\n                    cmd = (f'netsh advfirewall firewall add rule '\n                           f'name=\"{rule}\" dir={dirn} action=allow '\n                           f'protocol={proto} localport={port} profile=any')\n                    _, rc = self._run_cmd(cmd)\n                    self._sharing_log(\n                        f\"  {'\u2705' if rc==0 else '\u26a0'} {port}/{proto} {dirn.upper()} \u2192 {'OK' if rc==0 else 'Already exists / Error'}\",\n                        C[\"success\"] if rc==0 else C[\"warning\"])\n            self._sharing_log(f\"\u2705 Port {port}/{proto_str} ({name}) \u2192 Done!\", C[\"success\"])\n        self._launch_job(f\"open_port_client_{port}_{name}\", _r)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # INDIVIDUAL SECURITY ACTIONS \u2014 HOST\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _host_single_security(self, key):\n        \"\"\"Apply one specific HOST security setting.\"\"\"\n        self._sharing_log(f\"\ud83d\udd12 [HOST] Security setting apply kar raha hoon: {key}\", C[\"accent4\"])\n        def _r():\n            if key == \"network_discovery\":\n                self._run_cmd('netsh advfirewall firewall set rule group=\"Network Discovery\" new enable=Yes profile=private')\n                self._sharing_log(\"  \u2705 Network Discovery \u2192 ON (Private profile)\", C[\"success\"])\n            elif key == \"fp_sharing_rules\":\n                self._run_cmd('netsh advfirewall firewall set rule group=\"File and Printer Sharing\" new enable=Yes profile=any')\n                self._sharing_log(\"  \u2705 File &amp; Printer Sharing Rules \u2192 ON (All profiles)\", C[\"success\"])\n            elif key == \"network_private\":\n                self._run_cmd('powershell -Command \"Set-NetConnectionProfile -NetworkCategory Private\"')\n                self._sharing_log(\"  \u2705 Network Profile \u2192 Private\", C[\"success\"])\n            elif key == \"pwd_sharing_off\":\n                self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Lsa\" /v LimitBlankPasswordUse /t REG_DWORD /d 0 /f')\n                self._sharing_log(\"  \u2705 Password Protected Sharing \u2192 OFF (LimitBlankPasswordUse=0)\", C[\"success\"])\n            elif key == \"smb_sign_optional\":\n                self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanServer\\\\Parameters\" /v RequireSecuritySignature /t REG_DWORD /d 0 /f')\n                self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanServer\\\\Parameters\" /v EnableSecuritySignature /t REG_DWORD /d 1 /f')\n                self._sharing_log(\"  \u2705 SMB Server Signing \u2192 Optional (RequireSecuritySignature=0, Enable=1)\", C[\"success\"])\n            elif key == \"fw_private_off\":\n                self._run_cmd('netsh advfirewall set privateprofile state off')\n                self._sharing_log(\"  \u2705 Windows Defender Firewall \u2192 Private profile OFF\", C[\"success\"])\n                self._sharing_log(\"  \u26a0 Sirf trusted/local LAN pe karo!\", C[\"warning\"])\n            elif key == \"allow_ping\":\n                self._run_cmd('netsh advfirewall firewall add rule name=\"GodawariAllowPing_IN\" protocol=ICMPv4 dir=in action=allow')\n                self._run_cmd('netsh advfirewall firewall add rule name=\"GodawariAllowPing_OUT\" protocol=ICMPv4 dir=out action=allow')\n                self._sharing_log(\"  \u2705 ICMPv4 Ping \u2192 Allowed (IN + OUT)\", C[\"success\"])\n            self._sharing_log(f\"\u2705 [HOST] {key} \u2192 Complete!\", C[\"success\"])\n        self._launch_job(f\"host_security_{key}\", _r)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # INDIVIDUAL SECURITY ACTIONS \u2014 CLIENT\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _client_single_security(self, key):\n        \"\"\"Apply one specific CLIENT security setting.\"\"\"\n        self._sharing_log(f\"\ud83d\udd12 [CLIENT] Security setting: {key}\", C[\"accent2\"])\n        def _r():\n            if key == \"network_discovery\":\n                self._run_cmd('netsh advfirewall firewall set rule group=\"Network Discovery\" new enable=Yes profile=private')\n                self._sharing_log(\"  \u2705 Network Discovery \u2192 ON (Private profile)\", C[\"success\"])\n            elif key == \"fp_sharing_rules\":\n                self._run_cmd('netsh advfirewall firewall set rule group=\"File and Printer Sharing\" new enable=Yes profile=any')\n                self._sharing_log(\"  \u2705 File &amp; Printer Sharing Rules \u2192 ON (All profiles)\", C[\"success\"])\n            elif key == \"network_private\":\n                self._run_cmd('powershell -Command \"Set-NetConnectionProfile -NetworkCategory Private\"')\n                self._sharing_log(\"  \u2705 Network Profile \u2192 Private\", C[\"success\"])\n            elif key == \"smb_sign_optional\":\n                self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanWorkstation\\\\Parameters\" /v RequireSecuritySignature /t REG_DWORD /d 0 /f')\n                self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanWorkstation\\\\Parameters\" /v EnableSecuritySignature /t REG_DWORD /d 1 /f')\n                self._sharing_log(\"  \u2705 SMB Client Signing \u2192 Optional (RequireSecuritySignature=0)\", C[\"success\"])\n            elif key == \"point_print\":\n                self._run_cmd('reg add \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Printers\\\\PointAndPrint\" /v NoWarningNoElevationOnInstall /t REG_DWORD /d 1 /f')\n                self._run_cmd('reg add \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Printers\\\\PointAndPrint\" /v UpdatePromptSettings /t REG_DWORD /d 2 /f')\n                self._sharing_log(\"  \u2705 Point &amp; Print \u2192 No Warning, No Elevation on Install\", C[\"success\"])\n            elif key == \"fw_private_off\":\n                self._run_cmd('netsh advfirewall set privateprofile state off')\n                self._sharing_log(\"  \u2705 Windows Defender Firewall \u2192 Private profile OFF (Client)\", C[\"success\"])\n                self._sharing_log(\"  \u26a0 Sirf trusted/local LAN pe karo!\", C[\"warning\"])\n            elif key == \"allow_ping\":\n                self._run_cmd('netsh advfirewall firewall add rule name=\"GodawariClientPing_IN\" protocol=ICMPv4 dir=in action=allow')\n                self._run_cmd('netsh advfirewall firewall add rule name=\"GodawariClientPing_OUT\" protocol=ICMPv4 dir=out action=allow')\n                self._sharing_log(\"  \u2705 ICMPv4 Ping \u2192 Allowed on Client (IN + OUT)\", C[\"success\"])\n            self._sharing_log(f\"\u2705 [CLIENT] {key} \u2192 Complete!\", C[\"success\"])\n        self._launch_job(f\"client_single_reg_{key}\", _r)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # INDIVIDUAL REGISTRY CHANGES \u2014 HOST\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _host_single_reg(self, key):\n        \"\"\"Apply one specific HOST registry change.\"\"\"\n        self._sharing_log(f\"\ud83d\udddd [HOST] Registry: {key}\", C[\"accent4\"])\n        def _r():\n            try:\n                if key == \"AutoShareServer\":\n                    self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                        r\"SYSTEM\\CurrentControlSet\\Services\\LanmanServer\\Parameters\",\n                        \"AutoShareServer\", 1, winreg.REG_DWORD)\n                    self._sharing_log(\"  \u2705 AutoShareServer = 1  (Admin C$,D$ shares ON)\", C[\"success\"])\n                elif key == \"AutoShareWks\":\n                    self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                        r\"SYSTEM\\CurrentControlSet\\Services\\LanmanServer\\Parameters\",\n                        \"AutoShareWks\", 1, winreg.REG_DWORD)\n                    self._sharing_log(\"  \u2705 AutoShareWks = 1  (Workstation shares ON)\", C[\"success\"])\n                elif key == \"IRPStackSize\":\n                    self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                        r\"SYSTEM\\CurrentControlSet\\Services\\LanmanServer\\Parameters\",\n                        \"IRPStackSize\", 20, winreg.REG_DWORD)\n                    self._sharing_log(\"  \u2705 IRPStackSize = 20  (Large network packets fix)\", C[\"success\"])\n                elif key == \"LimitBlankPasswordUse\":\n                    self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                        r\"SYSTEM\\CurrentControlSet\\Control\\Lsa\",\n                        \"LimitBlankPasswordUse\", 0, winreg.REG_DWORD)\n                    self._sharing_log(\"  \u2705 LimitBlankPasswordUse = 0  (Blank password allowed)\", C[\"success\"])\n                elif key == \"DisableWebPrinting\":\n                    self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                        r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                        \"DisableWebPrinting\", 0, winreg.REG_DWORD)\n                    self._sharing_log(\"  \u2705 DisableWebPrinting = 0  (Web printing enabled)\", C[\"success\"])\n                elif key == \"EnableSMB1\":\n                    if messagebox.askyesno(\"SMB1 Enable\",\n                            \"SMB1 enable karna chahte hain?\\n\\n\"\n                            \"\u26a0 Security risk \u2014 sirf XP/Win7 clients ke liye!\\nContinue?\"):\n                        self._run_cmd('powershell -Command \"Set-SmbServerConfiguration -EnableSMB1Protocol $true -Force\"')\n                        self._sharing_log(\"  \u2705 SMB1 Protocol \u2192 Enabled\", C[\"warning\"])\n                self._sharing_log(f\"\u2705 [HOST] {key} \u2192 Done!\", C[\"success\"])\n            except Exception as ex:\n                self._sharing_log(f\"  \u274c {key}: {ex}\", C[\"error\"])\n        self._launch_job(f\"host_single_reg_{key}\", _r)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # INDIVIDUAL REGISTRY CHANGES \u2014 CLIENT\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _client_single_reg(self, key):\n        \"\"\"Apply one specific CLIENT registry change.\"\"\"\n        self._sharing_log(f\"\ud83d\udddd [CLIENT] Registry: {key}\", C[\"accent2\"])\n        def _r():\n            try:\n                if key == \"AllowInsecureGuestAuth\":\n                    self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                        r\"SYSTEM\\CurrentControlSet\\Services\\LanmanWorkstation\\Parameters\",\n                        \"AllowInsecureGuestAuth\", 1, winreg.REG_DWORD)\n                    self._sharing_log(\"  \u2705 AllowInsecureGuestAuth = 1  (Guest share access)\", C[\"success\"])\n                elif key == \"LimitBlankPasswordUse\":\n                    self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                        r\"SYSTEM\\CurrentControlSet\\Control\\Lsa\",\n                        \"LimitBlankPasswordUse\", 0, winreg.REG_DWORD)\n                    self._sharing_log(\"  \u2705 LimitBlankPasswordUse = 0  (Blank password connect)\", C[\"success\"])\n                elif key == \"RequireSecuritySignature\":\n                    self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                        r\"SYSTEM\\CurrentControlSet\\Services\\LanmanWorkstation\\Parameters\",\n                        \"RequireSecuritySignature\", 0, winreg.REG_DWORD)\n                    self._sharing_log(\"  \u2705 RequireSecuritySignature = 0  (SMB signing optional)\", C[\"success\"])\n                elif key == \"PnP_NoWarning\":\n                    self._run_cmd('reg add \"HKLM/SOFTWARE/Policies/Microsoft/Windows NT/Printers/PointAndPrint\" /v NoWarningNoElevationOnInstall /t REG_DWORD /d 1 /f')\n                    self._sharing_log(\"  \u2705 PnP NoWarningNoElevationOnInstall = 1\", C[\"success\"])\n                elif key == \"PnP_UpdatePrompt\":\n                    self._run_cmd('reg add \"HKLM/SOFTWARE/Policies/Microsoft/Windows NT/Printers/PointAndPrint\" /v UpdatePromptSettings /t REG_DWORD /d 2 /f')\n                    self._sharing_log(\"  \u2705 PnP UpdatePromptSettings = 2\", C[\"success\"])\n                elif key == \"PnP_RestrictDriver\":\n                    self._run_cmd('reg add \"HKLM/SOFTWARE/Policies/Microsoft/Windows NT/Printers/PointAndPrint\" /v RestrictDriverInstallationToAdministrators /t REG_DWORD /d 0 /f')\n                    self._sharing_log(\"  \u2705 PnP RestrictDriverInstallationToAdministrators = 0\", C[\"success\"])\n                self._sharing_log(f\"\u2705 [CLIENT] {key} \u2192 Done!\", C[\"success\"])\n            except Exception as ex:\n                self._sharing_log(f\"  \u274c {key}: {ex}\", C[\"error\"])\n        self._launch_job(\"apply_sharing_client_changes\", _r)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # INDIVIDUAL SERVICE STARTER \u2014 HOST/CLIENT SHARED\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _host_single_svc(self, svc_name):\n        \"\"\"Start and set a single service to Auto.\"\"\"\n        svc_display = {\n            \"Spooler\": \"Print Spooler\",\n            \"LanmanServer\": \"Server (File &amp; Printer Sharing)\",\n            \"LanmanWorkstation\": \"Workstation (Network Redirector)\",\n            \"lmhosts\": \"TCP/IP NetBIOS Helper\",\n            \"fdPHost\": \"Function Discovery Provider Host\",\n            \"FDResPub\": \"Function Discovery Resource Publication\",\n            \"SSDPSRV\": \"SSDP Discovery\",\n        }.get(svc_name, svc_name)\n        self._sharing_log(f\"\u2699\ufe0f Service: {svc_display} \u2192 Auto + Start\", C[\"accent4\"])\n        def _r():\n            _, r1 = self._run_cmd(f'sc config \"{svc_name}\" start= auto')\n            _, r2 = self._run_cmd(f'sc start \"{svc_name}\"')\n            ok = r1 == 0 or r2 == 0\n            self._sharing_log(\n                f\"  {'\u2705' if ok else '\u26a0'} {svc_display} \u2192 {'Auto+Started' if ok else 'Check manually'}\",\n                C[\"success\"] if ok else C[\"warning\"])\n        threading.Thread(target=_r, daemon=True).start()\n\n    def _check_sharing_status(self):\n        \"\"\"Quick check: Network Discovery, File Sharing, Spooler, Workgroup.\"\"\"\n        self._sharing_log(\"\u2550\"*56, C[\"border\"])\n        self._sharing_log(\"\ud83d\udd0e Sharing Status Check chal raha hai...\", C[\"accent4\"])\n        self._launch_job(\"check_sharing_status\", self._do_check_sharing_status)\n\n    def _do_check_sharing_status(self):\n        # Spooler\n        out, _ = self._run_cmd('sc query spooler')\n        running = \"running\" in out.lower()\n        self._sharing_log(f\"  {'\u2705' if running else '\u274c'} Print Spooler: {'Running' if running else 'Stopped'}\",\n                          C[\"success\"] if running else C[\"error\"])\n\n        # Server / LanmanServer\n        out2, _ = self._run_cmd('sc query lanmanserver')\n        srv = \"running\" in out2.lower()\n        self._sharing_log(f\"  {'\u2705' if srv else '\u274c'} LanmanServer (File Sharing): {'Running' if srv else 'Stopped'}\",\n                          C[\"success\"] if srv else C[\"error\"])\n\n        # Workgroup\n        out3, _ = self._run_cmd('wmic computersystem get Workgroup /value')\n        wg = out3.strip().replace(\"Workgroup=\",\"\").strip()\n        self._sharing_log(f\"  \u2139 Workgroup: {wg if wg else 'Unknown'}\", C[\"text_dim\"])\n\n        # Computer Name + IP\n        out4, _ = self._run_cmd('ipconfig')\n        for line in out4.splitlines():\n            if \"IPv4\" in line and \"169.\" not in line:\n                self._sharing_log(f\"  \u2139 {line.strip()}\", C[\"text_dim\"])\n                break\n\n        # Firewall File &amp; Printer Sharing state\n        out5, _ = self._run_cmd('netsh advfirewall firewall show rule name=\"File and Printer Sharing (SMB-In)\"')\n        enabled_fw = \"enabled\" in out5.lower()\n        self._sharing_log(\n            f\"  {'\u2705' if enabled_fw else '\u26a0'} Firewall F&amp;P Rule: {'Enabled' if enabled_fw else 'Disabled/Missing'}\",\n            C[\"success\"] if enabled_fw else C[\"warning\"])\n\n        # Printer sharing via PowerShell\n        out6, _ = self._run_cmd(\n            'powershell -Command \"Get-Printer | Select-Object Name,Shared,ShareName | ConvertTo-Csv -NoTypeInformation\"',\n            timeout=10)\n        any_shared = False\n        for line in out6.splitlines()[1:]:\n            parts = line.strip().replace('\"','').split(',')\n            if len(parts) &gt;= 2 and parts[1].strip().lower() == \"true\":\n                any_shared = True\n                self._sharing_log(\n                    f\"  \u2705 Shared Printer: {parts[0].strip()}  \u2192  ShareName: {parts[2].strip() if len(parts)&gt;2 else '\u2014'}\",\n                    C[\"success\"])\n        if not any_shared:\n            self._sharing_log(\"  \u26a0 Koi printer shared nahi hai! Host pe Auto-Share button chalao.\", C[\"warning\"])\n\n        self._sharing_log(\"\u2705 Status check complete!\", C[\"success\"])\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \ud83d\udda5 HOST COMPUTER \u2014 PRINTER SHARING METHODS\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _host_open_ports(self):\n        if not messagebox.askyesno(\"Host: Port Fix\",\n                \"HOST computer pe ye ports open honge:\\n\\n\"\n                \"\u2022 445 TCP/UDP  \u2014 SMB File &amp; Printer Sharing\\n\"\n                \"\u2022 139 TCP      \u2014 NetBIOS Session Service\\n\"\n                \"\u2022 137 UDP      \u2014 NetBIOS Name Service\\n\"\n                \"\u2022 138 UDP      \u2014 NetBIOS Datagram Service\\n\"\n                \"\u2022 135 TCP      \u2014 RPC Endpoint Mapper\\n\"\n                \"\u2022 9100 TCP     \u2014 RAW Print Port\\n\"\n                \"\u2022 631  TCP     \u2014 IPP Print\\n\\n\"\n                \"\u26a0 Sirf private/trusted network pe karo!\\nContinue karein?\"):\n            return\n        self._sharing_log(\"\u2550\"*56, C[\"border\"])\n        self._sharing_log(\"\ud83d\udd0c [HOST] Printer ports khol raha hoon...\", C[\"accent4\"])\n        self._launch_job(\"host_open_ports\", self._do_host_open_ports)\n\n    def _do_host_open_ports(self):\n        ports = [\n            (445,  \"TCP\", \"SMB-Print-TCP\"),\n            (445,  \"UDP\", \"SMB-Print-UDP\"),\n            (139,  \"TCP\", \"NetBIOS-Session\"),\n            (137,  \"UDP\", \"NetBIOS-Name\"),\n            (138,  \"UDP\", \"NetBIOS-Datagram\"),\n            (135,  \"TCP\", \"RPC-Endpoint\"),\n            (9100, \"TCP\", \"RAW-Print\"),\n            (631,  \"TCP\", \"IPP-Print\"),\n        ]\n        for port, proto, name in ports:\n            cmd_in = (f'netsh advfirewall firewall add rule '\n                      f'name=\"GodawariShare_{name}_IN\" '\n                      f'dir=in action=allow protocol={proto} '\n                      f'localport={port} profile=any')\n            _, rc = self._run_cmd(cmd_in)\n            cmd_out = (f'netsh advfirewall firewall add rule '\n                       f'name=\"GodawariShare_{name}_OUT\" '\n                       f'dir=out action=allow protocol={proto} '\n                       f'localport={port} profile=any')\n            self._run_cmd(cmd_out)\n            sym = \"\u2705\" if rc == 0 else \"\u26a0\"\n            self._sharing_log(\n                f\"  {sym} Port {port}/{proto} ({name}) \u2192 IN+OUT opened\",\n                C[\"success\"] if rc == 0 else C[\"warning\"])\n\n        # Enable predefined Windows rule group\n        self._run_cmd(\n            'netsh advfirewall firewall set rule '\n            'group=\"File and Printer Sharing\" new enable=Yes profile=any')\n        self._sharing_log(\"  \u2705 Windows 'File and Printer Sharing' rule group \u2192 ON\", C[\"success\"])\n        self._sharing_log(\"\u2705 [HOST] All printer sharing ports opened!\", C[\"success\"])\n\n    def _host_security_fix(self):\n        if not messagebox.askyesno(\"Host: Security &amp; Firewall Fix\",\n                \"HOST security changes honge:\\n\\n\"\n                \"\u2022 Network Discovery \u2192 Enable (Private profile)\\n\"\n                \"\u2022 File &amp; Printer Sharing firewall rules \u2192 ON\\n\"\n                \"\u2022 Network profile \u2192 Private\\n\"\n                \"\u2022 SMB security signature \u2192 Optional\\n\"\n                \"\u2022 Password Protected Sharing \u2192 aapki choice\\n\\n\"\n                \"Continue karein?\"):\n            return\n        pwd_off = messagebox.askyesno(\"Password Protected Sharing\",\n            \"Password Protected Sharing BAND karna chahte hain?\\n\\n\"\n            \"\u2705 YES = Band karo (Client bina password connect kar sake)\\n\"\n            \"\u274c NO  = On rehne do (Zyada secure)\")\n        self._sharing_log(\"\u2550\"*56, C[\"border\"])\n        self._sharing_log(\"\ud83d\udd12 [HOST] Security &amp; Firewall fix chal raha hai...\", C[\"accent4\"])\n        self._launch_job(\"host_security_fix\", lambda: self._do_host_security_fix(pwd_off))\n\n    def _do_host_security_fix(self, disable_pwd_sharing):\n        # Network Discovery \u2014 private\n        self._run_cmd('netsh advfirewall firewall set rule group=\"Network Discovery\" new enable=Yes profile=private')\n        self._sharing_log(\"  \u2705 Network Discovery \u2192 ON (Private)\", C[\"success\"])\n\n        # File &amp; Printer Sharing \u2014 all profiles\n        self._run_cmd('netsh advfirewall firewall set rule group=\"File and Printer Sharing\" new enable=Yes profile=any')\n        self._sharing_log(\"  \u2705 File &amp; Printer Sharing rules \u2192 ON (All profiles)\", C[\"success\"])\n\n        # Network profile \u2192 Private\n        self._run_cmd('powershell -Command \"Set-NetConnectionProfile -NetworkCategory Private\"')\n        self._sharing_log(\"  \u2705 Network profile \u2192 Private\", C[\"success\"])\n\n        # Password protected sharing\n        val = 0 if disable_pwd_sharing else 1\n        self._run_cmd(\n            f'reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Lsa\" '\n            f'/v LimitBlankPasswordUse /t REG_DWORD /d {val} /f')\n        self._sharing_log(\n            f\"  \u2705 Password Protected Sharing \u2192 {'OFF' if disable_pwd_sharing else 'ON (unchanged)'}\",\n            C[\"success\"])\n\n        # SMB server signature \u2014 optional (not required)\n        self._run_cmd(\n            'reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanServer\\\\Parameters\" '\n            '/v RequireSecuritySignature /t REG_DWORD /d 0 /f')\n        self._run_cmd(\n            'reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanServer\\\\Parameters\" '\n            '/v EnableSecuritySignature /t REG_DWORD /d 1 /f')\n        self._sharing_log(\"  \u2705 SMB signature \u2192 Optional (not required)\", C[\"success\"])\n\n        self._sharing_log(\"\u2705 [HOST] Security fix complete!\", C[\"success\"])\n\n    def _host_registry_fix(self):\n        if not messagebox.askyesno(\"Host: Registry Changes\",\n                \"HOST ke liye ye registry changes honge:\\n\\n\"\n                \"\u2022 AutoShareServer = 1 (admin shares enable)\\n\"\n                \"\u2022 AutoShareWks   = 1 (workstation shares)\\n\"\n                \"\u2022 IRPStackSize   = 20 (large network packets)\\n\"\n                \"\u2022 LimitBlankPasswordUse = 0\\n\"\n                \"\u2022 DisableWebPrinting    = 0\\n\"\n                \"\u2022 SMB1 status check (aapki marzi)\\n\\n\"\n                \"\u26a0 Registry badlega \u2014 seedha asar padega!\\nContinue karein?\"):\n            return\n        self._sharing_log(\"\u2550\"*56, C[\"border\"])\n        self._sharing_log(\"\ud83d\udddd [HOST] Registry changes apply kar raha hoon...\", C[\"accent4\"])\n        self._launch_job(\"host_registry_fix\", self._do_host_registry_fix)\n\n    def _do_host_registry_fix(self):\n        changes = [\n            (winreg.HKEY_LOCAL_MACHINE,\n             r\"SYSTEM\\CurrentControlSet\\Services\\LanmanServer\\Parameters\",\n             \"AutoShareServer\", 1, winreg.REG_DWORD),\n            (winreg.HKEY_LOCAL_MACHINE,\n             r\"SYSTEM\\CurrentControlSet\\Services\\LanmanServer\\Parameters\",\n             \"AutoShareWks\", 1, winreg.REG_DWORD),\n            (winreg.HKEY_LOCAL_MACHINE,\n             r\"SYSTEM\\CurrentControlSet\\Services\\LanmanServer\\Parameters\",\n             \"IRPStackSize\", 20, winreg.REG_DWORD),\n            (winreg.HKEY_LOCAL_MACHINE,\n             r\"SYSTEM\\CurrentControlSet\\Control\\Lsa\",\n             \"LimitBlankPasswordUse\", 0, winreg.REG_DWORD),\n            (winreg.HKEY_LOCAL_MACHINE,\n             r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n             \"DisableWebPrinting\", 0, winreg.REG_DWORD),\n        ]\n        for hive, path, name, val, typ in changes:\n            try:\n                self._reg_set(hive, path, name, val, typ)\n                self._sharing_log(f\"  \u2705 {name} = {val}\", C[\"success\"])\n            except Exception as e:\n                self._sharing_log(f\"  \u26a0 {name}: {e}\", C[\"warning\"])\n\n        # SMB1 check\n        out, _ = self._run_cmd(\n            'powershell -Command \"(Get-SmbServerConfiguration).EnableSMB1Protocol\"',\n            timeout=10)\n        smb1_on = out.strip().lower() == \"true\"\n        self._sharing_log(\n            f\"  \u2139 SMB1 currently: {'Enabled' if smb1_on else 'Disabled'}\",\n            C[\"text_dim\"])\n        if not smb1_on:\n            def ask_smb1():\n                if messagebox.askyesno(\"SMB1 Protocol\",\n                        \"SMB1 abhi BAND hai.\\n\\n\"\n                        \"Purane clients (Windows XP/7) ke liye SMB1 chahiye.\\n\"\n                        \"Enable karein?\\n\\n\"\n                        \"\u26a0 Security risk \u2014 sirf trusted/local network pe karo!\"):\n                    self._run_cmd(\n                        'powershell -Command \"Set-SmbServerConfiguration -EnableSMB1Protocol $true -Force\"')\n                    self._sharing_log(\"  \u2705 SMB1 \u2192 Enabled\", C[\"success\"])\n                else:\n                    self._sharing_log(\"  \u2139 SMB1 \u2192 Unchanged (Disabled)\", C[\"text_dim\"])\n            self.after(0, ask_smb1)\n\n        self._sharing_log(\"\u2705 [HOST] Registry changes complete!\", C[\"success\"])\n        self._sharing_log(\"   \u26a0 Restart karna recommended hai.\", C[\"warning\"])\n\n    def _host_enable_services(self):\n        if not messagebox.askyesno(\"Host: Enable Sharing Services\",\n                \"Ye services start + Auto hogi HOST pe:\\n\\n\"\n                \"\u2022 Spooler          \u2014 Print queue manager\\n\"\n                \"\u2022 LanmanServer     \u2014 Network shares provide karta hai\\n\"\n                \"\u2022 LanmanWorkstation \u2014 SMB client\\n\"\n                \"\u2022 lmhosts          \u2014 TCP/IP NetBIOS Helper\\n\"\n                \"\u2022 fdPHost          \u2014 Function Discovery Host\\n\"\n                \"\u2022 FDResPub         \u2014 Network resource publishing\\n\"\n                \"\u2022 SSDPSRV          \u2014 SSDP Discovery\\n\"\n                \"\u2022 upnphost         \u2014 UPnP\\n\"\n                \"\u2022 Dnscache         \u2014 DNS Client\\n\\n\"\n                \"Continue karein?\"):\n            return\n        self._sharing_log(\"\u2550\"*56, C[\"border\"])\n        self._sharing_log(\"\ud83c\udfe0 [HOST] Sharing services enable kar raha hoon...\", C[\"accent4\"])\n        self._launch_job(\"host_enable_services\", self._do_host_enable_services)\n\n    def _do_host_enable_services(self):\n        services = [\n            (\"Spooler\",            \"Print Spooler\"),\n            (\"LanmanServer\",       \"Server (File Sharing)\"),\n            (\"LanmanWorkstation\",  \"Workstation\"),\n            (\"lmhosts\",            \"TCP/IP NetBIOS Helper\"),\n            (\"fdPHost\",            \"Function Discovery Host\"),\n            (\"FDResPub\",           \"Function Discovery Resource Publication\"),\n            (\"SSDPSRV\",            \"SSDP Discovery\"),\n            (\"upnphost\",           \"UPnP Device Host\"),\n            (\"Dnscache\",           \"DNS Client\"),\n        ]\n        for svc, display in services:\n            self._run_cmd(f'sc config {svc} start= auto')\n            out, rc = self._run_cmd(f'net start {svc}')\n            ok = rc == 0 or \"already\" in out.lower() or \"started\" in out.lower()\n            self._sharing_log(\n                f\"  {'\u2705' if ok else '\u26a0'} {display} ({svc}) \u2192 Auto + Started\",\n                C[\"success\"] if ok else C[\"warning\"])\n        self._sharing_log(\"\u2705 [HOST] All sharing services enabled!\", C[\"success\"])\n\n    def _host_auto_share(self):\n        \"\"\"Auto-share selected printer from HOST + open Windows confirmation.\"\"\"\n        sel = self.printer_tree.selection()\n        if not sel or not self._printer_data:\n            messagebox.showinfo(\"Printer Select Karo\",\n                \"Pehle printer list mein se printer click karke select karo,\\n\"\n                \"phir 'Auto-Share' button dabao.\")\n            return\n        idx = self.printer_tree.index(sel[0])\n        if idx &gt;= len(self._printer_data):\n            return\n        printer_name = self._printer_data[idx][2][\"name\"]\n        share_name   = printer_name.replace(\" \", \"_\")[:20]\n\n        if not messagebox.askyesno(\"Host: Auto-Share Printer\",\n                f\"Printer:    {printer_name}\\n\"\n                f\"Share Name: {share_name}\\n\\n\"\n                \"Ye automatically share ho jaayega.\\n\"\n                \"Firewall rules bhi enable honge.\\n\"\n                \"Sharing hone ke baad Windows confirmation window\\n\"\n                \"aur Printer Properties khud khul jaayengi.\\n\\n\"\n                \"Continue karein?\"):\n            return\n        self._sharing_log(\"\u2550\"*56, C[\"border\"])\n        self._sharing_log(\n            f\"\ud83d\udce4 [HOST] '{printer_name}' ko share kar raha hoon \u2192 ShareName: '{share_name}'\",\n            C[\"accent4\"])\n        self._launch_job(\"host_auto_share\", lambda: self._do_host_auto_share(printer_name, share_name))\n\n    def _do_host_auto_share(self, printer_name, share_name):\n        # 1) Ensure spooler running\n        self._run_cmd('net start spooler')\n        self._sharing_log(\"  \u2705 Spooler started\", C[\"success\"])\n\n        # 2) Enable firewall rules\n        self._run_cmd(\n            'netsh advfirewall firewall set rule '\n            'group=\"File and Printer Sharing\" new enable=Yes profile=any')\n        self._sharing_log(\"  \u2705 File &amp; Printer Sharing firewall \u2192 ON\", C[\"success\"])\n\n        # 3) Share via PowerShell (primary)\n        out, rc = self._run_cmd(\n            f'powershell -Command \"Set-Printer -Name \\'{printer_name}\\' '\n            f'-Shared $true -ShareName \\'{share_name}\\'\"',\n            timeout=15)\n        if rc == 0:\n            self._sharing_log(\n                f\"  \u2705 '{printer_name}' shared as '{share_name}' (PowerShell)\", C[\"success\"])\n        else:\n            # Fallback: rundll32\n            self._run_cmd(\n                f'rundll32 printui.dll,PrintUIEntry /Xs /n \"{printer_name}\" '\n                f'attributes +shared sharename \"{share_name}\"',\n                timeout=10)\n            self._sharing_log(\n                f\"  \u2705 Shared via legacy method (rundll32)\", C[\"success\"])\n\n        # 4) Restart spooler to apply\n        self._run_cmd('net stop spooler /y')\n        time.sleep(1)\n        self._run_cmd('net start spooler')\n        self._sharing_log(\"  \u2705 Spooler restarted \u2014 sharing active\", C[\"success\"])\n\n        # 5) Open Windows confirmation automatically\n        hostname = self._get_hostname()\n        unc_path = f\"\\\\\\\\{hostname}\\\\{share_name}\"\n\n        def _open_confirmation():\n            # Open Printers &amp; Scanners control panel\n            subprocess.Popen([\"control.exe\", \"printers\"], shell=False)\n            time.sleep(1)\n            # Open Printer Properties (sharing tab visible)\n            try:\n                subprocess.Popen(\n                    [\"rundll32.exe\", \"printui.dll,PrintUIEntry\", \"/p\", \"/n\", printer_name],\n                    shell=False)\n            except Exception:\n                pass\n            # Final confirmation dialog\n            messagebox.showinfo(\n                \"\ud83c\udf89 Printer Sharing Complete!\",\n                f\"\u2705 Printer successfully shared!\\n\\n\"\n                f\"Printer Name : {printer_name}\\n\"\n                f\"Share Name   : {share_name}\\n\"\n                f\"UNC Path     : {unc_path}\\n\"\n                f\"Host PC      : {hostname}\\n\\n\"\n                f\"Client computers isko iss address se connect kar sakte hain:\\n\"\n                f\"  {unc_path}\\n\\n\"\n                \"Printers window aur Printer Properties\\n\"\n                \"ab khul gaye hain \u2014 Sharing tab check karo. \u2705\")\n            self._sharing_log(\n                f\"\u2705 [HOST] SHARING CONFIRMED!  UNC: {unc_path}\", C[\"success\"])\n\n        self.after(0, _open_confirmation)\n        self.after(500, self._printer_detect)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \ud83d\udd34 ERROR 0x0000709 \u2014 AUTO-FIX  (HOST)\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _fix_error_709_host(self):\n        \"\"\"Error 0x0000709 fix: HOST side \u2014 default printer registry + spooler + RPC.\"\"\"\n        if not messagebox.askyesno(\"Fix Error 0x0000709 \u2014 HOST\",\n                \"Error 0x0000709 matlab:\\n\"\n                \"  'Operation could not be completed \u2014 default printer cannot be set'\\n\\n\"\n                \"HOST pe ye fixes honge:\\n\"\n                \"  1. Spooler stop \u2192 spool folder clean \u2192 restart\\n\"\n                \"  2. UserSelectedDefault registry fix\\n\"\n                \"  3. DefaultSpoolDirectory path verify\\n\"\n                \"  4. Spooler DLLs re-register (localspl, spoolss, win32spl)\\n\"\n                \"  5. RPC service verify\\n\"\n                \"  6. Windows 'Manage my default printer' feature disable\\n\"\n                \"  7. Spooler startup = Auto forced\\n\\n\"\n                \"Continue karein?\"):\n            return\n        self._sharing_log(\"\u2550\"*56, C[\"border\"])\n        self._sharing_log(\"\ud83d\udd34 [HOST] Error 0x0000709 fix chal raha hai...\", C[\"error\"])\n        self._launch_job(\"fix_error_709_host\", self._do_fix_error_709_host)\n\n    def _do_fix_error_709_host(self):\n        log = self._sharing_log\n        L = C\n\n        # Step 1 \u2014 Spooler stop + spool clean + restart\n        log(\"  [1/7] Spooler stop + spool clean...\", L[\"accent4\"])\n        self._run_cmd('net stop spooler /y')\n        time.sleep(1)\n        spool_dir = os.path.join(os.environ.get(\"SYSTEMROOT\",\"C:\\\\Windows\"),\n                                  \"System32\",\"spool\",\"PRINTERS\")\n        deleted = 0\n        for f in Path(spool_dir).glob(\"*\"):\n            try: f.unlink(); deleted += 1\n            except: pass\n        log(f\"  \u2705 {deleted} spool files deleted\", L[\"success\"])\n\n        # Step 2 \u2014 UserSelectedDefault registry\n        log(\"  [2/7] UserSelectedDefault registry fix...\", L[\"accent4\"])\n        try:\n            key = winreg.OpenKey(\n                winreg.HKEY_CURRENT_USER,\n                r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows\",\n                0, winreg.KEY_SET_VALUE | winreg.KEY_READ)\n            try:\n                winreg.DeleteValue(key, \"UserSelectedDefault\")\n                log(\"  \u2705 UserSelectedDefault removed (will auto-rebuild)\", L[\"success\"])\n            except FileNotFoundError:\n                log(\"  \u2139 UserSelectedDefault not found \u2014 OK\", L[\"text_dim\"])\n            winreg.CloseKey(key)\n        except Exception as e:\n            log(f\"  \u26a0 UserSelectedDefault: {e}\", L[\"warning\"])\n\n        # Also clear Device registry stale default\n        try:\n            key2 = winreg.OpenKey(\n                winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\\Printers\",\n                0, winreg.KEY_SET_VALUE | winreg.KEY_READ)\n            try:\n                winreg.DeleteValue(key2, \"DefaultSpoolDirectory\")\n            except: pass\n            winreg.CloseKey(key2)\n        except: pass\n\n        # Step 3 \u2014 DefaultSpoolDirectory path set correct\n        log(\"  [3/7] DefaultSpoolDirectory path verify + fix...\", L[\"accent4\"])\n        try:\n            key3 = winreg.OpenKey(\n                winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\\Printers\",\n                0, winreg.KEY_SET_VALUE)\n            winreg.SetValueEx(key3, \"DefaultSpoolDirectory\", 0,\n                              winreg.REG_SZ, spool_dir)\n            winreg.CloseKey(key3)\n            log(f\"  \u2705 DefaultSpoolDirectory = {spool_dir}\", L[\"success\"])\n        except Exception as e:\n            log(f\"  \u26a0 Spool dir registry: {e}\", L[\"warning\"])\n\n        # Step 4 \u2014 Re-register spooler DLLs\n        log(\"  [4/7] Spooler DLLs re-register...\", L[\"accent4\"])\n        sys32 = os.path.join(os.environ.get(\"SYSTEMROOT\",\"C:\\\\Windows\"), \"System32\")\n        for dll in [\"localspl.dll\",\"spoolss.dll\",\"win32spl.dll\",\"inetpp.dll\"]:\n            path = os.path.join(sys32, dll)\n            if os.path.exists(path):\n                self._run_cmd(f'regsvr32 /s \"{path}\"')\n                log(f\"  \u2705 Registered: {dll}\", L[\"success\"])\n\n        # Step 5 \u2014 RPC service running\n        log(\"  [5/7] RPC service verify...\", L[\"accent4\"])\n        self._run_cmd('sc config RpcSs start= auto')\n        self._run_cmd('sc start RpcSs')\n        out, _ = self._run_cmd('sc query RpcSs')\n        log(\"  \u2705 RPC: Running\" if \"RUNNING\" in out else \"  \u26a0 RPC: Check manually\", L[\"success\"] if \"RUNNING\" in out else L[\"warning\"])\n\n        # Step 6 \u2014 \"Let Windows manage my default printer\" OFF\n        log(\"  [6/7] Windows auto-default printer feature \u2192 OFF...\", L[\"accent4\"])\n        try:\n            key4 = winreg.OpenKey(\n                winreg.HKEY_CURRENT_USER,\n                r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows\",\n                0, winreg.KEY_SET_VALUE)\n            winreg.SetValueEx(key4, \"LegacyDefaultPrinterMode\", 0, winreg.REG_DWORD, 1)\n            winreg.CloseKey(key4)\n            log(\"  \u2705 LegacyDefaultPrinterMode = 1 (Windows auto-manage OFF)\", L[\"success\"])\n        except Exception as e:\n            log(f\"  \u26a0 LegacyDefaultPrinterMode: {e}\", L[\"warning\"])\n\n        # Step 7 \u2014 Spooler auto + restart\n        log(\"  [7/7] Spooler startup = Auto + Start...\", L[\"accent4\"])\n        self._run_cmd('sc config Spooler start= auto')\n        self._run_cmd('net start spooler')\n        time.sleep(1)\n        out2, _ = self._run_cmd('sc query Spooler')\n        if \"RUNNING\" in out2:\n            log(\"  \u2705 Spooler: Running!\", L[\"success\"])\n        else:\n            log(\"  \u26a0 Spooler start nahi hua \u2014 Full Repair try karo\", L[\"warning\"])\n\n        log(\"\", L[\"text\"])\n        log(\"\u2705 [HOST] Error 0x0000709 FIX COMPLETE!\", L[\"success\"])\n        log(\"   \u25ba Ab printer detect karo aur default set karo.\", L[\"text_dim\"])\n        self.after(0, self._refresh_spooler_status)\n        self.after(500, self._printer_detect)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \ud83d\udd34 ERROR 0x0000011b \u2014 AUTO-FIX  (HOST)\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _fix_error_11b_host(self):\n        \"\"\"Error 0x0000011b fix: HOST side \u2014 RpcAuthnLevelPrivacyEnabled rollback + SMB.\"\"\"\n        if not messagebox.askyesno(\"Fix Error 0x0000011b \u2014 HOST\",\n                \"Error 0x0000011b matlab:\\n\"\n                \"'Windows cannot connect to the printer \u2014 Operation failed with error 0x0000011b'\\n\\n\"\n                \"Ye Microsoft ke Windows Update (KB5005565/KB5005566) ke baad\\n\"\n                \"aata hai \u2014 RPC encryption policy strict ho gayi hai.\\n\\n\"\n                \"HOST pe ye fixes honge:\\n\"\n                \"  1. RpcAuthnLevelPrivacyEnabled = 0  (KB5005565 rollback)\\n\"\n                \"  2. RestrictRemoteClients = 0  (RPC remote access allow)\\n\"\n                \"  3. EnableAuthEpResolution = 1\\n\"\n                \"  4. LanmanServer security relax\\n\"\n                \"  5. Spooler restart\\n\"\n                \"  6. Firewall rules verify\\n\\n\"\n                \"\u26a0 Sirf trusted/private LAN pe karo!\\nContinue karein?\"):\n            return\n        self._sharing_log(\"\u2550\"*56, C[\"border\"])\n        self._sharing_log(\"\ud83d\udd34 [HOST] Error 0x0000011b fix chal raha hai...\", C[\"error\"])\n        self._launch_job(\"fix_error_11b_host\", self._do_fix_error_11b_host)\n\n    def _do_fix_error_11b_host(self):\n        log = self._sharing_log\n        L = C\n\n        # Step 1 \u2014 RpcAuthnLevelPrivacyEnabled = 0 (THE main fix for 11b)\n        log(\"  [1/6] RpcAuthnLevelPrivacyEnabled = 0 (KB5005565 fix)...\", L[\"accent4\"])\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                \"RpcAuthnLevelPrivacyEnabled\", 0, winreg.REG_DWORD)\n            log(\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0  (HOST \u2014 RPC encryption relaxed)\", L[\"success\"])\n        except Exception as e:\n            # Fallback via reg command\n            self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\" /v RpcAuthnLevelPrivacyEnabled /t REG_DWORD /d 0 /f')\n            log(f\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0 (via reg cmd, {e})\", L[\"success\"])\n\n        # Step 2 \u2014 RestrictRemoteClients = 0\n        log(\"  [2/6] RPC RestrictRemoteClients = 0...\", L[\"accent4\"])\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SOFTWARE\\Policies\\Microsoft\\Windows NT\\Rpc\",\n                \"RestrictRemoteClients\", 0, winreg.REG_DWORD)\n            log(\"  \u2705 RestrictRemoteClients = 0\", L[\"success\"])\n        except Exception as e:\n            self._run_cmd('reg add \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Rpc\" /v RestrictRemoteClients /t REG_DWORD /d 0 /f')\n            log(f\"  \u2705 RestrictRemoteClients = 0 (reg cmd)\", L[\"success\"])\n\n        # Step 3 \u2014 EnableAuthEpResolution = 1\n        log(\"  [3/6] EnableAuthEpResolution = 1...\", L[\"accent4\"])\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SOFTWARE\\Policies\\Microsoft\\Windows NT\\Rpc\",\n                \"EnableAuthEpResolution\", 1, winreg.REG_DWORD)\n            log(\"  \u2705 EnableAuthEpResolution = 1\", L[\"success\"])\n        except Exception as e:\n            self._run_cmd('reg add \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Rpc\" /v EnableAuthEpResolution /t REG_DWORD /d 1 /f')\n            log(f\"  \u2705 EnableAuthEpResolution = 1 (reg cmd)\", L[\"success\"])\n\n        # Step 4 \u2014 LanmanServer security relax\n        log(\"  [4/6] LanmanServer security relax...\", L[\"accent4\"])\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanServer\\\\Parameters\" /v RequireSecuritySignature /t REG_DWORD /d 0 /f')\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanServer\\\\Parameters\" /v EnableSecuritySignature /t REG_DWORD /d 1 /f')\n        log(\"  \u2705 LanmanServer SMB signing: optional\", L[\"success\"])\n\n        # Step 5 \u2014 Spooler restart\n        log(\"  [5/6] Spooler restart...\", L[\"accent4\"])\n        self._run_cmd('net stop spooler /y')\n        time.sleep(1)\n        self._run_cmd('net start spooler')\n        out, _ = self._run_cmd('sc query Spooler')\n        log(\"  \u2705 Spooler: Running\" if \"RUNNING\" in out else \"  \u26a0 Spooler check karo\", L[\"success\"] if \"RUNNING\" in out else L[\"warning\"])\n\n        # Step 6 \u2014 Firewall printer rules\n        log(\"  [6/6] Firewall rules verify...\", L[\"accent4\"])\n        self._run_cmd('netsh advfirewall firewall set rule group=\"File and Printer Sharing\" new enable=Yes profile=any')\n        for port, proto, name in [(445,\"TCP\",\"SMB\"),(135,\"TCP\",\"RPC\"),(9100,\"TCP\",\"RAW\")]:\n            self._run_cmd(f'netsh advfirewall firewall add rule name=\"Godawari11b_{name}\" dir=in action=allow protocol={proto} localport={port} profile=any')\n        log(\"  \u2705 Firewall rules: set\", L[\"success\"])\n\n        log(\"\", L[\"text\"])\n        log(\"\u2705 [HOST] Error 0x0000011b FIX COMPLETE!\", L[\"success\"])\n        log(\"   \u25ba IMPORTANT: HOST + CLIENT dono pe ye fix karo!\", L[\"warning\"])\n        log(\"   \u25ba Phir HOST restart karo for registry to take effect.\", L[\"text_dim\"])\n        self.after(0, self._refresh_spooler_status)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \ud83d\udd34 ERROR 0x0000709 \u2014 AUTO-FIX  (CLIENT)\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _fix_error_709_client(self):\n        if not messagebox.askyesno(\"Fix Error 0x0000709 \u2014 CLIENT\",\n                \"CLIENT pe Error 0x0000709 fix:\\n\\n\"\n                \"  1. Spooler stop + clean + restart\\n\"\n                \"  2. UserSelectedDefault registry clear\\n\"\n                \"  3. LegacyDefaultPrinterMode = 1\\n\"\n                \"  4. AllowInsecureGuestAuth = 1\\n\"\n                \"  5. LimitBlankPasswordUse = 0\\n\"\n                \"  6. Spooler DLLs re-register\\n\"\n                \"  7. Spooler Auto + Start\\n\\n\"\n                \"Continue karein?\"):\n            return\n        self._sharing_log(\"\u2550\"*56, C[\"border\"])\n        self._sharing_log(\"\ud83d\udd34 [CLIENT] Error 0x0000709 fix chal raha hai...\", C[\"error\"])\n        self._launch_job(\"fix_error_709_client\", self._do_fix_error_709_client)\n\n    def _do_fix_error_709_client(self):\n        log = self._sharing_log\n        L = C\n\n        log(\"  [1/7] Spooler stop + spool clean...\", L[\"accent4\"])\n        self._run_cmd('net stop spooler /y')\n        time.sleep(1)\n        spool_dir = os.path.join(os.environ.get(\"SYSTEMROOT\",\"C:\\\\Windows\"),\"System32\",\"spool\",\"PRINTERS\")\n        deleted = 0\n        for f in Path(spool_dir).glob(\"*\"):\n            try: f.unlink(); deleted += 1\n            except: pass\n        log(f\"  \u2705 {deleted} spool files deleted\", L[\"success\"])\n\n        log(\"  [2/7] UserSelectedDefault registry clear...\", L[\"accent4\"])\n        try:\n            key = winreg.OpenKey(winreg.HKEY_CURRENT_USER,\n                r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows\",\n                0, winreg.KEY_SET_VALUE | winreg.KEY_READ)\n            try:\n                winreg.DeleteValue(key, \"UserSelectedDefault\")\n                log(\"  \u2705 UserSelectedDefault removed\", L[\"success\"])\n            except FileNotFoundError:\n                log(\"  \u2139 UserSelectedDefault not found \u2014 OK\", L[\"text_dim\"])\n            winreg.CloseKey(key)\n        except Exception as e:\n            log(f\"  \u26a0 {e}\", L[\"warning\"])\n\n        log(\"  [3/7] LegacyDefaultPrinterMode = 1 (Windows auto-manage OFF)...\", L[\"accent4\"])\n        try:\n            key2 = winreg.OpenKey(winreg.HKEY_CURRENT_USER,\n                r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows\",\n                0, winreg.KEY_SET_VALUE)\n            winreg.SetValueEx(key2, \"LegacyDefaultPrinterMode\", 0, winreg.REG_DWORD, 1)\n            winreg.CloseKey(key2)\n            log(\"  \u2705 LegacyDefaultPrinterMode = 1\", L[\"success\"])\n        except Exception as e:\n            log(f\"  \u26a0 {e}\", L[\"warning\"])\n\n        log(\"  [4/7] AllowInsecureGuestAuth = 1...\", L[\"accent4\"])\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Services\\LanmanWorkstation\\Parameters\",\n                \"AllowInsecureGuestAuth\", 1, winreg.REG_DWORD)\n            log(\"  \u2705 AllowInsecureGuestAuth = 1\", L[\"success\"])\n        except Exception as e:\n            log(f\"  \u26a0 {e}\", L[\"warning\"])\n\n        log(\"  [5/7] LimitBlankPasswordUse = 0...\", L[\"accent4\"])\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Lsa\" /v LimitBlankPasswordUse /t REG_DWORD /d 0 /f')\n        log(\"  \u2705 LimitBlankPasswordUse = 0\", L[\"success\"])\n\n        log(\"  [6/7] Spooler DLLs re-register...\", L[\"accent4\"])\n        sys32 = os.path.join(os.environ.get(\"SYSTEMROOT\",\"C:\\\\Windows\"), \"System32\")\n        for dll in [\"localspl.dll\",\"spoolss.dll\",\"win32spl.dll\"]:\n            path = os.path.join(sys32, dll)\n            if os.path.exists(path):\n                self._run_cmd(f'regsvr32 /s \"{path}\"')\n                log(f\"  \u2705 Registered: {dll}\", L[\"success\"])\n\n        log(\"  [7/7] Spooler Auto + Start...\", L[\"accent4\"])\n        self._run_cmd('sc config Spooler start= auto')\n        self._run_cmd('net start spooler')\n        time.sleep(1)\n        out, _ = self._run_cmd('sc query Spooler')\n        log(\"  \u2705 Spooler: Running!\" if \"RUNNING\" in out else \"  \u26a0 Spooler check karo\", L[\"success\"] if \"RUNNING\" in out else L[\"warning\"])\n\n        log(\"\", L[\"text\"])\n        log(\"\u2705 [CLIENT] Error 0x0000709 FIX COMPLETE!\", L[\"success\"])\n        log(\"   \u25ba Ab 'Detect Printers' karo aur default printer set karo.\", L[\"text_dim\"])\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \ud83d\udd34 ERROR 0x0000011b \u2014 AUTO-FIX  (CLIENT)\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _fix_error_11b_client(self):\n        if not messagebox.askyesno(\"Fix Error 0x0000011b \u2014 CLIENT\",\n                \"CLIENT pe Error 0x0000011b fix:\\n\\n\"\n                \"'Windows cannot connect to the printer \u2014 0x0000011b'\\n\"\n                \"Ye Windows Update KB5005565 ke baad aata hai.\\n\\n\"\n                \"  1. RpcAuthnLevelPrivacyEnabled = 0  \u2190 MAIN FIX\\n\"\n                \"  2. RestrictRemoteClients = 0\\n\"\n                \"  3. EnableAuthEpResolution = 1\\n\"\n                \"  4. LanmanWorkstation SMB signing relax\\n\"\n                \"  5. AllowInsecureGuestAuth = 1\\n\"\n                \"  6. Point &amp; Print restrictions relax\\n\"\n                \"  7. Firewall rules + Spooler restart\\n\\n\"\n                \"\u26a0 Sirf trusted LAN pe karo!\\nContinue karein?\"):\n            return\n        self._sharing_log(\"\u2550\"*56, C[\"border\"])\n        self._sharing_log(\"\ud83d\udd34 [CLIENT] Error 0x0000011b fix chal raha hai...\", C[\"error\"])\n        self._launch_job(\"fix_error_11b_client\", self._do_fix_error_11b_client)\n\n    def _do_fix_error_11b_client(self):\n        log = self._sharing_log\n        L = C\n\n        # Step 1 \u2014 THE main fix\n        log(\"  [1/7] RpcAuthnLevelPrivacyEnabled = 0  \u2190 MAIN FIX...\", L[\"accent4\"])\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                \"RpcAuthnLevelPrivacyEnabled\", 0, winreg.REG_DWORD)\n            log(\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0  (CLIENT)\", L[\"success\"])\n        except Exception as e:\n            self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\" /v RpcAuthnLevelPrivacyEnabled /t REG_DWORD /d 0 /f')\n            log(f\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0 (reg cmd, {e})\", L[\"success\"])\n\n        # Step 2 \u2014 RestrictRemoteClients\n        log(\"  [2/7] RestrictRemoteClients = 0...\", L[\"accent4\"])\n        self._run_cmd('reg add \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Rpc\" /v RestrictRemoteClients /t REG_DWORD /d 0 /f')\n        log(\"  \u2705 RestrictRemoteClients = 0\", L[\"success\"])\n\n        # Step 3 \u2014 EnableAuthEpResolution\n        log(\"  [3/7] EnableAuthEpResolution = 1...\", L[\"accent4\"])\n        self._run_cmd('reg add \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Rpc\" /v EnableAuthEpResolution /t REG_DWORD /d 1 /f')\n        log(\"  \u2705 EnableAuthEpResolution = 1\", L[\"success\"])\n\n        # Step 4 \u2014 LanmanWorkstation signing relax\n        log(\"  [4/7] LanmanWorkstation SMB signing relax...\", L[\"accent4\"])\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanWorkstation\\\\Parameters\" /v RequireSecuritySignature /t REG_DWORD /d 0 /f')\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanWorkstation\\\\Parameters\" /v EnableSecuritySignature /t REG_DWORD /d 1 /f')\n        log(\"  \u2705 LanmanWorkstation SMB signing: optional\", L[\"success\"])\n\n        # Step 5 \u2014 AllowInsecureGuestAuth\n        log(\"  [5/7] AllowInsecureGuestAuth = 1...\", L[\"accent4\"])\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Services\\LanmanWorkstation\\Parameters\",\n                \"AllowInsecureGuestAuth\", 1, winreg.REG_DWORD)\n            log(\"  \u2705 AllowInsecureGuestAuth = 1\", L[\"success\"])\n        except Exception as e:\n            log(f\"  \u26a0 {e}\", L[\"warning\"])\n\n        # Step 6 \u2014 Point &amp; Print relax\n        log(\"  [6/7] Point &amp; Print restrictions relax...\", L[\"accent4\"])\n        for cmd in [\n            'reg add \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Printers\\\\PointAndPrint\" /v NoWarningNoElevationOnInstall /t REG_DWORD /d 1 /f',\n            'reg add \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Printers\\\\PointAndPrint\" /v UpdatePromptSettings /t REG_DWORD /d 2 /f',\n            'reg add \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Printers\\\\PointAndPrint\" /v RestrictDriverInstallationToAdministrators /t REG_DWORD /d 0 /f',\n        ]:\n            self._run_cmd(cmd)\n        log(\"  \u2705 Point &amp; Print: relaxed\", L[\"success\"])\n\n        # Step 7 \u2014 Firewall + Spooler\n        log(\"  [7/7] Firewall + Spooler restart...\", L[\"accent4\"])\n        self._run_cmd('netsh advfirewall firewall set rule group=\"File and Printer Sharing\" new enable=Yes profile=any')\n        self._run_cmd('net stop spooler /y')\n        time.sleep(1)\n        self._run_cmd('net start spooler')\n        out, _ = self._run_cmd('sc query Spooler')\n        log(\"  \u2705 Spooler: Running\" if \"RUNNING\" in out else \"  \u26a0 Spooler check karo\", L[\"success\"] if \"RUNNING\" in out else L[\"warning\"])\n\n        log(\"\", L[\"text\"])\n        log(\"\u2705 [CLIENT] Error 0x0000011b FIX COMPLETE!\", L[\"success\"])\n        log(\"   \u25ba HOST pe bhi yahi fix karo!\", L[\"warning\"])\n        log(\"   \u25ba Phir computer restart karo \u2014 printer connect hoga.\", L[\"text_dim\"])\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \ud83d\ude80 MEGA AUTO-FIX \u2014 HOST (Sabkuch ek saath)\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \ud83d\udd34 ENTERPRISE PRINTER RECOVERY CENTER \u2014 Backend Methods\n    #  Tab 4: Network Printer Recovery \u2014 All repair logic\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    # \u2500\u2500 Internal logging helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_log(self, msg, color=None):\n        \"\"\"Log to repair log panel.\"\"\"\n        color = color or C[\"text\"]\n        self._append_log(getattr(self, \"epr_repair_log\", None) or\n                         getattr(self, \"printer_log\", None), msg, color)\n\n    def _epr_diag(self, msg, color=None):\n        \"\"\"Log to live diagnostics panel.\"\"\"\n        color = color or C[\"text\"]\n        self._append_log(getattr(self, \"epr_diag_log\", None) or\n                         getattr(self, \"printer_log\", None), msg, color)\n\n    def _epr_summary(self, msg, color=None):\n        \"\"\"Log to recovery summary panel.\"\"\"\n        color = color or C[\"text\"]\n        self._append_log(getattr(self, \"epr_summary_log\", None) or\n                         getattr(self, \"printer_log\", None), msg, color)\n\n    def _epr_detect_log(self, msg, color=None):\n        \"\"\"Log to auto-detection panel.\"\"\"\n        color = color or C[\"text\"]\n        self._append_log(getattr(self, \"epr_detect_log\", None) or\n                         getattr(self, \"printer_log\", None), msg, color)\n\n    def _epr_set_status(self, msg, color=None):\n        \"\"\"Update status label on the EPR tab.\"\"\"\n        color = color or C[\"accent4\"]\n        def _do():\n            try:\n                lbl = getattr(self, \"epr_status_lbl\", None)\n                if lbl:\n                    lbl.config(text=msg, fg=color)\n            except Exception:\n                pass\n        self.after(0, _do)\n\n    def _epr_progress_start(self):\n        def _do():\n            try:\n                p = getattr(self, \"epr_progress\", None)\n                if p:\n                    p.start(12)\n            except Exception:\n                pass\n        self.after(0, _do)\n\n    def _epr_progress_stop(self):\n        def _do():\n            try:\n                p = getattr(self, \"epr_progress\", None)\n                if p:\n                    p.stop()\n            except Exception:\n                pass\n        self.after(0, _do)\n\n    def _epr_submit(self, name, fn, *args, **kwargs):\n        \"\"\"Submit an EPR task to worker manager.\"\"\"\n        mgr = getattr(self, \"worker_manager\", None)\n        if mgr:\n            try:\n                mgr.submit(name, fn, *args, **kwargs)\n                return\n            except Exception:\n                pass\n        self._launch_job(\"bg_task\", fn, *args, **kwargs)\n\n    def _epr_reg_backup(self, hive, path, backup_name):\n        \"\"\"Backup a registry key before modifying it.\"\"\"\n        try:\n            backup_dir = Path(os.environ.get(\"TEMP\", \"C:\\\\Temp\")) / \"GodawariEPR_Backup\"\n            backup_dir.mkdir(parents=True, exist_ok=True)\n            ts = datetime.datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n            backup_file = str(backup_dir / f\"{backup_name}_{ts}.reg\")\n            hive_str = {\n                winreg.HKEY_LOCAL_MACHINE:  \"HKLM\",\n                winreg.HKEY_CURRENT_USER:   \"HKCU\",\n                winreg.HKEY_USERS:          \"HKU\",\n            }.get(hive, \"HKLM\")\n            self._run_cmd(f'reg export \"{hive_str}\\\\{path}\" \"{backup_file}\" /y', timeout=10)\n            return backup_file\n        except Exception:\n            return None\n\n    # \u2500\u2500 Auto Detection \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_auto_detect(self):\n        self._epr_submit(\"epr_auto_detect\", self._do_epr_auto_detect)\n\n    def _do_epr_auto_detect(self):\n        log = self._epr_detect_log\n        self._epr_progress_start()\n        self._epr_set_status(\"Running auto-detection...\", C[\"accent4\"])\n        log(\"\u2550\" * 54, C[\"border\"])\n        log(\"\ud83d\udd0d AUTO-DETECTION STARTING...\", C[\"accent\"])\n        issues = []\n\n        # 1. Spooler check\n        log(\"  [1/8] Checking Print Spooler...\", C[\"text_dim\"])\n        out, _ = self._run_cmd(\"sc query Spooler\", timeout=8)\n        if \"RUNNING\" not in out:\n            log(\"  \u274c Spooler NOT running\", C[\"error\"])\n            issues.append(\"Spooler stopped\")\n        else:\n            log(\"  \u2705 Spooler: Running\", C[\"success\"])\n\n        # 2. RPC setting check\n        log(\"  [2/8] Checking RpcAuthnLevelPrivacyEnabled...\", C[\"text_dim\"])\n        try:\n            key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                0, winreg.KEY_READ)\n            val, _ = winreg.QueryValueEx(key, \"RpcAuthnLevelPrivacyEnabled\")\n            winreg.CloseKey(key)\n            if val == 1:\n                log(\"  \u26a0 RpcAuthnLevelPrivacyEnabled = 1 (may block printer sharing)\", C[\"warning\"])\n                issues.append(\"RPC Privacy = 1 (error 0x0000011b risk)\")\n            else:\n                log(\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0 (OK)\", C[\"success\"])\n        except FileNotFoundError:\n            log(\"  \u2139 RpcAuthnLevelPrivacyEnabled not set (default=1 on patched Win11)\", C[\"warning\"])\n            issues.append(\"RPC Privacy key missing \u2014 may default to 1\")\n        except Exception as e:\n            log(f\"  \u26a0 RPC check failed: {e}\", C[\"warning\"])\n\n        # 3. Firewall check\n        log(\"  [3/8] Checking Firewall sharing rules...\", C[\"text_dim\"])\n        out2, _ = self._run_cmd(\n            'netsh advfirewall firewall show rule name=\"File and Printer Sharing (SMB-In)\" verbose',\n            timeout=10)\n        if \"Enabled\" not in out2 and \"Yes\" not in out2:\n            log(\"  \u274c File &amp; Printer Sharing firewall rules may be OFF\", C[\"error\"])\n            issues.append(\"Firewall sharing rules disabled\")\n        else:\n            log(\"  \u2705 Firewall: F&amp;P Sharing rules OK\", C[\"success\"])\n\n        # 4. Network discovery\n        log(\"  [4/8] Checking Network Discovery...\", C[\"text_dim\"])\n        out3, _ = self._run_cmd(\n            \"netsh advfirewall firewall show rule name=\\\"Network Discovery (NB-Datagram-In)\\\" verbose\",\n            timeout=10)\n        if \"Enabled\" not in out3 and \"Yes\" not in out3:\n            log(\"  \u26a0 Network Discovery may be disabled\", C[\"warning\"])\n            issues.append(\"Network Discovery disabled\")\n        else:\n            log(\"  \u2705 Network Discovery: OK\", C[\"success\"])\n\n        # 5. SMB1 check\n        log(\"  [5/8] Checking SMB services...\", C[\"text_dim\"])\n        out4, _ = self._run_cmd(\"sc query LanmanServer\", timeout=8)\n        if \"RUNNING\" not in out4:\n            log(\"  \u274c LanmanServer (Server service) NOT running\", C[\"error\"])\n            issues.append(\"LanmanServer stopped\")\n        else:\n            log(\"  \u2705 LanmanServer: Running\", C[\"success\"])\n\n        # 6. Point &amp; Print check\n        log(\"  [6/8] Checking Point &amp; Print restrictions...\", C[\"text_dim\"])\n        try:\n            key2 = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,\n                r\"SOFTWARE\\Policies\\Microsoft\\Windows NT\\Printers\\PointAndPrint\",\n                0, winreg.KEY_READ)\n            try:\n                restrict, _ = winreg.QueryValueEx(key2, \"Restricted\")\n                if restrict == 1:\n                    log(\"  \u26a0 Point &amp; Print Restricted = 1 (may block driver install)\", C[\"warning\"])\n                    issues.append(\"Point &amp; Print restriction active\")\n                else:\n                    log(\"  \u2705 Point &amp; Print: Not restricted\", C[\"success\"])\n            except FileNotFoundError:\n                log(\"  \u2705 Point &amp; Print: Default (OK)\", C[\"success\"])\n            winreg.CloseKey(key2)\n        except Exception:\n            log(\"  \u2139 Point &amp; Print GPO key not found (OK)\", C[\"text_dim\"])\n\n        # 7. Printer port reachability (if host/share entered)\n        host = getattr(self, \"epr_host_var\", tk.StringVar()).get().strip()\n        if host:\n            log(f\"  [7/8] Pinging host: {host}...\", C[\"text_dim\"])\n            out5, rc5 = self._run_cmd(f\"ping -n 2 -w 1000 {host}\", timeout=10)\n            if rc5 == 0 and \"TTL=\" in out5:\n                log(f\"  \u2705 Host reachable: {host}\", C[\"success\"])\n            else:\n                log(f\"  \u274c Host NOT reachable: {host}\", C[\"error\"])\n                issues.append(f\"Host unreachable: {host}\")\n        else:\n            log(\"  [7/8] Host not entered \u2014 skip ping\", C[\"text_dim\"])\n\n        # 8. Spool directory check\n        log(\"  [8/8] Checking spool directory...\", C[\"text_dim\"])\n        spool_dir = os.path.join(os.environ.get(\"SYSTEMROOT\", \"C:\\\\Windows\"),\n                                  \"System32\", \"spool\", \"PRINTERS\")\n        try:\n            stuck = list(Path(spool_dir).glob(\"*.SPL\")) + list(Path(spool_dir).glob(\"*.SHD\"))\n            if stuck:\n                log(f\"  \u26a0 {len(stuck)} stuck spool files found\", C[\"warning\"])\n                issues.append(f\"{len(stuck)} stuck spool files\")\n            else:\n                log(\"  \u2705 Spool directory: Clean\", C[\"success\"])\n        except Exception:\n            log(\"  \u2139 Spool check skipped (access issue)\", C[\"text_dim\"])\n\n        # Summary\n        log(\"\", C[\"text\"])\n        if issues:\n            log(f\"\u26a0 ISSUES DETECTED ({len(issues)}):\", C[\"warning\"])\n            for iss in issues:\n                log(f\"  \u2022 {iss}\", C[\"error\"])\n            log(\"\", C[\"text\"])\n            log(\"\u2192 Click FULL AUTO FIX to repair all detected issues.\", C[\"accent4\"])\n        else:\n            log(\"\u2705 No major issues detected! Network printer should work.\", C[\"success\"])\n\n        self._epr_progress_stop()\n        self._epr_set_status(\n            f\"Detection complete \u2014 {len(issues)} issue(s) found\",\n            C[\"error\"] if issues else C[\"success\"])\n\n    # \u2500\u2500 Full Auto Fix \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_full_auto_fix(self):\n        if not messagebox.askyesno(\n            \"\ud83d\ude80 FULL AUTO FIX \u2014 Enterprise Printer Recovery\",\n            \"This will automatically perform 18 repair steps:\\n\\n\"\n            \"  1.  Diagnose printer sharing problems\\n\"\n            \"  2.  Detect root cause\\n\"\n            \"  3.  Repair Print Spooler\\n\"\n            \"  4.  Repair RPC + SMB issues\\n\"\n            \"  5.  Repair Point &amp; Print restrictions\\n\"\n            \"  6.  Repair firewall sharing rules\\n\"\n            \"  7.  Repair network discovery\\n\"\n            \"  8.  Repair printer sharing settings\\n\"\n            \"  9.  Repair broken printer cache\\n\"\n            \" 10. Remove corrupted printer mappings\\n\"\n            \" 11. Repair Canon printer compatibility\\n\"\n            \" 12. Detect x86/x64 driver mismatch\\n\"\n            \" 13. Repair driver installation issues\\n\"\n            \" 14. Validate printer reachability\\n\"\n            \" 15. Reconnect shared printer\\n\"\n            \" 16. Validate successful printer installation\\n\"\n            \" 17. Generate repair summary\\n\"\n            \" 18. Log all actions safely\\n\\n\"\n            \"\u26a0 Run as Administrator for full effect.\\n\"\n            \"Continue?\"):\n            return\n        self._epr_submit(\"epr_full_auto_fix\", self._do_epr_full_auto_fix)\n\n    def _do_epr_full_auto_fix(self):\n        log  = self._epr_log\n        diag = self._epr_diag\n        summ = self._epr_summary\n        self._epr_progress_start()\n        results = []\n\n        def step(n, total, msg):\n            self._epr_set_status(f\"[{n}/{total}] {msg}\", C[\"accent4\"])\n            log(f\"\\n[{n:02d}/{total}] {msg}\", C[\"accent4\"])\n            diag(f\"  \u25ba {msg}\", C[\"text_dim\"])\n\n        log(\"\u2550\" * 56, C[\"border\"])\n        log(\"\ud83d\ude80 FULL AUTO FIX \u2014 Enterprise Network Printer Recovery\", C[\"error\"])\n        log(\"\u2550\" * 56, C[\"border\"])\n\n        TOTAL = 18\n\n        # \u2500\u2500 Step 1: Diagnose \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(1, TOTAL, \"Diagnosing printer sharing problems\")\n        self._do_epr_auto_detect()\n        results.append(\"\u2705 Diagnosis complete\")\n\n        # \u2500\u2500 Step 2: Detect root cause \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(2, TOTAL, \"Detecting root cause (RPC, spooler, firewall)\")\n        rpc_broken = False\n        spooler_broken = False\n        try:\n            key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\", 0, winreg.KEY_READ)\n            try:\n                val, _ = winreg.QueryValueEx(key, \"RpcAuthnLevelPrivacyEnabled\")\n                rpc_broken = (val == 1)\n            except FileNotFoundError:\n                rpc_broken = True   # missing = system default may be 1 on patched Win11\n            winreg.CloseKey(key)\n        except Exception:\n            rpc_broken = True\n\n        out_sp, _ = self._run_cmd(\"sc query Spooler\", timeout=8)\n        spooler_broken = \"RUNNING\" not in out_sp\n        log(f\"  RPC broken: {rpc_broken}  |  Spooler broken: {spooler_broken}\", C[\"text_dim\"])\n        results.append(f\"\u2705 Root cause: RPC={rpc_broken}, Spooler={spooler_broken}\")\n\n        # \u2500\u2500 Step 3: Repair Spooler \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(3, TOTAL, \"Repairing Print Spooler\")\n        self._run_cmd(\"net stop spooler /y\", timeout=8)\n        time.sleep(1)\n        spool_dir = os.path.join(os.environ.get(\"SYSTEMROOT\", \"C:\\\\Windows\"),\n                                  \"System32\", \"spool\", \"PRINTERS\")\n        cleared = 0\n        try:\n            for f in Path(spool_dir).glob(\"*\"):\n                try:\n                    f.unlink(); cleared += 1\n                except Exception:\n                    pass\n        except Exception:\n            pass\n        self._run_cmd(\"sc config Spooler start= auto\")\n        self._run_cmd(\"net start spooler\", timeout=8)\n        time.sleep(1)\n        out_sp2, _ = self._run_cmd(\"sc query Spooler\", timeout=8)\n        ok = \"RUNNING\" in out_sp2\n        log(f\"  {'\u2705' if ok else '\u274c'} Spooler: {'Running' if ok else 'FAILED'} | {cleared} spool files cleared\",\n            C[\"success\"] if ok else C[\"error\"])\n        results.append(f\"{'\u2705' if ok else '\u274c'} Spooler repair\")\n\n        # \u2500\u2500 Step 4: RPC + SMB repair \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(4, TOTAL, \"Repairing RPC + SMB issues\")\n        self._epr_reg_backup(winreg.HKEY_LOCAL_MACHINE,\n            r\"SYSTEM\\CurrentControlSet\\Control\\Print\", \"RpcPrint_backup\")\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                \"RpcAuthnLevelPrivacyEnabled\", 0, winreg.REG_DWORD)\n            log(\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0\", C[\"success\"])\n        except Exception:\n            self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\" /v RpcAuthnLevelPrivacyEnabled /t REG_DWORD /d 0 /f')\n            log(\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0 (via reg cmd)\", C[\"success\"])\n\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SOFTWARE\\Policies\\Microsoft\\Windows NT\\Rpc\",\n                \"RestrictRemoteClients\", 0, winreg.REG_DWORD)\n            log(\"  \u2705 RestrictRemoteClients = 0\", C[\"success\"])\n        except Exception:\n            self._run_cmd('reg add \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Rpc\" /v RestrictRemoteClients /t REG_DWORD /d 0 /f')\n\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanServer\\\\Parameters\" /v RequireSecuritySignature /t REG_DWORD /d 0 /f')\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanWorkstation\\\\Parameters\" /v RequireSecuritySignature /t REG_DWORD /d 0 /f')\n        log(\"  \u2705 SMB signing: optional on both sides\", C[\"success\"])\n        results.append(\"\u2705 RPC + SMB repaired\")\n\n        # \u2500\u2500 Step 5: Point &amp; Print \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(5, TOTAL, \"Repairing Point &amp; Print restrictions\")\n        self._do_epr_point_print_repair_silent()\n        results.append(\"\u2705 Point &amp; Print repaired\")\n\n        # \u2500\u2500 Step 6: Firewall \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(6, TOTAL, \"Repairing firewall sharing rules\")\n        self._do_epr_firewall_fix_silent()\n        results.append(\"\u2705 Firewall rules applied\")\n\n        # \u2500\u2500 Step 7: Network discovery \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(7, TOTAL, \"Repairing network discovery\")\n        self._do_epr_enable_netdiscovery_silent()\n        results.append(\"\u2705 Network discovery enabled\")\n\n        # \u2500\u2500 Step 8: Printer sharing settings \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(8, TOTAL, \"Repairing printer sharing settings\")\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanServer\\\\Parameters\" /v AutoShareServer /t REG_DWORD /d 1 /f')\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanServer\\\\Parameters\" /v AutoShareWks /t REG_DWORD /d 1 /f')\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Lsa\" /v LimitBlankPasswordUse /t REG_DWORD /d 0 /f')\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanWorkstation\\\\Parameters\" /v AllowInsecureGuestAuth /t REG_DWORD /d 1 /f')\n        log(\"  \u2705 Sharing settings: AutoShare + LimitBlank + GuestAuth\", C[\"success\"])\n        results.append(\"\u2705 Sharing settings repaired\")\n\n        # \u2500\u2500 Step 9: Printer cache \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(9, TOTAL, \"Repairing broken printer cache\")\n        self._do_epr_cache_cleaner_silent()\n        results.append(\"\u2705 Printer cache cleaned\")\n\n        # \u2500\u2500 Step 10: Remove corrupted mappings \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(10, TOTAL, \"Removing corrupted printer mappings\")\n        removed = 0\n        try:\n            ps_script = (\n                \"$printers = Get-Printer -ErrorAction SilentlyContinue | \"\n                \"Where-Object {$_.PrinterStatus -eq 'Error' -or $_.PrinterStatus -eq 'Offline'};\"\n                \"foreach ($p in $printers) { Remove-Printer -Name $p.Name -ErrorAction SilentlyContinue; \"\n                \"Write-Output \\\"REMOVED:$($p.Name)\\\" }\"\n            )\n            out_rm = self._run_cmd(\n                f'powershell -NoProfile -Command \"{ps_script}\"', timeout=30)\n            out_str = out_rm[0] if isinstance(out_rm, tuple) else str(out_rm)\n            removed = out_str.count(\"REMOVED:\")\n            log(f\"  \u2705 {removed} corrupted printer mapping(s) removed\", C[\"success\"])\n        except Exception as e:\n            log(f\"  \u26a0 Mapping removal: {e}\", C[\"warning\"])\n        results.append(f\"\u2705 Removed {removed} corrupted mapping(s)\")\n\n        # \u2500\u2500 Step 11: Canon compatibility \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(11, TOTAL, \"Repairing Canon printer compatibility\")\n        self._do_epr_canon_fix_silent()\n        results.append(\"\u2705 Canon compatibility applied\")\n\n        # \u2500\u2500 Step 12: Driver mismatch detection \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(12, TOTAL, \"Detecting x86/x64 driver mismatch\")\n        arch_ok = self._do_epr_check_driver_arch()\n        results.append(f\"{'\u2705' if arch_ok else '\u26a0'} Driver arch: {'OK' if arch_ok else 'Mismatch detected'}\")\n\n        # \u2500\u2500 Step 13: Driver repair \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(13, TOTAL, \"Repairing driver installation issues\")\n        sys32 = os.path.join(os.environ.get(\"SYSTEMROOT\", \"C:\\\\Windows\"), \"System32\")\n        for dll in [\"localspl.dll\", \"spoolss.dll\", \"win32spl.dll\", \"winspool.drv\"]:\n            path = os.path.join(sys32, dll)\n            if os.path.exists(path):\n                self._run_cmd(f'regsvr32 /s \"{path}\"')\n        log(\"  \u2705 Spooler DLLs re-registered\", C[\"success\"])\n        results.append(\"\u2705 Driver DLLs re-registered\")\n\n        # \u2500\u2500 Step 14: Validate reachability \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(14, TOTAL, \"Validating printer reachability\")\n        host = getattr(self, \"epr_host_var\", tk.StringVar()).get().strip()\n        if host:\n            safe_host = re.sub(r\"[^A-Za-z0-9_.:-]\", \"\", host)\n            out_ping, rc_ping = self._run_cmd(f\"ping -n 1 -w 1000 {safe_host}\", timeout=5)\n            reachable = rc_ping == 0 and \"TTL=\" in out_ping.upper()\n            log(f\"  {'\u2705' if reachable else '\u274c'} Host {host}: {'reachable' if reachable else 'unreachable'}\", C[\"success\"] if reachable else C[\"error\"])\n            results.append(f\"{'\u2705' if reachable else '\u274c'} Host reachability: {host}\")\n        else:\n            log(\"  \u2139 Host not specified \u2014 skip ping test\", C[\"text_dim\"])\n            results.append(\"\u2139 Host reachability: skipped (no host entered)\")\n\n        # \u2500\u2500 Step 15: Reconnect shared printer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(15, TOTAL, \"Reconnecting shared printer\")\n        share = getattr(self, \"epr_share_var\", tk.StringVar()).get().strip()\n        if host and share:\n            safe_host = re.sub(r\"[^A-Za-z0-9_.:-]\", \"\", host)\n            safe_share = re.sub(r\"[^A-Za-z0-9_.$ -]\", \"\", share).strip()\n            unc = f\"\\\\\\\\{safe_host}\\\\{safe_share}\"\n            out_nu, rc_nu = self._run_cmd(f'net use \"{unc}\" /persistent:yes', timeout=8)\n            if rc_nu == 0 or \"completed\" in out_nu.lower():\n                log(f\"  \u2705 Connected to: {unc}\", C[\"success\"])\n                results.append(f\"\u2705 Reconnected: {unc}\")\n            else:\n                log(f\"  \u26a0 net use result: {out_nu[:100]}\", C[\"warning\"])\n                results.append(f\"\u26a0 Reconnect attempted: {unc}\")\n        else:\n            log(\"  \u2139 Host/Share not specified \u2014 skip reconnect\", C[\"text_dim\"])\n            results.append(\"\u2139 Reconnect: skipped (enter Host IP and Share Name above)\")\n\n        # \u2500\u2500 Step 16: Validate installation \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(16, TOTAL, \"Validating successful printer installation\")\n        out_list, _ = self._run_cmd(\n            'powershell -NoProfile -Command \"Get-Printer | Select-Object Name,PrinterStatus | ConvertTo-Csv -NoTypeInformation\"',\n            timeout=12)\n        printer_count = max(0, out_list.count(\"\\n\") - 1)\n        log(f\"  \u2705 {printer_count} printer(s) found after repair\", C[\"success\"])\n        results.append(f\"\u2705 Validation: {printer_count} printer(s) visible\")\n\n        # \u2500\u2500 Step 17: Spooler final restart \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(17, TOTAL, \"Final spooler restart + service validation\")\n        self._run_cmd(\"net stop spooler /y\", timeout=8)\n        time.sleep(1)\n        self._run_cmd(\"net start spooler\", timeout=8)\n        out_final, _ = self._run_cmd(\"sc query Spooler\", timeout=8)\n        spooler_ok = \"RUNNING\" in out_final\n        log(f\"  {'\u2705' if spooler_ok else '\u274c'} Final spooler state: {'Running' if spooler_ok else 'STOPPED'}\", C[\"success\"] if spooler_ok else C[\"error\"])\n        self.after(0, self._refresh_spooler_status)\n\n        # \u2500\u2500 Step 18: Generate summary \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(18, TOTAL, \"Generating repair summary + logging\")\n        ts = datetime.datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\")\n        summ(\"\u2550\" * 50, C[\"border\"])\n        summ(f\"\ud83d\udd34 ENTERPRISE PRINTER RECOVERY \u2014 SUMMARY\", C[\"accent\"])\n        summ(f\"   Completed at: {ts}\", C[\"text_dim\"])\n        summ(\"\", C[\"text\"])\n        for r in results:\n            color = C[\"success\"] if r.startswith(\"\u2705\") else (C[\"error\"] if r.startswith(\"\u274c\") else C[\"warning\"])\n            summ(f\"  {r}\", color)\n        summ(\"\", C[\"text\"])\n        passed = sum(1 for r in results if r.startswith(\"\u2705\"))\n        failed = sum(1 for r in results if r.startswith(\"\u274c\"))\n        summ(f\"  Total: {passed} passed / {failed} failed / {len(results)} steps\", C[\"accent4\"])\n        if failed == 0:\n            summ(\"  \u25ba REPAIR SUCCESSFUL \u2014 Try your printer now!\", C[\"success\"])\n            summ(\"  \u25ba Restart this PC if printer still not working.\", C[\"text_dim\"])\n        else:\n            summ(\"  \u25ba Some steps had issues \u2014 check Repair Log for details.\", C[\"warning\"])\n            summ(\"  \u25ba Try individual repair buttons for failed steps.\", C[\"text_dim\"])\n        summ(\"\u2550\" * 50, C[\"border\"])\n\n        self._epr_progress_stop()\n        self._epr_set_status(\n            f\"COMPLETE \u2014 {passed}/{len(results)} steps passed\",\n            C[\"success\"] if failed == 0 else C[\"warning\"])\n\n        # Structured log\n        try:\n            lg = getattr(self, \"structured_logger\", None)\n            if lg:\n                lg.log(\"epr_full_auto_fix\", \"Full Auto Fix completed\", {\n                    \"passed\": passed, \"failed\": failed, \"steps\": len(results)})\n        except Exception:\n            pass\n\n    # \u2500\u2500 Connection Tester Methods \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_ping_host(self):\n        host = getattr(self, \"epr_host_var\", tk.StringVar()).get().strip()\n        if not host:\n            messagebox.showinfo(\"Host IP\", \"Host IP ya naam enter karo upar.\")\n            return\n        self._epr_submit(\"epr_ping\", self._do_epr_ping, host)\n\n    def _do_epr_ping(self, host):\n        self._epr_set_status(f\"Pinging {host}...\")\n        self._epr_diag(f\"\ud83d\udd0c Pinging {host}...\", C[\"text_dim\"])\n        out, rc = self._run_cmd(f\"ping -n 4 -w 1000 {host}\", timeout=12)\n        if rc == 0 and \"TTL=\" in out:\n            self._epr_diag(f\"  \u2705 Host reachable: {host}\", C[\"success\"])\n            self._epr_set_status(f\"\u2705 {host} is reachable\", C[\"success\"])\n        else:\n            self._epr_diag(f\"  \u274c Host NOT reachable: {host}\", C[\"error\"])\n            self._epr_set_status(f\"\u274c {host} unreachable \u2014 check IP/network\", C[\"error\"])\n\n    def _epr_test_smb(self):\n        host  = getattr(self, \"epr_host_var\",  tk.StringVar()).get().strip()\n        share = getattr(self, \"epr_share_var\", tk.StringVar()).get().strip()\n        if not host:\n            messagebox.showinfo(\"Host\", \"Host IP enter karo.\")\n            return\n        self._epr_submit(\"epr_smb_test\", self._do_epr_test_smb, host, share)\n\n    def _do_epr_test_smb(self, host, share):\n        self._epr_set_status(f\"Testing SMB: \\\\\\\\{host}...\")\n        self._epr_diag(f\"\ud83d\uddc2 Testing SMB share: \\\\\\\\{host}\\\\{share or '*'}\", C[\"text_dim\"])\n        unc = f\"\\\\\\\\{host}\" if not share else f\"\\\\\\\\{host}\\\\{share}\"\n        out, rc = self._run_cmd(f'net use \"{unc}\" /persistent:no', timeout=12)\n        if rc == 0 or \"completed\" in out.lower():\n            self._epr_diag(f\"  \u2705 SMB accessible: {unc}\", C[\"success\"])\n            self._epr_set_status(f\"\u2705 SMB OK: {unc}\", C[\"success\"])\n        else:\n            # Try listing\n            out2, rc2 = self._run_cmd(f'dir \"{unc}\"', timeout=8)\n            if rc2 == 0:\n                self._epr_diag(f\"  \u2705 SMB share visible: {unc}\", C[\"success\"])\n                self._epr_set_status(f\"\u2705 SMB OK\", C[\"success\"])\n            else:\n                self._epr_diag(f\"  \u274c SMB not accessible: {unc}\", C[\"error\"])\n                self._epr_diag(f\"     Result: {out[:120]}\", C[\"text_dim\"])\n                self._epr_set_status(f\"\u274c SMB failed \u2014 check sharing settings\", C[\"error\"])\n\n    def _epr_validate_printer(self):\n        host  = getattr(self, \"epr_host_var\",  tk.StringVar()).get().strip()\n        share = getattr(self, \"epr_share_var\", tk.StringVar()).get().strip()\n        if not host or not share:\n            messagebox.showinfo(\"Input\", \"Host IP aur Share Name dono enter karo.\")\n            return\n        self._epr_submit(\"epr_validate\", self._do_epr_validate_printer, host, share)\n\n    def _do_epr_validate_printer(self, host, share):\n        unc = f\"\\\\\\\\{host}\\\\{share}\"\n        self._epr_set_status(f\"Validating: {unc}...\")\n        self._epr_diag(f\"\ud83d\udda8 Validating printer path: {unc}\", C[\"text_dim\"])\n        out, rc = self._run_cmd(f'rundll32 printui.dll,PrintUIEntry /ga /n\"{unc}\"', timeout=15)\n        if rc == 0:\n            self._epr_diag(f\"  \u2705 Printer connection validated: {unc}\", C[\"success\"])\n            self._epr_set_status(f\"\u2705 Printer reachable: {unc}\", C[\"success\"])\n        else:\n            # Fallback: add printer via PowerShell\n            ps = f'Add-Printer -ConnectionName \"{unc}\" -ErrorAction SilentlyContinue; if ($?) {{ \"OK\" }} else {{ \"FAIL\" }}'\n            out2, _ = self._run_cmd(f'powershell -NoProfile -Command \"{ps}\"', timeout=20)\n            if \"OK\" in out2:\n                self._epr_diag(f\"  \u2705 Printer added via PowerShell: {unc}\", C[\"success\"])\n                self._epr_set_status(f\"\u2705 Printer added\", C[\"success\"])\n            else:\n                self._epr_diag(f\"  \u274c Could not connect to printer: {unc}\", C[\"error\"])\n                self._epr_set_status(f\"\u274c Printer not reachable \u2014 run FULL AUTO FIX\", C[\"error\"])\n\n    def _epr_reconnect_shared(self):\n        host  = getattr(self, \"epr_host_var\",  tk.StringVar()).get().strip()\n        share = getattr(self, \"epr_share_var\", tk.StringVar()).get().strip()\n        if not host or not share:\n            messagebox.showinfo(\"Input\", \"Host IP aur Share Name dono enter karo.\")\n            return\n        if not messagebox.askyesno(\"Reconnect Shared Printer\",\n                f\"Printer reconnect hoga:\\n\\\\\\\\{host}\\\\{share}\\n\\nContinue?\"):\n            return\n        self._epr_submit(\"epr_reconnect\", self._do_epr_reconnect_shared, host, share)\n\n    def _do_epr_reconnect_shared(self, host, share):\n        log = self._epr_log\n        unc = f\"\\\\\\\\{host}\\\\{share}\"\n        self._epr_set_status(f\"Reconnecting: {unc}...\")\n        log(f\"\ud83d\udd17 Reconnecting shared printer: {unc}\", C[\"accent4\"])\n\n        # Remove old connection\n        self._run_cmd(f'net use \"{unc}\" /delete /y', timeout=10)\n        log(\"  \u2139 Old connection removed\", C[\"text_dim\"])\n\n        # Firewall\n        self._run_cmd('netsh advfirewall firewall set rule group=\"File and Printer Sharing\" new enable=Yes profile=any')\n        log(\"  \u2705 Firewall rules: ON\", C[\"success\"])\n\n        # RPC fix\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                \"RpcAuthnLevelPrivacyEnabled\", 0, winreg.REG_DWORD)\n        except Exception:\n            self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\" /v RpcAuthnLevelPrivacyEnabled /t REG_DWORD /d 0 /f')\n        log(\"  \u2705 RPC setting: OK\", C[\"success\"])\n\n        # Reconnect\n        out, rc = self._run_cmd(f'net use \"{unc}\" /persistent:yes', timeout=15)\n        if rc == 0 or \"completed\" in out.lower():\n            log(f\"  \u2705 Connected: {unc}\", C[\"success\"])\n        else:\n            log(f\"  \u26a0 net use: {out[:120]}\", C[\"warning\"])\n\n        # Add as printer\n        ps = f'Add-Printer -ConnectionName \"{unc}\" -ErrorAction SilentlyContinue'\n        self._run_cmd(f'powershell -NoProfile -Command \"{ps}\"', timeout=20)\n        log(f\"  \u2705 Printer install attempted: {unc}\", C[\"success\"])\n\n        # Spooler restart\n        self._run_cmd(\"net stop spooler /y\"); time.sleep(1)\n        self._run_cmd(\"net start spooler\")\n        log(\"  \u2705 Spooler restarted\", C[\"success\"])\n        log(\"\u2705 Shared printer reconnect complete!\", C[\"success\"])\n        self._epr_set_status(\"\u2705 Reconnect complete\", C[\"success\"])\n\n    # \u2500\u2500 Firewall &amp; Network Discovery \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_firewall_fix(self):\n        self._epr_submit(\"epr_fw_fix\", self._do_epr_firewall_fix_silent)\n\n    def _do_epr_firewall_fix_silent(self):\n        self._epr_set_status(\"Applying firewall rules...\")\n        cmds = [\n            'netsh advfirewall firewall set rule group=\"File and Printer Sharing\" new enable=Yes profile=any',\n            'netsh advfirewall firewall set rule group=\"Network Discovery\" new enable=Yes profile=Private',\n            'netsh advfirewall firewall add rule name=\"EPR_SMB_In\" dir=in action=allow protocol=TCP localport=445 profile=any',\n            'netsh advfirewall firewall add rule name=\"EPR_SMB_Out\" dir=out action=allow protocol=TCP localport=445 profile=any',\n            'netsh advfirewall firewall add rule name=\"EPR_RPC_In\" dir=in action=allow protocol=TCP localport=135 profile=any',\n            'netsh advfirewall firewall add rule name=\"EPR_RAW_In\" dir=in action=allow protocol=TCP localport=9100 profile=any',\n            'netsh advfirewall firewall add rule name=\"EPR_NetBIOS_In\" dir=in action=allow protocol=TCP localport=139 profile=any',\n        ]\n        for cmd in cmds:\n            self._run_cmd(cmd, timeout=10)\n        self._epr_log(\"  \u2705 Firewall sharing rules applied\", C[\"success\"])\n        self._epr_set_status(\"\u2705 Firewall rules applied\", C[\"success\"])\n\n    def _epr_enable_netdiscovery(self):\n        self._epr_submit(\"epr_netdisc\", self._do_epr_enable_netdiscovery_silent)\n\n    def _do_epr_enable_netdiscovery_silent(self):\n        self._epr_set_status(\"Enabling network discovery...\")\n        self._run_cmd('netsh advfirewall firewall set rule group=\"Network Discovery\" new enable=Yes profile=Private')\n        # FD services\n        for svc in [\"FDResPub\", \"fdPHost\", \"SSDPSRV\", \"upnphost\"]:\n            self._run_cmd(f\"sc config {svc} start= auto\")\n            self._run_cmd(f\"net start {svc}\")\n        self._epr_log(\"  \u2705 Network discovery enabled + FD services started\", C[\"success\"])\n        self._epr_set_status(\"\u2705 Network discovery: ON\", C[\"success\"])\n\n    # \u2500\u2500 Network Share Validator \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_net_share_validator(self):\n        host  = getattr(self, \"epr_host_var\",  tk.StringVar()).get().strip()\n        share = getattr(self, \"epr_share_var\", tk.StringVar()).get().strip()\n        if not host:\n            messagebox.showinfo(\"Host\", \"Host IP enter karo.\")\n            return\n        self._epr_submit(\"epr_nsv\", self._do_epr_net_share_validator, host, share)\n\n    def _do_epr_net_share_validator(self, host, share):\n        log = self._epr_diag\n        self._epr_set_status(f\"Validating share: \\\\\\\\{host}...\")\n        log(f\"\ud83c\udf10 Network Share Validator: \\\\\\\\{host}\\\\{share or ''}\", C[\"accent4\"])\n\n        # Ping\n        out, rc = self._run_cmd(f\"ping -n 2 -w 1000 {host}\", timeout=8)\n        log(f\"  Ping: {'\u2705 OK' if (rc==0 and 'TTL=' in out) else '\u274c FAIL'}\", C[\"success\"] if (rc==0 and \"TTL=\" in out) else C[\"error\"])\n\n        # Port 445\n        ps445 = f\"Test-NetConnection -ComputerName {host} -Port 445 -InformationLevel Quiet 2&gt;$null\"\n        out445, _ = self._run_cmd(f'powershell -NoProfile -Command \"{ps445}\"', timeout=10)\n        log(f\"  Port 445: {'\u2705 Open' if 'True' in out445 else '\u274c Closed/Filtered'}\", C[\"success\"] if \"True\" in out445 else C[\"error\"])\n\n        # Port 139\n        ps139 = f\"Test-NetConnection -ComputerName {host} -Port 139 -InformationLevel Quiet 2&gt;$null\"\n        out139, _ = self._run_cmd(f'powershell -NoProfile -Command \"{ps139}\"', timeout=10)\n        log(f\"  Port 139: {'\u2705 Open' if 'True' in out139 else '\u26a0 Closed'}\", C[\"success\"] if \"True\" in out139 else C[\"warning\"])\n\n        # Share list\n        if share:\n            out_nu, rc_nu = self._run_cmd(f'net use \"\\\\\\\\{host}\\\\{share}\" /persistent:no', timeout=12)\n            log(f\"  Share: {'\u2705 Accessible' if (rc_nu==0 or 'completed' in out_nu.lower()) else '\u274c Not accessible'}\", C[\"success\"] if (rc_nu==0) else C[\"error\"])\n\n        self._epr_set_status(\"\u2705 Share validation done\", C[\"success\"])\n\n    # \u2500\u2500 Smart Spooler Recovery \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_smart_spooler(self):\n        if not messagebox.askyesno(\"Smart Spooler Recovery\",\n                \"Deep spooler repair:\\n\"\n                \"1. Stop spooler + dependents\\n\"\n                \"2. Clear spool directory\\n\"\n                \"3. Re-register spooler DLLs\\n\"\n                \"4. Repair spooler registry\\n\"\n                \"5. Restart spooler\\n\\nContinue?\"):\n            return\n        self._epr_submit(\"epr_smart_spooler\", self._do_epr_smart_spooler)\n\n    def _do_epr_smart_spooler(self):\n        log = self._epr_log\n        self._epr_set_status(\"Smart Spooler Recovery running...\")\n        log(\"\u2550\" * 48, C[\"border\"])\n        log(\"\u26a1 Smart Spooler Recovery\", C[\"accent4\"])\n\n        # Stop dependent services\n        for svc in [\"RpcSs\", \"SENS\"]:\n            pass   # don't stop critical services\n        self._run_cmd(\"net stop spooler /y\"); time.sleep(1)\n        log(\"  \u2705 Spooler stopped\", C[\"success\"])\n\n        # Clear spool directory\n        spool = Path(os.environ.get(\"SYSTEMROOT\", \"C:\\\\Windows\")) / \"System32\" / \"spool\" / \"PRINTERS\"\n        n = 0\n        for f in spool.glob(\"*\"):\n            try: f.unlink(); n += 1\n            except Exception: pass\n        log(f\"  \u2705 {n} spool files cleared\", C[\"success\"])\n\n        # Re-register DLLs\n        sys32 = os.path.join(os.environ.get(\"SYSTEMROOT\", \"C:\\\\Windows\"), \"System32\")\n        for dll in [\"localspl.dll\", \"spoolss.dll\", \"win32spl.dll\", \"winspool.drv\", \"ntprint.dll\"]:\n            p = os.path.join(sys32, dll)\n            if os.path.exists(p):\n                self._run_cmd(f'regsvr32 /s \"{p}\"')\n        log(\"  \u2705 Spooler DLLs re-registered\", C[\"success\"])\n\n        # Registry repair\n        self._run_cmd('sc config Spooler start= auto')\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\Spooler\" /v Start /t REG_DWORD /d 2 /f')\n\n        # Start spooler\n        self._run_cmd(\"net start spooler\"); time.sleep(2)\n        out, _ = self._run_cmd(\"sc query Spooler\", timeout=8)\n        ok = \"RUNNING\" in out\n        log(f\"  {'\u2705 Spooler: Running!' if ok else '\u274c Spooler failed to start'}\", C[\"success\"] if ok else C[\"error\"])\n        self.after(0, self._refresh_spooler_status)\n        self._epr_set_status(\"\u2705 Smart Spooler Recovery complete\" if ok else \"\u274c Spooler still failing\", C[\"success\"] if ok else C[\"error\"])\n\n    # \u2500\u2500 RPC + SMB Repair \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_rpc_smb_repair(self):\n        if not messagebox.askyesno(\"RPC + SMB Repair\",\n                \"This will:\\n\"\n                \"1. Set RpcAuthnLevelPrivacyEnabled = 0\\n\"\n                \"2. Set RestrictRemoteClients = 0\\n\"\n                \"3. Enable SMB signing optional\\n\"\n                \"4. Enable AllowInsecureGuestAuth\\n\"\n                \"5. Restart spooler\\n\\nContinue?\"):\n            return\n        self._epr_submit(\"epr_rpc_smb\", self._do_epr_rpc_smb)\n\n    def _do_epr_rpc_smb(self):\n        log = self._epr_log\n        self._epr_set_status(\"RPC + SMB Repair running...\")\n        log(\"\u2550\" * 48, C[\"border\"])\n        log(\"\ud83d\udd27 RPC + SMB Repair\", C[\"accent4\"])\n\n        self._epr_reg_backup(winreg.HKEY_LOCAL_MACHINE,\n            r\"SYSTEM\\CurrentControlSet\\Control\\Print\", \"RPC_backup\")\n\n        # RpcAuthnLevelPrivacyEnabled\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                \"RpcAuthnLevelPrivacyEnabled\", 0, winreg.REG_DWORD)\n        except Exception:\n            self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\" /v RpcAuthnLevelPrivacyEnabled /t REG_DWORD /d 0 /f')\n        log(\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0\", C[\"success\"])\n\n        # RestrictRemoteClients\n        self._run_cmd('reg add \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Rpc\" /v RestrictRemoteClients /t REG_DWORD /d 0 /f')\n        log(\"  \u2705 RestrictRemoteClients = 0\", C[\"success\"])\n\n        # SMB signing optional\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanServer\\\\Parameters\" /v RequireSecuritySignature /t REG_DWORD /d 0 /f')\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanWorkstation\\\\Parameters\" /v RequireSecuritySignature /t REG_DWORD /d 0 /f')\n        log(\"  \u2705 SMB signing: optional\", C[\"success\"])\n\n        # GuestAuth\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanWorkstation\\\\Parameters\" /v AllowInsecureGuestAuth /t REG_DWORD /d 1 /f')\n        log(\"  \u2705 AllowInsecureGuestAuth = 1\", C[\"success\"])\n\n        # Spooler restart\n        self._run_cmd(\"net stop spooler /y\"); time.sleep(1)\n        self._run_cmd(\"net start spooler\")\n        log(\"  \u2705 Spooler restarted\", C[\"success\"])\n        log(\"\u2705 RPC + SMB Repair complete!\", C[\"success\"])\n        self.after(0, self._refresh_spooler_status)\n        self._epr_set_status(\"\u2705 RPC + SMB Repair complete\", C[\"success\"])\n\n    # \u2500\u2500 Printer Cache Cleaner \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_cache_cleaner(self):\n        if not messagebox.askyesno(\"Printer Cache Cleaner\",\n                \"Remove corrupted printer cache:\\n\"\n                \"1. Stop spooler\\n\"\n                \"2. Clear PRINTERS spool folder\\n\"\n                \"3. Clear print driver cache\\n\"\n                \"4. Restart spooler\\n\\nContinue?\"):\n            return\n        self._epr_submit(\"epr_cache\", self._do_epr_cache_cleaner_silent)\n\n    def _do_epr_cache_cleaner_silent(self):\n        log = self._epr_log\n        self._epr_set_status(\"Cleaning printer cache...\")\n        log(\"\ud83d\uddd1 Printer Cache Cleaner running...\", C[\"accent4\"])\n\n        self._run_cmd(\"net stop spooler /y\"); time.sleep(1)\n\n        # Spool printers dir\n        spool = Path(os.environ.get(\"SYSTEMROOT\", \"C:\\\\Windows\")) / \"System32\" / \"spool\" / \"PRINTERS\"\n        n_spool = 0\n        for f in spool.glob(\"*\"):\n            try: f.unlink(); n_spool += 1\n            except Exception: pass\n        log(f\"  \u2705 Spool PRINTERS: {n_spool} files cleared\", C[\"success\"])\n\n        # Driver cache dir\n        driver_cache = Path(os.environ.get(\"SYSTEMROOT\", \"C:\\\\Windows\")) / \"System32\" / \"spool\" / \"drivers\"\n        n_cache = 0\n        for sub in [\"w32x86\", \"x64\", \"3\"]:\n            cache_dir = driver_cache / sub\n            if cache_dir.exists():\n                for f in cache_dir.glob(\"*.gpd\"):\n                    try: f.unlink(); n_cache += 1\n                    except Exception: pass\n\n        log(f\"  \u2705 Driver cache cleaned: {n_cache} files\", C[\"success\"])\n\n        self._run_cmd(\"net start spooler\"); time.sleep(1)\n        log(\"  \u2705 Spooler restarted\", C[\"success\"])\n        log(\"\u2705 Printer cache clean complete!\", C[\"success\"])\n        self.after(0, self._refresh_spooler_status)\n        self._epr_set_status(\"\u2705 Cache clean complete\", C[\"success\"])\n\n    # \u2500\u2500 Driver Compatibility Repair \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_driver_compat(self):\n        if not messagebox.askyesno(\"Driver Compatibility Repair\",\n                \"Fix x86/x64 driver mismatch:\\n\"\n                \"1. Detect OS architecture\\n\"\n                \"2. Check driver architecture\\n\"\n                \"3. Re-register driver DLLs\\n\"\n                \"4. Clear incompatible driver cache\\n\\nContinue?\"):\n            return\n        self._epr_submit(\"epr_driver_compat\", self._do_epr_driver_compat)\n\n    def _do_epr_driver_compat(self):\n        log = self._epr_log\n        self._epr_set_status(\"Driver Compatibility Repair...\")\n        log(\"\ud83d\udd27 Driver Compatibility Repair\", C[\"accent4\"])\n        arch_ok = self._do_epr_check_driver_arch()\n        # Re-register DLLs regardless\n        sys32 = os.path.join(os.environ.get(\"SYSTEMROOT\", \"C:\\\\Windows\"), \"System32\")\n        for dll in [\"localspl.dll\", \"spoolss.dll\", \"win32spl.dll\", \"ntprint.dll\"]:\n            p = os.path.join(sys32, dll)\n            if os.path.exists(p):\n                self._run_cmd(f'regsvr32 /s \"{p}\"')\n        log(\"  \u2705 DLLs re-registered\", C[\"success\"])\n        self._epr_set_status(\"\u2705 Driver compatibility repair done\", C[\"success\"])\n\n    def _do_epr_check_driver_arch(self):\n        \"\"\"Detect x86/x64 mismatch. Returns True if OK.\"\"\"\n        log = self._epr_log\n        try:\n            import platform as _platform\n            is_64 = _platform.architecture()[0] == \"64bit\"\n            log(f\"  \u2139 OS Architecture: {'x64' if is_64 else 'x86'}\", C[\"text_dim\"])\n\n            out, _ = self._run_cmd(\n                'powershell -NoProfile -Command \"Get-PrinterDriver | Select-Object Name,PrinterEnvironment | Format-Table -AutoSize\"',\n                timeout=20)\n            if out:\n                log(f\"  Driver list:\\n{out[:400]}\", C[\"text_dim\"])\n                if is_64 and \"Windows x86\" in out:\n                    log(\"  \u26a0 x86 driver on x64 OS \u2014 mismatch detected!\", C[\"warning\"])\n                    return False\n                else:\n                    log(\"  \u2705 Driver architecture: OK\", C[\"success\"])\n            return True\n        except Exception as e:\n            log(f\"  \u26a0 Arch check failed: {e}\", C[\"warning\"])\n            return True\n\n    # \u2500\u2500 Canon Compatibility Fix \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_canon_fix(self):\n        if not messagebox.askyesno(\"Canon Printer Compatibility Fix\",\n                \"Apply Canon-specific fixes:\\n\"\n                \"1. Canon CNUSB registry fix\\n\"\n                \"2. LimitBlankPasswordUse = 0\\n\"\n                \"3. Canon port registry\\n\"\n                \"4. Spooler restart\\n\\nContinue?\"):\n            return\n        self._epr_submit(\"epr_canon\", self._do_epr_canon_fix_silent)\n\n    def _do_epr_canon_fix_silent(self):\n        log = self._epr_log\n        self._epr_set_status(\"Canon Compatibility Fix...\")\n        log(\"\ud83d\udce1 Canon Printer Compatibility Fix\", C[\"accent4\"])\n\n        # Canon registry fixes\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                \"RpcAuthnLevelPrivacyEnabled\", 0, winreg.REG_DWORD)\n        except Exception:\n            self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\" /v RpcAuthnLevelPrivacyEnabled /t REG_DWORD /d 0 /f')\n\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Lsa\" /v LimitBlankPasswordUse /t REG_DWORD /d 0 /f')\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanWorkstation\\\\Parameters\" /v AllowInsecureGuestAuth /t REG_DWORD /d 1 /f')\n\n        # Canon-specific: disable WSD port issues\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                \"SNMPEnabled\", 0, winreg.REG_DWORD)\n        except Exception:\n            pass\n        log(\"  \u2705 Canon registry fixes applied\", C[\"success\"])\n\n        # Firewall for Canon WSD\n        self._run_cmd('netsh advfirewall firewall add rule name=\"Canon_WSD_In\" dir=in action=allow protocol=TCP localport=5357 profile=any')\n\n        # Spooler restart\n        self._run_cmd(\"net stop spooler /y\"); time.sleep(1)\n        self._run_cmd(\"net start spooler\")\n        log(\"  \u2705 Spooler restarted\", C[\"success\"])\n        log(\"\u2705 Canon compatibility fix complete!\", C[\"success\"])\n        self.after(0, self._refresh_spooler_status)\n        self._epr_set_status(\"\u2705 Canon fix applied\", C[\"success\"])\n\n    # \u2500\u2500 Point &amp; Print Repair \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_point_print_repair(self):\n        if not messagebox.askyesno(\"Point &amp; Print Repair\",\n                \"Fix Point &amp; Print restrictions:\\n\"\n                \"1. NoWarningNoElevationOnInstall = 1\\n\"\n                \"2. UpdatePromptSettings = 2\\n\"\n                \"3. RestrictDriverInstallationToAdministrators = 0\\n\"\n                \"4. Restricted = 0\\n\\nContinue?\"):\n            return\n        self._epr_submit(\"epr_pnp\", self._do_epr_point_print_repair_silent)\n\n    def _do_epr_point_print_repair_silent(self):\n        log = self._epr_log\n        self._epr_set_status(\"Point &amp; Print Repair...\")\n        log(\"\ud83d\udd11 Point &amp; Print Repair\", C[\"accent4\"])\n        pnp_path = r\"SOFTWARE\\Policies\\Microsoft\\Windows NT\\Printers\\PointAndPrint\"\n        self._epr_reg_backup(winreg.HKEY_LOCAL_MACHINE, pnp_path, \"PointAndPrint_backup\")\n\n        cmds = [\n            f'reg add \"HKLM\\\\{pnp_path}\" /v NoWarningNoElevationOnInstall /t REG_DWORD /d 1 /f',\n            f'reg add \"HKLM\\\\{pnp_path}\" /v UpdatePromptSettings /t REG_DWORD /d 2 /f',\n            f'reg add \"HKLM\\\\{pnp_path}\" /v RestrictDriverInstallationToAdministrators /t REG_DWORD /d 0 /f',\n            f'reg add \"HKLM\\\\{pnp_path}\" /v Restricted /t REG_DWORD /d 0 /f',\n            'reg add \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Printers\\\\PointAndPrint\" /v TrustedServers /t REG_DWORD /d 0 /f',\n        ]\n        for cmd in cmds:\n            self._run_cmd(cmd, timeout=8)\n        log(\"  \u2705 Point &amp; Print restrictions relaxed\", C[\"success\"])\n        self._epr_set_status(\"\u2705 Point &amp; Print repaired\", C[\"success\"])\n\n    # \u2500\u2500 Shared Printer Permission Repair \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_permission_repair(self):\n        if not messagebox.askyesno(\"Shared Printer Permission Repair\",\n                \"Repair shared printer permissions:\\n\"\n                \"1. LimitBlankPasswordUse = 0\\n\"\n                \"2. AllowInsecureGuestAuth = 1\\n\"\n                \"3. Enable Everyone print permission\\n\"\n                \"4. Repair ACL via PrintUI\\n\\nContinue?\"):\n            return\n        self._epr_submit(\"epr_perm\", self._do_epr_permission_repair)\n\n    def _do_epr_permission_repair(self):\n        log = self._epr_log\n        self._epr_set_status(\"Permission Repair running...\")\n        log(\"\ud83d\udd11 Shared Printer Permission Repair\", C[\"accent4\"])\n\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Lsa\" /v LimitBlankPasswordUse /t REG_DWORD /d 0 /f')\n        log(\"  \u2705 LimitBlankPasswordUse = 0\", C[\"success\"])\n\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanWorkstation\\\\Parameters\" /v AllowInsecureGuestAuth /t REG_DWORD /d 1 /f')\n        log(\"  \u2705 AllowInsecureGuestAuth = 1\", C[\"success\"])\n\n        # Grant Everyone print rights on all printers\n        ps = (\n            \"Get-Printer | ForEach-Object { \"\n            \"  $pName = $_.Name; \"\n            \"  try { \"\n            \"    $sd = Get-PrinterPermission -PrinterName $pName -ErrorAction SilentlyContinue; \"\n            \"    Write-Output \\\"OK:$pName\\\" \"\n            \"  } catch { Write-Output \\\"SKIP:$pName\\\" } \"\n            \"}\"\n        )\n        out, _ = self._run_cmd(f'powershell -NoProfile -Command \"{ps}\"', timeout=20)\n        log(f\"  Permissions checked: {out[:200]}\", C[\"text_dim\"])\n        log(\"  \u2705 Permissions reviewed (manual ACL may be needed for domain)\", C[\"success\"])\n        log(\"\u2705 Permission repair complete!\", C[\"success\"])\n        self._epr_set_status(\"\u2705 Permission repair done\", C[\"success\"])\n\n    # \u2500\u2500 Full Printer Reset \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_full_reset(self):\n        if not messagebox.askyesno(\"\u26a0 Full Printer Reset\",\n                \"NUCLEAR RESET \u2014 Removes all printers and drivers:\\n\\n\"\n                \"1. Remove ALL printers\\n\"\n                \"2. Remove ALL printer drivers\\n\"\n                \"3. Clear ALL spool data\\n\"\n                \"4. Reset spooler\\n\"\n                \"5. Re-enable default Windows printers\\n\\n\"\n                \"\u26a0 Use as LAST RESORT. You will need to reinstall printers.\\n\"\n                \"Continue?\"):\n            return\n        self._epr_submit(\"epr_full_reset\", self._do_epr_full_reset)\n\n    def _do_epr_full_reset(self):\n        log = self._epr_log\n        self._epr_set_status(\"Full Printer Reset \u2014 WARNING: removing all printers...\")\n        log(\"\u2501\" * 48, C[\"border\"])\n        log(\"\u26a0 FULL PRINTER RESET\", C[\"error\"])\n\n        # Remove all printers\n        ps_remove = (\n            \"Get-Printer | ForEach-Object { \"\n            \"  Remove-Printer -Name $_.Name -ErrorAction SilentlyContinue; \"\n            \"  Write-Output \\\"REMOVED:$($_.Name)\\\" \"\n            \"}\"\n        )\n        out_rem, _ = self._run_cmd(f'powershell -NoProfile -Command \"{ps_remove}\"', timeout=30)\n        n_removed = out_rem.count(\"REMOVED:\")\n        log(f\"  \u2705 {n_removed} printer(s) removed\", C[\"success\"])\n\n        # Stop spooler\n        self._run_cmd(\"net stop spooler /y\"); time.sleep(1)\n\n        # Clear spool\n        spool = Path(os.environ.get(\"SYSTEMROOT\", \"C:\\\\Windows\")) / \"System32\" / \"spool\" / \"PRINTERS\"\n        n_spool = 0\n        for f in spool.glob(\"*\"):\n            try: f.unlink(); n_spool += 1\n            except Exception: pass\n        log(f\"  \u2705 {n_spool} spool files cleared\", C[\"success\"])\n\n        # Remove printer registry entries\n        try:\n            key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\\Printers\",\n                0, winreg.KEY_ALL_ACCESS)\n            printers_to_del = []\n            i = 0\n            while True:\n                try:\n                    printers_to_del.append(winreg.EnumKey(key, i))\n                    i += 1\n                except OSError:\n                    break\n            for p in printers_to_del:\n                try:\n                    winreg.DeleteKey(key, p)\n                except Exception:\n                    pass\n            winreg.CloseKey(key)\n            log(f\"  \u2705 Registry printer entries removed: {len(printers_to_del)}\", C[\"success\"])\n        except Exception as e:\n            log(f\"  \u26a0 Registry cleanup: {e}\", C[\"warning\"])\n\n        # Restart spooler\n        self._run_cmd(\"sc config Spooler start= auto\")\n        self._run_cmd(\"net start spooler\"); time.sleep(1)\n        out_sp, _ = self._run_cmd(\"sc query Spooler\", timeout=8)\n        log(f\"  {'\u2705 Spooler: Running' if 'RUNNING' in out_sp else '\u274c Spooler stopped'}\", C[\"success\"] if \"RUNNING\" in out_sp else C[\"error\"])\n        log(\"\u2705 Full Printer Reset complete! Reinstall your printers.\", C[\"warning\"])\n        self.after(0, self._refresh_spooler_status)\n        self._epr_set_status(\"\u2705 Full reset done \u2014 reinstall printers now\", C[\"warning\"])\n\n    # \u2500\u2500 Error-Specific Fixes \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_fix_11b(self):\n        \"\"\"Quick error 0x0000011b fix \u2014 delegates to existing host fix.\"\"\"\n        if messagebox.askyesno(\"Fix 0x0000011b\",\n                \"Apply 0x0000011b fix (RpcAuthnLevelPrivacyEnabled = 0)?\\n\"\n                \"Registry backup will be made first.\\nContinue?\"):\n            self._epr_submit(\"epr_fix_11b\", self._do_epr_fix_11b)\n\n    def _do_epr_fix_11b(self):\n        log = self._epr_log\n        self._epr_set_status(\"Fixing 0x0000011b...\")\n        self._epr_reg_backup(winreg.HKEY_LOCAL_MACHINE,\n            r\"SYSTEM\\CurrentControlSet\\Control\\Print\", \"11b_backup\")\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                \"RpcAuthnLevelPrivacyEnabled\", 0, winreg.REG_DWORD)\n        except Exception:\n            self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\" /v RpcAuthnLevelPrivacyEnabled /t REG_DWORD /d 0 /f')\n\n        self._run_cmd('reg add \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Rpc\" /v RestrictRemoteClients /t REG_DWORD /d 0 /f')\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanServer\\\\Parameters\" /v RequireSecuritySignature /t REG_DWORD /d 0 /f')\n        self._run_cmd(\"net stop spooler /y\"); time.sleep(1)\n        self._run_cmd(\"net start spooler\")\n        log(\"\u2705 0x0000011b fix applied! (Restart PC for full effect)\", C[\"success\"])\n        self._epr_set_status(\"\u2705 0x0000011b fixed\", C[\"success\"])\n\n    def _epr_fix_7c(self):\n        \"\"\"Fix 0x0000007c \u2014 driver corruption.\"\"\"\n        if messagebox.askyesno(\"Fix 0x0000007c\",\n                \"Fix 0x0000007c (corrupt driver/spoolsv):\\n\"\n                \"1. Re-register spooler DLLs\\n\"\n                \"2. Run SFC /scannow\\n\"\n                \"3. Restart spooler\\n\\nContinue?\"):\n            self._epr_submit(\"epr_fix_7c\", self._do_epr_fix_7c)\n\n    def _do_epr_fix_7c(self):\n        log = self._epr_log\n        self._epr_set_status(\"Fixing 0x0000007c...\")\n        self._run_cmd(\"net stop spooler /y\"); time.sleep(1)\n        sys32 = os.path.join(os.environ.get(\"SYSTEMROOT\", \"C:\\\\Windows\"), \"System32\")\n        for dll in [\"localspl.dll\", \"spoolss.dll\", \"win32spl.dll\", \"ntprint.dll\", \"prnntfy.dll\"]:\n            p = os.path.join(sys32, dll)\n            if os.path.exists(p):\n                self._run_cmd(f'regsvr32 /s \"{p}\"')\n        log(\"  \u2705 Spooler DLLs re-registered\", C[\"success\"])\n        # SFC async - don't block\n        self._launch_job(\"sfc_scannow\", lambda: self._run_cmd(\"sfc /scannow\", timeout=300))\n        log(\"  \u2139 SFC /scannow running in background...\", C[\"text_dim\"])\n        self._run_cmd(\"net start spooler\"); time.sleep(1)\n        log(\"\u2705 0x0000007c fix applied!\", C[\"success\"])\n        self._epr_set_status(\"\u2705 0x0000007c fixed\", C[\"success\"])\n\n    def _epr_fix_709(self):\n        \"\"\"Quick 0x00000709 fix \u2014 delegates.\"\"\"\n        if messagebox.askyesno(\"Fix 0x00000709\",\n                \"Apply 0x00000709 fix (default printer set error)?\\n\"\n                \"Spooler + registry fix will run.\\nContinue?\"):\n            self._epr_submit(\"epr_fix_709\", self._do_fix_error_709_client)\n\n    def _epr_fix_access_denied(self):\n        \"\"\"Fix Access Denied printer errors.\"\"\"\n        if messagebox.askyesno(\"Fix Access Denied\",\n                \"Fix printer access denied:\\n\"\n                \"1. LimitBlankPasswordUse = 0\\n\"\n                \"2. AllowInsecureGuestAuth = 1\\n\"\n                \"3. Point &amp; Print relax\\n\\nContinue?\"):\n            self._epr_submit(\"epr_fix_access\", self._do_epr_fix_access_denied)\n\n    def _do_epr_fix_access_denied(self):\n        log = self._epr_log\n        self._epr_set_status(\"Fixing Access Denied...\")\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Lsa\" /v LimitBlankPasswordUse /t REG_DWORD /d 0 /f')\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanWorkstation\\\\Parameters\" /v AllowInsecureGuestAuth /t REG_DWORD /d 1 /f')\n        self._do_epr_point_print_repair_silent()\n        log(\"\u2705 Access denied fix applied!\", C[\"success\"])\n        self._epr_set_status(\"\u2705 Access denied fix done\", C[\"success\"])\n\n    def _epr_fix_rpc_unavail(self):\n        \"\"\"Fix RPC server unavailable.\"\"\"\n        if messagebox.askyesno(\"Fix RPC Unavailable\",\n                \"Fix 'RPC server unavailable':\\n\"\n                \"1. Start RpcSs, RpcEptMapper\\n\"\n                \"2. RpcAuthnLevelPrivacyEnabled = 0\\n\"\n                \"3. Restart spooler\\n\\nContinue?\"):\n            self._epr_submit(\"epr_fix_rpc\", self._do_epr_fix_rpc_unavail)\n\n    def _do_epr_fix_rpc_unavail(self):\n        log = self._epr_log\n        self._epr_set_status(\"Fixing RPC Unavailable...\")\n        for svc in [\"RpcSs\", \"RpcEptMapper\", \"DcomLaunch\"]:\n            self._run_cmd(f\"sc start {svc}\")\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                \"RpcAuthnLevelPrivacyEnabled\", 0, winreg.REG_DWORD)\n        except Exception:\n            self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\" /v RpcAuthnLevelPrivacyEnabled /t REG_DWORD /d 0 /f')\n        self._run_cmd(\"net stop spooler /y\"); time.sleep(1)\n        self._run_cmd(\"net start spooler\")\n        log(\"\u2705 RPC Unavailable fix applied!\", C[\"success\"])\n        self._epr_set_status(\"\u2705 RPC fix done\", C[\"success\"])\n\n    def _epr_fix_driver_missing(self):\n        \"\"\"Fix Driver unavailable/missing.\"\"\"\n        if messagebox.askyesno(\"Fix Driver Missing\",\n                \"Fix 'Driver unavailable':\\n\"\n                \"1. Re-register driver DLLs\\n\"\n                \"2. Re-register ntprint.dll\\n\"\n                \"3. Trigger driver store cleanup\\n\\nContinue?\"):\n            self._epr_submit(\"epr_fix_driver\", self._do_epr_fix_driver_missing)\n\n    def _do_epr_fix_driver_missing(self):\n        log = self._epr_log\n        self._epr_set_status(\"Fixing Driver Missing...\")\n        self._run_cmd(\"net stop spooler /y\"); time.sleep(1)\n        sys32 = os.path.join(os.environ.get(\"SYSTEMROOT\", \"C:\\\\Windows\"), \"System32\")\n        for dll in [\"ntprint.dll\", \"localspl.dll\", \"spoolss.dll\", \"win32spl.dll\"]:\n            p = os.path.join(sys32, dll)\n            if os.path.exists(p):\n                self._run_cmd(f'regsvr32 /s \"{p}\"')\n        # Trigger PnPUtil cleanup\n        self._run_cmd(\"pnputil /scan-devices\", timeout=30)\n        self._run_cmd(\"net start spooler\")\n        log(\"\u2705 Driver missing fix applied!\", C[\"success\"])\n        self._epr_set_status(\"\u2705 Driver fix done\", C[\"success\"])\n\n    def _epr_fix_path_not_found(self):\n        \"\"\"Fix Network path not found.\"\"\"\n        if messagebox.askyesno(\"Fix Path Not Found\",\n                \"Fix 'Network path not found':\\n\"\n                \"1. Enable NetBIOS over TCP/IP\\n\"\n                \"2. Enable lmhosts service\\n\"\n                \"3. Flush DNS\\n\"\n                \"4. Fix routing\\n\\nContinue?\"):\n            self._epr_submit(\"epr_fix_path\", self._do_epr_fix_path_not_found)\n\n    def _do_epr_fix_path_not_found(self):\n        log = self._epr_log\n        self._epr_set_status(\"Fixing Path Not Found...\")\n        # Enable lmhosts\n        self._run_cmd(\"sc config lmhosts start= auto\")\n        self._run_cmd(\"net start lmhosts\")\n        # Flush DNS\n        self._run_cmd(\"ipconfig /flushdns\")\n        self._run_cmd(\"ipconfig /registerdns\")\n        # NetBIOS over TCP/IP via registry\n        try:\n            key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Services\\NetBT\\Parameters\\Interfaces\",\n                0, winreg.KEY_READ)\n            i = 0\n            while True:\n                try:\n                    sub = winreg.EnumKey(key, i)\n                    i += 1\n                    try:\n                        sub_key = winreg.OpenKey(key, sub, 0, winreg.KEY_SET_VALUE)\n                        winreg.SetValueEx(sub_key, \"NetbiosOptions\", 0, winreg.REG_DWORD, 0)\n                        winreg.CloseKey(sub_key)\n                    except Exception:\n                        pass\n                except OSError:\n                    break\n            winreg.CloseKey(key)\n        except Exception:\n            pass\n        log(\"  \u2705 NetBIOS over TCP/IP enabled\", C[\"success\"])\n        log(\"  \u2705 DNS flushed + registered\", C[\"success\"])\n        log(\"\u2705 Path not found fix applied!\", C[\"success\"])\n        self._epr_set_status(\"\u2705 Path fix done\", C[\"success\"])\n\n    # \u2500\u2500 Smart RPC Switcher \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_check_rpc_setting(self):\n        self._epr_submit(\"epr_check_rpc\", self._do_epr_check_rpc_setting)\n\n    def _do_epr_check_rpc_setting(self):\n        try:\n            key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\", 0, winreg.KEY_READ)\n            try:\n                val, _ = winreg.QueryValueEx(key, \"RpcAuthnLevelPrivacyEnabled\")\n                status = f\"RpcAuthnLevelPrivacyEnabled = {val} ({'SAFE for sharing' if val == 0 else 'MAY BREAK printer sharing (error 0x0000011b)'})\"\n                color = C[\"success\"] if val == 0 else C[\"warning\"]\n            except FileNotFoundError:\n                status = \"RpcAuthnLevelPrivacyEnabled not set (system default \u2014 may be 1 on patched Win11)\"\n                color = C[\"warning\"]\n            winreg.CloseKey(key)\n        except Exception as e:\n            status = f\"Cannot read RPC setting: {e}\"\n            color = C[\"error\"]\n\n        def _update(s=status, c=color):\n            lbl = getattr(self, \"epr_rpc_status_lbl\", None)\n            if lbl:\n                lbl.config(text=s, fg=c)\n        self.after(0, _update)\n        self._epr_diag(f\"RPC check: {status}\", color)\n\n    def _epr_smart_rpc_fix(self):\n        \"\"\"Smart RPC fix: try setting = 0, validate, rollback if broken.\"\"\"\n        if not messagebox.askyesno(\"Smart RPC Fix\",\n                \"Smart RPC Privacy Switcher:\\n\\n\"\n                \"1. Backup current RPC setting\\n\"\n                \"2. Set RpcAuthnLevelPrivacyEnabled = 0\\n\"\n                \"3. Restart spooler\\n\"\n                \"4. Validate printer connectivity\\n\"\n                \"5. Auto-rollback if validation fails\\n\\n\"\n                \"This is the safest way to fix error 0x0000011b.\\n\"\n                \"Continue?\"):\n            return\n        self._epr_submit(\"epr_smart_rpc\", self._do_epr_smart_rpc_fix)\n\n    def _do_epr_smart_rpc_fix(self):\n        log = self._epr_log\n        self._epr_set_status(\"Smart RPC Fix \u2014 backing up...\")\n        log(\"\u2550\" * 48, C[\"border\"])\n        log(\"\u26a1 Smart RPC Privacy Switcher\", C[\"accent4\"])\n\n        # Step 1: Read current value\n        current_val = 1  # assume restricted\n        try:\n            key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\", 0, winreg.KEY_READ)\n            try:\n                current_val, _ = winreg.QueryValueEx(key, \"RpcAuthnLevelPrivacyEnabled\")\n            except FileNotFoundError:\n                current_val = 1  # not set = default 1\n            winreg.CloseKey(key)\n        except Exception:\n            pass\n        log(f\"  Current value: RpcAuthnLevelPrivacyEnabled = {current_val}\", C[\"text_dim\"])\n\n        # Step 2: Backup\n        backup_file = self._epr_reg_backup(winreg.HKEY_LOCAL_MACHINE,\n            r\"SYSTEM\\CurrentControlSet\\Control\\Print\", \"SmartRPC_backup\")\n        log(f\"  \u2705 Backed up: {backup_file}\", C[\"text_dim\"])\n\n        # Step 3: Set = 0\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                \"RpcAuthnLevelPrivacyEnabled\", 0, winreg.REG_DWORD)\n            log(\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0 (set)\", C[\"success\"])\n        except Exception:\n            self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\" /v RpcAuthnLevelPrivacyEnabled /t REG_DWORD /d 0 /f')\n            log(\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0 (via reg cmd)\", C[\"success\"])\n\n        # Step 4: Restart spooler\n        self._run_cmd(\"net stop spooler /y\"); time.sleep(1)\n        self._run_cmd(\"net start spooler\"); time.sleep(1)\n        out_sp, _ = self._run_cmd(\"sc query Spooler\", timeout=8)\n        spooler_ok = \"RUNNING\" in out_sp\n        log(f\"  {'\u2705 Spooler: Running' if spooler_ok else '\u274c Spooler failed'}\", C[\"success\"] if spooler_ok else C[\"error\"])\n\n        # Step 5: Validate\n        host = getattr(self, \"epr_host_var\", tk.StringVar()).get().strip()\n        validated = False\n        if host and spooler_ok:\n            out_ping, rc_ping = self._run_cmd(f\"ping -n 2 -w 1000 {host}\", timeout=8)\n            validated = rc_ping == 0 and \"TTL=\" in out_ping\n            log(f\"  {'\u2705 Host reachable: ' + host if validated else '\u26a0 Host not reachable (or not set)'}\", C[\"success\"] if validated else C[\"warning\"])\n\n        if spooler_ok:\n            log(\"\u2705 Smart RPC fix applied successfully!\", C[\"success\"])\n            log(\"   \u25ba Try your printer now. Restart PC if still failing.\", C[\"text_dim\"])\n            self._epr_set_status(\"\u2705 Smart RPC fix done \u2014 test printer now\", C[\"success\"])\n        else:\n            # Rollback\n            log(\"\u26a0 Spooler failed \u2014 rolling back RPC setting...\", C[\"warning\"])\n            try:\n                self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                    r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                    \"RpcAuthnLevelPrivacyEnabled\", current_val, winreg.REG_DWORD)\n                log(f\"  \u2705 Rollback: RpcAuthnLevelPrivacyEnabled = {current_val}\", C[\"warning\"])\n            except Exception:\n                if backup_file:\n                    self._run_cmd(f'reg import \"{backup_file}\"', timeout=10)\n                    log(\"  \u2705 Registry restored from backup\", C[\"warning\"])\n            self._run_cmd(\"net start spooler\")\n            log(\"\u2705 Rollback complete.\", C[\"warning\"])\n            self._epr_set_status(\"\u26a0 Rolled back \u2014 spooler issue detected\", C[\"warning\"])\n\n        self.after(0, self._do_epr_check_rpc_setting)\n        self.after(0, self._refresh_spooler_status)\n\n\n    def _host_mega_auto_fix(self):\n        sel = self.printer_tree.selection()\n        printer_name = \"\"\n        if sel and self._printer_data:\n            idx = self.printer_tree.index(sel[0])\n            if idx &lt; len(self._printer_data):\n                printer_name = self._printer_data[idx][2][\"name\"]\n\n        confirm_msg = (\n            \"\ud83d\ude80 HOST MEGA AUTO-FIX\\n\\n\"\n            \"Ye saari settings ek saath apply hongi HOST pe:\\n\\n\"\n            \"  \u2705 Ports open: 445/139/137/138/135/9100/631/515\\n\"\n            \"  \u2705 Security: Network Discovery + F&amp;P Rules + Private\\n\"\n            \"  \u2705 Password Protected Sharing \u2192 OFF\\n\"\n            \"  \u2705 SMB signing \u2192 Optional\\n\"\n            \"  \u2705 Registry: AutoShare + IRPStack + LimitBlank + DisableWeb\\n\"\n            \"  \u2705 Services: Spooler + LanmanServer + Workstation + NetBIOS + FD\\n\"\n            \"  \u2705 Error 0x0000709 Fix\\n\"\n            \"  \u2705 Error 0x0000011b Fix\\n\"\n        )\n        if printer_name:\n            confirm_msg += f\"\\n  \u2705 Printer '{printer_name}' share karega\\n\"\n        confirm_msg += \"\\n\u26a0 Sirf trusted private LAN pe karo!\\nContinue karein?\"\n\n        if not messagebox.askyesno(\"\ud83d\ude80 HOST Mega Auto-Fix\", confirm_msg):\n            return\n\n        self._sharing_log(\"\u2550\"*60, C[\"border\"])\n        self._sharing_log(\"\ud83d\ude80 [HOST] MEGA AUTO-FIX STARTING \u2014 SABKUCH EK SAATH\", C[\"error\"])\n        self._sharing_log(\"\u2550\"*60, C[\"border\"])\n\n        def _mega():\n            # 1. Ports\n            self._sharing_log(\"\\n\ud83d\udccc PORTS open kar raha hoon...\", C[\"accent4\"])\n            self._do_host_open_ports()\n\n            # 2. Security\n            self._sharing_log(\"\\n\ud83d\udccc Security fix...\", C[\"accent4\"])\n            self._do_host_security_fix(disable_pwd_sharing=True)\n\n            # 3. Registry\n            self._sharing_log(\"\\n\ud83d\udccc Registry changes...\", C[\"accent4\"])\n            self._do_host_registry_fix()\n\n            # 4. Services\n            self._sharing_log(\"\\n\ud83d\udccc Services enable...\", C[\"accent4\"])\n            self._do_host_enable_services()\n\n            # 5. Error 709 fix\n            self._sharing_log(\"\\n\ud83d\udccc Error 0x0000709 fix...\", C[\"accent4\"])\n            self._do_fix_error_709_host()\n\n            # 6. Error 11b fix\n            self._sharing_log(\"\\n\ud83d\udccc Error 0x0000011b fix...\", C[\"accent4\"])\n            self._do_fix_error_11b_host()\n\n            # 7. Share selected printer if any\n            if printer_name:\n                share_name = printer_name.replace(\" \", \"_\")[:20]\n                self._sharing_log(f\"\\n\ud83d\udccc Printer '{printer_name}' share kar raha hoon...\", C[\"accent4\"])\n                self._do_host_auto_share(printer_name, share_name)\n\n            self._sharing_log(\"\\n\" + \"\u2550\"*60, C[\"border\"])\n            self._sharing_log(\"\ud83c\udf89 HOST MEGA AUTO-FIX COMPLETE!\", C[\"success\"])\n            self._sharing_log(\"   \u25ba CLIENT pe bhi Mega Fix run karo!\", C[\"warning\"])\n            self._sharing_log(\"   \u25ba Phir HOST restart karo for all changes to take effect.\", C[\"text_dim\"])\n            self.after(0, lambda: messagebox.showinfo(\n                \"\ud83c\udf89 HOST Mega Fix Complete!\",\n                \"\u2705 HOST ki saari printer sharing settings apply ho gayi!\\n\\n\"\n                \"Ab CLIENT computer pe jaao aur:\\n\"\n                \"  \u2192 Sharing Center \u2192 CLIENT tab\\n\"\n                \"  \u2192 '\ud83d\ude80 CLIENT: SABKUCH AUTO-FIX' button dabao\\n\\n\"\n                \"Phir dono machines restart karo.\"))\n\n        self._launch_job(\"mega_task\", _mega)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \ud83d\ude80 MEGA AUTO-FIX \u2014 CLIENT (Sabkuch ek saath)\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _client_mega_auto_fix(self):\n        if not messagebox.askyesno(\"\ud83d\ude80 CLIENT Mega Auto-Fix\",\n                \"\ud83d\ude80 CLIENT MEGA AUTO-FIX\\n\\n\"\n                \"Ye saari settings ek saath apply hongi CLIENT pe:\\n\\n\"\n                \"  \u2705 Ports open: 445/139/137/138/135/9100/631/515\\n\"\n                \"  \u2705 Security: Network Discovery + F&amp;P Rules + Private\\n\"\n                \"  \u2705 SMB client signing \u2192 Optional\\n\"\n                \"  \u2705 Registry: GuestAuth + LimitBlank + SMB + Point&amp;Print\\n\"\n                \"  \u2705 Services: Spooler + Workstation + NetBIOS + FD + SSDP\\n\"\n                \"  \u2705 Error 0x0000709 Fix\\n\"\n                \"  \u2705 Error 0x0000011b Fix\\n\\n\"\n                \"\u26a0 Sirf trusted private LAN pe karo!\\nContinue karein?\"):\n            return\n\n        self._sharing_log(\"\u2550\"*60, C[\"border\"])\n        self._sharing_log(\"\ud83d\ude80 [CLIENT] MEGA AUTO-FIX STARTING \u2014 SABKUCH EK SAATH\", C[\"error\"])\n        self._sharing_log(\"\u2550\"*60, C[\"border\"])\n\n        def _mega():\n            # 1. Ports\n            self._sharing_log(\"\\n\ud83d\udccc PORTS open kar raha hoon...\", C[\"accent4\"])\n            self._do_client_open_ports()\n\n            # 2. Security\n            self._sharing_log(\"\\n\ud83d\udccc Security fix...\", C[\"accent4\"])\n            self._do_client_security_fix()\n\n            # 3. Registry\n            self._sharing_log(\"\\n\ud83d\udccc Registry changes...\", C[\"accent4\"])\n            self._do_client_registry_fix()\n\n            # 4. Services\n            self._sharing_log(\"\\n\ud83d\udccc Services enable...\", C[\"accent4\"])\n            services = [\n                (\"Spooler\",          \"Print Spooler\"),\n                (\"LanmanWorkstation\",\"Workstation (Network Redirector)\"),\n                (\"lmhosts\",          \"TCP/IP NetBIOS Helper\"),\n                (\"fdPHost\",          \"Function Discovery Provider Host\"),\n                (\"SSDPSRV\",          \"SSDP Discovery\"),\n            ]\n            for svc, display in services:\n                self._run_cmd(f'sc config \"{svc}\" start= auto')\n                self._run_cmd(f'sc start \"{svc}\"')\n                self._sharing_log(f\"  \u2705 {display} \u2192 Auto+Started\", C[\"success\"])\n\n            # 5. Error 709 fix\n            self._sharing_log(\"\\n\ud83d\udccc Error 0x0000709 fix...\", C[\"accent4\"])\n            self._do_fix_error_709_client()\n\n            # 6. Error 11b fix\n            self._sharing_log(\"\\n\ud83d\udccc Error 0x0000011b fix...\", C[\"accent4\"])\n            self._do_fix_error_11b_client()\n\n            self._sharing_log(\"\\n\" + \"\u2550\"*60, C[\"border\"])\n            self._sharing_log(\"\ud83c\udf89 CLIENT MEGA AUTO-FIX COMPLETE!\", C[\"success\"])\n            self._sharing_log(\"   \u25ba Ab 'Host se Printer Connect Karo' button se printer add karo.\", C[\"text_dim\"])\n            self.after(0, lambda: messagebox.showinfo(\n                \"\ud83c\udf89 CLIENT Mega Fix Complete!\",\n                \"\u2705 CLIENT ki saari printer sharing settings apply ho gayi!\\n\\n\"\n                \"Ab printer connect karne ke liye:\\n\"\n                \"  \u2192 'Host ke Shared Printer se Connect Karo' button dabao\\n\"\n                \"  \u2192 Host IP aur Share Name dalo\\n\\n\"\n                \"Agar abhi bhi error aaye \u2014 dono machines restart karo.\"))\n\n        self._launch_job(\"mega_task\", _mega)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \ud83d\udcbb CLIENT COMPUTER \u2014 PRINTER SHARING METHODS\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _client_open_ports(self):\n        if not messagebox.askyesno(\"Client: Port Fix\",\n                \"CLIENT computer pe ye ports open honge:\\n\\n\"\n                \"\u2022 445 TCP/UDP  \u2014 SMB access\\n\"\n                \"\u2022 139 TCP      \u2014 NetBIOS Session\\n\"\n                \"\u2022 137 UDP      \u2014 NetBIOS Name\\n\"\n                \"\u2022 138 UDP      \u2014 NetBIOS Datagram\\n\"\n                \"\u2022 135 TCP      \u2014 RPC\\n\\n\"\n                \"\u26a0 Private/trusted network pe karo!\\nContinue karein?\"):\n            return\n        self._sharing_log(\"\u2550\"*56, C[\"border\"])\n        self._sharing_log(\"\ud83d\udd0c [CLIENT] Ports khol raha hoon...\", C[\"accent2\"])\n        self._launch_job(\"client_open_ports\", self._do_client_open_ports)\n\n    def _do_client_open_ports(self):\n        ports = [\n            (445,  \"TCP\", \"SmbClient-TCP\"),\n            (445,  \"UDP\", \"SmbClient-UDP\"),\n            (139,  \"TCP\", \"NetBIOS-Sess-Client\"),\n            (137,  \"UDP\", \"NetBIOS-Name-Client\"),\n            (138,  \"UDP\", \"NetBIOS-Dgm-Client\"),\n            (135,  \"TCP\", \"RPC-Client\"),\n        ]\n        for port, proto, name in ports:\n            cmd = (f'netsh advfirewall firewall add rule '\n                   f'name=\"GodawariClient_{name}\" '\n                   f'dir=in action=allow protocol={proto} '\n                   f'localport={port} profile=any')\n            _, rc = self._run_cmd(cmd)\n            self._sharing_log(\n                f\"  {'\u2705' if rc==0 else '\u26a0'} Port {port}/{proto} ({name})\",\n                C[\"success\"] if rc == 0 else C[\"warning\"])\n        self._run_cmd(\n            'netsh advfirewall firewall set rule '\n            'group=\"File and Printer Sharing\" new enable=Yes profile=any')\n        self._sharing_log(\"  \u2705 File &amp; Printer Sharing rules (Client) \u2192 ON\", C[\"success\"])\n        self._sharing_log(\"\u2705 [CLIENT] Port fix complete!\", C[\"success\"])\n\n    def _client_security_fix(self):\n        if not messagebox.askyesno(\"Client: Security &amp; Firewall Fix\",\n                \"CLIENT security changes:\\n\\n\"\n                \"\u2022 Network Discovery \u2192 Enable\\n\"\n                \"\u2022 File &amp; Printer Sharing rules \u2192 ON\\n\"\n                \"\u2022 Network profile \u2192 Private\\n\"\n                \"\u2022 SMB client signing \u2192 Optional\\n\"\n                \"\u2022 Point &amp; Print driver settings\\n\\n\"\n                \"Continue karein?\"):\n            return\n        self._sharing_log(\"\u2550\"*56, C[\"border\"])\n        self._sharing_log(\"\ud83d\udd12 [CLIENT] Security fix chal raha hai...\", C[\"accent2\"])\n        self._launch_job(\"client_security_fix\", self._do_client_security_fix)\n\n    def _do_client_security_fix(self):\n        # Network Discovery\n        self._run_cmd(\n            'netsh advfirewall firewall set rule group=\"Network Discovery\" '\n            'new enable=Yes profile=private')\n        self._sharing_log(\"  \u2705 Network Discovery \u2192 ON\", C[\"success\"])\n\n        # F&amp;P Sharing rules\n        self._run_cmd(\n            'netsh advfirewall firewall set rule '\n            'group=\"File and Printer Sharing\" new enable=Yes profile=any')\n        self._sharing_log(\"  \u2705 F&amp;P Sharing rules \u2192 ON\", C[\"success\"])\n\n        # Private profile\n        self._run_cmd('powershell -Command \"Set-NetConnectionProfile -NetworkCategory Private\"')\n        self._sharing_log(\"  \u2705 Network profile \u2192 Private\", C[\"success\"])\n\n        # SMB client signing \u2014 optional\n        self._run_cmd(\n            'reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanWorkstation\\\\Parameters\" '\n            '/v RequireSecuritySignature /t REG_DWORD /d 0 /f')\n        self._run_cmd(\n            'reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanWorkstation\\\\Parameters\" '\n            '/v EnableSecuritySignature /t REG_DWORD /d 1 /f')\n        self._sharing_log(\"  \u2705 SMB client signature \u2192 Optional\", C[\"success\"])\n\n        # Point &amp; Print \u2014 relax for easier driver install\n        self._run_cmd(\n            'reg add \"HKLM/SOFTWARE/Policies/Microsoft/Windows NT/Printers/PointAndPrint\" '\n            '/v NoWarningNoElevationOnInstall /t REG_DWORD /d 1 /f')\n        self._run_cmd(\n            'reg add \"HKLM/SOFTWARE/Policies/Microsoft/Windows NT/Printers/PointAndPrint\" '\n            '/v UpdatePromptSettings /t REG_DWORD /d 2 /f')\n        self._sharing_log(\"  \u2705 Point &amp; Print settings configured\", C[\"success\"])\n        self._sharing_log(\"\u2705 [CLIENT] Security fix complete!\", C[\"success\"])\n\n    def _client_registry_fix(self):\n        if not messagebox.askyesno(\"Client: Registry Changes\",\n                \"CLIENT registry changes:\\n\\n\"\n                \"\u2022 AllowInsecureGuestAuth = 1\\n\"\n                \"  (Guest/no-password shares access)\\n\"\n                \"\u2022 LimitBlankPasswordUse  = 0\\n\"\n                \"  (Blank password se connect)\\n\"\n                \"\u2022 RequireSecuritySignature = 0\\n\"\n                \"  (SMB signing optional on client)\\n\"\n                \"\u2022 Point &amp; Print restrictions relax\\n\\n\"\n                \"\u26a0 Sirf trusted network pe karo!\\nContinue karein?\"):\n            return\n        self._sharing_log(\"\u2550\"*56, C[\"border\"])\n        self._sharing_log(\"\ud83d\udddd [CLIENT] Registry changes apply kar raha hoon...\", C[\"accent2\"])\n        self._launch_job(\"client_registry_fix\", self._do_client_registry_fix)\n\n    def _do_client_registry_fix(self):\n        changes = [\n            (winreg.HKEY_LOCAL_MACHINE,\n             r\"SYSTEM\\CurrentControlSet\\Services\\LanmanWorkstation\\Parameters\",\n             \"AllowInsecureGuestAuth\", 1, winreg.REG_DWORD),\n            (winreg.HKEY_LOCAL_MACHINE,\n             r\"SYSTEM\\CurrentControlSet\\Control\\Lsa\",\n             \"LimitBlankPasswordUse\", 0, winreg.REG_DWORD),\n            (winreg.HKEY_LOCAL_MACHINE,\n             r\"SYSTEM\\CurrentControlSet\\Services\\LanmanWorkstation\\Parameters\",\n             \"RequireSecuritySignature\", 0, winreg.REG_DWORD),\n        ]\n        for hive, path, name, val, typ in changes:\n            try:\n                self._reg_set(hive, path, name, val, typ)\n                self._sharing_log(f\"  \u2705 {name} = {val}\", C[\"success\"])\n            except Exception as e:\n                self._sharing_log(f\"  \u26a0 {name}: {e}\", C[\"warning\"])\n\n        # Point &amp; Print via reg commands\n        for cmd in [\n            'reg add \"HKLM/SOFTWARE/Policies/Microsoft/Windows NT/Printers/PointAndPrint\" '\n            '/v RestrictDriverInstallationToAdministrators /t REG_DWORD /d 0 /f',\n            'reg add \"HKLM/SOFTWARE/Policies/Microsoft/Windows NT/Printers/PointAndPrint\" '\n            '/v NoWarningNoElevationOnInstall /t REG_DWORD /d 1 /f',\n            'reg add \"HKLM/SOFTWARE/Policies/Microsoft/Windows NT/Printers/PointAndPrint\" '\n            '/v UpdatePromptSettings /t REG_DWORD /d 2 /f',\n        ]:\n            self._run_cmd(cmd)\n        self._sharing_log(\"  \u2705 Point &amp; Print registry \u2192 configured\", C[\"success\"])\n        self._sharing_log(\"\u2705 [CLIENT] Registry changes complete!\", C[\"success\"])\n        self._sharing_log(\"   \u26a0 Restart recommended.\", C[\"warning\"])\n\n    def _client_connect_printer(self):\n        \"\"\"CLIENT: Dialog to connect to HOST's shared printer.\"\"\"\n        dlg = tk.Toplevel(self)\n        dlg.title(\"\ud83d\udda8 Client \u2014 Host se Shared Printer Connect Karo\")\n        dlg.geometry(\"540x470\")\n        dlg.configure(bg=C[\"bg\"])\n        dlg.grab_set()\n\n        tk.Label(dlg, text=\"\ud83d\udda8  Client: Host se Printer Connect Karo\",\n                 font=FONTS[\"subhead\"], fg=C[\"accent2\"], bg=C[\"bg\"]).pack(\n                 pady=(16,4), padx=20)\n        tk.Label(dlg,\n                 text=\"Host PC ka naam/IP aur Printer Share Name daalein\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"]).pack(padx=20)\n\n        info = tk.Frame(dlg, bg=C[\"card\"])\n        info.pack(fill=\"x\", padx=20, pady=8)\n\n        fields = {}\n        field_defs = [\n            (\"Host PC Name / IP:\",   \"host\",  \"e.g. 192.168.1.5  ya  OFFICPC\",  False),\n            (\"Printer Share Name:\",  \"share\", \"e.g. HP_LaserJet\",                False),\n            (\"Username (optional):\", \"user\",  \"khali chhod sakte hain\",           False),\n            (\"Password (optional):\", \"pwd\",   \"khali chhod sakte hain\",           True),\n        ]\n        for lbl, key, placeholder, secret in field_defs:\n            row = tk.Frame(info, bg=C[\"card\"])\n            row.pack(fill=\"x\", pady=4, padx=8)\n            tk.Label(row, text=lbl, font=FONTS[\"body\"], fg=C[\"text\"],\n                     bg=C[\"card\"], width=22, anchor=\"w\").pack(side=\"left\")\n            e = tk.Entry(row, font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"],\n                         insertbackground=C[\"text\"], relief=\"flat\", bd=4,\n                         width=24, show=\"*\" if secret else \"\")\n            e.insert(0, placeholder)\n            e.bind(\"\",\n                   lambda ev, p=placeholder, en=e: en.delete(0, \"end\") if en.get() == p else None)\n            e.bind(\"\",\n                   lambda ev, p=placeholder, en=e: en.insert(0, p) if not en.get() else None)\n            e.pack(side=\"left\", padx=4)\n            fields[key] = e\n\n        log = scrolledtext.ScrolledText(\n            dlg, height=9, font=FONTS[\"mono\"],\n            bg=C[\"bg\"], fg=C[\"text\"], bd=0, state=\"disabled\")\n        log.pack(fill=\"both\", expand=True, padx=20, pady=4)\n\n        def _log(msg, col=C[\"text\"]):\n            log.config(state=\"normal\")\n            log.insert(\"end\", msg + \"\\n\")\n            log.see(\"end\")\n            log.config(state=\"disabled\")\n\n        def _do_connect():\n            host  = fields[\"host\"].get().strip()\n            share = fields[\"share\"].get().strip()\n            user  = fields[\"user\"].get().strip()\n            pwd   = fields[\"pwd\"].get().strip()\n            if not host or \"e.g\" in host:\n                messagebox.showwarning(\"Host Missing\",\n                    \"Host PC ka naam ya IP enter karo.\", parent=dlg)\n                return\n            if not share or \"e.g\" in share:\n                messagebox.showwarning(\"Share Missing\",\n                    \"Printer share name enter karo.\", parent=dlg)\n                return\n            unc = f\"\\\\\\\\{host}\\\\{share}\"\n\n            def _run():\n                _log(f\"\ud83d\udd17 Connecting to: {unc}\")\n\n                # Step 1: Client firewall\n                self._run_cmd(\n                    'netsh advfirewall firewall set rule '\n                    'group=\"File and Printer Sharing\" new enable=Yes profile=any')\n                _log(\"  \u2705 Client firewall rules \u2192 ON\")\n\n                # Step 2: net use (authentication)\n                has_user = user and \"khali\" not in user\n                has_pwd  = pwd  and \"khali\" not in pwd\n                if has_user and has_pwd:\n                    net_cmd = f'net use \"{unc}\" /user:{user} {pwd} /persistent:yes'\n                elif has_user:\n                    net_cmd = f'net use \"{unc}\" /user:{user} /persistent:yes'\n                else:\n                    net_cmd = f'net use \"{unc}\" /persistent:yes'\n\n                out, rc = self._run_cmd(net_cmd, timeout=15)\n                if rc == 0 or \"completed\" in out.lower():\n                    _log(f\"  \u2705 Network path accessible: {unc}\")\n                else:\n                    _log(f\"  \u26a0 net use: {out[:120]}\")\n                    _log(\"  \u2139 Phir bhi printer add karne ki koshish kar raha hoon...\")\n\n                # Step 3: Add printer \u2014 PowerShell\n                out2, rc2 = self._run_cmd(\n                    f'powershell -Command \"Add-Printer -ConnectionName \\'{unc}\\'\"',\n                    timeout=20)\n                if rc2 == 0:\n                    _log(f\"  \u2705 Printer added from {unc}!\")\n                else:\n                    # Fallback 1: rundll32\n                    self._run_cmd(\n                        f'rundll32 printui.dll,PrintUIEntry /in /n \"{unc}\"')\n                    _log(\"  \u2705 Printer add attempt via legacy method (rundll32)\")\n                    _log(f\"  \u2139 Agar nahi hua: Control Panel \u2192 Printers \u2192 \"\n                         f\"Add Printer \u2192 Network \u2192 {unc}\")\n\n                # Step 4: Auto-open confirmation\n                def _confirm():\n                    subprocess.Popen([\"control.exe\", \"printers\"], shell=False)\n                    time.sleep(1)\n                    self._printer_detect()\n                    messagebox.showinfo(\n                        \"\ud83d\udda8 Connection Result\",\n                        f\"Connection attempt complete!\\n\\n\"\n                        f\"Host  : {host}\\n\"\n                        f\"Share : {share}\\n\"\n                        f\"Path  : {unc}\\n\\n\"\n                        \"\u2705 Printers window khul gaya hai.\\n\"\n                        \"Wahan shared printer check karo.\\n\\n\"\n                        \"Agar nahi dikh raha:\\n\"\n                        \"1. Host pe 'Auto-Share' dobara chalao\\n\"\n                        \"2. Host pe 'Port Fix' chalao\\n\"\n                        \"3. Dono PC ek hi workgroup mein hain? Check karo.\",\n                        parent=dlg)\n                self.after(0, _confirm)\n                self._sharing_log(\n                    f\"[CLIENT] Printer connect attempt \u2192 {unc}\", C[\"accent2\"])\n\n            self._launch_job(\"open_network_explorer\", _run)\n\n        def _do_ping():\n            host = fields[\"host\"].get().strip()\n            if not host or \"e.g\" in host:\n                messagebox.showwarning(\"Host Missing\",\n                    \"Host ka IP ya naam pehle enter karo.\", parent=dlg)\n                return\n            threading.Thread(\n                target=lambda: _log(self._run_cmd(f'ping -n 3 {host}')[0]),\n                daemon=True).start()\n\n        def _browse():\n            subprocess.Popen([\"explorer.exe\", \"Network\"], shell=False)\n\n        btn_f = tk.Frame(dlg, bg=C[\"bg\"])\n        btn_f.pack(pady=8)\n        self._btn(btn_f, \"\ud83d\udda8 Connect Printer\",  C[\"btn_warn\"],   _do_connect).pack(side=\"left\", padx=4)\n        self._btn(btn_f, \"\ud83c\udfd3 Ping Host\",        C[\"btn_chip\"],   _do_ping).pack(side=\"left\", padx=4)\n        self._btn(btn_f, \"\ud83c\udf10 Browse Network\",   C[\"btn_info\"],   _browse).pack(side=\"left\", padx=4)\n        self._btn(btn_f, \"\u274c Close\",             C[\"btn_danger\"], dlg.destroy).pack(side=\"left\", padx=4)\n\n    def _build_driver(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udce6 Driver Checker\",\n                             \"Third-party drivers \u2014 outdated ya problem wale dhundho, update karo\")\n\n        # \u2500\u2500 Guide Banner \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        guide = tk.Frame(frame, bg=\"#0D1F0D\", highlightbackground=C[\"accent2\"], highlightthickness=1)\n        guide.pack(fill=\"x\", padx=16, pady=(4, 6))\n        tk.Label(guide, text=\"\ud83d\udcd6  Kaise use karein?\", font=FONTS[\"subhead\"], fg=C[\"accent2\"], bg=\"#0D1F0D\").pack(anchor=\"w\", padx=12, pady=(8,2))\n        for s in [\n            \"\u2460 'Scan Drivers' dabao \u2014 third-party drivers ki list aayegi\",\n            \"\u2461 List mein driver select karo \u2192 'Open in Device Manager' se update/uninstall karo\",\n            \"\u2462 'Open Driver Folder' se driver file directly dekh sakte ho\",\n            \"\u2463 'Export CSV' se list save karo \u2014 customer ko dene ke liye useful\",\n            \"\u26a0  Old 'Link Date' wale drivers update karne chahiye \u2014 yellow mein highlight honge\",\n        ]:\n            tk.Label(guide, text=s, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=\"#0D1F0D\", anchor=\"w\").pack(anchor=\"w\", padx=20, pady=1)\n        tk.Label(guide, text=\"\", bg=\"#0D1F0D\").pack(pady=3)\n\n        # \u2500\u2500 Action Buttons \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        self._action_card_grid(frame, [\n            (\"\ud83d\udd0d\", \"Scan Drivers\",         \"Third-party drivers scan karo\",          C[\"btn_info\"],   self._scan_drivers),\n            (\"\ud83d\udda5\",  \"Open Device Manager\",  \"Windows Device Manager mein update karo\",C[\"btn_warn\"],   self._driver_open_devmgr),\n            (\"\ud83d\udcc2\", \"Open Driver Folder\",   \"Selected driver ki file location kholo\", C[\"btn_chip\"],   self._driver_open_folder),\n            (\"\ud83d\udce5\", \"Export CSV\",           \"Driver list CSV mein save karo\",         C[\"accent2\"],    self._driver_export_csv),\n        ], cols=4)\n\n        # \u2500\u2500 Treeview for driver list \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        tv_frame = tk.Frame(frame, bg=C[\"bg\"])\n        tv_frame.pack(fill=\"both\", expand=True, padx=16, pady=(4, 4))\n\n        cols = (\"Display Name\", \"Module\", \"Type\", \"Link Date\", \"Path\")\n        self.driver_tree = ttk.Treeview(tv_frame, columns=cols, show=\"headings\",\n                                         height=18, style=\"Custom.Treeview\",\n                                         selectmode=\"browse\")\n        for col, w in zip(cols, [200, 130, 80, 110, 380]):\n            self.driver_tree.heading(col, text=col)\n            self.driver_tree.column(col, width=w, anchor=\"w\")\n        self.driver_tree.tag_configure(\"old\",  foreground=C[\"warning\"])\n        self.driver_tree.tag_configure(\"ok\",   foreground=C[\"success\"])\n        dsb = ttk.Scrollbar(tv_frame, orient=\"vertical\", command=self.driver_tree.yview)\n        self.driver_tree.configure(yscrollcommand=dsb.set)\n        self.driver_tree.pack(side=\"left\", fill=\"both\", expand=True)\n        dsb.pack(side=\"right\", fill=\"y\")\n\n        # Status bar\n        self.driver_status_lbl = tk.Label(frame, text=\"  Scan karo \u2014 drivers list yahan aayegi\",\n                                           font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"], anchor=\"w\")\n        self.driver_status_lbl.pack(fill=\"x\", padx=16, pady=(2, 4))\n\n        # Fallback log (error/warnings ke liye)\n        self.driver_log = self._scrolled_text(frame, height=4)\n        self._driver_rows = []   # store parsed data\n        return frame\n\n    def _scan_drivers(self):\n        self._launch_job(\"scan_drivers\", self._do_scan_drivers)\n\n    def _do_scan_drivers(self):\n        import datetime as _dt\n        self.after(0, lambda: self.driver_tree.delete(*self.driver_tree.get_children()))\n        self.after(0, lambda: self.driver_status_lbl.config(text=\"  \u23f3 Scanning drivers...\", fg=C[\"accent4\"]))\n        self._append_log(self.driver_log, \"\ud83d\udd0d driverquery chal raha hai...\", C[\"accent4\"])\n        out, rc = self._run_cmd('driverquery /FO CSV /V', timeout=30)\n        if rc != 0 or not out.strip():\n            self._append_log(self.driver_log, \"\u274c driverquery failed. Admin mode mein run karo.\", C[\"error\"])\n            self.after(0, lambda: self.driver_status_lbl.config(text=\"  \u274c Scan failed \u2014 Admin mode use karo\", fg=C[\"error\"]))\n            return\n        try:\n            reader = csv.DictReader(io.StringIO(out))\n            self._driver_rows = []\n            cutoff_year = _dt.datetime.now().year - 3   # 3 saal purana = old\n\n            for r in reader:\n                mod  = (r.get(\"Module Name\") or r.get(\"ModuleName\") or \"\").strip()\n                disp = (r.get(\"Display Name\") or r.get(\"DisplayName\") or \"\").strip()\n                dtype= (r.get(\"Driver Type\")  or r.get(\"DriverType\")  or \"\").strip()\n                link = (r.get(\"Link Date\")    or r.get(\"LinkDate\")    or \"\").strip()\n                path = (r.get(\"Path\") or \"\").strip()\n                if not mod and not disp:\n                    continue\n                if \"microsoft\" in (disp.lower() + \" \" + path.lower()):\n                    continue\n                self._driver_rows.append((disp or mod, mod, dtype, link, path))\n\n            # Sort: purane pehle (link date ascending)\n            self._driver_rows.sort(key=lambda x: (x[3] or \"0000\", x[0].lower()))\n\n            def populate():\n                for name, mod, dtype, link, path in self._driver_rows:\n                    # Tag: old if link year &lt; cutoff\n                    tag = \"ok\"\n                    try:\n                        yr = int(link.split(\"/\")[-1]) if \"/\" in link else int(link[-4:]) if len(link) &gt;= 4 else 9999\n                        if yr &lt; cutoff_year:\n                            tag = \"old\"\n                    except:\n                        pass\n                    self.driver_tree.insert(\"\", \"end\", values=(name, mod, dtype, link, path), tags=(tag,))\n\n                total = len(self._driver_rows)\n                self.driver_status_lbl.config(\n                    text=f\"  \u2705 {total} third-party drivers found  |  \ud83d\udfe1 Yellow = 3+ saal purane (update recommended)\",\n                    fg=C[\"success\"])\n                self._append_log(self.driver_log, f\"\u2705 {total} drivers found.\", C[\"success\"])\n            self.after(0, populate)\n\n        except Exception as e:\n            self._append_log(self.driver_log, f\"\u26a0 Parse error: {e}\", C[\"warning\"])\n            self.after(0, lambda: self.driver_status_lbl.config(text=f\"  \u26a0 Error: {e}\", fg=C[\"warning\"]))\n\n    def _driver_open_devmgr(self):\n        \"\"\"Windows Device Manager open karo \u2014 wahan driver update/uninstall possible hai.\"\"\"\n        self._run_cmd(\"devmgmt.msc\", timeout=5)\n        self._append_log(self.driver_log, \"\u2705 Device Manager khola gaya. Driver select karo \u2192 Right-click \u2192 Update Driver.\", C[\"success\"])\n\n    def _driver_open_folder(self):\n        \"\"\"Selected driver ki folder location Explorer mein open karo.\"\"\"\n        sel = self.driver_tree.selection()\n        if not sel:\n            messagebox.showinfo(\"Select Driver\", \"Pehle list mein ek driver select karo.\")\n            return\n        path = self.driver_tree.item(sel[0])[\"values\"][4]\n        if not path or not os.path.exists(path):\n            messagebox.showwarning(\"Not Found\", f\"Driver file nahi mili:\\n{path}\")\n            return\n        folder = os.path.dirname(path)\n        try:\n            os.startfile(folder)\n            self._append_log(self.driver_log, f\"\ud83d\udcc2 Folder khola: {folder}\", C[\"success\"])\n        except Exception as e:\n            messagebox.showerror(\"Error\", str(e))\n\n    # ---------- DUPLICATE FINDER ----------\n    def _build_dupfinder(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83e\uddec Duplicate Finder\", \"Find &amp; remove duplicate files (size + hash)\")\n\n        top = tk.Frame(frame, bg=C[\"card\"])\n        top.pack(fill=\"x\", padx=16, pady=8)\n\n        tk.Label(top, text=\"Folder:\", font=FONTS[\"body\"], fg=C[\"text\"], bg=C[\"card\"]).pack(side=\"left\", padx=6)\n        self.dup_folder_var = tk.StringVar(value=os.path.join(os.path.expanduser(\"~\"), \"Downloads\"))\n        self.dup_folder_entry = tk.Entry(top, textvariable=self.dup_folder_var, width=46, font=FONTS[\"body\"])\n        self.dup_folder_entry.pack(side=\"left\", padx=6)\n        self._btn(top, \"\ud83d\udcc1 Browse\", C[\"btn_info\"], self._dup_pick_folder).pack(side=\"left\", padx=4)\n\n        tk.Label(top, text=\"Mode:\", font=FONTS[\"body\"], fg=C[\"text\"], bg=C[\"card\"]).pack(side=\"left\", padx=(12, 4))\n        self.dup_mode_var = tk.StringVar(value=\"fast\")\n        ttk.Combobox(top, values=[\"fast\", \"accurate\"], textvariable=self.dup_mode_var,\n                     width=10, font=FONTS[\"body\"], state=\"readonly\").pack(side=\"left\", padx=4)\n\n        tk.Label(top, text=\"Min MB:\", font=FONTS[\"body\"], fg=C[\"text\"], bg=C[\"card\"]).pack(side=\"left\", padx=(12, 4))\n        self.dup_min_mb = tk.Entry(top, width=6, font=FONTS[\"body\"])\n        self.dup_min_mb.insert(0, \"1\")\n        self.dup_min_mb.pack(side=\"left\", padx=4)\n\n        self._action_card_grid(frame, [\n            (\"\ud83d\udd0d\", \"Scan Duplicates\",          \"Folder mein duplicate files dhundho\", C[\"btn_danger\"], self._dup_start_scan),\n            (\"\ud83d\udce6\", \"Move to Quarantine\",        \"Selected files quarantine mein bhejo\",C[\"btn_warn\"],   self._dup_quarantine_selected),\n            (\"\ud83d\uddd1\",  \"Delete Selected\",          \"Selected files permanently delete karo\",C[\"btn_danger\"],self._dup_delete_selected),\n            (\"\ud83d\udcc2\", \"Open Selected Folder\",     \"File ki location folder open karo\",   C[\"btn_chip\"],   self._dup_open_selected_folder),\n        ], cols=4)\n\n        prog = tk.Frame(frame, bg=C[\"card\"])\n        prog.pack(fill=\"x\", padx=16, pady=(0, 6))\n        self.dup_status_lbl = tk.Label(prog, text=\"Ready\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], anchor=\"w\")\n        self.dup_status_lbl.pack(fill=\"x\", padx=8, pady=(6, 2))\n        self.dup_progress = tk.DoubleVar(value=0)\n        ttk.Progressbar(prog, variable=self.dup_progress, maximum=100, mode=\"determinate\").pack(fill=\"x\", padx=8, pady=(0, 8))\n\n        cols = (\"Group\", \"Filename\", \"Size\", \"Path\")\n        self.dup_tree = ttk.Treeview(frame, columns=cols, show=\"headings\", height=20, style=\"Custom.Treeview\", selectmode=\"extended\")\n        for col, w in zip(cols, [80, 260, 90, 520]):\n            self.dup_tree.heading(col, text=col)\n            self.dup_tree.column(col, width=w, anchor=\"w\")\n        vsb = ttk.Scrollbar(frame, orient=\"vertical\", command=self.dup_tree.yview)\n        self.dup_tree.configure(yscrollcommand=vsb.set)\n        self.dup_tree.pack(side=\"left\", fill=\"both\", expand=True, padx=16, pady=8)\n        vsb.pack(side=\"right\", fill=\"y\", pady=8, padx=(0, 8))\n\n        self.dup_log = self._scrolled_text(frame, height=8)\n        self._dup_results = []  # list of meta dicts aligned with displayed rows\n        return frame\n\n    def _dup_pick_folder(self):\n        path = filedialog.askdirectory(title=\"Select Folder to Scan\")\n        if path:\n            self.dup_folder_var.set(path)\n\n    def _dup_start_scan(self):\n        folder = (self.dup_folder_var.get() or \"\").strip()\n        if not folder or not os.path.isdir(folder):\n            messagebox.showwarning(\"Input\", \"Valid folder select karo.\")\n            return\n        mode = (self.dup_mode_var.get() or \"fast\").strip().lower()\n        try:\n            min_mb = float((self.dup_min_mb.get() or \"0\").strip())\n        except Exception:\n            min_mb = 0\n        min_bytes = int(max(0, min_mb) * 1024 * 1024)\n        if not messagebox.askyesno(\"Duplicate Scan\",\n                                   f\"Folder: {folder}\\nMode: {mode}\\nMin size: {min_mb} MB\\n\\nScan start karein?\"):\n            return\n        self.dup_tree.delete(*self.dup_tree.get_children())\n        self._dup_results = []\n        self.dup_progress.set(0)\n        self.dup_status_lbl.config(text=\"Scanning...\", fg=C[\"accent4\"])\n        self._launch_job(\"duplicate_scan\", self._dup_do_scan, folder, mode, min_bytes)\n\n    def _dup_hash_fast(self, path, size):\n        h = hashlib.sha256()\n        with open(path, \"rb\") as f:\n            head = f.read(min(size, 1024 * 1024))\n            h.update(head)\n            if size &gt; 2 * 1024 * 1024:\n                try:\n                    f.seek(max(0, size - 1024 * 1024))\n                    tail = f.read(1024 * 1024)\n                    h.update(tail)\n                except Exception:\n                    pass\n        return h.hexdigest()\n\n    def _dup_hash_full(self, path):\n        h = hashlib.sha256()\n        with open(path, \"rb\") as f:\n            while True:\n                chunk = f.read(1024 * 1024)\n                if not chunk:\n                    break\n                h.update(chunk)\n        return h.hexdigest()\n\n    def _dup_do_scan(self, folder, mode, min_bytes):\n        try:\n            self._append_log(self.dup_log, f\"\ud83d\udd0d Scanning: {folder}\", C[\"accent\"])\n            files = []\n            scanned = 0\n            for dirpath, _, filenames in os.walk(folder):\n                for fn in filenames:\n                    full = os.path.join(dirpath, fn)\n                    try:\n                        st = os.stat(full)\n                        if st.st_size &lt; min_bytes:\n                            continue\n                        files.append((full, int(st.st_size)))\n                    except Exception:\n                        continue\n                scanned += 1\n                if scanned % 200 == 0:\n                    self.after(0, lambda s=scanned: self.dup_status_lbl.config(text=f\"Scanning... {s} folders\", fg=C[\"accent4\"]))\n\n            by_size = {}\n            for p, sz in files:\n                by_size.setdefault(sz, []).append(p)\n            candidates = [(sz, ps) for sz, ps in by_size.items() if len(ps) &gt; 1]\n            if not candidates:\n                self.after(0, lambda: self.dup_status_lbl.config(text=\"No duplicates candidates found.\", fg=C[\"warning\"]))\n                self.after(0, lambda: self.dup_progress.set(100))\n                self._append_log(self.dup_log, \"\u2705 No duplicate candidates (by size).\", C[\"success\"])\n                return\n\n            total = sum(len(ps) for _, ps in candidates)\n            done = 0\n            groups = []\n            for sz, paths in candidates:\n                hash_map = {}\n                for p in paths:\n                    try:\n                        if mode == \"accurate\":\n                            hx = self._dup_hash_full(p)\n                        else:\n                            hx = self._dup_hash_fast(p, sz)\n                        hash_map.setdefault(hx, []).append(p)\n                    except Exception:\n                        continue\n                    done += 1\n                    if done % 25 == 0:\n                        pct = int((done / max(1, total)) * 100)\n                        self.after(0, lambda pct=pct: self.dup_progress.set(pct))\n                        self.after(0, lambda d=done, t=total: self.dup_status_lbl.config(text=f\"Hashing... {d}/{t}\", fg=C[\"accent4\"]))\n                for hx, ps in hash_map.items():\n                    if len(ps) &gt; 1:\n                        groups.append({\"size\": sz, \"hash\": hx, \"paths\": ps})\n\n            def render():\n                self.dup_tree.delete(*self.dup_tree.get_children())\n                self._dup_results = []\n                gid = 0\n                dup_files = 0\n                dup_bytes = 0\n                for g in groups:\n                    gid += 1\n                    group_label = f\"G{gid}\"\n                    for p in g[\"paths\"]:\n                        name = os.path.basename(p)\n                        self.dup_tree.insert(\"\", \"end\",\n                                             values=(group_label, name, self._fmt_size(g[\"size\"]), p))\n                        self._dup_results.append({\"path\": p, \"group\": group_label, \"size\": g[\"size\"], \"hash\": g[\"hash\"]})\n                        dup_files += 1\n                    # duplicates count excludes one \"original\"\n                    if len(g[\"paths\"]) &gt; 1:\n                        dup_bytes += (len(g[\"paths\"]) - 1) * g[\"size\"]\n                self.dup_progress.set(100)\n                if groups:\n                    self.dup_status_lbl.config(\n                        text=f\"\u2705 {len(groups)} duplicate group(s) found | extra space: {self._fmt_size(dup_bytes)}\",\n                        fg=C[\"success\"])\n                    self._append_log(self.dup_log, f\"\u2705 Groups: {len(groups)} | Extra space: {self._fmt_size(dup_bytes)}\", C[\"success\"])\n                else:\n                    self.dup_status_lbl.config(text=\"No duplicates found (hash matched none).\", fg=C[\"warning\"])\n                    self._append_log(self.dup_log, \"\u2705 No duplicates after hashing.\", C[\"success\"])\n\n            self.after(0, render)\n        except Exception as e:\n            self.after(0, lambda: self.dup_status_lbl.config(text=f\"Scan failed: {e}\", fg=C[\"error\"]))\n\n    def _dup_selected_entries(self):\n        items = []\n        for iid in self.dup_tree.selection():\n            idx = self.dup_tree.index(iid)\n            if 0 &lt;= idx &lt; len(self._dup_results):\n                items.append(self._dup_results[idx])\n        return items\n\n    def _dup_quarantine_selected(self):\n        sel = self._dup_selected_entries()\n        if not sel:\n            messagebox.showinfo(\"No Selection\", \"Pehle duplicate files select karo.\")\n            return\n        base = (self.dup_folder_var.get() or \"\").strip()\n        quarantine = os.path.join(base, \"_Duplicate_Quarantine\")\n        if not messagebox.askyesno(\"Quarantine\",\n                                   f\"Selected {len(sel)} file(s) quarantine folder me move honge:\\n{quarantine}\\n\\nProceed?\"):\n            return\n        os.makedirs(quarantine, exist_ok=True)\n        moved = 0\n        for it in sel:\n            src = it.get(\"path\", \"\")\n            if not src or not os.path.exists(src):\n                continue\n            dst = os.path.join(quarantine, os.path.basename(src))\n            # avoid overwrite\n            if os.path.exists(dst):\n                root, ext = os.path.splitext(dst)\n                dst = f\"{root}_{int(time.time())}{ext}\"\n            try:\n                shutil.move(src, dst)\n                moved += 1\n            except Exception as e:\n                self._append_log(self.dup_log, f\"\u274c Move failed: {src} ({e})\", C[\"error\"])\n        self._append_log(self.dup_log, f\"\u2705 Moved to quarantine: {moved}\", C[\"success\"])\n        self._dup_start_scan()\n\n    def _dup_delete_selected(self):\n        sel = self._dup_selected_entries()\n        if not sel:\n            messagebox.showinfo(\"No Selection\", \"Pehle duplicate files select karo.\")\n            return\n        if not messagebox.askyesno(\"Permanent Delete\",\n                                   f\"\u26a0\ufe0f Selected {len(sel)} file(s) PERMANENT delete honge.\\nUndo possible nahi.\\n\\nProceed?\"):\n            return\n        deleted = 0\n        for it in sel:\n            src = it.get(\"path\", \"\")\n            if not src or not os.path.exists(src):\n                continue\n            try:\n                os.remove(src)\n                deleted += 1\n            except Exception as e:\n                self._append_log(self.dup_log, f\"\u274c Delete failed: {src} ({e})\", C[\"error\"])\n        self._append_log(self.dup_log, f\"\ud83d\uddd1 Deleted: {deleted}\", C[\"warning\"])\n        self._dup_start_scan()\n\n    def _dup_open_selected_folder(self):\n        sel = self._dup_selected_entries()\n        if not sel:\n            messagebox.showinfo(\"No Selection\", \"Pehle ek file select karo.\")\n            return\n        p = sel[0].get(\"path\", \"\")\n        if not p:\n            return\n        folder = os.path.dirname(p)\n        try:\n            os.startfile(folder)\n        except Exception:\n            pass\n\n    def _build_backup(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udcbe Backup/Restore\", \"Profiles\")\n        self._action_card_grid(frame, [\n            (\"\ud83d\udcc0\", \"Backup Settings\",  \"Current settings JSON mein save karo\", C[\"btn_info\"], self._backup_settings),\n            (\"\ud83d\udd04\", \"Restore Settings\", \"Pehle saved settings wapas lao\",       C[\"btn_warn\"], self._restore_settings),\n        ], cols=2)\n        self.backup_log = self._scrolled_text(frame, height=18)\n        return frame\n\n    def _backup_settings(self):\n        data = {\"reg\": {k: v.get() for k, v in self.reg_vars.items()}, \"gp\": {k: v.get() for k, v in self.gp_vars.items()}}\n        fpath = filedialog.asksaveasfilename(defaultextension=\".json\", filetypes=[(\"JSON\",\"*.json\")])\n        if fpath:\n            with open(fpath, \"w\") as f:\n                json.dump(data, f, indent=2)\n            self._append_log(self.backup_log, \"\u2705 Saved\", C[\"success\"])\n\n    def _restore_settings(self):\n        fpath = filedialog.askopenfilename(filetypes=[(\"JSON\",\"*.json\")])\n        if fpath:\n            with open(fpath, \"r\") as f:\n                data = json.load(f)\n            if \"reg\" in data:\n                for k, val in data[\"reg\"].items():\n                    if k in self.reg_vars:\n                        self.reg_vars[k].set(bool(val))\n            self._append_log(self.backup_log, \"\u2705 Restored\", C[\"success\"])\n\n    def _build_report(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udcca HTML Report\", \"Export system report\")\n        self._action_card_grid(frame, [\n            (\"\ud83d\udcd1\", \"Generate Report\", \"System ka HTML report export karo\", C[\"btn_info\"], self._export_report),\n        ], cols=1)\n        self.report_log = self._scrolled_text(frame, height=18)\n        return frame\n\n    def _export_report(self):\n        fpath = filedialog.asksaveasfilename(defaultextension=\".html\", filetypes=[(\"HTML\",\"*.html\")])\n        if fpath:\n            vm = psutil.virtual_memory()\n            du = psutil.disk_usage(\"/\")\n            html = f\"\nGodawari Report\nCPU: {psutil.cpu_percent()}% | RAM: {vm.percent}% | Disk: {du.percent}%\"\n            with open(fpath, \"w\") as f:\n                f.write(html)\n            self._append_log(self.report_log, \"\u2705 Saved\", C[\"success\"])\n            os.startfile(fpath)\n\n    def _build_log(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udcdd Activity Log\", \"History\")\n        self._action_card_grid(frame, [\n            (\"\ud83d\udcbe\", \"Save Log\",   \"Log file Desktop pe save karo\",C[\"btn_info\"],   self._save_log),\n            (\"\ud83d\uddd1\", \"Clear Log\",  \"Log screen saaf karo\",          C[\"btn_danger\"], self._clear_log),\n        ], cols=2)\n        log_frame = tk.Frame(frame, bg=C[\"card\"])\n        log_frame.pack(fill=\"both\", expand=True, padx=16, pady=8)\n        self.log_text = scrolledtext.ScrolledText(log_frame, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"], height=28, bd=0, wrap=\"word\", relief=\"flat\", state=\"disabled\")\n        self.log_text.pack(fill=\"both\", expand=True, padx=8, pady=(0,8))\n        for line, color in self.log_lines:\n            self.log_text.config(state=\"normal\")\n            self.log_text.insert(\"end\", line + \"\\n\", f\"c{color.replace('#','')}\")\n            self.log_text.tag_config(f\"c{color.replace('#','')}\", foreground=color)\n            self.log_text.config(state=\"disabled\")\n        return frame\n\n    def _save_log(self):\n        path = os.path.join(os.path.expanduser(\"~\"), \"Desktop\", f\"Godawari_Log_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.txt\")\n        self.log_text.config(state=\"normal\")\n        with open(path, \"w\", encoding=\"utf-8\") as f:\n            f.write(self.log_text.get(\"1.0\", \"end\"))\n        self.log_text.config(state=\"disabled\")\n        messagebox.showinfo(\"Saved\", f\"Log saved to Desktop\")\n\n    def _clear_log(self):\n        self.log_lines.clear()\n        self.log_text.config(state=\"normal\")\n        self.log_text.delete(\"1.0\", \"end\")\n        self.log_text.config(state=\"disabled\")\n\n    # ---------- REMAINING HARDWARE SECTIONS (unchanged) ----------\n    def _build_motherboard(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udda5\ufe0f Motherboard Info\", \"Board &amp; BIOS\", hw=True)\n        self._action_card_grid(frame, [\n            (\"\ud83d\udda5\", \"Scan Motherboard\", \"Board maker, model, BIOS version\", C[\"btn_hw\"], self._scan_mb),\n        ], cols=1)\n        self.mb_log = self._scrolled_text(frame, 20)\n        return frame\n\n    def _scan_mb(self):\n        self.mb_log.config(state=\"normal\")\n        self.mb_log.delete(\"1.0\", \"end\")\n        self.mb_log.config(state=\"disabled\")\n        self._launch_job(\"scan_mb\", self._do_scan_mb)\n\n    def _do_scan_mb(self):\n        out, _ = self._run_cmd(\"wmic baseboard get Manufacturer,Product,Version,SerialNumber /format:list\")\n        self._append_log(self.mb_log, \"\u2550\"*50, C[\"border\"])\n        self._append_log(self.mb_log, \"  MOTHERBOARD INFORMATION\", C[\"hw_accent\"])\n        for line in out.splitlines():\n            if \"=\" in line:\n                self._append_log(self.mb_log, f\"  {line}\", C[\"text\"])\n        self._set_status(\"Motherboard scan complete\", C[\"success\"])\n\n    def _build_chip_diag(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udd2c CPU Diagnostics\", \"Architecture &amp; Cache\", hw=True)\n        self._action_card_grid(frame, [\n            (\"\ud83d\udd2c\", \"Full CPU Analysis\", \"CPU cores, cache, speed details\", C[\"btn_chip\"], self._scan_cpu),\n        ], cols=1)\n        self.chip_log = self._scrolled_text(frame, 20)\n        return frame\n\n    def _scan_cpu(self):\n        self.chip_log.config(state=\"normal\")\n        self.chip_log.delete(\"1.0\", \"end\")\n        self.chip_log.config(state=\"disabled\")\n        self._launch_job(\"scan_cpu\", self._do_scan_cpu)\n\n    def _do_scan_cpu(self):\n        out, _ = self._run_cmd(\"wmic cpu get Name,MaxClockSpeed,NumberOfCores,L2CacheSize,L3CacheSize /format:list\")\n        self._append_log(self.chip_log, \"\u2550\"*50, C[\"border\"])\n        self._append_log(self.chip_log, \"  CPU ARCHITECTURE &amp; CACHE\", C[\"hw_accent\"])\n        for line in out.splitlines():\n            if \"=\" in line:\n                self._append_log(self.chip_log, f\"  {line}\", C[\"text\"])\n\n    def _build_voltage_monitor(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\u26a1 Voltage Monitor\", \"PSU Rails Reference\", hw=True)\n        self._action_card_grid(frame, [\n            (\"\u26a1\", \"Scan Voltages\", \"PSU rails reference chart dekhao\", C[\"btn_chip\"], self._scan_volts),\n        ], cols=1)\n        self.volt_log = self._scrolled_text(frame, 20)\n        return frame\n\n    def _scan_volts(self):\n        self.volt_log.config(state=\"normal\")\n        self.volt_log.delete(\"1.0\", \"end\")\n        self.volt_log.config(state=\"disabled\")\n        self._launch_job(\"scan_volts\", self._do_scan_volts)\n\n    def _do_scan_volts(self):\n        self._append_log(self.volt_log, \"  PSU Rails (ATX Standard Reference):\", C[\"hw_accent\"])\n        for rail, spec in [(\"3.3V Rail\", \"3.135-3.465V\"), (\"5V Rail\", \"4.750-5.250V\"), (\"12V Rail\", \"11.400-12.600V\")]:\n            self._append_log(self.volt_log, f\"  {rail:&lt;15}: {spec}\", C[\"text\"])\n\n    def _build_gpu_diag_fixed(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83c\udfae GPU Diagnostics\", \"Real GPU Stats\", hw=True)\n        self._action_card_grid(frame, [\n            (\"\ud83c\udfae\", \"Scan GPU\", \"Graphics card details scan karo\", C[\"btn_chip\"], self._scan_gpu),\n        ], cols=1)\n        self.gpu_log = self._scrolled_text(frame, 20)\n        return frame\n\n    def _scan_gpu(self):\n        self.gpu_log.config(state=\"normal\")\n        self.gpu_log.delete(\"1.0\", \"end\")\n        self.gpu_log.config(state=\"disabled\")\n        self._launch_job(\"scan_gpu\", self._do_scan_gpu)\n\n    def _do_scan_gpu(self):\n        out, _ = self._run_cmd(\"wmic path win32_VideoController get Name,AdapterRAM,DriverVersion,VideoProcessor /format:list\")\n        self._append_log(self.gpu_log, \"\u2550\"*50, C[\"border\"])\n        self._append_log(self.gpu_log, \"  GPU INFORMATION\", C[\"hw_accent\"])\n        for line in out.splitlines():\n            if \"=\" in line and line.split(\"=\")[1].strip():\n                if \"AdapterRAM\" in line:\n                    try:\n                        line = f\"VRAM={self._fmt_size(int(line.split('=')[1]))}\"\n                    except:\n                        pass\n                self._append_log(self.gpu_log, line, C[\"text\"])\n\n    def _build_ram_slots(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83c\udccf RAM Slots\", \"DIMM Info\", hw=True)\n        self._action_card_grid(frame, [\n            (\"\ud83c\udccf\", \"Scan RAM Slots\", \"DIMM slot info \u2014 size, speed, brand\", C[\"btn_chip\"], self._scan_dimms),\n        ], cols=1)\n        self.ramslot_log = self._scrolled_text(frame, 20)\n        return frame\n\n    def _scan_dimms(self):\n        self.ramslot_log.config(state=\"normal\")\n        self.ramslot_log.delete(\"1.0\", \"end\")\n        self.ramslot_log.config(state=\"disabled\")\n        self._launch_job(\"scan_dimms\", self._do_scan_dimms)\n\n    def _do_scan_dimms(self):\n        out, _ = self._run_cmd(\"wmic memorychip get BankLabel,Capacity,Speed,Manufacturer /format:list\")\n        self._append_log(self.ramslot_log, \"\u2550\"*50, C[\"border\"])\n        self._append_log(self.ramslot_log, \"  RAM SLOT INFORMATION\", C[\"hw_accent\"])\n        for line in out.splitlines():\n            if \"=\" in line:\n                self._append_log(self.ramslot_log, f\"  {line}\", C[\"text\"])\n\n    def _build_post_codes(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udcdf POST Codes\", \"Reference\", hw=True)\n        self.post_tree = ttk.Treeview(frame, columns=(\"BIOS\", \"Code\", \"Meaning\", \"Fix\"), show=\"headings\", height=24, style=\"Custom.Treeview\")\n        for col, w in zip((\"BIOS\", \"Code\", \"Meaning\", \"Fix\"), [100,100,300,400]):\n            self.post_tree.heading(col, text=col)\n            self.post_tree.column(col, width=w, anchor=\"w\")\n        for row in [(\"AMI\",\"1 Beep\",\"DRAM Refresh\",\"Reseat RAM\"),\n                    (\"AMI\",\"5 Beeps\",\"CPU Error\",\"Reseat CPU\"),\n                    (\"Award\",\"1 Long\",\"DRAM Error\",\"Check RAM\"),\n                    (\"Phoenix\",\"1-1-2\",\"CPU Fail\",\"Check CPU Socket\")]:\n            self.post_tree.insert(\"\", \"end\", values=row)\n        self.post_tree.pack(fill=\"both\", expand=True, padx=16, pady=8)\n        return frame\n\n    def _build_cap_check(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udd0d Capacitor Guide\", \"Visual Inspection\", hw=True)\n        self.cap_guide = self._scrolled_text(frame, 25)\n        self._append_log(self.cap_guide, \"\u274c BAD: Bulging top, leaked crust.\\n\u2705 GOOD: Flat top, clean base.\\nMOSFET BAD: Cracked, burnt legs.\", C[\"error\"])\n        return frame\n\n    # ---------- POWER BOOST SECTION (clean grid layout) ----------\n    def _build_boost_section(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\u26a1 Ultimate Power Boost\", \"PC ki speed badhaane ke liye professional tweaks \u2014 ek click mein\")\n\n        # \u2500\u2500 Top: One-Click master button \u2500\u2500\n        master_row = tk.Frame(frame, bg=C[\"card\"])\n        master_row.pack(fill=\"x\", padx=16, pady=(10, 4))\n        tk.Label(master_row, text=\"\ud83d\udd25  Sabse pehle yahi chalao:\",\n                 font=FONTS[\"subhead\"], fg=C[\"accent4\"], bg=C[\"card\"]).pack(side=\"left\", padx=14, pady=10)\n        def one_click_all_boosts():\n            if self._create_restore_point(\"Ultimate Power Boost\"):\n                self._launch_job(\"run_all_boosts\", self._run_all_boosts)\n        tk.Button(master_row, text=\"\u26a1 ONE-CLICK: Saare Boosts Apply Karo\",\n                  font=(\"Segoe UI\", 11, \"bold\"), bg=C[\"accent4\"], fg=C[\"bg\"],\n                  bd=0, padx=20, pady=10, cursor=\"hand2\",\n                  command=one_click_all_boosts).pack(side=\"left\", padx=10, pady=8)\n\n        # \u2500\u2500 Grid: individual tweak cards \u2500\u2500\n        grid_lbl = tk.Frame(frame, bg=C[\"bg\"])\n        grid_lbl.pack(fill=\"x\", padx=16, pady=(8, 2))\n        tk.Label(grid_lbl, text=\"Ya alag alag apply karo:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"]).pack(side=\"left\")\n\n        grid = tk.Frame(frame, bg=C[\"bg\"])\n        grid.pack(fill=\"x\", padx=16, pady=4)\n\n        boost_items = [\n            (\"\u26a1\", \"CPU Cores Unpark\",   \"Sabhi cores active karo\\n(latency kum hoti hai)\",       C[\"btn_hw\"],     lambda: self._confirm_and_run(\"Unpark CPU Cores\", \"Sabhi CPU cores hamesha active rahenge, latency kum hogi.\", lambda: f\"CPU cores: {psutil.cpu_count()}\", self._unpark_cpu_cores, None)),\n            (\"\ud83c\udfaf\", \"App Priority Fix\",   \"Foreground app ko\\nzyada CPU do\",                        C[\"btn_info\"],   lambda: self._confirm_and_run(\"Priority Optimizer\", \"Foreground apps ko zyada CPU priority milegi.\", lambda: \"Default Windows settings.\", self._auto_priority_optimizer, None)),\n            (\"\ud83d\udcc0\", \"Pagefile Optimize\",  \"RAM ke hisaab se\\nPagefile set karo (1.5x)\",             C[\"btn_warn\"],   lambda: self._confirm_and_run(\"Optimal Pagefile\", \"Pagefile 1.5x RAM size pe set hoga.\", lambda: \"Current pagefile badle ga.\", self._optimal_pagefile, None)),\n            (\"\ud83e\udde0\", \"RAM Compression Off\",\"Memory compression band\\n(CPU load ghatega)\",            C[\"btn_chip\"],   lambda: self._confirm_and_run(\"Disable Memory Compression\", \"Memory compression disable hoga, CPU load kum hoga.\", lambda: \"Currently on.\", self._disable_memory_compression, None)),\n            (\"\ud83c\udfae\", \"Game Mode ON\",       \"Game Mode + GPU\\nScheduling enable karo\",                C[\"btn_info\"],   lambda: self._confirm_and_run(\"Game Mode\", \"Game Mode aur GPU hardware scheduling enable hoga.\", lambda: \"Current: unknown.\", self._enable_game_mode, None)),\n            (\"\u2601\ufe0f\", \"OneDrive Hatao\",     \"OneDrive uninstall karo\\n(Explorer fast hoga)\",          C[\"btn_danger\"], lambda: self._confirm_and_run(\"Remove OneDrive\", \"OneDrive poori tarah uninstall hoga.\", lambda: \"OneDrive installed hai.\", self._remove_onedrive, None)),\n        ]\n\n        for i, (emoji, title, desc, color, cmd) in enumerate(boost_items):\n            col = i % 3\n            row_n = i // 3\n            card = tk.Frame(grid, bg=C[\"card\"], highlightbackground=color, highlightthickness=1)\n            card.grid(row=row_n, column=col, padx=6, pady=6, sticky=\"nsew\")\n            grid.columnconfigure(col, weight=1)\n            tk.Label(card, text=emoji, font=(\"Segoe UI\", 18), fg=color, bg=C[\"card\"]).pack(pady=(10, 2))\n            tk.Label(card, text=title, font=FONTS[\"subhead\"], fg=C[\"text\"], bg=C[\"card\"]).pack()\n            tk.Label(card, text=desc, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"],\n                     justify=\"center\", wraplength=180).pack(padx=8, pady=4)\n            tk.Button(card, text=\"\u25b6 Apply\", font=FONTS[\"small\"],\n                      bg=color, fg=C[\"bg\"] if color in [C[\"accent\"], C[\"accent2\"], C[\"accent4\"]] else C[\"text\"],\n                      bd=0, padx=14, pady=5, cursor=\"hand2\",\n                      command=cmd).pack(pady=(0, 10))\n\n        # \u2500\u2500 Log area \u2500\u2500\n        tk.Label(frame, text=\"  Result Log:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"]).pack(anchor=\"w\", padx=16, pady=(8, 2))\n        self.boost_log = self._scrolled_text(frame, height=10)\n        return frame\n\n    def _run_all_boosts(self):\n        self._append_log(self.boost_log, \"Starting Deep Scan + Ultimate Power Boost...\", C[\"accent4\"])\n        self._deep_boost_scan()\n        self._unpark_cpu_cores(quiet=True)\n        self._auto_priority_optimizer(quiet=True)\n        self._optimal_pagefile(quiet=True)\n        self._disable_memory_compression(quiet=True)\n        self._enable_game_mode(quiet=True)\n        self._remove_onedrive(quiet=True)\n        self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Multimedia\\SystemProfile\", \"NetworkThrottlingIndex\", 0xffffffff, winreg.REG_DWORD, \"Network throttling disabled\", self.boost_log)\n        self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\DeliveryOptimization\\Config\", \"DODownloadMode\", 0, winreg.REG_DWORD, \"Delivery Optimization P2P off\", self.boost_log)\n        self._service_stop_checked(\"DoSvc\", \"Delivery Optimization service\", self.boost_log)\n        self._service_config_checked(\"DoSvc\", \"disabled\", \"Delivery Optimization service\", self.boost_log)\n        self._run_cmd('powercfg -h off')\n        self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Power\", \"HiberbootEnabled\", 0, winreg.REG_DWORD, \"Fast Startup disabled\", self.boost_log)\n        self._append_log(self.boost_log, \"\ud83c\udf89 All boosts applied! Restart recommended.\", C[\"success\"])\n        self._set_status(\"Ultimate Power Boost Complete\", C[\"success\"])\n\n    def _deep_boost_scan(self):\n        try:\n            vm = psutil.virtual_memory()\n            self._append_log(self.boost_log, f\"Deep scan: RAM used {vm.percent:.1f}% | available {self._fmt_size(vm.available)}\", C[\"text\"])\n            heavy = []\n            for proc in psutil.process_iter(['pid', 'name', 'memory_info']):\n                try:\n                    mem = proc.info.get('memory_info')\n                    rss = mem.rss if mem else 0\n                    if rss:\n                        heavy.append((rss, proc.info.get('pid'), proc.info.get('name') or 'unknown'))\n                except Exception:\n                    pass\n            for rss, pid, name in sorted(heavy, reverse=True)[:5]:\n                self._append_log(self.boost_log, f\"Deep scan process: PID {pid} {name} {self._fmt_size(rss)}\", C[\"text_dim\"])\n            junk_total = 0\n            for path in [os.environ.get(\"TEMP\", \"\"), r\"C:\\Windows\\Temp\", os.path.join(os.environ.get(\"LOCALAPPDATA\", \"\"), r\"Microsoft\\Windows\\Explorer\")]:\n                if path and os.path.exists(path):\n                    junk_total += self._folder_size(path)\n            self._append_log(self.boost_log, f\"Deep scan cache estimate: {self._fmt_size(junk_total)}\", C[\"accent\"])\n        except Exception as e:\n            self._append_log(self.boost_log, f\"Deep scan skipped: {e}\", C[\"warning\"])\n\n    def _unpark_cpu_cores(self, quiet=False):\n        try:\n            self._run_cmd('powercfg -setacvalueindex scheme_current sub_processor 0cc5b647-c1df-4637-891a-dec35c318583 0')\n            self._run_cmd('powercfg -setactive scheme_current')\n            msg = \"\u2705 CPU Cores Unparked (All cores active)\"\n            if not quiet:\n                self._append_log(self.boost_log, msg, C[\"success\"])\n            else:\n                self._log(msg, \"OK\")\n        except:\n            pass\n\n    def _auto_priority_optimizer(self, quiet=False):\n        self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Multimedia\\SystemProfile\", \"SystemResponsiveness\", 0, winreg.REG_DWORD)\n        self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Multimedia\\SystemProfile\", \"EnablePriorityBoost\", 1, winreg.REG_DWORD)\n        self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Multimedia\\SystemProfile\\Tasks\\Games\", \"GPU Priority\", 8, winreg.REG_DWORD)\n        self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Multimedia\\SystemProfile\\Tasks\\Games\", \"Priority\", 6, winreg.REG_DWORD)\n        msg = \"\u2705 Foreground app priority boosted, background lowered\"\n        if not quiet:\n            self._append_log(self.boost_log, msg, C[\"success\"])\n        else:\n            self._log(msg, \"OK\")\n\n    def _optimal_pagefile(self, quiet=False):\n        try:\n            total_ram_gb = psutil.virtual_memory().total // (1024**3)\n            recommended_mb = max(1024, total_ram_gb * 1024)  # min 1GB\n            self._run_cmd(f'wmic pagefileset where name=\"C:\\\\\\\\pagefile.sys\" set InitialSize={recommended_mb},MaximumSize={recommended_mb}')\n            msg = f\"\u2705 Pagefile set to {recommended_mb}MB (1x RAM)\"\n            if not quiet:\n                self._append_log(self.boost_log, msg, C[\"success\"])\n        except Exception as e:\n            self._append_log(self.boost_log, f\"Pagefile error: {e}\", C[\"error\"])\n\n    def _disable_memory_compression(self, quiet=False):\n        self._run_cmd('powershell \"Disable-MMAgent -MemoryCompression\"')\n        msg = \"\u2705 Memory Compression Disabled (CPU load reduced)\"\n        if not quiet:\n            self._append_log(self.boost_log, msg, C[\"success\"])\n        else:\n            self._log(msg, \"OK\")\n\n    def _enable_game_mode(self, quiet=False):\n        self._reg_set(winreg.HKEY_CURRENT_USER, r\"Software\\Microsoft\\Windows\\CurrentVersion\\GameDVR\", \"AppCaptureEnabled\", 0, winreg.REG_DWORD)\n        self._reg_set(winreg.HKEY_CURRENT_USER, r\"Software\\Microsoft\\Windows\\CurrentVersion\\GameDVR\", \"GameDVR_Enabled\", 0, winreg.REG_DWORD)\n        self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\PolicyManager\\default\\ApplicationManagement\\AllowGameDVR\", \"value\", 0, winreg.REG_DWORD)\n        self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Multimedia\\SystemProfile\", \"SystemResponsiveness\", 0, winreg.REG_DWORD)\n        self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Multimedia\\SystemProfile\\Tasks\\Games\", \"GPU Priority\", 8, winreg.REG_DWORD)\n        self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Multimedia\\SystemProfile\\Tasks\\Games\", \"Priority\", 6, winreg.REG_DWORD)\n        msg = \"\u2705 Game Mode + GPU Scheduling Enabled\"\n        if not quiet:\n            self._append_log(self.boost_log, msg, C[\"success\"])\n        else:\n            self._log(msg, \"OK\")\n\n    def _remove_onedrive(self, quiet=False):\n        try:\n            self._run_cmd('taskkill /f /im OneDrive.exe')\n            self._run_cmd('%SystemRoot%\\\\SysWOW64\\\\OneDriveSetup.exe /uninstall')\n            self._run_cmd('%SystemRoot%\\\\System32\\\\OneDriveSetup.exe /uninstall')\n            self._run_cmd('rd \"%UserProfile%\\\\OneDrive\" /s /q')\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Policies\\Microsoft\\Windows\\OneDrive\", \"DisableFileSyncNGSC\", 1, winreg.REG_DWORD)\n            msg = \"\u2705 OneDrive completely removed (Explorer will be faster)\"\n            if not quiet:\n                self._append_log(self.boost_log, msg, C[\"success\"])\n            else:\n                self._log(msg, \"OK\")\n        except Exception as e:\n            self._append_log(self.boost_log, f\"OneDrive removal error: {e}\", C[\"error\"])\n\n    # ---------- QUICK ACTIONS ----------\n    def _quick_clean_and_ram(self):\n        \"\"\"Clean Temp + RAM Optimize \u2014 ek saath dono kaam\"\"\"\n        self._quick_clean_temp()\n        self.after(500, self._quick_optimize_ram)\n\n    def _quick_services_and_registry(self):\n        \"\"\"Services disable + Registry tweaks \u2014 ek saath dono kaam\"\"\"\n        self._quick_services()\n        self.after(500, self._quick_registry)\n\n    def _quick_clean_temp(self):\n        self._show_section(\"cleaner\")\n        self._professional_scan()\n\n    def _quick_optimize_ram(self):\n        self._show_section(\"memory\")\n        self._ram_empty_with_confirm()\n\n    def _quick_services(self):\n        self._show_section(\"services\")\n        self._scan_impacting_services()\n\n    def _quick_registry(self):\n        self._show_section(\"registry\")\n        self._apply_registry()\n\n    def _full_scan(self):\n        def before():\n            return \"Starting full system scan (cleaner + services).\"\n        def action():\n            self._do_full_scan()\n        self._confirm_and_run(\"Full System Scan\", \"This will scan for junk files and heavy services. No changes will be applied automatically.\", before, action, None)\n\n    def _do_full_scan(self):\n        self._do_clean_scan()\n        self._do_scan_services()\n        self._log(\"Full scan complete\", \"OK\")\n\n    def _one_click_health_scan(self):\n        self._set_status(\"Health scan...\", C[\"accent4\"])\n        self._launch_job(\"health_scan\", self._do_health_scan)\n\n    def _do_health_scan(self):\n        try:\n            report = self.health_engine.analyze()\n            self._last_health_report = report\n            self.after(0, lambda: self._apply_health_report_ui(report))\n            lines = [f\"Health Score: {report['score']}/100 ({report['grade']})\"]\n            for c in report.get(\"checks\", [])[:12]:\n                lines.append(f\"  \u2022 {c['name']}: {c['detail']}\")\n            if report.get(\"recommendations\"):\n                lines.append(\"\\nRecommendations:\")\n                for r in report[\"recommendations\"]:\n                    lines.append(f\"  \u2192 {r}\")\n            msg = \"\\n\".join(lines)\n            self.after(0, lambda: messagebox.showinfo(\"System Health Scan\", msg))\n            self.after(0, lambda: self._set_status(f\"Health score: {report['score']}/100\", C[\"success\"]))\n        except Exception as e:\n            self.after(0, lambda: messagebox.showerror(\"Health Scan\", str(e)))\n\n    def _apply_health_report_ui(self, report):\n        if not report or \"health\" not in getattr(self, \"dash_cards\", {}):\n            return\n        try:\n            score = int(report.get(\"score\", 0))\n            grade = report.get(\"grade\", \"\")\n            color = C.get(report.get(\"color\", \"accent\"), C[\"accent\"])\n            self.dash_cards[\"health\"]._value_lbl.config(text=f\"{score}\")\n            self.dash_cards[\"health\"]._bar.config(value=score)\n            if hasattr(self, \"safety_health_lbl\"):\n                self.safety_health_lbl.config(\n                    text=f\"{score}/100 \u2014 {grade}\", fg=color)\n            if hasattr(self, \"dashboard_recommendation_tree\"):\n                self._refresh_intelligent_recommendations()\n            if hasattr(self, \"safety_recommendations\"):\n                self.safety_recommendations.config(text=self._recommendations_as_text(limit=6), fg=C[\"text\"])\n        except Exception:\n            pass\n\n    def _refresh_health_score_card(self):\n        def task():\n            try:\n                report = self.health_engine.analyze()\n                self._last_health_report = report\n                self.after(0, lambda r=report: self._apply_health_report_ui(r))\n            except Exception:\n                pass\n        self._launch_job(\"health_score_refresh\", task)\n\n    def _one_click_all_boosts(self):\n        if self._create_restore_point(\"One Click All Boosts\"):\n            self._launch_job(\"run_all_boosts\", self._run_all_boosts)\n\n    # ---------- ADVANCED TOOLS ----------\n    def _adv_tree(self, parent, columns, height=12):\n        wrap = tk.Frame(parent, bg=C[\"card\"])\n        tree = ttk.Treeview(wrap, columns=columns, show=\"headings\", height=height, style=\"Custom.Treeview\")\n        vsb = ttk.Scrollbar(wrap, orient=\"vertical\", command=tree.yview)\n        hsb = ttk.Scrollbar(wrap, orient=\"horizontal\", command=tree.xview)\n        tree.configure(yscrollcommand=vsb.set, xscrollcommand=hsb.set)\n        tree.grid(row=0, column=0, sticky=\"nsew\")\n        vsb.grid(row=0, column=1, sticky=\"ns\")\n        hsb.grid(row=1, column=0, sticky=\"ew\")\n        wrap.rowconfigure(0, weight=1)\n        wrap.columnconfigure(0, weight=1)\n        for col in columns:\n            tree.heading(col, text=col)\n            tree.column(col, width=130, anchor=\"w\", stretch=True)\n        return wrap, tree\n\n    def _adv_card(self, parent, title):\n        frame = tk.LabelFrame(parent, text=title, font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"], bd=1, relief=\"flat\", labelanchor=\"nw\")\n        return frame\n\n    def _build_driver_manager(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"Driver Manager\", \"Driver scan, purane driver aur unsigned risk check\")\n        content = self._scrollable_section_body(frame)\n        self._action_card_grid(content, [\n            (\"\ud83d\udd0d\", \"Driver Scan\", \"Saare drivers scan karo\", C[\"btn_info\"], self._driver_scan_all),\n            (\"\ud83d\udccb\", \"Purane Only\", \"Purane drivers filter karo\", C[\"btn_chip\"], self._driver_filter_old),\n            (\"\ud83d\udd04\", \"Unsigned Only\", \"Unsigned drivers filter karo\", C[\"btn_warn\"], self._driver_filter_unsigned),\n            (\"\ud83d\udcbe\", \"CSV Backup\", \"Driver list CSV mein save karo\", C[\"btn\"], self._driver_export_csv),\n            (\"\ud83c\udf10\", \"Device Manager\", \"Device Manager kholo\", C[\"accent2\"], lambda: self._run_cmd(\"devmgmt.msc\")),\n            (\"\u2699\", \"Driver Update via WU\", \"Windows Update se driver updates dhundo\", C[\"btn_chip\"], self._easydriver_update_via_windows_update),\n        ], cols=6)\n        body = tk.Frame(content, bg=C[\"bg\"])\n        body.pack(fill=\"both\", expand=True, padx=14, pady=8)\n        left = tk.Frame(body, bg=C[\"card\"])\n        left.pack(side=\"left\", fill=\"both\", expand=True, padx=(0,8))\n        right = tk.Frame(body, bg=C[\"card\"], width=380)\n        right.pack(side=\"right\", fill=\"both\", padx=(8,0))\n        right.pack_propagate(False)\n        cols = [\"Device Name\", \"Driver Version\", \"Driver Date\", \"Status\", \"Age\"]\n        wrap, self.driver_tree = self._adv_tree(left, cols, height=18)\n        wrap.pack(fill=\"both\", expand=True, padx=8, pady=8)\n        self.driver_tree.tag_configure(\"old\", foreground=C[\"warning\"])\n        self.driver_tree.tag_configure(\"very_old\", foreground=C[\"error\"])\n        self.driver_tree.tag_configure(\"unsigned\", foreground=C[\"error\"])\n        self.driver_tree.tag_configure(\"ok\", foreground=C[\"success\"])\n        self.driver_tree.bind(\"&lt;&gt;\", self._driver_on_select)\n        self.driver_detail = tk.Frame(right, bg=C[\"card\"])\n        self.driver_detail.pack(fill=\"both\", expand=True, padx=10, pady=10)\n        tk.Label(self.driver_detail, text=\"Driver select karo\", font=FONTS[\"subhead\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\")\n        self.driver_log = self._scrolled_text(content, height=7)\n        self.driver_all_rows = []\n        return frame\n\n    def _build_easy_driver_clone(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udda5 Easy Driver\",\n                             \"Missing/Outdated driver scan, Windows Update driver install, backup &amp; restore \u2014 DriverEasy style\")\n        content = self._scrollable_section_body(frame)\n\n        # \u2500\u2500 Fixed top area: info banner + action buttons \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        top = tk.Frame(content, bg=C[\"bg\"])\n        top.pack(fill=\"x\")\n\n        info = tk.Frame(top, bg=\"#0D1A0D\", highlightbackground=C[\"accent2\"], highlightthickness=1)\n        info.pack(fill=\"x\", padx=16, pady=(4, 6))\n        for txt in [\n            \"\ud83c\udf10 Internet required for Windows Update driver downloads.\",\n            \"\ud83d\udcbe Driver backup uses built-in pnputil export/restore.\",\n            \"\u26a0 Only signed drivers install successfully \u2014 unsigned drivers are skipped.\",\n            \"\u2705 Missing driver scan uses real PnP device status and WMI fallback.\",\n        ]:\n            tk.Label(info, text=txt, font=FONTS[\"small\"], fg=C[\"text_dim\"],\n                     bg=\"#0D1A0D\", anchor=\"w\").pack(anchor=\"w\", padx=12, pady=1)\n        tk.Label(info, text=\"\", bg=\"#0D1A0D\").pack(pady=2)\n\n        self._action_card_grid(top, [\n            (\"\ud83d\udd0d\", \"Scan Missing\",  \"Error/missing drivers dhundo\", C[\"error\"],   self._easydriver_scan_and_show),\n            (\"\ud83d\udccb\", \"Scan Outdated\", \"Purane drivers list karo\",       C[\"btn_warn\"], self._easydriver_show_outdated),\n            (\"\ud83c\udf10\", \"Update via WU\",  \"Windows Update se install karo\", C[\"btn_chip\"], self._easydriver_update_via_windows_update),\n            (\"\ud83d\udcbe\", \"Backup All\",    \"Saare installed drivers export karo\", C[\"accent2\"], self._easydriver_backup_all),\n            (\"\ud83d\udce5\", \"Restore Backup\", \"Backup folder se restore karo\",   C[\"btn_chip\"], self._easydriver_restore_from_backup),\n            (\"\ud83d\udda5\", \"Device Manager\", \"Windows Device Manager kholo\",   C[\"btn\"],     lambda: self._run_cmd(\"devmgmt.msc\", timeout=5)),\n        ], cols=3)\n\n        # \u2500\u2500 Progress bar (always visible, fixed below buttons) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        clone_prog_frame = tk.Frame(content, bg=C[\"card\"], relief=\"flat\", bd=0)\n        clone_prog_frame.pack(fill=\"x\", padx=16, pady=(4, 2))\n        self.clone_status_label = tk.Label(\n            clone_prog_frame,\n            text=\"Ready\",\n            font=FONTS[\"small\"],\n            fg=C[\"text_dim\"],\n            bg=C[\"card\"],\n            anchor=\"w\"\n        )\n        self.clone_status_label.pack(fill=\"x\", padx=6, pady=(4, 2))\n        self.clone_progress_var = tk.DoubleVar(value=0.0)\n        self.clone_progress_bar = ttk.Progressbar(\n            clone_prog_frame,\n            variable=self.clone_progress_var,\n            maximum=100.0,\n            mode=\"determinate\"\n        )\n        self.clone_progress_bar.pack(fill=\"x\", padx=6, pady=(0, 6))\n\n        # \u2500\u2500 Scrollable body: tree + log \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        body_outer = tk.Frame(content, bg=C[\"bg\"])\n        body_outer.pack(fill=\"both\", expand=True, padx=16, pady=(4, 6))\n\n        cols = (\"Device Name\", \"Status\", \"Class\", \"Severity\", \"Action\")\n        self.driver_easy_tree = ttk.Treeview(body_outer, columns=cols, show=\"headings\",\n                                              height=12, style=\"Custom.Treeview\",\n                                              selectmode=\"browse\")\n        for col, w in zip(cols, [300, 90, 120, 90, 150]):\n            self.driver_easy_tree.heading(col, text=col)\n            self.driver_easy_tree.column(col, width=w, anchor=\"w\")\n        self.driver_easy_tree.tag_configure(\"critical\", foreground=C[\"error\"])\n        self.driver_easy_tree.tag_configure(\"warning\", foreground=C[\"warning\"])\n        self.driver_easy_tree.tag_configure(\"ok\", foreground=C[\"success\"])\n\n        vsb = ttk.Scrollbar(body_outer, orient=\"vertical\", command=self.driver_easy_tree.yview)\n        self.driver_easy_tree.configure(yscrollcommand=vsb.set)\n        self.driver_easy_tree.pack(side=\"left\", fill=\"both\", expand=True)\n        vsb.pack(side=\"right\", fill=\"y\")\n\n        self.driver_easy_log = self._scrolled_text(content, height=6)\n        self.driver_easy_rows = []\n        return frame\n\n    def _easydriver_set_progress(self, pct, text=None, mode=\"determinate\"):\n        def _update():\n            try:\n                pct_float = max(0.0, min(100.0, float(pct)))\n            except Exception:\n                pct_float = 0.0\n            if hasattr(self, \"clone_progress_bar\"):\n                try:\n                    self.clone_progress_bar.stop()\n                    self.clone_progress_bar.config(mode=mode)\n                    if mode == \"indeterminate\":\n                        self.clone_progress_bar.start(10)\n                except Exception:\n                    pass\n            if hasattr(self, \"clone_progress_var\"):\n                try:\n                    self.clone_progress_var.set(pct_float)\n                except Exception:\n                    pass\n            if hasattr(self, \"clone_status_label\") and text is not None:\n                self.clone_status_label.config(text=f\"{int(pct_float)}% - {str(text)[:180]}\")\n        self.after(0, _update)\n\n    def _easydriver_scan_and_show(self):\n        self._append_log(self.driver_easy_log, \"\ud83d\udd0d Easy Driver scan starting...\", C[\"accent\"])\n        self._easydriver_set_progress(0, \"Scanning missing/error drivers...\")\n        self._launch_job(\"easy_driver_scan\", self._do_easydriver_scan)\n\n    def _easydriver_show_outdated(self):\n        self._append_log(self.driver_easy_log, \"\ud83d\udd0d Easy Driver outdated scan starting...\", C[\"accent\"])\n        self._easydriver_set_progress(0, \"Scanning outdated drivers...\")\n        self._launch_job(\"easy_driver_outdated\", self._do_easydriver_show_outdated)\n\n    def _easydriver_check_internet(self):\n        import urllib.request\n        import urllib.error\n\n        for url in [\n            \"https://www.microsoft.com\",\n            \"https://www.google.com\",\n            \"https://1.1.1.1\",\n        ]:\n            try:\n                urllib.request.urlopen(url, timeout=5)\n                return True\n            except Exception:\n                continue\n\n        messagebox.showerror(\n            \"Internet Connection Nahi Mili\",\n            \"Driver auto-download ke liye internet zaroori hai.\\n\\n\"\n            \"Kya check karo:\\n\"\n            \"  1\ufe0f\u20e3  Wi-Fi ya LAN cable connected hai?\\n\"\n            \"  2\ufe0f\u20e3  Antivirus/Firewall block to nahi kar raha?\\n\"\n            \"  3\ufe0f\u20e3  Browser mein koi website khulti hai?\\n\\n\"\n            \"Offline kya kar sakte hain:\\n\"\n            \"  \u2705 Driver Scan \u2014 chalegi\\n\"\n            \"  \u2705 Driver Backup \u2014 chalegi (pnputil)\\n\"\n            \"  \u2705 Driver Restore \u2014 chalegi (agar backup hai)\\n\"\n            \"  \u274c Auto Download \u2014 nahi chalegi\"\n        )\n        return False\n\n    def _easydriver_update_via_windows_update(self):\n        if not hasattr(self, \"driver_easy_log\") and hasattr(self, \"driver_log\"):\n            self.driver_easy_log = self.driver_log\n        if not self._easydriver_check_internet():\n            return\n\n        if not messagebox.askyesno(\n            \"Windows Update Driver\",\n            \"Windows Update se drivers download aur install honge.\\n\\n\"\n            \"\u26a0 Kuch drivers ke liye reboot required hoga.\\n\"\n            \"\u26a0 Installation mein 5-15 minute lag sakta hai.\\n\\n\"\n            \"Pehle system restore point create kiya jaayega.\\n\\n\"\n            \"Continue karein?\"\n        ):\n            return\n\n        self._easydriver_set_progress(5, \"Creating restore point...\")\n        self._append_log(self.driver_easy_log, \"System Restore Point bana raha hoon...\", C[\"accent4\"])\n        rp = safe_powershell(\n            'Checkpoint-Computer -Description \"GodawariDriverUpdate\" '\n            '-RestorePointType DEVICE_DRIVER_INSTALL', timeout=120)\n        if rp.returncode == 0:\n            self._append_log(self.driver_easy_log, \"\u2705 Restore point created\", C[\"success\"])\n\n        wu_script = r\"\"\"\n        try {\n            $UpdateSession = New-Object -ComObject Microsoft.Update.Session\n            $Searcher = $UpdateSession.CreateUpdateSearcher()\n            $SearchResult = $Searcher.Search(\"IsInstalled=0 and Type='Driver'\")\n\n            $Updates = $SearchResult.Updates\n            $Count = $Updates.Count\n\n            if ($Count -eq 0) {\n                Write-Output \"NO_UPDATES\"\n                exit 0\n            }\n\n            Write-Output \"FOUND:$Count\"\n\n            $ToInstall = New-Object -ComObject Microsoft.Update.UpdateColl\n            for ($i=0; $i -lt $Updates.Count; $i++) {\n                $update = $Updates.Item($i)\n                Write-Output \"DRIVER:$($update.Title)\"\n                $ToInstall.Add($update) | Out-Null\n            }\n\n            $Downloader = $UpdateSession.CreateUpdateDownloader()\n            $Downloader.Updates = $ToInstall\n            Write-Output \"DOWNLOADING...\"\n            $DownloadResult = $Downloader.Download()\n            Write-Output \"DOWNLOAD_RC:$($DownloadResult.ResultCode)\"\n\n            $Installer = $UpdateSession.CreateUpdateInstaller()\n            $Installer.Updates = $ToInstall\n            Write-Output \"INSTALLING...\"\n            $InstallResult = $Installer.Install()\n            Write-Output \"INSTALL_RC:$($InstallResult.ResultCode)\"\n            Write-Output \"REBOOT_REQUIRED:$($InstallResult.RebootRequired)\"\n\n        } catch {\n            Write-Output \"ERROR:$($_.Exception.Message)\"\n        }\n        \"\"\"\n\n        def run_wu():\n            self._easydriver_set_progress(15, \"Searching Windows Update drivers...\")\n            result = safe_powershell(wu_script, timeout=600)\n            for line in result.output.splitlines():\n                line = line.strip()\n                if not line:\n                    continue\n                if line == \"NO_UPDATES\":\n                    self._easydriver_set_progress(100, \"No driver updates found.\")\n                    self.after(0, lambda: self._append_log(self.driver_easy_log, \"\u2705 Saare drivers up-to-date hain!\", C[\"success\"]))\n                elif line.startswith(\"FOUND:\"):\n                    count = line.split(\":\", 1)[1]\n                    self._easydriver_set_progress(30, f\"{count} driver update(s) found.\")\n                    self.after(0, lambda c=count: self._append_log(self.driver_easy_log, f\"\ud83d\udd0d {c} driver update(s) mila!\", C[\"accent4\"]))\n                elif line.startswith(\"DRIVER:\"):\n                    name = line.split(\":\", 1)[1]\n                    self.after(0, lambda n=name: self._append_log(self.driver_easy_log, f\"  \ud83d\udce6 {n}\", C[\"text\"]))\n                elif line.startswith(\"DOWNLOADING\"):\n                    self._easydriver_set_progress(45, \"Downloading driver updates...\", \"indeterminate\")\n                elif line.startswith(\"DOWNLOAD_RC:\"):\n                    self._easydriver_set_progress(65, f\"Download finished rc={line.split(':', 1)[1]}\")\n                elif line.startswith(\"INSTALLING\"):\n                    self._easydriver_set_progress(75, \"Installing driver updates...\", \"indeterminate\")\n                elif line.startswith(\"INSTALL_RC:\"):\n                    rc = line.split(\":\", 1)[1]\n                    status = \"\u2705 Install successful\" if rc in (\"2\", \"3\") else f\"\u26a0 Install rc={rc}\"\n                    color = C[\"success\"] if rc in (\"2\", \"3\") else C[\"warning\"]\n                    self._easydriver_set_progress(100 if rc in (\"2\", \"3\") else 90, status)\n                    self.after(0, lambda s=status, c=color: self._append_log(self.driver_easy_log, s, c))\n                elif line.startswith(\"REBOOT_REQUIRED:True\"):\n                    self.after(0, lambda: messagebox.showinfo(\n                        \"Reboot Required\",\n                        \"Driver install complete!\\n\\nSystem restart zaroori hai.\\nAbhi restart karein?\"\n                    ))\n                elif line.startswith(\"ERROR:\"):\n                    err = line.split(\":\", 1)[1]\n                    self._easydriver_set_progress(0, f\"Windows Update failed: {err}\")\n                    self.after(0, lambda e=err: self._append_log(self.driver_easy_log, f\"\u274c Error: {e}\", C[\"error\"]))\n\n        self._launch_job(\"easy_driver_update\", run_wu)\n\n    def _easydriver_backup_all(self):\n        backup_dir = filedialog.askdirectory(\n            title=\"Driver Backup Folder Select Karo (naya ya khali folder choose karo)\")\n        if not backup_dir:\n            return\n\n        if not messagebox.askyesno(\n            \"Driver Backup Confirm\",\n            f\"Saare installed drivers yahan export honge:\\n{backup_dir}\\n\\n\" \\\n            \"Isme kuch minute lag sakte hain.\\nContinue?\"):\n            return\n\n        self._append_log(self.driver_easy_log, f\"Driver backup shuru: {backup_dir}\", C[\"accent4\"])\n        self._easydriver_set_progress(0, \"Driver backup starting...\")\n\n        def run_backup():\n            self._easydriver_set_progress(10, \"Exporting installed drivers...\", \"indeterminate\")\n            result = safe_run([\"pnputil\", \"/export-driver\", \"*\", backup_dir], timeout=300)\n            out = (result.output or \"\").strip()\n            rc = result.returncode\n            inf_count = 0\n            try:\n                for root, _, files in os.walk(backup_dir):\n                    for f in files:\n                        if f.lower().endswith(\".inf\"):\n                            inf_count += 1\n            except Exception:\n                pass\n            if rc == 0:\n                self._easydriver_set_progress(100, f\"Backup complete: {inf_count} drivers exported.\")\n                self.after(0, lambda: self._append_log(\n                    self.driver_easy_log,\n                    f\"\u2705 Backup complete! {inf_count} drivers exported to:\\n{backup_dir}\",\n                    C[\"success\"]))\n                self.after(0, lambda: messagebox.showinfo(\n                    \"Backup Complete\",\n                    f\"\u2705 {inf_count} driver files backup ho gaye!\\n\\nLocation:\\n{backup_dir}\\n\\n\"\n                    \"Restore ke liye: 'Restore From Backup' button dabao.\"))\n            else:\n                self._easydriver_set_progress(0, f\"Backup failed rc={rc}\")\n                self.after(0, lambda: self._append_log(\n                    self.driver_easy_log,\n                    f\"\u274c Backup failed (rc={rc})\\n{out[:300]}\",\n                    C[\"error\"]))\n\n        self._launch_job(\"easy_driver_backup\", run_backup)\n\n    def _easydriver_restore_from_backup(self):\n        backup_dir = filedialog.askdirectory(\n            title=\"Driver Backup Folder Select Karo (jahan .inf files hain)\")\n        if not backup_dir:\n            return\n\n        inf_files = [f for f in os.listdir(backup_dir) if f.lower().endswith(\".inf\")]\n        if not inf_files:\n            messagebox.showerror(\"INF Files Nahi Mili\",\n                                 f\"Selected folder mein koi .inf file nahi mili:\\n{backup_dir}\\n\\n\"\n                                 \"Sahi backup folder select karo.\")\n            return\n\n        if not messagebox.askyesno(\n            \"Driver Restore Confirm\",\n            f\"Folder: {backup_dir}\\n\"\n            f\"INF files found: {len(inf_files)}\\n\\n\"\n            \"\u26a0 Yeh sab drivers install karne ki koshish karega.\\n\"\n            \"\u26a0 Kuch drivers ke liye reboot required ho sakta hai.\\n\"\n            \"\u26a0 Sirf digitally signed drivers install honge.\\n\\n\"\n            \"Continue?\"):\n            return\n\n        self._append_log(self.driver_easy_log,\n                         f\"Driver restore shuru: {backup_dir} ({len(inf_files)} INF files)\",\n                         C[\"accent4\"])\n        self._easydriver_set_progress(0, f\"Restoring {len(inf_files)} driver INF files...\")\n\n        def run_restore():\n            self._easydriver_set_progress(15, \"Installing drivers from backup...\", \"indeterminate\")\n            backup_dir_abs = os.path.abspath(backup_dir)\n            cmd = [\n                \"pnputil\",\n                \"/add-driver\",\n                backup_dir_abs,\n                \"/subdirs\",\n                \"/install\",\n            ]\n            result = safe_run(cmd, timeout=600)\n            out = (result.output or \"\").strip()\n            rc = result.returncode\n            installed = sum(1 for line in out.splitlines() if \"published name\" in line.lower())\n            failed = sum(1 for line in out.splitlines() if \"failed\" in line.lower())\n            status = \"OK\" if rc == 0 else \"PARTIAL\"\n            color = C[\"success\"] if status == \"OK\" else C[\"warning\"]\n            self._easydriver_set_progress(100 if rc == 0 else 90, f\"Restore {status}: {installed} installed, {failed} failed\")\n            self.after(0, lambda: self._append_log(\n                self.driver_easy_log,\n                f\"{'\u2705' if status=='OK' else '\u26a0'} Restore complete: \"\n                f\"{installed} drivers installed, {failed} failed\\n\"\n                f\"Return code: {rc}\",\n                color))\n            if rc == 0:\n                self.after(0, lambda: messagebox.showinfo(\n                    \"Restore Complete\",\n                    f\"\u2705 Driver restore complete!\\n\\n\"\n                    f\"Installed: {installed}\\n\"\n                    f\"Failed: {failed}\\n\\n\"\n                    \"System restart recommended.\"))\n\n        self._launch_job(\"easy_driver_restore\", run_restore)\n\n    def _easydriver_fill_tree(self, rows):\n        self.driver_easy_tree.delete(*self.driver_easy_tree.get_children())\n        for row in rows:\n            self.driver_easy_tree.insert(\"\", \"end\",\n                values=(row[\"name\"], row[\"status\"], row[\"class\"], row[\"severity\"], row[\"action\"]),\n                tags=(row[\"severity\"],))\n\n    def _easydriver_scan_missing(self):\n        script = \"\"\"\n        $devices = Get-PnpDevice -PresentOnly |\n            Where-Object { $_.Status -ne 'OK' } |\n            Select-Object Status, Class, FriendlyName, InstanceId,\n                          @{N='HardwareID';E={($_.HardwareID -join ';')}} |\n            ConvertTo-Json -Depth 2\n        \"\"\"\n        result = safe_powershell(script, timeout=60)\n        if result.returncode != 0 or not result.output.strip():\n            return self._easydriver_scan_missing_wmi()\n        try:\n            data = json.loads(result.output)\n            if isinstance(data, dict):\n                data = [data]\n        except json.JSONDecodeError:\n            return self._easydriver_scan_missing_wmi()\n        missing = []\n        for device in data:\n            name = device.get(\"FriendlyName\") or device.get(\"InstanceId\") or \"Unknown Device\"\n            status = device.get(\"Status\") or \"Unknown\"\n            missing.append({\n                \"name\": name,\n                \"status\": status,\n                \"class\": device.get(\"Class\") or \"Unknown\",\n                \"severity\": \"critical\" if status.lower() in (\"error\",\"unknown\") else \"warning\",\n                \"action\": \"Install Driver\" if status.lower() == \"unknown\" else \"Update Driver\",\n            })\n        return missing\n\n    def _easydriver_scan_missing_wmi(self):\n        script = \"\"\"\n        Get-WmiObject Win32_PnPEntity |\n        Where-Object { $_.ConfigManagerErrorCode -ne 0 } |\n        Select-Object Name, ConfigManagerErrorCode, DeviceID,\n                      @{N='HardwareID';E={($_.HardwareID -join ';')}} |\n        ConvertTo-Json\n        \"\"\"\n        result = safe_powershell(script, timeout=60)\n        try:\n            data = json.loads(result.output)\n            if isinstance(data, dict):\n                data = [data]\n            return [{\n                \"name\": d.get(\"Name\", \"Unknown\"),\n                \"status\": f\"Error Code {d.get('ConfigManagerErrorCode')}\",\n                \"class\": \"Unknown\",\n                \"severity\": \"warning\",\n                \"action\": \"Update Driver\",\n            } for d in data if d.get(\"Name\")]\n        except Exception:\n            return []\n\n    def _do_easydriver_scan(self):\n        try:\n            self._easydriver_set_progress(20, \"Querying PnP devices...\")\n            self.after(0, lambda: self._append_log(self.driver_easy_log, \"\ud83d\udd0d WMI aur PnP device query chal rahi hai...\", C[\"text_dim\"]))\n            rows = self._easydriver_scan_missing()\n            self._easydriver_set_progress(70, \"Preparing scan results...\")\n            if not rows:\n                self._easydriver_set_progress(100, \"No missing/error drivers detected.\")\n                self.after(0, lambda: self._append_log(self.driver_easy_log, \"\u2705 No missing or error drivers detected.\", C[\"success\"]))\n                self.after(0, lambda: self._easydriver_fill_tree([]))\n                return\n            for device in rows:\n                name = device.get(\"name\", \"Unknown\")\n                self.after(0, lambda n=name: self._append_log(self.driver_easy_log, f\"  \u2022 Checking: {n}\", C[\"text_dim\"]))\n            self.after(0, lambda: self._easydriver_fill_tree(rows))\n            self._easydriver_set_progress(100, f\"{len(rows)} problem device(s) detected.\")\n            self.after(0, lambda: self._append_log(self.driver_easy_log, f\"\u2705 {len(rows)} problem device(s) detected.\", C[\"warning\"]))\n        except Exception as e:\n            self._easydriver_set_progress(0, f\"Driver scan failed: {e}\")\n            self.after(0, lambda: self._append_log(self.driver_easy_log, f\"\u26a0 Driver scan failed: {e}\", C[\"error\"]))\n\n    def _do_easydriver_show_outdated(self):\n        try:\n            self._easydriver_set_progress(20, \"Reading signed driver inventory...\")\n            script = \"\"\"\n            Get-WmiObject Win32_PnPSignedDriver |\n            Select-Object DeviceName,DriverVersion,DriverDate,IsSigned,InfName |\n            ConvertTo-Json -Depth 2\n            \"\"\"\n            result = safe_powershell(script, timeout=120)\n            if result.returncode != 0 or not result.output.strip():\n                raise RuntimeError(\"Driver WMI query failed\")\n            data = json.loads(result.output)\n            if isinstance(data, dict):\n                data = [data]\n            rows = []\n            now = datetime.datetime.now()\n            total = max(1, len(data))\n            for d in data:\n                dt = self._driver_parse_date(d.get(\"DriverDate\"))\n                days = (now - dt).days if dt else None\n                signed = bool(d.get(\"IsSigned\"))\n                if days is None or days &lt; 365:\n                    continue\n                rows.append({\n                    \"name\": d.get(\"DeviceName\") or \"Unknown\",\n                    \"status\": \"Signed\" if signed else \"Unsigned\",\n                    \"class\": d.get(\"InfName\") or \"Driver Package\",\n                    \"severity\": \"critical\" if not signed else \"warning\",\n                    \"action\": f\"{days} days old\",\n                })\n                if len(rows) % 20 == 0:\n                    self._easydriver_set_progress(min(85, 20 + int((len(rows) / total) * 60)), \"Analyzing driver ages...\")\n            if not rows:\n                self._easydriver_set_progress(100, \"No outdated drivers older than 365 days found.\")\n                self.after(0, lambda: self._append_log(self.driver_easy_log, \"\u2705 No outdated drivers older than 365 days found.\", C[\"success\"]))\n                self.after(0, lambda: self._easydriver_fill_tree([]))\n                return\n            self.after(0, lambda: self._easydriver_fill_tree(rows))\n            self._easydriver_set_progress(100, f\"{len(rows)} outdated drivers detected.\")\n            self.after(0, lambda: self._append_log(self.driver_easy_log, f\"\u2705 {len(rows)} outdated drivers detected.\", C[\"warning\"]))\n        except Exception as e:\n            self._easydriver_set_progress(0, f\"Outdated scan failed: {e}\")\n            self.after(0, lambda: self._append_log(self.driver_easy_log, f\"\u26a0 Outdated scan failed: {e}\", C[\"error\"]))\n\n    def _build_partition_manager(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udcbd Partition Manager\",\n                             \"Partition operations with safe merge, shrink, extend, format, clone, and restore support.\")\n        content = self._scrollable_section_body(frame)\n\n        # \u2500\u2500 Fixed top: action buttons \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        top = tk.Frame(content, bg=C[\"bg\"])\n        top.pack(fill=\"x\")\n\n        self._action_card_grid(top, [\n            (\"\ud83d\udd04\", \"Refresh\", \"Partition map refresh karo\", C[\"accent\"], self._partition_refresh_tree),\n            (\"\ud83d\udd17\", \"Merge\", \"Do partitions merge karo\", C[\"accent2\"], self._partition_merge_prompt),\n            (\"\u2194\ufe0f\", \"Split\", \"Partition split karo\", C[\"btn_warn\"], self._partition_split_prompt),\n            (\"\u2b06\ufe0f\", \"Extend\", \"Partition expand karo\", C[\"btn_chip\"], self._partition_extend_prompt),\n            (\"\u2b07\ufe0f\", \"Shrink\", \"Partition shrink karo\", C[\"warning\"], self._partition_shrink_prompt),\n            (\"\ud83c\udf00\", \"Clone\", \"Partition contents clone karo\", C[\"btn\"], self._partition_clone_prompt),\n            (\"\u2699\ufe0f\", \"Format\", \"Partition NTFS format karo\", C[\"error\"], self._partition_format_prompt),\n            (\"\ud83d\udd20\", \"Change Letter\", \"Drive letter change karo\", C[\"btn\"], self._partition_change_letter_prompt),\n            (\"\u26d4\", \"Cancel\", \"Running partition op cancel karo\", C[\"warning\"], self._partition_cancel_operation),\n            (\"\ud83d\udcbe\", \"Backup Table\", \"Partition table ka backup banao\", C[\"accent4\"], self._partition_backup_table),\n        ], cols=3)\n\n        # \u2500\u2500 Progress bars (FIXED \u2014 always visible, below buttons) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        prog_container = tk.Frame(content, bg=C[\"bg\"])\n        prog_container.pack(fill=\"x\", padx=16, pady=(6, 2))\n\n        # Operation progress bar\n        progress_label_frame = tk.Frame(prog_container, bg=C[\"bg\"])\n        progress_label_frame.pack(fill=\"x\")\n        self.partition_op_status = tk.Label(\n            progress_label_frame,\n            text=\"Ready for partition operations.\",\n            font=FONTS[\"small\"],\n            fg=C[\"text_dim\"],\n            bg=C[\"bg\"],\n            anchor=\"w\",\n        )\n        self.partition_op_status.pack(side=\"left\", fill=\"x\", expand=True)\n        self.partition_op_pct_label = tk.Label(\n            progress_label_frame,\n            text=\"0%\",\n            font=FONTS[\"small\"],\n            fg=C[\"text_dim\"],\n            bg=C[\"bg\"],\n            anchor=\"e\",\n            width=6,\n        )\n        self.partition_op_pct_label.pack(side=\"right\")\n        self.partition_op_progress_var = tk.DoubleVar(value=0.0)\n        self.partition_op_progress_bar = ttk.Progressbar(\n            prog_container,\n            variable=self.partition_op_progress_var,\n            maximum=100.0,\n            mode=\"determinate\",\n        )\n        self.partition_op_progress_bar.pack(fill=\"x\", pady=(2, 6))\n\n        # Merge-specific progress bar\n        self.partition_merge_status_label = tk.Label(\n            prog_container,\n            text=\"Ready for partition merge operations.\",\n            font=FONTS[\"small\"],\n            fg=C[\"text_dim\"],\n            bg=C[\"bg\"],\n            anchor=\"w\",\n        )\n        self.partition_merge_status_label.pack(fill=\"x\")\n        self.partition_merge_progress_var = tk.DoubleVar(value=0.0)\n        self.partition_merge_progress = ttk.Progressbar(\n            prog_container,\n            variable=self.partition_merge_progress_var,\n            maximum=100.0,\n            mode=\"determinate\"\n        )\n        self.partition_merge_progress.pack(fill=\"x\", pady=(2, 4))\n\n        # \u2500\u2500 Disk bar canvas (responsive width &amp; redraw on resize) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        self.partition_canvas = tk.Canvas(content, height=self._dpi_px(80), bg=C[\"card\"], bd=0, highlightthickness=0)\n        self.partition_canvas.pack(fill=\"x\", padx=16, pady=(4, 4))\n        self.partition_canvas.bind(\"\", lambda event: self._partition_redraw_disk_bar())\n\n        # \u2500\u2500 Detail label \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        self.partition_detail = tk.Label(content, text=\"Select partition for details.\", font=FONTS[\"small\"],\n                                         fg=C[\"text_dim\"], bg=C[\"bg\"], anchor=\"w\")\n        self.partition_detail.pack(fill=\"x\", padx=16, pady=(0, 2))\n\n        # \u2500\u2500 Tree + log in scrollable body (expands to fill remaining space) \u2500\n        body = tk.Frame(content, bg=C[\"bg\"])\n        body.pack(fill=\"both\", expand=True, padx=16, pady=(0, 4))\n\n        cols = (\"Disk\", \"Partition\", \"Letter\", \"Type\", \"SizeGB\", \"FS\", \"Health\")\n        self.partition_tree = ttk.Treeview(body, columns=cols, show=\"headings\",\n                                           height=14, style=\"Custom.Treeview\",\n                                           selectmode=\"extended\")\n        for col, width in zip(cols, [60, 70, 70, 140, 90, 110, 110]):\n            self.partition_tree.heading(col, text=col)\n            self.partition_tree.column(col, width=width, anchor=\"w\")\n        self.partition_tree.tag_configure(\"warning\", foreground=C[\"warning\"])\n        self.partition_tree.tag_configure(\"error\", foreground=C[\"error\"])\n        self.partition_tree.pack(side=\"left\", fill=\"both\", expand=True)\n\n        vsb = ttk.Scrollbar(body, orient=\"vertical\", command=self.partition_tree.yview)\n        self.partition_tree.configure(yscrollcommand=vsb.set)\n        vsb.pack(side=\"right\", fill=\"y\")\n\n        self.partition_tree.bind(\"&lt;&gt;\", self._partition_on_tree_select)\n\n        self.partition_log = self._scrolled_text(content, height=5)\n        self.partition_data = {}\n        self._partition_refresh_tree()\n        return frame\n\n    def _partition_refresh_tree(self):\n        self._append_log(self.partition_log, \"\ud83d\udd04 Refreshing partition map...\", C[\"accent\"])\n        self._launch_job(\"partition_refresh\", self._partition_refresh_worker)\n\n    def _partition_refresh_worker(self):\n        try:\n            self._partition_update_progress(10, \"Querying disk and partition metadata...\")\n            data = self._partition_fetch_all_disks()\n            if not data or not data.get(\"Partitions\"):\n                self._partition_update_progress(0, \"Partition refresh failed: no data returned.\")\n                self.after(0, lambda: self._append_log(self.partition_log, \"\u274c Partition refresh failed.\", C[\"error\"]))\n                return\n            self.partition_data = data\n            self.after(0, lambda: self._partition_render_tree(data))\n            self._partition_update_progress(100, \"Partition map refreshed.\")\n            self.after(0, lambda: self._append_log(self.partition_log, \"\u2705 Partition map refreshed.\", C[\"success\"]))\n        except Exception as e:\n            self._partition_update_progress(0, f\"Partition refresh failed: {e}\")\n            self.after(0, lambda: self._append_log(self.partition_log, f\"\u274c Partition refresh failed: {e}\", C[\"error\"]))\n        finally:\n            self._partition_reset_progress_delayed(1500)\n\n    def _partition_update_progress(self, pct, status_text):\n        def _update():\n            try:\n                pct_float = max(0.0, min(100.0, float(pct)))\n            except Exception:\n                pct_float = 0.0\n            if hasattr(self, \"partition_op_progress_var\"):\n                self.partition_op_progress_var.set(pct_float)\n            if hasattr(self, \"partition_op_status\"):\n                self.partition_op_status.config(text=str(status_text)[:200])\n            if hasattr(self, \"partition_op_pct_label\"):\n                self.partition_op_pct_label.config(text=f\"{int(pct_float)}%\")\n            if hasattr(self, \"partition_merge_status_label\"):\n                self.partition_merge_status_label.config(text=str(status_text)[:200])\n            if hasattr(self, \"partition_merge_progress_var\"):\n                self.partition_merge_progress_var.set(pct_float)\n        self.after(0, _update)\n\n    def _partition_reset_progress_delayed(self, delay_ms=3000, session_id=None):\n        def _reset():\n            with self._partition_op_lock:\n                if session_id and self._partition_operation_session != session_id:\n                    return\n            self._partition_update_progress(0, \"Ready for partition operations.\")\n        self.after(delay_ms, _reset)\n\n    def _partition_start_operation(self, name):\n        with self._partition_op_lock:\n            if self._partition_operation_active:\n                return False, \"Another partition operation is already running.\"\n            self._partition_operation_active = True\n            self._partition_operation_session = f\"partition-{int(time.time() * 1000)}\"\n            self._partition_cancel_event.clear()\n            self._partition_operation_log = []\n            self._partition_operation_start_time = time.time()\n        self._partition_update_progress(0, f\"{name} initializing...\")\n        self._audit_event(\"partition_operation_start\", {\n            \"session\": self._partition_operation_session,\n            \"name\": name,\n        })\n        return True, self._partition_operation_session\n\n    def _partition_end_operation(self, session_id, success, message, color=C[\"success\"]):\n        with self._partition_op_lock:\n            if self._partition_operation_session != session_id:\n                return\n            elapsed = time.time() - (self._partition_operation_start_time or time.time())\n            self._partition_operation_active = False\n            self._partition_operation_session = None\n            self._partition_operation_start_time = None\n        self._audit_event(\"partition_operation_end\", {\n            \"session\": session_id,\n            \"success\": success,\n            \"message\": message,\n            \"elapsed_seconds\": round(elapsed, 2),\n        })\n        self._partition_update_progress(100 if success else 0, message)\n        self._partition_reset_progress_delayed(3000, session_id)\n\n    def _partition_cancel_operation(self):\n        if not self._partition_operation_active:\n            self._append_log(self.partition_log, \"\u26a0 Koi active partition operation nahi hai.\", C[\"warning\"])\n            return\n        self._partition_cancel_event.set()\n        self._partition_update_progress(0, \"Cancellation requested... Please wait.\")\n        self._append_log(self.partition_log, \"\u23f9 Partition operation cancellation requested.\", C[\"warning\"])\n        self._audit_event(\"partition_operation_cancel_requested\", {\"session\": self._partition_operation_session})\n\n    def _partition_operation_is_cancelled(self):\n        return self._partition_cancel_event.is_set()\n\n    def _partition_log_diagnostic(self, level, message, extra=None):\n        entry = {\n            \"ts\": datetime.datetime.now().isoformat(timespec=\"seconds\"),\n            \"level\": level,\n            \"message\": message,\n        }\n        if extra:\n            entry.update(extra)\n        self._partition_operation_log.append(entry)\n        self._audit_event(\"partition_operation_log\", entry)\n        color = C[\"success\"] if level == \"OK\" else C[\"warning\"] if level in (\"WARN\", \"INFO\") else C[\"error\"]\n        self._append_log(self.partition_log, message, color)\n\n    def _partition_run_powershell_cancelable(self, script, timeout=60):\n        Result = collections.namedtuple(\"Result\", [\"returncode\", \"output\"])\n        proc = subprocess.Popen(\n            [\"powershell\", \"-NoProfile\", \"-NonInteractive\", \"-Command\", script],\n            stdout=subprocess.PIPE,\n            stderr=subprocess.PIPE,\n            text=True,\n            creationflags=subprocess.CREATE_NO_WINDOW,\n        )\n        deadline = time.time() + timeout\n        while proc.poll() is None and time.time() &lt; deadline:\n            if self._partition_operation_is_cancelled():\n                proc.terminate()\n                try:\n                    proc.wait(10)\n                except Exception:\n                    proc.kill()\n                return Result(1, \"Operation cancelled\")\n            time.sleep(0.5)\n        if proc.poll() is None:\n            proc.kill()\n            return Result(1, \"Timeout waiting for PowerShell\")\n        out, err = proc.communicate()\n        return Result(proc.returncode, (out or \"\") + (err or \"\"))\n\n    def _partition_run_cmd_cancelable(self, cmd, timeout=3600):\n        start = time.time()\n        proc = subprocess.Popen(\n            cmd,\n            stdout=subprocess.PIPE,\n            stderr=subprocess.PIPE,\n            text=True,\n            creationflags=subprocess.CREATE_NO_WINDOW,\n        )\n        while proc.poll() is None:\n            if self._partition_operation_is_cancelled():\n                proc.terminate()\n                try:\n                    proc.wait(10)\n                except Exception:\n                    proc.kill()\n                return SafeRunResult(\"Operation cancelled\", 1, args=list(cmd), elapsed_ms=int((time.time() - start) * 1000))\n            if time.time() - start &gt; timeout:\n                proc.kill()\n                return SafeRunResult(\"Timeout waiting for command\", -1, args=list(cmd), elapsed_ms=int((time.time() - start) * 1000), timed_out=True)\n            time.sleep(0.5)\n        out, err = proc.communicate()\n        elapsed = int((time.time() - start) * 1000)\n        return SafeRunResult((out or \"\") + (err or \"\"), proc.returncode, args=list(cmd), elapsed_ms=elapsed)\n\n    def _partition_query_disk_info(self, disk_number):\n        script = f\"$d = Get-Disk -Number {disk_number} -ErrorAction Stop; $dyn = $d | Select-Object -ExpandProperty IsDynamic -ErrorAction SilentlyContinue; [pscustomobject]@{{Number=$d.Number;PartitionStyle=$d.PartitionStyle;IsSystem=$d.IsSystem;IsBoot=$d.IsBoot;IsOffline=$d.IsOffline;IsReadOnly=$d.IsReadOnly;IsDynamic=$dyn}} | ConvertTo-Json -Depth 2\"\n        result = safe_powershell(script, timeout=15)\n        if result.returncode != 0 or not result.output.strip():\n            return {}\n        try:\n            return json.loads(result.output)\n        except Exception:\n            return {}\n\n    def _partition_query_partition_info(self, part):\n        if not part or 'DiskNumber' not in part or 'PartitionNumber' not in part:\n            return {}\n        script = f\"Get-Partition -DiskNumber {part['DiskNumber']} -PartitionNumber {part['PartitionNumber']} | Select-Object DriveLetter,Type,IsBoot,IsOffline,AccessPaths,Size,SizeRemaining,IsHidden | ConvertTo-Json -Depth 2\"\n        result = safe_powershell(script, timeout=15)\n        if result.returncode != 0 or not result.output.strip():\n            return {}\n        try:\n            info = json.loads(result.output)\n            if isinstance(info, dict):\n                return info\n            return info[0] if isinstance(info, list) and info else info\n        except Exception:\n            return {}\n\n    def _partition_query_supported_size(self, disk_number, partition_number):\n        script = f\"Get-PartitionSupportedSize -DiskNumber {disk_number} -PartitionNumber {partition_number} | ConvertTo-Json -Depth 2\"\n        result = safe_powershell(script, timeout=15)\n        if result.returncode != 0 or not result.output.strip():\n            return {}\n        try:\n            return json.loads(result.output)\n        except Exception:\n            return {}\n\n    def _partition_query_volume_info(self, drive_letter):\n        if not drive_letter:\n            return {}\n        script = f\"Get-Volume -DriveLetter {drive_letter} | Select-Object DriveLetter,FileSystem,HealthStatus,Size,SizeRemaining,DriveType | ConvertTo-Json -Depth 2\"\n        result = safe_powershell(script, timeout=15)\n        if result.returncode != 0 or not result.output.strip():\n            return {}\n        try:\n            info = json.loads(result.output)\n            if isinstance(info, dict):\n                return info\n            return info[0] if isinstance(info, list) and info else info\n        except Exception:\n            return {}\n\n    def _partition_detect_bitlocker(self, letter):\n        if not letter:\n            return False, \"\"\n        script = f\"try {{ Get-BitLockerVolume -MountPoint '{letter}:' | Select-Object ProtectionStatus,VolumeStatus | ConvertTo-Json -Depth 2 }} catch {{ Write-Output '' }}\"\n        result = safe_powershell(script, timeout=15)\n        if result.returncode != 0 or not result.output.strip():\n            return False, \"\"\n        try:\n            info = json.loads(result.output)\n            protection = info.get('ProtectionStatus') if isinstance(info, dict) else None\n            status = info.get('VolumeStatus') if isinstance(info, dict) else None\n            enabled = protection not in (0, None) or (status and status.lower() != 'fullydecrypted')\n            return bool(enabled), f\"BitLocker status={status}, protection={protection}\"\n        except Exception:\n            return False, \"\"\n\n    def _partition_folder_size(self, path):\n        total = 0\n        try:\n            for root, _, files in os.walk(path):\n                for f in files:\n                    try:\n                        total += os.path.getsize(os.path.join(root, f))\n                    except Exception:\n                        pass\n        except Exception:\n            pass\n        return total\n\n    def _partition_confirm_action(self, title, message, warnings=None):\n        body = message\n        if warnings:\n            body += \"\\n\\nWarnings:\\n\" + \"\\n\".join([f\"- {w}\" for w in warnings])\n        body += \"\\n\\nBackup recommend kiya jata hai. Continue?\"\n        return messagebox.askyesno(title, body)\n\n    def _partition_preflight_checks(self, action, part=None, dest_part=None, new_size=None):\n        result = {\"ok\": True, \"errors\": [], \"warnings\": [], \"details\": {}}\n        if not is_admin():\n            result[\"ok\"] = False\n            result[\"errors\"].append(\"Administrator privileges required for partition operations.\")\n            return result\n        if action in (\"extend\", \"shrink\", \"split\", \"format\", \"change_letter\", \"merge\", \"clone\"):\n            if part is None:\n                result[\"ok\"] = False\n                result[\"errors\"].append(\"Partition metadata missing.\")\n                return result\n            if part.get(\"DriveLetter\", \"\").upper() == \"C\":\n                result[\"errors\"].append(\"System volume C: pe direct operation unsafe hai.\")\n            if part.get(\"Type\") in {\"System\", \"Reserved\", \"Recovery\", \"EFI\", \"Unknown\"}:\n                result[\"warnings\"].append(\"Selected partition type is special or protected.\")\n            disk_info = self._partition_query_disk_info(part[\"DiskNumber\"])\n            if disk_info.get(\"IsOffline\"):\n                result[\"errors\"].append(\"Target disk is offline.\")\n            if disk_info.get(\"IsReadOnly\"):\n                result[\"errors\"].append(\"Target disk is read-only.\")\n            if disk_info.get(\"IsDynamic\"):\n                result[\"warnings\"].append(\"Dynamic disk detected \u2014 partition operations may not be fully supported.\")\n            if disk_info.get(\"PartitionStyle\") not in (\"MBR\", \"GPT\"):\n                result[\"warnings\"].append(\"Unknown or unsupported partition style.\")\n            if action in (\"extend\", \"shrink\", \"split\") and new_size is not None:\n                supported = self._partition_query_supported_size(part[\"DiskNumber\"], part[\"PartitionNumber\"])\n                if supported:\n                    min_size = supported.get(\"SizeMin\") or 0\n                    max_size = supported.get(\"SizeMax\") or 0\n                    requested = int(new_size * 1024 ** 3)\n                    if action == \"shrink\" and requested &lt; min_size:\n                        result[\"errors\"].append(\"Requested shrink size below supported minimum.\")\n                    if action == \"extend\" and requested &gt; max_size:\n                        result[\"errors\"].append(\"Requested extend size exceeds supported maximum.\")\n                    if action == \"split\" and requested &gt;= (part.get(\"Size\") or 0):\n                        result[\"errors\"].append(\"Split size must be smaller than current partition size.\")\n        if action == \"clone\":\n            src_letter = part.get(\"DriveLetter\")\n            dst_letter = dest_part.get(\"DriveLetter\") if dest_part else None\n            if not src_letter or not dst_letter:\n                result[\"errors\"].append(\"Clone ke liye dono source aur destination drive letters chahiye.\")\n            else:\n                source_bytes = self._partition_folder_size(f\"{src_letter}:\\\\\")\n                try:\n                    usage = shutil.disk_usage(f\"{dst_letter}:\\\\\")\n                    if usage.free &lt; source_bytes:\n                        result[\"errors\"].append(\"Destination volume par kaafi free space nahi hai.\")\n                except Exception:\n                    result[\"warnings\"].append(\"Destination free space check failed; manual verify karo.\")\n                if source_bytes == 0:\n                    result[\"warnings\"].append(\"Source folder size calculation zero ya failed. Progress estimate may be inaccurate.\")\n        if action == \"format\":\n            if part.get(\"DriveLetter\", \"\").upper() == \"C\":\n                result[\"errors\"].append(\"System volume C: ko format nahi kiya ja sakta.\")\n            bitlocker_enabled, bitlocker_info = self._partition_detect_bitlocker(part.get(\"DriveLetter\"))\n            if bitlocker_enabled:\n                result[\"errors\"].append(f\"BitLocker enabled on {part.get('DriveLetter', '')}: \u2014 disable before formatting. {bitlocker_info}\")\n        if action == \"change_letter\":\n            new_letter = dest_part if isinstance(dest_part, str) else None\n            if new_letter and new_letter.upper() == \"C\":\n                result[\"errors\"].append(\"Drive letter C: reserved hai \u2014 choose another letter.\")\n        if action == \"merge\":\n            if dest_part and part and part.get(\"DiskNumber\") != dest_part.get(\"DiskNumber\"):\n                result[\"errors\"].append(\"Merge ke liye same disk par partitions hone chahiye.\")\n            if dest_part and abs(int(part.get(\"PartitionNumber\", 0)) - int(dest_part.get(\"PartitionNumber\", 0))) != 1:\n                result[\"errors\"].append(\"Merge ke liye partitions adjacent hone chahiye.\")\n        if result[\"errors\"]:\n            result[\"ok\"] = False\n        return result\n\n    def _partition_verify_post_operation(self, action, part=None, expected=None):\n        if not part or not part.get(\"DiskNumber\"):\n            return False, \"Post-operation verification failed: partition metadata missing.\"\n        if action in (\"extend\", \"shrink\", \"split\"):\n            info = self._partition_query_partition_info(part)\n            if not info:\n                return False, \"Unable to verify partition after resize/split.\"\n            if expected is not None and isinstance(expected, (int, float)):\n                actual_gb = round((info.get(\"Size\") or 0) / (1024 ** 3), 2)\n                if abs(actual_gb - expected) &gt; 0.5:\n                    return False, f\"Expected size {expected} GB, actual {actual_gb} GB.\"\n        if action == \"change_letter\":\n            info = self._partition_query_partition_info(part)\n            if info and str(info.get(\"DriveLetter\", \"\")).upper() != str(expected).upper():\n                return False, f\"Drive letter change verification failed - expected {expected}:.\"\n        if action == \"format\":\n            vol = self._partition_query_volume_info(part.get(\"DriveLetter\"))\n            if not vol or vol.get(\"FileSystem\") != \"NTFS\":\n                return False, f\"Format verification failed \u2014 expected NTFS on {part.get('DriveLetter','')}:\"\n            if vol.get(\"HealthStatus\", \"\").lower() not in (\"healthy\", \"healthy\"):\n                return False, f\"Volume health warning: {vol.get('HealthStatus')}\"\n        return True, \"Verification passed\"\n\n    def _partition_render_tree(self, data):\n        self.partition_tree.delete(*self.partition_tree.get_children())\n        partitions = data.get(\"Partitions\") or []\n        volumes = data.get(\"Volumes\") or []\n        if isinstance(partitions, dict):\n            partitions = [partitions]\n        if isinstance(volumes, dict):\n            volumes = [volumes]\n\n        for part in partitions:\n            disk = part.get(\"DiskNumber\")\n            pno = part.get(\"PartitionNumber\")\n            letter = part.get(\"DriveLetter\") or \"\"\n            ptype = part.get(\"Type\") or \"\"\n            sizegb = part.get(\"SizeGB\") or round((part.get(\"Size\") or 0) / (1024**3), 2)\n            fs = \"\"\n            health = \"\"\n            if letter:\n                vol = next((v for v in volumes if v.get(\"DriveLetter\") == letter), None)\n                if vol:\n                    fs = vol.get(\"FileSystem\") or \"\"\n                    health = vol.get(\"HealthStatus\") or \"\"\n            self.partition_tree.insert(\"\", \"end\", iid=f\"{disk}-{pno}\", values=(disk, pno, letter, ptype, sizegb, fs, health))\n\n        if data.get(\"Disks\"):\n            disk = data.get(\"Disks\")[0]\n            self._partition_selected_disk = str(disk.get(\"Number\"))\n            parts = [p for p in partitions if str(p.get(\"DiskNumber\")) == str(disk.get(\"Number\"))]\n            self._partition_draw_disk_bar(self.partition_canvas, disk, parts)\n\n    def _partition_redraw_disk_bar(self):\n        if not getattr(self, \"partition_data\", None):\n            return\n        selected_disk = getattr(self, \"_partition_selected_disk\", None)\n        disks = self.partition_data.get(\"Disks\") or []\n        disk = None\n        if selected_disk is not None:\n            disk = next((d for d in disks if str(d.get(\"Number\")) == str(selected_disk)), None)\n        if not disk and disks:\n            disk = disks[0]\n            self._partition_selected_disk = str(disk.get(\"Number\"))\n        if not disk:\n            return\n        parts = [p for p in (self.partition_data.get(\"Partitions\") or []) if str(p.get(\"DiskNumber\")) == str(disk.get(\"Number\"))]\n        self._partition_draw_disk_bar(self.partition_canvas, disk, parts)\n\n    def _partition_on_tree_select(self, event=None):\n        sel = self.partition_tree.selection()\n        if not sel:\n            return\n        values = self.partition_tree.item(sel[0])[\"values\"]\n        if len(values) &lt; 2:\n            return\n        disk, pno = values[0], values[1]\n        self._partition_selected_disk = str(disk)\n        part = self._partition_find_data(disk, pno)\n        if not part:\n            return\n        details = [\n            f\"Disk: {disk}\",\n            f\"Partition: {pno}\",\n            f\"Type: {part.get('Type','Unknown')}\",\n            f\"Letter: {part.get('DriveLetter','')}\",\n            f\"Size: {part.get('SizeGB') or round((part.get('Size') or 0)/(1024**3),2)} GB\",\n        ]\n        self.partition_detail.config(text=\" | \".join(details))\n        disk_data = next((d for d in (self.partition_data.get('Disks') or []) if str(d.get('Number')) == str(disk)), None)\n        if disk_data:\n            parts = [p for p in (self.partition_data.get('Partitions') or []) if str(p.get('DiskNumber')) == str(disk)]\n            self._partition_draw_disk_bar(self.partition_canvas, disk_data, parts)\n\n    def _partition_find_data(self, disk, partition_number):\n        for part in (self.partition_data.get(\"Partitions\") or []):\n            if str(part.get(\"DiskNumber\")) == str(disk) and str(part.get(\"PartitionNumber\")) == str(partition_number):\n                return part\n        return None\n\n    def _partition_fetch_all_disks(self):\n        script = \"\"\"\n        $disks = Get-Disk | Select-Object Number,Size,FriendlyName,PartitionStyle,OperationalStatus,@{N='SizeGB';E={[math]::Round($_.Size/1GB,2)}}\n        $parts = Get-Partition | Select-Object DiskNumber,PartitionNumber,DriveLetter,Size,Type,IsActive,IsHidden,@{N='SizeGB';E={[math]::Round($_.Size/1GB,2)}},@{N='AccessPaths';E={$_.AccessPaths -join ';'}}\n        $vols  = Get-Volume | Select-Object DriveLetter,FileSystem,SizeRemaining,Size,HealthStatus,@{N='FreeGB';E={[math]::Round($_.SizeRemaining/1GB,2)}},@{N='TotalGB';E={[math]::Round($_.Size/1GB,2)}}\n        @{Disks=$disks; Partitions=$parts; Volumes=$vols} | ConvertTo-Json -Depth 4\n        \"\"\"\n        result = safe_powershell(script, timeout=30)\n        if result.returncode != 0 or not result.output.strip():\n            return self._partition_fetch_via_wmic()\n        try:\n            return json.loads(result.output)\n        except json.JSONDecodeError:\n            return self._partition_fetch_via_wmic()\n\n    def _partition_fetch_via_wmic(self):\n        script = \"\"\"\n        Get-WmiObject Win32_DiskPartition |\n        Select-Object DiskIndex,Index,Name,Size,Type,Bootable |\n        ConvertTo-Json\n        \"\"\"\n        result = safe_powershell(script, timeout=20)\n        try:\n            data = json.loads(result.output)\n            if isinstance(data, dict):\n                data = [data]\n            return {\"Disks\": [], \"Partitions\": data, \"Volumes\": []}\n        except Exception:\n            return {\"Disks\": [], \"Partitions\": [], \"Volumes\": []}\n\n    def _partition_draw_disk_bar(self, canvas, disk_data, partitions):\n        canvas.delete(\"all\")\n        W = canvas.winfo_width() or 900\n        H = max(self._dpi_px(60), canvas.winfo_height() or self._dpi_px(60))\n        colors = {\n            \"System\": \"#FF6B6B\",\n            \"Primary\": \"#4DABF7\",\n            \"Recovery\": \"#FFD43B\",\n            \"Unknown\": \"#868E96\",\n            \"Unallocated\": \"#2D3436\",\n        }\n        total_bytes = sum(p.get(\"Size\", 0) for p in partitions)\n        if total_bytes == 0:\n            return\n        x = 0\n        for p in partitions:\n            w = int((p.get(\"Size\", 0) / total_bytes) * W)\n            if w &lt; 2:\n                w = 2\n            ptype = p.get(\"Type\", \"Primary\")\n            color = colors.get(ptype, \"#4DABF7\")\n            letter = p.get(\"DriveLetter\") or \"?\"\n            size_gb = round((p.get(\"Size\") or 0) / (1024**3), 1)\n            canvas.create_rectangle(x, 5, x + w - 2, H - 5,\n                                    fill=color, outline=\"#1A1A2A\", width=1)\n            if w &gt; 40:\n                canvas.create_text(x + w//2, H//2,\n                                   text=f\"{letter}:\\n{size_gb}GB\",\n                                   font=(\"Segoe UI\", 8, \"bold\"),\n                                   fill=\"white\", anchor=\"center\")\n            x += w\n        disk_total = disk_data.get(\"Size\", 0)\n        unalloc = disk_total - total_bytes\n        if unalloc &gt; 100 * 1024 * 1024:\n            w = int((unalloc / disk_total) * W)\n            canvas.create_rectangle(x, 5, x + w - 2, H - 5,\n                                    fill=\"#2D3436\", outline=\"#555\", width=1,\n                                    dash=(4, 2))\n            if w &gt; 60:\n                canvas.create_text(x + w//2, H//2,\n                                   text=f\"Free\\n{round(unalloc/(1024**3),1)}GB\",\n                                   font=(\"Segoe UI\", 8), fill=\"#AAA\", anchor=\"center\")\n\n    def _partition_merge_prompt(self):\n        sel = self.partition_tree.selection()\n        if len(sel) != 2:\n            messagebox.showinfo(\"Select Two Partitions\", \"Pehle 2 adjacent partitions select karo \u2014 source aur destination.\")\n            return\n        src_data = self._partition_find_data(*self.partition_tree.item(sel[0])[\"values\"][:2])\n        dst_data = self._partition_find_data(*self.partition_tree.item(sel[1])[\"values\"][:2])\n        if not src_data or not dst_data:\n            return\n        if src_data.get(\"SizeGB\", 0) &gt; dst_data.get(\"SizeGB\", 0):\n            source, dest = dst_data, src_data\n        else:\n            source, dest = src_data, dst_data\n        if not messagebox.askyesno(\"Merge Partitions\",\n                                  f\"Source: {source.get('DriveLetter','')} ({source.get('SizeGB')} GB)\\n\"\n                                  f\"Destination: {dest.get('DriveLetter','')} ({dest.get('SizeGB')} GB)\\n\\n\"\n                                  \"Data source ko destination par copy karke merge kiya jayega. Continue?\" ):\n            return\n        self._launch_job(\"partition_merge\", self._partition_merge_worker, source, dest)\n\n    def _partition_merge_worker(self, source, dest):\n        started, session_id = self._partition_start_operation(\"Merge Partitions\")\n        if not started:\n            self._append_log(self.partition_log, \"\u26a0 Another partition operation is already running.\", C[\"warning\"])\n            return\n        success = False\n        message = \"Partition merge failed\"\n        try:\n            self._partition_update_progress(0, \"Partition merge started...\")\n            success, message = self._partition_merge(source, dest)\n            color = C[\"success\"] if success else C[\"error\"]\n            self.after(0, lambda: self._append_log(self.partition_log, message, color))\n            if success:\n                self._partition_update_progress(100, \"Partition merge completed.\")\n                self.after(0, self._partition_refresh_tree)\n            else:\n                self._partition_update_progress(0, \"Partition merge failed.\")\n        except Exception as e:\n            message = f\"Partition merge failed: {e}\"\n            self._partition_log_diagnostic(\"ERROR\", message)\n            self._partition_update_progress(0, message)\n        finally:\n            self._partition_end_operation(session_id, success, message, C[\"success\"] if success else C[\"error\"])\n\n    def _partition_merge(self, source_part, dest_part):\n        journal = []\n        def update_merge_progress(percent, text=None):\n            self._partition_update_progress(percent, text or \"Merging...\")\n            if text is not None and hasattr(self, \"partition_merge_status_label\"):\n                self.after(0, lambda: self.partition_merge_status_label.config(text=text))\n            if hasattr(self, \"partition_merge_progress_var\"):\n                self.after(0, lambda: self.partition_merge_progress_var.set(max(0.0, min(100.0, float(percent)))))\n\n        def jlog(msg, level=\"INFO\", pct=None):\n            journal.append({\"ts\": datetime.datetime.now().isoformat(), \"level\": level, \"msg\": msg})\n            self._append_log(self.partition_log, msg, C[\"success\"] if level == \"OK\" else C[\"warning\"] if level == \"WARN\" else C[\"error\"])\n            if pct is not None:\n                update_merge_progress(pct, msg)\n\n        if not is_admin():\n            jlog(\"Admin rights nahi hain. Run as Administrator karo.\", \"ERROR\")\n            return False, \"Admin required\"\n\n        if source_part.get(\"DiskNumber\") != dest_part.get(\"DiskNumber\"):\n            jlog(\"Partitions alag disk par hain \u2014 merge supported nahi. Use same disk.\", \"ERROR\")\n            return False, \"Different disks\"\n\n        if abs(int(source_part.get(\"PartitionNumber\", 0)) - int(dest_part.get(\"PartitionNumber\", 0))) != 1:\n            jlog(\"Partitions adjacent nahi hain. Merge ke liye adjacent partitions chahiye.\", \"ERROR\")\n            return False, \"Partitions not adjacent\"\n\n        protected_types = {\"System\", \"Reserved\", \"Recovery\", \"EFI\", \"Unknown\"}\n        if source_part.get(\"Type\") in protected_types or dest_part.get(\"Type\") in protected_types:\n            jlog(\"System/Recovery partition pe merge block hai.\", \"ERROR\")\n            return False, \"Protected partition\"\n\n        jlog(\"SMART check chal raha hai...\", \"INFO\")\n        smart_script = \"\"\"\n        Get-WmiObject -Namespace root/wmi -Class MSStorageDriver_FailurePredictStatus |\n            Select-Object PredictFailure,Reason | ConvertTo-Json\n        \"\"\"\n        smart_result = safe_powershell(smart_script, timeout=15)\n        try:\n            smart_data = json.loads(smart_result.output)\n            if isinstance(smart_data, dict):\n                smart_data = [smart_data]\n            for s in smart_data:\n                if s.get(\"PredictFailure\"):\n                    jlog(\"SMART: Disk failure predicted! Merge BLOCKED. Pehle data backup karo.\", \"ERROR\")\n                    return False, \"SMART failure predicted\"\n        except Exception:\n            jlog(\"SMART check available nahi \u2014 proceeding with caution.\", \"WARN\")\n\n        src_letter = source_part.get(\"DriveLetter\") or self._partition_assign_temp_letter(source_part)\n        dst_letter = dest_part.get(\"DriveLetter\") or self._partition_assign_temp_letter(dest_part)\n        backup_dir = os.path.join(os.environ.get(\"APPDATA\", \"\"), \"GodawariOptimizer\", \"partition_backups\")\n        os.makedirs(backup_dir, exist_ok=True)\n        if src_letter and dst_letter:\n            self._record_rollback_point(\n                \"partition_merge\",\n                details={\n                    \"source_letter\": src_letter,\n                    \"dest_letter\": dst_letter,\n                    \"src_disk\": source_part.get(\"DiskNumber\"),\n                    \"src_partition\": source_part.get(\"PartitionNumber\"),\n                    \"dest_disk\": dest_part.get(\"DiskNumber\"),\n                    \"dest_partition\": dest_part.get(\"PartitionNumber\"),\n                    \"backup_dir\": backup_dir,\n                },\n                snapshot_path=backup_dir)\n        if not src_letter or not dst_letter:\n            jlog(\"Drive letter missing \u2014 merge ke liye drive letters chahiye.\", \"ERROR\")\n            return False, \"Drive letter required\"\n\n        jlog(f\"Data copy shuru kar raha hoon: {src_letter}: \u2192 {dst_letter}: ...\", \"INFO\")\n        ts = datetime.datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n        copy_log = os.path.join(backup_dir, f\"robocopy_{ts}.log\")\n        robocopy_cmd = [\n            \"robocopy\",\n            f\"{src_letter}:\\\\\",\n            f\"{dst_letter}:\\\\GodawariMerge_{ts}\",\n            \"/MIR\", \"/COPYALL\", \"/R:3\", \"/W:5\",\n            \"/NFL\", f\"/LOG:{copy_log}\", \"/TEE\"\n        ]\n        copy_result = safe_run(robocopy_cmd, timeout=7200)\n        if copy_result.returncode &gt;= 8:\n            jlog(f\"Data copy FAILED (rc={copy_result.returncode}). Merge aborted.\", \"ERROR\", pct=20)\n            return False, f\"Robocopy failed: rc={copy_result.returncode}\"\n\n        src_count = self._partition_count_files(f\"{src_letter}:\\\\\")\n        dst_count = self._partition_count_files(f\"{dst_letter}:\\\\GodawariMerge_{ts}\")\n        if src_count &gt; 0 and dst_count &lt; int(src_count * 0.95):\n            jlog(f\"Verification FAILED: src={src_count} files, dst={dst_count} files\", \"ERROR\", pct=40)\n            return False, \"File count mismatch after copy\"\n        jlog(f\"Verification OK: {src_count} \u2192 {dst_count} files\", \"OK\", pct=45)\n\n        diskpart_script = f\"\"\"select disk {source_part['DiskNumber']}\\nselect partition {source_part['PartitionNumber']}\\ndelete partition override\\n\"\"\"\n        diskpart_file = os.path.join(backup_dir, f\"diskpart_delete_{ts}.txt\")\n        with open(diskpart_file, \"w\", encoding=\"utf-8\") as f:\n            f.write(diskpart_script)\n        delete_result = safe_run([\"diskpart\", \"/s\", diskpart_file], timeout=60)\n        if delete_result.returncode != 0:\n            jlog(f\"Partition delete failed: {delete_result.output[:200]}\", \"ERROR\", pct=55)\n            return False, \"Delete failed\"\n        jlog(\"Source partition deleted.\", \"OK\", pct=60)\n\n        extend_script = f\"\"\"select disk {dest_part['DiskNumber']}\\nselect partition {dest_part['PartitionNumber']}\\nextend\\n\"\"\"\n        extend_file = os.path.join(backup_dir, f\"diskpart_extend_{ts}.txt\")\n        with open(extend_file, \"w\", encoding=\"utf-8\") as f:\n            f.write(extend_script)\n        extend_result = safe_run([\"diskpart\", \"/s\", extend_file], timeout=60)\n        if extend_result.returncode != 0:\n            ps_extend = f\"\"\"\n            $maxSize = (Get-PartitionSupportedSize -DiskNumber {dest_part['DiskNumber']} -PartitionNumber {dest_part['PartitionNumber']}).SizeMax\n            Resize-Partition -DiskNumber {dest_part['DiskNumber']} -PartitionNumber {dest_part['PartitionNumber']} -Size $maxSize\n            \"\"\"\n            ps_result = safe_powershell(ps_extend, timeout=60)\n            if ps_result.returncode != 0:\n                jlog(\"Extend FAILED \u2014 manual extend required via Disk Management\", \"ERROR\", pct=70)\n                return False, \"Extend failed\"\n        jlog(\"Partition extended!\", \"OK\", pct=75)\n\n        verify_script = f\"\"\"\n        Get-Partition -DiskNumber {dest_part['DiskNumber']} -PartitionNumber {dest_part['PartitionNumber']} |\n            Select-Object @{{N='SizeGB';E={{[math]::Round($_.Size/1GB,2)}}}} |\n            ConvertTo-Json\n        \"\"\"\n        verify_result = safe_powershell(verify_script, timeout=15)\n        try:\n            new_size = json.loads(verify_result.output).get(\"SizeGB\", 0)\n            expected = round((source_part.get(\"SizeGB\", 0) + dest_part.get(\"SizeGB\", 0)) * 0.98, 1)\n            if new_size &gt;= expected:\n                jlog(f\"VERIFY OK: New size = {new_size} GB\", \"OK\", pct=90)\n            else:\n                jlog(f\"Size verify: {new_size} GB (expected ~{expected} GB) \u2014 check manually\", \"WARN\", pct=85)\n        except Exception:\n            jlog(\"Size verify parse failed \u2014 visually confirm\", \"WARN\", pct=85)\n\n        journal_file = os.path.join(backup_dir, f\"partition_merge_journal_{ts}.json\")\n        with open(journal_file, \"w\", encoding=\"utf-8\") as f:\n            json.dump(journal, f, indent=2, ensure_ascii=False)\n        jlog(f\"Merge complete! Journal saved: {journal_file}\", \"OK\")\n        return True, \"Merge successful\"\n\n    def _partition_count_files(self, path):\n        count = 0\n        try:\n            for root, _, files in os.walk(path):\n                count += len(files)\n        except Exception:\n            pass\n        return count\n\n    def _partition_assign_temp_letter(self, part):\n        if part.get(\"DriveLetter\"):\n            return part[\"DriveLetter\"]\n        existing = [v for v in \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"]\n        script = 'Get-Volume | Select-Object -ExpandProperty DriveLetter | ConvertTo-Json'\n        result = safe_powershell(script, timeout=15)\n        used = set()\n        try:\n            letters = json.loads(result.output)\n            if isinstance(letters, list):\n                used.update([str(x) for x in letters if x])\n            elif isinstance(letters, str):\n                used.add(letters)\n        except Exception:\n            pass\n        for letter in \"RSTUVWXYZ\":\n            if letter in used:\n                continue\n            assign_script = f\"$p = Get-Partition -DiskNumber {part['DiskNumber']} -PartitionNumber {part['PartitionNumber']}; Add-PartitionAccessPath -InputObject $p -AssignDriveLetter -DriveLetter {letter} -ErrorAction SilentlyContinue\"\n            assign_res = safe_powershell(assign_script, timeout=20)\n            if assign_res.returncode == 0:\n                return letter\n        return None\n\n    def _partition_extend_prompt(self):\n        sel = self.partition_tree.selection()\n        if len(sel) != 1:\n            messagebox.showinfo(\"Select Partition\", \"Pehle ek partition select karo.\")\n            return\n        values = self.partition_tree.item(sel[0])[\"values\"]\n        part = self._partition_find_data(*values[:2])\n        if not part:\n            return\n        import tkinter.simpledialog as simpledialog\n        current = part.get(\"SizeGB\") or round((part.get(\"Size\") or 0)/(1024**3),2)\n        new_size = simpledialog.askfloat(\"Extend Partition\", f\"Naya size (GB) enter karo (current {current}):\", initialvalue=current + 10, minvalue=current + 1)\n        if not new_size:\n            return\n        if not messagebox.askyesno(\"Extend Partition\", f\"Partition {part.get('DriveLetter','')} ko {new_size} GB tak extend karna hai?\\nContinue?\"):\n            return\n        preflight = self._partition_preflight_checks(\"extend\", part, new_size=new_size)\n        if not preflight[\"ok\"]:\n            messagebox.showerror(\"Preflight Failed\", \"\\n\".join(preflight[\"errors\"]))\n            return\n        if preflight[\"warnings\"] and not self._partition_confirm_action(\"Extend Partition\", f\"Extending partition {part.get('DriveLetter','')} to {new_size} GB.\", preflight[\"warnings\"]):\n            return\n        dry_run = messagebox.askyesno(\"Dry-Run Recommended\", \"Dry-run preview recommended for partition extend. Yes = preview only, No = run actual operation now.\")\n        self._launch_job(\"partition_extend\", self._partition_extend_worker, part, new_size, dry_run)\n\n    def _partition_extend_worker(self, part, new_size, dry_run=False):\n        started, session_id = self._partition_start_operation(\"Extend Partition\")\n        if not started:\n            self._append_log(self.partition_log, \"\u26a0 Another partition operation is already running.\", C[\"warning\"])\n            return\n        self._partition_log_diagnostic(\"INFO\", f\"Starting partition extend: {part.get('DriveLetter','')} to {new_size} GB\", {\"dry_run\": dry_run})\n        command = f\"Resize-Partition -DiskNumber {part['DiskNumber']} -PartitionNumber {part['PartitionNumber']} -Size ({new_size}GB)\"\n        if dry_run:\n            command += \" -WhatIf\"\n        self._partition_update_progress(15, \"Preparing extend command...\")\n        self._partition_log_diagnostic(\"INFO\", \"Executing Resize-Partition (or dry-run).\")\n        self._partition_update_progress(35, \"Executing PowerShell command...\")\n        result = self._partition_run_powershell_cancelable(command, timeout=90)\n        if self._partition_operation_is_cancelled():\n            self._partition_log_diagnostic(\"WARN\", \"Extend operation cancelled.\")\n            self._partition_end_operation(session_id, False, \"Extend cancelled\", C[\"warning\"])\n            return\n        self._partition_update_progress(70, \"Verifying result...\")\n        if result.returncode == 0:\n            if dry_run:\n                self._partition_log_diagnostic(\"OK\", \"Dry-run complete: extend command validated.\")\n                self._partition_end_operation(session_id, True, \"Dry-run complete\", C[\"success\"])\n                return\n            verify_ok, verify_msg = self._partition_verify_post_operation(\"extend\", part, expected=new_size)\n            if verify_ok:\n                self._partition_log_diagnostic(\"OK\", f\"Extended to {new_size} GB successfully.\")\n                self.after(0, self._partition_refresh_tree)\n                self._partition_end_operation(session_id, True, f\"\u2705 Extended to {new_size} GB successfully!\", C[\"success\"])\n            else:\n                self._partition_log_diagnostic(\"ERROR\", verify_msg)\n                self._partition_end_operation(session_id, False, f\"\u274c Extend verify failed: {verify_msg}\", C[\"error\"])\n        else:\n            self._partition_log_diagnostic(\"ERROR\", f\"Extend failed: {result.output[:200]}\")\n            self._partition_end_operation(session_id, False, \"\u274c Extend failed\", C[\"error\"])\n\n    def _partition_shrink_prompt(self):\n        sel = self.partition_tree.selection()\n        if len(sel) != 1:\n            messagebox.showinfo(\"Select Partition\", \"Pehle ek partition select karo.\")\n            return\n        values = self.partition_tree.item(sel[0])[\"values\"]\n        part = self._partition_find_data(*values[:2])\n        if not part:\n            return\n        import tkinter.simpledialog as simpledialog\n        current = part.get(\"SizeGB\") or round((part.get(\"Size\") or 0)/(1024**3),2)\n        new_size = simpledialog.askfloat(\"Shrink Partition\", f\"Naya size (GB) enter karo (current {current}):\", initialvalue=max(current - 10, 1), minvalue=1, maxvalue=current - 1)\n        if not new_size:\n            return\n        if not messagebox.askyesno(\"Shrink Partition\", f\"Partition {part.get('DriveLetter','')} ko {new_size} GB tak shrink karna hai?\\nContinue?\"):\n            return\n        preflight = self._partition_preflight_checks(\"shrink\", part, new_size=new_size)\n        if not preflight[\"ok\"]:\n            messagebox.showerror(\"Preflight Failed\", \"\\n\".join(preflight[\"errors\"]))\n            return\n        if preflight[\"warnings\"] and not self._partition_confirm_action(\"Shrink Partition\", f\"Shrinking partition {part.get('DriveLetter','')} to {new_size} GB.\", preflight[\"warnings\"]):\n            return\n        dry_run = messagebox.askyesno(\"Dry-Run Recommended\", \"Dry-run preview recommended for partition shrink. Yes = preview only, No = run actual operation now.\")\n        self._launch_job(\"partition_shrink\", self._partition_shrink_worker, part, new_size, dry_run)\n\n    def _partition_shrink_worker(self, part, new_size, dry_run=False):\n        started, session_id = self._partition_start_operation(\"Shrink Partition\")\n        if not started:\n            self._append_log(self.partition_log, \"\u26a0 Another partition operation is already running.\", C[\"warning\"])\n            return\n        self._partition_log_diagnostic(\"INFO\", f\"Starting partition shrink: {part.get('DriveLetter','')} to {new_size} GB\", {\"dry_run\": dry_run})\n        command = f\"Resize-Partition -DiskNumber {part['DiskNumber']} -PartitionNumber {part['PartitionNumber']} -Size ({new_size}GB)\"\n        if dry_run:\n            command += \" -WhatIf\"\n        self._partition_update_progress(15, \"Preparing shrink command...\")\n        self._partition_update_progress(35, \"Executing PowerShell command...\")\n        result = self._partition_run_powershell_cancelable(command, timeout=90)\n        if self._partition_operation_is_cancelled():\n            self._partition_log_diagnostic(\"WARN\", \"Shrink operation cancelled.\")\n            self._partition_end_operation(session_id, False, \"Shrink cancelled\", C[\"warning\"])\n            return\n        self._partition_update_progress(70, \"Verifying shrink result...\")\n        if result.returncode == 0:\n            if dry_run:\n                self._partition_log_diagnostic(\"OK\", \"Dry-run complete: shrink command validated.\")\n                self._partition_end_operation(session_id, True, \"Dry-run complete\", C[\"success\"])\n                return\n            verify_ok, verify_msg = self._partition_verify_post_operation(\"shrink\", part, expected=new_size)\n            if verify_ok:\n                self._partition_log_diagnostic(\"OK\", f\"Shrunk to {new_size} GB successfully.\")\n                self.after(0, self._partition_refresh_tree)\n                self._partition_end_operation(session_id, True, f\"\u2705 Shrunk to {new_size} GB successfully!\", C[\"success\"])\n            else:\n                self._partition_log_diagnostic(\"ERROR\", verify_msg)\n                self._partition_end_operation(session_id, False, f\"\u274c Shrink verify failed: {verify_msg}\", C[\"error\"])\n        else:\n            self._partition_log_diagnostic(\"ERROR\", f\"Shrink failed: {result.output[:200]}\")\n            self._partition_end_operation(session_id, False, \"\u274c Shrink failed\", C[\"error\"])\n\n    def _partition_format_prompt(self):\n        sel = self.partition_tree.selection()\n        if len(sel) != 1:\n            messagebox.showinfo(\"Select Partition\", \"Pehle ek partition select karo.\")\n            return\n        values = self.partition_tree.item(sel[0])[\"values\"]\n        part = self._partition_find_data(*values[:2])\n        if not part:\n            messagebox.showinfo(\"Format Partition\", \"Partition metadata nahi mila.\")\n            return\n        if not messagebox.askyesno(\n            \"Format Partition\",\n            f\"Partition {part.get('DriveLetter','(no letter)')} ko NTFS se format karne se saari files permanently delete ho jayengi.\\n\\n\"\n            \"Yeh operation irreversible hai.\\n\\nContinue?\"\n        ):\n            return\n        preflight = self._partition_preflight_checks(\"format\", part)\n        if not preflight[\"ok\"]:\n            messagebox.showerror(\"Preflight Failed\", \"\\n\".join(preflight[\"errors\"]))\n            return\n        if preflight[\"warnings\"] and not self._partition_confirm_action(\n            \"Format Partition\",\n            f\"Formatting partition {part.get('DriveLetter','')} to NTFS.\",\n            preflight[\"warnings\"]\n        ):\n            return\n        dry_run = messagebox.askyesno(\n            \"Dry-Run Recommended\",\n            \"Dry-run preview recommended for format. Yes = preview only, No = run actual operation now.\"\n        )\n        self._launch_job(\"partition_format\", self._partition_format_worker, part, dry_run)\n\n    def _partition_format_worker(self, part, dry_run=False):\n        started, session_id = self._partition_start_operation(\"Format Partition\")\n        if not started:\n            self._append_log(self.partition_log, \"\u26a0 Another partition operation is already running.\", C[\"warning\"])\n            return\n        self._partition_log_diagnostic(\"INFO\", f\"Starting format on partition {part.get('DriveLetter','')} ({part.get('DiskNumber')}/{part.get('PartitionNumber')})\", {\"dry_run\": dry_run})\n        label = f\"Godawari_{datetime.datetime.now().strftime('%Y%m%d')}\"\n        self._partition_update_progress(10, \"Preparing format command...\")\n        if part.get(\"DriveLetter\"):\n            command = f\"Format-Volume -DriveLetter {part['DriveLetter']} -FileSystem NTFS -NewFileSystemLabel '{label}' -Confirm:$false\"\n        else:\n            command = f\"$part = Get-Partition -DiskNumber {part['DiskNumber']} -PartitionNumber {part['PartitionNumber']}; Format-Volume -Partition $part -FileSystem NTFS -NewFileSystemLabel '{label}' -Confirm:$false\"\n        if dry_run:\n            command += \" -WhatIf\"\n        self._partition_update_progress(35, \"Executing format command...\")\n        result = self._partition_run_powershell_cancelable(command, timeout=120)\n        if self._partition_operation_is_cancelled():\n            self._partition_log_diagnostic(\"WARN\", \"Format operation cancelled.\")\n            self._partition_end_operation(session_id, False, \"Format cancelled\", C[\"warning\"])\n            return\n        if result.returncode == 0:\n            if dry_run:\n                self._partition_log_diagnostic(\"OK\", \"Dry-run complete: format command validated.\")\n                self._partition_end_operation(session_id, True, \"Dry-run complete\", C[\"success\"])\n                return\n            self._partition_update_progress(65, \"Verifying format result...\")\n            verify_ok, verify_msg = self._partition_verify_post_operation(\"format\", part)\n            if verify_ok:\n                self._partition_log_diagnostic(\"OK\", f\"Partition formatted to NTFS successfully.\")\n                self.after(0, self._partition_refresh_tree)\n                self._partition_end_operation(session_id, True, \"\u2705 Partition formatted successfully\", C[\"success\"])\n            else:\n                self._partition_log_diagnostic(\"ERROR\", verify_msg)\n                self._partition_end_operation(session_id, False, f\"\u274c Format verify failed: {verify_msg}\", C[\"error\"])\n        else:\n            self._partition_log_diagnostic(\"ERROR\", f\"Format failed: {result.output[:200]}\")\n            self._partition_end_operation(session_id, False, \"\u274c Format failed\", C[\"error\"])\n\n    def _partition_change_letter_prompt(self):\n        sel = self.partition_tree.selection()\n        if len(sel) != 1:\n            messagebox.showinfo(\"Select Partition\", \"Pehle ek partition select karo.\")\n            return\n        values = self.partition_tree.item(sel[0])[\"values\"]\n        part = self._partition_find_data(*values[:2])\n        if not part:\n            return\n        import tkinter.simpledialog as simpledialog\n        new_letter = simpledialog.askstring(\"Change Drive Letter\", \"Naya drive letter enter karo:\", initialvalue=part.get(\"DriveLetter\") or \"G\")\n        if not new_letter:\n            return\n        letter = new_letter.strip().upper()[:1]\n        if not letter.isalpha():\n            messagebox.showerror(\"Invalid Letter\", \"Sirf A-Z drive letter use karo.\")\n            return\n        if not messagebox.askyesno(\"Change Drive Letter\", f\"{part.get('DriveLetter','')} ko {letter}: pe change karna hai?\\nContinue?\"):\n            return\n        preflight = self._partition_preflight_checks(\"change_letter\", part, dest_part=letter)\n        if not preflight[\"ok\"]:\n            messagebox.showerror(\"Preflight Failed\", \"\\n\".join(preflight[\"errors\"]))\n            return\n        if preflight[\"warnings\"] and not self._partition_confirm_action(\"Change Drive Letter\", f\"Changing drive letter for {part.get('DriveLetter','')} to {letter}:\", preflight[\"warnings\"]):\n            return\n        dry_run = messagebox.askyesno(\"Dry-Run Recommended\", \"Dry-run preview recommended for drive letter change. Yes = preview only, No = run actual operation now.\")\n        self._launch_job(\"partition_change_letter\", self._partition_change_letter_worker, part, letter, dry_run)\n\n    def _partition_change_letter_worker(self, part, letter, dry_run=False):\n        started, session_id = self._partition_start_operation(\"Change Drive Letter\")\n        if not started:\n            self._append_log(self.partition_log, \"\u26a0 Another partition operation is already running.\", C[\"warning\"])\n            return\n        self._partition_log_diagnostic(\"INFO\", f\"Starting drive letter change: {part.get('DriveLetter','')} \u2192 {letter}\", {\"dry_run\": dry_run})\n        command = f\"Set-Partition -DiskNumber {part['DiskNumber']} -PartitionNumber {part['PartitionNumber']} -NewDriveLetter {letter}\"\n        if dry_run:\n            command += \" -WhatIf\"\n        self._partition_update_progress(15, \"Preparing change letter command...\")\n        self._partition_update_progress(50, \"Executing PowerShell Set-Partition...\")\n        result = self._partition_run_powershell_cancelable(command, timeout=45)\n        if self._partition_operation_is_cancelled():\n            self._partition_log_diagnostic(\"WARN\", \"Drive letter change cancelled.\")\n            self._partition_end_operation(session_id, False, \"Change letter cancelled\", C[\"warning\"])\n            return\n        if result.returncode == 0:\n            if dry_run:\n                self._partition_log_diagnostic(\"OK\", \"Dry-run complete: drive letter change command validated.\")\n                self._partition_end_operation(session_id, True, \"Dry-run complete\", C[\"success\"])\n                return\n            verify_ok, verify_msg = self._partition_verify_post_operation(\"change_letter\", part, expected=letter)\n            if verify_ok:\n                self._partition_log_diagnostic(\"OK\", f\"Drive letter changed to {letter} successfully.\")\n                self.after(0, self._partition_refresh_tree)\n                self._partition_end_operation(session_id, True, f\"\u2705 Drive letter changed to {letter}:\", C[\"success\"])\n            else:\n                self._partition_log_diagnostic(\"ERROR\", verify_msg)\n                self._partition_end_operation(session_id, False, f\"\u274c Change letter verify failed: {verify_msg}\", C[\"error\"])\n        else:\n            self._partition_log_diagnostic(\"ERROR\", f\"Change letter failed: {result.output[:200]}\")\n            self._partition_end_operation(session_id, False, \"\u274c Change letter failed\", C[\"error\"])\n\n    def _partition_split_prompt(self):\n        sel = self.partition_tree.selection()\n        if len(sel) != 1:\n            messagebox.showinfo(\"Select Partition\", \"Pehle ek partition select karo.\")\n            return\n        values = self.partition_tree.item(sel[0])[\"values\"]\n        part = self._partition_find_data(*values[:2])\n        if not part:\n            return\n        import tkinter.simpledialog as simpledialog\n        current = part.get(\"SizeGB\") or round((part.get(\"Size\") or 0)/(1024**3),2)\n        new_size = simpledialog.askfloat(\"Split Partition\", f\"Nayi sub-partition ka size (GB) enter karo, current {current}:\", initialvalue=max(current / 2, 1), minvalue=1, maxvalue=current - 1)\n        if not new_size:\n            return\n        if not messagebox.askyesno(\"Split Partition\", f\"Partition {current} GB se {new_size} GB ka new partition banega. Continue?\"):\n            return\n        preflight = self._partition_preflight_checks(\"split\", part, new_size=new_size)\n        if not preflight[\"ok\"]:\n            messagebox.showerror(\"Preflight Failed\", \"\\n\".join(preflight[\"errors\"]))\n            return\n        if preflight[\"warnings\"] and not self._partition_confirm_action(\"Split Partition\", f\"Split partition {part.get('DriveLetter','')} into new {new_size} GB volume.\", preflight[\"warnings\"]):\n            return\n        dry_run = messagebox.askyesno(\"Dry-Run Recommended\", \"Dry-run preview recommended for partition split. Yes = preview only, No = run actual operation now.\")\n        self._launch_job(\"partition_split\", self._partition_split_worker, part, new_size, dry_run)\n\n    def _partition_split_worker(self, part, new_size, dry_run=False):\n        started, session_id = self._partition_start_operation(\"Split Partition\")\n        if not started:\n            self._append_log(self.partition_log, \"\u26a0 Another partition operation is already running.\", C[\"warning\"])\n            return\n        if not is_admin():\n            self._partition_log_diagnostic(\"ERROR\", \"Admin rights required for split.\")\n            self._partition_end_operation(session_id, False, \"Admin required\", C[\"error\"])\n            return\n        self._partition_log_diagnostic(\"INFO\", f\"Starting partition split: {part.get('DriveLetter','')} -&gt; {new_size} GB\", {\"dry_run\": dry_run})\n        self._partition_update_progress(25, \"Preparing split plan...\")\n        command = f\"$diskNum = {part['DiskNumber']}; $partNum = {part['PartitionNumber']}; $newSize = {new_size}GB; $currentPart = Get-Partition -DiskNumber $diskNum -PartitionNumber $partNum; $targetSize = $currentPart.Size - $newSize - 1MB; Resize-Partition -DiskNumber $diskNum -PartitionNumber $partNum -Size $targetSize\"\n        if not dry_run:\n            command += \"; $newPart = New-Partition -DiskNumber $diskNum -Size $newSize -AssignDriveLetter; Format-Volume -DriveLetter $newPart.DriveLetter -FileSystem NTFS -NewFileSystemLabel 'GodawariSplit' -Confirm:$false\"\n        else:\n            command += \" -WhatIf\"\n        self._partition_update_progress(40, \"Executing split command...\")\n        result = self._partition_run_powershell_cancelable(command, timeout=240)\n        if self._partition_operation_is_cancelled():\n            self._partition_log_diagnostic(\"WARN\", \"Split operation cancelled.\")\n            self._partition_end_operation(session_id, False, \"Split cancelled\", C[\"warning\"])\n            return\n        if result.returncode == 0:\n            if dry_run:\n                self._partition_log_diagnostic(\"OK\", \"Dry-run complete: split command validated.\")\n                self._partition_end_operation(session_id, True, \"Dry-run complete\", C[\"success\"])\n                return\n            self._partition_update_progress(85, \"Verifying split result...\")\n            verify_ok, verify_msg = self._partition_verify_post_operation(\"split\", part, expected=new_size)\n            if verify_ok:\n                self._partition_log_diagnostic(\"OK\", f\"Split created with {new_size} GB successfully.\")\n                self.after(0, self._partition_refresh_tree)\n                self._partition_end_operation(session_id, True, f\"\u2705 Split created with {new_size} GB.\", C[\"success\"])\n            else:\n                self._partition_log_diagnostic(\"ERROR\", verify_msg)\n                self._partition_end_operation(session_id, False, f\"\u274c Split verify failed: {verify_msg}\", C[\"error\"])\n        else:\n            self._partition_log_diagnostic(\"ERROR\", f\"Split failed: {result.output[:200]}\")\n            self._partition_end_operation(session_id, False, \"\u274c Split failed\", C[\"error\"])\n\n    def _partition_clone_prompt(self):\n        sel = self.partition_tree.selection()\n        if len(sel) != 1:\n            messagebox.showinfo(\"Select Partition\", \"Pehle ek source partition select karo.\")\n            return\n        src = self._partition_find_data(*self.partition_tree.item(sel[0])[\"values\"][:2])\n        if not src or not src.get(\"DriveLetter\"):\n            messagebox.showinfo(\"Clone Partition\", \"Source partition ko drive letter chahiye.\")\n            return\n        candidates = [p for p in (self.partition_data.get(\"Partitions\") or []) if p.get(\"DriveLetter\") and p.get(\"DriveLetter\") != src.get(\"DriveLetter\")]\n        if not candidates:\n            messagebox.showinfo(\"Clone Partition\", \"Kam se kam ek destination partition drive letter ke saath chahiye.\")\n            return\n        options = [f\"{p.get('DriveLetter')}: {p.get('SizeGB')}GB {p.get('Type')}\" for p in candidates]\n        import tkinter.simpledialog as simpledialog\n        choice = simpledialog.askstring(\"Clone Target\", \"Destination partition choose karo:\\n\" + \"\\n\".join(options), initialvalue=options[0])\n        if not choice:\n            return\n        selected = None\n        for p, label in zip(candidates, options):\n            if choice.strip() == label:\n                selected = p\n                break\n        if not selected:\n            messagebox.showerror(\"Invalid Selection\", \"Valid destination select karo.\")\n            return\n        if not messagebox.askyesno(\"Clone Partition\", f\"Source {src.get('DriveLetter')}: ko {selected.get('DriveLetter')}: par clone karna hai?\\nContinue?\"):\n            return\n        preflight = self._partition_preflight_checks(\"clone\", src, dest_part=selected)\n        if not preflight[\"ok\"]:\n            messagebox.showerror(\"Preflight Failed\", \"\\n\".join(preflight[\"errors\"]))\n            return\n        if preflight[\"warnings\"] and not self._partition_confirm_action(\"Clone Partition\", f\"Clone {src.get('DriveLetter','')} to {selected.get('DriveLetter','')}.\", preflight[\"warnings\"]):\n            return\n        dry_run = messagebox.askyesno(\"Dry-Run Recommended\", \"Dry-run preview recommended for partition clone. Yes = preview only, No = run actual operation now.\")\n        self._launch_job(\"partition_clone\", self._partition_clone_worker, src, selected, dry_run)\n\n    def _partition_clone_worker(self, source_part, dest_part, dry_run=False):\n        started, session_id = self._partition_start_operation(\"Clone Partition\")\n        if not started:\n            self._append_log(self.partition_log, \"\u26a0 Another partition operation is already running.\", C[\"warning\"])\n            return\n        src_letter = source_part.get(\"DriveLetter\")\n        dst_letter = dest_part.get(\"DriveLetter\")\n        if not src_letter or not dst_letter:\n            self._partition_log_diagnostic(\"ERROR\", \"Clone failed: drive letters required.\")\n            self._partition_end_operation(session_id, False, \"Clone failed\", C[\"error\"])\n            return\n        self._partition_log_diagnostic(\"INFO\", f\"Starting clone: {src_letter}: \u2192 {dst_letter}:\", {\"dry_run\": dry_run})\n        ts = datetime.datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n        dst_folder = f\"{dst_letter}:\\\\GodawariClone_{ts}\"\n        copy_log = os.path.join(os.environ.get(\"APPDATA\", \"\"), \"GodawariOptimizer\", \"partition_backups\", f\"clone_{ts}.log\")\n        os.makedirs(os.path.dirname(copy_log), exist_ok=True)\n        self._partition_update_progress(10, \"Calculating source size...\")\n        total_bytes = self._partition_folder_size(f\"{src_letter}:\\\\\")\n        self._partition_log_diagnostic(\"INFO\", f\"Source size: {total_bytes} bytes\")\n        if not dry_run:\n            try:\n                usage = shutil.disk_usage(f\"{dst_letter}:\\\\\")\n                if usage.free &lt; total_bytes:\n                    self._partition_log_diagnostic(\"ERROR\", \"Destination volume does not have enough free space.\")\n                    self._partition_end_operation(session_id, False, \"Clone failed: insufficient free space\", C[\"error\"])\n                    return\n            except Exception:\n                self._partition_log_diagnostic(\"WARN\", \"Unable to verify destination free space.\")\n        self._partition_update_progress(20, f\"Starting robocopy (source size: {round(total_bytes/1024**3,1)} GB)...\")\n        cmd = [\"robocopy\", f\"{src_letter}:\\\\\", dst_folder, \"/MIR\", \"/COPYALL\", \"/R:3\", \"/W:5\", f\"/LOG:{copy_log}\", \"/TEE\"]\n        if dry_run:\n            cmd.append(\"/L\")\n        result = self._partition_run_cmd_cancelable(cmd, timeout=7200)\n        if self._partition_operation_is_cancelled():\n            self._partition_log_diagnostic(\"WARN\", \"Clone operation cancelled.\")\n            self._partition_end_operation(session_id, False, \"Clone cancelled\", C[\"warning\"])\n            return\n        self._partition_update_progress(90, \"Verifying copied files...\")\n        if dry_run:\n            self._partition_log_diagnostic(\"OK\", \"Dry-run complete: clone plan validated.\")\n            self._partition_end_operation(session_id, True, \"Dry-run complete\", C[\"success\"])\n            return\n        if result.returncode &gt;= 8:\n            self._partition_log_diagnostic(\"ERROR\", f\"Clone failed: rc={result.returncode}\")\n            self._partition_end_operation(session_id, False, \"\u274c Clone failed\", C[\"error\"])\n        else:\n            self._partition_log_diagnostic(\"OK\", f\"Clone complete: {dst_folder}\")\n            self.after(0, self._partition_refresh_tree)\n            self._partition_end_operation(session_id, True, f\"\u2705 Clone complete: {dst_folder}\", C[\"success\"])\n\n    def _partition_backup_table(self):\n        self._launch_job(\"partition_backup\", self._partition_backup_table_worker)\n\n    def _partition_backup_table_worker(self):\n        backup_dir = os.path.join(os.environ.get(\"APPDATA\", \"\"), \"GodawariOptimizer\", \"partition_backups\")\n        os.makedirs(backup_dir, exist_ok=True)\n        ts = datetime.datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n        backup_file = os.path.join(backup_dir, f\"partition_backup_{ts}.json\")\n        backup_script = \"\"\"\n        $data = @{\n            Disks = (Get-Disk | ConvertTo-Json -Depth 3)\n            Partitions = (Get-Partition | ConvertTo-Json -Depth 3)\n        }\n        $data | ConvertTo-Json -Depth 4\n        \"\"\"\n        self._partition_update_progress(20, \"Reading partition table...\")\n        self._partition_update_progress(50, \"PowerShell query running...\")\n        result = safe_powershell(backup_script, timeout=20)\n        if result.returncode == 0 and result.output.strip():\n            with open(backup_file, \"w\", encoding=\"utf-8\") as f:\n                f.write(result.output)\n            self._partition_update_progress(100, \"\u2705 Partition table backup saved!\")\n            self.after(0, lambda: self._append_log(self.partition_log, f\"\u2705 Partition table backup saved: {backup_file}\", C[\"success\"]))\n        else:\n            self._partition_update_progress(0, \"\u274c Backup failed\")\n            self.after(0, lambda: self._append_log(self.partition_log, f\"\u274c Partition backup failed: {getattr(result, 'output', '')[:200]}\", C[\"error\"]))\n        self._partition_reset_progress_delayed(3000)\n\n    def _partition_get_selected_partitions(self):\n        return [self._partition_find_data(*self.partition_tree.item(iid)[\"values\"][:2]) for iid in self.partition_tree.selection() if self._partition_find_data(*self.partition_tree.item(iid)[\"values\"][:2])]\n\n    def _driver_scan_all(self):\n        self._append_log(self.driver_log, \"Driver scan shuru ho raha hai...\", C[\"accent\"])\n        self._launch_job(\"driver_scan_all\", self._do_driver_scan)\n\n    def _driver_age_text(self, days):\n        if days is None:\n            return \"Nahi pata\"\n        if days &gt;= 365:\n            return f\"{days//365} saal {(days%365)//30} mahine\"\n        return f\"{days} din\"\n\n    def _driver_parse_date(self, raw):\n        try:\n            if not raw:\n                return None\n            text = str(raw)\n            if re.match(r\"^\\d{14}\", text):\n                return datetime.datetime.strptime(text[:14], \"%Y%m%d%H%M%S\")\n            m = re.search(r\"/Date\\((\\d+)\", text)\n            if m:\n                return datetime.datetime.fromtimestamp(int(m.group(1)) / 1000)\n            for fmt in (\"%Y-%m-%dT%H:%M:%S\", \"%m/%d/%Y %H:%M:%S\", \"%Y-%m-%d\"):\n                try:\n                    return datetime.datetime.strptime(text[:19], fmt)\n                except Exception:\n                    pass\n        except Exception:\n            return None\n        return None\n\n    def _do_driver_scan(self):\n        try:\n            cmd = 'powershell -NoProfile -Command \"Get-WmiObject Win32_PnPSignedDriver | Select-Object DeviceName,DriverVersion,DriverDate,IsSigned,InfName | ConvertTo-Json\"'\n            out, rc = self._run_cmd(cmd, timeout=180)\n            if rc != 0:\n                self._append_log(self.driver_log, f\"Error aaya: {out[:300]}\", C[\"error\"])\n                return\n            data = json.loads(out) if out.strip() else []\n            if isinstance(data, dict):\n                data = [data]\n            rows = []\n            now = datetime.datetime.now()\n            for d in data:\n                dt = self._driver_parse_date(d.get(\"DriverDate\"))\n                days = (now - dt).days if dt else None\n                signed = bool(d.get(\"IsSigned\"))\n                tag = \"ok\"\n                if not signed:\n                    tag = \"unsigned\"\n                elif days is not None and days &gt; 730:\n                    tag = \"very_old\"\n                elif days is not None and days &gt; 365:\n                    tag = \"old\"\n                rows.append({\n                    \"device\": d.get(\"DeviceName\") or \"Naam nahi mila\",\n                    \"version\": d.get(\"DriverVersion\") or \"Nahi pata\",\n                    \"date\": dt.strftime(\"%Y-%m-%d\") if dt else \"Nahi pata\",\n                    \"signed\": signed,\n                    \"inf\": d.get(\"InfName\") or \"Nahi pata\",\n                    \"days\": days,\n                    \"age\": self._driver_age_text(days),\n                    \"tag\": tag,\n                })\n            self.after(0, lambda: self._driver_fill_rows(rows))\n        except Exception as e:\n            self._append_log(self.driver_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _driver_fill_rows(self, rows):\n        try:\n            self.driver_all_rows = rows\n            self.driver_tree.delete(*self.driver_tree.get_children())\n            for idx, r in enumerate(rows):\n                status = \"Signed\" if r[\"signed\"] else \"Unsigned\"\n                self.driver_tree.insert(\"\", \"end\", iid=str(idx), values=(r[\"device\"], r[\"version\"], r[\"date\"], status, r[\"age\"]), tags=(r[\"tag\"],))\n            self._append_log(self.driver_log, f\"\u2705 Kaam ho gaya: {len(rows)} drivers load ho gaye\", C[\"success\"])\n        except Exception as e:\n            self._append_log(self.driver_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _driver_filter_old(self):\n        try:\n            rows = [r for r in getattr(self, \"driver_all_rows\", []) if (r.get(\"days\") or 0) &gt;= 365]\n            self._driver_fill_rows(rows)\n            self._append_log(self.driver_log, \"Purane drivers filter ho gaye\", C[\"warning\"])\n        except Exception as e:\n            self._append_log(self.driver_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _driver_filter_unsigned(self):\n        try:\n            rows = [r for r in getattr(self, \"driver_all_rows\", []) if not r.get(\"signed\")]\n            self._driver_fill_rows(rows)\n            self._append_log(self.driver_log, \"Unsigned drivers filter ho gaye\", C[\"warning\"])\n        except Exception as e:\n            self._append_log(self.driver_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _driver_on_select(self, event):\n        try:\n            sel = self.driver_tree.selection()\n            if not sel:\n                return\n            vals = self.driver_tree.item(sel[0], \"values\")\n            device = vals[0]\n            row = next((r for r in getattr(self, \"driver_all_rows\", []) if r.get(\"device\") == device), None)\n            if not row:\n                return\n            for w in self.driver_detail.winfo_children():\n                w.destroy()\n            tk.Label(self.driver_detail, text=row[\"device\"], font=(\"Segoe UI\", 13, \"bold\"), fg=C[\"accent\"], bg=C[\"card\"], wraplength=330, justify=\"left\").pack(anchor=\"w\", pady=(0,8))\n            info = [\n                f\"Version: {row['version']}\",\n                f\"Date: {row['date']}\",\n                f\"Signed: {'Haan' if row['signed'] else 'Nahi'}\",\n                f\"INF file: {row['inf']}\",\n            ]\n            for line in info:\n                tk.Label(self.driver_detail, text=line, font=FONTS[\"body\"], fg=C[\"text\"], bg=C[\"card\"], wraplength=330, justify=\"left\").pack(anchor=\"w\", pady=2)\n            if not row[\"signed\"]:\n                rec, color = \"\u26a0 Unsigned driver - security risk\", C[\"error\"]\n            elif (row.get(\"days\") or 0) &gt; 730:\n                rec, color = \"\u26a0 Bahut purana driver - update recommended\", C[\"warning\"]\n            elif row.get(\"days\") is not None and row[\"days\"] &lt; 180:\n                rec, color = \"\u2705 Recent driver - action ki zaroorat nahi\", C[\"success\"]\n            else:\n                rec, color = \"Info: Driver theek lag raha hai\", C[\"text_dim\"]\n            tk.Label(self.driver_detail, text=rec, font=FONTS[\"subhead\"], fg=color, bg=C[\"card\"], wraplength=330, justify=\"left\").pack(anchor=\"w\", pady=12)\n        except Exception as e:\n            self._append_log(self.driver_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _driver_export_csv(self):\n        try:\n            rows = getattr(self, \"driver_all_rows\", [])\n            if not rows:\n                messagebox.showwarning(\"Data nahi mila\", \"Pehle driver scan karo\")\n                return\n            csv_mod = __import__(\"csv\")\n            desktop = os.path.join(os.environ.get(\"USERPROFILE\", \"\"), \"Desktop\")\n            path = os.path.join(desktop, f\"Godawari_Driver_Report_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.csv\")\n            with open(path, \"w\", newline=\"\", encoding=\"utf-8-sig\") as f:\n                writer = csv_mod.writer(f)\n                writer.writerow([\"DeviceName\", \"DriverVersion\", \"DriverDate\", \"Signed\", \"Age\"])\n                for r in rows:\n                    writer.writerow([r[\"device\"], r[\"version\"], r[\"date\"], \"Haan\" if r[\"signed\"] else \"Nahi\", r[\"age\"]])\n            self._append_log(self.driver_log, f\"\u2705 Kaam ho gaya: CSV save hua - {path}\", C[\"success\"])\n            messagebox.showinfo(\"Kaam ho gaya\", f\"Driver CSV save ho gaya:\\n{path}\")\n        except Exception as e:\n            self._append_log(self.driver_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _build_svc_presets(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"Services Preset Manager\", \"Gaming, office, safe aur repair presets\")\n        content = self._scrollable_section_body(frame)\n        self.svc_presets_data = {\n            \"Gaming\": {\"description\": \"Maximum performance - gaming ke liye\", \"icon\": \"\ud83c\udfae\", \"color\": C[\"btn_danger\"], \"disable\": [\"SysMain\",\"DiagTrack\",\"WSearch\",\"TabletInputService\",\"Fax\",\"PrintNotify\",\"WerSvc\",\"XblAuthManager\",\"XblGameSave\",\"XboxNetApiSvc\"], \"manual\": [\"wuauserv\"], \"keep_running\": [\"AudioSrv\",\"AudioEndpointBuilder\",\"Themes\"]},\n            \"Office/Work\": {\"description\": \"Stable aur fast - office work ke liye\", \"icon\": \"\ud83d\udcbc\", \"color\": C[\"btn_info\"], \"disable\": [\"XblAuthManager\",\"XblGameSave\",\"XboxNetApiSvc\",\"Fax\",\"RetailDemo\",\"DiagTrack\"], \"manual\": [\"SysMain\",\"WSearch\"], \"keep_running\": [\"wuauserv\",\"AudioSrv\",\"Themes\"]},\n            \"Minimal/Safe\": {\"description\": \"Sirf zaroori services - slow PC ke liye\", \"icon\": \"\ud83d\udee1\", \"color\": C[\"btn_chip\"], \"disable\": [\"SysMain\",\"DiagTrack\",\"WSearch\",\"TabletInputService\",\"Fax\",\"PrintNotify\",\"WerSvc\",\"XblAuthManager\",\"XblGameSave\",\"XboxNetApiSvc\",\"RetailDemo\",\"MapsBroker\",\"lfsvc\",\"SharedAccess\"], \"manual\": [\"wuauserv\",\"BITS\"], \"keep_running\": [\"AudioSrv\",\"Themes\",\"LanmanWorkstation\"]},\n            \"Repair Shop\": {\"description\": \"Troubleshooting ke liye - diagnostics on\", \"icon\": \"\ud83d\udd27\", \"color\": C[\"hw_accent\"], \"disable\": [\"XblAuthManager\",\"XblGameSave\",\"Fax\",\"RetailDemo\"], \"manual\": [\"DiagTrack\",\"WerSvc\"], \"keep_running\": [\"WSearch\",\"wuauserv\",\"SysMain\",\"AudioSrv\"]},\n        }\n        self.svc_selected_preset = tk.StringVar(value=\"Gaming\")\n        self.svc_preset_snapshot = {}\n        self.svc_preset_cards = {}\n        cards = tk.Frame(content, bg=C[\"bg\"])\n        cards.pack(fill=\"x\", padx=14, pady=8)\n        for i, (name, data) in enumerate(self.svc_presets_data.items()):\n            card = tk.Frame(cards, bg=C[\"card\"], highlightbackground=data[\"color\"], highlightthickness=1, cursor=\"hand2\")\n            card.grid(row=0, column=i, sticky=\"nsew\", padx=5)\n            cards.columnconfigure(i, weight=1)\n            tk.Label(card, text=data[\"icon\"], font=(\"Segoe UI\", 22), fg=data[\"color\"], bg=C[\"card\"]).pack(pady=(8,0))\n            tk.Label(card, text=name, font=FONTS[\"subhead\"], fg=C[\"text\"], bg=C[\"card\"]).pack()\n            tk.Label(card, text=data[\"description\"], font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=220).pack(padx=8, pady=(0,8))\n            card.bind(\"\", lambda e, n=name: self._svc_preset_select(n))\n            for child in card.winfo_children():\n                child.bind(\"\", lambda e, n=name: self._svc_preset_select(n))\n            self.svc_preset_cards[name] = card\n        body = tk.Frame(content, bg=C[\"bg\"])\n        body.pack(fill=\"both\", expand=True, padx=14)\n        left = tk.Frame(body, bg=C[\"card\"])\n        left.pack(side=\"left\", fill=\"both\", expand=True, padx=(0,8))\n        right = tk.Frame(body, bg=C[\"card\"], width=360)\n        right.pack(side=\"right\", fill=\"both\", padx=(8,0))\n        right.pack_propagate(False)\n        wrap, self.svc_tree = self._adv_tree(left, [\"Service Naam\", \"Display Naam\", \"Action\", \"Current Status\"], height=16)\n        wrap.pack(fill=\"both\", expand=True, padx=8, pady=8)\n        self.svc_tree.tag_configure(\"risk\", foreground=C[\"error\"])\n        self.svc_status_text = self._scrolled_text(right, height=15)\n        btns = tk.Frame(content, bg=C[\"bg\"])\n        btns.pack(fill=\"x\", padx=14, pady=6)\n        for label, color, cmd in [\n            (\"Status Check\", C[\"btn_info\"], self._svc_preset_check_status),\n            (\"Preset Apply\", C[\"btn_danger\"], lambda: self._svc_preset_apply(self.svc_selected_preset.get())),\n            (\"Custom Save\", C[\"btn\"], self._svc_preset_save_custom),\n            (\"Custom Load\", C[\"btn_chip\"], self._svc_preset_load_custom),\n            (\"Previous Restore\", C[\"btn_warn\"], self._svc_preset_restore),\n        ]:\n            self._btn(btns, label, color, cmd).pack(side=\"left\", padx=4)\n        self.svc_log = self._scrolled_text(content, height=6)\n        self._svc_preset_select(\"Gaming\")\n        return frame\n\n    def _svc_preset_select(self, preset_name):\n        try:\n            self.svc_selected_preset.set(preset_name)\n            for name, card in self.svc_preset_cards.items():\n                card.configure(bg=C[\"panel\"] if name == preset_name else C[\"card\"])\n                for child in card.winfo_children():\n                    child.configure(bg=card[\"bg\"])\n            data = self.svc_presets_data[preset_name]\n            self.svc_tree.delete(*self.svc_tree.get_children())\n            for svc in data.get(\"disable\", []):\n                self.svc_tree.insert(\"\", \"end\", values=(svc, svc, \"Disable\", \"Check pending\"))\n            for svc in data.get(\"manual\", []):\n                self.svc_tree.insert(\"\", \"end\", values=(svc, svc, \"Manual\", \"Check pending\"))\n            for svc in data.get(\"keep_running\", []):\n                self.svc_tree.insert(\"\", \"end\", values=(svc, svc, \"Keep\", \"Check pending\"))\n            self._append_log(self.svc_log, f\"{preset_name} preset select ho gaya\", C[\"accent\"])\n        except Exception as e:\n            self._append_log(self.svc_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _svc_preset_check_status(self):\n        try:\n            services = []\n            for iid in self.svc_tree.get_children():\n                vals = self.svc_tree.item(iid, \"values\")\n                if len(vals) &gt;= 3:\n                    services.append((iid, vals[0], vals[2]))\n            self._launch_job(\"svc_preset_check\", self._do_svc_preset_check, services)\n        except Exception as e:\n            self._append_log(self.svc_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _do_svc_preset_check(self, services=None):\n        try:\n            updates = []\n            for iid, svc, action in (services or []):\n                status = self._svc_get_status(svc)\n                updates.append((iid, status, action))\n            def apply():\n                for iid, status, action in updates:\n                    vals = list(self.svc_tree.item(iid, \"values\"))\n                    vals[3] = status\n                    tags = (\"risk\",) if status == \"Running\" and vals[2] == \"Disable\" else ()\n                    self.svc_tree.item(iid, values=vals, tags=tags)\n                self._append_log(self.svc_log, \"\u2705 Kaam ho gaya: Service status update ho gaya\", C[\"success\"])\n            self.after(0, apply)\n        except Exception as e:\n            self._append_log(self.svc_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _svc_preset_apply(self, preset_name):\n        try:\n            data = self.svc_presets_data.get(preset_name)\n            if not data:\n                messagebox.showwarning(\"Preset nahi mila\", \"Pehle preset select karo\")\n                return\n            count = len(data.get(\"disable\", [])) + len(data.get(\"manual\", []))\n            if not messagebox.askyesno(\"Confirm karo\", f\"{preset_name} preset apply karna hai?\\n{count} services change hongi.\"):\n                return\n            self._launch_job(\"svc_preset_apply\", self._do_svc_preset_apply, preset_name, data)\n        except Exception as e:\n            self._append_log(self.svc_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _do_svc_preset_apply(self, preset_name, preset_data):\n        try:\n            affected = set(preset_data.get(\"disable\", []) + preset_data.get(\"manual\", []) + preset_data.get(\"keep_running\", []))\n            self.svc_preset_snapshot = {svc: self._svc_get_start_type(svc) for svc in affected}\n            for svc in preset_data.get(\"disable\", []):\n                out, rc = self._run_cmd(f\"sc config {svc} start= disabled\", timeout=40)\n                self._append_log(self.svc_log, f\"{svc}: disabled set - rc {rc}\", C[\"warning\"] if rc else C[\"success\"])\n                self._run_cmd(f\"sc stop {svc}\", timeout=25)\n            for svc in preset_data.get(\"manual\", []):\n                out, rc = self._run_cmd(f\"sc config {svc} start= demand\", timeout=40)\n                self._append_log(self.svc_log, f\"{svc}: manual set - rc {rc}\", C[\"success\"] if rc == 0 else C[\"warning\"])\n            self._append_log(self.svc_log, f\"\u2705 Kaam ho gaya: {preset_name} preset apply ho gaya\", C[\"success\"])\n            self._svc_preset_check_status()\n        except Exception as e:\n            self._append_log(self.svc_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _svc_preset_save_custom(self):\n        self._launch_job(\"svc_custom_save\", self._svc_preset_save_custom_worker)\n\n    def _svc_preset_save_custom_worker(self):\n        try:\n            all_svcs = set()\n            for data in self.svc_presets_data.values():\n                all_svcs.update(data.get(\"disable\", []) + data.get(\"manual\", []) + data.get(\"keep_running\", []))\n            custom = {\"description\": \"Saved custom service state\", \"icon\": \"\ud83d\udcbe\", \"color\": C[\"btn\"], \"disable\": [], \"manual\": [], \"keep_running\": []}\n            for svc in all_svcs:\n                st = self._svc_get_start_type(svc)\n                if st == \"disabled\":\n                    custom[\"disable\"].append(svc)\n                elif st == \"demand\":\n                    custom[\"manual\"].append(svc)\n                elif st == \"auto\":\n                    custom[\"keep_running\"].append(svc)\n            path = os.path.join(os.environ.get(\"APPDATA\", \"\"), \"GodawariOptimizer\", \"svc_custom.json\")\n            os.makedirs(os.path.dirname(path), exist_ok=True)\n            with open(path, \"w\", encoding=\"utf-8\") as f:\n                json.dump(custom, f, indent=2)\n            self.svc_presets_data[\"Custom\"] = custom\n            self._append_log(self.svc_log, f\"\u2705 Kaam ho gaya: Custom preset save hua - {path}\", C[\"success\"])\n        except Exception as e:\n            self._append_log(self.svc_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _svc_preset_load_custom(self):\n        try:\n            path = os.path.join(os.environ.get(\"APPDATA\", \"\"), \"GodawariOptimizer\", \"svc_custom.json\")\n            if not os.path.exists(path):\n                messagebox.showwarning(\"Custom nahi mila\", \"Custom preset abhi save nahi hai\")\n                return\n            with open(path, \"r\", encoding=\"utf-8\") as f:\n                self.svc_presets_data[\"Custom\"] = json.load(f)\n            self._svc_preset_select(\"Custom\")\n            self._append_log(self.svc_log, \"\u2705 Kaam ho gaya: Custom preset load ho gaya\", C[\"success\"])\n        except Exception as e:\n            self._append_log(self.svc_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _svc_preset_restore(self):\n        try:\n            if not getattr(self, \"svc_preset_snapshot\", {}):\n                messagebox.showwarning(\"Snapshot nahi mila\", \"Restore ke liye pehle preset apply hona chahiye\")\n                return\n            if not messagebox.askyesno(\"Confirm karo\", \"Previous service state restore karna hai?\"):\n                return\n            self._launch_job(\"svc_restore\", self._svc_preset_restore_worker)\n        except Exception as e:\n            self._append_log(self.svc_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _svc_preset_restore_worker(self):\n        try:\n            for svc, st in self.svc_preset_snapshot.items():\n                if st in (\"auto\", \"demand\", \"disabled\"):\n                    out, rc = self._run_cmd(f\"sc config {svc} start= {st}\", timeout=40)\n                    self._append_log(self.svc_log, f\"{svc}: {st} restore - rc {rc}\", C[\"success\"] if rc == 0 else C[\"warning\"])\n            self._append_log(self.svc_log, \"\u2705 Kaam ho gaya: Previous state restore ho gayi\", C[\"success\"])\n        except Exception as e:\n            self._append_log(self.svc_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _svc_get_start_type(self, service_name):\n        try:\n            out, rc = self._run_cmd(f\"sc qc {service_name}\", timeout=20)\n            m = re.search(r\"START_TYPE\\s+:\\s+\\d+\\s+(\\w+)\", out)\n            text = (m.group(1).lower() if m else \"\")\n            if \"auto\" in text:\n                return \"auto\"\n            if \"demand\" in text:\n                return \"demand\"\n            if \"disabled\" in text:\n                return \"disabled\"\n        except Exception:\n            pass\n        return \"unknown\"\n\n    def _svc_get_status(self, service_name):\n        try:\n            out, rc = self._run_cmd(f\"sc query {service_name}\", timeout=20)\n            m = re.search(r\"STATE\\s+:\\s+\\d+\\s+(\\w+)\", out)\n            if m:\n                return \"Running\" if m.group(1).upper() == \"RUNNING\" else \"Stopped\"\n        except Exception:\n            pass\n        return \"Unknown\"\n\n    # Remaining advanced menus are implemented as operational compact panels.\n    def _build_disk_analyzer(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"Disk Space Analyzer\", \"Drive/folder size aur Windows bloat check\")\n        content = self._scrollable_section_body(frame)\n        top = tk.Frame(content, bg=C[\"bg\"])\n        top.pack(fill=\"x\", padx=14, pady=8)\n        string_mod = __import__(\"string\")\n        drives = [f\"{d}:\\\\\" for d in string_mod.ascii_uppercase if os.path.exists(f\"{d}:\\\\\")]\n        self.disk_drive_var = tk.StringVar(value=drives[0] if drives else \"C:\\\\\")\n        self.disk_depth_var = tk.IntVar(value=2)\n        ttk.Combobox(top, textvariable=self.disk_drive_var, values=drives + [\"Custom folder browse karo\"], width=28, state=\"readonly\").pack(side=\"left\", padx=4)\n        tk.Spinbox(top, from_=1, to=5, textvariable=self.disk_depth_var, width=5, bg=C[\"card\"], fg=C[\"text\"]).pack(side=\"left\", padx=4)\n        self._btn(top, \"Scan Drive\", C[\"btn_info\"], self._disk_start_scan).pack(side=\"left\", padx=4)\n        status = tk.Frame(content, bg=C[\"bg\"])\n        status.pack(fill=\"x\", padx=14, pady=(0, 6))\n        self.disk_scan_status = tk.Label(status, text=\"Ready to scan.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"], anchor=\"w\")\n        self.disk_scan_status.pack(side=\"left\", fill=\"x\", expand=True)\n        self.disk_scan_progress_var = tk.DoubleVar(value=0.0)\n        self.disk_scan_progress = ttk.Progressbar(status, variable=self.disk_scan_progress_var, maximum=100.0, mode=\"determinate\")\n        self.disk_scan_progress.pack(side=\"right\", fill=\"x\", expand=False, ipadx=90, padx=(8, 0))\n        body = tk.Frame(content, bg=C[\"bg\"])\n        body.pack(fill=\"both\", expand=True, padx=14)\n        left = tk.Frame(body, bg=C[\"card\"])\n        left.pack(side=\"left\", fill=\"both\", expand=True, padx=(0,8))\n        right = tk.Frame(body, bg=C[\"card\"], width=360)\n        right.pack(side=\"right\", fill=\"both\", padx=(8,0))\n        right.pack_propagate(False)\n        wrap, self.disk_tree = self._adv_tree(left, [\"Folder\", \"Size\", \"Files Count\", \"% Parent\"], height=18)\n        wrap.pack(fill=\"both\", expand=True, padx=8, pady=8)\n        self.disk_summary = self._scrolled_text(right, height=18)\n        self._action_card_grid(content, [\n            (\"\ud83d\udd0d\", \"Scan Drive\", \"Selected drive scan karo\", C[\"btn_info\"], self._disk_start_scan),\n            (\"\ud83d\udcc2\", \"Folder Kholo\", \"Selected folder Explorer mein kholo\", C[\"btn_chip\"], self._disk_open_selected),\n            (\"\ud83e\uddf9\", \"Temp Clean\", \"Temp folders directly clean karo\", C[\"btn_warn\"], self._disk_clean_temp),\n            (\"\ud83d\udcbe\", \"Report Export\", \"Results CSV mein save karo\", C[\"btn\"], self._disk_export_report),\n            (\"\ud83d\udd04\", \"Refresh\", \"Dobara scan karo\", C[\"accent2\"], self._disk_start_scan),\n        ], cols=5)\n        self.disk_log = self._scrolled_text(content, height=5)\n        self.disk_results = []\n        return frame\n\n    def _disk_start_scan(self):\n        try:\n            root = self.disk_drive_var.get()\n            if root == \"Custom folder browse karo\":\n                root = filedialog.askdirectory()\n                if not root:\n                    return\n                self.disk_drive_var.set(root)\n            self._append_log(self.disk_log, f\"Scan shuru: {root}\", C[\"accent\"])\n            self._disk_update_scan_progress(0, f\"Scanning {root}...\")\n            self._launch_job(\"disk_scan\", self._do_disk_scan, root, int(self.disk_depth_var.get()))\n        except Exception as e:\n            self._append_log(self.disk_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _disk_update_scan_progress(self, pct, text=None):\n        def _update():\n            try:\n                pct_float = max(0.0, min(100.0, float(pct)))\n            except Exception:\n                pct_float = 0.0\n            if hasattr(self, \"disk_scan_progress_var\"):\n                self.disk_scan_progress_var.set(pct_float)\n            if hasattr(self, \"disk_scan_status\") and text is not None:\n                self.disk_scan_status.config(text=f\"{int(pct_float)}% - {str(text)[:160]}\")\n        self.after(0, _update)\n\n    def _do_disk_scan(self, root_path, max_depth):\n        try:\n            root_path = os.path.abspath(root_path)\n            base_depth = root_path.rstrip(\"\\\\/\").count(os.sep)\n            results = []\n            scanned_dirs = 0\n            for cur, dirs, files in os.walk(root_path):\n                depth = cur.rstrip(\"\\\\/\").count(os.sep) - base_depth\n                if depth &gt; max_depth:\n                    dirs[:] = []\n                    continue\n                dirs[:] = [d for d in dirs if not d.startswith(\"$\")]\n                size, count = self._disk_get_folder_size(cur)\n                results.append((cur, size, count, 0))\n                scanned_dirs += 1\n                if scanned_dirs % 8 == 0:\n                    self._disk_update_scan_progress(min(95, 5 + scanned_dirs), f\"{scanned_dirs} folders scanned...\")\n                if len(results) &gt; 250:\n                    break\n            results.sort(key=lambda x: x[1], reverse=True)\n            top = results[:50]\n            bloat = self._disk_check_windows_bloat()\n            self._disk_update_scan_progress(100, f\"{len(top)} folders ready.\")\n            self.after(0, lambda: (self._disk_populate_treeview(top), self._disk_generate_recommendations(bloat)))\n        except Exception as e:\n            self._disk_update_scan_progress(0, f\"Scan failed: {e}\")\n            self._append_log(self.disk_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _disk_get_folder_size(self, path):\n        total = 0\n        count = 0\n        try:\n            for root, dirs, files in os.walk(path):\n                dirs[:] = [d for d in dirs if not d.startswith(\"$\")]\n                for fn in files:\n                    try:\n                        fp = os.path.join(root, fn)\n                        total += os.path.getsize(fp)\n                        count += 1\n                        if count &gt;= 3000:\n                            return total, count\n                    except Exception:\n                        continue\n        except Exception:\n            return total, count\n        return total, count\n\n    def _disk_populate_treeview(self, results):\n        try:\n            self.disk_results = results\n            self.disk_tree.delete(*self.disk_tree.get_children())\n            parent_size = results[0][1] if results else 1\n            for path, size, count, _pct in results:\n                pct = (size / parent_size * 100) if parent_size else 0\n                self.disk_tree.insert(\"\", \"end\", values=(path, self._fmt_size_disk(size), count, f\"{pct:.1f}%\"))\n            self._append_log(self.disk_log, f\"\u2705 Kaam ho gaya: {len(results)} folders show ho rahe hain\", C[\"success\"])\n        except Exception as e:\n            self._append_log(self.disk_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _disk_check_windows_bloat(self):\n        data = {}\n        try:\n            user = os.environ.get(\"USERNAME\", \"\")\n            paths = {\n                \"Windows Temp\": r\"C:\\Windows\\Temp\",\n                \"User Temp\": os.path.join(os.environ.get(\"USERPROFILE\", \"\"), \"AppData\", \"Local\", \"Temp\"),\n                \"Windows Update Cache\": r\"C:\\Windows\\SoftwareDistribution\\Download\",\n                \"Windows Installer\": r\"C:\\Windows\\Installer\",\n                \"Recycle Bin\": r\"C:\\$Recycle.Bin\",\n                \"hiberfil.sys\": r\"C:\\hiberfil.sys\",\n                \"pagefile.sys\": r\"C:\\pagefile.sys\",\n            }\n            for name, path in paths.items():\n                if os.path.isfile(path):\n                    data[name] = os.path.getsize(path)\n                elif os.path.isdir(path):\n                    data[name] = self._disk_get_folder_size(path)[0]\n                else:\n                    data[name] = 0\n        except Exception as e:\n            self._append_log(self.disk_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n        return data\n\n    def _disk_generate_recommendations(self, bloat_data):\n        try:\n            self.disk_summary.config(state=\"normal\")\n            self.disk_summary.delete(\"1.0\", \"end\")\n            self.disk_summary.insert(\"end\", \"Windows Bloat Summary\\n\\n\")\n            recs = []\n            for name, size in bloat_data.items():\n                self.disk_summary.insert(\"end\", f\"{name}: {self._fmt_size_disk(size)}\\n\")\n            if bloat_data.get(\"Windows Temp\", 0) + bloat_data.get(\"User Temp\", 0) &gt; 500*1024*1024:\n                recs.append(\"\ud83d\udfe1 Temp files cleanup recommended - Junk Cleaner use karo\")\n            if bloat_data.get(\"Windows Update Cache\", 0) &gt; 1024*1024*1024:\n                recs.append(\"\ud83d\udfe1 Windows Update cache bada hai - safe clear ho sakta hai\")\n            if bloat_data.get(\"Recycle Bin\", 0) &gt; 100*1024*1024:\n                recs.append(\"\ud83d\udfe1 Recycle Bin empty karo\")\n            if bloat_data.get(\"hiberfil.sys\", 0) &gt; 2*1024*1024*1024:\n                recs.append(\"\ud83d\udfe1 Hibernation disable karo agar laptop nahi hai: powercfg /h off\")\n            if bloat_data.get(\"Windows Installer\", 0) &gt; 2*1024*1024*1024:\n                recs.append(\"\u26a0 Windows Installer folder bada hai - careful cleanup needed\")\n            self.disk_summary.insert(\"end\", \"\\nRecommendations\\n\\n\" + (\"\\n\".join(recs) if recs else \"\u2705 Koi badi cleanup warning nahi mili\"))\n            self.disk_summary.config(state=\"disabled\")\n        except Exception as e:\n            self._append_log(self.disk_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _disk_open_selected(self):\n        try:\n            sel = self.disk_tree.selection()\n            if not sel:\n                messagebox.showwarning(\"Select karo\", \"Pehle folder select karo\")\n                return\n            path = self.disk_tree.item(sel[0], \"values\")[0]\n            if os.path.exists(path):\n                os.startfile(path)\n        except Exception as e:\n            self._append_log(self.disk_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _disk_clean_temp(self):\n        if messagebox.askyesno(\"Confirm karo\", \"Temp files delete karne hain?\"):\n            self._launch_job(\"disk_clean_temp\", self._disk_clean_temp_worker)\n\n    def _disk_clean_temp_worker(self):\n        try:\n            for folder in [r\"C:\\Windows\\Temp\", os.path.join(os.environ.get(\"USERPROFILE\", \"\"), \"AppData\", \"Local\", \"Temp\")]:\n                if os.path.isdir(folder):\n                    for name in os.listdir(folder):\n                        p = os.path.join(folder, name)\n                        try:\n                            shutil.rmtree(p) if os.path.isdir(p) else os.remove(p)\n                        except Exception:\n                            pass\n            self._append_log(self.disk_log, \"\u2705 Kaam ho gaya: Temp clean ho gaya\", C[\"success\"])\n        except Exception as e:\n            self._append_log(self.disk_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _disk_export_report(self):\n        try:\n            if not getattr(self, \"disk_results\", []):\n                messagebox.showwarning(\"Data nahi mila\", \"Pehle disk scan karo\")\n                return\n            csv_mod = __import__(\"csv\")\n            path = os.path.join(os.environ.get(\"USERPROFILE\", \"\"), \"Desktop\", f\"Godawari_Disk_Report_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.csv\")\n            with open(path, \"w\", newline=\"\", encoding=\"utf-8-sig\") as f:\n                writer = csv_mod.writer(f)\n                writer.writerow([\"Folder\", \"SizeBytes\", \"FilesCount\"])\n                for r in self.disk_results:\n                    writer.writerow([r[0], r[1], r[2]])\n            messagebox.showinfo(\"Kaam ho gaya\", f\"Report save ho gayi:\\n{path}\")\n        except Exception as e:\n            self._append_log(self.disk_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _fmt_size_disk(self, bytes):\n        try:\n            val = float(bytes)\n            for unit in [\"B\", \"KB\", \"MB\", \"GB\", \"TB\"]:\n                if val &lt; 1024:\n                    return f\"{val:.1f} {unit}\"\n                val /= 1024\n            return f\"{val:.1f} PB\"\n        except Exception:\n            return \"0 B\"\n\n    def _build_bsod_history(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"BSOD History\", \"Crash events, stop code aur minidump report\")\n        content = self._scrollable_section_body(frame)\n        self._action_card_grid(content, [\n            (\"\ud83d\udd0d\", \"BSOD Scan\", \"Event log se BSOD history nikalo\", C[\"btn_info\"], self._bsod_scan),\n            (\"\ud83d\udcc2\", \"Dump Folder\", \"Minidump folder kholo\", C[\"btn_chip\"], self._bsod_open_dumps),\n            (\"\ud83d\udccb\", \"Dump Copy\", \"Dumps Desktop pe copy karo\", C[\"btn_warn\"], self._bsod_copy_dumps),\n            (\"\ud83d\udcbe\", \"Report Export\", \"BSOD report save karo\", C[\"btn\"], self._bsod_export_report),\n            (\"\ud83e\uddf9\", \"Events Clear\", \"BSOD events clean karo\", C[\"btn_danger\"], self._bsod_clear_events),\n        ], cols=5)\n        body = tk.Frame(content, bg=C[\"bg\"])\n        body.pack(fill=\"both\", expand=True, padx=14, pady=8)\n        left = tk.Frame(body, bg=C[\"card\"])\n        left.pack(side=\"left\", fill=\"both\", expand=True, padx=(0,8))\n        right = tk.Frame(body, bg=C[\"card\"], width=390)\n        right.pack(side=\"right\", fill=\"both\", padx=(8,0))\n        right.pack_propagate(False)\n        wrap, self.bsod_tree = self._adv_tree(left, [\"Date Time\", \"Event ID\", \"Stop Code\", \"Description\"], height=14)\n        wrap.pack(fill=\"both\", expand=True, padx=8, pady=8)\n        self.bsod_tree.bind(\"&lt;&gt;\", self._bsod_on_select)\n        self.bsod_detail = self._scrolled_text(right, height=16)\n        dump_frame = tk.Frame(content, bg=C[\"card\"])\n        dump_frame.pack(fill=\"x\", padx=14, pady=(0,8))\n        wrap2, self.bsod_dump_tree = self._adv_tree(dump_frame, [\"File Naam\", \"Date\", \"Size\"], height=5)\n        wrap2.pack(fill=\"x\", padx=8, pady=8)\n        self.bsod_log = self._scrolled_text(content, height=5)\n        self.bsod_rows = []\n        return frame\n\n    def _bsod_scan(self):\n        self._append_log(self.bsod_log, \"BSOD scan shuru ho raha hai...\", C[\"accent\"])\n        self._launch_job(\"bsod_scan\", self._do_bsod_scan)\n\n    def _do_bsod_scan(self):\n        try:\n            cmd = '''powershell -NoProfile -Command \"Get-WinEvent -FilterHashtable @{LogName='System'; Id=41,1001,6008} -MaxEvents 50 -ErrorAction SilentlyContinue | Select-Object TimeCreated, Id, Message | ConvertTo-Json\"'''\n            out, rc = self._run_cmd(cmd, timeout=120)\n            data = json.loads(out) if out.strip() else []\n            if isinstance(data, dict):\n                data = [data]\n            rows = []\n            for ev in data:\n                msg = ev.get(\"Message\", \"\") or \"\"\n                code = self._bsod_parse_stop_code(msg)\n                desc = \"BugCheck crash\" if str(ev.get(\"Id\")) == \"1001\" else (\"Unexpected shutdown\" if str(ev.get(\"Id\")) == \"6008\" else \"Kernel Power restart\")\n                rows.append({\"time\": str(ev.get(\"TimeCreated\", \"\"))[:19], \"id\": str(ev.get(\"Id\", \"\")), \"code\": code, \"desc\": desc, \"msg\": msg})\n            dumps = []\n            dump_dir = r\"C:\\Windows\\Minidump\"\n            if os.path.isdir(dump_dir):\n                for fn in os.listdir(dump_dir):\n                    if fn.lower().endswith(\".dmp\"):\n                        p = os.path.join(dump_dir, fn)\n                        try:\n                            dumps.append((fn, datetime.datetime.fromtimestamp(os.path.getmtime(p)).strftime(\"%Y-%m-%d %H:%M\"), self._fmt_size_disk(os.path.getsize(p))))\n                        except Exception:\n                            pass\n            self.after(0, lambda: self._bsod_fill(rows, dumps))\n        except Exception as e:\n            self._append_log(self.bsod_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _bsod_fill(self, rows, dumps):\n        self.bsod_rows = rows\n        self.bsod_tree.delete(*self.bsod_tree.get_children())\n        for i, r in enumerate(rows):\n            self.bsod_tree.insert(\"\", \"end\", iid=str(i), values=(r[\"time\"], r[\"id\"], r[\"code\"], r[\"desc\"]))\n        self.bsod_dump_tree.delete(*self.bsod_dump_tree.get_children())\n        for d in dumps:\n            self.bsod_dump_tree.insert(\"\", \"end\", values=d)\n        self._append_log(self.bsod_log, f\"\u2705 Kaam ho gaya: {len(rows)} events aur {len(dumps)} dumps mile\", C[\"success\"])\n\n    def _bsod_parse_stop_code(self, message):\n        try:\n            m = re.search(r\"0x[0-9A-Fa-f]{8}\", message or \"\")\n            return m.group(0).upper() if m else \"Nahi mila\"\n        except Exception:\n            return \"Nahi mila\"\n\n    def _bsod_stop_db(self):\n        return {\n            \"0X0000001A\": (\"MEMORY_MANAGEMENT\", \"RAM faulty hai ya driver memory corrupt kar raha hai\", \"RAM test karo - MemTest86 chalao\"),\n            \"0X0000003B\": (\"SYSTEM_SERVICE_EXCEPTION\", \"Driver ya system service mein error\", \"Recent driver uninstall karo\"),\n            \"0X0000007E\": (\"SYSTEM_THREAD_EXCEPTION\", \"Driver crash - usually graphics ya chipset driver\", \"GPU driver reinstall karo\"),\n            \"0X0000007F\": (\"UNEXPECTED_KERNEL_MODE_TRAP\", \"CPU hardware error ya overclocking\", \"Overclock remove karo, RAM check karo\"),\n            \"0X00000050\": (\"PAGE_FAULT_IN_NONPAGED_AREA\", \"RAM ya driver ne invalid memory access kiya\", \"RAM slots change karo, driver update karo\"),\n            \"0X0000009F\": (\"DRIVER_POWER_STATE_FAILURE\", \"Sleep/hibernate se wake pe driver fail\", \"Power management driver update karo\"),\n            \"0X000000D1\": (\"DRIVER_IRQL_NOT_LESS_OR_EQUAL\", \"Driver ne wrong memory access kiya - faulty driver\", \"Recent installed driver remove karo\"),\n            \"0X000000EF\": (\"CRITICAL_PROCESS_DIED\", \"Windows ka critical process crash ho gaya\", \"SFC /scannow chalao\"),\n            \"0X0000000A\": (\"IRQL_NOT_LESS_OR_EQUAL\", \"Driver IRQ level problem - usually RAM ya driver\", \"RAM test + driver check\"),\n            \"0X00000024\": (\"NTFS_FILE_SYSTEM\", \"NTFS disk corruption - HDD/SSD issue\", \"chkdsk /f /r chalao\"),\n            \"0X0000002E\": (\"DATA_BUS_ERROR\", \"RAM ya motherboard hardware fault\", \"RAM replace karo\"),\n            \"0X00000074\": (\"BAD_SYSTEM_CONFIG_INFO\", \"Registry corrupt hai\", \"Registry repair ya Windows repair chalao\"),\n            \"0X000000C4\": (\"DRIVER_VERIFIER_DETECTED_VIOLATION\", \"Driver Verifier ne faulty driver pakda\", \"Driver Verifier disable karo: verifier /reset\"),\n            \"0XC0000005\": (\"ACCESS_VIOLATION\", \"Program ne invalid memory access kiya\", \"Application reinstall karo\"),\n        }\n\n    def _bsod_on_select(self, event):\n        try:\n            sel = self.bsod_tree.selection()\n            if not sel:\n                return\n            r = self.bsod_rows[int(sel[0])]\n            name, explain, fix = self._bsod_stop_db().get(r[\"code\"].upper(), (\"Unknown Stop Code\", f\"Stop code database mein nahi - online search karo: {r['code']}\", \"Microsoft support aur driver history check karo\"))\n            text = f\"Date/Time: {r['time']}\\nEvent ID: {r['id']}\\nStop Code: {r['code']}\\nNaam: {name}\\n\\nSamjhaav: {explain}\\n\\nFix Steps:\\n1. {fix}\\n2. Recent driver/update check karo\\n3. RAM aur disk health test karo\\n\\nFull Message:\\n{r['msg'][:1200]}\"\n            self.bsod_detail.config(state=\"normal\")\n            self.bsod_detail.delete(\"1.0\", \"end\")\n            self.bsod_detail.insert(\"end\", text)\n            self.bsod_detail.config(state=\"disabled\")\n        except Exception as e:\n            self._append_log(self.bsod_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _bsod_open_dumps(self):\n        try:\n            os.startfile(r\"C:\\Windows\\Minidump\")\n        except Exception as e:\n            self._append_log(self.bsod_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _bsod_copy_dumps(self):\n        self._launch_job(\"bsod_copy_dumps\", self._bsod_copy_dumps_worker)\n\n    def _bsod_copy_dumps_worker(self):\n        try:\n            src = r\"C:\\Windows\\Minidump\"\n            dst = os.path.join(os.environ.get(\"USERPROFILE\", \"\"), \"Desktop\", \"Minidumps\")\n            os.makedirs(dst, exist_ok=True)\n            count = 0\n            if os.path.isdir(src):\n                for fn in os.listdir(src):\n                    if fn.lower().endswith(\".dmp\"):\n                        shutil.copy2(os.path.join(src, fn), os.path.join(dst, fn))\n                        count += 1\n            self._append_log(self.bsod_log, f\"\u2705 Kaam ho gaya: {count} dump files copy ho gaye\", C[\"success\"])\n        except Exception as e:\n            self._append_log(self.bsod_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _bsod_export_report(self):\n        try:\n            path = os.path.join(os.environ.get(\"USERPROFILE\", \"\"), \"Desktop\", f\"Godawari_BSOD_Report_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.txt\")\n            with open(path, \"w\", encoding=\"utf-8\") as f:\n                for r in getattr(self, \"bsod_rows\", []):\n                    f.write(f\"{r['time']} | {r['id']} | {r['code']} | {r['desc']}\\n{r['msg']}\\n\\n\")\n            messagebox.showinfo(\"Kaam ho gaya\", f\"BSOD report save ho gayi:\\n{path}\")\n        except Exception as e:\n            self._append_log(self.bsod_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _bsod_clear_events(self):\n        if messagebox.askyesno(\"Confirm karo\", \"System event log clear karna destructive action hai. Kya continue karna hai?\"):\n            self._launch_job(\"bsod_clear_events\", lambda: self._append_log(self.bsod_log, f\"Result: {self._run_cmd('wevtutil cl System', timeout=60)[0]}\", C[\"warning\"]))\n\n    def _bsod_search_online(self, stop_code):\n        try:\n            os.startfile(f\"https://www.google.com/search?q=BSOD+{stop_code}+fix\")\n        except Exception as e:\n            self._append_log(self.bsod_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _build_corrupt_wizard(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"Corrupt Windows Repair Wizard\", \"Step-by-step SFC, DISM aur CBS analysis\")\n        content = self._scrollable_section_body(frame)\n        self.corrupt_results = {}\n        self.corrupt_indicator = tk.Frame(content, bg=C[\"bg\"])\n        self.corrupt_indicator.pack(fill=\"x\", padx=14, pady=8)\n        self.corrupt_content = tk.Frame(content, bg=C[\"card\"])\n        self.corrupt_content.pack(fill=\"both\", expand=True, padx=14, pady=8)\n        self.corrupt_log = self._scrolled_text(content, height=8)\n        nav = tk.Frame(content, bg=C[\"bg\"])\n        nav.pack(fill=\"x\", padx=14, pady=6)\n        self._btn(nav, \"\u21a9 Back\", C[\"btn_chip\"], self._corrupt_wizard_back).pack(side=\"left\", padx=4)\n        self._btn(nav, \"\u25b6 Next Step\", C[\"btn_info\"], self._corrupt_wizard_next).pack(side=\"left\", padx=4)\n        self._btn(nav, \"\u23ed Skip Step\", C[\"btn_warn\"], self._corrupt_wizard_skip).pack(side=\"left\", padx=4)\n        self._btn(nav, \"\u23f9 Stop\", C[\"btn_danger\"], self._corrupt_wizard_stop).pack(side=\"left\", padx=4)\n        self._corrupt_wizard_show_step(1)\n        return frame\n\n    def _corrupt_wizard_build_step_indicator(self, parent):\n        for w in parent.winfo_children():\n            w.destroy()\n        for i in range(1, 7):\n            color = C[\"accent\"] if i == self._corrupt_wizard_step else (C[\"success\"] if i &lt; self._corrupt_wizard_step else C[\"border\"])\n            tk.Label(parent, text=f\"  {i}  \", font=FONTS[\"subhead\"], fg=C[\"text\"], bg=color).pack(side=\"left\", padx=6, pady=4)\n        tk.Label(parent, text=f\"Step {self._corrupt_wizard_step} of 6\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"bg\"]).pack(side=\"left\", padx=14)\n\n    def _corrupt_wizard_show_step(self, step_num):\n        self._corrupt_wizard_step = max(1, min(6, int(step_num)))\n        self._corrupt_wizard_build_step_indicator(self.corrupt_indicator)\n        for w in self.corrupt_content.winfo_children():\n            w.destroy()\n        getattr(self, f\"_corrupt_wizard_build_step{self._corrupt_wizard_step}\")(self.corrupt_content)\n\n    def _corrupt_step_label(self, parent, title, body):\n        tk.Label(parent, text=title, font=(\"Segoe UI\", 16, \"bold\"), fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=14, pady=(14,4))\n        tk.Label(parent, text=body, font=FONTS[\"body\"], fg=C[\"text\"], bg=C[\"card\"], wraplength=900, justify=\"left\").pack(anchor=\"w\", padx=14, pady=(0,10))\n\n    def _corrupt_wizard_build_step1(self, parent):\n        self._corrupt_step_label(parent, \"Pre-Check &amp; Restore Point\", \"Repair shuru karne se pehle admin, free space aur Windows version check hota hai.\")\n        self._btn(parent, \"Pre-check chalao\", C[\"btn_info\"], lambda: self._launch_job(\"corrupt_precheck\", self._corrupt_check_prerequisites)).pack(anchor=\"w\", padx=14)\n        self._btn(parent, \"Restore Point banao\", C[\"btn_warn\"], lambda: self._launch_job(\"corrupt_restore_point\", lambda: self._append_log(self.corrupt_log, self._run_cmd('wmic.exe /Namespace:\\\\\\\\root\\\\default Path SystemRestore Call CreateRestorePoint \"Before Corrupt Windows Repair\", 100, 7', timeout=120)[0], C[\"warning\"]))).pack(anchor=\"w\", padx=14, pady=6)\n\n    def _corrupt_wizard_build_step2(self, parent):\n        self._corrupt_step_label(parent, \"SFC Scan\", \"Windows system files check karta hai aur corrupt files repair karne ki koshish karta hai.\")\n        self._btn(parent, \"Run SFC\", C[\"btn_info\"], lambda: self._launch_job(\"corrupt_sfc_1\", self._do_corrupt_sfc_scan, 2)).pack(anchor=\"w\", padx=14)\n\n    def _corrupt_wizard_build_step3(self, parent):\n        self._corrupt_step_label(parent, \"DISM RestoreHealth\", \"Windows image repair karta hai. Internet connection helpful hota hai.\")\n        self._btn(parent, \"Run DISM\", C[\"btn_danger\"], lambda: self._launch_job(\"corrupt_dism\", self._do_corrupt_dism)).pack(anchor=\"w\", padx=14)\n\n    def _corrupt_wizard_build_step4(self, parent):\n        self._corrupt_step_label(parent, \"SFC Re-scan\", \"DISM ke baad SFC dobara chalao taaki files final verify ho sakein.\")\n        self._btn(parent, \"Run SFC Dobara\", C[\"btn_info\"], lambda: self._launch_job(\"corrupt_sfc_2\", self._do_corrupt_sfc_scan, 4)).pack(anchor=\"w\", padx=14)\n\n    def _corrupt_wizard_build_step5(self, parent):\n        self._corrupt_step_label(parent, \"CBS Log Analysis\", \"CBS.log se exact corrupt file names nikaale jaate hain.\")\n        self._btn(parent, \"Analyze CBS Log\", C[\"btn_chip\"], lambda: self._launch_job(\"corrupt_cbs\", self._do_corrupt_cbs_analysis)).pack(anchor=\"w\", padx=14)\n        wrap, self.corrupt_cbs_tree = self._adv_tree(parent, [\"File Naam\", \"Path\", \"Status\"], height=8)\n        wrap.pack(fill=\"both\", expand=True, padx=14, pady=10)\n\n    def _corrupt_wizard_build_step6(self, parent):\n        self._corrupt_step_label(parent, \"Result &amp; Next Steps\", \"Repair run ka summary aur advanced recovery options.\")\n        for label, cmd in [(\"Open WinRE\", \"reagentc /boottore\"), (\"Safe Mode Enable\", \"bcdedit /set {current} safeboot minimal\"), (\"chkdsk Schedule\", \"chkdsk C: /f /r /x\"), (\"System Reset Option\", \"ms-settings:recovery\")]:\n            self._btn(parent, label, C[\"btn_warn\"], lambda c=cmd: self._run_cmd(c, timeout=120)).pack(side=\"left\", padx=8, pady=12)\n        self._btn(parent, \"Repair Report Save\", C[\"btn\"], self._corrupt_save_report).pack(side=\"left\", padx=8, pady=12)\n\n    def _corrupt_wizard_next(self):\n        self._corrupt_wizard_show_step(self._corrupt_wizard_step + 1)\n\n    def _corrupt_wizard_back(self):\n        self._corrupt_wizard_show_step(self._corrupt_wizard_step - 1)\n\n    def _corrupt_wizard_skip(self):\n        self._append_log(self.corrupt_log, f\"Step {self._corrupt_wizard_step} skip ho gaya\", C[\"warning\"])\n        self._corrupt_wizard_next()\n\n    def _corrupt_wizard_stop(self):\n        self._corrupt_wizard_running = False\n        self._append_log(self.corrupt_log, \"Stop request set ho gaya. Running command khatam hone par rukega.\", C[\"warning\"])\n\n    def _do_corrupt_sfc_scan(self, step):\n        try:\n            self._corrupt_wizard_running = True\n            out, rc = self._run_cmd(\"sfc /scannow\", timeout=3600)\n            result, color = self._corrupt_parse_sfc_result(out)\n            self.corrupt_results[f\"sfc_{step}\"] = result\n            self._append_log(self.corrupt_log, out[-3000:], color)\n            self._append_log(self.corrupt_log, result, color)\n        except Exception as e:\n            self._append_log(self.corrupt_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n        finally:\n            self._corrupt_wizard_running = False\n\n    def _do_corrupt_dism(self):\n        try:\n            out, rc = self._run_cmd(\"DISM /Online /Cleanup-Image /RestoreHealth /NoRestart\", timeout=3600)\n            ok = \"restore operation completed successfully\" in out.lower()\n            self.corrupt_results[\"dism\"] = \"DISM success\" if ok else \"DISM warning\"\n            self._append_log(self.corrupt_log, out[-3000:], C[\"success\"] if ok else C[\"warning\"])\n        except Exception as e:\n            self._append_log(self.corrupt_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _do_corrupt_cbs_analysis(self):\n        try:\n            rows = self._corrupt_parse_cbs_log()\n            def fill():\n                if hasattr(self, \"corrupt_cbs_tree\"):\n                    self.corrupt_cbs_tree.delete(*self.corrupt_cbs_tree.get_children())\n                    for r in rows:\n                        self.corrupt_cbs_tree.insert(\"\", \"end\", values=r)\n                self._append_log(self.corrupt_log, f\"\u2705 Kaam ho gaya: {len(rows)} CBS entries mile\", C[\"success\"] if not rows else C[\"warning\"])\n            self.after(0, fill)\n        except Exception as e:\n            self._append_log(self.corrupt_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _corrupt_parse_sfc_result(self, output):\n        low = (output or \"\").lower()\n        if \"did not find any integrity violations\" in low:\n            return \"\u2705 Corruption nahi mila\", C[\"success\"]\n        if \"found corrupt files and successfully repaired\" in low or \"repaired them\" in low:\n            return \"\u2705 Files automatically fix ho gayi\", C[\"success\"]\n        if \"unable to fix\" in low or \"unable to repair\" in low:\n            return \"\u26a0 Repair needed - Step 3 DISM chalao\", C[\"error\"]\n        if \"could not perform\" in low:\n            return \"\u26a0 Admin mode required ho sakta hai\", C[\"warning\"]\n        return \"SFC result clear nahi hai - log check karo\", C[\"warning\"]\n\n    def _corrupt_parse_cbs_log(self):\n        rows = []\n        path = r\"C:\\Windows\\Logs\\CBS\\CBS.log\"\n        if not os.path.exists(path):\n            return rows\n        with open(path, \"r\", encoding=\"utf-8\", errors=\"ignore\") as f:\n            for line in f:\n                if \"[SR]\" not in line:\n                    continue\n                name = None\n                for pat in [r\"\\[SR\\].*?Cannot repair member file \\[l:.*?\\](.+?),\", r\"\\[SR\\] Repairing (.+?) \\.\", r\"Cannot repair member file.*?\\\\(.+?)$\"]:\n                    m = re.search(pat, line)\n                    if m:\n                        name = m.group(1).strip().strip('\"')\n                        break\n                if name:\n                    rows.append((os.path.basename(name), name, \"CBS mein mention\"))\n                if len(rows) &gt;= 200:\n                    break\n        return rows\n\n    def _corrupt_check_prerequisites(self):\n        try:\n            admin = bool(ctypes.windll.shell32.IsUserAnAdmin())\n            free = shutil.disk_usage(\"C:\\\\\").free\n            ver = platform.platform()\n            self._append_log(self.corrupt_log, f\"Admin: {'Haan' if admin else 'Nahi'}\", C[\"success\"] if admin else C[\"error\"])\n            self._append_log(self.corrupt_log, f\"C free space: {self._fmt_size_disk(free)}\", C[\"success\"] if free &gt; 2*1024*1024*1024 else C[\"error\"])\n            self._append_log(self.corrupt_log, f\"Windows: {ver}\", C[\"accent\"])\n        except Exception as e:\n            self._append_log(self.corrupt_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _corrupt_save_report(self):\n        try:\n            path = os.path.join(os.environ.get(\"USERPROFILE\", \"\"), \"Desktop\", f\"Godawari_Repair_Report_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.txt\")\n            text = self.corrupt_log.get(\"1.0\", \"end\")\n            with open(path, \"w\", encoding=\"utf-8\") as f:\n                f.write(text)\n            messagebox.showinfo(\"Kaam ho gaya\", f\"Repair report save ho gayi:\\n{path}\")\n        except Exception as e:\n            self._append_log(self.corrupt_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _build_password_audit(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"Password &amp; Security Audit\", \"Accounts, firewall, BitLocker aur failed login check\")\n        content = self._scrollable_section_body(frame)\n        self._action_card_grid(content, [\n            (\"\ud83d\udd0d\", \"Full Scan\", \"Poora security audit chalao\", C[\"btn_info\"], self._sec_full_scan),\n            (\"\ud83d\udd12\", \"Firewall On\", \"Saare firewall profiles on karo\", C[\"btn_danger\"], self._sec_enable_firewall),\n            (\"\ud83d\udc65\", \"Guest Fix\", \"Guest account disable karo\", C[\"btn_warn\"], self._sec_fix_guest),\n            (\"\ud83d\udcbe\", \"Report Export\", \"Security report save karo\", C[\"btn\"], self._sec_export_report),\n            (\"\ud83d\udd11\", \"Password Reset\", \"Selected account ka password reset karo\", C[\"btn_chip\"], self._sec_reset_selected_password),\n        ], cols=5)\n        self.sec_summary = tk.Frame(content, bg=C[\"bg\"])\n        self.sec_summary.pack(fill=\"x\", padx=14)\n        self.sec_summary_labels = []\n        for title in [\"Local Accounts\", \"Security Issues\", \"Firewall\", \"BitLocker\"]:\n            card = self._stat_card(self.sec_summary, title, \"Scan pending\", C[\"accent\"])\n            card.pack(side=\"left\", fill=\"x\", expand=True, padx=5, pady=6)\n            self.sec_summary_labels.append(card._value_lbl)\n        nb = ttk.Notebook(content)\n        nb.pack(fill=\"both\", expand=True, padx=14, pady=8)\n        self.sec_trees = {}\n        for tab, cols in {\n            \"Accounts\": [\"Username\", \"Account Type\", \"Status\", \"Password Required\", \"Last Logon\", \"Risk\"],\n            \"Firewall\": [\"Profile\", \"State\", \"Inbound\", \"Outbound\", \"Note\"],\n            \"BitLocker\": [\"Drive\", \"Status\", \"Protection\", \"Encryption\", \"Recovery Key\"],\n            \"Login Events\": [\"Time\", \"Username\", \"Logon Type\", \"Source IP\", \"Reason\"],\n        }.items():\n            pane = tk.Frame(nb, bg=C[\"card\"])\n            nb.add(pane, text=tab)\n            wrap, tree = self._adv_tree(pane, cols, height=10)\n            wrap.pack(fill=\"both\", expand=True, padx=8, pady=8)\n            self.sec_trees[tab] = tree\n        self.sec_reco = self._scrolled_text(content, height=5)\n        self.sec_log = self._scrolled_text(content, height=5)\n        self.sec_data = {}\n        return frame\n\n    def _sec_full_scan(self):\n        self._launch_job(\"security_full_scan\", self._do_sec_full_scan)\n\n    def _do_sec_full_scan(self):\n        try:\n            data = {\"accounts\": self._sec_scan_accounts(), \"firewall\": self._sec_scan_firewall(), \"bitlocker\": self._sec_scan_bitlocker(), \"login\": self._sec_scan_login_events()}\n            self.sec_data = data\n            self.after(0, lambda: (self._sec_populate_accounts_tab(data[\"accounts\"]), self._sec_populate_firewall_tab(data[\"firewall\"]), self._sec_populate_bitlocker_tab(data[\"bitlocker\"]), self._sec_populate_login_tab(data[\"login\"]), self._sec_generate_recommendations(data)))\n        except Exception as e:\n            self._append_log(self.sec_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _sec_scan_accounts(self):\n        out, rc = self._run_cmd('powershell -NoProfile -Command \"Get-LocalUser | Select-Object Name,Enabled,PasswordRequired,LastLogon | ConvertTo-Json\"', timeout=80)\n        users = json.loads(out) if out.strip().startswith((\"{\", \"[\")) else []\n        if isinstance(users, dict):\n            users = [users]\n        admins_out, _ = self._run_cmd(\"net localgroup Administrators\", timeout=40)\n        return {\"users\": users, \"admins_text\": admins_out}\n\n    def _sec_scan_firewall(self):\n        out, rc = self._run_cmd(\"netsh advfirewall show allprofiles\", timeout=60)\n        return out\n\n    def _sec_scan_bitlocker(self):\n        rows = []\n        string_mod = __import__(\"string\")\n        for d in string_mod.ascii_uppercase:\n            drive = f\"{d}:\"\n            if os.path.exists(drive + \"\\\\\"):\n                out, rc = self._run_cmd(f\"manage-bde -status {drive}\", timeout=45)\n                rows.append((drive, out))\n        return rows\n\n    def _sec_scan_login_events(self):\n        out, rc = self._run_cmd(\"powershell -NoProfile -Command \\\"Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4625} -MaxEvents 30 -ErrorAction SilentlyContinue | Select-Object TimeCreated, Message | ConvertTo-Json\\\"\", timeout=90)\n        try:\n            data = json.loads(out) if out.strip() else []\n            return [data] if isinstance(data, dict) else data\n        except Exception:\n            return []\n\n    def _sec_populate_accounts_tab(self, data):\n        tree = self.sec_trees[\"Accounts\"]\n        tree.delete(*tree.get_children())\n        admins = data.get(\"admins_text\", \"\")\n        risks = 0\n        for u in data.get(\"users\", []):\n            name = u.get(\"Name\", \"\")\n            is_admin = name and name.lower() in admins.lower()\n            enabled = bool(u.get(\"Enabled\"))\n            pwd = bool(u.get(\"PasswordRequired\"))\n            risk = \"OK\"\n            if name.lower() == \"guest\" and enabled:\n                risk = \"HIGH\"\n            elif not pwd:\n                risk = \"MEDIUM\"\n            if risk != \"OK\":\n                risks += 1\n            tree.insert(\"\", \"end\", values=(name, \"Admin\" if is_admin else \"User\", \"Enabled\" if enabled else \"Disabled\", \"Haan\" if pwd else \"Nahi\", str(u.get(\"LastLogon\", \"\"))[:19], risk))\n        self.sec_summary_labels[0].config(text=f\"{len(data.get('users', []))} users\")\n        self.sec_summary_labels[1].config(text=f\"{risks} issues\")\n\n    def _sec_populate_firewall_tab(self, data):\n        tree = self.sec_trees[\"Firewall\"]\n        tree.delete(*tree.get_children())\n        on_count = len(re.findall(r\"State\\s+ON\", data, re.I))\n        for profile in [\"Domain\", \"Private\", \"Public\"]:\n            m = re.search(profile + r\".*?State\\s+(\\w+).*?Firewall Policy\\s+([^\\r\\n]+)\", data, re.I | re.S)\n            state = m.group(1) if m else \"Unknown\"\n            policy = m.group(2) if m else \"Nahi mila\"\n            tree.insert(\"\", \"end\", values=(profile, state, policy, policy, \"Firewall profile\"))\n        self.sec_summary_labels[2].config(text=\"All ON\" if on_count &gt;= 3 else \"Partially OFF\")\n\n    def _sec_populate_bitlocker_tab(self, data):\n        tree = self.sec_trees[\"BitLocker\"]\n        tree.delete(*tree.get_children())\n        protected = 0\n        for drive, out in data:\n            conv = re.search(r\"Conversion Status:\\s+(.+)\", out)\n            prot = re.search(r\"Protection Status:\\s+(.+)\", out)\n            enc = re.search(r\"Encryption Method:\\s+(.+)\", out)\n            ptxt = prot.group(1).strip() if prot else \"Unknown\"\n            if \"On\" in ptxt:\n                protected += 1\n            tree.insert(\"\", \"end\", values=(drive, conv.group(1).strip() if conv else \"Unknown\", ptxt, enc.group(1).strip() if enc else \"Unknown\", \"Check needed\"))\n        self.sec_summary_labels[3].config(text=f\"{protected}/{len(data)} protected\")\n\n    def _sec_populate_login_tab(self, data):\n        tree = self.sec_trees[\"Login Events\"]\n        tree.delete(*tree.get_children())\n        for ev in data:\n            msg = ev.get(\"Message\", \"\") or \"\"\n            user = re.search(r\"Account Name:\\s+([^\\r\\n]+)\", msg)\n            typ = re.search(r\"Logon Type:\\s+(\\d+)\", msg)\n            ip = re.search(r\"Source Network Address:\\s+([^\\r\\n]+)\", msg)\n            reason = re.search(r\"Failure Reason:\\s+([^\\r\\n]+)\", msg)\n            tree.insert(\"\", \"end\", values=(str(ev.get(\"TimeCreated\", \"\"))[:19], user.group(1).strip() if user else \"Nahi mila\", typ.group(1) if typ else \"Nahi\", ip.group(1).strip() if ip else \"-\", reason.group(1).strip() if reason else \"-\"))\n\n    def _sec_generate_recommendations(self, all_data):\n        recs = []\n        users = all_data.get(\"accounts\", {}).get(\"users\", [])\n        guest = [u for u in users if str(u.get(\"Name\", \"\")).lower() == \"guest\" and u.get(\"Enabled\")]\n        no_pwd = [u.get(\"Name\") for u in users if not u.get(\"PasswordRequired\")]\n        if guest:\n            recs.append(\"\u274c Guest account immediately disable karo\")\n        if no_pwd:\n            recs.append(\"\u274c In accounts ko password lagao: \" + \", \".join(map(str, no_pwd)))\n        if \"State                                 OFF\" in all_data.get(\"firewall\", \"\"):\n            recs.append(\"\u274c Windows Firewall enable karo\")\n        if not recs:\n            recs.append(\"\u2705 Major security issue nahi mila\")\n        self.sec_reco.config(state=\"normal\")\n        self.sec_reco.delete(\"1.0\", \"end\")\n        self.sec_reco.insert(\"end\", \"\\n\".join(recs))\n        self.sec_reco.config(state=\"disabled\")\n        self._append_log(self.sec_log, \"\u2705 Kaam ho gaya: Security audit complete\", C[\"success\"])\n\n    def _sec_enable_firewall(self):\n        if messagebox.askyesno(\"Confirm karo\", \"Saare firewall profiles ON karne hain?\"):\n            self._launch_job(\"sec_firewall_on\", lambda: self._append_log(self.sec_log, self._run_cmd(\"netsh advfirewall set allprofiles state on\", timeout=60)[0], C[\"success\"]))\n\n    def _sec_fix_guest(self):\n        if messagebox.askyesno(\"Confirm karo\", \"Guest account disable karna hai?\"):\n            self._launch_job(\"sec_guest_fix\", lambda: self._append_log(self.sec_log, self._run_cmd(\"net user Guest /active:no\", timeout=60)[0], C[\"success\"]))\n\n    def _sec_export_report(self):\n        try:\n            path = os.path.join(os.environ.get(\"USERPROFILE\", \"\"), \"Desktop\", f\"Godawari_Security_Report_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.json\")\n            with open(path, \"w\", encoding=\"utf-8\") as f:\n                json.dump(getattr(self, \"sec_data\", {}), f, indent=2, ensure_ascii=False, default=str)\n            messagebox.showinfo(\"Kaam ho gaya\", f\"Security report save ho gayi:\\n{path}\")\n        except Exception as e:\n            self._append_log(self.sec_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _sec_account_action(self, action, username):\n        cmds = {\"enable\": f\"net user {username} /active:yes\", \"disable\": f\"net user {username} /active:no\", \"require_password\": f\"net user {username} /passwordreq:yes\", \"remove_admin\": f\"net localgroup Administrators {username} /delete\"}\n        if action in cmds and messagebox.askyesno(\"Confirm karo\", f\"{username} par action apply karna hai?\"):\n            self._launch_job(\"sec_account_action\", lambda: self._append_log(self.sec_log, self._run_cmd(cmds[action], timeout=60)[0], C[\"warning\"]))\n\n    def _sec_reset_selected_password(self):\n        \"\"\"Reset password for selected account. PASSWORD FIELD IS OPTIONAL.\n        \n        ENGINEERING FIX #2: Allow empty password input to be treated as 'skip' or 'no-password mode'.\n        Empty input no longer triggers a validation error - user can choose to skip password reset.\n        \"\"\"\n        try:\n            tree = self.sec_trees.get(\"Accounts\") if hasattr(self, \"sec_trees\") else None\n            if tree is None:\n                messagebox.showwarning(\"Account select karo\", \"Pehle Security Scan chalao aur account select karo\")\n                return\n            sel = tree.selection()\n            if not sel:\n                messagebox.showwarning(\"Account select karo\", \"Pehle Accounts tab mein user select karo\")\n                return\n            username = tree.item(sel[0], \"values\")[0]\n            if not username:\n                messagebox.showwarning(\"User nahi mila\", \"Selected account ka username nahi mila\")\n                return\n            \n            simpledialog = __import__(\"tkinter.simpledialog\", fromlist=[\"askstring\"])\n            \n            # FIX: Password is now OPTIONAL - user can enter empty password to skip\n            new_password = simpledialog.askstring(\n                \"Naya password\",\n                f\"{username} ke liye naya password daalo:\\n\\n(Khali chhod ke OK karo to skip ho jayega)\",\n                show=\"*\"\n            )\n            if new_password is None:\n                # User clicked Cancel - operation aborted\n                return\n            \n            # FIX: Empty password is now ACCEPTED as 'skip' or 'no-password' mode\n            if not new_password:\n                # User entered empty password - ask if they want to skip OR set no password\n                choice = messagebox.askyesnocancel(\n                    \"Password Reset - Confirmation\",\n                    f\"Blank password entry for {username}:\\n\\n\"\n                    \"Yes = Set empty password (no-password mode)\\n\"\n                    \"No = Skip this account\\n\"\n                    \"Cancel = Go back and enter password\"\n                )\n                if choice is None:\n                    # User clicked Cancel - go back to ask for password again\n                    self._sec_reset_selected_password()\n                    return\n                elif choice is False:\n                    # User clicked No - skip this account\n                    messagebox.showinfo(\"Skipped\", f\"Password reset skipped for {username}\")\n                    return\n                # choice is True - proceed with empty password (no-password mode)\n            else:\n                # User entered a password - confirm it\n                confirm_password = simpledialog.askstring(\n                    \"Password confirm\",\n                    \"Naya password dobara daalo:\",\n                    show=\"*\"\n                )\n                if confirm_password is None:\n                    return\n                if new_password != confirm_password:\n                    messagebox.showerror(\"Password match nahi\", \"Dono password same nahi hain\")\n                    return\n                if len(new_password) &lt; 6:\n                    if not messagebox.askyesno(\"Password weak hai\", \"Password 6 characters se chhota hai. Kya phir bhi set karna hai?\"):\n                        return\n            \n            # Final confirmation before executing password reset\n            mode_text = \"no-password mode\" if not new_password else \"set karna\"\n            if not messagebox.askyesno(\"Kya aap sure hain?\", f\"{username} ka password {mode_text} hai? Confirm karo?\"):\n                return\n            \n            self._launch_job(\"sec_password_reset\", self._do_sec_reset_password, username, new_password)\n        except Exception as e:\n            self._append_log(self.sec_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _do_sec_reset_password(self, username, new_password):\n        \"\"\"Execute password reset for the user account.\n        \n        ENGINEERING FIX #3: Handles both regular passwords AND empty passwords (no-password mode).\n        Empty password is accepted and processed without error.\n        \"\"\"\n        try:\n            # FIX: Support empty password for no-password mode\n            if new_password == \"\":\n                # No-password mode: set empty password using PowerShell\n                cmd = (\n                    f\"powershell -NoProfile -Command \"\n                    f'\"$user = [ADSI](\\'WinNT://./\\' + \\'{username}\\'); '\n                    f'$user.SetPassword(\\'\\'); $user.CommitChanges()\"'\n                )\n                out, rc = self._run_cmd(cmd, timeout=60)\n                success_msg = f\"\u2705 No-password mode set for {username}\"\n                user_msg = f\"No-password mode activated for {username}\"\n            else:\n                # Regular password reset using net user command\n                out, rc = self._run_cmd([\"net\", \"user\", username, new_password], timeout=60)\n                success_msg = f\"\u2705 Kaam ho gaya: {username} ka password reset ho gaya\"\n                user_msg = f\"{username} ka password reset ho gaya\"\n            \n            if rc == 0:\n                self._append_log(self.sec_log, success_msg, C[\"success\"])\n                self.after(0, lambda m=user_msg: messagebox.showinfo(\"Kaam ho gaya\", m))\n                self.after(500, self._sec_full_scan)\n            else:\n                error_text = out[:300] if out else \"Unknown error\"\n                self._append_log(self.sec_log, f\"Password reset nahi hua: {error_text}\", C[\"error\"])\n                self.after(0, lambda: messagebox.showerror(\n                    \"Password reset nahi hua\",\n                    f\"{username} ka password reset nahi hua.\\n{error_text}\"\n                ))\n        except Exception as e:\n            self._append_log(self.sec_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _build_auto_backup(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"Auto Backup\", \"Sources, destination, schedule aur registry backup\")\n        content = self._scrollable_section_body(frame)\n        top = tk.Frame(content, bg=C[\"bg\"])\n        top.pack(fill=\"x\", padx=14, pady=8)\n        src = self._adv_card(top, \"Backup Sources\")\n        src.pack(side=\"left\", fill=\"both\", expand=True, padx=(0,8))\n        self.backup_source_list = tk.Listbox(src, bg=C[\"card\"], fg=C[\"text\"], selectbackground=C[\"accent\"], height=8)\n        self.backup_source_list.pack(fill=\"both\", expand=True, padx=8, pady=8)\n        user = os.environ.get(\"USERPROFILE\", \"\")\n        if not self.backup_sources:\n            self.backup_sources = [os.path.join(user, x) for x in [\"Desktop\", \"Documents\", \"Downloads\", \"Pictures\"] if os.path.exists(os.path.join(user, x))]\n        for p in self.backup_sources:\n            self.backup_source_list.insert(\"end\", p)\n        self._btn(src, \"Custom Folder Add\", C[\"btn_chip\"], lambda: self._backup_add_source()).pack(side=\"left\", padx=8, pady=4)\n        self._btn(src, \"Selected Remove\", C[\"btn_warn\"], lambda: self._backup_remove_source()).pack(side=\"left\", padx=8, pady=4)\n        dst = self._adv_card(top, \"Destination &amp; Schedule\")\n        dst.pack(side=\"right\", fill=\"both\", expand=True, padx=(8,0))\n        tk.Entry(dst, textvariable=self.backup_dest_var, bg=C[\"panel\"], fg=C[\"text\"]).pack(fill=\"x\", padx=8, pady=4)\n        self._btn(dst, \"Browse\", C[\"btn_chip\"], lambda: self.backup_dest_var.set(filedialog.askdirectory() or self.backup_dest_var.get())).pack(anchor=\"w\", padx=8)\n        ttk.Combobox(dst, textvariable=self.backup_schedule_var, values=[\"Manual Only\", \"Daily\", \"Weekly\", \"Monthly\"], state=\"readonly\").pack(fill=\"x\", padx=8, pady=4)\n        tk.Entry(dst, textvariable=self.backup_time_var, bg=C[\"panel\"], fg=C[\"text\"]).pack(fill=\"x\", padx=8, pady=4)\n        modes = self._adv_card(content, \"\ud83d\udcc1 Overwrite Mode - Backup Size Control\")\n        modes.pack(fill=\"x\", padx=14, pady=6)\n        for val, txt in [(\"mirror\", \"\u267b Overwrite Previous (Mirror) - size same rahega\"), (\"versioned\", \"\ud83d\udcc5 Keep Last N Versions - purane auto delete\"), (\"incremental\", \"\u26a1 Incremental - sirf changed files\")]:\n            tk.Radiobutton(modes, text=txt, variable=self.backup_overwrite_mode, value=val, bg=C[\"card\"], fg=C[\"text\"], selectcolor=C[\"panel\"], activebackground=C[\"card\"]).pack(anchor=\"w\", padx=8)\n        tk.Spinbox(modes, from_=1, to=10, textvariable=self.backup_keep_n, width=5, bg=C[\"panel\"], fg=C[\"text\"]).pack(anchor=\"w\", padx=28, pady=2)\n        reg = self._adv_card(content, \"\ud83d\uddc2 Registry Auto-Backup (RegBack)\")\n        reg.pack(fill=\"x\", padx=14, pady=6)\n        tk.Checkbutton(reg, text=\"RegBack enable rakho\", variable=self.regback_enabled, bg=C[\"card\"], fg=C[\"text\"], selectcolor=C[\"panel\"]).pack(anchor=\"w\", padx=8)\n        tk.Label(reg, text=\"Windows crash ho jaaye to restore ke liye SYSTEM, SOFTWARE, SAM, SECURITY, DEFAULT hives backup honge\", fg=C[\"warning\"], bg=C[\"card\"], font=FONTS[\"small\"], wraplength=1050, justify=\"left\").pack(anchor=\"w\", padx=8)\n        self._action_card_grid(content, [\n            (\"\u25b6\", \"Backup Now\", \"Abhi backup chalao\", C[\"btn_info\"], self._backup_run_now),\n            (\"\ud83d\udcc5\", \"Schedule Enable\", \"Task Scheduler mein add karo\", C[\"btn_chip\"], self._backup_schedule_enable),\n            (\"\u274c\", \"Schedule Remove\", \"Scheduled task hatao\", C[\"btn_warn\"], self._backup_schedule_remove),\n            (\"\ud83d\udcc2\", \"Folder Kholo\", \"Backup folder kholo\", C[\"accent2\"], self._backup_open_folder),\n            (\"\ud83d\udcbe\", \"Config Save\", \"Settings save karo\", C[\"btn\"], self._backup_save_config),\n            (\"\ud83d\udcc2\", \"Config Load\", \"Settings load karo\", C[\"btn_chip\"], self._backup_load_config),\n        ], cols=6)\n        # \u2500\u2500 Progress bar \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        prog_card = self._adv_card(content, \"\ud83d\udcca Backup Progress\")\n        prog_card.pack(fill=\"x\", padx=14, pady=4)\n        self.backup_progress_var = tk.DoubleVar(value=0.0)\n        self.backup_progress_bar = ttk.Progressbar(\n            prog_card, variable=self.backup_progress_var,\n            maximum=100, mode=\"determinate\")\n        self.backup_progress_bar.pack(fill=\"x\", padx=12, pady=(4, 2))\n        self.backup_status_lbl = tk.Label(\n            prog_card, text=\"Ready \u2014 'Backup Now' press karo\",\n            font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"])\n        self.backup_status_lbl.pack(anchor=\"w\", padx=12, pady=(0, 6))\n        # \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        wrap, self.backup_history_tree = self._adv_tree(content, [\"#\", \"Date Time\", \"Mode\", \"Sources\", \"Destination\", \"Total Size\", \"Status\", \"Duration\"], height=6)\n        wrap.pack(fill=\"x\", padx=14, pady=6)\n        self.backup_log = self._scrolled_text(content, height=6)\n        self._backup_load_config(silent=True)\n        self._backup_refresh_history()\n        return frame\n\n    def _backup_add_source(self):\n        p = filedialog.askdirectory()\n        if p:\n            self.backup_sources.append(p)\n            self.backup_source_list.insert(\"end\", p)\n\n    def _backup_remove_source(self):\n        try:\n            idx = self.backup_source_list.curselection()\n            if idx:\n                self.backup_sources.pop(idx[0])\n                self.backup_source_list.delete(idx[0])\n        except Exception as e:\n            self._append_log(self.backup_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _backup_run_now(self):\n        try:\n            dest = self.backup_dest_var.get().strip()\n            sources = self._backup_get_selected_sources()\n            mode = self.backup_overwrite_mode.get()\n            keep_n = int(self.backup_keep_n.get())\n            regback = bool(self.regback_enabled.get())\n            self._launch_job(\"auto_backup_now\", self._do_run_backup, dest, sources, mode, keep_n, regback)\n        except Exception as e:\n            self._append_log(self.backup_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _do_run_backup(self, dest=None, sources=None, mode=None, keep_n=None, regback_enabled=None):\n        def _set_status(msg, pct=None, color=None):\n            try:\n                self.after(0, lambda m=msg, c=color or C[\"text_dim\"]:\n                           self.backup_status_lbl.config(text=m, fg=c)\n                           if False else None)\n                self.after(0, lambda m=msg, c=color or C[\"text_dim\"]:\n                           self.backup_status_lbl.config(text=m, fg=c))\n                if pct is not None:\n                    self.after(0, lambda p=float(pct): self.backup_progress_var.set(p))\n            except Exception:\n                pass\n\n        def _set_indeterminate(on=True):\n            try:\n                if on:\n                    self.after(0, lambda: self.backup_progress_bar.config(mode=\"indeterminate\"))\n                    self.after(50, lambda: self.backup_progress_bar.start(12))\n                else:\n                    self.after(0, lambda: self.backup_progress_bar.stop())\n                    self.after(0, lambda: self.backup_progress_bar.config(mode=\"determinate\"))\n            except Exception:\n                pass\n\n        try:\n            dest = (dest or \"\").strip()\n            sources = list(sources or [])\n            if not dest or not os.path.isdir(dest):\n                self._append_log(self.backup_log, \"Pehle valid destination folder select karo\", C[\"error\"])\n                _set_status(\"\u274c Destination folder invalid hai\", color=C[\"error\"])\n                return\n            if not sources:\n                self._append_log(self.backup_log, \"Pehle backup source select karo\", C[\"error\"])\n                _set_status(\"\u274c Koi source select nahi kiya\", color=C[\"error\"])\n                return\n\n            start = time.time()\n            timestamp = datetime.datetime.now().strftime(\"%Y-%m-%d_%H-%M\")\n            mode = mode or \"mirror\"\n            base_dest = dest\n            if mode == \"versioned\":\n                base_dest = os.path.join(dest, f\"Backup_{timestamp}\")\n                os.makedirs(base_dest, exist_ok=True)\n\n            total_sources = len([s for s in sources if os.path.isdir(s)])\n            done_sources = 0\n\n            for source in sources:\n                if not os.path.isdir(source):\n                    self._append_log(self.backup_log, f\"\u26a0\ufe0f Skipped (not found): {source}\", C[\"warning\"])\n                    continue\n\n                src_name = os.path.basename(source.rstrip(\"\\\\/\")) or source\n                dest_sub = os.path.join(base_dest, src_name)\n\n                # Pre-count files for determinate progress\n                try:\n                    file_count = sum(len(files) for _, _, files in os.walk(source))\n                except Exception:\n                    file_count = 0\n\n                _set_status(f\"\ud83d\udcc2 Copying: {src_name}  ({done_sources+1}/{total_sources})  [{file_count} files]\",\n                            pct=(done_sources / max(1, total_sources)) * 85, color=C[\"accent4\"])\n                self._append_log(self.backup_log,\n                                 f\"\u25b6 Source: {source}  \u2192  {dest_sub}  ({file_count} files)\",\n                                 C[\"accent4\"])\n\n                flag = \"/MIR\" if mode == \"mirror\" else (\"/XO /E\" if mode == \"incremental\" else \"/E\")\n\n                # Stream robocopy output line by line for live feedback\n                try:\n                    startupinfo = subprocess.STARTUPINFO()\n                    startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW\n                    proc = subprocess.Popen(\n                        f'robocopy \"{source}\" \"{dest_sub}\" {flag} /R:2 /W:5 /NP /TEE',\n                        shell=True,\n                        stdout=subprocess.PIPE,\n                        stderr=subprocess.STDOUT,\n                        text=True,\n                        startupinfo=startupinfo,\n                    )\n                    copied = 0\n                    for line in proc.stdout:\n                        line = line.strip()\n                        if not line:\n                            continue\n                        # robocopy progress lines contain file names\n                        if any(x in line.lower() for x in [\"new file\", \"newer\", \"extra\", \"copying\"]):\n                            copied += 1\n                            if copied % 5 == 0 or file_count &lt;= 20:\n                                _set_status(\n                                    f\"\ud83d\udcc2 {src_name}: {copied} files copied\u2026\",\n                                    pct=min(85, (done_sources / max(1, total_sources)) * 85 +\n                                            min(15, (copied / max(1, file_count)) * 15)),\n                                    color=C[\"accent4\"]\n                                )\n                        # Log important lines only\n                        if any(x in line for x in [\"ERROR\", \"WARN\", \"Access is denied\", \"Failed\"]):\n                            self._append_log(self.backup_log, f\"  \u26a0\ufe0f {line}\", C[\"warning\"])\n                    rc = proc.wait()\n                except Exception as pex:\n                    rc = -1\n                    self._append_log(self.backup_log, f\"\u26a0\ufe0f robocopy error: {pex}\", C[\"warning\"])\n\n                color = C[\"success\"] if rc &lt; 8 else C[\"warning\"]\n                self._append_log(self.backup_log,\n                                 f\"  \u2705 {src_name}: robocopy exit code {rc}  ({copied if 'copied' in dir() else '?'} files copied)\",\n                                 color)\n                done_sources += 1\n\n            # Versioned: cleanup old backups\n            if mode == \"versioned\":\n                glob_mod = __import__(\"glob\")\n                versions = sorted(glob_mod.glob(os.path.join(dest, \"Backup_*\")))\n                while len(versions) &gt; int(keep_n or 3):\n                    shutil.rmtree(versions.pop(0), ignore_errors=True)\n\n            # Registry backup\n            _set_status(\"\ud83d\uddc2 Registry backup chal raha hai\u2026\", pct=88, color=C[\"accent4\"])\n            reg_backup_path = \"\"\n            if bool(regback_enabled):\n                reg_backup_path = self._do_regback_backup(base_dest) or \"\"\n\n            # Final size\n            _set_status(\"\ud83d\udcca Size calculate ho raha hai\u2026\", pct=95, color=C[\"text_dim\"])\n            total = self._backup_calculate_size(base_dest)\n            dur = time.time() - start\n            status = \"Files + Registry\" if reg_backup_path else \"Files only\"\n\n            self._backup_add_history({\n                \"dt\": datetime.datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\"),\n                \"mode\": mode,\n                \"sources\": len(sources),\n                \"dest\": base_dest,\n                \"size\": f\"{total:.1f} MB\",\n                \"status\": status,\n                \"duration\": f\"{dur:.1f}s\"\n            })\n\n            _set_status(f\"\u2705 Backup complete! {total:.1f} MB  \u2022  {dur:.1f}s\", pct=100, color=C[\"success\"])\n            self._append_log(self.backup_log, f\"\u2705 Kaam ho gaya: Backup complete  [{total:.1f} MB, {dur:.1f}s]\", C[\"success\"])\n            if reg_backup_path:\n                self._append_log(self.backup_log, f\"Registry recovery backup: {reg_backup_path}\", C[\"success\"])\n            self.after(0, lambda: messagebox.showinfo(\"Kaam ho gaya\", f\"\u2705 Backup complete!\\n\\nSize: {total:.1f} MB\\nTime: {dur:.1f}s\\nDest: {base_dest}\"))\n\n        except Exception as e:\n            _set_indeterminate(False)\n            _set_status(f\"\u274c Error: {e}\", pct=0, color=C[\"error\"])\n            self._append_log(self.backup_log, f\"\u274c Error aaya: {str(e)}\", C[\"error\"])\n\n    def _do_regback_backup(self, dest_folder):\n        try:\n            stamp = datetime.datetime.now().strftime(\"%Y-%m-%d_%H-%M-%S\")\n            reg_dest = os.path.join(dest_folder, f\"Registry_Recovery_{stamp}\")\n            os.makedirs(reg_dest, exist_ok=True)\n            regback = r\"C:\\Windows\\System32\\config\\RegBack\"\n            names = [\"DEFAULT\", \"SAM\", \"SECURITY\", \"SOFTWARE\", \"SYSTEM\"]\n            manifest = {\n                \"created_at\": datetime.datetime.now().isoformat(timespec=\"seconds\"),\n                \"machine\": platform.node(),\n                \"windows\": platform.platform(),\n                \"method\": \"\",\n                \"files\": [],\n                \"restore_note\": \"WinRE Command Prompt se restore karne ke liye RESTORE_GUIDE_HINGLISH.txt padho.\",\n            }\n            if os.path.exists(os.path.join(regback, \"SYSTEM\")) and os.path.getsize(os.path.join(regback, \"SYSTEM\")) &gt; 0:\n                manifest[\"method\"] = \"RegBack folder copy\"\n                for n in names:\n                    src = os.path.join(regback, n)\n                    if os.path.exists(src):\n                        dst = os.path.join(reg_dest, f\"{n}.hiv\")\n                        shutil.copy2(src, dst)\n                        manifest[\"files\"].append(self._backup_registry_file_info(dst, n))\n                        self._append_log(self.backup_log, f\"{n} hive backup ho gaya\", C[\"success\"])\n            else:\n                manifest[\"method\"] = \"Live reg save\"\n                hive_cmds = [\n                    (\"SYSTEM\", \"HKLM\\\\SYSTEM\"),\n                    (\"SOFTWARE\", \"HKLM\\\\SOFTWARE\"),\n                    (\"SAM\", \"HKLM\\\\SAM\"),\n                    (\"SECURITY\", \"HKLM\\\\SECURITY\"),\n                    (\"DEFAULT\", \"HKU\\\\.DEFAULT\"),\n                ]\n                for hive_name, hive_key in hive_cmds:\n                    dst = os.path.join(reg_dest, f\"{hive_name}.hiv\")\n                    out, rc = self._run_cmd(f'reg save \"{hive_key}\" \"{dst}\" /y', timeout=180)\n                    if rc == 0 and os.path.exists(dst):\n                        manifest[\"files\"].append(self._backup_registry_file_info(dst, hive_name))\n                        self._append_log(self.backup_log, f\"{hive_name} hive backup ho gaya\", C[\"success\"])\n                    else:\n                        self._append_log(self.backup_log, f\"{hive_name} hive backup nahi hua: {out[:200]}\", C[\"warning\"])\n            self._backup_write_registry_restore_guide(reg_dest, manifest)\n            with open(os.path.join(reg_dest, \"registry_manifest.json\"), \"w\", encoding=\"utf-8\") as f:\n                json.dump(manifest, f, indent=2, ensure_ascii=False)\n            self._append_log(self.backup_log, \"Registry crash-recovery backup complete ho gaya\", C[\"success\"])\n            return reg_dest\n        except Exception as e:\n            self._append_log(self.backup_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n            return \"\"\n\n    def _backup_registry_file_info(self, path, hive_name):\n        try:\n            h = hashlib.sha256()\n            with open(path, \"rb\") as f:\n                for chunk in iter(lambda: f.read(1024 * 1024), b\"\"):\n                    h.update(chunk)\n            return {\n                \"hive\": hive_name,\n                \"file\": os.path.basename(path),\n                \"size_bytes\": os.path.getsize(path),\n                \"sha256\": h.hexdigest(),\n            }\n        except Exception as e:\n            return {\n                \"hive\": hive_name,\n                \"file\": os.path.basename(path),\n                \"size_bytes\": 0,\n                \"error\": str(e),\n            }\n\n    def _backup_write_registry_restore_guide(self, reg_dest, manifest):\n        try:\n            guide = os.path.join(reg_dest, \"RESTORE_GUIDE_HINGLISH.txt\")\n            lines = [\n                \"Godawari Computers - Registry Crash Recovery Guide\",\n                \"\",\n                \"Kab use kare:\",\n                \"- Windows boot nahi ho raha ho aur registry corrupt ka doubt ho.\",\n                \"- Pehle customer ka data backup verify karo.\",\n                \"- Ye advanced recovery hai. Galat hive restore karne se Windows aur kharab ho sakta hai.\",\n                \"\",\n                \"WinRE se restore ka tarika:\",\n                \"1. Windows Recovery Environment open karo.\",\n                \"2. Troubleshoot &gt; Advanced options &gt; Command Prompt kholo.\",\n                \"3. Windows drive letter confirm karo. WinRE mein C: kabhi-kabhi D: hota hai.\",\n                \"   Command: bcdedit | find \\\"osdevice\\\"\",\n                \"4. Existing registry hives ka backup banao:\",\n                \"   mkdir C:\\\\Windows\\\\System32\\\\config\\\\Godawari_BadRegistry_Backup\",\n                \"   copy C:\\\\Windows\\\\System32\\\\config\\\\SYSTEM C:\\\\Windows\\\\System32\\\\config\\\\Godawari_BadRegistry_Backup\\\\SYSTEM.bad\",\n                \"   copy C:\\\\Windows\\\\System32\\\\config\\\\SOFTWARE C:\\\\Windows\\\\System32\\\\config\\\\Godawari_BadRegistry_Backup\\\\SOFTWARE.bad\",\n                \"   copy C:\\\\Windows\\\\System32\\\\config\\\\SAM C:\\\\Windows\\\\System32\\\\config\\\\Godawari_BadRegistry_Backup\\\\SAM.bad\",\n                \"   copy C:\\\\Windows\\\\System32\\\\config\\\\SECURITY C:\\\\Windows\\\\System32\\\\config\\\\Godawari_BadRegistry_Backup\\\\SECURITY.bad\",\n                \"   copy C:\\\\Windows\\\\System32\\\\config\\\\DEFAULT C:\\\\Windows\\\\System32\\\\config\\\\Godawari_BadRegistry_Backup\\\\DEFAULT.bad\",\n                \"\",\n                \"5. Is backup folder se hives restore karo. BACKUP_PATH ko actual path se replace karo:\",\n                \"   copy /y BACKUP_PATH\\\\SYSTEM.hiv C:\\\\Windows\\\\System32\\\\config\\\\SYSTEM\",\n                \"   copy /y BACKUP_PATH\\\\SOFTWARE.hiv C:\\\\Windows\\\\System32\\\\config\\\\SOFTWARE\",\n                \"   copy /y BACKUP_PATH\\\\SAM.hiv C:\\\\Windows\\\\System32\\\\config\\\\SAM\",\n                \"   copy /y BACKUP_PATH\\\\SECURITY.hiv C:\\\\Windows\\\\System32\\\\config\\\\SECURITY\",\n                \"   copy /y BACKUP_PATH\\\\DEFAULT.hiv C:\\\\Windows\\\\System32\\\\config\\\\DEFAULT\",\n                \"\",\n                \"6. Restart karo:\",\n                \"   wpeutil reboot\",\n                \"\",\n                \"Important:\",\n                \"- Agar backup external drive par hai to pehle drive letter check karo: diskpart &gt; list volume\",\n                \"- SYSTEM aur SOFTWARE hives same backup set se restore karo.\",\n                \"- BitLocker enabled ho to recovery key ki zaroorat pad sakti hai.\",\n                \"\",\n                f\"Backup created at: {manifest.get('created_at', '')}\",\n                f\"Machine: {manifest.get('machine', '')}\",\n                f\"Windows: {manifest.get('windows', '')}\",\n                f\"Backup method: {manifest.get('method', '')}\",\n                \"\",\n                \"Files:\",\n            ]\n            for item in manifest.get(\"files\", []):\n                lines.append(f\"- {item.get('hive')}: {item.get('file')} | {item.get('size_bytes')} bytes | sha256 {item.get('sha256', '')}\")\n            with open(guide, \"w\", encoding=\"utf-8\") as f:\n                f.write(\"\\n\".join(lines))\n        except Exception as e:\n            self._append_log(self.backup_log, f\"Restore guide banane mein error aaya: {str(e)}\", C[\"warning\"])\n\n    def _backup_config_data(self):\n        return {\"sources\": self.backup_sources, \"dest\": self.backup_dest_var.get(), \"schedule\": self.backup_schedule_var.get(), \"time\": self.backup_time_var.get(), \"mode\": self.backup_overwrite_mode.get(), \"keep_n\": self.backup_keep_n.get(), \"regback\": self.regback_enabled.get(), \"history\": getattr(self, \"backup_history\", [])}\n\n    def _backup_save_config(self):\n        try:\n            os.makedirs(os.path.dirname(self.backup_config_file), exist_ok=True)\n            with open(self.backup_config_file, \"w\", encoding=\"utf-8\") as f:\n                json.dump(self._backup_config_data(), f, indent=2, ensure_ascii=False)\n            self._append_log(self.backup_log, \"\u2705 Kaam ho gaya: Config save ho gaya\", C[\"success\"])\n        except Exception as e:\n            self._append_log(self.backup_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _backup_load_config(self, silent=False):\n        try:\n            if os.path.exists(self.backup_config_file):\n                with open(self.backup_config_file, \"r\", encoding=\"utf-8\") as f:\n                    data = json.load(f)\n                self.backup_sources = data.get(\"sources\", self.backup_sources)\n                self.backup_dest_var.set(data.get(\"dest\", \"\"))\n                self.backup_schedule_var.set(data.get(\"schedule\", \"Manual Only\"))\n                self.backup_time_var.set(data.get(\"time\", \"02:00\"))\n                self.backup_overwrite_mode.set(data.get(\"mode\", \"mirror\"))\n                self.backup_keep_n.set(int(data.get(\"keep_n\", 3)))\n                self.regback_enabled.set(bool(data.get(\"regback\", True)))\n                self.backup_history = data.get(\"history\", [])\n                if hasattr(self, \"backup_source_list\"):\n                    self.backup_source_list.delete(0, \"end\")\n                    for p in self.backup_sources:\n                        self.backup_source_list.insert(\"end\", p)\n            if not silent:\n                self._append_log(self.backup_log, \"\u2705 Kaam ho gaya: Config load ho gaya\", C[\"success\"])\n        except Exception as e:\n            if not silent:\n                self._append_log(self.backup_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _backup_schedule_enable(self):\n        try:\n            sched = self.backup_schedule_var.get()\n            if sched == \"Manual Only\":\n                messagebox.showwarning(\"Schedule nahi hai\", \"Daily, Weekly ya Monthly select karo\")\n                return\n            script_path = sys.argv[0]\n            time_txt = self.backup_time_var.get()\n            sc = \"daily\" if sched == \"Daily\" else (\"weekly /d MON\" if sched == \"Weekly\" else \"monthly /d 1\")\n            cmd = f'schtasks /create /tn \"GodawariAutoBackup\" /tr \"pythonw \\\\\"{script_path}\\\\\" --backup\" /sc {sc} /st {time_txt} /f'\n            self._launch_job(\"backup_schedule_enable\", lambda: self._append_log(self.backup_log, self._run_cmd(cmd, timeout=90)[0], C[\"success\"]))\n        except Exception as e:\n            self._append_log(self.backup_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _backup_schedule_remove(self):\n        if messagebox.askyesno(\"Confirm karo\", \"GodawariAutoBackup scheduled task remove karna hai?\"):\n            self._launch_job(\"backup_schedule_remove\", lambda: self._append_log(self.backup_log, self._run_cmd('schtasks /delete /tn \"GodawariAutoBackup\" /f', timeout=60)[0], C[\"warning\"]))\n\n    def _backup_add_history(self, entry):\n        self.backup_history = getattr(self, \"backup_history\", [])\n        self.backup_history.insert(0, entry)\n        self.backup_history = self.backup_history[:50]\n        self.after(0, self._backup_save_config)\n        self.after(0, self._backup_refresh_history)\n\n    def _backup_refresh_history(self):\n        try:\n            if not hasattr(self, \"backup_history\"):\n                self.backup_history = []\n            if hasattr(self, \"backup_history_tree\"):\n                self.backup_history_tree.delete(*self.backup_history_tree.get_children())\n                for i, h in enumerate(self.backup_history[:50], 1):\n                    self.backup_history_tree.insert(\"\", \"end\", values=(i, h.get(\"dt\", \"\"), h.get(\"mode\", \"\"), h.get(\"sources\", \"\"), h.get(\"dest\", \"\"), h.get(\"size\", \"\"), h.get(\"status\", \"\"), h.get(\"duration\", \"\")))\n        except Exception as e:\n            self._append_log(self.backup_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _backup_calculate_size(self, folder):\n        total = 0\n        try:\n            for root, dirs, files in os.walk(folder):\n                for fn in files:\n                    try:\n                        total += os.path.getsize(os.path.join(root, fn))\n                    except Exception:\n                        pass\n        except Exception:\n            pass\n        return total / (1024 * 1024)\n\n    def _backup_open_folder(self):\n        try:\n            dest = self.backup_dest_var.get().strip()\n            if dest and os.path.isdir(dest):\n                os.startfile(dest)\n            else:\n                messagebox.showwarning(\"Folder nahi mila\", \"Pehle valid backup folder select karo\")\n        except Exception as e:\n            self._append_log(self.backup_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _backup_get_selected_sources(self):\n        try:\n            if hasattr(self, \"backup_source_list\") and self.backup_source_list.curselection():\n                return [self.backup_source_list.get(i) for i in self.backup_source_list.curselection()]\n            return list(self.backup_sources)\n        except Exception:\n            return list(self.backup_sources)\n\n    # ---------- UTILITIES ----------\n    def _toggle_theme(self):\n        self.current_theme = \"light\" if self.current_theme == \"dark\" else \"dark\"\n        self.theme_btn.config(text=\"\u2600\ufe0f\" if self.current_theme == \"light\" else \"\ud83c\udf19\")\n\n    def _save_settings(self):\n        try:\n            with open(self.settings_file, \"w\") as f:\n                json.dump({\"theme\": self.current_theme}, f)\n        except:\n            pass\n\n    def _load_settings(self):\n        if os.path.exists(self.settings_file):\n            try:\n                with open(self.settings_file, \"r\") as f:\n                    data = json.load(f)\n                    self.current_theme = data.get(\"theme\", \"dark\")\n            except:\n                pass\n\n    def _fmt_size(self, size):\n        for unit in [\"B\",\"KB\",\"MB\",\"GB\"]:\n            if size &lt; 1024:\n                return f\"{size:.1f} {unit}\"\n            size /= 1024\n        return f\"{size:.1f} TB\"\n\n    def _format_seconds(self, seconds):\n        try:\n            seconds = max(0, int(float(seconds)))\n        except Exception:\n            seconds = 0\n        h, rem = divmod(seconds, 3600)\n        m, s = divmod(rem, 60)\n        if h:\n            return f\"{h:02d}:{m:02d}:{s:02d}\"\n        return f\"{m:02d}:{s:02d}\"\n\n    def _section_header(self, parent, title, subtitle=\"\", hw=False):\n        hdr = tk.Frame(parent, bg=C[\"panel\"] if not hw else \"#1A0A2E\")\n        hdr.pack(fill=\"x\")\n        fg = C[\"hw_accent\"] if hw else C[\"accent\"]\n        tk.Label(hdr, text=f\"  {title}\", font=FONTS[\"heading\"], fg=fg, bg=hdr[\"bg\"]).pack(side=\"left\", pady=10, padx=8)\n        if subtitle:\n            tk.Label(hdr, text=f\"\u2014  {subtitle}\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=hdr[\"bg\"]).pack(side=\"left\", pady=10)\n\n    def _btn(self, parent, text, color, cmd):\n        return tk.Button(parent, text=self._fix_text(text), font=FONTS[\"small\"], bg=color, fg=C[\"text\"], bd=0, padx=12, pady=6, cursor=\"hand2\", command=cmd)\n\n    def _action_card_grid(self, parent, actions, cols=4, button_refs=None):\n        \"\"\"\n        HDD/SSD repair jaisa card-grid banata hai.\n        actions = list of (emoji, title, subtitle, color, cmd_func)\n        cols = columns per row (default 4)\n        button_refs = optional list to collect created button widgets.\n        \"\"\"\n        grid_frame = tk.Frame(parent, bg=C[\"bg\"])\n        grid_frame.pack(fill=\"x\", padx=14, pady=4)\n        cols = max(1, min(int(cols or 1), 4))\n        for i in range(cols):\n            grid_frame.columnconfigure(i, weight=1)\n        for idx, (emoji, title, subtitle, color, cmd_func) in enumerate(actions):\n            col = idx % cols\n            row_n = idx // cols\n            card = tk.Frame(grid_frame, bg=C[\"card\"], bd=1, relief=\"flat\",\n                            highlightbackground=color, highlightthickness=1)\n            card.grid(row=row_n, column=col, padx=5, pady=5, sticky=\"nsew\")\n            tk.Label(card, text=emoji, font=(\"Segoe UI\", 18),\n                     fg=color, bg=C[\"card\"]).pack(pady=(8, 2))\n            tk.Label(card, text=title, font=FONTS[\"subhead\"],\n                     fg=C[\"text\"], bg=C[\"card\"]).pack()\n            tk.Label(card, text=subtitle, font=FONTS[\"small\"],\n                     fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=160, justify=\"center\").pack(padx=6)\n            btn = tk.Button(card, text=\"\u25b6  Run\", font=FONTS[\"small\"],\n                      bg=color, fg=\"#000\" if color in (C.get(\"accent\",\"\"), C.get(\"accent2\",\"\")) else C[\"text\"],\n                      bd=0, padx=12, pady=5, cursor=\"hand2\",\n                      command=cmd_func)\n            btn.pack(pady=(6, 10))\n            if isinstance(button_refs, list):\n                button_refs.append(btn)\n        return grid_frame\n\n    def _compact_action_grid(self, parent, actions, cols=2):\n        grid = tk.Frame(parent, bg=C[\"card\"])\n        grid.pack(fill=\"x\", padx=8, pady=(0, 6))\n        cols = max(1, int(cols or 1))\n        for i in range(cols):\n            grid.columnconfigure(i, weight=1)\n        for idx, (label, color, cmd_func) in enumerate(actions):\n            row = idx // cols\n            col = idx % cols\n            btn = tk.Button(\n                grid, text=self._fix_text(label), font=FONTS[\"small\"],\n                bg=color, fg=C[\"text\"], bd=0, padx=8, pady=5,\n                cursor=\"hand2\", command=cmd_func\n            )\n            btn.grid(row=row, column=col, sticky=\"ew\", padx=3, pady=3)\n        return grid\n\n    def _bind_tree_responsive_columns(self, tree, specs):\n        \"\"\"\n        specs: [(column_name, base_width, grow_weight), ...]\n        Keeps tree columns readable while allowing wide screens to use extra room.\n        \"\"\"\n        safe_specs = []\n        for col, base, weight in specs:\n            try:\n                safe_specs.append((col, max(40, int(base)), max(0, int(weight))))\n            except Exception:\n                pass\n        if not safe_specs:\n            return\n\n        def _resize(_event=None):\n            try:\n                base_total = sum(base for _col, base, _weight in safe_specs)\n                available = max(tree.winfo_width() - 28, base_total)\n                extra = max(0, available - base_total)\n                weight_total = sum(weight for _col, _base, weight in safe_specs) or 1\n                for col, base, weight in safe_specs:\n                    width = base + int(extra * (weight / weight_total))\n                    tree.column(col, width=width, stretch=True)\n            except Exception:\n                pass\n\n        tree.bind(\"\", _resize, add=\"+\")\n        try:\n            tree.after(80, _resize)\n        except Exception:\n            pass\n\n    def _scrolled_text(self, parent, height=12):\n        st = scrolledtext.ScrolledText(parent, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], height=height, bd=0, wrap=\"word\", relief=\"flat\", state=\"disabled\")\n        st.pack(fill=\"both\", expand=True, padx=8, pady=(0,8))\n        return st\n\n    def _stat_card(self, parent, title, value, color):\n        card = tk.Frame(parent, bg=C[\"card\"], pady=14, padx=14)\n        tk.Label(card, text=title, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\")\n        lbl = tk.Label(card, text=value, font=(\"Segoe UI\", 22, \"bold\"), fg=color, bg=C[\"card\"])\n        lbl.pack(anchor=\"w\", pady=(4,0))\n        bar = ttk.Progressbar(card, length=140, mode=\"determinate\")\n        bar.pack(fill=\"x\", pady=(6,0))\n        card._value_lbl = lbl\n        card._bar = bar\n        return card\n\n    def _append_log(self, widget, msg, color=None):\n        def _do():\n            try:\n                widget.config(state=\"normal\")\n                start = widget.index(\"end-1c\")\n                widget.insert(\"end\", self._fix_text(msg) + \"\\n\")\n                if color:\n                    end = widget.index(\"end-1c\")\n                    tag = f\"c{color.replace('#','')}\"\n                    widget.tag_config(tag, foreground=color)\n                    widget.tag_add(tag, start, end)\n                widget.see(\"end\")\n                widget.config(state=\"disabled\")\n            except:\n                pass\n        self.after(0, _do)\n\n    def _reg_set(self, hive, path, name, value, vtype):\n        try:\n            key = winreg.OpenKey(hive, path, 0, winreg.KEY_ALL_ACCESS)\n        except:\n            key = winreg.CreateKey(hive, path)\n        winreg.SetValueEx(key, name, 0, vtype, value)\n        winreg.CloseKey(key)\n\n    def _reg_get(self, hive, path, name):\n        try:\n            key = winreg.OpenKey(hive, path, 0, winreg.KEY_READ)\n            try:\n                value, vtype = winreg.QueryValueEx(key, name)\n                return True, value, vtype\n            finally:\n                winreg.CloseKey(key)\n        except FileNotFoundError:\n            return False, None, None\n        except OSError:\n            return False, None, None\n\n    def _same_reg_value(self, current, desired, vtype):\n        if vtype == winreg.REG_DWORD:\n            try:\n                return int(current) == int(desired)\n            except Exception:\n                return False\n        if vtype == winreg.REG_BINARY:\n            return bytes(current or b\"\") == bytes(desired or b\"\")\n        return str(current) == str(desired)\n\n    def _action_summary(self, title, results):\n        changed = sum(1 for r in results if r.get(\"state\") == \"changed\")\n        already = sum(1 for r in results if r.get(\"state\") == \"already\")\n        failed = [r for r in results if r.get(\"state\") == \"failed\"]\n        lines = [f\"{title} summary:\"]\n        lines.append(f\"Applied now: {changed}\")\n        lines.append(f\"Already done: {already}\")\n        if failed:\n            lines.append(f\"Failed: {len(failed)}\")\n            lines.extend(f\"- {r.get('label', 'item')}: {r.get('error', '')}\" for r in failed[:8])\n        elif changed == 0 and already &gt; 0:\n            lines.append(\"No new change needed.\")\n        return {\n            \"changed\": changed,\n            \"already\": already,\n            \"failed\": len(failed),\n            \"already_done\": changed == 0 and already &gt; 0 and not failed,\n            \"message\": \"\\n\".join(lines),\n        }\n\n    def _reg_set_checked(self, hive, path, name, value, vtype, label=None, log_widget=None):\n        label = label or name\n        exists, current, current_type = self._reg_get(hive, path, name)\n        if exists and current_type == vtype and self._same_reg_value(current, value, vtype):\n            if log_widget is not None:\n                self._append_log(log_widget, f\"Already done: {label}\", C[\"warning\"])\n            return {\"state\": \"already\", \"label\": label}\n        try:\n            self._reg_set(hive, path, name, value, vtype)\n            if log_widget is not None:\n                self._append_log(log_widget, f\"Applied: {label}\", C[\"success\"])\n            return {\"state\": \"changed\", \"label\": label}\n        except Exception as e:\n            if log_widget is not None:\n                self._append_log(log_widget, f\"Failed: {label} - {e}\", C[\"error\"])\n            return {\"state\": \"failed\", \"label\": label, \"error\": str(e)}\n\n    def _service_state(self, name):\n        out, rc = self._run_cmd(f'sc query \"{name}\"', timeout=20)\n        if rc != 0:\n            return \"\", out\n        match = re.search(r\"STATE\\s*:\\s*\\d+\\s+([A-Z_]+)\", out, re.I)\n        return (match.group(1).upper() if match else \"\"), out\n\n    def _service_start_mode(self, name):\n        out, rc = self._run_cmd(f'sc qc \"{name}\"', timeout=20)\n        if rc != 0:\n            return \"\", out\n        match = re.search(r\"START_TYPE\\s*:\\s*\\d+\\s+([A-Z_]+)\", out, re.I)\n        return (match.group(1).upper() if match else \"\"), out\n\n    def _service_dependents(self, name):\n        \"\"\"\n        Return list of dependent service names (best-effort).\n        Uses: sc enumdepend \n        \"\"\"\n        out, rc = self._run_cmd(f'sc enumdepend \"{name}\"', timeout=25)\n        if rc != 0 or not out:\n            return []\n        deps = []\n        for ln in out.splitlines():\n            ln = ln.strip()\n            if not ln:\n                continue\n            m = re.search(r\"^SERVICE_NAME:\\s*(.+)$\", ln, re.I)\n            if m:\n                dep = m.group(1).strip()\n                if dep and dep.lower() not in {name.lower()}:\n                    deps.append(dep)\n        # Dedupe preserve order\n        seen = set()\n        uniq = []\n        for d in deps:\n            dl = d.lower()\n            if dl in seen:\n                continue\n            seen.add(dl)\n            uniq.append(d)\n        return uniq\n\n    def _svc_snapshot_path(self):\n        base = getattr(self, \"backup_dir\", \"\") or os.getcwd()\n        return os.path.join(base, \"service_startmode_snapshot.json\")\n\n    def _svc_save_start_mode_snapshot(self, names):\n        try:\n            items = {}\n            for n in names:\n                mode, _ = self._service_start_mode(n)\n                if mode:\n                    items[n] = mode\n            if not items:\n                return\n            payload = {\n                \"ts\": datetime.datetime.now().isoformat(timespec=\"seconds\"),\n                \"items\": items,\n            }\n            with open(self._svc_snapshot_path(), \"w\", encoding=\"utf-8\") as f:\n                json.dump(payload, f, ensure_ascii=False, indent=2)\n        except Exception:\n            pass\n\n    def _svc_restore_snapshot(self):\n        path = self._svc_snapshot_path()\n        if not os.path.exists(path):\n            messagebox.showwarning(\"No Snapshot\", f\"Snapshot file nahi mili:\\n{path}\\n\\nPehle disable actions chalao (snapshot auto save hota hai).\")\n            return\n        if not messagebox.askyesno(\"Restore Snapshot\", \"Snapshot se previous service start-modes restore karein?\\n(Admin required for some services)\"):\n            return\n        try:\n            with open(path, \"r\", encoding=\"utf-8\") as f:\n                payload = json.load(f)\n            items = (payload or {}).get(\"items\", {}) if isinstance(payload, dict) else {}\n        except Exception as e:\n            messagebox.showerror(\"Snapshot Error\", str(e))\n            return\n        if not items:\n            messagebox.showinfo(\"Empty Snapshot\", \"Snapshot empty hai.\")\n            return\n        # Map SC qc START_TYPE to sc config value\n        map_mode = {\n            \"DISABLED\": \"disabled\",\n            \"AUTO_START\": \"auto\",\n            \"DEMAND_START\": \"demand\",\n        }\n        results = []\n        for name, mode in items.items():\n            start_type = map_mode.get(str(mode).upper(), \"demand\")\n            results.append(self._service_config_checked(name, start_type, f\"{name} start={start_type}\", None))\n        summary = self._action_summary(\"Service Snapshot Restore\", results)\n        messagebox.showinfo(\"Restore Result\", summary[\"message\"])\n        self._scan_impacting_services()\n\n    def _svc_apply_pack(self, pack):\n        if not messagebox.askyesno(\"Apply Service Pack\", f\"Apply recommended pack: {pack}?\\n\\nReboot recommended.\"):\n            return\n        # Keep it conservative; snapshot first for rollback\n        targets = []\n        if pack == \"ssd_laptop\":\n            targets = [\n                (\"SysMain\", \"disabled\"),\n                (\"WSearch\", \"disabled\"),\n                (\"DiagTrack\", \"disabled\"),\n            ]\n        elif pack == \"hdd_desktop\":\n            targets = [\n                (\"DiagTrack\", \"disabled\"),\n                (\"WSearch\", \"disabled\"),\n            ]\n        names = [t[0] for t in targets]\n        self._svc_save_start_mode_snapshot(names)\n        results = []\n        for svc, start in targets:\n            results.append(self._service_config_checked(svc, start, f\"{svc} start={start}\", None))\n            if start == \"disabled\":\n                results.append(self._service_stop_checked(svc, svc, None))\n        summary = self._action_summary(f\"Service Pack: {pack}\", results)\n        messagebox.showinfo(\"Pack Result\", summary[\"message\"] + \"\\nRestart recommended.\")\n        self._scan_impacting_services()\n\n    def _service_stop_checked(self, name, label=None, log_widget=None):\n        label = label or name\n        state, detail = self._service_state(name)\n        if state == \"STOPPED\":\n            if log_widget is not None:\n                self._append_log(log_widget, f\"Already stopped: {label}\", C[\"warning\"])\n            return {\"state\": \"already\", \"label\": label}\n        out, rc = self._run_cmd(f'sc stop \"{name}\"', timeout=40)\n        combined = f\"{detail}\\n{out}\".lower()\n        if rc == 0 or \"stop_pending\" in combined or \"stopped\" in combined:\n            if log_widget is not None:\n                self._append_log(log_widget, f\"Stopped: {label}\", C[\"success\"])\n            return {\"state\": \"changed\", \"label\": label}\n        if \"not been started\" in combined or \"service has not been started\" in combined:\n            if log_widget is not None:\n                self._append_log(log_widget, f\"Already stopped: {label}\", C[\"warning\"])\n            return {\"state\": \"already\", \"label\": label}\n        if log_widget is not None:\n            self._append_log(log_widget, f\"Stop failed: {label} - {out[:120]}\", C[\"error\"])\n        return {\"state\": \"failed\", \"label\": label, \"error\": out[:300]}\n\n    def _service_start_checked(self, name, label=None, log_widget=None):\n        label = label or name\n        state, _ = self._service_state(name)\n        if state == \"RUNNING\":\n            if log_widget is not None:\n                self._append_log(log_widget, f\"Already running: {label}\", C[\"warning\"])\n            return {\"state\": \"already\", \"label\": label}\n        out, rc = self._run_cmd(f'sc start \"{name}\"', timeout=40)\n        combined = out.lower()\n        if rc == 0 or \"running\" in combined or \"start_pending\" in combined:\n            if log_widget is not None:\n                self._append_log(log_widget, f\"Started: {label}\", C[\"success\"])\n            return {\"state\": \"changed\", \"label\": label}\n        if \"already running\" in combined or \"instance of the service is already running\" in combined:\n            if log_widget is not None:\n                self._append_log(log_widget, f\"Already running: {label}\", C[\"warning\"])\n            return {\"state\": \"already\", \"label\": label}\n        if log_widget is not None:\n            self._append_log(log_widget, f\"Start failed: {label} - {out[:120]}\", C[\"error\"])\n        return {\"state\": \"failed\", \"label\": label, \"error\": out[:300]}\n\n    def _service_config_checked(self, name, start_type, label=None, log_widget=None):\n        label = label or name\n        desired = {\n            \"disabled\": \"DISABLED\",\n            \"auto\": \"AUTO_START\",\n            \"demand\": \"DEMAND_START\",\n            \"manual\": \"DEMAND_START\",\n        }.get(str(start_type).lower(), str(start_type).upper())\n        current, _ = self._service_start_mode(name)\n        if current == desired:\n            if log_widget is not None:\n                self._append_log(log_widget, f\"Already configured: {label} start={start_type}\", C[\"warning\"])\n            return {\"state\": \"already\", \"label\": label}\n        out, rc = self._run_cmd(f'sc config \"{name}\" start= {start_type}', timeout=30)\n        if rc == 0:\n            if log_widget is not None:\n                self._append_log(log_widget, f\"Configured: {label} start={start_type}\", C[\"success\"])\n            return {\"state\": \"changed\", \"label\": label}\n        if log_widget is not None:\n            self._append_log(log_widget, f\"Config failed: {label} - {out[:120]}\", C[\"error\"])\n        return {\"state\": \"failed\", \"label\": label, \"error\": out[:300]}\n\n    def _fsutil_last_access_checked(self, log_widget=None):\n        label = \"NTFS last access timestamp\"\n        out, _ = self._run_cmd(\"fsutil behavior query disablelastaccess\", timeout=20)\n        match = re.search(r\"DisableLastAccess\\s*=\\s*(\\d+)\", out, re.I)\n        if match and int(match.group(1)) in (1, 3):\n            if log_widget is not None:\n                self._append_log(log_widget, f\"Already done: {label}\", C[\"warning\"])\n            return {\"state\": \"already\", \"label\": label}\n        out, rc = self._run_cmd(\"fsutil behavior set disablelastaccess 1\", timeout=30)\n        if rc == 0:\n            if log_widget is not None:\n                self._append_log(log_widget, f\"Applied: {label}\", C[\"success\"])\n            return {\"state\": \"changed\", \"label\": label}\n        if log_widget is not None:\n            self._append_log(log_widget, f\"Failed: {label} - {out[:120]}\", C[\"error\"])\n        return {\"state\": \"failed\", \"label\": label, \"error\": out[:300]}\n\n    def _task_records_from_schtasks(self, out):\n        try:\n            reader = csv.DictReader(io.StringIO(out))\n            records = []\n            for row in reader:\n                task_name = (row.get(\"TaskName\") or row.get(\"Task Name\") or \"\").strip()\n                if task_name:\n                    records.append(row)\n            if records:\n                return records\n        except Exception:\n            pass\n        records = []\n        try:\n            for row in csv.reader(io.StringIO(out)):\n                if len(row) &lt; 2:\n                    continue\n                first = row[0].strip()\n                if first in (\"HostName\", \"TaskName\"):\n                    continue\n                task_name = row[1].strip() if len(row) &gt; 1 else first\n                if task_name:\n                    records.append({\n                        \"TaskName\": task_name,\n                        \"Status\": row[3].strip() if len(row) &gt; 3 else \"\",\n                        \"Last Run Time\": row[5].strip() if len(row) &gt; 5 else \"\",\n                        \"Run As User\": row[14].strip() if len(row) &gt; 14 else \"\",\n                        \"Task To Run\": row[8].strip() if len(row) &gt; 8 else \"\",\n                        \"Scheduled Task State\": row[11].strip() if len(row) &gt; 11 else \"\",\n                    })\n        except Exception:\n            pass\n        return records\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # SUSPICIOUS / UNKNOWN PROCESS SCANNER\n    # Checks: Running processes, Startup (Registry + Folder),\n    #         Hidden folders, Scheduled tasks \u2014 flags unknown ones\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _build_suspicion_scanner(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udd34 Suspicious Process &amp; Entry Scanner\",\n                             \"Unknown processes in RAM, Startup, Registry &amp; Hidden Folders\")\n        body = self._scrollable_section_body(frame)\n\n        self._action_card_grid(body, [\n            (\"\ud83d\udd0d\", \"Full Scan\",           \"Processes, startup, folders, tasks sab scan\",C[\"btn_danger\"], self._susp_full_scan),\n            (\"\u26a1\", \"Scan Running Procs\",  \"RAM mein chal rahe unknown processes\",       C[\"btn_warn\"],   self._susp_scan_procs),\n            (\"\ud83d\ude80\", \"Scan Startup\",        \"Startup entries mein suspicious cheezein\",   C[\"btn_info\"],   self._susp_scan_startup),\n            (\"\ud83d\udcc1\", \"Scan Hidden Folders\", \"Hidden folders dhundho\",                     C[\"btn_hw\"],     self._susp_scan_hidden),\n            (\"\ud83d\udcc5\", \"Scan Unknown Tasks\",  \"Unknown scheduled tasks flag karo\",          C[\"btn_chip\"],   self._susp_scan_tasks),\n            (\"\ud83d\uddd1\",  \"Kill Selected\",      \"Selected process terminate karo\",            C[\"btn_danger\"], self._susp_kill_selected),\n            (\"\ud83d\udd12\", \"Disable Selected\",    \"Selected entry disable karo\",                C[\"btn_warn\"],   self._susp_disable_selected),\n            (\"\ud83d\udce6\", \"Quarantine Selected\", \"Selected file quarantine mein bhejo\",        C[\"btn_info\"],   self._susp_quarantine_selected),\n            (\"\ud83d\udd17\", \"VirusTotal URL\",      \"URL clipboard mein copy karo\",               C[\"btn_chip\"],   self._susp_copy_virustotal_url),\n        ], cols=3)\n\n        # \u2500\u2500 Stats row \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        stats_row = tk.Frame(body, bg=C[\"bg\"])\n        stats_row.pack(fill=\"x\", padx=16, pady=6)\n        self.susp_count_vars = {}\n        for i, (k, lbl, col) in enumerate([\n            (\"proc\",    \"Running Procs\",   C[\"error\"]),\n            (\"startup\", \"Startup Entries\", C[\"warning\"]),\n            (\"hidden\",  \"Hidden Items\",    C[\"hw_accent\"]),\n            (\"tasks\",   \"Unknown Tasks\",   C[\"accent4\"]),\n            (\"total\",   \"TOTAL FLAGS\",     C[\"accent\"]),\n        ]):\n            card = tk.Frame(stats_row, bg=C[\"card\"], padx=12, pady=8)\n            card.grid(row=0, column=i, padx=5, sticky=\"ew\")\n            stats_row.columnconfigure(i, weight=1)\n            tk.Label(card, text=lbl,  font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\")\n            v = tk.StringVar(value=\"--\")\n            self.susp_count_vars[k] = v\n            tk.Label(card, textvariable=v, font=(\"Segoe UI\",16,\"bold\"), fg=col, bg=C[\"card\"]).pack(anchor=\"w\")\n\n        # \u2500\u2500 Full-width flagged entries list \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        list_frame = tk.Frame(body, bg=C[\"card\"])\n        list_frame.pack(fill=\"both\", expand=True, padx=16, pady=(4,0))\n        list_frame.rowconfigure(0, weight=1)\n        list_frame.columnconfigure(0, weight=1)\n\n        tk.Label(list_frame, text=\"  \ud83d\udea8 Flagged Entries  (saari entries ek sath \u2014 click karo detail ke liye)\",\n                 font=FONTS[\"subhead\"], fg=C[\"error\"], bg=C[\"card\"]).grid(\n                 row=0, column=0, columnspan=2, sticky=\"w\", pady=(8,4), padx=8)\n\n        cols = (\"Category\",\"Name\",\"Risk\",\"Location/PID\",\"Action\")\n        self.susp_tree = ttk.Treeview(list_frame, columns=cols, show=\"headings\",\n                                      height=24, style=\"Custom.Treeview\")\n        widths = [110, 220, 80, 380, 100]\n        for col, w in zip(cols, widths):\n            self.susp_tree.heading(col, text=col)\n            self.susp_tree.column(col, width=w, anchor=\"w\")\n        self.susp_tree.tag_configure(\"high\",   foreground=C[\"error\"])\n        self.susp_tree.tag_configure(\"medium\", foreground=C[\"warning\"])\n        self.susp_tree.tag_configure(\"low\",    foreground=C[\"text_dim\"])\n        lsb = ttk.Scrollbar(list_frame, orient=\"vertical\", command=self.susp_tree.yview)\n        hsb2 = ttk.Scrollbar(list_frame, orient=\"horizontal\", command=self.susp_tree.xview)\n        self.susp_tree.configure(yscrollcommand=lsb.set, xscrollcommand=hsb2.set)\n        self.susp_tree.grid(row=1, column=0, sticky=\"nsew\", padx=(8,0), pady=(0,0))\n        lsb.grid(row=1, column=1, sticky=\"ns\", pady=(0,0))\n        hsb2.grid(row=2, column=0, sticky=\"ew\", padx=(8,0), pady=(0,4))\n        list_frame.rowconfigure(1, weight=1)\n        self._bind_tree_responsive_columns(self.susp_tree, [\n            (\"Category\", 110, 1), (\"Name\", 220, 3), (\"Risk\", 80, 0),\n            (\"Location/PID\", 380, 5), (\"Action\", 100, 1)\n        ])\n        self.susp_tree.bind(\"&lt;&gt;\", self._susp_on_select)\n\n        # \u2500\u2500 Bottom: detail strip + legend \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        bot = tk.Frame(body, bg=C[\"panel\"])\n        bot.pack(fill=\"x\", padx=16, pady=(2,4))\n        bot.columnconfigure(0, weight=1)\n        bot.columnconfigure(1, weight=0)\n\n        # Detail box\n        detail_wrap = tk.Frame(bot, bg=C[\"card\"])\n        detail_wrap.grid(row=0, column=0, sticky=\"nsew\", padx=(0,6), pady=4)\n        detail_wrap.rowconfigure(1, weight=1)\n        detail_wrap.columnconfigure(0, weight=1)\n\n        hdr_d = tk.Frame(detail_wrap, bg=C[\"card\"])\n        hdr_d.grid(row=0, column=0, sticky=\"ew\", padx=6, pady=(4,2))\n        tk.Label(hdr_d, text=\"  \ud83d\udd0d Entry Details &amp; Recommendation\",\n                 font=FONTS[\"subhead\"], fg=C[\"warning\"], bg=C[\"card\"]).pack(side=\"left\")\n        tk.Label(hdr_d, text=\"(entry click karo \u2014 yahan detail dikhegi)\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\", padx=6)\n\n        self.susp_detail = scrolledtext.ScrolledText(\n            detail_wrap, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"],\n            height=5, bd=0, relief=\"flat\", state=\"disabled\", wrap=\"word\")\n        self.susp_detail.grid(row=1, column=0, sticky=\"nsew\", padx=6, pady=(0,4))\n\n        # Legend (right side of bottom strip)\n        leg_wrap = tk.Frame(bot, bg=C[\"card\"])\n        leg_wrap.grid(row=0, column=1, sticky=\"nsew\", padx=(0,0), pady=4)\n        tk.Label(leg_wrap, text=\"  Legend\", font=FONTS[\"small\"],\n                 fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=8, pady=(6,2))\n        for color, label in [(C[\"error\"],   \"\ud83d\udd34 High Risk\"),\n                             (C[\"warning\"], \"\ud83d\udfe1 Medium Risk\"),\n                             (C[\"text_dim\"],\"\u26aa Low / Safe\")]:\n            tk.Label(leg_wrap, text=label, font=FONTS[\"small\"],\n                     fg=color, bg=C[\"card\"]).pack(anchor=\"w\", padx=12, pady=2)\n\n        self.susp_status = tk.Label(body, text=\"  Click 'Full Scan' to detect suspicious entries\",\n                                    font=FONTS[\"small\"], fg=C[\"accent2\"], bg=C[\"bg\"], anchor=\"w\")\n        self.susp_status.pack(fill=\"x\", padx=16, pady=(0,4))\n\n        # Internal store: {iid: meta_dict}\n        self._susp_meta = {}\n        return frame\n\n    def _susp_quarantine_dir(self):\n        base = getattr(self, \"backup_dir\", \"\") or os.path.join(os.path.expanduser(\"~\"), \"Desktop\")\n        q = os.path.join(base, \"Godawari_Quarantine\")\n        try:\n            os.makedirs(q, exist_ok=True)\n        except Exception:\n            pass\n        return q\n\n    def _susp_quarantine_selected(self):\n        sel = self.susp_tree.selection()\n        if not sel:\n            messagebox.showinfo(\"No Selection\", \"Select entries first.\")\n            return\n        qdir = self._susp_quarantine_dir()\n        moved = 0\n        for iid in sel:\n            meta = self._susp_meta.get(iid, {})\n            p = meta.get(\"exe\") or meta.get(\"path\") or \"\"\n            if not p or not os.path.exists(p) or os.path.isdir(p):\n                continue\n            dst = os.path.join(qdir, os.path.basename(p))\n            if os.path.exists(dst):\n                root, ext = os.path.splitext(dst)\n                dst = f\"{root}_{int(time.time())}{ext}\"\n            try:\n                shutil.move(p, dst)\n                moved += 1\n                self.susp_tree.delete(iid)\n            except Exception as e:\n                messagebox.showwarning(\"Move failed\", f\"{p}\\n{e}\")\n        self._set_status(f\"Quarantined {moved} file(s)\", C[\"success\"] if moved else C[\"warning\"])\n        messagebox.showinfo(\"Quarantine\", f\"\u2705 Quarantined: {moved}\\nFolder:\\n{qdir}\")\n\n    def _susp_copy_virustotal_url(self):\n        sel = self.susp_tree.selection()\n        if not sel:\n            messagebox.showinfo(\"No Selection\", \"Select a file/process entry first.\")\n            return\n        iid = sel[0]\n        meta = self._susp_meta.get(iid, {})\n        p = meta.get(\"exe\") or meta.get(\"path\") or \"\"\n        if not p or not os.path.exists(p) or os.path.isdir(p):\n            messagebox.showwarning(\"No File\", \"Selected entry ke paas valid file path nahi hai.\")\n            return\n        try:\n            h = self._sha256_file(p)\n            url = f\"https://www.virustotal.com/gui/file/{h}\"\n            self.clipboard_clear()\n            self.clipboard_append(url)\n            self.update()\n            messagebox.showinfo(\"Copied\", f\"\u2705 VirusTotal URL copied:\\n{url}\")\n        except Exception as e:\n            messagebox.showerror(\"Error\", str(e))\n\n    # \u2500\u2500 Scan orchestrators \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _susp_full_scan(self):\n        self.susp_status.config(text=\"  \ud83d\udd0d Full scan running...\", fg=C[\"accent4\"])\n        for i in self.susp_tree.get_children():\n            self.susp_tree.delete(i)\n        self._susp_meta.clear()\n        for k in self.susp_count_vars:\n            self.susp_count_vars[k].set(\"...\")\n        self._launch_job(\"susp_full_scan\", self._do_susp_full_scan)\n\n    def _do_susp_full_scan(self):\n        pc = self._do_susp_scan_procs(batch=True)\n        sc = self._do_susp_scan_startup(batch=True)\n        hc = self._do_susp_scan_hidden(batch=True)\n        tc = self._do_susp_scan_tasks(batch=True)\n        total = pc + sc + hc + tc\n        def update():\n            self.susp_count_vars[\"proc\"].set(str(pc))\n            self.susp_count_vars[\"startup\"].set(str(sc))\n            self.susp_count_vars[\"hidden\"].set(str(hc))\n            self.susp_count_vars[\"tasks\"].set(str(tc))\n            self.susp_count_vars[\"total\"].set(str(total))\n            self.susp_status.config(\n                text=f\"  \u2705 Scan complete \u2014 {total} suspicious entries found\",\n                fg=C[\"success\"] if total == 0 else C[\"error\"])\n        self.after(0, update)\n\n    def _susp_scan_procs(self):\n        self._launch_job(\"susp_scan_procs\", self._do_susp_scan_procs)\n\n    def _susp_scan_startup(self):\n        self._launch_job(\"susp_scan_startup\", self._do_susp_scan_startup)\n\n    def _susp_scan_hidden(self):\n        self._launch_job(\"susp_scan_hidden\", self._do_susp_scan_hidden)\n\n    def _susp_scan_tasks(self):\n        self._launch_job(\"susp_scan_tasks\", self._do_susp_scan_tasks)\n\n    # \u2500\u2500 Known-safe whitelist (lowercase) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    _KNOWN_SAFE = {\n        \"system\",\"system idle process\",\"svchost.exe\",\"lsass.exe\",\"winlogon.exe\",\n        \"csrss.exe\",\"smss.exe\",\"wininit.exe\",\"services.exe\",\"explorer.exe\",\n        \"taskhostw.exe\",\"taskhost.exe\",\"dwm.exe\",\"spoolsv.exe\",\"searchindexer.exe\",\n        \"antimalware service executable\",\"msmpeng.exe\",\"msseces.exe\",\n        \"audiodg.exe\",\"fontdrvhost.exe\",\"sihost.exe\",\"runtimebroker.exe\",\n        \"ctfmon.exe\",\"dllhost.exe\",\"conhost.exe\",\"cmd.exe\",\"powershell.exe\",\n        \"python.exe\",\"pythonw.exe\",\"msiexec.exe\",\"wuauclt.exe\",\"wermgr.exe\",\n        \"backgroundtaskhost.exe\",\"settingsynchost.exe\",\"compattelrunner.exe\",\n        \"dashost.exe\",\"searchhost.exe\",\"securityhealthsystray.exe\",\n        \"shellexperiencehost.exe\",\"startmenuexperiencehost.exe\",\n        \"textinputhost.exe\",\"useroobebroker.exe\",\"applicationframehost.exe\",\n    }\n\n    _SUSPICIOUS_INDICATORS = [\n        \"temp\",\"tmp\",\"appdata\\\\local\\\\temp\",\"appdata\\\\roaming\",\n        \"programdata\",\"users\\\\public\",\"recycle\",\"windows\\\\temp\",\n        \"\\\\downloads\\\\\",\"no description\",\"unknown\",\"(null)\",\n    ]\n\n    _HIGH_RISK_NAMES = {\n        \"cryptominer\",\"miner\",\"torrent\",\"hack\",\"crack\",\"keygen\",\"patch\",\n        \"loader\",\"injector\",\"rat\",\"trojan\",\"worm\",\"virus\",\"malware\",\n        \"spyware\",\"adware\",\"pup\",\"hijack\",\"rootkit\",\n    }\n\n    def _susp_risk(self, name, path):\n        n = name.lower()\n        p = (path or \"\").lower()\n        if any(h in n for h in self._HIGH_RISK_NAMES):\n            return \"High\"\n        if any(ind in p for ind in self._SUSPICIOUS_INDICATORS):\n            return \"Medium\"\n        if n not in self._KNOWN_SAFE and name.endswith(\".exe\"):\n            if any(c.isdigit() for c in name[:6]):\n                return \"Medium\"\n        return \"Low\"\n\n    def _susp_insert(self, category, name, risk, location, action, meta=None):\n        tag = {\"High\":\"high\",\"Medium\":\"medium\"}.get(risk,\"low\")\n        iid = self.susp_tree.insert(\"\",\"end\",\n            values=(category, name, risk, location, action), tags=(tag,))\n        self._susp_meta[iid] = meta or {}\n\n    # \u2500\u2500 Running Process scan \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _do_susp_scan_procs(self, batch=False):\n        rows = []\n        for proc in psutil.process_iter(['pid','name','exe','cmdline','username','cpu_percent','memory_info']):\n            try:\n                pname = (proc.info.get('name') or \"\").strip()\n                exe   = (proc.info.get('exe')  or \"\").strip()\n                pid   = proc.info['pid']\n                if pid in (0, 4) or not pname:\n                    continue\n                risk = self._susp_risk(pname, exe)\n                try:\n                    mem_mb = round((proc.info.get('memory_info') or proc.memory_info()).rss / (1024*1024), 1)\n                    mem_str = f\"{mem_mb} MB\"\n                except:\n                    mem_str = \"--\"\n                rows.append((\"Running Proc\", pname, risk,\n                             f\"PID:{pid}  {exe[:55]}  RAM:{mem_str}\", \"Kill\",\n                             {\"pid\":pid,\"exe\":exe,\"type\":\"proc\",\n                              \"cmdline\":\" \".join(proc.info.get('cmdline') or [])}))\n            except:\n                pass\n\n        # Sort: High risk pehle, phir naam se\n        risk_order = {\"High\": 0, \"Medium\": 1, \"Low\": 2}\n        rows.sort(key=lambda r: (risk_order.get(r[2], 3), r[1].lower()))\n\n        def insert():\n            for r in rows:\n                self._susp_insert(*r)\n            if not batch:\n                flagged = sum(1 for r in rows if r[2] in (\"High\",\"Medium\"))\n                self.susp_count_vars[\"proc\"].set(str(len(rows)))\n                self.susp_status.config(\n                    text=f\"  Processes: {len(rows)} total  |  {flagged} flagged (High/Medium)\",\n                    fg=C[\"warning\"] if flagged else C[\"success\"])\n        self.after(0, insert)\n        return len(rows)\n\n    # \u2500\u2500 Startup scan (Registry + Folder) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _do_susp_scan_startup(self, batch=False):\n        rows = []\n        reg_paths = [\n            (winreg.HKEY_CURRENT_USER,  r\"Software\\Microsoft\\Windows\\CurrentVersion\\Run\",     \"HKCU Run\"),\n            (winreg.HKEY_LOCAL_MACHINE, r\"Software\\Microsoft\\Windows\\CurrentVersion\\Run\",     \"HKLM Run\"),\n            (winreg.HKEY_CURRENT_USER,  r\"Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce\", \"HKCU RunOnce\"),\n            (winreg.HKEY_LOCAL_MACHINE, r\"Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce\", \"HKLM RunOnce\"),\n            (winreg.HKEY_LOCAL_MACHINE, r\"Software\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Run\", \"HKLM Run(32)\"),\n        ]\n        for hive, path, label in reg_paths:\n            try:\n                key = winreg.OpenKey(hive, path, 0, winreg.KEY_READ)\n                i = 0\n                while True:\n                    try:\n                        name, value, _ = winreg.EnumValue(key, i)\n                        risk = self._susp_risk(name, value)\n                        # Flag anything in risky paths or unknown names\n                        if risk != \"Low\" or any(ind in value.lower()\n                                                 for ind in self._SUSPICIOUS_INDICATORS):\n                            rows.append((f\"Startup/{label}\", name, risk,\n                                         value[:80], \"Disable\",\n                                         {\"type\":\"reg_startup\",\"hive\":hive,\n                                          \"path\":path,\"name\":name,\"value\":value}))\n                        i += 1\n                    except OSError:\n                        break\n                winreg.CloseKey(key)\n            except:\n                pass\n\n        # Startup folders\n        for folder, label in [\n            (os.path.join(os.environ.get(\"APPDATA\",\"\"),\n                          r\"Microsoft\\Windows\\Start Menu\\Programs\\Startup\"), \"User Startup Folder\"),\n            (os.path.join(os.environ.get(\"PROGRAMDATA\",\"\"),\n                          r\"Microsoft\\Windows\\Start Menu\\Programs\\StartUp\"),  \"Common Startup Folder\"),\n        ]:\n            if not os.path.exists(folder):\n                continue\n            for f in Path(folder).glob(\"*\"):\n                if f.is_file():\n                    risk = self._susp_risk(f.name, str(f))\n                    rows.append((f\"Startup Folder\", f.name, risk,\n                                 str(f)[:80], \"Open Folder\",\n                                 {\"type\":\"folder_startup\",\"path\":str(f)}))\n\n        def insert():\n            for r in rows:\n                self._susp_insert(*r)\n            if not batch:\n                self.susp_count_vars[\"startup\"].set(str(len(rows)))\n                self.susp_status.config(\n                    text=f\"  Startup scan: {len(rows)} flagged\", fg=C[\"warning\"] if rows else C[\"success\"])\n        self.after(0, insert)\n        return len(rows)\n\n    # \u2500\u2500 Hidden folder scan \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _do_susp_scan_hidden(self, batch=False):\n        rows = []\n        scan_roots = [\n            os.environ.get(\"APPDATA\",\"\"),\n            os.environ.get(\"LOCALAPPDATA\",\"\"),\n            os.environ.get(\"PROGRAMDATA\",\"\"),\n            os.path.join(os.environ.get(\"SYSTEMROOT\",\"C:\\\\Windows\"), \"Temp\"),\n            os.path.join(os.environ.get(\"SYSTEMROOT\",\"C:\\\\Windows\"), \"System32\\\\Tasks\"),\n        ]\n        exe_exts = {\".exe\",\".bat\",\".cmd\",\".vbs\",\".ps1\",\".js\",\".scr\",\".pif\",\".com\"}\n        count = 0\n        for root_path in scan_roots:\n            if not os.path.exists(root_path):\n                continue\n            try:\n                for entry in os.scandir(root_path):\n                    try:\n                        # Hidden attribute check (Windows: FILE_ATTRIBUTE_HIDDEN = 2)\n                        attrs = entry.stat().st_file_attributes if hasattr(entry.stat(), 'st_file_attributes') else 0\n                        is_hidden = bool(attrs &amp; 2)\n                        ext = os.path.splitext(entry.name)[1].lower()\n                        is_exec = ext in exe_exts\n                        if is_hidden and is_exec:\n                            risk = \"High\"\n                        elif is_hidden and entry.is_dir():\n                            risk = \"Medium\"\n                        elif is_exec and any(\n                                ind in entry.path.lower()\n                                for ind in [\"temp\",\"tmp\",\"appdata\",\"programdata\"]):\n                            risk = \"Medium\"\n                        else:\n                            continue\n                        rows.append((\"Hidden/Temp Exec\",\n                                     entry.name, risk,\n                                     entry.path[:80], \"Open Folder\",\n                                     {\"type\":\"hidden_file\",\"path\":entry.path}))\n                        count += 1\n                        if count &gt;= 50:\n                            break\n                    except:\n                        pass\n            except:\n                pass\n            if count &gt;= 50:\n                break\n\n        def insert():\n            for r in rows:\n                self._susp_insert(*r)\n            if not batch:\n                self.susp_count_vars[\"hidden\"].set(str(len(rows)))\n                self.susp_status.config(\n                    text=f\"  Hidden scan: {len(rows)} flagged\", fg=C[\"warning\"] if rows else C[\"success\"])\n        self.after(0, insert)\n        return len(rows)\n\n    # \u2500\u2500 Unknown Scheduled Task scan \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _do_susp_scan_tasks(self, batch=False):\n        rows = []\n        out, _ = self._run_cmd('schtasks /query /fo CSV /v', timeout=20)\n        ms_paths = {\"\\\\microsoft\\\\\", \"\\\\windows\\\\\"}\n        seen = set()\n        for record in self._task_records_from_schtasks(out):\n            task_path = (record.get(\"TaskName\") or \"\").strip()\n            status = (record.get(\"Status\") or record.get(\"Scheduled Task State\") or \"\").strip()\n            run_as = (record.get(\"Run As User\") or \"\").strip()\n            task_to_run = (record.get(\"Task To Run\") or \"\").strip()\n            if not task_path or task_path in seen:\n                continue\n            seen.add(task_path)\n            path_low = task_path.lower()\n            process_text = task_to_run or task_path\n            if any(ms in path_low for ms in ms_paths):\n                continue\n            if status.lower() == \"disabled\":\n                continue\n            risk = \"High\" if any(x in (path_low + \" \" + process_text.lower()) for x in [\"temp\",\"tmp\",\"appdata\",\"programdata\",\"public\"]) else \"Medium\"\n            rows.append((\"Unknown Task\", task_path, risk,\n                         f\"Status:{status}  RunAs:{run_as[:30]}  Process:{process_text[:60]}\", \"Disable\",\n                         {\"type\":\"task\",\"path\":task_path}))\n\n        def insert():\n            for r in rows:\n                self._susp_insert(*r)\n            if not batch:\n                self.susp_count_vars[\"tasks\"].set(str(len(rows)))\n                self.susp_status.config(\n                    text=f\"  Task scan: {len(rows)} flagged\", fg=C[\"warning\"] if rows else C[\"success\"])\n        self.after(0, insert)\n        return len(rows)\n\n    # \u2500\u2500 Selection handler \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _susp_on_select(self, event=None):\n        sel = self.susp_tree.selection()\n        if not sel:\n            return\n        iid = sel[0]\n        vals = self.susp_tree.item(iid, \"values\")\n        meta = self._susp_meta.get(iid, {})\n        cat, name, risk, location, action = vals\n        lines = [\n            f\"Category  : {cat}\",\n            f\"Name      : {name}\",\n            f\"Risk      : {risk}\",\n            f\"Location  : {location}\",\n            f\"Action    : {action}\",\n            \"\",\n        ]\n        if meta.get(\"exe\"):\n            lines.append(f\"EXE Path  : {meta['exe']}\")\n        if meta.get(\"cmdline\"):\n            lines.append(f\"CMD Line  : {meta['cmdline'][:200]}\")\n        if meta.get(\"value\"):\n            lines.append(f\"Reg Value : {meta['value']}\")\n        lines += [\"\", \"\u2500\"*50, \"\"]\n        t = meta.get(\"type\",\"\")\n        if risk == \"High\":\n            lines.append(\"\u26a0 RECOMMENDATION: High-risk entry detected!\")\n            lines.append(\"  \u2192 Terminate/disable immediately if you don't recognize it.\")\n            lines.append(\"  \u2192 Upload the EXE to virustotal.com for verification.\")\n        elif risk == \"Medium\":\n            lines.append(\"\u26a0 RECOMMENDATION: Unknown entry \u2014 verify before disabling.\")\n            lines.append(\"  \u2192 Search the process name online.\")\n            lines.append(\"  \u2192 If not recognized, use 'Disable Selected'.\")\n        else:\n            lines.append(\"\u2139 LOW RISK \u2014 Unusual location but may be legitimate.\")\n            lines.append(\"  \u2192 Monitor if CPU/RAM usage is high.\")\n        if t == \"proc\":\n            lines.append(f\"\\nKill command: taskkill /PID {meta.get('pid','')} /F\")\n        elif t in (\"reg_startup\",\"folder_startup\"):\n            lines.append(\"\\nTo remove: use 'Disable Selected' button above.\")\n        elif t == \"task\":\n            lines.append(f\"\\nDisable: schtasks /Change /TN \\\"{meta.get('path','')}\\\" /Disable\")\n\n        self.susp_detail.config(state=\"normal\")\n        self.susp_detail.delete(\"1.0\",\"end\")\n        self.susp_detail.insert(\"end\", \"\\n\".join(lines))\n        self.susp_detail.config(state=\"disabled\")\n\n    # \u2500\u2500 Action buttons \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _susp_kill_selected(self):\n        sel = self.susp_tree.selection()\n        if not sel:\n            messagebox.showinfo(\"No Selection\",\"Select a running process entry to kill.\")\n            return\n        killed = 0\n        for iid in sel:\n            meta = self._susp_meta.get(iid, {})\n            if meta.get(\"type\") == \"proc\":\n                pid = meta.get(\"pid\")\n                if pid and messagebox.askyesno(\"Kill Process\",\n                        f\"Kill PID {pid} ({self.susp_tree.item(iid,'values')[1]})?\"):\n                    out, rc = self._run_cmd(f'taskkill /PID {pid} /F')\n                    if rc == 0:\n                        self.susp_tree.delete(iid)\n                        killed += 1\n                    else:\n                        messagebox.showerror(\"Failed\", f\"Could not kill PID {pid}:\\n{out}\")\n        if killed:\n            self._set_status(f\"Killed {killed} process(es)\", C[\"success\"])\n\n    def _susp_disable_selected(self):\n        sel = self.susp_tree.selection()\n        if not sel:\n            messagebox.showinfo(\"No Selection\",\"Select an entry to disable.\")\n            return\n        disabled = 0\n        for iid in sel:\n            meta = self._susp_meta.get(iid, {})\n            t = meta.get(\"type\",\"\")\n            name_disp = self.susp_tree.item(iid,\"values\")[1]\n            if not messagebox.askyesno(\"Disable Entry\", f\"Disable '{name_disp}'?\"):\n                continue\n            try:\n                if t == \"reg_startup\":\n                    hive = meta[\"hive\"]\n                    path = meta[\"path\"]\n                    name = meta[\"name\"]\n                    value = meta[\"value\"]\n                    key = winreg.OpenKey(hive, path, 0,\n                                        winreg.KEY_SET_VALUE | winreg.KEY_READ)\n                    # Rename with disabled prefix\n                    winreg.SetValueEx(key, \"__GodawariDisabled__\"+name, 0,\n                                      winreg.REG_SZ, value)\n                    winreg.DeleteValue(key, name)\n                    winreg.CloseKey(key)\n                    disabled += 1\n                    self.susp_tree.delete(iid)\n                elif t == \"folder_startup\":\n                    src = Path(meta[\"path\"])\n                    dst = src.with_name(src.name + \".disabled\")\n                    if src.exists():\n                        src.rename(dst)\n                    disabled += 1\n                    self.susp_tree.delete(iid)\n                elif t == \"task\":\n                    task_path = meta.get(\"path\",\"\")\n                    self._run_cmd(f'schtasks /Change /TN \"{task_path}\" /Disable')\n                    disabled += 1\n                    self.susp_tree.delete(iid)\n                elif t == \"hidden_file\":\n                    path = meta.get(\"path\",\"\")\n                    if messagebox.askyesno(\"Delete File\",\n                            f\"Delete this suspicious file?\\n{path}\"):\n                        try:\n                            os.remove(path)\n                        except Exception as e:\n                            messagebox.showerror(\"Error\", str(e))\n                    disabled += 1\n                    self.susp_tree.delete(iid)\n            except Exception as e:\n                messagebox.showerror(\"Error\", f\"Could not disable {name_disp}:\\n{e}\")\n        if disabled:\n            self._set_status(f\"Disabled {disabled} suspicious entry(ies)\", C[\"success\"])\n\n    def _create_restore_point(self, description=\"Godawari Optimizer\"):\n        if self._restore_prompt_count &gt; 0:\n            return True\n        mgr = getattr(self, \"restore_point_manager\", None)\n        if mgr is None:\n            return True\n\n        def _ask(desc):\n            return messagebox.askyesno(\"Restore Point\", f\"Create restore point?\\n{desc}\")\n\n        self._restore_prompt_count += 1\n        self._set_status(\"Creating restore point...\", C[\"warning\"])\n        ok = mgr.create(description, ask_callback=_ask, force=False)\n        if ok:\n            self._audit_event(\"restore_point_created\", {\"description\": description})\n            return True\n        return messagebox.askyesno(\"Failed\", \"Restore point failed. Continue anyway?\")\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # HDD / SSD REPAIR SECTION \u2014 Real Actions with Before/After Proof\n    # Features: SMART, Bad Sector Repair, MBR/BCD Fix, NTFS Fix,\n    #           Partition Repair, VSS Repair, Defrag/TRIM, Offline Mode\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _build_hdd_repair(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n\n        # \u2500\u2500 Section Header \u2500\u2500\n        hdr = tk.Frame(frame, bg=C[\"panel\"], pady=10)\n        hdr.pack(fill=\"x\")\n        tk.Label(hdr, text=\"\ud83d\udcbe  HDD / SSD REPAIR CENTER\",\n                 font=(\"Segoe UI\", 15, \"bold\"), fg=C[\"accent\"], bg=C[\"panel\"]).pack(side=\"left\", padx=18)\n        tk.Label(hdr, text=\"Real Repair \u2022 Bad Sector Fix \u2022 MBR/BCD \u2022 NTFS \u2022 Partition \u2022 WinPE Mode\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"left\", padx=6)\n        tk.Frame(hdr, bg=C[\"accent\"], height=2).pack(side=\"bottom\", fill=\"x\")\n\n        # \u2500\u2500 Scrollable content \u2500\u2500\n        outer = tk.Frame(frame, bg=C[\"bg\"])\n        outer.pack(fill=\"both\", expand=True)\n        canvas2 = tk.Canvas(outer, bg=C[\"bg\"], highlightthickness=0)\n        vsb = tk.Scrollbar(outer, orient=\"vertical\", command=canvas2.yview)\n        self.hdd_scroll_frame = tk.Frame(canvas2, bg=C[\"bg\"])\n        self.hdd_scroll_frame.bind(\"\",\n            lambda e: canvas2.configure(scrollregion=canvas2.bbox(\"all\")))\n        hdd_window = canvas2.create_window((0, 0), window=self.hdd_scroll_frame, anchor=\"nw\")\n        canvas2.configure(yscrollcommand=vsb.set)\n        vsb.pack(side=\"right\", fill=\"y\")\n        canvas2.pack(side=\"left\", fill=\"both\", expand=True)\n\n        def _hdd_resize(e):\n            try:\n                canvas2.itemconfig(hdd_window, width=e.width)\n                canvas2.configure(scrollregion=canvas2.bbox(\"all\"))\n            except Exception:\n                pass\n        canvas2.bind(\"\", _hdd_resize)\n\n        def _hdd_scroll(e):\n            canvas2.yview_scroll(int(-1*(e.delta/120)), \"units\")\n        self._bind_scoped_mousewheel(self.hdd_scroll_frame, canvas2)\n        sf = self.hdd_scroll_frame  # shorthand\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # ROW 1 \u2014 Drive Selector + SMART Info\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        row1 = tk.Frame(sf, bg=C[\"bg\"])\n        row1.pack(fill=\"x\", padx=14, pady=(12, 4))\n\n        # Drive Selector Card\n        drv_card = tk.LabelFrame(row1, text=\" \ud83d\uddb4  Drive Selector \",\n                                 font=FONTS[\"subhead\"], fg=C[\"accent\"],\n                                 bg=C[\"card\"], bd=1, relief=\"flat\")\n        drv_card.pack(side=\"left\", fill=\"y\", padx=(0, 8))\n\n        tk.Label(drv_card, text=\"Target Drive:\", font=FONTS[\"body\"],\n                 fg=C[\"text_dim\"], bg=C[\"card\"]).grid(row=0, column=0, padx=10, pady=6, sticky=\"w\")\n        self.hdd_drive_var = tk.StringVar(value=\"C:\")\n        drives = self._get_available_drives()\n        drv_cb = ttk.Combobox(drv_card, textvariable=self.hdd_drive_var,\n                               values=drives, width=8, state=\"readonly\")\n        drv_cb.grid(row=0, column=1, padx=8, pady=6)\n\n        tk.Label(drv_card, text=\"Mode:\", font=FONTS[\"body\"],\n                 fg=C[\"text_dim\"], bg=C[\"card\"]).grid(row=1, column=0, padx=10, pady=4, sticky=\"w\")\n        self.hdd_mode_var = tk.StringVar(value=\"Online (Live Windows)\")\n        mode_cb = ttk.Combobox(drv_card, textvariable=self.hdd_mode_var,\n                                values=[\"Online (Live Windows)\", \"Offline / WinPE Mode\"],\n                                width=22, state=\"readonly\")\n        mode_cb.grid(row=1, column=1, padx=8, pady=4)\n\n        tk.Button(drv_card, text=\"\ud83d\udd04  Refresh Drives\", font=FONTS[\"small\"],\n                  bg=C[\"btn\"], fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=self._hdd_refresh_drives(drv_cb)).grid(row=2, column=0, columnspan=2,\n                                                                   padx=10, pady=8, sticky=\"ew\")\n\n        # SMART Status Card\n        smart_card = tk.LabelFrame(row1, text=\" \ud83d\udcca  S.M.A.R.T. Drive Health \",\n                                    font=FONTS[\"subhead\"], fg=C[\"accent\"],\n                                    bg=C[\"card\"], bd=1, relief=\"flat\")\n        smart_card.pack(side=\"left\", fill=\"both\", expand=True)\n\n        self.smart_log = scrolledtext.ScrolledText(smart_card, font=FONTS[\"mono\"],\n                                                    bg=\"#050D1A\", fg=C[\"success\"],\n                                                    height=7, state=\"disabled\",\n                                                    insertbackground=C[\"accent\"])\n        self.smart_log.pack(fill=\"both\", expand=True, padx=8, pady=6)\n\n        btn_smart_row = tk.Frame(smart_card, bg=C[\"card\"])\n        btn_smart_row.pack(fill=\"x\", padx=8, pady=(0, 8))\n        tk.Button(btn_smart_row, text=\"\ud83d\udcca Full SMART Report\",\n                  font=FONTS[\"small\"], bg=C[\"btn_info\"], fg=C[\"text\"],\n                  bd=0, padx=10, pady=5, cursor=\"hand2\",\n                  command=self._hdd_smart_report).pack(side=\"left\", padx=4)\n        tk.Button(btn_smart_row, text=\"\u26a1 Quick SMART Check\",\n                  font=FONTS[\"small\"], bg=C[\"btn\"], fg=C[\"text\"],\n                  bd=0, padx=10, pady=5, cursor=\"hand2\",\n                  command=self._hdd_smart_quick).pack(side=\"left\", padx=4)\n        tk.Button(btn_smart_row, text=\"\ud83d\udcbe Save Report\",\n                  font=FONTS[\"small\"], bg=C[\"accent2\"], fg=\"#000\",\n                  bd=0, padx=10, pady=5, cursor=\"hand2\",\n                  command=lambda: self._hdd_save_log(self.smart_log, \"SMART_Report\")).pack(side=\"left\", padx=4)\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # ROW 2 \u2014 Action Buttons Grid\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        row2_lbl = tk.Frame(sf, bg=C[\"bg\"])\n        row2_lbl.pack(fill=\"x\", padx=14, pady=(10, 2))\n        tk.Label(row2_lbl, text=\"\ud83d\udd27  REPAIR ACTIONS  \u2014  Har button real command chalata hai. Proof log mein dikh'ta hai.\",\n                 font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"bg\"]).pack(side=\"left\")\n\n        row2 = tk.Frame(sf, bg=C[\"bg\"])\n        row2.pack(fill=\"x\", padx=14, pady=2)\n\n        def repair_btn(parent, emoji, title, subtitle, color, cmd_func, col, row_n):\n            card = tk.Frame(parent, bg=C[\"card\"], bd=1, relief=\"flat\",\n                            highlightbackground=color, highlightthickness=1)\n            card.grid(row=row_n, column=col, padx=5, pady=5, sticky=\"nsew\")\n            parent.columnconfigure(col, weight=1)\n            tk.Label(card, text=emoji, font=(\"Segoe UI\", 20),\n                     fg=color, bg=C[\"card\"]).pack(pady=(8, 2))\n            tk.Label(card, text=title, font=FONTS[\"subhead\"],\n                     fg=C[\"text\"], bg=C[\"card\"]).pack()\n            tk.Label(card, text=subtitle, font=FONTS[\"small\"],\n                     fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=170).pack(padx=6)\n            tk.Button(card, text=\"\u25b6  Run\", font=FONTS[\"small\"],\n                      bg=color, fg=\"#000\" if color in [C[\"accent\"], C[\"accent2\"]] else C[\"text\"],\n                      bd=0, padx=12, pady=5, cursor=\"hand2\",\n                      command=cmd_func).pack(pady=(6, 10))\n\n        repair_btn(row2, \"\ud83e\ude7a\", \"Bad Sector Scan+Fix\",\n                   \"chkdsk /f /r /x\\nBad sectors mark+recover\", C[\"warning\"],\n                   self._hdd_bad_sector_fix, 0, 0)\n        repair_btn(row2, \"\ud83d\udd11\", \"MBR / Boot Repair\",\n                   \"bootrec /fixmbr\\nbootrec /fixboot\\nbootrec /rebuildbcd\", C[\"accent3\"],\n                   self._hdd_mbr_repair, 1, 0)\n        repair_btn(row2, \"\ud83d\udcc1\", \"NTFS File System Fix\",\n                   \"fsutil dirty bit\\nNTFS journal reset\\nchkdsk /f\", C[\"accent\"],\n                   self._hdd_ntfs_fix, 2, 0)\n        repair_btn(row2, \"\ud83d\udcc2\", \"Partition Table Repair\",\n                   \"diskpart automount\\nPartition visibility\\nDrive letter assign\", C[\"btn_info\"],\n                   self._hdd_partition_repair, 3, 0)\n\n        row2b = tk.Frame(sf, bg=C[\"bg\"])\n        row2b.pack(fill=\"x\", padx=14, pady=2)\n        repair_btn(row2b, \"\ud83d\udd04\", \"VSS / Shadow Copy Fix\",\n                   \"VSS service repair\\nShadow storage reset\", C[\"accent2\"],\n                   self._hdd_vss_repair, 0, 0)\n        repair_btn(row2b, \"\u26a1\", \"SSD TRIM + Optimize\",\n                   \"Optimize-Volume -ReTrim\\nSSD best practice\", C[\"hw_accent\"],\n                   self._hdd_ssd_trim, 1, 0)\n        repair_btn(row2b, \"\ud83d\uddc2\", \"HDD Defrag\",\n                   \"defrag /U /V /X\\nFull defrag + report\", C[\"accent4\"],\n                   self._hdd_defrag, 2, 0)\n        repair_btn(row2b, \"\ud83e\udd16\", \"Auto Optimize (TRIM/Defrag)\",\n                   \"Detect SSD/HDD\\nRun best optimize\", C[\"btn_chip\"],\n                   self._hdd_auto_optimize, 3, 0)\n        repair_btn(row2b, \"\ud83e\uddf9\", \"Disk Cleanup (Deep)\",\n                   \"cleanmgr /sagerun:1\\nSystem files bhi clean\", C[\"btn\"],\n                   self._hdd_deep_cleanup, 3, 0)\n\n        row2c = tk.Frame(sf, bg=C[\"bg\"])\n        row2c.pack(fill=\"x\", padx=14, pady=2)\n        repair_btn(row2c, \"\ud83c\udfe5\", \"SFC + DISM Full Repair\",\n                   \"SFC /scannow output\\nDISM RestoreHealth live\", C[\"accent3\"],\n                   self._hdd_sfc_dism_full, 0, 0)\n        repair_btn(row2c, \"\ud83d\udccb\", \"Error Event Log\",\n                   \"Last 20 Disk errors\\nEvent Viewer data\", C[\"accent\"],\n                   self._hdd_error_log, 1, 0)\n        repair_btn(row2c, \"\ud83d\udca5\", \"BSoD / Crash Dump Info\",\n                   \"Last crash details\\nMinidump analysis\", C[\"accent3\"],\n                   self._hdd_bsod_info, 2, 0)\n        repair_btn(row2c, \"\ud83d\ude80\", \"One-Click Full Repair\",\n                   \"SMART+SFC+CHKDSK\\n+MBR+VSS \u2014 All in one\", C[\"warning\"],\n                   self._hdd_full_repair, 3, 0)\n\n        svc_card = tk.LabelFrame(sf, text=\" \ud83d\udee1\ufe0f  Win32 Telemetry Service Control Panel \",\n                                 font=FONTS[\"subhead\"], fg=C[\"accent4\"],\n                                 bg=C[\"card\"], bd=1, relief=\"flat\")\n        svc_card.pack(fill=\"x\", padx=14, pady=(10, 4))\n        tk.Label(svc_card,\n                 text=\"Only safe, non-essential telemetry services are shown here. Critical OS services are excluded.\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\").pack(anchor=\"w\", padx=10, pady=(10, 2))\n        svc_row = tk.Frame(svc_card, bg=C[\"card\"])\n        svc_row.pack(fill=\"x\", padx=10, pady=(0, 6))\n        self.hdd_service_status_lbl = tk.Label(svc_row, text=\"Telemetry panel ready\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"])\n        self.hdd_service_status_lbl.pack(side=\"left\", anchor=\"w\")\n        tk.Button(svc_row, text=\"\ud83d\udd0d Scan Safe Services\", font=FONTS[\"small\"], bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=10, pady=4, cursor=\"hand2\",\n                  command=self._hdd_refresh_service_list).pack(side=\"right\", padx=4)\n        list_frame = tk.Frame(svc_card, bg=C[\"card\"])\n        list_frame.pack(fill=\"x\", padx=10, pady=(0, 6))\n        self.hdd_service_listbox = tk.Listbox(list_frame, height=4, selectmode=\"extended\",\n                                              bg=C[\"bg\"], fg=C[\"text\"], font=FONTS[\"small\"], relief=\"flat\", bd=0)\n        self.hdd_service_listbox.pack(side=\"left\", fill=\"both\", expand=True)\n        scrollbar = tk.Scrollbar(list_frame, orient=\"vertical\", command=self.hdd_service_listbox.yview)\n        scrollbar.pack(side=\"right\", fill=\"y\")\n        self.hdd_service_listbox.config(yscrollcommand=scrollbar.set)\n        action_row = tk.Frame(svc_card, bg=C[\"card\"])\n        action_row.pack(fill=\"x\", padx=10, pady=(0, 10))\n        tk.Button(action_row, text=\"\u26d4 Stop Selected\", font=FONTS[\"small\"], bg=C[\"btn_warn\"], fg=C[\"text\"], bd=0, padx=10, pady=4, cursor=\"hand2\",\n                  command=self._hdd_stop_selected_telemetry_services).pack(side=\"left\", padx=4)\n        tk.Button(action_row, text=\"\u267b\ufe0f Refresh Status\", font=FONTS[\"small\"], bg=C[\"btn\"], fg=C[\"text\"], bd=0, padx=10, pady=4, cursor=\"hand2\",\n                  command=self._hdd_refresh_service_list).pack(side=\"left\", padx=4)\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # ROW 3 \u2014 WinPE / Offline Mode\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        winpe_card = tk.LabelFrame(sf, text=\" \ud83d\udda5\ufe0f  WinPE / Offline Mode \u2014 Boot-Level Repair Commands \",\n                                    font=FONTS[\"subhead\"], fg=C[\"accent4\"],\n                                    bg=C[\"card\"], bd=1, relief=\"flat\")\n        winpe_card.pack(fill=\"x\", padx=14, pady=(10, 4))\n\n        winpe_info = tk.Frame(winpe_card, bg=C[\"card\"])\n        winpe_info.pack(fill=\"x\", padx=10, pady=(6, 4))\n        info_text = (\"WinPE / Offline Mode mein yeh tool Windows Recovery Environment (RE) ke saath kaam karta hai.\\n\"\n                     \"Jab Windows boot nahi hota \u2014 tab bhi yeh commands kaam karte hain.\\n\"\n                     \"How to use: PC restart karo \u2192 F8/Shift+F8 dabao \u2192 Troubleshoot \u2192 Command Prompt \u2192 script chalao\")\n        tk.Label(winpe_info, text=info_text, font=FONTS[\"small\"], fg=C[\"accent4\"],\n                 bg=C[\"card\"], justify=\"left\").pack(anchor=\"w\")\n\n        winpe_btns = tk.Frame(winpe_card, bg=C[\"card\"])\n        winpe_btns.pack(fill=\"x\", padx=10, pady=(2, 10))\n\n        def wbtn(txt, cmd, col):\n            tk.Button(winpe_btns, text=txt, font=FONTS[\"small\"],\n                      bg=C[\"btn_warn\"], fg=C[\"text\"], bd=0, padx=10, pady=6,\n                      cursor=\"hand2\", command=cmd).grid(row=0, column=col, padx=4, pady=2, sticky=\"ew\")\n            winpe_btns.columnconfigure(col, weight=1)\n\n        wbtn(\"\ud83d\udd11 Generate MBR Fix .bat\", self._winpe_gen_mbr_bat, 0)\n        wbtn(\"\ud83e\ude7a Generate ChkDsk .bat\", self._winpe_gen_chkdsk_bat, 1)\n        wbtn(\"\ud83d\udccb Generate Full Repair .bat\", self._winpe_gen_full_bat, 2)\n        wbtn(\"\ud83d\udcbf Open Windows RE\", self._winpe_open_recovery, 3)\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # ROW 4 \u2014 Action Log\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        log_card = tk.LabelFrame(sf, text=\" \ud83d\udccb  Repair Action Log \u2014 Proof of Every Action \",\n                                  font=FONTS[\"subhead\"], fg=C[\"accent2\"],\n                                  bg=C[\"card\"], bd=1, relief=\"flat\")\n        log_card.pack(fill=\"x\", padx=14, pady=(6, 14))\n\n        log_btns = tk.Frame(log_card, bg=C[\"card\"])\n        log_btns.pack(fill=\"x\", padx=8, pady=(6, 2))\n        tk.Button(log_btns, text=\"\ud83d\uddd1 Clear Log\", font=FONTS[\"small\"],\n                  bg=C[\"btn_danger\"], fg=C[\"text\"], bd=0, padx=8, pady=4,\n                  cursor=\"hand2\",\n                  command=lambda: self._hdd_clear_log()).pack(side=\"left\", padx=4)\n        tk.Button(log_btns, text=\"\ud83d\udcbe Save Log to Desktop\", font=FONTS[\"small\"],\n                  bg=C[\"accent2\"], fg=\"#000\", bd=0, padx=8, pady=4,\n                  cursor=\"hand2\",\n                  command=lambda: self._hdd_save_log(self.hdd_log, \"HDD_Repair_Log\")).pack(side=\"left\", padx=4)\n\n        self.hdd_log = scrolledtext.ScrolledText(log_card, font=FONTS[\"mono\"],\n                                                  bg=\"#030810\", fg=C[\"text\"],\n                                                  height=12, state=\"disabled\",\n                                                  insertbackground=C[\"accent\"])\n        self.hdd_log.pack(fill=\"both\", expand=True, padx=8, pady=(2, 10))\n        self._hdd_log(\"\ud83d\udcbe HDD/SSD Repair Center Ready. Drive select karo aur action lo.\", C[\"accent\"])\n        self._hdd_log(f\"\ud83d\udda5  Mode: {self.hdd_mode_var.get()} | Drive: {self.hdd_drive_var.get()}\", C[\"text_dim\"])\n\n        return frame\n\n    # \u2500\u2500 Drive helpers \u2500\u2500\n    def _get_available_drives(self):\n        drives = []\n        for letter in \"CDEFGHIJKLMNOPQRSTUVWXYZ\":\n            path = f\"{letter}:\\\\\"\n            if os.path.exists(path):\n                drives.append(f\"{letter}:\")\n        return drives if drives else [\"C:\"]\n\n    def _hdd_refresh_drives(self, cb):\n        def _do():\n            drives = self._get_available_drives()\n            cb[\"values\"] = drives\n            self._hdd_log(f\"\ud83d\udd04 Drives refreshed: {', '.join(drives)}\", C[\"accent2\"])\n        return _do\n\n    def _hdd_log(self, msg, color=None):\n        ts = datetime.datetime.now().strftime(\"%H:%M:%S\")\n        full = f\"[{ts}]  {msg}\"\n        self._append_log(self.hdd_log, full, color or C[\"text\"])\n\n    def _hdd_clear_log(self):\n        try:\n            self.hdd_log.config(state=\"normal\")\n            self.hdd_log.delete(\"1.0\", \"end\")\n            self.hdd_log.config(state=\"disabled\")\n        except:\n            pass\n\n    def _hdd_save_log(self, widget, prefix):\n        try:\n            content = widget.get(\"1.0\", \"end\")\n            desktop = os.path.join(os.path.expanduser(\"~\"), \"Desktop\")\n            ts = datetime.datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n            fpath = os.path.join(desktop, f\"{prefix}_{ts}.txt\")\n            with open(fpath, \"w\", encoding=\"utf-8\") as f:\n                f.write(content)\n            messagebox.showinfo(\"Saved\", f\"Log saved to:\\n{fpath}\")\n            self._hdd_log(f\"\ud83d\udcbe Log saved: {fpath}\", C[\"accent2\"])\n        except Exception as e:\n            messagebox.showerror(\"Error\", str(e))\n\n    def _hdd_safe_telemetry_services(self):\n        return {\n            \"diagtrack\": \"Connected User Experiences and Telemetry\",\n            \"wersvc\": \"Windows Error Reporting Service\",\n            \"wmpnetworksvc\": \"WMP Network Sharing Service\",\n            \"dmwappushservice\": \"Device Management WAP Push Service\",\n            \"wsearch\": \"Windows Search\",\n        }\n\n    def _hdd_refresh_service_list(self):\n        try:\n            self.hdd_service_listbox.delete(0, \"end\")\n            safe_services = self._hdd_safe_telemetry_services()\n            found = []\n            for svc in psutil.win_service_iter():\n                try:\n                    info = svc.as_dict(attrs=[\"name\", \"display_name\", \"status\"])\n                except Exception:\n                    continue\n                name = str(info.get(\"name\", \"\") or \"\").lower()\n                if name not in safe_services:\n                    continue\n                display = safe_services.get(name, info.get(\"display_name\", \"Unknown\"))\n                status = str(info.get(\"status\", \"unknown\")).capitalize()\n                entry = f\"{name} | {display} | {status}\"\n                self.hdd_service_listbox.insert(\"end\", entry)\n                found.append(entry)\n            self.hdd_service_status_lbl.config(text=f\"{len(found)} safe telemetry services listed.\")\n            if not found:\n                self.hdd_service_status_lbl.config(text=\"No safe telemetry services found on this system.\")\n        except Exception as e:\n            self.hdd_service_status_lbl.config(text=f\"Service scan failed: {str(e)[:80]}\")\n\n    def _hdd_stop_selected_telemetry_services(self):\n        selected = [self.hdd_service_listbox.get(i) for i in self.hdd_service_listbox.curselection()]\n        if not selected:\n            messagebox.showinfo(\"Select Service\", \"Pehele ek ya zyada service select karo.\")\n            return\n        if not messagebox.askyesno(\"Stop Services\", \"Selected telemetry services ko stop karna safe hai. Continue karo?\"):\n            return\n        stopped = 0\n        errors = []\n        for row in selected:\n            name = row.split(\"|\")[0].strip()\n            try:\n                svc = psutil.win_service_get(name)\n                status = svc.status()\n                if status.lower() == \"running\":\n                    svc.stop()\n                    stopped += 1\n                    self._hdd_service_status_lbl.config(text=f\"Stopping {name}...\")\n                else:\n                    errors.append(f\"{name} already {status}\")\n            except Exception as e:\n                errors.append(f\"{name}: {e}\")\n        if stopped:\n            self._hdd_service_status_lbl.config(text=f\"{stopped} telemetry service(s) stop requested.\")\n        if errors:\n            self._hdd_service_status_lbl.config(text=f\"Errors: {len(errors)} (see log)\")\n        self._hdd_recovery_emit_metrics({\n            \"service_control\": f\"Stopped {stopped} services | Errors: {len(errors)}\",\n            \"status_text\": \"Telemetry service control action complete.\",\n            \"progress_pct\": None,\n        })\n\n    def _hdd_action_submit(self, name, target, *args, **kwargs):\n        if not hasattr(self, \"_hdd_action_lock\"):\n            self._hdd_action_lock = threading.Lock()\n            self._hdd_action_running = False\n        with self._hdd_action_lock:\n            if getattr(self, \"_hdd_action_running\", False):\n                self._hdd_log(\"\u26a0\ufe0f HDD/Recovery action already running \u2014 duplicate request skipped.\", C[\"warning\"])\n                return False\n            self._hdd_action_running = True\n\n        def _wrapped(*args, **kwargs):\n            try:\n                return target(*args, **kwargs)\n            finally:\n                with self._hdd_action_lock:\n                    self._hdd_action_running = False\n                try:\n                    gc.collect()\n                except Exception:\n                    pass\n\n        manager = getattr(self, \"worker_manager\", None)\n        if manager is not None and hasattr(manager, \"submit\"):\n            try:\n                manager.submit(name, _wrapped, *args, **kwargs)\n                return True\n            except Exception:\n                pass\n        try:\n            threading.Thread(target=_wrapped, args=args, kwargs=kwargs, daemon=True).start()\n            return True\n        except Exception:\n            return False\n\n    def _do_kernel_working_set_trim(self):\n        batch = {\n            \"phase\": \"kernel_trim\",\n            \"status_text\": \"Kernel working-set trim running...\",\n            \"progress_pct\": 0.0,\n            \"trimmed_processes\": 0,\n            \"errors\": 0,\n            \"delta_mb\": 0,\n        }\n        self._hdd_recovery_emit_metrics(batch)\n        before = psutil.virtual_memory()\n        kernel32 = ctypes.windll.kernel32\n        psapi = ctypes.windll.psapi\n        last_dispatch = time.monotonic()\n        safe_system = {\n            \"system\", \"idle\", \"csrss.exe\", \"wininit.exe\", \"services.exe\",\n            \"lsass.exe\", \"smss.exe\", \"svchost.exe\", \"explorer.exe\", \"dwm.exe\",\n            \"taskeng.exe\", \"taskhostw.exe\", \"winlogon.exe\",\n        }\n        for proc in psutil.process_iter(['pid', 'name']):\n            try:\n                pid = int(proc.info.get('pid') or 0)\n                if pid &lt;= 0 or pid == os.getpid():\n                    continue\n                name = str(proc.info.get('name') or '').lower()\n                if name in safe_system:\n                    continue\n                handle = kernel32.OpenProcess(0x001F0FFF, False, pid)\n                if not handle:\n                    continue\n                try:\n                    if psapi.EmptyWorkingSet(handle):\n                        batch[\"trimmed_processes\"] += 1\n                    try:\n                        kernel32.SetProcessWorkingSetSize(handle, -1, -1)\n                    except Exception:\n                        pass\n                finally:\n                    kernel32.CloseHandle(handle)\n            except (PermissionError, psutil.AccessDenied):\n                batch[\"errors\"] += 1\n            except Exception:\n                batch[\"errors\"] += 1\n            if time.monotonic() - last_dispatch &gt;= 0.120:\n                batch[\"status_text\"] = f\"Kernel trim scanning processes... {batch['trimmed_processes']} trimmed\"\n                batch[\"progress_pct\"] = min(100.0, (batch[\"trimmed_processes\"] / max(1, psutil.cpu_count(logical=False) * 3)) * 100.0)\n                self._hdd_recovery_emit_metrics(batch.copy())\n                last_dispatch = time.monotonic()\n        after = psutil.virtual_memory()\n        batch[\"status_text\"] = f\"Kernel trim complete \u2014 {batch['trimmed_processes']} processes trimmed\"\n        batch[\"progress_pct\"] = 100.0\n        batch[\"delta_mb\"] = int((after.available - before.available) / 1024**2)\n        self._hdd_recovery_emit_metrics(batch.copy())\n        self._hdd_log(f\"\u2705 Kernel working set trim complete, freed {self._fmt_size(batch['delta_mb'] * 1024**2)}\", C[\"success\"])\n\n    def _do_background_priority_demotion(self):\n        before = psutil.virtual_memory()\n        batch = {\n            \"phase\": \"priority_demotion\",\n            \"status_text\": \"Background process priority demotion running...\",\n            \"progress_pct\": 0.0,\n            \"demoted\": 0,\n            \"scanned\": 0,\n            \"errors\": 0,\n            \"delta_mb\": 0,\n        }\n        self._hdd_recovery_emit_metrics(batch)\n        idle_class = getattr(psutil, 'IDLE_PRIORITY_CLASS', getattr(psutil, 'BELOW_NORMAL_PRIORITY_CLASS', 64))\n        keep_names = {\n            'explorer.exe', 'taskmgr.exe', 'chrome.exe', 'firefox.exe', 'msedge.exe',\n            'dwm.exe', 'svchost.exe', 'services.exe', 'lsass.exe', 'wininit.exe',\n            'winlogon.exe', 'csrss.exe', 'system', 'idle', 'spoolsv.exe', 'steam.exe',\n        }\n        last_dispatch = time.monotonic()\n        for proc in psutil.process_iter(['pid', 'name', 'username', 'nice']):\n            batch[\"scanned\"] += 1\n            try:\n                pid = int(proc.info.get('pid') or 0)\n                if pid &lt;= 0 or pid == os.getpid():\n                    continue\n                name = str(proc.info.get('name') or '').lower()\n                username = str(proc.info.get('username') or '').lower()\n                if name in keep_names or any(term in name for term in ('microsoft', 'windows', 'service', 'system', 'sql', 'svchost')):\n                    continue\n                if username in ('nt authority\\\\system', 'local service', 'network service'):\n                    continue\n                current = proc.info.get('nice')\n                if current == idle_class:\n                    continue\n                try:\n                    proc.nice(idle_class)\n                    batch[\"demoted\"] += 1\n                except (PermissionError, psutil.AccessDenied):\n                    batch[\"errors\"] += 1\n                except Exception:\n                    batch[\"errors\"] += 1\n            except (PermissionError, psutil.AccessDenied):\n                batch[\"errors\"] += 1\n            except Exception:\n                batch[\"errors\"] += 1\n            if time.monotonic() - last_dispatch &gt;= 0.120:\n                batch[\"status_text\"] = f\"Demoting background apps... {batch['demoted']} demoted\"\n                batch[\"progress_pct\"] = min(100.0, (batch[\"scanned\"] / max(1, psutil.cpu_count(logical=False) * 10)) * 100.0)\n                self._hdd_recovery_emit_metrics(batch.copy())\n                last_dispatch = time.monotonic()\n        after = psutil.virtual_memory()\n        batch[\"status_text\"] = f\"Priority demotion done \u2014 {batch['demoted']} apps moved to idle\"\n        batch[\"progress_pct\"] = 100.0\n        batch[\"delta_mb\"] = int((after.available - before.available) / 1024**2) if 'before' in locals() else 0\n        self._hdd_recovery_emit_metrics(batch.copy())\n        self._hdd_log(f\"\u2705 Background process demotion complete: {batch['demoted']} processes\", C[\"success\"])\n\n    def _do_smart_standby_boost(self):\n        batch = {\n            \"phase\": \"standby_boost\",\n            \"status_text\": \"Smart standby booster evaluating memory...\",\n            \"progress_pct\": 0.0,\n            \"predicted_ram_mb\": 0,\n            \"confidence_score\": 0,\n            \"delta_mb\": 0,\n        }\n        vm = psutil.virtual_memory()\n        before = vm.available\n        standby_bytes = getattr(vm, 'standby', None) or getattr(vm, 'cached', 0)\n        standby_mb = int(standby_bytes / 1024**2)\n        predicted_free_mb = int(min(standby_mb * 0.65, before / 1024**2 * 0.60))\n        batch[\"predicted_ram_mb\"] = predicted_free_mb\n        batch[\"confidence_score\"] = min(98, max(35, int((standby_mb / max(1, vm.total / 1024**2)) * 100)))\n        batch[\"status_text\"] = f\"Standby booster ready \u2014 {self._fmt_size(standby_bytes)} standby memory detected\"\n        self._hdd_recovery_emit_metrics(batch.copy())\n        if standby_mb &lt; 64:\n            batch[\"status_text\"] = \"Standby memory low; no booster action required.\"\n            batch[\"progress_pct\"] = 100.0\n            self._hdd_recovery_emit_metrics(batch.copy())\n            self._hdd_log(\"\u2139\ufe0f Standby booster skipped; standby cache low.\", C[\"text_dim\"])\n            return\n        self._purge_memory_lists()\n        after = psutil.virtual_memory()\n        batch[\"delta_mb\"] = int((after.available - before) / 1024**2)\n        batch[\"status_text\"] = f\"Standby boost complete \u2014 freed {self._fmt_size(batch['delta_mb'] * 1024**2)}\"\n        batch[\"progress_pct\"] = 100.0\n        self._hdd_recovery_emit_metrics(batch.copy())\n        self._hdd_log(f\"\u2705 Standby booster freed {self._fmt_size(batch['delta_mb'] * 1024**2)}\", C[\"success\"])\n\n    def _do_ram_compression_predictor(self):\n        try:\n            vm = psutil.virtual_memory()\n            predicted_free_mb = int(min(vm.available / 1024**2 * 0.20, vm.total / 1024**2 * 0.08))\n            confidence = min(95, max(30, int((100 - vm.percent) * 0.55 + 10)))\n            score_text = f\"Prediction: {self._fmt_size(predicted_free_mb * 1024**2)} free | Confidence {confidence}%\"\n            self.after(0, lambda: self.hdd_compression_pred_var.set(score_text))\n            self._hdd_recovery_emit_metrics({\n                \"phase\": \"compression_predictor\",\n                \"status_text\": \"RAM compression prediction ready\",\n                \"progress_pct\": 100.0,\n                \"predicted_ram_mb\": predicted_free_mb,\n                \"confidence_score\": confidence,\n            })\n            self._hdd_log(f\"\ud83e\udde0 {score_text}\", C[\"accent4\"])\n        except Exception as e:\n            self._hdd_log(f\"Compression predictor failed: {e}\", C[\"warning\"])\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # 1. SMART REPORT\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _hdd_smart_quick(self):\n        drive = self.hdd_drive_var.get().replace(\":\", \"\")\n        self._hdd_log(f\"\ud83d\udcca Quick SMART check: {drive}:\", C[\"accent\"])\n        self._append_log(self.smart_log, f\"[SMART QUICK CHECK \u2014 Drive {drive}:]\\n\", C[\"accent\"])\n\n        def _run():\n            # WMIC disk status\n            out1, rc1 = self._run_cmd(\n                f'wmic diskdrive get Caption,Status,MediaType,Size /format:list', timeout=15)\n            # PowerShell physical disk health\n            out2, rc2 = self._run_cmd(\n                'powershell -Command \"Get-PhysicalDisk | Select FriendlyName,HealthStatus,OperationalStatus,Size | Format-List\"',\n                timeout=15)\n            # Disk space info\n            out3, rc3 = self._run_cmd(\n                f'wmic logicaldisk where \"DeviceID=\\'{drive}:\\'\" get Caption,FreeSpace,Size,FileSystem,VolumeName /format:list',\n                timeout=10)\n\n            self.after(0, lambda: self._append_log(self.smart_log,\n                f\"\u2500\u2500 Physical Disk Status \u2500\u2500\\n{out1}\\n\\n\u2500\u2500 Health Status \u2500\u2500\\n{out2}\\n\\n\u2500\u2500 Logical Disk \u2500\u2500\\n{out3}\\n\",\n                C[\"text\"]))\n            status = \"OK\" if (\"OK\" in out1.upper() or \"HEALTHY\" in out2.upper()) else \"WARNING\"\n            color = C[\"success\"] if status == \"OK\" else C[\"error\"]\n            self.after(0, lambda: self._hdd_log(\n                f\"\u2705 SMART Quick: Drive {drive}: \u2014 Status: {status}\", color))\n            self.after(0, lambda: self._set_status(f\"SMART check done: {status}\", color))\n            if status != \"OK\":\n                self.after(0, lambda: self._hdd_log(\"\u26a0\ufe0f SMART warning detected \u2014 backup data immediately!\", C[\"warning\"]))\n\n        self._launch_job(\"hdd_smart_quick\", _run)\n\n    def _hdd_smart_report(self):\n        drive = self.hdd_drive_var.get().replace(\":\", \"\")\n        self._hdd_log(f\"\ud83d\udcca Full SMART Report starting for {drive}:\", C[\"accent\"])\n        self._append_log(self.smart_log, \"\\n[\u2550\u2550\u2550 FULL SMART REPORT \u2550\u2550\u2550]\\n\", C[\"accent\"])\n\n        def _run():\n            cmds = [\n                (\"Physical Disk Info\",\n                 'wmic diskdrive get Caption,Model,Status,MediaType,Size,InterfaceType,FirmwareRevision /format:list'),\n                (\"Volume Info\",\n                 f'wmic logicaldisk where \"DeviceID=\\'{drive}:\\'\" get Caption,FreeSpace,Size,FileSystem,VolumeName,DriveType /format:list'),\n                (\"Disk Partition\",\n                 f'wmic partition where \"DriveLetter=\\'{drive}:\\'\" get BlockSize,Bootable,Caption,DiskIndex,Index,Size,Type /format:list'),\n                (\"Physical Disk Health (PS)\",\n                 'powershell -Command \"Get-PhysicalDisk | Format-List *\"'),\n                (\"Disk Reliability (PS)\",\n                 'powershell -Command \"Get-Disk | Select Number,FriendlyName,HealthStatus,OperationalStatus,PartitionStyle,Size | Format-List\"'),\n                (\"Disk Errors (Event Log)\",\n                 'powershell -Command \"Get-EventLog -LogName System -Source \\\\\"disk\\\\\" -Newest 10 -ErrorAction SilentlyContinue | Select TimeGenerated,EntryType,Message | Format-List\"'),\n            ]\n            for label, cmd in cmds:\n                out, rc = self._run_cmd(cmd, timeout=20)\n                self.after(0, lambda l=label, o=out: self._append_log(\n                    self.smart_log, f\"\\n\u2500\u2500 {l} \u2500\u2500\\n{o}\\n\", C[\"text_dim\"]))\n\n            self.after(0, lambda: self._hdd_log(\"\u2705 Full SMART Report complete. Smart log mein dekho.\", C[\"success\"]))\n            self.after(0, lambda: self._set_status(\"SMART Report Complete\", C[\"success\"]))\n\n        self._launch_job(\"hdd_smart_report\", _run)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # 2. BAD SECTOR SCAN + FIX\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _hdd_bad_sector_fix(self):\n        drive = self.hdd_drive_var.get()\n        letter = drive.replace(\":\", \"\")\n        is_system = letter.upper() == \"C\"\n\n        if is_system:\n            msg = (f\"Drive {drive} system drive hai (Windows isi pe hai).\\n\\n\"\n                   f\"chkdsk /f /r NEXT BOOT pe schedule hoga.\\n\"\n                   f\"PC restart hoga aur chkdsk boot se pehle chalega.\\n\\n\"\n                   f\"Kya aap restart karke chkdsk schedule karna chahte hain?\")\n        else:\n            msg = (f\"Drive {drive} pe Bad Sector Scan + Fix chalega.\\n\\n\"\n                   f\"Command: chkdsk {drive} /f /r /x\\n\"\n                   f\"  /f = Errors fix karega\\n\"\n                   f\"  /r = Bad sectors dhundega aur data recover karega\\n\"\n                   f\"  /x = Drive forcefully dismount karega\\n\\n\"\n                   f\"\u26a0\ufe0f  Yeh 30-90 minutes le sakta hai!\\n\\n\"\n                   f\"BEFORE:\\n{self._hdd_disk_info_before(drive)}\\n\\nProceed?\")\n\n        if not messagebox.askyesno(\"Bad Sector Repair\", msg):\n            return\n\n        def _run():\n            self.after(0, lambda: self._hdd_log(f\"\ud83e\ude7a Bad Sector Fix started: {drive}\", C[\"accent4\"]))\n            self.after(0, lambda: self._set_status(f\"chkdsk {drive} running...\", C[\"accent4\"]))\n\n            if is_system:\n                # Schedule for next boot\n                out, rc = self._run_cmd(f'echo Y | chkdsk {drive} /f /r', timeout=15)\n                self.after(0, lambda: self._hdd_log(\n                    f\"\ud83d\udccb chkdsk output:\\n{out}\", C[\"text\"]))\n                if rc == 0 or \"schedule\" in out.lower() or \"next time\" in out.lower():\n                    self.after(0, lambda: self._hdd_log(\n                        \"\u2705 PROOF: chkdsk next boot ke liye schedule ho gaya!\", C[\"success\"]))\n                    self.after(0, lambda: messagebox.showinfo(\"Scheduled\",\n                        f\"\u2705 chkdsk {drive}: next restart pe automatically chalega.\\n\\n\"\n                        f\"PROOF: 'chkdsk schedule' registry mein set ho gayi hai.\\n\"\n                        f\"Verify: regedit \u2192 HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Session Manager\\\\BootExecute\"))\n                else:\n                    self.after(0, lambda: self._hdd_log(f\"\u26a0\ufe0f Output: {out}\", C[\"warning\"]))\n            else:\n                # Run immediately on non-system drive\n                out, rc = self._run_cmd(f'chkdsk {drive} /f /r /x', timeout=3600)\n                self.after(0, lambda: self._hdd_log(\n                    f\"\ud83d\udccb chkdsk Full Output:\\n{out[-1000:]}\", C[\"text\"]))\n\n                # Parse results\n                errors_found = any(k in out.lower() for k in\n                    [\"bad sector\", \"error\", \"found\", \"repaired\", \"corrupt\"])\n                clean = any(k in out.lower() for k in\n                    [\"no errors\", \"0 bad sectors\", \"found no problems\"])\n\n                if clean:\n                    self.after(0, lambda: self._hdd_log(\n                        f\"\u2705 PROOF: Drive {drive} \u2014 No bad sectors found. Drive clean hai!\", C[\"success\"]))\n                    self.after(0, lambda: messagebox.showinfo(\"Clean Drive\",\n                        f\"\u2705 Drive {drive}: CLEAN\\n\\nchkdsk ne koi bad sector nahi paaya.\\n\\nFull output log mein hai.\"))\n                elif errors_found:\n                    self.after(0, lambda: self._hdd_log(\n                        f\"\u26a0\ufe0f PROOF: Bad sectors mili/repair ki gayi. Output check karo.\", C[\"warning\"]))\n                    self.after(0, lambda: messagebox.showwarning(\"Repaired\",\n                        f\"\u26a0\ufe0f Drive {drive}: Issues found and repaired.\\n\\nBad sectors data lost ho sakta hai.\\n\\nBackup ASAP recommended!\"))\n                else:\n                    self.after(0, lambda: self._hdd_log(\n                        f\"\ud83d\udccb chkdsk complete. Output log mein hai.\", C[\"text_dim\"]))\n\n            self.after(0, lambda: self._set_status(\"chkdsk Done\", C[\"success\"]))\n\n        self._launch_job(\"hdd_bad_sector_fix\", _run)\n\n    def _hdd_disk_info_before(self, drive):\n        try:\n            usage = psutil.disk_usage(drive + \"\\\\\")\n            total_gb = usage.total / (1024**3)\n            used_gb = usage.used / (1024**3)\n            free_gb = usage.free / (1024**3)\n            return (f\"Drive: {drive}\\n\"\n                    f\"Total: {total_gb:.1f} GB\\n\"\n                    f\"Used:  {used_gb:.1f} GB\\n\"\n                    f\"Free:  {free_gb:.1f} GB ({100 - usage.percent:.1f}% free)\")\n        except:\n            return f\"Drive: {drive} (size info unavailable)\"\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # 3. MBR / BCD REPAIR\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _hdd_mbr_repair(self):\n        msg = (\"\u26a0\ufe0f  MBR / Boot Repair \u2014 Ye sirf tab use karo jab:\\n\\n\"\n               \"\u2022 PC boot nahi ho raha\\n\"\n               \"\u2022 'Boot sector not found' error aa raha hai\\n\"\n               \"\u2022 BCD (Boot Configuration Data) corrupt hai\\n\\n\"\n               \"Commands jo chalenge:\\n\"\n               \"  1. bootrec /fixmbr      \u2190 MBR rewrite\\n\"\n               \"  2. bootrec /fixboot     \u2190 Boot sector fix\\n\"\n               \"  3. bootrec /scanos      \u2190 Windows installations scan\\n\"\n               \"  4. bootrec /rebuildbcd  \u2190 BCD rebuild\\n\\n\"\n               \"REQUIRE: Admin rights (already have) + Restart recommended after.\\n\\n\"\n               \"Proceed?\")\n        if not messagebox.askyesno(\"MBR / Boot Repair\", msg):\n            return\n\n        def _run():\n            self.after(0, lambda: self._hdd_log(\"\ud83d\udd11 MBR/BCD Repair starting...\", C[\"accent3\"]))\n            results = []\n            steps = [\n                (\"bootrec /fixmbr\",     \"MBR rewrite\"),\n                (\"bootrec /fixboot\",    \"Boot sector fix\"),\n                (\"bootrec /scanos\",     \"OS scan\"),\n                (\"bootrec /rebuildbcd\", \"BCD rebuild\"),\n            ]\n            for cmd, label in steps:\n                out, rc = self._run_cmd(cmd, timeout=60)\n                status = \"\u2705\" if rc == 0 else \"\u26a0\ufe0f\"\n                color = C[\"success\"] if rc == 0 else C[\"warning\"]\n                result_line = f\"{status} {label}: rc={rc} | {out[:120]}\"\n                results.append(result_line)\n                self.after(0, lambda r=result_line, c=color: self._hdd_log(r, c))\n\n            summary = \"\\n\".join(results)\n            self.after(0, lambda: messagebox.showinfo(\"MBR/BCD Repair Complete\",\n                f\"\u2705 MBR/BCD Repair Done!\\n\\n{summary}\\n\\n\"\n                f\"PROOF: bootrec commands ran with above return codes.\\n\"\n                f\"Restart karo aur check karo PC boot hota hai ya nahi.\"))\n            self.after(0, lambda: self._set_status(\"MBR/BCD Repair Done\", C[\"success\"]))\n\n        threading.Thread(target=_run, daemon=True).start()\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # 4. NTFS FILE SYSTEM FIX\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _hdd_ntfs_fix(self):\n        drive = self.hdd_drive_var.get()\n        letter = drive.replace(\":\", \"\")\n        msg = (f\"NTFS File System Fix \u2014 Drive {drive}\\n\\n\"\n               f\"Steps:\\n\"\n               f\"  1. Dirty bit check (fsutil dirty query)\\n\"\n               f\"  2. NTFS USN Journal reset\\n\"\n               f\"  3. chkdsk /f (errors fix, no bad sector scan)\\n\\n\"\n               f\"Ye fast hai (5-15 min). System drive pe next boot schedule hoga.\\n\\nProceed?\")\n        if not messagebox.askyesno(\"NTFS Fix\", msg):\n            return\n\n        def _run():\n            self.after(0, lambda: self._hdd_log(f\"\ud83d\udcc1 NTFS Fix: {drive}\", C[\"accent\"]))\n\n            # Step 1: dirty bit\n            out1, _ = self._run_cmd(f'fsutil dirty query {drive}', timeout=10)\n            dirty = \"dirty\" in out1.lower()\n            self.after(0, lambda: self._hdd_log(\n                f\"{'\u26a0\ufe0f Dirty bit SET \u2014 NTFS needs repair' if dirty else '\u2705 Dirty bit: Clean'}\",\n                C[\"warning\"] if dirty else C[\"success\"]))\n\n            # Step 2: USN Journal reset\n            out2, rc2 = self._run_cmd(\n                f'fsutil usn deletejournal /d {drive}', timeout=15)\n            out3, rc3 = self._run_cmd(\n                f'fsutil usn createjournal m=1000 a=100 {drive}', timeout=15)\n            j_ok = rc2 == 0 and rc3 == 0\n            self.after(0, lambda: self._hdd_log(\n                f\"{'\u2705' if j_ok else '\u26a0\ufe0f'} NTFS Journal reset: {'Done' if j_ok else 'Partial (may need admin)'}\",\n                C[\"success\"] if j_ok else C[\"warning\"]))\n\n            # Step 3: chkdsk /f\n            if letter.upper() == \"C\":\n                out4, rc4 = self._run_cmd(f'echo Y | chkdsk {drive} /f', timeout=15)\n                scheduled = True\n            else:\n                out4, rc4 = self._run_cmd(f'chkdsk {drive} /f', timeout=1800)\n                scheduled = False\n\n            self.after(0, lambda: self._hdd_log(\n                f\"\ud83d\udccb chkdsk /f output:\\n{out4[-500:]}\", C[\"text\"]))\n\n            proof = (f\"PROOF:\\n\"\n                     f\"1. Dirty bit: {'SET (needed fix)' if dirty else 'Clean'}\\n\"\n                     f\"2. USN Journal: {'Reset OK' if j_ok else 'Partial'}\\n\"\n                     f\"3. chkdsk /f: {'Scheduled next boot' if scheduled else 'Ran immediately'} (rc={rc4})\\n\\n\"\n                     f\"Full output log mein hai.\")\n            self.after(0, lambda: messagebox.showinfo(\"NTFS Fix Complete\", proof))\n            self.after(0, lambda: self._hdd_log(\"\u2705 NTFS Fix complete.\", C[\"success\"]))\n            self.after(0, lambda: self._set_status(\"NTFS Fix Done\", C[\"success\"]))\n\n        self._launch_job(\"hdd_ntfs_fix\", _run)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # 5. PARTITION TABLE REPAIR\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _hdd_partition_repair(self):\n        drive = self.hdd_drive_var.get()\n        msg = (f\"Partition Repair \u2014 Drive {drive}\\n\\n\"\n               f\"Kya karega:\\n\"\n               f\"  1. Disk list \u2014 saare disks + partitions dikhayega\\n\"\n               f\"  2. Automount enable \u2014 hidden drives visible karega\\n\"\n               f\"  3. Drive letter assign karega agar missing ho\\n\"\n               f\"  4. Volume info + filesystem type check\\n\\n\"\n               f\"Proceed?\")\n        if not messagebox.askyesno(\"Partition Repair\", msg):\n            return\n\n        def _run():\n            self.after(0, lambda: self._hdd_log(\"\ud83d\udcc2 Partition Repair starting...\", C[\"btn_info\"]))\n\n            # Step 1: List disks\n            out1, _ = self._run_cmd(\n                'powershell -Command \"Get-Disk | Select Number,FriendlyName,PartitionStyle,HealthStatus,Size | Format-Table -AutoSize\"',\n                timeout=15)\n            self.after(0, lambda: self._hdd_log(f\"\ud83d\udccb Disk List:\\n{out1}\", C[\"text\"]))\n\n            # Step 2: List volumes\n            out2, _ = self._run_cmd(\n                'powershell -Command \"Get-Volume | Select DriveLetter,FileSystemLabel,FileSystem,HealthStatus,DriveType,Size,SizeRemaining | Format-Table -AutoSize\"',\n                timeout=15)\n            self.after(0, lambda: self._hdd_log(f\"\ud83d\udccb Volume List:\\n{out2}\", C[\"text\"]))\n\n            # Step 3: Enable automount\n            diskpart_script = \"automount enable\\nexit\\n\"\n            tmp = os.path.join(tempfile.gettempdir(), \"goda_diskpart.txt\")\n            with open(tmp, \"w\") as f:\n                f.write(diskpart_script)\n            out3, rc3 = self._run_cmd(f'diskpart /s \"{tmp}\"', timeout=20)\n            self.after(0, lambda: self._hdd_log(\n                f\"{'\u2705' if rc3 == 0 else '\u26a0\ufe0f'} Automount: {out3[:100]}\", C[\"success\"] if rc3 == 0 else C[\"warning\"]))\n\n            # Step 4: Check if target drive letter exists\n            letter = drive.replace(\":\", \"\")\n            out4, _ = self._run_cmd(\n                f'powershell -Command \"Get-Partition | Where-Object DriveLetter -eq \\'{letter}\\' | Format-List *\"',\n                timeout=10)\n            if out4.strip():\n                self.after(0, lambda: self._hdd_log(\n                    f\"\u2705 Drive {drive} partition info:\\n{out4[:300]}\", C[\"success\"]))\n            else:\n                self.after(0, lambda: self._hdd_log(\n                    f\"\u26a0\ufe0f Drive {drive} partition na mile \u2014 drive letter assign karni pad sakti hai\", C[\"warning\"]))\n\n            proof = (f\"PROOF \u2014 Partition Repair Done:\\n\"\n                     f\"1. Disk list fetched: {len(out1.splitlines())} lines\\n\"\n                     f\"2. Volume list fetched: {len(out2.splitlines())} volumes\\n\"\n                     f\"3. Automount enabled: rc={rc3}\\n\"\n                     f\"4. Partition check: {'Found' if out4.strip() else 'Not found (manual assign needed)'}\\n\\n\"\n                     f\"Full details log mein hain.\")\n            self.after(0, lambda: messagebox.showinfo(\"Partition Repair\", proof))\n            self.after(0, lambda: self._set_status(\"Partition Repair Done\", C[\"success\"]))\n\n        threading.Thread(target=_run, daemon=True).start()\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # 6. VSS / SHADOW COPY FIX\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _hdd_vss_repair(self):\n        msg = (\"VSS / Shadow Copy Fix\\n\\n\"\n               \"Steps:\\n\"\n               \"  1. VSS service stop\\n\"\n               \"  2. Old shadow copies delete\\n\"\n               \"  3. Shadow storage resize\\n\"\n               \"  4. VSS service restart\\n\"\n               \"  5. Volume Shadow Copy verify\\n\\n\"\n               \"\u26a0\ufe0f Existing restore points delete ho jayenge!\\n\\nProceed?\")\n        if not messagebox.askyesno(\"VSS Fix\", msg):\n            return\n\n        def _run():\n            self.after(0, lambda: self._hdd_log(\"\ud83d\udd04 VSS Repair starting...\", C[\"accent2\"]))\n            drive = self.hdd_drive_var.get()\n            steps_done = []\n\n            cmds = [\n                (\"net stop vss\",                               \"VSS stop\"),\n                (\"net stop swprv\",                             \"SWPRV stop\"),\n                (\"vssadmin delete shadows /all /quiet\",        \"Delete old shadows\"),\n                (f\"vssadmin resize shadowstorage /for={drive} /on={drive} /maxsize=10%\",\n                                                               \"Resize shadow storage\"),\n                (\"net start swprv\",                            \"SWPRV start\"),\n                (\"net start vss\",                              \"VSS start\"),\n            ]\n            for cmd, label in cmds:\n                out, rc = self._run_cmd(cmd, timeout=30)\n                ok = rc == 0\n                steps_done.append(f\"{'\u2705' if ok else '\u26a0\ufe0f'} {label}\")\n                self.after(0, lambda l=label, o=out, c=(C[\"success\"] if ok else C[\"warning\"]):\n                    self._hdd_log(f\"{'\u2705' if c==C['success'] else '\u26a0\ufe0f'} {l}: {o[:80]}\", c))\n\n            # Verify VSS running\n            out_v, _ = self._run_cmd('sc query vss', timeout=10)\n            running = \"running\" in out_v.lower()\n            self.after(0, lambda: self._hdd_log(\n                f\"{'\u2705 VSS service: RUNNING' if running else '\u26a0\ufe0f VSS service: Not running'}\",\n                C[\"success\"] if running else C[\"warning\"]))\n\n            proof = \"\\n\".join(steps_done) + f\"\\n\\nVSS Final Status: {'RUNNING \u2705' if running else 'Stopped \u26a0\ufe0f'}\"\n            self.after(0, lambda: messagebox.showinfo(\"VSS Repair Complete\",\n                f\"VSS / Shadow Copy Repair Done!\\n\\n{proof}\"))\n            self.after(0, lambda: self._set_status(\"VSS Repair Done\", C[\"success\"]))\n\n        threading.Thread(target=_run, daemon=True).start()\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # 7. SSD TRIM\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _hdd_ssd_trim(self):\n        drive = self.hdd_drive_var.get()\n        letter = drive.replace(\":\", \"\")\n\n        def _run():\n            self.after(0, lambda: self._hdd_log(f\"\u26a1 SSD TRIM + Optimize: {drive}\", C[\"hw_accent\"]))\n\n            # Check if SSD\n            out_type, _ = self._run_cmd(\n                f'powershell -Command \"(Get-PhysicalDisk | Where-Object {{ $_.DeviceId -eq (Get-Partition -DriveLetter \\'{letter}\\' -ErrorAction SilentlyContinue | Select -ExpandProperty DiskNumber) }}).MediaType\"',\n                timeout=10)\n            is_ssd = \"SSD\" in out_type.upper() or \"Solid\" in out_type\n\n            self.after(0, lambda: self._hdd_log(\n                f\"{'\u26a1 SSD detected' if is_ssd else '\u26a0\ufe0f HDD detected \u2014 TRIM not applicable, use Defrag instead'}\",\n                C[\"hw_accent\"] if is_ssd else C[\"warning\"]))\n\n            # TRIM\n            out1, rc1 = self._run_cmd(\n                f'powershell -Command \"Optimize-Volume -DriveLetter {letter} -ReTrim -Verbose\"',\n                timeout=120)\n            # Also optimize\n            out2, rc2 = self._run_cmd(\n                f'defrag {drive} /U /H /L', timeout=120)\n\n            self.after(0, lambda: self._hdd_log(f\"\ud83d\udccb TRIM output:\\n{out1[-300:]}\", C[\"text\"]))\n            self.after(0, lambda: self._hdd_log(\n                f\"{'\u2705' if rc1 == 0 else '\u26a0\ufe0f'} TRIM: rc={rc1}\", C[\"success\"] if rc1 == 0 else C[\"warning\"]))\n\n            proof = (f\"PROOF \u2014 SSD TRIM Done:\\n\"\n                     f\"Drive: {drive}\\n\"\n                     f\"Optimize-Volume -ReTrim: rc={rc1}\\n\"\n                     f\"defrag /L (thin provision): rc={rc2}\\n\"\n                     f\"Output: {out1[:200]}\")\n            self.after(0, lambda: messagebox.showinfo(\"SSD TRIM Complete\", proof))\n            self.after(0, lambda: self._set_status(\"SSD TRIM Done\", C[\"success\"]))\n\n        threading.Thread(target=_run, daemon=True).start()\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # 8. HDD DEFRAG\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _hdd_defrag(self):\n        drive = self.hdd_drive_var.get()\n        letter = drive.replace(\":\", \"\")\n        if not messagebox.askyesno(\"HDD Defrag\",\n            f\"Drive {drive} ko defragment karein?\\n\\n\"\n            f\"Command: defrag {drive} /U /V /X\\n\"\n            f\"  /U = Progress dikhao\\n  /V = Verbose report\\n  /X = Free space consolidate\\n\\n\"\n            f\"\u26a0\ufe0f 30-120 min lag sakta hai!\\n\\nProceed?\"):\n            return\n\n        def _run():\n            # Safety: avoid defrag on SSD (best-effort detection)\n            try:\n                ana, _ = self._run_cmd(f'defrag {drive} /A', timeout=120)\n                low = (ana or \"\").lower()\n                if \"solid state\" in low or \"ssd\" in low:\n                    self.after(0, lambda: self._hdd_log(\n                        f\"\u26a0\ufe0f Detected SSD for {drive}. Defrag skip. Use SSD TRIM instead.\", C[\"warning\"]))\n                    self.after(0, lambda: messagebox.showwarning(\n                        \"SSD Detected\",\n                        f\"Drive {drive} SSD lag rahi hai.\\n\\nSSD pe Defrag recommend nahi hota.\\n'\ud83d\udca8 SSD TRIM' use karo.\"\n                    ))\n                    return\n            except Exception:\n                pass\n            self.after(0, lambda: self._hdd_log(f\"\ud83d\uddc2 Defrag starting: {drive}\", C[\"accent4\"]))\n            self.after(0, lambda: self._set_status(f\"Defrag {drive}...\", C[\"accent4\"]))\n\n            before_info = self._hdd_disk_info_before(drive)\n            out, rc = self._run_cmd(f'defrag {drive} /U /V /X', timeout=7200)\n\n            self.after(0, lambda: self._hdd_log(f\"\ud83d\udccb Defrag output:\\n{out[-800:]}\", C[\"text\"]))\n\n            # Parse fragmentation info\n            lines = out.splitlines()\n            frag_lines = [l for l in lines if \"fragment\" in l.lower() or \"%\" in l]\n\n            proof = (f\"PROOF \u2014 HDD Defrag Done:\\n\\n\"\n                     f\"BEFORE:\\n{before_info}\\n\\n\"\n                     f\"Defrag rc: {rc}\\n\"\n                     f\"Fragmentation info:\\n\" + \"\\n\".join(frag_lines[:5]) +\n                     f\"\\n\\nFull output log mein hai.\")\n            self.after(0, lambda: messagebox.showinfo(\"Defrag Complete\", proof))\n            self.after(0, lambda: self._hdd_log(\"\u2705 Defrag complete!\", C[\"success\"]))\n            self.after(0, lambda: self._set_status(\"Defrag Done\", C[\"success\"]))\n\n        threading.Thread(target=_run, daemon=True).start()\n\n    def _hdd_auto_optimize(self):\n        drive = self.hdd_drive_var.get()\n        if not messagebox.askyesno(\"Auto Optimize\",\n                                   f\"Drive {drive} ke liye best optimize run karein?\\n\\nSSD \u2192 TRIM\\nHDD \u2192 Defrag\"):\n            return\n\n        def _run():\n            # Best-effort detection (simple, robust quoting)\n            out, _ = self._run_cmd(\n                'powershell -Command \"Get-PhysicalDisk | Select FriendlyName,MediaType,HealthStatus | Format-List *\"',\n                timeout=15\n            )\n            low = (out or \"\").lower()\n            if \"ssd\" in low or \"solid state\" in low:\n                self.after(0, lambda: self._hdd_log(\"\ud83e\udd16 Auto: SSD detected \u2192 running TRIM\", C[\"hw_accent\"]))\n                self.after(0, self._hdd_ssd_trim)\n            else:\n                self.after(0, lambda: self._hdd_log(\"\ud83e\udd16 Auto: HDD assumed \u2192 running Defrag\", C[\"accent4\"]))\n                self.after(0, self._hdd_defrag)\n\n        threading.Thread(target=_run, daemon=True).start()\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # 9. DEEP DISK CLEANUP\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _hdd_deep_cleanup(self):\n        drive = self.hdd_drive_var.get()\n        if not messagebox.askyesno(\"Deep Disk Cleanup\",\n            f\"Drive {drive} ka deep cleanup karein?\\n\\n\"\n            f\"Steps:\\n\"\n            f\"  1. cleanmgr /sageset:1 \u2192 all categories select\\n\"\n            f\"  2. cleanmgr /sagerun:1 \u2192 cleanup run\\n\"\n            f\"  3. Windows.old folder check\\n\"\n            f\"  4. Temp/Prefetch cleanup\\n\\nProceed?\"):\n            return\n\n        def _run():\n            self.after(0, lambda: self._hdd_log(\"\ud83e\uddf9 Deep Cleanup starting...\", C[\"btn\"]))\n\n            before = psutil.disk_usage(drive + \"\\\\\").free / (1024**3)\n\n            # Configure cleanup categories before running cleanup\n            cleanup_root = r\"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\VolumeCaches\"\n            categories = [\n                \"Temporary Files\", \"Recycle Bin\", \"Temporary Internet Files\",\n                \"Old ChkDsk Files\", \"Windows Error Reporting Files\",\n                \"Delivery Optimization Files\", \"Thumbnail Cache\",\n                \"Downloaded Program Files\",\n            ]\n            for cat in categories:\n                try:\n                    self._run_cmd(\n                        f'reg add \"{cleanup_root}\\\\{cat}\" /v StateFlags0099 /t REG_DWORD /d 2 /f',\n                        timeout=10)\n                except Exception:\n                    pass\n            self._run_cmd('cleanmgr /sageset:1', timeout=30)\n            out1, rc1 = self._run_cmd('cleanmgr /sagerun:1', timeout=300)\n            self.after(0, lambda: self._hdd_log(\n                f\"{'\u2705' if rc1 == 0 else '\u26a0\ufe0f'} cleanmgr: rc={rc1}\", C[\"success\"] if rc1 == 0 else C[\"warning\"]))\n\n            # Remove Windows.old if exists\n            wold = os.path.join(drive + \"\\\\\", \"Windows.old\")\n            if os.path.exists(wold):\n                try:\n                    out2, rc2 = self._run_cmd(f'rd /s /q \"{wold}\"', timeout=120)\n                    self.after(0, lambda: self._hdd_log(\"\u2705 Windows.old deleted!\", C[\"success\"]))\n                except:\n                    self.after(0, lambda: self._hdd_log(\"\u26a0\ufe0f Windows.old delete failed (in use)\", C[\"warning\"]))\n\n            # Temp cleanup\n            for path in [os.environ.get(\"TEMP\",\"\"), os.environ.get(\"TMP\",\"\"),\n                          \"C:\\\\Windows\\\\Temp\"]:\n                if path and os.path.exists(path):\n                    for f in Path(path).glob(\"*\"):\n                        try:\n                            if f.is_file():\n                                f.unlink()\n                            elif f.is_dir():\n                                shutil.rmtree(str(f), ignore_errors=True)\n                        except:\n                            pass\n\n            after = psutil.disk_usage(drive + \"\\\\\").free / (1024**3)\n            freed = after - before\n            color = C[\"success\"] if freed &gt; 0.1 else C[\"text_dim\"]\n            self.after(0, lambda: self._hdd_log(\n                f\"\u2705 PROOF: Free space {before:.1f} GB \u2192 {after:.1f} GB | Freed: {freed:.2f} GB\", color))\n            self.after(0, lambda: messagebox.showinfo(\"Deep Cleanup Complete\",\n                f\"\u2705 Deep Cleanup Done!\\n\\n\"\n                f\"BEFORE Free: {before:.2f} GB\\n\"\n                f\"AFTER Free:  {after:.2f} GB\\n\"\n                f\"Freed:       {freed:.2f} GB\"))\n            self.after(0, lambda: self._set_status(f\"Cleanup Done \u2014 {freed:.1f}GB freed\", C[\"success\"]))\n\n        threading.Thread(target=_run, daemon=True).start()\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # 10. SFC + DISM (FULL WITH OUTPUT)\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _hdd_sfc_dism_full(self):\n        if not messagebox.askyesno(\"SFC + DISM Full Repair\",\n            \"Windows File Integrity Repair chalein?\\n\\n\"\n            \"Step 1: SFC /scannow (5-15 min)\\n\"\n            \"Step 2: DISM /RestoreHealth (10-30 min)\\n\\n\"\n            \"\u26a0\ufe0f Internet needed for DISM.\\n\"\n            \"Full output log mein dikhega (pehle sirf 'Done' dikh'ta tha \u2014 ab full proof milega)\\n\\nProceed?\"):\n            return\n\n        def _run():\n            self.after(0, lambda: self._hdd_log(\"\ud83c\udfe5 SFC starting...\", C[\"accent3\"]))\n            self.after(0, lambda: self._set_status(\"SFC /scannow running...\", C[\"accent3\"]))\n\n            # SFC with full output capture\n            out_sfc, rc_sfc = self._run_cmd('sfc /scannow', timeout=900)\n            self.after(0, lambda: self._hdd_log(f\"\ud83d\udccb SFC Output:\\n{out_sfc}\", C[\"text\"]))\n\n            if \"no integrity violations\" in out_sfc.lower():\n                sfc_result = \"\u2705 No corrupt files found\"\n                sfc_color = C[\"success\"]\n            elif \"found and repaired\" in out_sfc.lower() or \"repaired\" in out_sfc.lower():\n                sfc_result = \"\u2705 Corrupt files found AND REPAIRED\"\n                sfc_color = C[\"accent4\"]\n            elif \"unable to fix\" in out_sfc.lower():\n                sfc_result = \"\u26a0\ufe0f Some files could not be repaired \u2014 run DISM then retry SFC\"\n                sfc_color = C[\"warning\"]\n            else:\n                sfc_result = f\"\ud83d\udccb SFC rc={rc_sfc} \u2014 check output above\"\n                sfc_color = C[\"text_dim\"]\n\n            self.after(0, lambda: self._hdd_log(f\"SFC PROOF: {sfc_result}\", sfc_color))\n\n            # DISM\n            self.after(0, lambda: self._hdd_log(\"\ud83c\udfe5 DISM RestoreHealth starting...\", C[\"accent3\"]))\n            self.after(0, lambda: self._set_status(\"DISM RestoreHealth...\", C[\"accent3\"]))\n            out_dism, rc_dism = self._run_cmd(\n                'DISM /Online /Cleanup-Image /RestoreHealth', timeout=3600)\n            self.after(0, lambda: self._hdd_log(f\"\ud83d\udccb DISM Output:\\n{out_dism[-800:]}\", C[\"text\"]))\n\n            if rc_dism == 0:\n                dism_result = \"\u2705 DISM RestoreHealth: SUCCESS\"\n                dism_color = C[\"success\"]\n            else:\n                dism_result = f\"\u26a0\ufe0f DISM rc={rc_dism} \u2014 internet check karo ya CBS log dekho\"\n                dism_color = C[\"warning\"]\n\n            self.after(0, lambda: self._hdd_log(f\"DISM PROOF: {dism_result}\", dism_color))\n\n            proof = (f\"FULL PROOF:\\n\\n\"\n                     f\"SFC /scannow:\\n  rc={rc_sfc}\\n  Result: {sfc_result}\\n\\n\"\n                     f\"DISM RestoreHealth:\\n  rc={rc_dism}\\n  Result: {dism_result}\\n\\n\"\n                     f\"Full output HDD log mein hai.\")\n            self.after(0, lambda: messagebox.showinfo(\"SFC + DISM Complete\", proof))\n            self.after(0, lambda: self._set_status(\"SFC + DISM Done\", C[\"success\"]))\n\n        threading.Thread(target=_run, daemon=True).start()\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # 11. ERROR EVENT LOG\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _hdd_error_log(self):\n        def _run():\n            self.after(0, lambda: self._hdd_log(\"\ud83d\udccb Fetching disk error events...\", C[\"accent\"]))\n            out, rc = self._run_cmd(\n                'powershell -Command \"Get-EventLog -LogName System -EntryType Error,Warning -Newest 30 '\n                '-ErrorAction SilentlyContinue | Where-Object {$_.Source -match \\'disk|ntfs|volsnap|storport|iaStorV\\'} '\n                '| Select-Object TimeGenerated,EntryType,Source,Message | Format-List\"',\n                timeout=30)\n            if not out.strip() or rc != 0:\n                out2, _ = self._run_cmd(\n                    'powershell -Command \"Get-WinEvent -LogName System -MaxEvents 50 -ErrorAction SilentlyContinue '\n                    '| Where-Object {$_.Message -match \\'disk|NTFS|sector\\'} '\n                    '| Select-Object TimeCreated,LevelDisplayName,Message | Format-List\"',\n                    timeout=30)\n                out = out2\n\n            self.after(0, lambda: self._hdd_log(\n                f\"\ud83d\udccb Disk Error Events:\\n{out if out.strip() else 'No recent disk errors found \u2014 system clean!'}\",\n                C[\"text\"]))\n\n            if not out.strip():\n                self.after(0, lambda: messagebox.showinfo(\"Event Log\",\n                    \"\u2705 No recent disk errors in Event Log!\\n\\nDisk system clean hai.\"))\n            else:\n                error_count = out.count(\"TimeGenerated\") + out.count(\"TimeCreated\")\n                self.after(0, lambda: messagebox.showwarning(\"Disk Errors Found\",\n                    f\"\u26a0\ufe0f {error_count} disk-related events found!\\n\\n\"\n                    f\"PROOF: Event Log se real data fetch kiya.\\n\"\n                    f\"Full details HDD log mein hain.\\n\\n\"\n                    f\"Recommendation: Bad sector scan chalao.\"))\n            self.after(0, lambda: self._set_status(\"Error Log Fetched\", C[\"success\"]))\n\n        threading.Thread(target=_run, daemon=True).start()\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # 12. BSOD / CRASH INFO\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _hdd_bsod_info(self):\n        def _run():\n            self.after(0, lambda: self._hdd_log(\"\ud83d\udca5 Fetching BSoD / Crash info...\", C[\"accent3\"]))\n\n            # Check minidump folder\n            minidump_path = r\"C:\\Windows\\Minidump\"\n            dumps = []\n            if os.path.exists(minidump_path):\n                dumps = sorted(Path(minidump_path).glob(\"*.dmp\"),\n                               key=lambda x: x.stat().st_mtime, reverse=True)[:5]\n\n            # Get last crash from Event Log\n            out_crash, _ = self._run_cmd(\n                'powershell -Command \"Get-EventLog -LogName System -Source \\'Microsoft-Windows-WER-SystemErrorReporting\\' '\n                '-Newest 5 -ErrorAction SilentlyContinue | Select TimeGenerated,Message | Format-List\"',\n                timeout=20)\n            # Reliability history\n            out_rel, _ = self._run_cmd(\n                'powershell -Command \"Get-WinEvent -ProviderName Microsoft-Windows-Kernel-Power -MaxEvents 5 '\n                '-ErrorAction SilentlyContinue | Select TimeCreated,LevelDisplayName,Message | Format-List\"',\n                timeout=20)\n            # Last BSOD from registry\n            out_reg, _ = self._run_cmd(\n                r'reg query \"HKLM\\SYSTEM\\CurrentControlSet\\Control\\CrashControl\" /v DumpFile',\n                timeout=10)\n\n            dump_info = \"\"\n            if dumps:\n                dump_info = f\"Recent Minidumps ({len(dumps)} files):\\n\"\n                for d in dumps:\n                    mtime = datetime.datetime.fromtimestamp(d.stat().st_mtime).strftime(\"%Y-%m-%d %H:%M\")\n                    dump_info += f\"  \u2022 {d.name} ({mtime}, {d.stat().st_size//1024} KB)\\n\"\n            else:\n                dump_info = \"No minidumps found \u2014 system stable hai ya dump disabled hai\\n\"\n\n            full_info = (f\"[BSoD / Crash Analysis]\\n\\n\"\n                         f\"{dump_info}\\n\"\n                         f\"\u2500\u2500 Event Log Crashes \u2500\u2500\\n{out_crash or 'No crash events'}\\n\\n\"\n                         f\"\u2500\u2500 Kernel Power Events \u2500\u2500\\n{out_rel or 'No power events'}\\n\\n\"\n                         f\"\u2500\u2500 Dump Config \u2500\u2500\\n{out_reg}\")\n\n            self.after(0, lambda: self._hdd_log(full_info, C[\"text\"]))\n            try:\n                deep_report, deep_severity, deep_count = self._build_bsod_deep_report()\n                deep_color = C[\"warning\"] if deep_severity == \"warning\" else C[\"success\"]\n                self.after(0, lambda r=deep_report, c=deep_color: self._hdd_log(\n                    \"\\n[Advanced BSoD Troubleshooting + Solution]\\n\" + r, c))\n            except Exception as e:\n                self.after(0, lambda err=e: self._hdd_log(\n                    f\"Advanced BSoD diagnosis failed: {err}\", C[\"warning\"]))\n\n            if dumps:\n                self.after(0, lambda: messagebox.showwarning(\"Crash Dumps Found\",\n                    f\"\u26a0\ufe0f {len(dumps)} minidump file(s) found!\\n\\n\"\n                    f\"PROOF: C:\\\\Windows\\\\Minidump mein actual .dmp files hain.\\n\\n\"\n                    f\"Latest: {dumps[0].name}\\n\\n\"\n                    f\"Analysis ke liye WinDbg ya WhoCrashed use karo.\"))\n            else:\n                self.after(0, lambda: messagebox.showinfo(\"BSoD Info\",\n                    \"\u2705 No recent BSoD/crash dumps found!\\n\\nSystem stable lag raha hai.\"))\n\n        threading.Thread(target=_run, daemon=True).start()\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # 13. ONE-CLICK FULL REPAIR\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _hdd_full_repair(self):\n        drive = self.hdd_drive_var.get()\n        msg = (f\"\u26a1 ONE-CLICK FULL HDD/SSD REPAIR\\n\\n\"\n               f\"Drive: {drive}\\n\\n\"\n               f\"Ye kya karega:\\n\"\n               f\"  1. \u2705 SMART Quick Check\\n\"\n               f\"  2. \u2705 NTFS Dirty Bit + Journal Reset\\n\"\n               f\"  3. \u2705 VSS / Shadow Copy Repair\\n\"\n               f\"  4. \u2705 SFC /scannow (file integrity)\\n\"\n               f\"  5. \u2705 DISM RestoreHealth\\n\"\n               f\"  6. \u2705 chkdsk /f (next boot if C:)\\n\"\n               f\"  7. \u2705 Deep Temp Cleanup\\n\"\n               f\"  8. \u2705 Error Event Log check\\n\\n\"\n               f\"\u26a0\ufe0f 45-90 minutes lag sakta hai!\\n\"\n               f\"\u26a0\ufe0f Internet DISM ke liye chahiye.\\n\\n\"\n               f\"Proceed?\")\n        if not messagebox.askyesno(\"Full Repair\", msg):\n            return\n\n        def _run():\n            results = []\n            def log_step(msg, color=None):\n                self.after(0, lambda m=msg, c=color: self._hdd_log(m, c or C[\"text\"]))\n                results.append(msg)\n\n            log_step(f\"\ud83d\ude80 FULL REPAIR STARTED \u2014 Drive {drive}\", C[\"accent\"])\n\n            # 1. SMART\n            log_step(\"Step 1/8: SMART Quick Check...\", C[\"text_dim\"])\n            out1, _ = self._run_cmd('wmic diskdrive get Caption,Status /format:list', timeout=15)\n            smart_ok = \"OK\" in out1.upper()\n            log_step(f\"{'\u2705' if smart_ok else '\u26a0\ufe0f'} SMART: {'OK' if smart_ok else 'Warning \u2014 check output'}\",\n                     C[\"success\"] if smart_ok else C[\"warning\"])\n\n            # 2. NTFS\n            log_step(\"Step 2/8: NTFS Journal Reset...\", C[\"text_dim\"])\n            self._run_cmd(f'fsutil usn deletejournal /d {drive}', timeout=15)\n            self._run_cmd(f'fsutil usn createjournal m=1000 a=100 {drive}', timeout=15)\n            log_step(\"\u2705 NTFS Journal reset done\", C[\"success\"])\n\n            # 3. VSS\n            log_step(\"Step 3/8: VSS Repair...\", C[\"text_dim\"])\n            self._run_cmd('net stop vss', timeout=20)\n            self._run_cmd('vssadmin delete shadows /all /quiet', timeout=30)\n            self._run_cmd('net start vss', timeout=20)\n            log_step(\"\u2705 VSS repaired\", C[\"success\"])\n\n            # 4. SFC\n            log_step(\"Step 4/8: SFC /scannow...\", C[\"text_dim\"])\n            out_sfc, rc_sfc = self._run_cmd('sfc /scannow', timeout=900)\n            if \"no integrity violations\" in out_sfc.lower():\n                log_step(\"\u2705 SFC: No corrupt files\", C[\"success\"])\n            elif \"repaired\" in out_sfc.lower():\n                log_step(\"\u2705 SFC: Files repaired!\", C[\"accent4\"])\n            else:\n                log_step(f\"\u26a0\ufe0f SFC rc={rc_sfc}\", C[\"warning\"])\n\n            # 5. DISM\n            log_step(\"Step 5/8: DISM RestoreHealth...\", C[\"text_dim\"])\n            out_dism, rc_dism = self._run_cmd(\n                'DISM /Online /Cleanup-Image /RestoreHealth', timeout=3600)\n            log_step(f\"{'\u2705' if rc_dism == 0 else '\u26a0\ufe0f'} DISM: rc={rc_dism}\",\n                     C[\"success\"] if rc_dism == 0 else C[\"warning\"])\n\n            # 6. chkdsk\n            log_step(\"Step 6/8: chkdsk...\", C[\"text_dim\"])\n            letter = drive.replace(\":\", \"\")\n            if letter.upper() == \"C\":\n                self._run_cmd(f'echo Y | chkdsk {drive} /f', timeout=15)\n                log_step(\"\u2705 chkdsk: Scheduled for next boot (C: drive)\", C[\"success\"])\n            else:\n                out_ck, rc_ck = self._run_cmd(f'chkdsk {drive} /f', timeout=1800)\n                log_step(f\"{'\u2705' if rc_ck == 0 else '\u26a0\ufe0f'} chkdsk: rc={rc_ck}\", C[\"success\"] if rc_ck == 0 else C[\"warning\"])\n\n            # 7. Temp cleanup\n            log_step(\"Step 7/8: Temp cleanup...\", C[\"text_dim\"])\n            before_free = psutil.disk_usage(drive + \"\\\\\").free / (1024**3)\n            for path in [os.environ.get(\"TEMP\",\"\"), \"C:\\\\Windows\\\\Temp\"]:\n                if path and os.path.exists(path):\n                    for f in Path(path).glob(\"*\"):\n                        try:\n                            if f.is_file(): f.unlink()\n                            elif f.is_dir(): shutil.rmtree(str(f), ignore_errors=True)\n                        except: pass\n            after_free = psutil.disk_usage(drive + \"\\\\\").free / (1024**3)\n            log_step(f\"\u2705 Temp cleanup: {after_free - before_free:.1f} GB freed\", C[\"success\"])\n\n            # 8. Error log check\n            log_step(\"Step 8/8: Error log check...\", C[\"text_dim\"])\n            out_err, _ = self._run_cmd(\n                'powershell -Command \"Get-EventLog -LogName System -EntryType Error -Newest 5 '\n                '-ErrorAction SilentlyContinue | Where-Object {$_.Source -match \\'disk|ntfs\\'} | Measure-Object | Select-Object Count\"',\n                timeout=20)\n            log_step(f\"\u2705 Error log checked: {out_err.strip()}\", C[\"success\"])\n\n            # Final summary\n            summary = \"\\n\".join(results[-10:])\n            self.after(0, lambda: messagebox.showinfo(\"\u2705 Full Repair Complete!\",\n                f\"ONE-CLICK FULL REPAIR DONE!\\n\\nDrive: {drive}\\n\\n\"\n                f\"PROOF \u2014 Steps completed:\\n{summary}\\n\\n\"\n                f\"\u26a0\ufe0f Restart karo aur chkdsk boot pe chalega (agar C: drive tha).\\n\"\n                f\"Full details HDD log mein hain.\"))\n            self.after(0, lambda: self._set_status(\"Full Repair DONE!\", C[\"success\"]))\n\n        threading.Thread(target=_run, daemon=True).start()\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # WINPE \u2014 Generate .bat scripts\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _winpe_gen_mbr_bat(self):\n        drive = self.hdd_drive_var.get()\n        content = f\"\"\"@echo off\n:: Godawari Computers \u2014 MBR / BCD Repair Script\n:: WinPE / Recovery Mode mein chalao\n:: Drive: {drive}\necho.\necho ========================================\necho  GODAWARI COMPUTERS \u2014 MBR REPAIR\necho ========================================\necho.\necho Step 1: Fixing MBR...\nbootrec /fixmbr\necho.\necho Step 2: Fixing Boot Sector...\nbootrec /fixboot\necho.\necho Step 3: Scanning OS installations...\nbootrec /scanos\necho.\necho Step 4: Rebuilding BCD...\nbootrec /rebuildbcd\necho.\necho Step 5: Disk list check...\ndiskpart /s %~dp0diskpart_list.txt\necho.\necho ========================================\necho  DONE! Restart karo.\necho ========================================\npause\n\"\"\"\n        diskpart_content = \"list disk\\nlist volume\\nexit\\n\"\n        desktop = os.path.join(os.path.expanduser(\"~\"), \"Desktop\")\n        fpath = os.path.join(desktop, \"Godawari_MBR_Fix.bat\")\n        fpath2 = os.path.join(desktop, \"diskpart_list.txt\")\n        try:\n            with open(fpath, \"w\") as f: f.write(content)\n            with open(fpath2, \"w\") as f: f.write(diskpart_content)\n            self._hdd_log(f\"\u2705 MBR Fix .bat saved: {fpath}\", C[\"success\"])\n            messagebox.showinfo(\"Saved\",\n                f\"\u2705 MBR Repair .bat file Desktop pe save ho gayi!\\n\\n{fpath}\\n\\n\"\n                f\"WinPE mein USB pe copy karo aur chalao.\")\n        except Exception as e:\n            messagebox.showerror(\"Error\", str(e))\n\n    def _winpe_gen_chkdsk_bat(self):\n        drive = self.hdd_drive_var.get()\n        content = f\"\"\"@echo off\n:: Godawari Computers \u2014 ChkDsk Repair Script\n:: WinPE / Recovery Mode mein chalao\necho.\necho ========================================\necho  GODAWARI COMPUTERS \u2014 CHKDSK REPAIR\necho  Drive: {drive}\necho ========================================\necho.\necho Bad Sector Scan + Fix starting...\necho (Yeh 30-90 min le sakta hai)\necho.\nchkdsk {drive} /f /r /x\necho.\necho NTFS Journal Reset...\nfsutil usn deletejournal /d {drive}\nfsutil usn createjournal m=1000 a=100 {drive}\necho.\necho ========================================\necho  DONE!\necho ========================================\npause\n\"\"\"\n        desktop = os.path.join(os.path.expanduser(\"~\"), \"Desktop\")\n        fpath = os.path.join(desktop, \"Godawari_ChkDsk_Fix.bat\")\n        try:\n            with open(fpath, \"w\") as f: f.write(content)\n            self._hdd_log(f\"\u2705 ChkDsk .bat saved: {fpath}\", C[\"success\"])\n            messagebox.showinfo(\"Saved\",\n                f\"\u2705 ChkDsk .bat Desktop pe save ho gayi!\\n\\n{fpath}\\n\\n\"\n                f\"WinPE ya Recovery CMD mein chalao.\")\n        except Exception as e:\n            messagebox.showerror(\"Error\", str(e))\n\n    def _winpe_gen_full_bat(self):\n        drive = self.hdd_drive_var.get()\n        content = f\"\"\"@echo off\n:: Godawari Computers \u2014 Full Repair Script\n:: WinPE / Recovery Mode mein chalao\necho.\necho ========================================\necho  GODAWARI COMPUTERS \u2014 FULL REPAIR\necho  Drive: {drive}\necho ========================================\necho.\necho [1/6] MBR Fix...\nbootrec /fixmbr\nbootrec /fixboot\nbootrec /rebuildbcd\necho.\necho [2/6] Bad Sector Scan...\nchkdsk {drive} /f /r /x\necho.\necho [3/6] NTFS Fix...\nfsutil usn deletejournal /d {drive}\nfsutil usn createjournal m=1000 a=100 {drive}\necho.\necho [4/6] SFC Scan...\nsfc /scannow\necho.\necho [5/6] DISM Repair...\nDISM /Online /Cleanup-Image /RestoreHealth\necho.\necho [6/6] DNS + Network Reset...\nipconfig /flushdns\nnetsh winsock reset\nnetsh int ip reset\necho.\necho ========================================\necho  ALL DONE! Restart karo.\necho ========================================\npause\n\"\"\"\n        desktop = os.path.join(os.path.expanduser(\"~\"), \"Desktop\")\n        fpath = os.path.join(desktop, \"Godawari_Full_Repair.bat\")\n        try:\n            with open(fpath, \"w\") as f: f.write(content)\n            self._hdd_log(f\"\u2705 Full Repair .bat saved: {fpath}\", C[\"success\"])\n            messagebox.showinfo(\"Saved\",\n                f\"\u2705 Full Repair .bat Desktop pe save ho gayi!\\n\\n{fpath}\\n\\n\"\n                f\"USB pe copy karo \u2192 WinPE/Recovery CMD mein chalao \u2192 Admin rights se.\")\n        except Exception as e:\n            messagebox.showerror(\"Error\", str(e))\n\n    def _winpe_open_recovery(self):\n        if not messagebox.askyesno(\"Open Windows Recovery\",\n            \"Windows Recovery Environment (RE) kholein?\\n\\n\"\n            \"PC restart hoga aur Recovery menu aayega.\\n\\n\"\n            \"Wahan se: Troubleshoot \u2192 Advanced \u2192 Command Prompt\\n\\n\"\n            \"Proceed?\"):\n            return\n        out, rc = self._run_cmd('reagentc /boottore', timeout=15)\n        if rc == 0:\n            self._hdd_log(\"\u2705 Recovery mode set \u2014 restarting...\", C[\"accent4\"])\n            messagebox.showinfo(\"Restarting\",\n                \"\u2705 System Recovery mode mein restart ho raha hai!\\n\\n\"\n                \"Wahan se Command Prompt select karo aur .bat script chalao.\")\n            self._run_cmd('shutdown /r /t 5 /c \"Godawari: Restarting to Recovery\"', timeout=10)\n        else:\n            self._hdd_log(f\"\u26a0\ufe0f reagentc failed: {out} \u2014 manual restart karo F8 dabao\", C[\"warning\"])\n            messagebox.showwarning(\"Manual Method\",\n                \"\u26a0\ufe0f Automatic recovery boot nahi hua.\\n\\n\"\n                \"Manual method:\\n\"\n                \"1. PC restart karo\\n\"\n                \"2. Boot ke time F8 dabao\\n\"\n                \"3. Troubleshoot \u2192 Advanced Options \u2192 Command Prompt\\n\"\n                \"4. Wahan .bat script chalao\")\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # OFFICE &amp; PDF TOOLS SECTION\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _build_office_tools(self, parent):\n        \"\"\"\n        Professional Office &amp; PDF Tools section.\n        Sub-tabs:\n          1. Image / PDF Converter  (JPG\u2192PDF, PDF\u2192Images)\n          2. PDF Operations         (Merge, Split, Rotate, Compress)\n          3. Office Converter       (DOC/XLS/PPT \u2192 PDF, PDF \u2192 Word/Excel)\n          4. Office File Repair     (DOCX, XLSX, PPTX, PDF recovery)\n        Dependencies must be available locally/offline; no runtime downloads.\n        \"\"\"\n        import threading\n\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n\n        # \u2500\u2500 Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        hdr = tk.Frame(frame, bg=C[\"panel\"])\n        hdr.pack(fill=\"x\")\n        tk.Label(hdr, text=\"  \ud83d\udcc4 Office &amp; PDF Tools\",\n                 font=FONTS[\"heading\"], fg=C[\"accent\"], bg=C[\"panel\"]).pack(side=\"left\", pady=10, padx=8)\n        tk.Label(hdr, text=\"Image\u2194PDF \u00b7 Merge \u00b7 Split \u00b7 Convert \u00b7 Repair  |  Offline local engines only\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"left\", pady=10, padx=4)\n\n        # \u2500\u2500 Sub-tab bar \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        tab_bar = tk.Frame(frame, bg=C[\"card\"])\n        tab_bar.pack(fill=\"x\", padx=0, pady=0)\n        tk.Frame(tab_bar, bg=C[\"border\"], height=1).pack(side=\"bottom\", fill=\"x\")\n\n        content_host = tk.Frame(frame, bg=C[\"bg\"])\n        content_host.pack(fill=\"both\", expand=True)\n\n        self._office_tab_frames = {}\n        self._office_active_tab = tk.StringVar(value=\"img_pdf\")\n\n        subtabs = [\n            (\"img_pdf\",    \"\ud83d\uddbc  Image \u2194 PDF\"),\n            (\"pdf_ops\",    \"\ud83d\udccb  PDF Operations\"),\n            (\"office_conv\",\"\ud83d\udcca  Office Converter\"),\n            (\"file_repair\",\"\ud83d\udd27  File Repair\"),\n        ]\n        self._office_tab_btns = {}\n\n        def _switch_office_tab(key):\n            self._office_active_tab.set(key)\n            for k, btn in self._office_tab_btns.items():\n                btn.config(bg=C[\"accent\"] if k == key else C[\"panel\"],\n                           fg=C[\"bg\"]     if k == key else C[\"text\"])\n            for k, f in self._office_tab_frames.items():\n                if k == key:\n                    f.pack(fill=\"both\", expand=True)\n                else:\n                    f.pack_forget()\n\n        for key, label in subtabs:\n            btn = tk.Button(tab_bar, text=label, font=FONTS[\"body\"],\n                            bg=C[\"panel\"], fg=C[\"text\"], bd=0,\n                            padx=18, pady=8, cursor=\"hand2\",\n                            command=lambda k=key: _switch_office_tab(k))\n            btn.pack(side=\"left\")\n            self._office_tab_btns[key] = btn\n\n        # \u2500\u2500 Shared log widget \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        log_host = tk.Frame(frame, bg=C[\"card\"])\n        log_host.pack(fill=\"x\", side=\"bottom\")\n        tk.Label(log_host, text=\"  Activity Log\", font=FONTS[\"small\"],\n                 fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=8, pady=(6,0))\n        self._ot_log = scrolledtext.ScrolledText(log_host, height=5, state=\"disabled\",\n                                                  bg=C[\"bg\"], fg=C[\"text\"], font=FONTS[\"small\"],\n                                                  bd=0, relief=\"flat\")\n        self._ot_log.pack(fill=\"x\", padx=8, pady=(2,6))\n\n        def ot_log(msg, color=None):\n            ts = datetime.datetime.now().strftime(\"%H:%M:%S\")\n            full = f\"[{ts}] {msg}\\n\"\n            self._ot_log.config(state=\"normal\")\n            tag = f\"c{abs(hash(color or 'def'))}\"\n            self._ot_log.tag_config(tag, foreground=color or C[\"text\"])\n            self._ot_log.insert(\"end\", full, tag)\n            self._ot_log.see(\"end\")\n            self._ot_log.config(state=\"disabled\")\n\n        self._ot_log_fn = ot_log\n\n        def _ensure_pkg(pkg_import, pip_name=None):\n            \"\"\"Return True only when an offline/local dependency is already available.\"\"\"\n            pip_name = pip_name or pkg_import\n            try:\n                __import__(pkg_import)\n                return True\n            except ImportError:\n                ot_log(\n                    f\"\u274c Missing local dependency: {pip_name}. Runtime download/install is disabled; bundle the offline wheel/package.\",\n                    C[\"error\"],\n                )\n            return False\n\n        self._ot_ensure_pkg = _ensure_pkg\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # TAB 1 \u2014 Image \u2194 PDF\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        t1 = tk.Frame(content_host, bg=C[\"bg\"])\n        self._office_tab_frames[\"img_pdf\"] = t1\n\n        def _make_card(parent, title):\n            card = tk.Frame(parent, bg=C[\"card\"])\n            card.pack(fill=\"x\", padx=16, pady=8)\n            tk.Label(card, text=title, font=FONTS[\"subhead\"],\n                     fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=10, pady=(8,4))\n            tk.Frame(card, bg=C[\"border\"], height=1).pack(fill=\"x\", padx=10)\n            body = tk.Frame(card, bg=C[\"card\"])\n            body.pack(fill=\"x\", padx=10, pady=8)\n            return body\n\n        # \u2500\u2500 JPG / PNG \u2192 single PDF \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        c1a = _make_card(t1, \"\ud83d\uddbc  Images \u2192 PDF  (JPG / PNG / BMP / TIFF \u2192 one PDF)\")\n        tk.Label(c1a, text=\"Images select karo (multiple Ctrl+click):\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\")\n\n        self._ot_img2pdf_files = tk.StringVar(value=\"\")\n        img2pdf_entry = tk.Entry(c1a, textvariable=self._ot_img2pdf_files,\n                                  font=FONTS[\"small\"], bg=C[\"bg\"], fg=C[\"text\"],\n                                  insertbackground=C[\"text\"], width=60)\n        img2pdf_entry.pack(side=\"left\", padx=(0,6), pady=4)\n\n        def _browse_images():\n            files = filedialog.askopenfilenames(\n                title=\"Images select karo\",\n                filetypes=[(\"Image files\",\"*.jpg *.jpeg *.png *.bmp *.tiff *.tif *.gif *.webp\"),\n                           (\"All files\",\"*.*\")])\n            if files:\n                self._ot_img2pdf_files.set(\";\".join(files))\n\n        tk.Button(c1a, text=\"Browse\u2026\", font=FONTS[\"small\"], bg=C[\"btn_info\"],\n                  fg=C[\"text\"], bd=0, padx=10, pady=4, cursor=\"hand2\",\n                  command=_browse_images).pack(side=\"left\", padx=4)\n\n        def _do_img2pdf():\n            paths = [p.strip() for p in self._ot_img2pdf_files.get().split(\";\") if p.strip()]\n            if not paths:\n                messagebox.showwarning(\"Warning\", \"Pehle images select karo.\")\n                return\n            # Pehli image ke naam se default PDF naam suggest karo\n            first_base = os.path.splitext(os.path.basename(paths[0]))[0] if paths else \"output\"\n            out = filedialog.asksaveasfilename(title=\"Output PDF save karein\",\n                                               defaultextension=\".pdf\",\n                                               initialfile=first_base,\n                                               filetypes=[(\"PDF\",\"*.pdf\")])\n            if not out:\n                return\n            def _run():\n                try:\n                    result = offline_images_to_pdf(\n                        paths,\n                        out,\n                        dpi=150,\n                        margin_mm=10,\n                        quality=85,\n                        auto_orientation=True,\n                        progress=lambda i, total, msg: ot_log(f\"  {i}/{total}: {msg}\", C[\"text_dim\"]),\n                    )\n                    ot_log(f\"\u2705 PDF bana diya: {out}  ({result.get('pages', 0)} images)\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"Done!\",\n                        f\"\u2705 {result.get('pages', 0)} images \u2192 PDF\\n\\n{out}\"))\n                except Exception as ex:\n                    ot_log(f\"\u274c Error: {ex}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n            threading.Thread(target=_run, daemon=True).start()\n\n        tk.Button(c1a, text=\"\u25b6 Convert to PDF\", font=FONTS[\"body\"],\n                  bg=C[\"accent\"], fg=C[\"bg\"], bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=_do_img2pdf).pack(side=\"left\", padx=10)\n\n        # \u2500\u2500 PDF \u2192 Images \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        c1b = _make_card(t1, \"\ud83d\udcc4  PDF \u2192 Images  (choose format: JPG / PNG / BMP / TIFF)\")\n        r1b = tk.Frame(c1b, bg=C[\"card\"])\n        r1b.pack(fill=\"x\")\n        tk.Label(r1b, text=\"PDF file:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_pdf2img_path = tk.StringVar()\n        tk.Entry(r1b, textvariable=self._ot_pdf2img_path, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=48).pack(side=\"left\", padx=4)\n        tk.Button(r1b, text=\"Browse\u2026\", font=FONTS[\"small\"], bg=C[\"btn_info\"],\n                  fg=C[\"text\"], bd=0, padx=10, pady=4, cursor=\"hand2\",\n                  command=lambda: self._ot_pdf2img_path.set(\n                      filedialog.askopenfilename(filetypes=[(\"PDF\",\"*.pdf\"),(\"All\",\"*.*\")])\n                  )).pack(side=\"left\", padx=4)\n\n        r1b2 = tk.Frame(c1b, bg=C[\"card\"])\n        r1b2.pack(fill=\"x\", pady=(4,0))\n        tk.Label(r1b2, text=\"Output format:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_pdf2img_fmt = tk.StringVar(value=\"JPG\")\n        for fmt in (\"JPG\", \"PNG\", \"BMP\", \"TIFF\"):\n            tk.Radiobutton(r1b2, text=fmt, variable=self._ot_pdf2img_fmt, value=fmt,\n                           font=FONTS[\"small\"], bg=C[\"card\"], fg=C[\"text\"],\n                           selectcolor=C[\"bg\"], activebackground=C[\"card\"]).pack(side=\"left\", padx=6)\n\n        tk.Label(r1b2, text=\"  DPI:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_pdf2img_dpi = tk.StringVar(value=\"150\")\n        tk.Entry(r1b2, textvariable=self._ot_pdf2img_dpi, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=5).pack(side=\"left\", padx=4)\n\n        def _do_pdf2img():\n            pdf_path = self._ot_pdf2img_path.get().strip()\n            if not pdf_path or not os.path.isfile(pdf_path):\n                messagebox.showwarning(\"Warning\", \"Valid PDF select karo.\")\n                return\n            out_dir = filedialog.askdirectory(title=\"Output folder choose karo\")\n            if not out_dir:\n                return\n            fmt  = self._ot_pdf2img_fmt.get()\n            try:\n                dpi = int(self._ot_pdf2img_dpi.get())\n            except Exception:\n                dpi = 150\n            def _run():\n                try:\n                    result = offline_pdf_to_images(\n                        pdf_path,\n                        out_dir,\n                        fmt=fmt.lower(),\n                        dpi=dpi,\n                        pages=None,\n                        jpeg_quality=90,\n                        progress=lambda i, total, msg: ot_log(f\"  {i}/{total}: {msg}\", C[\"text_dim\"]),\n                    )\n                    saved = result.get(\"count\", 0)\n                    ot_log(f\"\u2705 {saved} pages saved to: {out_dir}\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"Done!\", f\"\u2705 {saved} images saved!\\n\\n{out_dir}\"))\n                except Exception as ex:\n                    ot_log(f\"\u274c Error: {ex}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n            threading.Thread(target=_run, daemon=True).start()\n\n        tk.Button(c1b, text=\"\u25b6 Convert to Images\", font=FONTS[\"body\"],\n                  bg=C[\"accent\"], fg=C[\"bg\"], bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=_do_pdf2img).pack(anchor=\"w\", pady=(6,0))\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # TAB 2 \u2014 PDF Operations\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        t2 = tk.Frame(content_host, bg=C[\"bg\"])\n        self._office_tab_frames[\"pdf_ops\"] = t2\n\n        # \u2500\u2500 PDF Merge \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        c2a = _make_card(t2, \"\ud83d\udcce  PDF Merge  (multiple PDFs \u2192 ek PDF)\")\n        tk.Label(c2a, text=\"PDFs select karo (order matters):\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\")\n\n        self._ot_merge_list = tk.Listbox(c2a, bg=C[\"bg\"], fg=C[\"text\"], font=FONTS[\"small\"],\n                                          height=4, selectmode=\"extended\",\n                                          selectbackground=C[\"accent\"], activestyle=\"none\")\n        self._ot_merge_list.pack(fill=\"x\", pady=4)\n\n        mr = tk.Frame(c2a, bg=C[\"card\"])\n        mr.pack(fill=\"x\")\n        def _merge_add():\n            files = filedialog.askopenfilenames(filetypes=[(\"PDF\",\"*.pdf\"),(\"All\",\"*.*\")])\n            for f in files:\n                self._ot_merge_list.insert(\"end\", f)\n        def _merge_remove():\n            for i in reversed(self._ot_merge_list.curselection()):\n                self._ot_merge_list.delete(i)\n        def _merge_up():\n            sel = self._ot_merge_list.curselection()\n            for i in sel:\n                if i == 0: continue\n                txt = self._ot_merge_list.get(i)\n                self._ot_merge_list.delete(i)\n                self._ot_merge_list.insert(i-1, txt)\n                self._ot_merge_list.selection_set(i-1)\n        def _merge_down():\n            sel = list(self._ot_merge_list.curselection())\n            for i in reversed(sel):\n                if i &gt;= self._ot_merge_list.size()-1: continue\n                txt = self._ot_merge_list.get(i)\n                self._ot_merge_list.delete(i)\n                self._ot_merge_list.insert(i+1, txt)\n                self._ot_merge_list.selection_set(i+1)\n\n        for txt, cmd in [(\"+ Add PDFs\", _merge_add), (\"\u2715 Remove\", _merge_remove),\n                          (\"\u2191 Up\", _merge_up), (\"\u2193 Down\", _merge_down)]:\n            tk.Button(mr, text=txt, font=FONTS[\"small\"], bg=C[\"btn_info\"], fg=C[\"text\"],\n                      bd=0, padx=8, pady=4, cursor=\"hand2\", command=cmd).pack(side=\"left\", padx=3)\n\n        def _do_merge():\n            files = list(self._ot_merge_list.get(0, \"end\"))\n            if len(files) &lt; 2:\n                messagebox.showwarning(\"Warning\", \"Kam se kam 2 PDFs add karo.\")\n                return\n            out = filedialog.asksaveasfilename(title=\"Merged PDF save karein\",\n                                               defaultextension=\".pdf\",\n                                               filetypes=[(\"PDF\",\"*.pdf\")])\n            if not out:\n                return\n            def _run():\n                try:\n                    if not _ensure_pkg(\"pikepdf\"):\n                        return\n                    import pikepdf\n                    pdf_out = pikepdf.Pdf.new()\n                    for f in files:\n                        with pikepdf.open(f) as src:\n                            pdf_out.pages.extend(src.pages)\n                    pdf_out.save(out)\n                    ot_log(f\"\u2705 Merged {len(files)} PDFs \u2192 {out}\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"Done!\", f\"\u2705 {len(files)} PDFs merge ho gaye!\\n\\n{out}\"))\n                except Exception as ex:\n                    ot_log(f\"\u274c Merge error: {ex}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n            threading.Thread(target=_run, daemon=True).start()\n\n        tk.Button(c2a, text=\"\u25b6 Merge PDFs\", font=FONTS[\"body\"],\n                  bg=C[\"accent\"], fg=C[\"bg\"], bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=_do_merge).pack(anchor=\"w\", pady=(6,0))\n\n        # \u2500\u2500 PDF Split \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        c2b = _make_card(t2, \"\u2702\ufe0f  PDF Split  (ek PDF \u2192 alag alag pages ya ranges)\")\n        r2b = tk.Frame(c2b, bg=C[\"card\"])\n        r2b.pack(fill=\"x\")\n        tk.Label(r2b, text=\"PDF:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_split_path = tk.StringVar()\n        tk.Entry(r2b, textvariable=self._ot_split_path, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=46).pack(side=\"left\", padx=4)\n        tk.Button(r2b, text=\"Browse\u2026\", font=FONTS[\"small\"], bg=C[\"btn_info\"],\n                  fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=lambda: self._ot_split_path.set(\n                      filedialog.askopenfilename(filetypes=[(\"PDF\",\"*.pdf\"),(\"All\",\"*.*\")]))).pack(side=\"left\")\n\n        r2b2 = tk.Frame(c2b, bg=C[\"card\"])\n        r2b2.pack(fill=\"x\", pady=4)\n        tk.Label(r2b2, text=\"Mode:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_split_mode = tk.StringVar(value=\"all\")\n        tk.Radiobutton(r2b2, text=\"Har page alag file\", variable=self._ot_split_mode, value=\"all\",\n                       font=FONTS[\"small\"], bg=C[\"card\"], fg=C[\"text\"],\n                       selectcolor=C[\"bg\"], activebackground=C[\"card\"]).pack(side=\"left\", padx=6)\n        tk.Radiobutton(r2b2, text=\"Range (e.g. 1-3, 5, 7-9):\", variable=self._ot_split_mode, value=\"range\",\n                       font=FONTS[\"small\"], bg=C[\"card\"], fg=C[\"text\"],\n                       selectcolor=C[\"bg\"], activebackground=C[\"card\"]).pack(side=\"left\")\n        self._ot_split_range = tk.StringVar(value=\"1-3, 4-6\")\n        tk.Entry(r2b2, textvariable=self._ot_split_range, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=18).pack(side=\"left\", padx=4)\n\n        def _parse_ranges(text, total):\n            pages = set()\n            for part in text.split(\",\"):\n                part = part.strip()\n                if \"-\" in part:\n                    try:\n                        a, b = part.split(\"-\")\n                        pages.update(range(int(a)-1, int(b)))\n                    except Exception:\n                        pass\n                else:\n                    try:\n                        pages.add(int(part)-1)\n                    except Exception:\n                        pass\n            return sorted(p for p in pages if 0 &lt;= p &lt; total)\n\n        def _do_split():\n            pdf_path = self._ot_split_path.get().strip()\n            if not pdf_path or not os.path.isfile(pdf_path):\n                messagebox.showwarning(\"Warning\", \"Valid PDF select karo.\")\n                return\n            out_dir = filedialog.askdirectory(title=\"Output folder choose karo\")\n            if not out_dir:\n                return\n            mode = self._ot_split_mode.get()\n            def _run():\n                try:\n                    if not _ensure_pkg(\"pikepdf\"):\n                        return\n                    import pikepdf\n                    base = os.path.splitext(os.path.basename(pdf_path))[0]\n                    with pikepdf.open(pdf_path) as src:\n                        total = len(src.pages)\n                        if mode == \"all\":\n                            page_groups = [(i, [i]) for i in range(total)]\n                        else:\n                            idxs = _parse_ranges(self._ot_split_range.get(), total)\n                            if not idxs:\n                                ot_log(\"\u274c Range invalid hai.\", C[\"error\"]); return\n                            # Split on commas \u2192 each comma-segment = one file\n                            raw_parts = [p.strip() for p in self._ot_split_range.get().split(\",\") if p.strip()]\n                            page_groups = []\n                            for seg in raw_parts:\n                                grp = _parse_ranges(seg, total)\n                                page_groups.append((seg, grp))\n                        saved = 0\n                        for label, pages in page_groups:\n                            if not pages:\n                                continue\n                            out_pdf = pikepdf.Pdf.new()\n                            for idx in pages:\n                                out_pdf.pages.append(src.pages[idx])\n                            out_name = f\"{base}_p{label}.pdf\" if mode == \"range\" else f\"{base}_page{label+1:04d}.pdf\"\n                            out_pdf.save(os.path.join(out_dir, out_name))\n                            saved += 1\n                    ot_log(f\"\u2705 Split done: {saved} files \u2192 {out_dir}\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"Done!\", f\"\u2705 {saved} files split!\\n\\n{out_dir}\"))\n                except Exception as ex:\n                    ot_log(f\"\u274c Split error: {ex}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n            threading.Thread(target=_run, daemon=True).start()\n\n        tk.Button(c2b, text=\"\u25b6 Split PDF\", font=FONTS[\"body\"],\n                  bg=C[\"accent\"], fg=C[\"bg\"], bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=_do_split).pack(anchor=\"w\", pady=(6,0))\n\n        # \u2500\u2500 PDF Rotate \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        c2c = _make_card(t2, \"\ud83d\udd04  PDF Rotate  (pages ko rotate karo)\")\n        r2c = tk.Frame(c2c, bg=C[\"card\"])\n        r2c.pack(fill=\"x\")\n        tk.Label(r2c, text=\"PDF:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_rot_path = tk.StringVar()\n        tk.Entry(r2c, textvariable=self._ot_rot_path, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=46).pack(side=\"left\", padx=4)\n        tk.Button(r2c, text=\"Browse\u2026\", font=FONTS[\"small\"], bg=C[\"btn_info\"],\n                  fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=lambda: self._ot_rot_path.set(\n                      filedialog.askopenfilename(filetypes=[(\"PDF\",\"*.pdf\"),(\"All\",\"*.*\")]))).pack(side=\"left\")\n        r2c2 = tk.Frame(c2c, bg=C[\"card\"])\n        r2c2.pack(fill=\"x\", pady=4)\n        tk.Label(r2c2, text=\"Rotation:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_rot_deg = tk.StringVar(value=\"90\")\n        for d in (\"90\", \"180\", \"270\"):\n            tk.Radiobutton(r2c2, text=f\"{d}\u00b0\", variable=self._ot_rot_deg, value=d,\n                           font=FONTS[\"small\"], bg=C[\"card\"], fg=C[\"text\"],\n                           selectcolor=C[\"bg\"], activebackground=C[\"card\"]).pack(side=\"left\", padx=8)\n        tk.Label(r2c2, text=\"  Pages (blank=all, e.g. 1,3,5):\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_rot_pages = tk.StringVar(value=\"\")\n        tk.Entry(r2c2, textvariable=self._ot_rot_pages, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=14).pack(side=\"left\", padx=4)\n\n        def _do_rotate():\n            pdf_path = self._ot_rot_path.get().strip()\n            if not pdf_path or not os.path.isfile(pdf_path):\n                messagebox.showwarning(\"Warning\",\"Valid PDF select karo.\"); return\n            out = filedialog.asksaveasfilename(title=\"Rotated PDF save karein\",\n                                               defaultextension=\".pdf\",\n                                               filetypes=[(\"PDF\",\"*.pdf\")])\n            if not out: return\n            deg = int(self._ot_rot_deg.get())\n            def _run():\n                try:\n                    if not _ensure_pkg(\"pikepdf\"): return\n                    import pikepdf\n                    pages_raw = self._ot_rot_pages.get().strip()\n                    with pikepdf.open(pdf_path) as pdf:\n                        total = len(pdf.pages)\n                        if pages_raw:\n                            idxs = set()\n                            for p in pages_raw.split(\",\"):\n                                try: idxs.add(int(p.strip())-1)\n                                except Exception: pass\n                        else:\n                            idxs = set(range(total))\n                        for i, page in enumerate(pdf.pages):\n                            if i in idxs:\n                                cur = int(page.get(\"/Rotate\", 0))\n                                page[\"/Rotate\"] = (cur + deg) % 360\n                        pdf.save(out)\n                    ot_log(f\"\u2705 Rotated {len(idxs)} pages by {deg}\u00b0 \u2192 {out}\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"Done!\", f\"\u2705 PDF rotated!\\n\\n{out}\"))\n                except Exception as ex:\n                    ot_log(f\"\u274c Rotate error: {ex}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n            threading.Thread(target=_run, daemon=True).start()\n\n        tk.Button(c2c, text=\"\u25b6 Rotate PDF\", font=FONTS[\"body\"],\n                  bg=C[\"accent\"], fg=C[\"bg\"], bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=_do_rotate).pack(anchor=\"w\", pady=(6,0))\n\n        # \u2500\u2500 PDF Compress \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        c2d = _make_card(t2, \"\ud83d\udce6  PDF Compress  (file size kam karo)\")\n        r2d = tk.Frame(c2d, bg=C[\"card\"])\n        r2d.pack(fill=\"x\")\n        tk.Label(r2d, text=\"PDF:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_comp_path = tk.StringVar()\n        tk.Entry(r2d, textvariable=self._ot_comp_path, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=46).pack(side=\"left\", padx=4)\n        tk.Button(r2d, text=\"Browse\u2026\", font=FONTS[\"small\"], bg=C[\"btn_info\"],\n                  fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=lambda: self._ot_comp_path.set(\n                      filedialog.askopenfilename(filetypes=[(\"PDF\",\"*.pdf\"),(\"All\",\"*.*\")]))).pack(side=\"left\")\n\n        def _do_compress():\n            pdf_path = self._ot_comp_path.get().strip()\n            if not pdf_path or not os.path.isfile(pdf_path):\n                messagebox.showwarning(\"Warning\",\"Valid PDF select karo.\"); return\n            out = filedialog.asksaveasfilename(title=\"Compressed PDF save karein\",\n                                               defaultextension=\".pdf\",\n                                               filetypes=[(\"PDF\",\"*.pdf\")])\n            if not out: return\n            def _run():\n                try:\n                    if not _ensure_pkg(\"pikepdf\"): return\n                    import pikepdf\n                    before = os.path.getsize(pdf_path)\n                    with pikepdf.open(pdf_path) as pdf:\n                        pdf.save(out, compress_streams=True, object_stream_mode=pikepdf.ObjectStreamMode.generate)\n                    after = os.path.getsize(out)\n                    saved_pct = max(0, (before-after)/before*100) if before else 0\n                    msg = (f\"\u2705 Compressed!\\n\"\n                           f\"Before: {_human_size(before)}\\n\"\n                           f\"After:  {_human_size(after)}\\n\"\n                           f\"Saved:  {saved_pct:.1f}%\")\n                    ot_log(msg, C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"Done!\", f\"{msg}\\n\\n{out}\"))\n                except Exception as ex:\n                    ot_log(f\"\u274c Compress error: {ex}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n            threading.Thread(target=_run, daemon=True).start()\n\n        tk.Button(c2d, text=\"\u25b6 Compress PDF\", font=FONTS[\"body\"],\n                  bg=C[\"accent\"], fg=C[\"bg\"], bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=_do_compress).pack(anchor=\"w\", pady=(6,0))\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # TAB 3 \u2014 Office Converter\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        t3 = tk.Frame(content_host, bg=C[\"bg\"])\n        self._office_tab_frames[\"office_conv\"] = t3\n\n        tk.Label(t3, text=\"  \u2139\ufe0f  Office Converter requires Microsoft Office (Word/Excel) to be installed.\",\n                 font=FONTS[\"small\"], fg=C[\"accent4\"], bg=C[\"bg\"]).pack(anchor=\"w\", padx=16, pady=(8,2))\n        tk.Label(t3, text=\"  PDF \u2192 Word/Excel uses python-docx + openpyxl (no Office needed).\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"]).pack(anchor=\"w\", padx=16, pady=(0,4))\n\n        # \u2500\u2500 DOC/DOCX/XLS/XLSX/PPT/PPTX \u2192 PDF via Word/Excel COM \u2500\n        c3a = _make_card(t3, \"\ud83d\udcdd  Office File \u2192 PDF  (Word / Excel / PowerPoint)\")\n        r3a = tk.Frame(c3a, bg=C[\"card\"])\n        r3a.pack(fill=\"x\")\n        tk.Label(r3a, text=\"File:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_o2p_path = tk.StringVar()\n        tk.Entry(r3a, textvariable=self._ot_o2p_path, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=46).pack(side=\"left\", padx=4)\n        tk.Button(r3a, text=\"Browse\u2026\", font=FONTS[\"small\"], bg=C[\"btn_info\"],\n                  fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=lambda: self._ot_o2p_path.set(\n                      filedialog.askopenfilename(\n                          filetypes=[(\"Office files\",\"*.doc *.docx *.xls *.xlsx *.ppt *.pptx *.odt *.ods *.odp\"),\n                                     (\"All\",\"*.*\")]))).pack(side=\"left\")\n\n        def _do_office2pdf():\n            src = self._ot_o2p_path.get().strip()\n            if not src or not os.path.isfile(src):\n                messagebox.showwarning(\"Warning\",\"Valid Office file select karo.\"); return\n            out = filedialog.asksaveasfilename(title=\"Output PDF save karein\",\n                                               defaultextension=\".pdf\",\n                                               filetypes=[(\"PDF\",\"*.pdf\")])\n            if not out: return\n            def _run():\n                try:\n                    src_abs = os.path.abspath(src)\n                    out_abs = os.path.abspath(out)\n                    ext = os.path.splitext(src_abs)[1].lower()\n                    try:\n                        ot_log(\"LibreOffice offline engine se convert ho raha hai...\", C[\"text_dim\"])\n                        offline_office_to_pdf(src_abs, out_abs, timeout=180)\n                        ot_log(f\"OK LibreOffice convert done -&gt; {out_abs}\", C[\"success\"])\n                        self.after(0, lambda: messagebox.showinfo(\"Done!\", f\"PDF ready!\\n\\n{out_abs}\"))\n                        return\n                    except Exception as lo_ex:\n                        ot_log(f\"LibreOffice unavailable/failed: {lo_ex}\", C[\"warning\"])\n\n                    try:\n                        offline_office_com_to_pdf(src_abs, out_abs)\n                        ot_log(f\"OK Microsoft Office COM convert done -&gt; {out_abs}\", C[\"success\"])\n                        self.after(0, lambda: messagebox.showinfo(\"Done!\", f\"PDF ready!\\n\\n{out_abs}\"))\n                        return\n                    except Exception as com_ex:\n                        ot_log(f\"Microsoft Office COM unavailable/failed: {com_ex}\", C[\"warning\"])\n\n                    raise RuntimeError(\"No local Office PDF engine available. Install LibreOffice or Microsoft Office.\")\n\n                    # Try LibreOffice first (free)\n                    lo_paths = [\n                        r\"C:\\Program Files\\LibreOffice\\program\\soffice.exe\",\n                        r\"C:\\Program Files (x86)\\LibreOffice\\program\\soffice.exe\",\n                    ]\n                    lo_found = None  # handled by offline_office_to_pdf above\n                    if lo_found:\n                        ot_log(\"LibreOffice se convert ho raha hai\u2026\", C[\"text_dim\"])\n                        tmp_dir = tempfile.mkdtemp()\n                        res = safe_run([lo_found, \"--headless\", \"--convert-to\", \"pdf\",\n                                        \"--outdir\", tmp_dir, src_abs], timeout=120)\n                        gen = os.path.join(tmp_dir, os.path.splitext(os.path.basename(src_abs))[0]+\".pdf\")\n                        if os.path.isfile(gen):\n                            shutil.move(gen, out_abs)\n                            ot_log(f\"\u2705 LibreOffice convert done \u2192 {out_abs}\", C[\"success\"])\n                            self.after(0, lambda: messagebox.showinfo(\"Done!\", f\"\u2705 PDF ready!\\n\\n{out_abs}\"))\n                            return\n                    # COM automation fallback (MS Office required)\n                    try:\n                        import win32com.client\n                    except ImportError:\n                        _ensure_pkg(\"win32com\", \"pywin32\")\n                        import win32com.client\n\n                    if ext in (\".doc\", \".docx\", \".odt\"):\n                        app_prog = \"Word.Application\"\n                        wdFormatPDF = 17\n                        word = win32com.client.DispatchEx(app_prog)\n                        word.Visible = False\n                        try:\n                            doc = word.Documents.Open(src_abs)\n                            doc.SaveAs(out_abs, FileFormat=wdFormatPDF)\n                            doc.Close()\n                        finally:\n                            word.Quit()\n                        ot_log(f\"\u2705 Word \u2192 PDF: {out_abs}\", C[\"success\"])\n                    elif ext in (\".xls\", \".xlsx\", \".ods\"):\n                        xl = win32com.client.DispatchEx(\"Excel.Application\")\n                        xl.Visible = False\n                        try:\n                            wb = xl.Workbooks.Open(src_abs)\n                            wb.ExportAsFixedFormat(0, out_abs)\n                            wb.Close(False)\n                        finally:\n                            xl.Quit()\n                        ot_log(f\"\u2705 Excel \u2192 PDF: {out_abs}\", C[\"success\"])\n                    elif ext in (\".ppt\", \".pptx\", \".odp\"):\n                        pp = win32com.client.DispatchEx(\"PowerPoint.Application\")\n                        pp.Visible = True\n                        try:\n                            prs = pp.Presentations.Open(src_abs, WithWindow=False)\n                            prs.SaveAs(out_abs, 32)   # ppSaveAsPDF = 32\n                            prs.Close()\n                        finally:\n                            pp.Quit()\n                        ot_log(f\"\u2705 PowerPoint \u2192 PDF: {out_abs}\", C[\"success\"])\n                    else:\n                        ot_log(\"\u274c Format supported nahi hai COM automation ke liye.\", C[\"error\"])\n                        return\n                    self.after(0, lambda: messagebox.showinfo(\"Done!\", f\"\u2705 PDF ready!\\n\\n{out_abs}\"))\n                except Exception as ex:\n                    ot_log(f\"Convert error: {ex}\\n(Tip: LibreOffice ya Microsoft Office local/offline install chahiye)\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\",\n                        f\"{ex}\\n\\nTip: LibreOffice ya Microsoft Office local/offline install karke dobara try karo.\"))\n            if getattr(self, \"worker_manager\", None):\n                self.worker_manager.submit(_run, name=\"office_to_pdf\")\n            else:\n                threading.Thread(target=_run, daemon=True).start()\n\n        tk.Button(c3a, text=\"\u25b6 Convert to PDF\", font=FONTS[\"body\"],\n                  bg=C[\"accent\"], fg=C[\"bg\"], bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=_do_office2pdf).pack(anchor=\"w\", pady=(6,0))\n\n        # \u2500\u2500 PDF \u2192 Word (text extraction) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        c3b = _make_card(t3, \"\ud83d\udcc4\u2192\ud83d\udcdd  PDF \u2192 Word  (text extraction \u2014 python-docx)\")\n        r3b = tk.Frame(c3b, bg=C[\"card\"])\n        r3b.pack(fill=\"x\")\n        tk.Label(r3b, text=\"PDF:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_p2w_path = tk.StringVar()\n        tk.Entry(r3b, textvariable=self._ot_p2w_path, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=46).pack(side=\"left\", padx=4)\n        tk.Button(r3b, text=\"Browse\u2026\", font=FONTS[\"small\"], bg=C[\"btn_info\"],\n                  fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=lambda: self._ot_p2w_path.set(\n                      filedialog.askopenfilename(filetypes=[(\"PDF\",\"*.pdf\"),(\"All\",\"*.*\")]))).pack(side=\"left\")\n\n        def _do_pdf2word():\n            pdf_path = self._ot_p2w_path.get().strip()\n            if not pdf_path or not os.path.isfile(pdf_path):\n                messagebox.showwarning(\"Warning\",\"Valid PDF select karo.\"); return\n            out = filedialog.asksaveasfilename(title=\"Word file save karein\",\n                                               defaultextension=\".docx\",\n                                               filetypes=[(\"Word\",\"*.docx\")])\n            if not out: return\n            def _run():\n                try:\n                    if not _ensure_pkg(\"pikepdf\"): return\n                    if not _ensure_pkg(\"docx\", \"python-docx\"): return\n                    import pikepdf, docx\n                    doc = docx.Document()\n                    doc.add_heading(\"PDF \u2192 Word Conversion\", 0)\n                    doc.add_paragraph(f\"Source: {pdf_path}\")\n                    doc.add_paragraph(\"\u2500\" * 60)\n                    # Text extraction via pikepdf content streams\n                    with pikepdf.open(pdf_path) as pdf:\n                        for page_num, page in enumerate(pdf.pages):\n                            doc.add_heading(f\"Page {page_num+1}\", level=2)\n                            try:\n                                raw = page.obj.get(\"/Contents\")\n                                if raw is None:\n                                    doc.add_paragraph(\"[Empty page]\")\n                                    continue\n                                contents = pdf.get_object(raw.objgen) if hasattr(raw, 'objgen') else raw\n                                if hasattr(contents, 'read_bytes'):\n                                    data = contents.read_bytes()\n                                elif hasattr(contents, '__iter__'):\n                                    data = b\"\".join(s.read_bytes() for s in contents if hasattr(s, 'read_bytes'))\n                                else:\n                                    data = b\"\"\n                                try:\n                                    data = zlib.decompress(data)\n                                except Exception:\n                                    pass\n                                text_bits = re.findall(rb'\\(([^)]*)\\)', data)\n                                plain = \" \".join(b.decode(\"latin-1\", errors=\"replace\") for b in text_bits)\n                                doc.add_paragraph(plain[:4000] or \"[Could not extract text \u2014 scanned PDF?]\")\n                            except Exception as pe:\n                                doc.add_paragraph(f\"[Page extract error: {pe}]\")\n                    doc.save(out)\n                    ot_log(f\"\u2705 PDF \u2192 Word done: {out}\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"Done!\",\n                        f\"\u2705 Word file ready!\\n\\n{out}\\n\\n\"\n                        \"Note: Scanned PDFs ke liye OCR (Tesseract) ki zaroorat hoti hai.\"))\n                except Exception as ex:\n                    ot_log(f\"\u274c PDF\u2192Word error: {ex}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n            threading.Thread(target=_run, daemon=True).start()\n\n        tk.Button(c3b, text=\"\u25b6 PDF \u2192 Word\", font=FONTS[\"body\"],\n                  bg=C[\"accent\"], fg=C[\"bg\"], bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=_do_pdf2word).pack(anchor=\"w\", pady=(6,0))\n\n        # \u2500\u2500 PDF \u2192 Excel (table extraction) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        c3c = _make_card(t3, \"\ud83d\udcc4\u2192\ud83d\udcca  PDF \u2192 Excel  (table/text extraction \u2014 openpyxl)\")\n        r3c = tk.Frame(c3c, bg=C[\"card\"])\n        r3c.pack(fill=\"x\")\n        tk.Label(r3c, text=\"PDF:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_p2x_path = tk.StringVar()\n        tk.Entry(r3c, textvariable=self._ot_p2x_path, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=46).pack(side=\"left\", padx=4)\n        tk.Button(r3c, text=\"Browse\u2026\", font=FONTS[\"small\"], bg=C[\"btn_info\"],\n                  fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=lambda: self._ot_p2x_path.set(\n                      filedialog.askopenfilename(filetypes=[(\"PDF\",\"*.pdf\"),(\"All\",\"*.*\")]))).pack(side=\"left\")\n\n        def _do_pdf2excel():\n            pdf_path = self._ot_p2x_path.get().strip()\n            if not pdf_path or not os.path.isfile(pdf_path):\n                messagebox.showwarning(\"Warning\",\"Valid PDF select karo.\"); return\n            out = filedialog.asksaveasfilename(title=\"Excel file save karein\",\n                                               defaultextension=\".xlsx\",\n                                               filetypes=[(\"Excel\",\"*.xlsx\")])\n            if not out: return\n            def _run():\n                try:\n                    if not _ensure_pkg(\"pikepdf\"): return\n                    if not _ensure_pkg(\"openpyxl\"): return\n                    import pikepdf, openpyxl\n                    wb = openpyxl.Workbook()\n                    with pikepdf.open(pdf_path) as pdf:\n                        for page_num, page in enumerate(pdf.pages):\n                            ws = wb.create_sheet(title=f\"Page {page_num+1}\")\n                            ws.append([f\"=== PDF Page {page_num+1} ===\"])\n                            try:\n                                raw = page.obj.get(\"/Contents\")\n                                if raw is None:\n                                    ws.append([\"[Empty page]\"]); continue\n                                contents = pdf.get_object(raw.objgen) if hasattr(raw,'objgen') else raw\n                                if hasattr(contents,'read_bytes'):\n                                    data = contents.read_bytes()\n                                elif hasattr(contents,'__iter__'):\n                                    data = b\"\".join(s.read_bytes() for s in contents if hasattr(s,'read_bytes'))\n                                else:\n                                    data = b\"\"\n                                try: data = zlib.decompress(data)\n                                except Exception: pass\n                                text_bits = re.findall(rb'\\(([^)]*)\\)', data)\n                                lines = \" \".join(b.decode(\"latin-1\",errors=\"replace\") for b in text_bits)\n                                for row in lines.split(\"  \"):\n                                    row = row.strip()\n                                    if row:\n                                        ws.append([row])\n                            except Exception as pe:\n                                ws.append([f\"[Error: {pe}]\"])\n                    if \"Sheet\" in wb.sheetnames:\n                        del wb[\"Sheet\"]\n                    wb.save(out)\n                    ot_log(f\"\u2705 PDF \u2192 Excel done: {out}\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"Done!\",\n                        f\"\u2705 Excel ready!\\n\\n{out}\\n\\n\"\n                        \"Tip: Complex tables ke liye Tabula-py try karo.\"))\n                except Exception as ex:\n                    ot_log(f\"\u274c PDF\u2192Excel error: {ex}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n            threading.Thread(target=_run, daemon=True).start()\n\n        tk.Button(c3c, text=\"\u25b6 PDF \u2192 Excel\", font=FONTS[\"body\"],\n                  bg=C[\"accent\"], fg=C[\"bg\"], bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=_do_pdf2excel).pack(anchor=\"w\", pady=(6,0))\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # TAB 4 \u2014 Office File Repair\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        t4 = tk.Frame(content_host, bg=C[\"bg\"])\n        self._office_tab_frames[\"file_repair\"] = t4\n\n        # \u2500\u2500 Info banner \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        info_bar = tk.Frame(t4, bg=C[\"panel\"])\n        info_bar.pack(fill=\"x\", padx=16, pady=8)\n        tk.Label(info_bar,\n                 text=(\"  \ud83d\udd27  Office File Repair Engine\\n\"\n                       \"  DOCX/XLSX/PPTX = ZIP-based repair (pikepdf/python-docx/openpyxl)\\n\"\n                       \"  PDF = cross-reference table rebuild (pikepdf)\\n\"\n                       \"  Corrupt/truncated files ke liye best-effort recovery\"),\n                 font=FONTS[\"small\"], fg=C[\"text\"], bg=C[\"panel\"],\n                 justify=\"left\").pack(anchor=\"w\", padx=10, pady=8)\n\n        # \u2500\u2500 DOCX Repair \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        c4a = _make_card(t4, \"\ud83d\udcdd  Corrupt DOCX Repair\")\n        r4a = tk.Frame(c4a, bg=C[\"card\"])\n        r4a.pack(fill=\"x\")\n        tk.Label(r4a, text=\"Corrupt DOCX:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_fix_docx_path = tk.StringVar()\n        tk.Entry(r4a, textvariable=self._ot_fix_docx_path, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=44).pack(side=\"left\", padx=4)\n        tk.Button(r4a, text=\"Browse\u2026\", font=FONTS[\"small\"], bg=C[\"btn_info\"],\n                  fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=lambda: self._ot_fix_docx_path.set(\n                      filedialog.askopenfilename(filetypes=[(\"Word\",\"*.docx *.doc\"),(\"All\",\"*.*\")]))).pack(side=\"left\")\n\n        def _do_repair_docx():\n            src = self._ot_fix_docx_path.get().strip()\n            if not src or not os.path.isfile(src):\n                messagebox.showwarning(\"Warning\",\"Valid DOCX select karo.\"); return\n            out = filedialog.asksaveasfilename(title=\"Repaired DOCX save karein\",\n                                               defaultextension=\".docx\",\n                                               filetypes=[(\"Word\",\"*.docx\")])\n            if not out: return\n            def _run():\n                import zipfile\n                try:\n                    # Step 1: try python-docx direct open\n                    if not _ensure_pkg(\"docx\",\"python-docx\"): return\n                    import docx as _docx_mod\n                    try:\n                        doc = _docx_mod.Document(src)\n                        doc.save(out)\n                        ot_log(f\"\u2705 DOCX repair (direct): {out}\", C[\"success\"])\n                        self.after(0, lambda: messagebox.showinfo(\"Done!\", f\"\u2705 DOCX repaired!\\n\\n{out}\"))\n                        return\n                    except Exception as e1:\n                        ot_log(f\"  Direct open failed ({e1}), ZIP recovery try kar raha hai\u2026\", C[\"warning\"])\n\n                    # Step 2: ZIP-level recovery\n                    with zipfile.ZipFile(src, \"r\") as z:\n                        names = z.namelist()\n                    # Try to recover word/document.xml\n                    with zipfile.ZipFile(src, \"r\") as z_in:\n                        tmp_dir = tempfile.mkdtemp()\n                        recovered = []\n                        for name in names:\n                            try:\n                                data = z_in.read(name)\n                                dest = os.path.join(tmp_dir, name)\n                                os.makedirs(os.path.dirname(dest), exist_ok=True)\n                                with open(dest, \"wb\") as f:\n                                    f.write(data)\n                                recovered.append(name)\n                            except Exception:\n                                ot_log(f\"  \u26a0\ufe0f Skip: {name}\", C[\"warning\"])\n                    # Repack\n                    with zipfile.ZipFile(out, \"w\", compression=zipfile.ZIP_DEFLATED) as z_out:\n                        for name in recovered:\n                            z_out.write(os.path.join(tmp_dir, name), name)\n                    shutil.rmtree(tmp_dir, ignore_errors=True)\n                    ot_log(f\"\u2705 DOCX ZIP recovery: {len(recovered)}/{len(names)} parts saved \u2192 {out}\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"Done!\",\n                        f\"\u2705 DOCX ZIP repair done!\\n{len(recovered)}/{len(names)} parts recovered.\\n\\n{out}\"))\n                except Exception as ex:\n                    ot_log(f\"\u274c DOCX repair error: {ex}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n            threading.Thread(target=_run, daemon=True).start()\n\n        tk.Button(c4a, text=\"\u25b6 Repair DOCX\", font=FONTS[\"body\"],\n                  bg=C[\"warning\"], fg=C[\"bg\"], bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=_do_repair_docx).pack(anchor=\"w\", pady=(6,0))\n\n        # \u2500\u2500 XLSX Repair \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        c4b = _make_card(t4, \"\ud83d\udcca  Corrupt XLSX Repair\")\n        r4b = tk.Frame(c4b, bg=C[\"card\"])\n        r4b.pack(fill=\"x\")\n        tk.Label(r4b, text=\"Corrupt XLSX:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_fix_xlsx_path = tk.StringVar()\n        tk.Entry(r4b, textvariable=self._ot_fix_xlsx_path, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=44).pack(side=\"left\", padx=4)\n        tk.Button(r4b, text=\"Browse\u2026\", font=FONTS[\"small\"], bg=C[\"btn_info\"],\n                  fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=lambda: self._ot_fix_xlsx_path.set(\n                      filedialog.askopenfilename(filetypes=[(\"Excel\",\"*.xlsx *.xls\"),(\"All\",\"*.*\")]))).pack(side=\"left\")\n\n        def _do_repair_xlsx():\n            src = self._ot_fix_xlsx_path.get().strip()\n            if not src or not os.path.isfile(src):\n                messagebox.showwarning(\"Warning\",\"Valid XLSX select karo.\"); return\n            out = filedialog.asksaveasfilename(title=\"Repaired XLSX save karein\",\n                                               defaultextension=\".xlsx\",\n                                               filetypes=[(\"Excel\",\"*.xlsx\")])\n            if not out: return\n            def _run():\n                import zipfile\n                try:\n                    if not _ensure_pkg(\"openpyxl\"): return\n                    import openpyxl\n                    # Step 1: direct open\n                    try:\n                        wb = openpyxl.load_workbook(src, read_only=False, data_only=True, keep_links=False)\n                        wb.save(out)\n                        ot_log(f\"\u2705 XLSX repair (direct): {out}\", C[\"success\"])\n                        self.after(0, lambda: messagebox.showinfo(\"Done!\", f\"\u2705 XLSX repaired!\\n\\n{out}\"))\n                        return\n                    except Exception as e1:\n                        ot_log(f\"  Direct open failed ({e1}), ZIP recovery\u2026\", C[\"warning\"])\n                    # Step 2: ZIP recovery\n                    with zipfile.ZipFile(src,\"r\") as z:\n                        names = z.namelist()\n                    tmp_dir = tempfile.mkdtemp()\n                    recovered = []\n                    with zipfile.ZipFile(src,\"r\") as z_in:\n                        for name in names:\n                            try:\n                                data = z_in.read(name)\n                                dest = os.path.join(tmp_dir, name)\n                                os.makedirs(os.path.dirname(dest), exist_ok=True)\n                                with open(dest,\"wb\") as f: f.write(data)\n                                recovered.append(name)\n                            except Exception:\n                                ot_log(f\"  \u26a0\ufe0f Skip: {name}\", C[\"warning\"])\n                    with zipfile.ZipFile(out,\"w\",compression=zipfile.ZIP_DEFLATED) as z_out:\n                        for name in recovered:\n                            z_out.write(os.path.join(tmp_dir,name), name)\n                    shutil.rmtree(tmp_dir, ignore_errors=True)\n                    ot_log(f\"\u2705 XLSX ZIP recovery: {len(recovered)}/{len(names)} \u2192 {out}\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"Done!\",\n                        f\"\u2705 XLSX ZIP repair done!\\n{len(recovered)}/{len(names)} parts recovered.\\n\\n{out}\"))\n                except Exception as ex:\n                    ot_log(f\"\u274c XLSX repair error: {ex}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n            threading.Thread(target=_run, daemon=True).start()\n\n        tk.Button(c4b, text=\"\u25b6 Repair XLSX\", font=FONTS[\"body\"],\n                  bg=C[\"warning\"], fg=C[\"bg\"], bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=_do_repair_xlsx).pack(anchor=\"w\", pady=(6,0))\n\n        # \u2500\u2500 PDF Repair \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        c4c = _make_card(t4, \"\ud83d\udcc4  Corrupt PDF Repair  (cross-reference rebuild \u2014 pikepdf)\")\n        r4c = tk.Frame(c4c, bg=C[\"card\"])\n        r4c.pack(fill=\"x\")\n        tk.Label(r4c, text=\"Corrupt PDF:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_fix_pdf_path = tk.StringVar()\n        tk.Entry(r4c, textvariable=self._ot_fix_pdf_path, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=44).pack(side=\"left\", padx=4)\n        tk.Button(r4c, text=\"Browse\u2026\", font=FONTS[\"small\"], bg=C[\"btn_info\"],\n                  fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=lambda: self._ot_fix_pdf_path.set(\n                      filedialog.askopenfilename(filetypes=[(\"PDF\",\"*.pdf\"),(\"All\",\"*.*\")]))).pack(side=\"left\")\n\n        def _do_repair_pdf():\n            src = self._ot_fix_pdf_path.get().strip()\n            if not src or not os.path.isfile(src):\n                messagebox.showwarning(\"Warning\",\"Valid PDF select karo.\"); return\n            out = filedialog.asksaveasfilename(title=\"Repaired PDF save karein\",\n                                               defaultextension=\".pdf\",\n                                               filetypes=[(\"PDF\",\"*.pdf\")])\n            if not out: return\n            def _run():\n                try:\n                    if not _ensure_pkg(\"pikepdf\"): return\n                    import pikepdf\n                    before = os.path.getsize(src)\n                    with pikepdf.open(src, suppress_warnings=False,\n                                      allow_overwriting_input=False) as pdf:\n                        # pikepdf auto-rebuilds xref table on save\n                        pdf.save(out, fix_metadata_version=True,\n                                 compress_streams=True,\n                                 object_stream_mode=pikepdf.ObjectStreamMode.generate)\n                    after = os.path.getsize(out)\n                    ot_log(f\"\u2705 PDF repair done: {out}  ({_human_size(before)} \u2192 {_human_size(after)})\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"Done!\",\n                        f\"\u2705 PDF repaired!\\n\"\n                        f\"Before: {_human_size(before)}\\nAfter: {_human_size(after)}\\n\\n{out}\"))\n                except Exception as ex:\n                    ot_log(f\"\u274c PDF repair error: {ex}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n            threading.Thread(target=_run, daemon=True).start()\n\n        tk.Button(c4c, text=\"\u25b6 Repair PDF\", font=FONTS[\"body\"],\n                  bg=C[\"warning\"], fg=C[\"bg\"], bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=_do_repair_pdf).pack(anchor=\"w\", pady=(6,0))\n\n        # \u2500\u2500 PPTX Repair \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        c4d = _make_card(t4, \"\ud83d\udcca  Corrupt PPTX Repair  (PowerPoint ZIP recovery)\")\n        r4d = tk.Frame(c4d, bg=C[\"card\"])\n        r4d.pack(fill=\"x\")\n        tk.Label(r4d, text=\"Corrupt PPTX:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_fix_pptx_path = tk.StringVar()\n        tk.Entry(r4d, textvariable=self._ot_fix_pptx_path, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=44).pack(side=\"left\", padx=4)\n        tk.Button(r4d, text=\"Browse\u2026\", font=FONTS[\"small\"], bg=C[\"btn_info\"],\n                  fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=lambda: self._ot_fix_pptx_path.set(\n                      filedialog.askopenfilename(filetypes=[(\"PowerPoint\",\"*.pptx *.ppt\"),(\"All\",\"*.*\")]))).pack(side=\"left\")\n\n        def _do_repair_pptx():\n            src = self._ot_fix_pptx_path.get().strip()\n            if not src or not os.path.isfile(src):\n                messagebox.showwarning(\"Warning\",\"Valid PPTX select karo.\"); return\n            out = filedialog.asksaveasfilename(title=\"Repaired PPTX save karein\",\n                                               defaultextension=\".pptx\",\n                                               filetypes=[(\"PowerPoint\",\"*.pptx\")])\n            if not out: return\n            def _run():\n                import zipfile\n                try:\n                    with zipfile.ZipFile(src,\"r\") as z:\n                        names = z.namelist()\n                    tmp_dir = tempfile.mkdtemp()\n                    recovered = []\n                    with zipfile.ZipFile(src,\"r\") as z_in:\n                        for name in names:\n                            try:\n                                data = z_in.read(name)\n                                dest = os.path.join(tmp_dir,name)\n                                os.makedirs(os.path.dirname(dest),exist_ok=True)\n                                with open(dest,\"wb\") as f: f.write(data)\n                                recovered.append(name)\n                            except Exception:\n                                ot_log(f\"  \u26a0\ufe0f Skip: {name}\", C[\"warning\"])\n                    with zipfile.ZipFile(out,\"w\",compression=zipfile.ZIP_DEFLATED) as z_out:\n                        for name in recovered:\n                            z_out.write(os.path.join(tmp_dir,name), name)\n                    shutil.rmtree(tmp_dir, ignore_errors=True)\n                    ot_log(f\"\u2705 PPTX repair: {len(recovered)}/{len(names)} parts \u2192 {out}\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"Done!\",\n                        f\"\u2705 PPTX repaired!\\n{len(recovered)}/{len(names)} parts recovered.\\n\\n{out}\"))\n                except Exception as ex:\n                    ot_log(f\"\u274c PPTX repair error: {ex}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n            threading.Thread(target=_run, daemon=True).start()\n\n        tk.Button(c4d, text=\"\u25b6 Repair PPTX\", font=FONTS[\"body\"],\n                  bg=C[\"warning\"], fg=C[\"bg\"], bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=_do_repair_pptx).pack(anchor=\"w\", pady=(6,0))\n\n        # \u2500\u2500 Activate first tab \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _switch_office_tab(\"img_pdf\")\n        return frame\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # EXCEL TOOLS SECTION\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _build_excel_tools(self, parent):\n        \"\"\"\n        Excel Tools:\n          Tab 1 \u2014 Format Conversion   (Excel\u2194CSV, sheet splitter)\n          Tab 2 \u2014 Data Cleaning       (duplicate rows, bulk formatter, password remove)\n          Tab 3 \u2014 Merge &amp; Audit       (bulk merge, formula auditor)\n          Tab 4 \u2014 DOCX Security       (password protect / remove Word files)\n        \"\"\"\n        import threading, zipfile\n\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n\n        # \u2500\u2500 Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        hdr = tk.Frame(frame, bg=C[\"panel\"])\n        hdr.pack(fill=\"x\")\n        tk.Label(hdr, text=\"  \ud83d\udcca Excel &amp; Word Tools\",\n                 font=FONTS[\"heading\"], fg=C[\"accent\"], bg=C[\"panel\"]).pack(side=\"left\", pady=10, padx=8)\n        tk.Label(hdr, text=\"CSV \u00b7 Merge \u00b7 Clean \u00b7 Audit \u00b7 Password  |  Offline local dependencies only\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"left\", pady=10)\n\n        # \u2500\u2500 Sub-tab bar \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        tab_bar = tk.Frame(frame, bg=C[\"card\"])\n        tab_bar.pack(fill=\"x\")\n        tk.Frame(tab_bar, bg=C[\"border\"], height=1).pack(side=\"bottom\", fill=\"x\")\n        content_host = tk.Frame(frame, bg=C[\"bg\"])\n        content_host.pack(fill=\"both\", expand=True)\n\n        _xt_frames = {}\n        _xt_btns   = {}\n\n        def _xt_switch(key):\n            for k, b in _xt_btns.items():\n                b.config(bg=C[\"accent\"] if k==key else C[\"panel\"],\n                         fg=C[\"bg\"]     if k==key else C[\"text\"])\n            for k, f in _xt_frames.items():\n                (f.pack if k==key else f.pack_forget)(fill=\"both\", expand=True) if k==key else f.pack_forget()\n\n        subtabs = [(\"conv\",\"\u21c4  Conversion\"), (\"clean\",\"\ud83e\uddf9  Data Clean\"),\n                   (\"merge\",\"\ud83d\udd17  Merge &amp; Audit\"), (\"security\",\"\ud83d\udd10  Security\")]\n        for key, label in subtabs:\n            b = tk.Button(tab_bar, text=label, font=FONTS[\"body\"],\n                          bg=C[\"panel\"], fg=C[\"text\"], bd=0, padx=18, pady=8, cursor=\"hand2\",\n                          command=lambda k=key: _xt_switch(k))\n            b.pack(side=\"left\")\n            _xt_btns[key] = b\n\n        # \u2500\u2500 Shared log \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        log_host = tk.Frame(frame, bg=C[\"card\"])\n        log_host.pack(fill=\"x\", side=\"bottom\")\n        tk.Label(log_host, text=\"  Activity Log\", font=FONTS[\"small\"],\n                 fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=8, pady=(5,0))\n        _xt_log_w = scrolledtext.ScrolledText(log_host, height=4, state=\"disabled\",\n                                               bg=C[\"bg\"], fg=C[\"text\"], font=FONTS[\"small\"], bd=0)\n        _xt_log_w.pack(fill=\"x\", padx=8, pady=(2,6))\n\n        def xt_log(msg, color=None):\n            ts = datetime.datetime.now().strftime(\"%H:%M:%S\")\n            _xt_log_w.config(state=\"normal\")\n            tag = f\"t{abs(hash(color or ''))}\"\n            _xt_log_w.tag_config(tag, foreground=color or C[\"text\"])\n            _xt_log_w.insert(\"end\", f\"[{ts}] {msg}\\n\", tag)\n            _xt_log_w.see(\"end\")\n            _xt_log_w.config(state=\"disabled\")\n\n        def _xpkg(imp, pip=None):\n            pip = pip or imp\n            try: __import__(imp); return True\n            except ImportError:\n                xt_log(f\"\u274c Missing local dependency: {pip}. Runtime download/install is disabled.\", C[\"error\"])\n                return False\n\n        def _card(par, title):\n            c = tk.Frame(par, bg=C[\"card\"])\n            c.pack(fill=\"x\", padx=16, pady=10)\n            tk.Label(c, text=title, font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=10, pady=(8,4))\n            tk.Frame(c, bg=C[\"border\"], height=1).pack(fill=\"x\", padx=10)\n            b = tk.Frame(c, bg=C[\"card\"])\n            b.pack(fill=\"x\", padx=10, pady=10)\n            return b\n\n        def _row(par): r=tk.Frame(par,bg=C[\"card\"]); r.pack(fill=\"x\",pady=3); return r\n        def _lbl(par,txt): tk.Label(par,text=txt,font=FONTS[\"small\"],fg=C[\"text_dim\"],bg=C[\"card\"]).pack(side=\"left\",padx=(0,4))\n        def _entry(par,var,w=44): return tk.Entry(par,textvariable=var,font=FONTS[\"small\"],bg=C[\"bg\"],fg=C[\"text\"],insertbackground=C[\"text\"],width=w)\n        def _browse_btn(par,cmd): tk.Button(par,text=\"Browse\u2026\",font=FONTS[\"small\"],bg=C[\"btn_info\"],fg=C[\"text\"],bd=0,padx=8,pady=3,cursor=\"hand2\",command=cmd).pack(side=\"left\",padx=4)\n        def _action_btn(par,txt,cmd,color=None): tk.Button(par,text=txt,font=FONTS[\"body\"],bg=color or C[\"accent\"],fg=C[\"bg\"],bd=0,padx=14,pady=6,cursor=\"hand2\",command=cmd).pack(anchor=\"w\",pady=(8,2))\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # TAB 1 \u2014 Conversion\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        t1 = tk.Frame(content_host, bg=C[\"bg\"])\n        _xt_frames[\"conv\"] = t1\n\n        # Excel \u2192 CSV\n        b1a = _card(t1, \"\ud83d\udce4  Excel \u2192 CSV  (each sheet = one CSV)\")\n        r = _row(b1a); _lbl(r,\"XLSX:\"); v1a=tk.StringVar(); _entry(r,v1a).pack(side=\"left\",padx=4)\n        _browse_btn(r, lambda: v1a.set(filedialog.askopenfilename(filetypes=[(\"Excel\",\"*.xlsx *.xls\"),(\"All\",\"*.*\")])))\n        def _do_xl2csv():\n            src=v1a.get().strip()\n            if not src or not os.path.isfile(src): messagebox.showwarning(\"\",\"Valid XLSX select karo.\"); return\n            out_dir=filedialog.askdirectory(title=\"Output folder\")\n            if not out_dir: return\n            def _r():\n                try:\n                    if not _xpkg(\"openpyxl\"): return\n                    import openpyxl\n                    wb=openpyxl.load_workbook(src,data_only=True)\n                    saved=0\n                    for sh in wb.sheetnames:\n                        ws=wb[sh]\n                        out_path=os.path.join(out_dir,f\"{os.path.splitext(os.path.basename(src))[0]}_{sh}.csv\")\n                        with open(out_path,\"w\",newline=\"\",encoding=\"utf-8-sig\") as f:\n                            import csv as _csv\n                            w=_csv.writer(f)\n                            for row in ws.iter_rows(values_only=True): w.writerow([c if c is not None else \"\" for c in row])\n                        saved+=1\n                    xt_log(f\"\u2705 {saved} CSV files \u2192 {out_dir}\", C[\"success\"])\n                    self.after(0,lambda: messagebox.showinfo(\"Done!\",f\"\u2705 {saved} sheets exported!\\n{out_dir}\"))\n                except Exception as ex: xt_log(f\"\u274c {ex}\",C[\"error\"]); self.after(0,lambda: messagebox.showerror(\"Error\",str(ex)))\n            threading.Thread(target=_r,daemon=True).start()\n        _action_btn(b1a,\"\u25b6 Excel \u2192 CSV\",_do_xl2csv)\n\n        # CSV \u2192 Excel\n        b1b = _card(t1, \"\ud83d\udce5  CSV \u2192 Excel  (multiple CSVs \u2192 one XLSX, each = sheet)\")\n        r=_row(b1b); _lbl(r,\"CSVs:\"); v1b=tk.StringVar(); _entry(r,v1b,52).pack(side=\"left\",padx=4)\n        _browse_btn(r,lambda: v1b.set(\";\".join(filedialog.askopenfilenames(filetypes=[(\"CSV\",\"*.csv\"),(\"All\",\"*.*\")]))))\n        def _do_csv2xl():\n            files=[f.strip() for f in v1b.get().split(\";\") if f.strip()]\n            if not files: messagebox.showwarning(\"\",\"CSV select karo.\"); return\n            out=filedialog.asksaveasfilename(title=\"Output XLSX\",defaultextension=\".xlsx\",filetypes=[(\"Excel\",\"*.xlsx\")])\n            if not out: return\n            def _r():\n                try:\n                    if not _xpkg(\"openpyxl\"): return\n                    import openpyxl, csv as _csv\n                    wb=openpyxl.Workbook()\n                    wb.remove(wb.active)\n                    for f in files:\n                        sh_name=os.path.splitext(os.path.basename(f))[0][:31]\n                        ws=wb.create_sheet(title=sh_name)\n                        with open(f,newline=\"\",encoding=\"utf-8-sig\",errors=\"replace\") as fh:\n                            for row in _csv.reader(fh): ws.append(row)\n                    wb.save(out)\n                    xt_log(f\"\u2705 {len(files)} CSVs \u2192 {out}\",C[\"success\"])\n                    self.after(0,lambda: messagebox.showinfo(\"Done!\",f\"\u2705 Excel ready!\\n{out}\"))\n                except Exception as ex: xt_log(f\"\u274c {ex}\",C[\"error\"]); self.after(0,lambda: messagebox.showerror(\"Error\",str(ex)))\n            threading.Thread(target=_r,daemon=True).start()\n        _action_btn(b1b,\"\u25b6 CSV \u2192 Excel\",_do_csv2xl)\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # TAB 2 \u2014 Data Cleaning\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        t2 = tk.Frame(content_host, bg=C[\"bg\"])\n        _xt_frames[\"clean\"] = t2\n\n        # Duplicate row remover\n        b2a = _card(t2, \"\ud83e\uddf9  Duplicate Row Finder &amp; Remover\")\n        r=_row(b2a); _lbl(r,\"XLSX:\"); v2a=tk.StringVar(); _entry(r,v2a).pack(side=\"left\",padx=4)\n        _browse_btn(r,lambda: v2a.set(filedialog.askopenfilename(filetypes=[(\"Excel\",\"*.xlsx\"),(\"All\",\"*.*\")])))\n        r2=_row(b2a); _lbl(r2,\"Sheet name (blank=first):\"); v2a_sh=tk.StringVar(); _entry(r2,v2a_sh,16).pack(side=\"left\",padx=4)\n        _lbl(r2,\"  Key columns (e.g. A,B or blank=all):\"); v2a_col=tk.StringVar(); _entry(r2,v2a_col,14).pack(side=\"left\",padx=4)\n        self._xt_dup_mode = tk.StringVar(value=\"remove\")\n        r3=_row(b2a)\n        tk.Radiobutton(r3,text=\"Remove duplicates\",variable=self._xt_dup_mode,value=\"remove\",\n                       font=FONTS[\"small\"],bg=C[\"card\"],fg=C[\"text\"],selectcolor=C[\"bg\"],activebackground=C[\"card\"]).pack(side=\"left\",padx=6)\n        tk.Radiobutton(r3,text=\"Only mark/highlight\",variable=self._xt_dup_mode,value=\"mark\",\n                       font=FONTS[\"small\"],bg=C[\"card\"],fg=C[\"text\"],selectcolor=C[\"bg\"],activebackground=C[\"card\"]).pack(side=\"left\",padx=6)\n\n        def _do_dedup():\n            src=v2a.get().strip()\n            if not src or not os.path.isfile(src): messagebox.showwarning(\"\",\"Valid XLSX select karo.\"); return\n            out=filedialog.asksaveasfilename(title=\"Output XLSX\",defaultextension=\".xlsx\",filetypes=[(\"Excel\",\"*.xlsx\")])\n            if not out: return\n            def _r():\n                try:\n                    if not _xpkg(\"openpyxl\"): return\n                    import openpyxl\n                    from openpyxl.styles import PatternFill\n                    wb=openpyxl.load_workbook(src)\n                    sh_name=v2a_sh.get().strip() or wb.sheetnames[0]\n                    ws=wb[sh_name]\n                    data=list(ws.iter_rows(values_only=False))\n                    if not data: xt_log(\"\u26a0\ufe0f Sheet empty.\",C[\"warning\"]); return\n                    col_raw=v2a_col.get().strip()\n                    if col_raw:\n                        col_idxs=[ord(c.strip().upper())-65 for c in col_raw.split(\",\") if c.strip()]\n                    else:\n                        col_idxs=list(range(ws.max_column))\n                    seen=set(); dup_rows=[]; keep_rows=[]\n                    for i,row in enumerate(data):\n                        key=tuple((row[c].value if cmw:\n                                    img=img.resize((mw,int(img.height*mw/img.width)),Image.LANCZOS)\n                            base=os.path.splitext(os.path.basename(fp))[0]\n                            ext=\".jpg\" if fmt==\"JPEG\" else f\".{fmt.lower()}\"\n                            out_path=os.path.join(out_dir,f\"{base}{v1_suf.get()}{ext}\")\n                            save_kw={\"quality\":q} if fmt in (\"JPEG\",\"WEBP\") else {}\n                            img.convert(\"RGB\").save(out_path,fmt,**save_kw)\n                            done+=1\n                        except Exception as e: it_log(f\"\u26a0\ufe0f {fp}: {e}\",C[\"warning\"])\n                    it_log(f\"\u2705 {done}/{len(files)} images processed \u2192 {out_dir}\",C[\"success\"])\n                    self.after(0,lambda: messagebox.showinfo(\"Done!\",f\"\u2705 {done} images done!\\n{out_dir}\"))\n                except Exception as ex: it_log(f\"\u274c {ex}\",C[\"error\"]); self.after(0,lambda: messagebox.showerror(\"Error\",str(ex)))\n            threading.Thread(target=_r,daemon=True).start()\n        _abtn(b1,\"\u25b6 Resize &amp; Compress\",_do_resize)\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # TAB 2 \u2014 OCR\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        t2=tk.Frame(content_host,bg=C[\"bg\"]); _it_frames[\"ocr\"]=t2\n\n        b2=_card(t2,\"\ud83d\udcd6  OCR \u2014 Image / Screenshot \u2192 Text / Word / Excel\")\n        tk.Label(b2,text=\"\u26a0\ufe0f  Tesseract OCR pehle install karna hoga: https://github.com/UB-Mannheim/tesseract/wiki\",\n                 font=FONTS[\"small\"],fg=C[\"accent4\"],bg=C[\"card\"],cursor=\"hand2\").pack(anchor=\"w\",pady=(0,6))\n        r=_row(b2); _lbl(r,\"Images (multi-select):\"); v2_files=tk.StringVar(); _entry(r,v2_files,48)\n        _browse(r,lambda: v2_files.set(\";\".join(filedialog.askopenfilenames(\n            filetypes=[(\"Images\",\"*.jpg *.jpeg *.png *.bmp *.tiff *.webp\"),(\"All\",\"*.*\")]))))\n\n        r2=_row(b2)\n        _lbl(r2,\"Language:\"); v2_lang=tk.StringVar(value=\"eng+hin\")\n        for l in [(\"eng+hin\",\"Hindi+English\"),(\"eng\",\"English only\"),(\"hin\",\"Hindi only\")]:\n            tk.Radiobutton(r2,text=l[1],variable=v2_lang,value=l[0],font=FONTS[\"small\"],bg=C[\"card\"],fg=C[\"text\"],selectcolor=C[\"bg\"],activebackground=C[\"card\"]).pack(side=\"left\",padx=6)\n\n        r3=_row(b2); _lbl(r3,\"Output format:\"); v2_out=tk.StringVar(value=\"txt\")\n        for t,l in [(\"txt\",\"Plain Text\"),(\"docx\",\"Word DOCX\"),(\"xlsx\",\"Excel XLSX\")]:\n            tk.Radiobutton(r3,text=l,variable=v2_out,value=t,font=FONTS[\"small\"],bg=C[\"card\"],fg=C[\"text\"],selectcolor=C[\"bg\"],activebackground=C[\"card\"]).pack(side=\"left\",padx=6)\n\n        r4=_row(b2); _lbl(r4,\"Tesseract path (agar auto-detect fail ho):\"); v2_tess=tk.StringVar(value=r\"C:\\Program Files\\Tesseract-OCR\\tesseract.exe\")\n        _entry(r4,v2_tess,38)\n\n        def _do_ocr():\n            files=[f.strip() for f in v2_files.get().split(\";\") if f.strip()]\n            if not files: messagebox.showwarning(\"\",\"Images select karo.\"); return\n            out=filedialog.asksaveasfilename(title=\"Output file save\",\n                defaultextension=f\".{v2_out.get()}\",\n                filetypes=[(\"Output\",f\"*.{v2_out.get()}\"),(\"All\",\"*.*\")])\n            if not out: return\n            def _r():\n                try:\n                    if not _ipkg(\"PIL\",\"Pillow\"): return\n                    if not _ipkg(\"pytesseract\"): return\n                    import pytesseract\n                    from PIL import Image\n                    tp=v2_tess.get().strip()\n                    if tp and os.path.isfile(tp): pytesseract.pytesseract.tesseract_cmd=tp\n                    all_text=[]\n                    for fp in files:\n                        it_log(f\"  OCR: {os.path.basename(fp)}\u2026\",C[\"text_dim\"])\n                        img=Image.open(fp)\n                        txt=pytesseract.image_to_string(img,lang=v2_lang.get())\n                        all_text.append(f\"=== {os.path.basename(fp)} ===\\n{txt}\\n\")\n                    out_fmt=v2_out.get()\n                    if out_fmt==\"txt\":\n                        with open(out,\"w\",encoding=\"utf-8\") as f: f.write(\"\\n\".join(all_text))\n                    elif out_fmt==\"docx\":\n                        if not _ipkg(\"docx\",\"python-docx\"): return\n                        import docx\n                        doc=docx.Document()\n                        for block in all_text: doc.add_paragraph(block)\n                        doc.save(out)\n                    elif out_fmt==\"xlsx\":\n                        if not _ipkg(\"openpyxl\"): return\n                        import openpyxl\n                        wb=openpyxl.Workbook(); ws=wb.active; ws.title=\"OCR\"\n                        ws.append([\"Source File\",\"Extracted Text\"])\n                        for fp,txt in zip(files,all_text): ws.append([os.path.basename(fp),txt])\n                        wb.save(out)\n                    it_log(f\"\u2705 OCR done: {len(files)} files \u2192 {out}\",C[\"success\"])\n                    self.after(0,lambda: messagebox.showinfo(\"Done!\",f\"\u2705 OCR complete!\\n{out}\"))\n                except Exception as ex: it_log(f\"\u274c {ex}\\nTip: Tesseract install karo aur path sahi set karo.\",C[\"error\"]); self.after(0,lambda: messagebox.showerror(\"Error\",str(ex)))\n            threading.Thread(target=_r,daemon=True).start()\n        _abtn(b2,\"\u25b6 Run OCR\",_do_ocr)\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # TAB 3 \u2014 Background Remove\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        t3=tk.Frame(content_host,bg=C[\"bg\"]); _it_frames[\"bg\"]=t3\n\n        b3=_card(t3,\"\u2702  Background Remover  (rembg \u2014 AI-powered, first run ~100MB download)\")\n        tk.Label(b3,text=\"\u2139\ufe0f  First use mein model download hoga (~100 MB). Internet chahiye.\",\n                 font=FONTS[\"small\"],fg=C[\"accent4\"],bg=C[\"card\"]).pack(anchor=\"w\",pady=(0,6))\n        r=_row(b3); _lbl(r,\"Images:\"); v3_files=tk.StringVar(); _entry(r,v3_files,50)\n        _browse(r,lambda: v3_files.set(\";\".join(filedialog.askopenfilenames(\n            filetypes=[(\"Images\",\"*.jpg *.jpeg *.png *.webp *.bmp\"),(\"All\",\"*.*\")]))))\n        r2=_row(b3); _lbl(r2,\"Output suffix:\"); v3_suf=tk.StringVar(value=\"_nobg\"); _entry(r2,v3_suf,12)\n        _lbl(r2,\"  Output format (PNG recommended for transparency):\"); v3_fmt=tk.StringVar(value=\"PNG\")\n        for f in (\"PNG\",\"WEBP\"):\n            tk.Radiobutton(r2,text=f,variable=v3_fmt,value=f,font=FONTS[\"small\"],bg=C[\"card\"],fg=C[\"text\"],selectcolor=C[\"bg\"],activebackground=C[\"card\"]).pack(side=\"left\",padx=5)\n\n        def _do_bgrem():\n            files=[f.strip() for f in v3_files.get().split(\";\") if f.strip()]\n            if not files: messagebox.showwarning(\"\",\"Images select karo.\"); return\n            out_dir=filedialog.askdirectory(title=\"Output folder\")\n            if not out_dir: return\n            def _r():\n                try:\n                    if not _ipkg(\"rembg\"): return\n                    if not _ipkg(\"PIL\",\"Pillow\"): return\n                    from rembg import remove\n                    from PIL import Image\n                    import io\n                    done=0\n                    for fp in files:\n                        try:\n                            it_log(f\"  Processing: {os.path.basename(fp)}\u2026\",C[\"text_dim\"])\n                            with open(fp,\"rb\") as f: inp=f.read()\n                            out_bytes=remove(inp)\n                            base=os.path.splitext(os.path.basename(fp))[0]\n                            fmt=v3_fmt.get(); ext=\".png\" if fmt==\"PNG\" else \".webp\"\n                            out_path=os.path.join(out_dir,f\"{base}{v3_suf.get()}{ext}\")\n                            img=Image.open(io.BytesIO(out_bytes))\n                            img.save(out_path,fmt)\n                            done+=1\n                        except Exception as e: it_log(f\"\u26a0\ufe0f {os.path.basename(fp)}: {e}\",C[\"warning\"])\n                    it_log(f\"\u2705 Background removed: {done}/{len(files)} \u2192 {out_dir}\",C[\"success\"])\n                    self.after(0,lambda: messagebox.showinfo(\"Done!\",f\"\u2705 {done} images processed!\\n{out_dir}\"))\n                except Exception as ex: it_log(f\"\u274c {ex}\",C[\"error\"]); self.after(0,lambda: messagebox.showerror(\"Error\",str(ex)))\n            threading.Thread(target=_r,daemon=True).start()\n        _abtn(b3,\"\u25b6 Remove Background\",_do_bgrem)\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # TAB 4 \u2014 Crop (Images + PDF)\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        t4=tk.Frame(content_host,bg=C[\"bg\"]); _it_frames[\"crop\"]=t4\n\n        # Image crop\n        b4a=_card(t4,\"\u2702\ufe0f  Image Crop  (pixels \u2014 left, top, right, bottom)\")\n        r=_row(b4a); _lbl(r,\"Images:\"); v4a_files=tk.StringVar(); _entry(r,v4a_files,48)\n        _browse(r,lambda: v4a_files.set(\";\".join(filedialog.askopenfilenames(\n            filetypes=[(\"Images\",\"*.jpg *.jpeg *.png *.bmp *.tiff *.webp\"),(\"All\",\"*.*\")]))))\n        r2=_row(b4a)\n        _lbl(r2,\"Left:\"); v4a_l=tk.StringVar(value=\"0\"); _entry(r2,v4a_l,6)\n        _lbl(r2,\"Top:\"); v4a_t=tk.StringVar(value=\"0\"); _entry(r2,v4a_t,6)\n        _lbl(r2,\"Right:\"); v4a_r=tk.StringVar(value=\"800\"); _entry(r2,v4a_r,6)\n        _lbl(r2,\"Bottom:\"); v4a_b=tk.StringVar(value=\"600\"); _entry(r2,v4a_b,6)\n        # Suffix nahi \u2014 output folder alag hai, naam same rahega\n\n        def _do_img_crop():\n            files=[f.strip() for f in v4a_files.get().split(\";\") if f.strip()]\n            if not files: messagebox.showwarning(\"\",\"Images select karo.\"); return\n            out_dir=filedialog.askdirectory(title=\"Output folder\")\n            if not out_dir: return\n            def _r():\n                try:\n                    if not _ipkg(\"PIL\",\"Pillow\"): return\n                    from PIL import Image\n                    box=(int(v4a_l.get()),int(v4a_t.get()),int(v4a_r.get()),int(v4a_b.get()))\n                    done=0\n                    for fp in files:\n                        try:\n                            img=Image.open(fp)\n                            cropped=img.crop(box)\n                            base,ext=os.path.splitext(os.path.basename(fp))\n                            out_path=os.path.join(out_dir,f\"{base}{ext}\")  # same naam, alag folder\n                            cropped.save(out_path)\n                            done+=1\n                        except Exception as e: it_log(f\"\u26a0\ufe0f {os.path.basename(fp)}: {e}\",C[\"warning\"])\n                    it_log(f\"\u2705 Cropped {done}/{len(files)} images \u2192 {out_dir}\",C[\"success\"])\n                    self.after(0,lambda: messagebox.showinfo(\"Done!\",f\"\u2705 {done} images cropped!\\n{out_dir}\"))\n                except Exception as ex: it_log(f\"\u274c {ex}\",C[\"error\"]); self.after(0,lambda: messagebox.showerror(\"Error\",str(ex)))\n            threading.Thread(target=_r,daemon=True).start()\n        _abtn(b4a,\"\u25b6 Crop Images (pixel values)\",_do_img_crop)\n\n        # \u2500\u2500 Visual Mouse Crop for Images \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        def _do_visual_img_crop():\n            \"\"\"Mouse se drag karke image ka area select karo aur crop karo.\"\"\"\n            files=[f.strip() for f in v4a_files.get().split(\";\") if f.strip()]\n            if not files:\n                messagebox.showwarning(\"\",\"Pehle images select karo (upar wale entry mein).\")\n                return\n            if not _ipkg(\"PIL\",\"Pillow\"):\n                return\n            from PIL import Image as _PILImg, ImageTk as _ITk\n\n            # File index state\n            img_state = {\n                \"idx\": 0,\n                \"files\": files,\n                \"rect\": None,\n                \"drag_start\": None,\n                \"photo\": None,\n                \"scale\": 1.0,\n                \"orig_w\": 1, \"orig_h\": 1,\n                \"img_x\": 0, \"img_y\": 0,\n            }\n\n            iwin = tk.Toplevel(self)\n            iwin.title(\"\ud83d\uddb1  Visual Image Crop \u2014 Mouse se area select karo\")\n            iwin.geometry(\"980x700\")\n            iwin.configure(bg=C[\"bg\"])\n            iwin.grab_set()\n\n            # \u2500\u2500 Top controls \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            ictrl = tk.Frame(iwin, bg=C[\"panel\"])\n            ictrl.pack(fill=\"x\")\n            tk.Label(ictrl, text=\"Image:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"left\", padx=(10,4))\n            ifile_var = tk.StringVar(value=\"1\")\n            ifile_spin = tk.Spinbox(ictrl, from_=1, to=len(files), textvariable=ifile_var,\n                                    width=5, font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"],\n                                    buttonbackground=C[\"card\"])\n            ifile_spin.pack(side=\"left\", padx=4)\n            tk.Label(ictrl, text=f\"/ {len(files)}\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"left\")\n\n            iname_lbl = tk.Label(ictrl, text=\"\", font=FONTS[\"small\"], fg=C[\"accent4\"], bg=C[\"panel\"])\n            iname_lbl.pack(side=\"left\", padx=10)\n\n            icoord_lbl = tk.Label(ictrl, text=\"Selection: None\", font=FONTS[\"small\"],\n                                   fg=C[\"accent\"], bg=C[\"panel\"])\n            icoord_lbl.pack(side=\"left\", padx=16)\n\n            tk.Label(ictrl, text=\"\ud83d\uddb1 Drag to select crop area\", font=FONTS[\"small\"],\n                     fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"right\", padx=14)\n\n            # \u2500\u2500 Canvas \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            icf = tk.Frame(iwin, bg=C[\"bg\"])\n            icf.pack(fill=\"both\", expand=True, padx=8, pady=4)\n            icanvas = tk.Canvas(icf, bg=\"#1a1a2e\", cursor=\"crosshair\", highlightthickness=0)\n            icanvas.pack(fill=\"both\", expand=True)\n\n            def render_image(idx):\n                img_state[\"idx\"] = idx\n                img_state[\"rect\"] = None\n                icanvas.delete(\"all\")\n                fp = files[idx]\n                iname_lbl.config(text=os.path.basename(fp))\n                try:\n                    pil = _PILImg.open(fp)\n                    cw = icanvas.winfo_width() or 900\n                    ch = icanvas.winfo_height() or 560\n                    ow, oh = pil.size\n                    img_state[\"orig_w\"] = ow\n                    img_state[\"orig_h\"] = oh\n                    scale = min((cw-20)/ow, (ch-20)/oh, 1.0)\n                    img_state[\"scale\"] = scale\n                    disp = pil.resize((int(ow*scale), int(oh*scale)), _PILImg.LANCZOS)\n                    photo = _ITk.PhotoImage(disp)\n                    img_state[\"photo\"] = photo\n                    ix = (cw - int(ow*scale)) // 2\n                    iy = (ch - int(oh*scale)) // 2\n                    img_state[\"img_x\"] = ix\n                    img_state[\"img_y\"] = iy\n                    icanvas.create_image(ix, iy, anchor=\"nw\", image=photo, tags=\"img\")\n                    icanvas.create_rectangle(ix-1, iy-1, ix+int(ow*scale)+1, iy+int(oh*scale)+1,\n                                             outline=C[\"accent\"], width=1, tags=\"border\")\n                    icoord_lbl.config(text=\"Selection: None \u2014 drag karke area choose karo\")\n                except Exception as e:\n                    icoord_lbl.config(text=f\"Error loading image: {e}\")\n\n            irect_id = [None]\n\n            def ion_press(event):\n                img_state[\"drag_start\"] = (event.x, event.y)\n                img_state[\"rect\"] = None\n                if irect_id[0]:\n                    icanvas.delete(irect_id[0])\n                    irect_id[0] = None\n\n            def ion_drag(event):\n                if not img_state[\"drag_start\"]:\n                    return\n                x0,y0 = img_state[\"drag_start\"]\n                x1,y1 = event.x, event.y\n                if irect_id[0]:\n                    icanvas.delete(irect_id[0])\n                irect_id[0] = icanvas.create_rectangle(x0,y0,x1,y1,\n                    outline=\"#00FF88\", width=2, dash=(4,2), tags=\"isel\")\n                ix, iy = img_state[\"img_x\"], img_state[\"img_y\"]\n                sc = img_state[\"scale\"]\n                px0 = max(0, (min(x0,x1)-ix)/sc)\n                py0 = max(0, (min(y0,y1)-iy)/sc)\n                px1 = min(img_state[\"orig_w\"], (max(x0,x1)-ix)/sc)\n                py1 = min(img_state[\"orig_h\"], (max(y0,y1)-iy)/sc)\n                icoord_lbl.config(text=f\"Selection: ({px0:.0f},{py0:.0f}) \u2192 ({px1:.0f},{py1:.0f}) px  |  {px1-px0:.0f}\u00d7{py1-py0:.0f} px\")\n\n            def ion_release(event):\n                if not img_state[\"drag_start\"]:\n                    return\n                x0,y0 = img_state[\"drag_start\"]\n                x1,y1 = event.x, event.y\n                if abs(x1-x0)&lt;8 or abs(y1-y0)&lt;8:\n                    img_state[\"rect\"] = None\n                    icoord_lbl.config(text=\"Too small \u2014 thoda bada area select karo\")\n                    return\n                ix, iy = img_state[\"img_x\"], img_state[\"img_y\"]\n                sc = img_state[\"scale\"]\n                cx0,cy0 = min(x0,x1), min(y0,y1)\n                cx1,cy1 = max(x0,x1), max(y0,y1)\n                px0 = max(0, (cx0-ix)/sc)\n                py0 = max(0, (cy0-iy)/sc)\n                px1 = min(img_state[\"orig_w\"], (cx1-ix)/sc)\n                py1 = min(img_state[\"orig_h\"], (cy1-iy)/sc)\n                img_state[\"rect\"] = (int(px0), int(py0), int(px1), int(py1))\n                icoord_lbl.config(text=f\"\u2705 Selected: ({int(px0)},{int(py0)}) \u2192 ({int(px1)},{int(py1)}) px  |  Click 'Apply Crop'\")\n\n            icanvas.bind(\"\", ion_press)\n            icanvas.bind(\"\", ion_drag)\n            icanvas.bind(\"\", ion_release)\n\n            def igo_img(*_):\n                try:\n                    idx = int(ifile_var.get())-1\n                    idx = max(0, min(idx, len(files)-1))\n                    render_image(idx)\n                except Exception:\n                    pass\n            ifile_spin.config(command=igo_img)\n            ifile_spin.bind(\"\", igo_img)\n            icanvas.bind(\"\", lambda e: self.after(100, lambda: render_image(img_state[\"idx\"])))\n\n            # \u2500\u2500 Bottom buttons \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            ibtn_row = tk.Frame(iwin, bg=C[\"panel\"])\n            ibtn_row.pack(fill=\"x\", pady=4)\n\n            def apply_img_visual_crop():\n                if not img_state[\"rect\"]:\n                    messagebox.showwarning(\"\", \"Pehle mouse se area select karo.\")\n                    return\n                out_dir = filedialog.askdirectory(title=\"Cropped images save karne ke liye folder\")\n                if not out_dir:\n                    return\n                box = img_state[\"rect\"]\n                crop_all = crop_all_var.get()\n                target_idxs = list(range(len(files))) if crop_all else [img_state[\"idx\"]]\n                def _icrop_run():\n                    try:\n                        done = 0\n                        for idx in target_idxs:\n                            fp = files[idx]\n                            try:\n                                pil = _PILImg.open(fp)\n                                # Clamp box to actual image size\n                                ow, oh = pil.size\n                                safe_box = (\n                                    max(0, box[0]), max(0, box[1]),\n                                    min(ow, box[2]), min(oh, box[3])\n                                )\n                                cropped = pil.crop(safe_box)\n                                base, ext = os.path.splitext(os.path.basename(fp))\n                                suf = v4a_suf.get()\n                                out_path = os.path.join(out_dir, f\"{base}{ext}\")  # same naam, alag folder\n                                cropped.save(out_path)\n                                done += 1\n                            except Exception as e:\n                                it_log(f\"\u26a0\ufe0f {os.path.basename(fp)}: {e}\", C[\"warning\"])\n                        it_log(f\"\u2705 Visual crop: {done}/{len(target_idxs)} images \u2192 {out_dir}\", C[\"success\"])\n                        self.after(0, lambda: messagebox.showinfo(\"Done!\", f\"\u2705 {done} images cropped!\\n{out_dir}\"))\n                        self.after(0, iwin.destroy)\n                    except Exception as ex:\n                        it_log(f\"\u274c {ex}\", C[\"error\"])\n                        self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n                threading.Thread(target=_icrop_run, daemon=True).start()\n\n            crop_all_var = tk.BooleanVar(value=False)\n            tk.Checkbutton(ibtn_row, text=\"Sab images pe same crop apply karo\",\n                           variable=crop_all_var, font=FONTS[\"small\"],\n                           bg=C[\"panel\"], fg=C[\"text\"], selectcolor=C[\"bg\"],\n                           activebackground=C[\"panel\"]).pack(side=\"left\", padx=12, pady=6)\n\n            def ireset_sel():\n                img_state[\"rect\"] = None\n                if irect_id[0]:\n                    icanvas.delete(irect_id[0])\n                    irect_id[0] = None\n                icoord_lbl.config(text=\"Selection: Reset \u2014 dobara drag karo\")\n\n            tk.Button(ibtn_row, text=\"\u2705 Apply Crop\", font=FONTS[\"body\"],\n                      bg=C[\"success\"], fg=C[\"bg\"], bd=0, padx=20, pady=8,\n                      cursor=\"hand2\", command=apply_img_visual_crop).pack(side=\"left\", padx=8, pady=6)\n            tk.Button(ibtn_row, text=\"\ud83d\udd04 Reset\", font=FONTS[\"body\"],\n                      bg=C[\"btn_warn\"], fg=C[\"text\"], bd=0, padx=12, pady=8,\n                      cursor=\"hand2\", command=ireset_sel).pack(side=\"left\", padx=4)\n            tk.Button(ibtn_row, text=\"\u25c0 Prev\", font=FONTS[\"body\"],\n                      bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=10, pady=8,\n                      cursor=\"hand2\",\n                      command=lambda: (ifile_var.set(max(1, int(ifile_var.get())-1)), igo_img())).pack(side=\"left\", padx=4)\n            tk.Button(ibtn_row, text=\"Next \u25b6\", font=FONTS[\"body\"],\n                      bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=10, pady=8,\n                      cursor=\"hand2\",\n                      command=lambda: (ifile_var.set(min(len(files), int(ifile_var.get())+1)), igo_img())).pack(side=\"left\", padx=4)\n            tk.Button(ibtn_row, text=\"\u274c Cancel\", font=FONTS[\"body\"],\n                      bg=C[\"btn_danger\"], fg=C[\"text\"], bd=0, padx=12, pady=8,\n                      cursor=\"hand2\", command=iwin.destroy).pack(side=\"right\", padx=12)\n\n            iwin.update_idletasks()\n            self.after(150, lambda: render_image(0))\n\n        _abtn(b4a, \"\ud83d\uddb1  Visual Mouse Crop \u2014 Image (interactive)\", _do_visual_img_crop)\n\n        # PDF crop (page margins) + Visual Mouse Crop\n        b4b=_card(t4,\"\u2702\ufe0f  PDF Page Crop  (trim margins mm se  OR  mouse se visually select karo)\")\n        r=_row(b4b); _lbl(r,\"PDF:\"); v4b_pdf=tk.StringVar(); _entry(r,v4b_pdf,46)\n        _browse(r,lambda: v4b_pdf.set(filedialog.askopenfilename(filetypes=[(\"PDF\",\"*.pdf\"),(\"All\",\"*.*\")])))\n        r2=_row(b4b)\n        _lbl(r2,\"Left mm:\"); v4b_l=tk.StringVar(value=\"10\"); _entry(r2,v4b_l,5)\n        _lbl(r2,\"Bottom mm:\"); v4b_bot=tk.StringVar(value=\"10\"); _entry(r2,v4b_bot,5)\n        _lbl(r2,\"Right mm:\"); v4b_rr=tk.StringVar(value=\"10\"); _entry(r2,v4b_rr,5)\n        _lbl(r2,\"Top mm:\"); v4b_top=tk.StringVar(value=\"10\"); _entry(r2,v4b_top,5)\n        _lbl(r2,\"  Pages (blank=all):\"); v4b_pg=tk.StringVar(value=\"\"); _entry(r2,v4b_pg,10)\n\n        def _do_pdf_crop():\n            src=v4b_pdf.get().strip()\n            if not src or not os.path.isfile(src): messagebox.showwarning(\"\",\"Valid PDF select karo.\"); return\n            # Original PDF naam se default naam suggest karo\n            src_base=os.path.splitext(os.path.basename(src))[0]\n            out=filedialog.asksaveasfilename(title=\"Cropped PDF\",defaultextension=\".pdf\",\n                                             initialfile=src_base,\n                                             filetypes=[(\"PDF\",\"*.pdf\")])\n            if not out: return\n            def _r():\n                try:\n                    if not _ipkg(\"pikepdf\"): return\n                    import pikepdf\n                    # 1 mm \u2248 2.8346 PDF points\n                    mm2pt=lambda mm: float(mm)*2.8346\n                    l=mm2pt(v4b_l.get()); b=mm2pt(v4b_bot.get())\n                    rr=mm2pt(v4b_rr.get()); t=mm2pt(v4b_top.get())\n                    pages_raw=v4b_pg.get().strip()\n                    def _pk(v): return pikepdf.Real(round(v,4))\n                    with pikepdf.open(src) as pdf:\n                        total=len(pdf.pages)\n                        if pages_raw:\n                            idxs=set()\n                            for p in pages_raw.split(\",\"):\n                                p=p.strip()\n                                if \"-\" in p:\n                                    a,bb=p.split(\"-\"); [idxs.add(i) for i in range(int(a)-1,int(bb))]\n                                else:\n                                    try: idxs.add(int(p)-1)\n                                    except: pass\n                        else:\n                            idxs=set(range(total))\n                        for i,page in enumerate(pdf.pages):\n                            if i not in idxs: continue\n                            mb=page.mediabox\n                            x0,y0,x1,y1=float(mb[0]),float(mb[1]),float(mb[2]),float(mb[3])\n                            page.cropbox=pikepdf.Array([_pk(x0+l),_pk(y0+b),_pk(x1-rr),_pk(y1-t)])\n                        pdf.save(out)\n                    it_log(f\"\u2705 PDF cropped ({len(idxs)} pages) \u2192 {out}\",C[\"success\"])\n                    self.after(0,lambda: messagebox.showinfo(\"Done!\",f\"\u2705 PDF cropped!\\n{out}\"))\n                except Exception as ex: it_log(f\"\u274c {ex}\",C[\"error\"]); self.after(0,lambda: messagebox.showerror(\"Error\",str(ex)))\n            threading.Thread(target=_r,daemon=True).start()\n        _abtn(b4b,\"\u25b6 Crop PDF (mm margins)\",_do_pdf_crop)\n\n        # \u2500\u2500 Visual Mouse Crop \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        def _do_visual_pdf_crop():\n            \"\"\"Mouse se drag karke PDF page ka area select karo aur crop karo.\"\"\"\n            src = v4b_pdf.get().strip()\n            if not src or not os.path.isfile(src):\n                messagebox.showwarning(\"\", \"Pehle PDF select karo.\")\n                return\n            # Ensure dependencies\n            fitz_ok = _ipkg(\"fitz\", \"PyMuPDF\")\n            if not fitz_ok:\n                messagebox.showerror(\"Error\", \"PyMuPDF local package missing hai. Offline bundle/wheel se install karein.\")\n                return\n            import fitz\n            doc = fitz.open(src)\n            total_pages = len(doc)\n            if total_pages == 0:\n                messagebox.showerror(\"Error\", \"PDF mein koi page nahi hai.\")\n                doc.close()\n                return\n\n            # \u2500\u2500 Visual Crop Window \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            crop_win = tk.Toplevel(self)\n            crop_win.title(\"\ud83d\uddb1  Visual PDF Crop \u2014 Mouse se area select karo\")\n            crop_win.geometry(\"950x720\")\n            crop_win.configure(bg=C[\"bg\"])\n            crop_win.grab_set()\n\n            # State\n            state = {\n                \"page_idx\": 0,\n                \"rect\": None,       # (x1,y1,x2,y2) in canvas coords\n                \"drag_start\": None,\n                \"photo\": None,\n                \"scale\": 1.0,\n                \"page_w\": 1, \"page_h\": 1,\n                \"canvas_w\": 780, \"canvas_h\": 540,\n            }\n\n            # \u2500\u2500 Top controls \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            ctrl = tk.Frame(crop_win, bg=C[\"panel\"])\n            ctrl.pack(fill=\"x\", pady=0)\n            tk.Label(ctrl, text=\"Page:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"left\", padx=(10,4))\n            page_var = tk.StringVar(value=\"1\")\n            page_spin = tk.Spinbox(ctrl, from_=1, to=total_pages, textvariable=page_var,\n                                   width=5, font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"],\n                                   buttonbackground=C[\"card\"])\n            page_spin.pack(side=\"left\", padx=4)\n            tk.Label(ctrl, text=f\"/ {total_pages}\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"left\")\n\n            apply_all_var = tk.BooleanVar(value=False)\n            tk.Checkbutton(ctrl, text=\"Sab pages pe apply karo\", variable=apply_all_var,\n                           font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text\"],\n                           selectcolor=C[\"bg\"], activebackground=C[\"panel\"]).pack(side=\"left\", padx=16)\n\n            coord_lbl = tk.Label(ctrl, text=\"Selection: None\", font=FONTS[\"small\"],\n                                 fg=C[\"accent\"], bg=C[\"panel\"])\n            coord_lbl.pack(side=\"left\", padx=10)\n\n            tk.Label(ctrl, text=\"\ud83d\uddb1 Drag to select crop area\", font=FONTS[\"small\"],\n                     fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"right\", padx=14)\n\n            # \u2500\u2500 Canvas \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            canvas_frame = tk.Frame(crop_win, bg=C[\"bg\"])\n            canvas_frame.pack(fill=\"both\", expand=True, padx=8, pady=4)\n            canvas = tk.Canvas(canvas_frame, bg=\"#1a1a2e\", cursor=\"crosshair\",\n                                highlightthickness=0)\n            canvas.pack(fill=\"both\", expand=True)\n\n            def render_page(page_idx):\n                \"\"\"Render a PDF page onto the canvas.\"\"\"\n                state[\"page_idx\"] = page_idx\n                state[\"rect\"] = None\n                canvas.delete(\"all\")\n                page = doc[page_idx]\n                cw = canvas.winfo_width() or 780\n                ch = canvas.winfo_height() or 540\n                state[\"canvas_w\"] = cw\n                state[\"canvas_h\"] = ch\n                pw = page.rect.width\n                ph = page.rect.height\n                state[\"page_w\"] = pw\n                state[\"page_h\"] = ph\n                # Scale to fit canvas with padding\n                scale = min((cw - 20) / pw, (ch - 20) / ph)\n                state[\"scale\"] = scale\n                mat = fitz.Matrix(scale, scale)\n                pix = page.get_pixmap(matrix=mat)\n                import io as _io\n                from PIL import Image as _PILImg, ImageTk as _ITk\n                pil = _PILImg.open(_io.BytesIO(pix.tobytes(\"ppm\")))\n                photo = _ITk.PhotoImage(pil)\n                state[\"photo\"] = photo  # keep reference\n                state[\"img_x\"] = (cw - pix.width)  // 2\n                state[\"img_y\"] = (ch - pix.height) // 2\n                canvas.create_image(state[\"img_x\"], state[\"img_y\"], anchor=\"nw\", image=photo, tags=\"page\")\n                # Border\n                canvas.create_rectangle(\n                    state[\"img_x\"]-1, state[\"img_y\"]-1,\n                    state[\"img_x\"]+pix.width+1, state[\"img_y\"]+pix.height+1,\n                    outline=C[\"accent\"], width=1, tags=\"border\")\n                coord_lbl.config(text=\"Selection: None \u2014 drag karke area choose karo\")\n\n            # \u2500\u2500 Mouse drag for selection \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            rect_id = [None]\n\n            def on_press(event):\n                state[\"drag_start\"] = (event.x, event.y)\n                state[\"rect\"] = None\n                if rect_id[0]:\n                    canvas.delete(rect_id[0])\n                    rect_id[0] = None\n\n            def on_drag(event):\n                if not state[\"drag_start\"]:\n                    return\n                x0, y0 = state[\"drag_start\"]\n                x1, y1 = event.x, event.y\n                if rect_id[0]:\n                    canvas.delete(rect_id[0])\n                rect_id[0] = canvas.create_rectangle(\n                    x0, y0, x1, y1,\n                    outline=\"#00FF88\", width=2, dash=(4,2), tags=\"sel\")\n                # Show size hint\n                ix, iy = state[\"img_x\"], state[\"img_y\"]\n                sc = state[\"scale\"]\n                # Clamp to page\n                px0 = max(0, (min(x0,x1) - ix) / sc)\n                py0 = max(0, (min(y0,y1) - iy) / sc)\n                px1 = min(state[\"page_w\"], (max(x0,x1) - ix) / sc)\n                py1 = min(state[\"page_h\"], (max(y0,y1) - iy) / sc)\n                coord_lbl.config(text=f\"Selection: ({px0:.0f},{py0:.0f}) \u2192 ({px1:.0f},{py1:.0f}) pt  |  {px1-px0:.0f}\u00d7{py1-py0:.0f} pt\")\n\n            def on_release(event):\n                if not state[\"drag_start\"]:\n                    return\n                x0, y0 = state[\"drag_start\"]\n                x1, y1 = event.x, event.y\n                if abs(x1-x0) &lt; 10 or abs(y1-y0) &lt; 10:\n                    state[\"rect\"] = None\n                    coord_lbl.config(text=\"Too small \u2014 thoda bada area select karo\")\n                    return\n                # Convert canvas coords \u2192 PDF points\n                ix, iy = state[\"img_x\"], state[\"img_y\"]\n                sc = state[\"scale\"]\n                pw, ph = state[\"page_w\"], state[\"page_h\"]\n                # PDF origin is bottom-left, canvas top-left\n                cx0, cy0 = min(x0,x1), min(y0,y1)\n                cx1, cy1 = max(x0,x1), max(y0,y1)\n                # Clamp\n                pdf_x0 = max(0.0, (cx0 - ix) / sc)\n                pdf_y0_top = max(0.0, (cy0 - iy) / sc)  # distance from top\n                pdf_x1 = min(pw, (cx1 - ix) / sc)\n                pdf_y1_top = min(ph, (cy1 - iy) / sc)\n                # Convert to PDF coords (y flipped): pdf_y = ph - canvas_y\n                pdf_y1 = ph - pdf_y0_top   # top of selection in PDF coords\n                pdf_y0 = ph - pdf_y1_top   # bottom of selection in PDF coords\n                state[\"rect\"] = (pdf_x0, pdf_y0, pdf_x1, pdf_y1)\n                coord_lbl.config(text=f\"\u2705 Selected: ({pdf_x0:.0f},{pdf_y0:.0f}) \u2192 ({pdf_x1:.0f},{pdf_y1:.0f}) pt  |  Click 'Apply Crop'\")\n\n            canvas.bind(\"\", on_press)\n            canvas.bind(\"\", on_drag)\n            canvas.bind(\"\", on_release)\n\n            def go_page(*_):\n                try:\n                    idx = int(page_var.get()) - 1\n                    idx = max(0, min(idx, total_pages-1))\n                    render_page(idx)\n                except Exception:\n                    pass\n            page_spin.config(command=go_page)\n            page_spin.bind(\"\", go_page)\n\n            # Render on canvas resize\n            def on_resize(event):\n                render_page(state[\"page_idx\"])\n            canvas.bind(\"\", lambda e: self.after(100, lambda: render_page(state[\"page_idx\"])))\n\n            # \u2500\u2500 Bottom buttons \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            btn_row = tk.Frame(crop_win, bg=C[\"panel\"])\n            btn_row.pack(fill=\"x\", pady=4)\n\n            def apply_visual_crop():\n                if not state[\"rect\"]:\n                    messagebox.showwarning(\"\", \"Pehle mouse se area select karo.\")\n                    return\n                src_base = os.path.splitext(os.path.basename(src))[0]\n                out = filedialog.asksaveasfilename(\n                    title=\"Cropped PDF save karein\",\n                    defaultextension=\".pdf\",\n                    initialfile=src_base,\n                    filetypes=[(\"PDF\", \"*.pdf\")])\n                if not out:\n                    return\n                crop_box = state[\"rect\"]   # (x0, y0, x1, y1) in PDF points\n                apply_all = apply_all_var.get()\n                target_pages = list(range(total_pages)) if apply_all else [state[\"page_idx\"]]\n                def _crop_run():\n                    try:\n                        if not _ipkg(\"pikepdf\"): return\n                        import pikepdf\n                        def _pkv(v): return pikepdf.Real(round(v,4))\n                        with pikepdf.open(src) as pdf:\n                            for pidx in range(len(pdf.pages)):\n                                if pidx not in target_pages:\n                                    continue\n                                page = pdf.pages[pidx]\n                                mb = page.mediabox\n                                page.cropbox = pikepdf.Array([\n                                    _pkv(crop_box[0]),\n                                    _pkv(crop_box[1]),\n                                    _pkv(crop_box[2]),\n                                    _pkv(crop_box[3]),\n                                ])\n                            pdf.save(out)\n                        it_log(f\"\u2705 Visual crop applied ({len(target_pages)} pages) \u2192 {out}\", C[\"success\"])\n                        self.after(0, lambda: messagebox.showinfo(\"Done!\",\n                            f\"\u2705 PDF visually cropped!\\n{out}\"))\n                        self.after(0, crop_win.destroy)\n                    except Exception as ex:\n                        it_log(f\"\u274c Visual crop error: {ex}\", C[\"error\"])\n                        self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n                threading.Thread(target=_crop_run, daemon=True).start()\n\n            def reset_selection():\n                state[\"rect\"] = None\n                if rect_id[0]:\n                    canvas.delete(rect_id[0])\n                    rect_id[0] = None\n                coord_lbl.config(text=\"Selection: Reset \u2014 dobara drag karo\")\n\n            tk.Button(btn_row, text=\"\u2705 Apply Crop\", font=FONTS[\"body\"],\n                      bg=C[\"success\"], fg=C[\"bg\"], bd=0, padx=20, pady=8,\n                      cursor=\"hand2\", command=apply_visual_crop).pack(side=\"left\", padx=12, pady=6)\n            tk.Button(btn_row, text=\"\ud83d\udd04 Reset Selection\", font=FONTS[\"body\"],\n                      bg=C[\"btn_warn\"], fg=C[\"text\"], bd=0, padx=14, pady=8,\n                      cursor=\"hand2\", command=reset_selection).pack(side=\"left\", padx=6)\n            tk.Button(btn_row, text=\"\u25c0 Prev Page\", font=FONTS[\"body\"],\n                      bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=12, pady=8,\n                      cursor=\"hand2\",\n                      command=lambda: (page_var.set(max(1, int(page_var.get())-1)), go_page())).pack(side=\"left\", padx=4)\n            tk.Button(btn_row, text=\"Next Page \u25b6\", font=FONTS[\"body\"],\n                      bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=12, pady=8,\n                      cursor=\"hand2\",\n                      command=lambda: (page_var.set(min(total_pages, int(page_var.get())+1)), go_page())).pack(side=\"left\", padx=4)\n            tk.Button(btn_row, text=\"\u274c Cancel\", font=FONTS[\"body\"],\n                      bg=C[\"btn_danger\"], fg=C[\"text\"], bd=0, padx=12, pady=8,\n                      cursor=\"hand2\",\n                      command=lambda: (doc.close(), crop_win.destroy())).pack(side=\"right\", padx=12)\n\n            # Initial render after window shows\n            crop_win.update_idletasks()\n            self.after(150, lambda: render_page(0))\n\n        _abtn(b4b, \"\ud83d\uddb1  Visual Mouse Crop (interactive)\", _do_visual_pdf_crop)\n\n        _it_switch(\"resize\")\n        return frame\n\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # FILE MANAGER TOOLS SECTION\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _build_file_tools(self, parent):\n        \"\"\"\n        File Manager Tools:\n          Tab 1 \u2014 Bulk Rename         (counter, date, prefix/suffix, regex)\n          Tab 2 \u2014 Duplicate Finder    (MD5/SHA256 content-based)\n        \"\"\"\n        import threading, hashlib\n\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n\n        hdr=tk.Frame(frame,bg=C[\"panel\"]); hdr.pack(fill=\"x\")\n        tk.Label(hdr,text=\"  \ud83d\uddc2 File Manager Tools\",font=FONTS[\"heading\"],fg=C[\"accent\"],bg=C[\"panel\"]).pack(side=\"left\",pady=10,padx=8)\n        tk.Label(hdr,text=\"Bulk Rename \u00b7 Duplicate Finder  |  No extra installs needed\",\n                 font=FONTS[\"small\"],fg=C[\"text_dim\"],bg=C[\"panel\"]).pack(side=\"left\",pady=10)\n\n        tab_bar=tk.Frame(frame,bg=C[\"card\"]); tab_bar.pack(fill=\"x\")\n        tk.Frame(tab_bar,bg=C[\"border\"],height=1).pack(side=\"bottom\",fill=\"x\")\n        content_host=tk.Frame(frame,bg=C[\"bg\"]); content_host.pack(fill=\"both\",expand=True)\n\n        _ft_frames={}; _ft_btns={}\n        def _ft_switch(key):\n            for k,b in _ft_btns.items():\n                b.config(bg=C[\"accent\"] if k==key else C[\"panel\"],\n                         fg=C[\"bg\"]     if k==key else C[\"text\"])\n            for k,f in _ft_frames.items():\n                f.pack(fill=\"both\",expand=True) if k==key else f.pack_forget()\n\n        for key,label in [(\"rename\",\"\u270f  Bulk Rename\"),(\"dupfind\",\"\ud83d\udd0d  Duplicate Finder\")]:\n            b=tk.Button(tab_bar,text=label,font=FONTS[\"body\"],bg=C[\"panel\"],fg=C[\"text\"],\n                        bd=0,padx=18,pady=8,cursor=\"hand2\",command=lambda k=key: _ft_switch(k))\n            b.pack(side=\"left\"); _ft_btns[key]=b\n\n        log_host=tk.Frame(frame,bg=C[\"card\"]); log_host.pack(fill=\"x\",side=\"bottom\")\n        tk.Label(log_host,text=\"  Activity Log\",font=FONTS[\"small\"],fg=C[\"accent\"],bg=C[\"card\"]).pack(anchor=\"w\",padx=8,pady=(5,0))\n        _ft_log_w=scrolledtext.ScrolledText(log_host,height=4,state=\"disabled\",bg=C[\"bg\"],fg=C[\"text\"],font=FONTS[\"small\"],bd=0)\n        _ft_log_w.pack(fill=\"x\",padx=8,pady=(2,6))\n\n        def ft_log(msg,color=None):\n            ts=datetime.datetime.now().strftime(\"%H:%M:%S\")\n            _ft_log_w.config(state=\"normal\")\n            tag=f\"t{abs(hash(color or ''))}\"\n            _ft_log_w.tag_config(tag,foreground=color or C[\"text\"])\n            _ft_log_w.insert(\"end\",f\"[{ts}] {msg}\\n\",tag)\n            _ft_log_w.see(\"end\"); _ft_log_w.config(state=\"disabled\")\n\n        def _card(par,title):\n            c=tk.Frame(par,bg=C[\"card\"]); c.pack(fill=\"x\",padx=16,pady=10)\n            tk.Label(c,text=title,font=FONTS[\"subhead\"],fg=C[\"accent\"],bg=C[\"card\"]).pack(anchor=\"w\",padx=10,pady=(8,4))\n            tk.Frame(c,bg=C[\"border\"],height=1).pack(fill=\"x\",padx=10)\n            b=tk.Frame(c,bg=C[\"card\"]); b.pack(fill=\"x\",padx=10,pady=10); return b\n\n        def _row(par): r=tk.Frame(par,bg=C[\"card\"]); r.pack(fill=\"x\",pady=3); return r\n        def _lbl(par,txt): tk.Label(par,text=txt,font=FONTS[\"small\"],fg=C[\"text_dim\"],bg=C[\"card\"]).pack(side=\"left\",padx=(0,4))\n        def _entry(par,var,w=44): e=tk.Entry(par,textvariable=var,font=FONTS[\"small\"],bg=C[\"bg\"],fg=C[\"text\"],insertbackground=C[\"text\"],width=w); e.pack(side=\"left\",padx=4); return e\n        def _browse(par,cmd): tk.Button(par,text=\"Browse\u2026\",font=FONTS[\"small\"],bg=C[\"btn_info\"],fg=C[\"text\"],bd=0,padx=8,pady=3,cursor=\"hand2\",command=cmd).pack(side=\"left\",padx=4)\n        def _abtn(par,txt,cmd,color=None): tk.Button(par,text=txt,font=FONTS[\"body\"],bg=color or C[\"accent\"],fg=C[\"bg\"],bd=0,padx=14,pady=6,cursor=\"hand2\",command=cmd).pack(anchor=\"w\",pady=(8,2))\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # TAB 1 \u2014 Bulk Rename\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        t1=tk.Frame(content_host,bg=C[\"bg\"]); _ft_frames[\"rename\"]=t1\n\n        b1=_card(t1,\"\u270f\ufe0f  Bulk File Rename\")\n        r=_row(b1); _lbl(r,\"Folder:\"); v1_dir=tk.StringVar(); _entry(r,v1_dir,48)\n        _browse(r,lambda: v1_dir.set(filedialog.askdirectory(title=\"Folder select karo\")))\n        r2=_row(b1); _lbl(r2,\"Filter extension (e.g. .jpg or blank=all):\"); v1_ext=tk.StringVar(value=\"\"); _entry(r2,v1_ext,8)\n\n        # Pattern options\n        opt_frame=tk.LabelFrame(b1,text=\"  Rename Pattern  (all options combine karein)\",\n                                 font=FONTS[\"small\"],fg=C[\"accent\"],bg=C[\"card\"],bd=1,relief=\"groove\")\n        opt_frame.pack(fill=\"x\",pady=6)\n        or1=tk.Frame(opt_frame,bg=C[\"card\"]); or1.pack(fill=\"x\",padx=8,pady=4)\n        _lbl(or1,\"Prefix:\"); v1_pre=tk.StringVar(); _entry(or1,v1_pre,12)\n        _lbl(or1,\"  Suffix (before ext):\"); v1_suf=tk.StringVar(); _entry(or1,v1_suf,12)\n        or2=tk.Frame(opt_frame,bg=C[\"card\"]); or2.pack(fill=\"x\",padx=8,pady=4)\n        v1_counter=tk.BooleanVar(value=True)\n        tk.Checkbutton(or2,text=\"Add counter\",variable=v1_counter,font=FONTS[\"small\"],bg=C[\"card\"],fg=C[\"text\"],selectcolor=C[\"bg\"],activebackground=C[\"card\"]).pack(side=\"left\")\n        _lbl(or2,\"  Start:\"); v1_start=tk.StringVar(value=\"1\"); _entry(or2,v1_start,5)\n        _lbl(or2,\"  Padding (digits):\"); v1_pad=tk.StringVar(value=\"3\"); _entry(or2,v1_pad,4)\n        or3=tk.Frame(opt_frame,bg=C[\"card\"]); or3.pack(fill=\"x\",padx=8,pady=4)\n        v1_date=tk.BooleanVar(value=False)\n        tk.Checkbutton(or3,text=\"Add date\",variable=v1_date,font=FONTS[\"small\"],bg=C[\"card\"],fg=C[\"text\"],selectcolor=C[\"bg\"],activebackground=C[\"card\"]).pack(side=\"left\")\n        _lbl(or3,\"  Date source:\"); v1_datesrc=tk.StringVar(value=\"today\")\n        tk.Radiobutton(or3,text=\"Today\",variable=v1_datesrc,value=\"today\",font=FONTS[\"small\"],bg=C[\"card\"],fg=C[\"text\"],selectcolor=C[\"bg\"],activebackground=C[\"card\"]).pack(side=\"left\",padx=4)\n        tk.Radiobutton(or3,text=\"File modified date\",variable=v1_datesrc,value=\"mtime\",font=FONTS[\"small\"],bg=C[\"card\"],fg=C[\"text\"],selectcolor=C[\"bg\"],activebackground=C[\"card\"]).pack(side=\"left\",padx=4)\n        or4=tk.Frame(opt_frame,bg=C[\"card\"]); or4.pack(fill=\"x\",padx=8,pady=4)\n        v1_replace=tk.BooleanVar(value=False)\n        tk.Checkbutton(or4,text=\"Find &amp; Replace in name:\",variable=v1_replace,font=FONTS[\"small\"],bg=C[\"card\"],fg=C[\"text\"],selectcolor=C[\"bg\"],activebackground=C[\"card\"]).pack(side=\"left\")\n        _lbl(or4,\"Find:\"); v1_find=tk.StringVar(); _entry(or4,v1_find,14)\n        _lbl(or4,\"Replace:\"); v1_rep=tk.StringVar(); _entry(or4,v1_rep,14)\n\n        # Preview\n        prev_lbl=tk.Label(b1,text=\"Preview: (click 'Preview' to see)\",\n                           font=FONTS[\"small\"],fg=C[\"text_dim\"],bg=C[\"card\"],anchor=\"w\")\n        prev_lbl.pack(fill=\"x\",pady=(4,0))\n        prev_box=scrolledtext.ScrolledText(b1,height=5,state=\"disabled\",bg=C[\"bg\"],fg=C[\"text\"],font=FONTS[\"small\"],bd=0)\n        prev_box.pack(fill=\"x\",pady=4)\n\n        def _build_new_name(orig_name, idx, folder):\n            base,ext=os.path.splitext(orig_name)\n            filt=v1_ext.get().strip()\n            if filt and ext.lower()!=filt.lower(): return None  # skip\n            name=base\n            if v1_replace.get():\n                name=name.replace(v1_find.get(),v1_rep.get())\n            date_str=\"\"\n            if v1_date.get():\n                if v1_datesrc.get()==\"today\":\n                    date_str=datetime.datetime.now().strftime(\"%Y%m%d\")\n                else:\n                    try:\n                        mtime=os.path.getmtime(os.path.join(folder,orig_name))\n                        date_str=datetime.datetime.fromtimestamp(mtime).strftime(\"%Y%m%d\")\n                    except: date_str=\"\"\n            ctr_str=\"\"\n            if v1_counter.get():\n                try: start=int(v1_start.get()); pad=int(v1_pad.get())\n                except: start=1; pad=3\n                ctr_str=str(start+idx).zfill(pad)\n            new=v1_pre.get()+date_str+ctr_str+name+v1_suf.get()\n            return new+ext\n\n        def _do_preview():\n            folder=v1_dir.get().strip()\n            if not folder or not os.path.isdir(folder): messagebox.showwarning(\"\",\"Valid folder select karo.\"); return\n            files=sorted(os.listdir(folder))\n            lines=[]; idx=0\n            for f in files:\n                if not os.path.isfile(os.path.join(folder,f)): continue\n                nn=_build_new_name(f,idx,folder)\n                if nn:\n                    lines.append(f\"  {f}  \u2192  {nn}\"); idx+=1\n            prev_box.config(state=\"normal\"); prev_box.delete(\"1.0\",\"end\")\n            prev_box.insert(\"end\",\"\\n\".join(lines) if lines else \"No files match.\"); prev_box.config(state=\"disabled\")\n\n        def _do_rename():\n            folder=v1_dir.get().strip()\n            if not folder or not os.path.isdir(folder): messagebox.showwarning(\"\",\"Valid folder select karo.\"); return\n            if not messagebox.askyesno(\"Confirm Rename\",\"Files rename honge. Undo possible nahi. Proceed?\"): return\n            def _r():\n                files=sorted(os.listdir(folder))\n                done=0; idx=0\n                for f in files:\n                    if not os.path.isfile(os.path.join(folder,f)): continue\n                    nn=_build_new_name(f,idx,folder)\n                    if nn and nn!=f:\n                        try:\n                            os.rename(os.path.join(folder,f),os.path.join(folder,nn))\n                            done+=1\n                        except Exception as e: ft_log(f\"\u26a0\ufe0f {f}: {e}\",C[\"warning\"])\n                    idx+=1\n                ft_log(f\"\u2705 {done} files renamed in {folder}\",C[\"success\"])\n                self.after(0,lambda: messagebox.showinfo(\"Done!\",f\"\u2705 {done} files renamed!\"))\n            threading.Thread(target=_r,daemon=True).start()\n\n        br=_row(b1)\n        tk.Button(br,text=\"\ud83d\udc41 Preview\",font=FONTS[\"body\"],bg=C[\"btn_info\"],fg=C[\"text\"],bd=0,padx=12,pady=6,cursor=\"hand2\",command=_do_preview).pack(side=\"left\",padx=(0,8))\n        tk.Button(br,text=\"\u25b6 Rename Files\",font=FONTS[\"body\"],bg=C[\"accent\"],fg=C[\"bg\"],bd=0,padx=14,pady=6,cursor=\"hand2\",command=_do_rename).pack(side=\"left\")\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # TAB 2 \u2014 Duplicate Finder\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        t2=tk.Frame(content_host,bg=C[\"bg\"]); _ft_frames[\"dupfind\"]=t2\n\n        b2=_card(t2,\"\ud83d\udd0d  Duplicate File Finder  (MD5 / SHA256 content-based)\")\n        r=_row(b2); _lbl(r,\"Folder to scan:\"); v2_dir=tk.StringVar(); _entry(r,v2_dir,46)\n        _browse(r,lambda: v2_dir.set(filedialog.askdirectory(title=\"Folder select karo\")))\n        r2=_row(b2)\n        v2_sub=tk.BooleanVar(value=True)\n        tk.Checkbutton(r2,text=\"Include subfolders\",variable=v2_sub,font=FONTS[\"small\"],bg=C[\"card\"],fg=C[\"text\"],selectcolor=C[\"bg\"],activebackground=C[\"card\"]).pack(side=\"left\",padx=4)\n        _lbl(r2,\"  Hash:\"); v2_hash=tk.StringVar(value=\"md5\")\n        tk.Radiobutton(r2,text=\"MD5 (fast)\",variable=v2_hash,value=\"md5\",font=FONTS[\"small\"],bg=C[\"card\"],fg=C[\"text\"],selectcolor=C[\"bg\"],activebackground=C[\"card\"]).pack(side=\"left\",padx=4)\n        tk.Radiobutton(r2,text=\"SHA256 (accurate)\",variable=v2_hash,value=\"sha256\",font=FONTS[\"small\"],bg=C[\"card\"],fg=C[\"text\"],selectcolor=C[\"bg\"],activebackground=C[\"card\"]).pack(side=\"left\",padx=4)\n        _lbl(r2,\"  Min size (KB):\"); v2_min=tk.StringVar(value=\"1\"); _entry(r2,v2_min,6)\n        _lbl(r2,\"  Extension filter (blank=all):\"); v2_ext=tk.StringVar(); _entry(r2,v2_ext,8)\n\n        # Results tree\n        dup_cols=(\"File\",\"Size\",\"Hash\",\"Group\")\n        dup_tree=ttk.Treeview(b2,columns=dup_cols,show=\"headings\",height=10,style=\"Custom.Treeview\")\n        for col,w in zip(dup_cols,[380,80,120,60]):\n            dup_tree.heading(col,text=col); dup_tree.column(col,width=w,anchor=\"w\")\n        dup_sb=ttk.Scrollbar(b2,orient=\"vertical\",command=dup_tree.yview)\n        dup_tree.configure(yscrollcommand=dup_sb.set)\n        dup_tree.pack(side=\"left\",fill=\"both\",expand=True,pady=6)\n        dup_sb.pack(side=\"right\",fill=\"y\",pady=6)\n\n        dup_stat=tk.Label(b2,text=\"\",font=FONTS[\"small\"],fg=C[\"text_dim\"],bg=C[\"card\"]); dup_stat.pack(anchor=\"w\")\n\n        def _file_hash(path, algo):\n            h=hashlib.md5() if algo==\"md5\" else hashlib.sha256()\n            try:\n                with open(path,\"rb\") as f:\n                    for chunk in iter(lambda: f.read(65536),b\"\"): h.update(chunk)\n                return h.hexdigest()\n            except Exception: return None\n\n        def _do_scan_dups():\n            folder=v2_dir.get().strip()\n            if not folder or not os.path.isdir(folder): messagebox.showwarning(\"\",\"Valid folder select karo.\"); return\n            def _r():\n                try:\n                    ft_log(\"\ud83d\udd0d Scanning for duplicates\u2026\",C[\"accent4\"])\n                    algo=v2_hash.get(); sub=v2_sub.get()\n                    try: min_bytes=int(v2_min.get())*1024\n                    except: min_bytes=1024\n                    ext_filter=v2_ext.get().strip().lower()\n                    all_files=[]\n                    if sub:\n                        for root_d,dirs,files in os.walk(folder):\n                            for f in files:\n                                fp=os.path.join(root_d,f)\n                                if ext_filter and not f.lower().endswith(ext_filter): continue\n                                try:\n                                    if os.path.getsize(fp)&gt;=min_bytes: all_files.append(fp)\n                                except: pass\n                    else:\n                        for f in os.listdir(folder):\n                            fp=os.path.join(folder,f)\n                            if not os.path.isfile(fp): continue\n                            if ext_filter and not f.lower().endswith(ext_filter): continue\n                            try:\n                                if os.path.getsize(fp)&gt;=min_bytes: all_files.append(fp)\n                            except: pass\n                    ft_log(f\"  {len(all_files)} files found, hashing\u2026\",C[\"text_dim\"])\n                    hashes={}\n                    for fp in all_files:\n                        h=_file_hash(fp,algo)\n                        if h:\n                            hashes.setdefault(h,[]).append(fp)\n                    dups={h:paths for h,paths in hashes.items() if len(paths)&gt;1}\n                    # Update tree\n                    self.after(0,lambda: dup_tree.delete(*dup_tree.get_children()))\n                    grp=0\n                    for h,paths in dups.items():\n                        grp+=1\n                        for p in paths:\n                            try: sz=_human_size(os.path.getsize(p))\n                            except: sz=\"?\"\n                            self.after(0,lambda p=p,sz=sz,h=h,g=grp: dup_tree.insert(\"\",\"end\",values=(p,sz,h[:12]+\"\u2026\",f\"#{g}\")))\n                    total_dup_files=sum(len(v) for v in dups.values())\n                    stat_msg=f\"\u2705 Found {len(dups)} duplicate groups, {total_dup_files} files\"\n                    self.after(0,lambda: dup_stat.config(text=stat_msg))\n                    ft_log(stat_msg,C[\"success\"] if dups else C[\"text_dim\"])\n                except Exception as ex: ft_log(f\"\u274c {ex}\",C[\"error\"]); self.after(0,lambda: messagebox.showerror(\"Error\",str(ex)))\n            threading.Thread(target=_r,daemon=True).start()\n\n        def _del_selected_dups():\n            sel=dup_tree.selection()\n            if not sel: messagebox.showwarning(\"\",\"Tree mein files select karo.\"); return\n            paths=[dup_tree.item(s)[\"values\"][0] for s in sel]\n            if not messagebox.askyesno(\"Delete?\",f\"{len(paths)} files permanently delete honge?\\n\\nUNDO POSSIBLE NAHI!\\n\\n\"+\"\\n\".join(paths[:10])): return\n            deleted=0\n            for p in paths:\n                try: os.remove(p); deleted+=1\n                except Exception as e: ft_log(f\"\u26a0\ufe0f {p}: {e}\",C[\"warning\"])\n            [dup_tree.delete(s) for s in sel]\n            ft_log(f\"\u2705 {deleted}/{len(paths)} duplicate files deleted.\",C[\"success\"])\n            messagebox.showinfo(\"Done!\",f\"\u2705 {deleted} files deleted.\")\n\n        def _export_dup_report():\n            out=filedialog.asksaveasfilename(title=\"Save Report\",defaultextension=\".csv\",filetypes=[(\"CSV\",\"*.csv\")])\n            if not out: return\n            import csv\n            rows=[dup_tree.item(r)[\"values\"] for r in dup_tree.get_children()]\n            with open(out,\"w\",newline=\"\",encoding=\"utf-8-sig\") as f:\n                w=csv.writer(f); w.writerow(dup_cols); w.writerows(rows)\n            ft_log(f\"\u2705 Report saved: {out}\",C[\"success\"])\n            messagebox.showinfo(\"Done!\",f\"\u2705 Report saved!\\n{out}\")\n\n        br=_row(b2)\n        tk.Button(br,text=\"\u25b6 Scan for Duplicates\",font=FONTS[\"body\"],bg=C[\"accent\"],fg=C[\"bg\"],bd=0,padx=14,pady=6,cursor=\"hand2\",command=_do_scan_dups).pack(side=\"left\",padx=(0,8))\n        tk.Button(br,text=\"\ud83d\uddd1 Delete Selected\",font=FONTS[\"body\"],bg=C[\"error\"],fg=C[\"text\"],bd=0,padx=12,pady=6,cursor=\"hand2\",command=_del_selected_dups).pack(side=\"left\",padx=(0,8))\n        tk.Button(br,text=\"\ud83d\udce5 Export CSV Report\",font=FONTS[\"body\"],bg=C[\"btn_info\"],fg=C[\"text\"],bd=0,padx=12,pady=6,cursor=\"hand2\",command=_export_dup_report).pack(side=\"left\")\n\n        _ft_switch(\"rename\")\n        return frame\n\n# ---------- RUN ----------\nif __name__ == \"__main__\":\n    # Windows + tkinter + psutil already verified at top\n    try:\n        # The maintenance UI needs elevation for printer, disk and recovery actions.\n        if not is_admin() and _admin_elevation_enabled():\n            run_as_admin()\n            sys.exit(0)\n        app = GodawariUltimateOptimizer()\n        app.mainloop()\n    except Exception as e:\n        import traceback\n        err = traceback.format_exc()\n        try:\n            messagebox.showerror(\"Startup Error \u2014 Godawari Optimizer\",\n                f\"App start nahi ho saki:\\n\\n{err[-600:]}\")\n        except:\n            print(\"STARTUP ERROR:\\n\", err)\n            input(\"Press Enter...\")\n", "creation_timestamp": "2026-05-28T19:22:22.000000Z"}, {"uuid": "d99ed9e2-32a3-4336-a4cf-602f1ba89f02", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2021-1678", "type": "seen", "source": "https://gist.github.com/shravan4u/b8c2585da943b58f06870e17e3e908c2", "content": "\"\"\"\n\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\n\u2551     Godawari Computers Ultimate Optimizer Pro - v11.0           \u2551\n\u2551     Professional Edition | Real Actions | Before/After Stats    \u2551\n\u2551     Developed by: Shravan Shrimali                               \u2551\n\u2551     FULLY FIXED - READY TO RUN                                   \u2551\n\u255a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255d\n\"\"\"\n\nimport sys\nimport os\nimport struct\nimport subprocess\nimport platform\nimport base64\nimport re\nimport io\nimport zlib\nimport csv\nimport hashlib\nimport sqlite3\nimport zipfile\nimport html\nimport uuid\n\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n#  SAFE STARTUP \u2014 errors ko pakdo, user ko batao\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n# 1) Windows check\nif platform.system() != \"Windows\":\n    print(\"\u274c Yeh tool sirf Windows ke liye hai.\")\n    input(\"Press Enter to exit...\")\n    sys.exit(1)\n\n# 2) tkinter check\ntry:\n    import tkinter as tk\n    from tkinter import ttk, messagebox, scrolledtext, filedialog, simpledialog\nexcept ImportError:\n    print(\"\u274c tkinter nahi mila. Python ko reinstall karo (Include Tcl/Tk checkbox tick karo).\")\n    input(\"Press Enter to exit...\")\n    sys.exit(1)\n\ntry:\n    import customtkinter as ctk\n    ctk.set_appearance_mode(\"System\")\n    ctk.set_default_color_theme(\"blue\")\nexcept Exception:\n    ctk = None\n\n# 3) psutil offline dependency check\ndef _show_dependency_splash(title, message):\n    try:\n        splash = tk.Tk()\n        splash.withdraw()\n        win = tk.Toplevel(splash)\n        win.title(title)\n        win.configure(bg=\"#121826\")\n        win.resizable(False, False)\n        tk.Label(win, text=title, font=(\"Segoe UI\", 12, \"bold\"), fg=\"#FFB347\", bg=win[\"bg\"]).pack(padx=18, pady=(14, 6))\n        tk.Message(win, text=message, width=420, font=(\"Segoe UI\", 10), fg=\"#F0F4FA\", bg=win[\"bg\"]).pack(padx=18, pady=(0, 14))\n        tk.Button(win, text=\"OK\", command=win.destroy, bg=\"#2E5A9C\", fg=\"#F0F4FA\", bd=0, padx=12, pady=8).pack(pady=(0, 14))\n        win.update_idletasks()\n        win.lift()\n        win.attributes(\"-topmost\", True)\n        win.mainloop()\n    except Exception:\n        try:\n            root = tk.Tk(); root.withdraw()\n            messagebox.showerror(title, message)\n            root.destroy()\n        except Exception:\n            print(f\"{title}: {message}\")\n\n\ndef _ensure_psutil():\n    try:\n        import psutil\n        return psutil\n    except ImportError:\n        try:\n            _show_dependency_splash(\n                \"psutil Missing\",\n                \"psutil library nahi mili.\\n\\n\"\n                \"Runtime internet install disabled hai production/offline safety ke liye.\\n\"\n                \"Portable package me psutil bundled rakhein ya offline wheel se install karein.\"\n            )\n        except Exception:\n            pass\n        try:\n            root = tk.Tk(); root.withdraw()\n            messagebox.showerror(\n                \"psutil Missing\",\n                \"psutil library nahi mili.\\n\\n\"\n                \"Runtime internet install disabled hai production/offline safety ke liye.\\n\"\n                \"Portable package me psutil bundled rakhein ya offline wheel se install karein.\")\n            root.destroy()\n        except Exception as e:\n            print(f\"psutil dependency error: {e}\")\n        input(\"Press Enter to exit...\")\n        sys.exit(1)\n\npsutil = _ensure_psutil()\n\n# 4) winreg (Windows built-in \u2014 should always exist on Windows)\ntry:\n    import winreg\nexcept ImportError:\n    root = tk.Tk(); root.withdraw()\n    messagebox.showerror(\"Error\", \"winreg module nahi mila.\\nPython Windows version use karo.\")\n    root.destroy()\n    sys.exit(1)\n\n# 5) Standard library imports\nimport threading\nimport queue as _queue_module\nimport ctypes\nimport json\nimport inspect\nimport importlib\nfrom concurrent.futures import ThreadPoolExecutor\n\n# Windows DPI awareness ensures UI scales correctly on high-DPI displays.\nif sys.platform == \"win32\":\n    try:\n        ctypes.windll.shcore.SetProcessDpiAwareness(1)\n    except Exception:\n        pass\nimport datetime\nimport time\nimport shutil\nfrom pathlib import Path\nimport gc\nimport tempfile\nimport collections\n\ntry:\n    from godawari.optimization_profiles import get_cleaner_profiles, get_group_policy_profiles\nexcept ImportError:\n    def get_cleaner_profiles():\n        import os\n        return {\n            \"safe\": {\n                \"name\": \"Safe Clean\",\n                \"description\": \"Temp files, recycle bin, thumbnail cache \u2014 bilkul safe\",\n                \"paths\": [\n                    os.environ.get(\"TEMP\", \"\"),\n                    os.path.join(os.environ.get(\"LOCALAPPDATA\", \"\"), \"Temp\"),\n                    r\"C:\\Windows\\Temp\",\n                    os.path.join(os.environ.get(\"LOCALAPPDATA\", \"\"), \"Microsoft\", \"Windows\", \"Explorer\"),\n                ],\n                \"commands\": []\n            },\n            \"deep\": {\n                \"name\": \"Deep Clean\",\n                \"description\": \"Windows Update cache, prefetch, installer cache\",\n                \"paths\": [\n                    r\"C:\\Windows\\SoftwareDistribution\\Download\",\n                    r\"C:\\Windows\\Prefetch\",\n                ],\n                \"commands\": [\n                    'cleanmgr /sageset:99',\n                    'cleanmgr /sagerun:99',\n                ]\n            }\n        }\n\n    def get_group_policy_profiles():\n        return {\n            \"performance\": {\n                \"name\": \"Performance Mode\",\n                \"policies\": [\n                    {\"hive\": \"HKLM\",\n                     \"key\": r\"SOFTWARE\\Policies\\Microsoft\\Windows\\DataCollection\",\n                     \"name\": \"AllowTelemetry\", \"value\": 0, \"type\": \"DWORD\"},\n                    {\"hive\": \"HKLM\",\n                     \"key\": r\"SOFTWARE\\Policies\\Microsoft\\Windows\\CloudContent\",\n                     \"name\": \"DisableWindowsConsumerFeatures\", \"value\": 1, \"type\": \"DWORD\"},\n                ]\n            }\n        }\n\n\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n#  SAFE SUBPROCESS HELPERS (inline implementation)\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nclass SafeRunResult:\n    def __init__(self, output, returncode, args=None,\n                 elapsed_ms=0, timed_out=False):\n        self.output     = output\n        self.returncode = returncode\n        self.args       = args or []\n        self.elapsed_ms = elapsed_ms\n        self.timed_out  = timed_out\n\nclass PowerShellResult:\n    def __init__(self, output, returncode, elapsed_ms=0, timed_out=False):\n        self.output     = output\n        self.returncode = returncode\n        self.elapsed_ms = elapsed_ms\n        self.timed_out  = timed_out\n        self.args       = []\n\ndef safe_powershell(script, timeout=60):\n    \"\"\"Safe PowerShell execution wrapper\"\"\"\n    started = time.time()\n    try:\n        startupinfo = None\n        creationflags = 0\n        if sys.platform == \"win32\":\n            startupinfo = subprocess.STARTUPINFO()\n            startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW\n            creationflags = subprocess.CREATE_NO_WINDOW\n        encoded = base64.b64encode(script.encode(\"utf-16-le\")).decode(\"ascii\")\n        env = os.environ.copy()\n        env[\"PSModuleAnalysisCacheWriteDisabled\"] = \"1\"\n        result = subprocess.run(\n            [\"powershell\", \"-NoProfile\", \"-ExecutionPolicy\", \"Bypass\", \"-EncodedCommand\", encoded],\n            capture_output=True,\n            text=True,\n            encoding=\"utf-8\",\n            errors=\"replace\",\n            timeout=timeout,\n            startupinfo=startupinfo,\n            creationflags=creationflags,\n            env=env,\n        )\n        elapsed = int((time.time() - started) * 1000)\n        return PowerShellResult(\n            result.stdout, result.returncode, elapsed_ms=elapsed)\n    except subprocess.TimeoutExpired:\n        elapsed = int((time.time() - started) * 1000)\n        return PowerShellResult(\n            \"Timeout\", -1, elapsed_ms=elapsed, timed_out=True)\n    except Exception as e:\n        return PowerShellResult(str(e), -1)\n\ndef safe_run(cmd, timeout=60):\n    \"\"\"Safe command execution wrapper\"\"\"\n    started = time.time()\n    try:\n        result = subprocess.run(\n            cmd, capture_output=True, text=True, timeout=timeout)\n        elapsed = int((time.time() - started) * 1000)\n        return SafeRunResult(\n            result.stdout, result.returncode,\n            args=list(cmd), elapsed_ms=elapsed)\n    except subprocess.TimeoutExpired:\n        elapsed = int((time.time() - started) * 1000)\n        return SafeRunResult(\n            \"Timeout\", -1,\n            args=list(cmd), elapsed_ms=elapsed, timed_out=True)\n    except Exception as e:\n        return SafeRunResult(\n            str(e), -1,\n            args=list(cmd) if isinstance(cmd, (list, tuple)) else [])\n\ndef safe_stream_lines(cmd, callback=None):\n    \"\"\"Safe streaming command execution\"\"\"\n    try:\n        process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)\n        for line in iter(process.stdout.readline, \"\"):\n            if line and callback:\n                callback(line.strip())\n        process.wait()\n    except Exception as e:\n        if callback:\n            callback(f\"Error: {e}\")\n\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n#  WORKER MANAGER &amp; STRUCTURED LOGGER STUBS\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nclass TkWorkerManager:\n    \"\"\"Manages background worker threads for the GUI.\"\"\"\n    def __init__(self, root, workers=3, logger=None):\n        self.root = root\n        self.workers = max(1, int(workers or 1))\n        self.logger = logger\n        self._task_queue = _queue_module.Queue()\n        self._executor = ThreadPoolExecutor(max_workers=self.workers)\n        self._shutdown = False\n        self._safe_mode = False\n        try:\n            from godawari import startup_control as _startup_control\n            self._safe_mode = bool(getattr(_startup_control, \"STARTUP_FLAGS\", {}).get(\"safe_mode\", False))\n        except Exception:\n            self._safe_mode = False\n        if self._safe_mode and self.logger:\n            try:\n                self.logger.log(\"startup\", \"Safe-mode enabled: GUI background worker threads disabled\", {})\n            except Exception:\n                pass\n\n    def _execute_task(self, name, target, args, kwargs):\n        try:\n            target(*args, **kwargs)\n        except Exception as e:\n            if self.logger:\n                try:\n                    self.logger.log(\"worker_error\", f\"Worker task '{name}' failed\", {\"error\": str(e)})\n                except Exception:\n                    pass\n            try:\n                if hasattr(self.root, \"after\"):\n                    def _report(msg=str(e), task=name):\n                        if hasattr(self.root, \"_set_status\"):\n                            self.root._set_status(f\"Background task '{task}' failed: {msg}\", C.get(\"error\", \"red\"))\n                    self.root.after(0, _report)\n            except Exception:\n                pass\n\n    def submit(self, name, target, *args, **kwargs):\n        if self._safe_mode:\n            try:\n                threading.Thread(target=target, args=args, kwargs=kwargs, daemon=True).start()\n                return\n            except Exception:\n                pass\n        try:\n            self._executor.submit(self._execute_task, name, target, args, kwargs)\n        except Exception:\n            threading.Thread(target=target, args=args, kwargs=kwargs, daemon=True).start()\n\n# \u2500\u2500 Enterprise modular backend (godawari package) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n_SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))\nif _SCRIPT_DIR not in sys.path:\n    sys.path.insert(0, _SCRIPT_DIR)\ntry:\n    from godawari.system.powershell_tools import (\n        SafeRunResult,\n        PowerShellResult,\n        safe_powershell,\n        safe_run,\n        safe_stream_lines,\n    )\n    from godawari.system.admin_tools import is_admin, run_as_admin\n    from godawari.services.logger import StructuredLogger\n    from godawari.services.restore_points import RestorePointManager\n    from godawari.services.rollback import OperationRollbackVault\n    from godawari.services.session_manager import RecoverySessionManager\n    from godawari.core.health_engine import SystemHealthEngine\n    from godawari.core.menu_introspection import MenuIntrospectionEngine\n    from godawari.core.product_audit import ProductAuditEngine\n    from godawari.core.recommendations import RecommendationEngine\n    from godawari.services.maintenance_profiles import MaintenanceProfileEngine\n    from godawari.security.preflight import OperationPreflightEngine\n    from godawari.security.powershell_guard import SecurePowerShellEngine\n    from godawari.services.crash_recovery import CrashRecoveryCoordinator\n    from godawari.bootstrap import create_backend\n    _GODAWARI_BACKEND = True\nexcept ImportError:\n    _GODAWARI_BACKEND = False\n\nif not _GODAWARI_BACKEND:\n    # Minimal inline fallback \u2014 full backend: run via python main.py from project root\n    class StructuredLogger:\n        def __init__(self, log_file=\"\"):\n            self.log_file = log_file or \"\"\n        def log(self, event_type, message, data=None):\n            pass\n        def event(self, category, action, **kwargs):\n            pass\n        def read_recent(self, limit=200):\n            return []\n\n    class RestorePointManager:\n        def __init__(self, base_dir, logger=None):\n            self.base_dir = base_dir\n            self.logger = logger\n            self.policy = {\"mode\": \"ask\"}\n\n        def _ensure_restore_services(self):\n            safe_run([\"sc\", \"config\", \"vss\", \"start=auto\"], timeout=30)\n            safe_run([\"sc\", \"start\", \"vss\"], timeout=30)\n            safe_powershell(\n                \"$key='HKLM:\\\\SOFTWARE\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\SystemRestore';\"\n                \" if (-not (Test-Path $key)) { New-Item $key -Force }\"\n                \"; Set-ItemProperty -Path $key -Name SystemRestorePointCreationFrequency -Value 0 -Type DWord -Force\",\n                timeout=30,\n            )\n\n        def create(self, description, ask_callback=None, force=False):\n            if ask_callback and not ask_callback(description):\n                return False\n            if not is_admin() and not force:\n                return False\n            try:\n                self._ensure_restore_services()\n                result = safe_powershell(\n                    f'Checkpoint-Computer -Description \"{description}\" -RestorePointType \"MODIFY_SETTINGS\"',\n                    timeout=180,\n                )\n                return result.returncode == 0\n            except Exception:\n                return False\n\n        def list_recent(self, limit=8):\n            return []\n\n    class OperationRollbackVault:\n        def __init__(self, vault_dir, logger=None):\n            self.vault_dir = vault_dir\n        def list_sessions(self, limit=50):\n            return []\n        def restore_session(self, session_id):\n            return False, \"Rollback vault unavailable\"\n\n    class RecoverySessionManager:\n        def __init__(self, sessions_dir, logger=None):\n            self.sessions_dir = sessions_dir\n        def start(self, kind, meta=None):\n            return uuid.uuid4().hex\n        def complete(self, session_id, status=\"completed\"):\n            pass\n        def list_sessions(self, include_completed=False, limit=30):\n            return []\n        def find_orphaned(self):\n            return []\n\n    class SystemHealthEngine:\n        def analyze(self):\n            return {\"score\": 0, \"grade\": \"Unknown\", \"color\": \"warning\", \"checks\": [], \"recommendations\": []}\n\n    class SecurePowerShellEngine:\n        def __init__(self, logger=None):\n            self.logger = logger\n        def run(self, script, timeout=60):\n            return safe_powershell(script, timeout=timeout)\n\n    class ProductAuditEngine:\n        def list_audits(self):\n            return []\n        def summary(self):\n            return {\"menus\": 0, \"average_maturity\": 0, \"highest_risk\": []}\n        def to_markdown(self, audits=None):\n            return \"# Godawari Optimizer Pro - Professional Menu Audit\\n\\nBackend unavailable.\\n\"\n\n    class MenuIntrospectionEngine:\n        def scan(self):\n            return {\"menus\": [], \"menu_count\": 0, \"button_count\": 0, \"option_count\": 0}\n        def to_markdown(self):\n            return \"# Godawari Optimizer Pro - Detected Software Map\\n\\nBackend unavailable.\\n\"\n\n    class OperationPreflightEngine:\n        def analyze(self, title, commands=None):\n            class _Result:\n                risk = \"medium\"\n                score = 50\n                requires_admin = True\n                requires_restore_point = True\n                requires_rollback_snapshot = True\n                dry_run_recommended = True\n                typed_confirmation = False\n                findings = []\n            return _Result()\n\n    class RecommendationEngine:\n        def build(self, health_report, audits, limit=10):\n            return {\"generated\": \"\", \"count\": 0, \"items\": []}\n\n    class MaintenanceProfileEngine:\n        def list_profiles(self):\n            return []\n\n    class CrashRecoveryCoordinator:\n        def __init__(self, session_manager, marker_file):\n            self.session_manager = session_manager\n            self.marker_file = marker_file\n        def mark_running(self):\n            pass\n        def clear_running(self):\n            pass\n        def had_unclean_exit(self):\n            return False\n        def orphaned_sessions(self):\n            return []\n\n# Legacy duplicate classes removed \u2014 use godawari package (see main.py)\n\n# \u2500\u2500 Recovery/Forensics stubs (when godawari package unavailable) \u2500\u2500\ntry:\n    from godawari.recovery.manager import RecoveryManager\n    from godawari.recovery.results import RecoveryResultItem, RecoveryResultStore\n    from godawari.recovery.safety import get_recovery_safety\n    from godawari.recovery.validation import validate_recovered_file\n    from godawari.recovery.mft import recover_deleted_mft_files\n    from godawari.recovery.progress import make_progress_callback\n    from godawari.forensics import (\n        is_forensic_engine_available,\n        scan_disk_with_forensic_engine,\n        scan_disk_entropy,\n        validate_media_headers,\n        detect_nand_erase_state,\n        raw_read,\n    )\n    import math\nexcept ImportError:\n    import math\n\n    class RecoveryResultItem:\n        def __init__(self, *a, **kw): pass\n\n    class RecoveryResultStore:\n        def __init__(self, *a, **kw): self._items = []\n        def add(self, item): self._items.append(item)\n        def all(self): return self._items\n        def clear(self): self._items = []\n        def count(self): return len(self._items)\n\n    class RecoveryManager:\n        def __init__(self, *a, **kw): pass\n        def start(self, *a, **kw): return None\n        def stop(self): pass\n\n    def get_recovery_safety(*a, **kw):\n        class _Safety:\n            def validate_output_dir(self, d, *a): return d\n        return _Safety()\n\n    def validate_recovered_file(*a, **kw): return True\n    def recover_deleted_mft_files(*a, **kw): return []\n    def make_progress_callback(*a, **kw): return lambda *x: None\n    def is_forensic_engine_available(): return False\n    def scan_disk_with_forensic_engine(*a, **kw): return []\n    def scan_disk_entropy(*a, **kw): return []\n    def validate_media_headers(*a, **kw): return {}\n    def detect_nand_erase_state(*a, **kw): return False\n    def raw_read(*a, **kw): return b\"\"\n\n\n# 6) Global exception handler \u2014 koi bhi crash user ko dikhai de\ndef _global_exc_handler(exc_type, exc_value, exc_tb):\n    import traceback\n    err = \"\".join(traceback.format_exception(exc_type, exc_value, exc_tb))\n    try:\n        root = tk.Tk(); root.withdraw()\n        messagebox.showerror(\"Unexpected Error \u2014 Godawari Optimizer\",\n            f\"Ek error aayi:\\n\\n{err[-800:]}\\n\\n\"\n            \"Screenshot lo aur developer ko bhejo.\")\n        root.destroy()\n    except:\n        print(\"FATAL ERROR:\\n\", err)\n        input(\"Press Enter to exit...\")\n    sys.exit(1)\n\nsys.excepthook = _global_exc_handler\n\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n#  SCRIPT LAST UPDATED \u2014 File modification time\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\ndef _get_script_last_updated():\n    \"\"\"Script file ki last modification date/time return karta hai.\"\"\"\n    try:\n        script_path = os.path.abspath(sys.argv[0])\n        if os.path.exists(script_path):\n            mtime = os.path.getmtime(script_path)\n            dt = datetime.datetime.fromtimestamp(mtime)\n            return dt.strftime(\"%d/%m/%Y  %H:%M\")\n    except Exception:\n        pass\n    return \"Unknown\"\n\nSCRIPT_LAST_UPDATED = _get_script_last_updated()\n\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n#  ADMIN CHECK\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\ndef is_admin():\n    try:\n        return bool(ctypes.windll.shell32.IsUserAnAdmin())\n    except Exception:\n        return False\n\ndef _gui_python_executable():\n    \"\"\"Use pythonw for GUI relaunch so the console window does not flash.\"\"\"\n    exe = sys.executable\n    try:\n        if exe and os.path.basename(exe).lower() == \"python.exe\":\n            pythonw = os.path.join(os.path.dirname(exe), \"pythonw.exe\")\n            if os.path.exists(pythonw):\n                return pythonw\n    except Exception:\n        pass\n    return exe\n\ndef run_as_admin():\n    if not is_admin():\n        script = os.path.abspath(sys.argv[0])\n        params = subprocess.list2cmdline([script] + sys.argv[1:])\n        workdir = os.path.dirname(script) or None\n        rc = ctypes.windll.shell32.ShellExecuteW(\n            None, \"runas\", _gui_python_executable(), params, workdir, 1\n        )\n        if rc &lt;= 32:\n            raise OSError(f\"Admin restart failed. ShellExecuteW code: {rc}\")\n        sys.exit()\n\ndef _admin_elevation_enabled():\n    return os.environ.get(\"GODAWARI_NO_ELEVATE\", \"0\").lower() not in (\"1\", \"true\", \"yes\")\n\ndef powershell_helper(script, timeout=60):\n    \"\"\"PowerShell helper: returns (output, return_code) with full error handling.\"\"\"\n    try:\n        result = safe_powershell(script, timeout=timeout)\n        return result.output, result.returncode\n    except FileNotFoundError:\n        return \"PowerShell nahi mila.\", -1\n    except Exception as e:\n        return f\"PowerShell error: {e}\", -1\n\ndef _ps_single_quote(value):\n    return \"'\" + str(value).replace(\"'\", \"''\") + \"'\"\n\ndef _same_windows_path(left, right):\n    try:\n        return os.path.normcase(os.path.abspath(left)) == os.path.normcase(os.path.abspath(right))\n    except Exception:\n        return False\n\ndef _console_confirm(title, message):\n    print(\"\\n\" + \"=\" * 70)\n    print(title)\n    print(\"=\" * 70)\n    print(message)\n    try:\n        answer = input(\"\\nConfirm karein? (haan/y = yes): \").strip().lower()\n        return answer in (\"y\", \"yes\", \"haan\", \"ha\", \"h\")\n    except Exception:\n        return False\n\ndef _safe_callback(callback, *args):\n    if callback:\n        try:\n            callback(*args)\n        except InterruptedError:\n            raise\n        except Exception:\n            return \"unknown\"\n\ndef _find_locking_processes_with_psutil(file_path):\n    matches = {}\n    for proc in psutil.process_iter([\"pid\", \"name\", \"exe\"]):\n        try:\n            pid = proc.info.get(\"pid\")\n            if pid == os.getpid():\n                continue\n            paths = []\n            exe = proc.info.get(\"exe\")\n            if exe:\n                paths.append(exe)\n            try:\n                for opened in proc.open_files() or []:\n                    if getattr(opened, \"path\", None):\n                        paths.append(opened.path)\n            except (psutil.AccessDenied, psutil.NoSuchProcess, psutil.ZombieProcess):\n                pass\n            if any(_same_windows_path(p, file_path) for p in paths):\n                matches[int(pid)] = {\n                    \"pid\": int(pid),\n                    \"name\": proc.info.get(\"name\") or \"Unknown\",\n                    \"exe\": exe or \"\",\n                    \"source\": \"psutil\",\n                }\n        except (psutil.AccessDenied, psutil.NoSuchProcess, psutil.ZombieProcess):\n            continue\n        except Exception:\n            continue\n    return matches\n\ndef _find_locking_processes_with_powershell(file_path):\n    # PowerShell fallback requested:\n    # Get-Process | Where-Object {$_.Modules.FileName -contains file}\n    target = _ps_single_quote(file_path)\n    script = f\"\"\"\n$target = {target}\nGet-Process | Where-Object {{\n    try {{ $_.Modules.FileName -contains $target }} catch {{ $false }}\n}} | ForEach-Object {{\n    $p = ''\n    try {{ $p = $_.Path }} catch {{ $p = '' }}\n    \"$($_.Id)|$($_.ProcessName)|$p\"\n}}\n\"\"\"\n    output, rc = powershell_helper(script, timeout=90)\n    matches = {}\n    if rc != 0 and not output:\n        return matches\n    for line in output.splitlines():\n        parts = line.strip().split(\"|\", 2)\n        if len(parts) &lt; 2 or not parts[0].isdigit():\n            continue\n        pid = int(parts[0])\n        if pid == os.getpid():\n            continue\n        matches[pid] = {\n            \"pid\": pid,\n            \"name\": parts[1] or \"Unknown\",\n            \"exe\": parts[2] if len(parts) &gt; 2 else \"\",\n            \"source\": \"powershell\",\n        }\n    return matches\n\ndef _format_process_list(processes):\n    lines = []\n    for item in processes:\n        exe = item.get(\"exe\") or \"Path unavailable\"\n        lines.append(f\"PID {item['pid']} - {item.get('name', 'Unknown')} - {exe} [{item.get('source','')}]\")\n    return \"\\n\".join(lines)\n\ndef unlock_file_if_locked(file_path, confirm_callback=None, log_callback=None):\n    \"\"\"\n    Locked file ko release karne ke liye process scan karta hai.\n    psutil first, PowerShell Modules fallback, PID show, user confirm, then terminate.\n    \"\"\"\n    try:\n        target = os.path.abspath(os.path.expandvars(os.path.expanduser(str(file_path).strip().strip('\"'))))\n        if not target:\n            raise ValueError(\"File path empty hai.\")\n        if not os.path.exists(target):\n            raise FileNotFoundError(f\"File nahi mili: {target}\")\n\n        _safe_callback(log_callback, f\"Locked file scan start: {target}\")\n        matches = _find_locking_processes_with_psutil(target)\n        ps_matches = _find_locking_processes_with_powershell(target)\n        matches.update(ps_matches)\n\n        processes = sorted(matches.values(), key=lambda x: x[\"pid\"])\n        if not processes:\n            msg = \"Koi locking process nahi mila. File abhi locked nahi lag rahi.\"\n            _safe_callback(log_callback, msg)\n            print(msg)\n            return {\"ok\": True, \"file\": target, \"terminated\": [], \"errors\": [], \"message\": msg}\n\n        details = _format_process_list(processes)\n        prompt = (\n            f\"Ye process file use kar rahe hain:\\n\\n{details}\\n\\n\"\n            \"In PID ko terminate karne se unsaved data loss ho sakta hai.\\n\"\n            \"Terminate karna hai?\"\n        )\n        confirm = confirm_callback or _console_confirm\n        if not confirm(\"Locked File Unlock\", prompt):\n            msg = \"User ne terminate cancel kiya.\"\n            _safe_callback(log_callback, msg)\n            return {\"ok\": False, \"file\": target, \"terminated\": [], \"errors\": [], \"message\": msg}\n\n        terminated = []\n        errors = []\n        for info in processes:\n            pid = info[\"pid\"]\n            try:\n                proc = psutil.Process(pid)\n                proc.terminate()\n                try:\n                    proc.wait(timeout=8)\n                except psutil.TimeoutExpired:\n                    pass\n                terminated.append(pid)\n                _safe_callback(log_callback, f\"PID terminate kiya: {pid} ({info.get('name','Unknown')})\")\n            except psutil.NoSuchProcess:\n                terminated.append(pid)\n            except psutil.AccessDenied:\n                errors.append(f\"PID {pid}: access denied. Admin mode me run karein.\")\n            except Exception as e:\n                errors.append(f\"PID {pid}: {e}\")\n\n        ok = len(errors) == 0\n        msg = f\"Terminate complete. Terminated: {len(terminated)}, Errors: {len(errors)}\"\n        _safe_callback(log_callback, msg)\n        if errors:\n            _safe_callback(log_callback, \"\\n\".join(errors))\n        return {\"ok\": ok, \"file\": target, \"terminated\": terminated, \"errors\": errors, \"message\": msg}\n    except Exception as e:\n        msg = f\"Unlock error: {e}\"\n        _safe_callback(log_callback, msg)\n        print(msg)\n        return {\"ok\": False, \"file\": str(file_path), \"terminated\": [], \"errors\": [msg], \"message\": msg}\n\ndef _human_size(num_bytes):\n    try:\n        value = float(num_bytes)\n        for unit in (\"B\", \"KB\", \"MB\", \"GB\", \"TB\"):\n            if value &lt; 1024 or unit == \"TB\":\n                return f\"{value:.1f} {unit}\" if unit != \"B\" else f\"{int(value)} B\"\n            value /= 1024\n    except Exception:\n        return \"0 B\"\n\ndef _is_dangerous_cleanup_target(folder_path):\n    try:\n        path = os.path.normcase(os.path.abspath(folder_path))\n        drive, tail = os.path.splitdrive(path)\n        if tail in (\"\\\\\", \"\"):\n            return True, \"Drive root delete nahi kar sakte.\"\n        protected = [\n            os.environ.get(\"SystemRoot\", r\"C:\\Windows\"),\n            os.environ.get(\"ProgramFiles\", r\"C:\\Program Files\"),\n            os.environ.get(\"ProgramFiles(x86)\", r\"C:\\Program Files (x86)\"),\n            os.environ.get(\"ProgramData\", r\"C:\\ProgramData\"),\n            os.environ.get(\"USERPROFILE\", \"\"),\n        ]\n        for item in protected:\n            if item and path == os.path.normcase(os.path.abspath(item)):\n                return True, f\"Protected folder delete block kiya: {item}\"\n    except Exception as e:\n        return True, f\"Path safety check failed: {e}\"\n    return False, \"\"\n\ndef _program_terms_from_folder(folder_path):\n    base = os.path.basename(os.path.normpath(folder_path)).lower()\n    raw = \"\".join(ch if ch.isalnum() else \" \" for ch in base).split()\n    blocked = {\"app\", \"program\", \"files\", \"setup\", \"install\", \"windows\", \"system\"}\n    return [w for w in raw if len(w) &gt;= 3 and w not in blocked]\n\ndef _registry_value_text(key):\n    chunks = []\n    try:\n        i = 0\n        while True:\n            try:\n                name, value, _ = winreg.EnumValue(key, i)\n                chunks.append(str(name))\n                chunks.append(str(value))\n                i += 1\n            except OSError:\n                break\n    except Exception:\n        pass\n    return \" \".join(chunks).lower()\n\ndef _find_registry_entries_for_program(folder_path, max_results=100):\n    folder_text = os.path.normcase(os.path.abspath(folder_path)).lower()\n    terms = _program_terms_from_folder(folder_path)\n    if not terms:\n        terms = [os.path.basename(os.path.normpath(folder_path)).lower()]\n    roots = [\n        (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\"),\n        (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\"),\n        (\"HKCU\", winreg.HKEY_CURRENT_USER, r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\"),\n        (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\"),\n        (\"HKCU\", winreg.HKEY_CURRENT_USER, r\"SOFTWARE\"),\n        (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Services\"),\n    ]\n    found = []\n    deadline = time.time() + 8\n\n    def check_subkey(hive_name, hive, path):\n        if len(found) &gt;= max_results or time.time() &gt; deadline:\n            return\n        try:\n            key = winreg.OpenKey(hive, path, 0, winreg.KEY_READ)\n        except Exception:\n            return\n        try:\n            text = f\"{path.lower()} {_registry_value_text(key)}\"\n            if folder_text in text or any(term in text for term in terms):\n                found.append(f\"{hive_name}\\\\{path}\")\n        finally:\n            try:\n                winreg.CloseKey(key)\n            except Exception:\n                pass\n\n    for hive_name, hive, root_path in roots:\n        if len(found) &gt;= max_results or time.time() &gt; deadline:\n            break\n        try:\n            root = winreg.OpenKey(hive, root_path, 0, winreg.KEY_READ)\n        except Exception:\n            continue\n        try:\n            i = 0\n            while len(found) &lt; max_results and time.time() &lt;= deadline:\n                try:\n                    sub = winreg.EnumKey(root, i)\n                    i += 1\n                    check_subkey(hive_name, hive, root_path + \"\\\\\" + sub)\n                except OSError:\n                    break\n                except Exception:\n                    continue\n        finally:\n            try:\n                winreg.CloseKey(root)\n            except Exception:\n                pass\n    return found\n\ndef _scan_folder_with_os_walk(folder_path, max_preview=80):\n    info = {\"files\": 0, \"dirs\": 0, \"size\": 0, \"preview\": [], \"errors\": []}\n\n    def on_error(error):\n        info[\"errors\"].append(str(error))\n\n    for root, dirs, files in os.walk(folder_path, onerror=on_error):\n        info[\"dirs\"] += len(dirs)\n        for name in files:\n            path = os.path.join(root, name)\n            info[\"files\"] += 1\n            try:\n                info[\"size\"] += os.path.getsize(path)\n            except Exception as e:\n                info[\"errors\"].append(f\"{path}: {e}\")\n            if len(info[\"preview\"]) &lt; max_preview:\n                info[\"preview\"].append(path)\n    return info\n\ndef _rmtree_error_handler(func, path, exc_info):\n    try:\n        os.chmod(path, 0o700)\n        func(path)\n    except Exception:\n        raise\n\ndef deep_cleanup_program(folder_path, confirm_callback=None, log_callback=None):\n    \"\"\"\n    Program folder ka deep cleanup: os.walk scan, winreg registry clues, user confirm, shutil.rmtree.\n    Registry entries sirf list hoti hain; delete folder ko shutil.rmtree se kiya jata hai.\n    \"\"\"\n    try:\n        target = os.path.abspath(os.path.expandvars(os.path.expanduser(str(folder_path).strip().strip('\"'))))\n        if not target:\n            raise ValueError(\"Folder path empty hai.\")\n        if not os.path.isdir(target):\n            raise NotADirectoryError(f\"Folder nahi mila: {target}\")\n\n        blocked, reason = _is_dangerous_cleanup_target(target)\n        if blocked:\n            raise PermissionError(reason)\n\n        admin_note = \"\"\n        if not is_admin():\n            admin_note = \"Warning: App admin mode me nahi hai; kuch files delete nahi ho sakti.\\n\\n\"\n            _safe_callback(log_callback, admin_note.strip())\n\n        _safe_callback(log_callback, f\"Deep cleanup scan start: {target}\")\n        scan = _scan_folder_with_os_walk(target)\n        reg_entries = _find_registry_entries_for_program(target)\n\n        preview = \"\\n\".join(scan[\"preview\"][:40])\n        if scan[\"files\"] &gt; 40:\n            preview += f\"\\n... aur {scan['files'] - 40} file(s)\"\n        reg_preview = \"\\n\".join(reg_entries[:40]) if reg_entries else \"Koi matching registry clue nahi mila.\"\n        if len(reg_entries) &gt; 40:\n            reg_preview += f\"\\n... aur {len(reg_entries) - 40} registry entry\"\n\n        prompt = (\n            f\"{admin_note}\"\n            f\"Folder: {target}\\n\"\n            f\"Files: {scan['files']}\\n\"\n            f\"Subfolders: {scan['dirs']}\\n\"\n            f\"Approx Size: {_human_size(scan['size'])}\\n\"\n            f\"Registry clues: {len(reg_entries)}\\n\"\n        )\n        if scan[\"errors\"]:\n            prompt += f\"Scan warnings: {len(scan['errors'])}\\n\"\n        prompt += (\n            f\"\\nFile list preview:\\n{preview or 'Folder empty hai.'}\\n\\n\"\n            f\"Registry list preview:\\n{reg_preview}\\n\\n\"\n            \"Confirm karne par folder permanently delete hoga:\\n\"\n            \"shutil.rmtree(folder_path)\\n\\n\"\n            \"Delete karein?\"\n        )\n\n        confirm = confirm_callback or _console_confirm\n        if not confirm(\"Deep Cleanup Program\", prompt):\n            msg = \"User ne deep cleanup cancel kiya.\"\n            _safe_callback(log_callback, msg)\n            return {\"ok\": False, \"folder\": target, \"deleted\": False, \"registry_entries\": reg_entries, \"message\": msg}\n\n        shutil.rmtree(target, onerror=_rmtree_error_handler)\n        msg = f\"Deep cleanup complete: {target} delete ho gaya.\"\n        _safe_callback(log_callback, msg)\n        return {\n            \"ok\": True,\n            \"folder\": target,\n            \"deleted\": True,\n            \"files\": scan[\"files\"],\n            \"dirs\": scan[\"dirs\"],\n            \"size\": scan[\"size\"],\n            \"registry_entries\": reg_entries,\n            \"scan_errors\": scan[\"errors\"],\n            \"message\": msg,\n        }\n    except Exception as e:\n        msg = f\"Deep cleanup error: {e}\"\n        _safe_callback(log_callback, msg)\n        print(msg)\n        return {\"ok\": False, \"folder\": str(folder_path), \"deleted\": False, \"registry_entries\": [], \"errors\": [msg], \"message\": msg}\n\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n#  COLOR THEME\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n# ---------------------------------------------------------------------\n# RAW DATA RECOVERY ENGINE\n# ---------------------------------------------------------------------\nSECTOR_SIZE = 512\nDEFAULT_RAW_DISK = \"\"  # User ko disk select karni hogi \u2014 PhysicalDrive0 default unsafe tha\nRAW_READ_RETRIES = 3\nRAW_MIN_READ_CHUNK = 4096\nRAW_SCAN_DEVICE_CHUNK = 2 * 1024 * 1024\nRAW_SCAN_IMAGE_CHUNK = 8 * 1024 * 1024\nRAW_SCAN_OVERLAP = 1024 * 1024\nRAW_SCAN_DEVICE_PAUSE_MS = 25\nRAW_SCAN_PROGRESS_STEP = 32 * 1024 * 1024\n\nSIGNATURES = {\n    \"JPG\": {\n        \"ext\": \".jpg\",\n        \"headers\": [b\"\\xFF\\xD8\\xFF\"],\n        \"footer\": b\"\\xFF\\xD9\",\n        \"max_size\": 50 * 1024 * 1024,\n        \"description\": \"JPEG image\",\n    },\n    \"PDF\": {\n        \"ext\": \".pdf\",\n        \"headers\": [b\"%PDF\"],\n        \"footer\": b\"%%EOF\",\n        \"max_size\": 200 * 1024 * 1024,\n        \"description\": \"PDF document\",\n    },\n    \"MP4\": {\n        \"ext\": \".mp4\",\n        \"headers\": [b\"ftyp\"],\n        \"footer\": None,\n        \"max_size\": 2 * 1024 * 1024 * 1024,\n        \"description\": \"MP4 video\",\n    },\n    \"ZIP\": {\n        \"ext\": \".zip\",\n        \"headers\": [b\"PK\\x03\\x04\"],\n        \"footer\": b\"PK\\x05\\x06\",\n        \"max_size\": 500 * 1024 * 1024,\n        \"description\": \"ZIP archive\",\n    },\n    \"EXE\": {\n        \"ext\": \".exe\",\n        \"headers\": [b\"MZ\"],\n        \"footer\": None,\n        \"max_size\": 200 * 1024 * 1024,\n        \"description\": \"Windows executable\",\n    },\n}\n\ndef _raw_progress(progress_callback, message):\n    _safe_callback(progress_callback, message)\n\ndef _is_raw_device_path(path):\n    return bool(re.match(r\"^\\\\\\\\\\.\\\\(PhysicalDrive\\d+|[A-Z]:)$\", str(path or \"\"), re.I))\n\ndef _require_raw_admin(disk_path=None):\n    if (disk_path is None or _is_raw_device_path(disk_path)) and not is_admin():\n        raise PermissionError(\"Admin rights chahiye. Raw disk access ke liye Run as Administrator karein.\")\n\ndef _powershell_read_raw_bytes(disk_path, offset, length):\n    script = f\"\"\"\n$path = {_ps_single_quote(disk_path)}\n$offset = [Int64]{int(offset)}\n$length = [Int32]{int(length)}\n$fs = [System.IO.File]::Open($path, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::ReadWrite)\ntry {{\n    [void]$fs.Seek($offset, [System.IO.SeekOrigin]::Begin)\n    $buffer = New-Object byte[] $length\n    $read = $fs.Read($buffer, 0, $length)\n    if ($read -le 0) {{ \"\" }} else {{ [Convert]::ToBase64String($buffer, 0, $read) }}\n}} finally {{\n    $fs.Close()\n}}\n\"\"\"\n    output, rc = powershell_helper(script, timeout=120)\n    if rc != 0:\n        raise OSError(f\"PowerShell raw read failed: {output}\")\n    output = output.strip()\n    if not output:\n        return b\"\"\n    try:\n        return base64.b64decode(output)\n    except Exception as e:\n        raise OSError(f\"PowerShell fallback decode failed: {e}. Output: {output[:120]}\")\n\ndef _read_raw_at(disk_path, offset, length, disk_handle=None):\n    if length &lt;= 0:\n        return b\"\"\n    if disk_handle is not None:\n        try:\n            disk_handle.seek(offset)\n            return disk_handle.read(length)\n        except Exception:\n            return \"Unknown\"\n\n    try:\n        from godawari.forensics.engine import raw_read as _forensic_raw_read\n    except Exception:\n        _forensic_raw_read = None\n\n    if _forensic_raw_read is not None:\n        try:\n            return _forensic_raw_read(disk_path, offset, int(length))\n        except Exception:\n            pass\n\n    last_error = None\n    read_len = int(length)\n    for _ in range(RAW_READ_RETRIES):\n        try:\n            with open(disk_path, \"rb\", buffering=0) as disk:\n                disk.seek(offset)\n                return disk.read(read_len)\n        except Exception as e:\n            last_error = e\n            read_len = max(RAW_MIN_READ_CHUNK, read_len // 2)\n    try:\n        return _powershell_read_raw_bytes(disk_path, offset, length)\n    except Exception:\n        if last_error:\n            raise last_error\n        raise\n\ndef _scan_chunk_profile(disk_path, block_size):\n    base = max(int(block_size or SECTOR_SIZE) * 1024, RAW_SCAN_DEVICE_CHUNK)\n    if _is_raw_device_path(disk_path):\n        chunk_size = min(max(base, RAW_SCAN_DEVICE_CHUNK), 4 * 1024 * 1024)\n        pause_s = RAW_SCAN_DEVICE_PAUSE_MS / 1000.0\n    else:\n        chunk_size = min(max(base, RAW_SCAN_IMAGE_CHUNK), 16 * 1024 * 1024)\n        pause_s = 0.0\n    return chunk_size, pause_s\n\ndef _detect_signature_in_sector(sector, sector_offset, file_types):\n    hits = []\n    for file_type in file_types:\n        meta = SIGNATURES.get(file_type)\n        if not meta:\n            continue\n        for header in meta[\"headers\"]:\n            start = 0\n            while True:\n                pos = sector.find(header, start)\n                if pos &lt; 0:\n                    break\n                real_offset = sector_offset + pos\n                confidence = \"medium\"\n                if file_type == \"MP4\":\n                    if pos &lt; 4:\n                        start = pos + 1\n                        continue\n                    box_start = pos - 4\n                    try:\n                        box_size = struct.unpack(\"&gt;I\", sector[box_start:box_start + 4])[0]\n                    except Exception:\n                        box_size = 0\n                    if box_size &lt; 8 or box_size &gt; 1024 * 1024 * 1024:\n                        start = pos + 1\n                        continue\n                    real_offset = sector_offset + box_start\n                    confidence = \"high\"\n                elif pos == 0:\n                    confidence = \"high\"\n                hits.append({\n                    \"disk_path\": \"\",\n                    \"offset\": real_offset,\n                    \"sector\": real_offset // SECTOR_SIZE,\n                    \"file_type\": file_type,\n                    \"extension\": meta[\"ext\"],\n                    \"signature\": header.hex(\" \").upper(),\n                    \"confidence\": confidence,\n                    \"description\": meta[\"description\"],\n                })\n                start = pos + 1\n    return hits\n\ndef scan_disk_for_files(disk_path, max_bytes=None, start_offset=0, file_types=None, progress_callback=None, stats_callback=None):\n    \"\"\"\n    Raw disk ko 512-byte sector-by-sector scan karta hai aur JPG/PDF/MP4/ZIP/EXE signatures dhundta hai.\n    Example: scan_disk_for_files(DEFAULT_RAW_DISK)\n    \"\"\"\n    disk_path = str(disk_path or DEFAULT_RAW_DISK).strip()\n    if not disk_path:\n        raise ValueError(\"Scan ke liye source disk/image select karein\")\n    _require_raw_admin(disk_path)\n    file_types = [ft.upper().strip(\".\") for ft in (file_types or SIGNATURES.keys()) if ft]\n    file_types = [ft for ft in file_types if ft in SIGNATURES]\n    if not file_types:\n        file_types = list(SIGNATURES.keys())\n    chunk_size = 1024 * 1024\n    chunk_size -= chunk_size % SECTOR_SIZE\n    offset = int(start_offset)\n    scanned = 0\n    found = []\n    seen = set()\n    disk = None\n    use_powershell = False\n    total_size = int(max_bytes) if max_bytes is not None else _disk_source_size(disk_path)\n    try:\n        try:\n            from godawari.forensics.engine import scan_disk_with_forensic_engine as _forensic_scan\n        except Exception:\n            _forensic_scan = None\n\n        if _forensic_scan is not None:\n            try:\n                found = _forensic_scan(disk_path, max_bytes=max_bytes, start_offset=offset, file_types=file_types, progress_callback=progress_callback)\n                if found:\n                    return found\n                _raw_progress(progress_callback, \"Forensic scan empty \u2014 Python sector scan fallback\")\n            except Exception as e:\n                _raw_progress(progress_callback, f\"Forensic engine failed, Python fallback use ho raha hai: {e}\")\n\n        try:\n            disk = open(disk_path, \"rb\", buffering=0)\n            disk.seek(offset)\n            _raw_progress(progress_callback, f\"Raw disk open ho gaya: {disk_path}\")\n        except Exception as e:\n            use_powershell = True\n            _raw_progress(progress_callback, f\"Python raw open failed, PowerShell fallback use ho raha hai: {e}\")\n\n        while True:\n            if max_bytes is not None:\n                remaining = int(max_bytes) - scanned\n                if remaining &lt;= 0:\n                    break\n                read_len = min(chunk_size, remaining)\n            else:\n                read_len = chunk_size\n\n            if use_powershell:\n                data = _powershell_read_raw_bytes(disk_path, offset + scanned, read_len)\n            else:\n                data = disk.read(read_len)\n            if not data:\n                break\n\n            usable = len(data) - (len(data) % SECTOR_SIZE)\n            for pos in range(0, usable, SECTOR_SIZE):\n                sector_offset = offset + scanned + pos\n                sector = data[pos:pos + SECTOR_SIZE]\n                for hit in _detect_signature_in_sector(sector, sector_offset, file_types):\n                    key = (hit[\"offset\"], hit[\"file_type\"])\n                    if key in seen:\n                        continue\n                    seen.add(key)\n                    hit[\"disk_path\"] = disk_path\n                    found.append(hit)\n\n            scanned += len(data)\n            if scanned % (4 * 1024 * 1024) &lt; chunk_size:\n                if total_size:\n                    pct = min(100, int((scanned / total_size) * 100))\n                    _raw_progress(progress_callback, f\"Raw scan {pct}% complete \u2014 {_human_size(scanned)} scanned, {len(found)} signatures mili\")\n                else:\n                    _raw_progress(progress_callback, f\"Raw scan: {_human_size(scanned)} scanned, {len(found)} file signature mile\")\n                if stats_callback:\n                    try:\n                        stats_callback({\n                            \"pct\": pct if total_size else min(99, scanned // (32 * 1024 * 1024)),\n                            \"files_found\": len(found),\n                            \"bytes_scanned\": scanned,\n                            \"message\": f\"{len(found)} signatures \u2014 {_human_size(scanned)} scanned\",\n                        })\n                    except Exception:\n                        pass\n    except Exception as e:\n        _raw_progress(progress_callback, f\"Raw scan error: {e}\")\n        raise\n    finally:\n        if disk is not None:\n            try:\n                disk.close()\n            except Exception:\n                pass\n    _raw_progress(progress_callback, f\"Scan complete: {len(found)} signatures mile\")\n    return found\n\ndef _read_until_footer(disk_path, offset, footer, max_size, disk_handle=None, progress_callback=None):\n    data = bytearray()\n    read_pos = int(offset)\n    overlap = max(len(footer) + 16, 64)\n    while len(data) &lt; max_size:\n        to_read = min(1024 * 1024, max_size - len(data))\n        chunk = _read_raw_at(disk_path, read_pos, to_read, disk_handle=disk_handle)\n        if not chunk:\n            break\n        previous_tail = bytes(data[-overlap:])\n        data.extend(chunk)\n        search_area = previous_tail + chunk\n        idx = search_area.find(footer)\n        if idx &gt;= 0:\n            absolute_end = len(data) - len(chunk) - len(previous_tail) + idx + len(footer)\n            if absolute_end &lt; 0:\n                absolute_end = len(data)\n            return bytes(data[:absolute_end])\n        read_pos += len(chunk)\n        if len(data) % (32 * 1024 * 1024) &lt; 1024 * 1024:\n            _raw_progress(progress_callback, f\"Boundary dhund rahe hain: {_human_size(len(data))} read\")\n    return bytes(data)\n\ndef _estimate_mp4_size(disk_path, offset, max_size, disk_handle=None):\n    pos = int(offset)\n    total = 0\n    boxes = 0\n    while total &lt; max_size and boxes &lt; 10000:\n        header = _read_raw_at(disk_path, pos, 16, disk_handle=disk_handle)\n        if len(header) &lt; 8:\n            break\n        box_size, box_type = struct.unpack(\"&gt;I4s\", header[:8])\n        header_len = 8\n        if boxes == 0 and box_type != b\"ftyp\":\n            return None\n        if box_size == 1:\n            if len(header) &lt; 16:\n                break\n            box_size = struct.unpack(\"&gt;Q\", header[8:16])[0]\n            header_len = 16\n        elif box_size == 0:\n            break\n        if box_size &lt; header_len or box_size &gt; (max_size - total):\n            break\n        total += box_size\n        pos += box_size\n        boxes += 1\n    return total if total &gt;= 8 else None\n\ndef _estimate_exe_size(disk_path, offset, max_size, disk_handle=None):\n    head = _read_raw_at(disk_path, offset, 4096, disk_handle=disk_handle)\n    if len(head) &lt; 0x40 or head[:2] != b\"MZ\":\n        return None\n    try:\n        pe_offset = struct.unpack_from(\"= 0 and len(data) &gt;= eocd + 22:\n            comment_len = struct.unpack_from(\" len(data):\n                extra = _read_raw_at(disk_path, offset + len(data), wanted - len(data), disk_handle=disk_handle)\n                data += extra\n            data = data[:wanted]\n    else:\n        data = _read_until_footer(disk_path, offset, meta[\"footer\"], limit, disk_handle=disk_handle, progress_callback=progress_callback)\n\n    if not data:\n        raise OSError(\"Koi data extract nahi hua.\")\n    safe_offset = f\"{offset:012X}\"\n    out_path = safety.validate_write_path(\n        os.path.join(output_dir, f\"recovered_{file_type.lower()}_{safe_offset}{meta['ext']}\"),\n        disk_path,\n    )\n    with open(out_path, \"wb\") as out:\n        out.write(data)\n    complete = True\n    if meta.get(\"footer\") and meta[\"footer\"] not in data[-4096:]:\n        complete = False\n    _raw_progress(progress_callback, f\"Extraction done: {out_path} ({_human_size(len(data))})\")\n    return {\n        \"ok\": True,\n        \"path\": out_path,\n        \"bytes\": len(data),\n        \"file_type\": file_type,\n        \"offset\": offset,\n        \"complete_boundary\": complete,\n    }\n\ndef create_disk_image(source_disk, img_path, max_bytes=None, progress_callback=None):\n    \"\"\"Raw disk/volume ka IMG backup banata hai. Example source: DEFAULT_RAW_DISK.\"\"\"\n    source_disk = str(source_disk or DEFAULT_RAW_DISK)\n    if not source_disk:\n        raise ValueError(\"Source disk select karein \u2014 default PhysicalDrive0 ab disabled hai\")\n    _require_raw_admin(source_disk)\n    try:\n        from godawari.services.config_manager import ConfigManager\n        safety = get_recovery_safety(ConfigManager())\n    except Exception:\n        safety = get_recovery_safety()\n    img_path = safety.validate_write_path(os.path.abspath(os.path.expanduser(str(img_path))), source_disk)\n    os.makedirs(os.path.dirname(img_path) or os.getcwd(), exist_ok=True)\n    chunk_size = 4 * 1024 * 1024\n    copied = 0\n    disk = None\n    use_powershell = False\n    total_size = int(max_bytes) if max_bytes is not None else _disk_source_size(source_disk)\n    last_pct = -1\n    last_update = 0\n    try:\n        try:\n            disk = open(source_disk, \"rb\", buffering=0)\n            _raw_progress(progress_callback, f\"IMG source open ho gaya: {source_disk}\")\n        except Exception as e:\n            use_powershell = True\n            _raw_progress(progress_callback, f\"Python raw open failed, PowerShell fallback use hoga: {e}\")\n        with open(img_path, \"wb\") as out:\n            while True:\n                if max_bytes is not None:\n                    remaining = int(max_bytes) - copied\n                    if remaining &lt;= 0:\n                        break\n                    read_len = min(chunk_size, remaining)\n                else:\n                    read_len = chunk_size\n                if use_powershell:\n                    data = _powershell_read_raw_bytes(source_disk, copied, read_len)\n                else:\n                    data = disk.read(read_len)\n                if not data:\n                    break\n                out.write(data)\n                copied += len(data)\n                now = time.time()\n                progress_text = None\n                if total_size:\n                    pct = min(100, int((copied / total_size) * 100))\n                    if pct != last_pct or now - last_update &gt; 1:\n                        last_pct = pct\n                        last_update = now\n                        progress_text = f\"IMG creation: {pct}% complete ({_human_size(copied)} copied)\"\n                elif now - last_update &gt; 1:\n                    last_update = now\n                    progress_text = f\"IMG ban rahi hai: {_human_size(copied)} copied\"\n                if progress_text:\n                    _raw_progress(progress_callback, progress_text)\n    finally:\n        if disk is not None:\n            try:\n                disk.close()\n            except Exception:\n                pass\n    _raw_progress(progress_callback, f\"IMG complete: {img_path} ({_human_size(copied)})\")\n    return {\"ok\": True, \"img_path\": img_path, \"bytes\": copied}\n\ndef copy_disk_range_to_img(source_disk, img_path, start_offset=0, max_bytes=None, progress_callback=None):\n    \"\"\"Hex/sector viewer se selected range ko IMG me export karta hai.\"\"\"\n    source_disk = str(source_disk or DEFAULT_RAW_DISK)\n    if not source_disk:\n        raise ValueError(\"Source disk select karein\")\n    _require_raw_admin(source_disk)\n    try:\n        from godawari.services.config_manager import ConfigManager\n        safety = get_recovery_safety(ConfigManager())\n    except Exception:\n        safety = get_recovery_safety()\n    img_path = safety.validate_write_path(os.path.abspath(os.path.expanduser(str(img_path))), source_disk)\n    os.makedirs(os.path.dirname(img_path) or os.getcwd(), exist_ok=True)\n    start_offset = int(start_offset)\n    chunk_size = 4 * 1024 * 1024\n    copied = 0\n    source_size = _disk_source_size(source_disk)\n    if max_bytes is None and source_size:\n        max_bytes = max(0, source_size - start_offset)\n    total_size = int(max_bytes) if max_bytes is not None else None\n    last_pct = -1\n    last_update = 0\n    with open(img_path, \"wb\") as out:\n        while True:\n            if max_bytes is not None:\n                remaining = int(max_bytes) - copied\n                if remaining &lt;= 0:\n                    break\n                read_len = min(chunk_size, remaining)\n            else:\n                read_len = chunk_size\n            data = _read_raw_at(source_disk, start_offset + copied, read_len)\n            if not data:\n                break\n            out.write(data)\n            copied += len(data)\n            now = time.time()\n            progress_text = None\n            if total_size:\n                pct = min(100, int((copied / total_size) * 100))\n                if pct != last_pct or now - last_update &gt; 1:\n                    last_pct = pct\n                    last_update = now\n                    progress_text = f\"Sector IMG export: {pct}% complete ({_human_size(copied)} copied)\"\n            elif now - last_update &gt; 1:\n                last_update = now\n                progress_text = f\"Sector IMG export: {_human_size(copied)} copied\"\n            if progress_text:\n                _raw_progress(progress_callback, progress_text)\n    _raw_progress(progress_callback, f\"Sector IMG complete: {img_path} ({_human_size(copied)})\")\n    return {\"ok\": True, \"img_path\": img_path, \"bytes\": copied, \"start_offset\": start_offset}\n\ndef raw_hex_viewer(sector_num, disk_path=DEFAULT_RAW_DISK, sectors=1, bytes_per_line=16):\n    \"\"\"DiskGenius style raw hex view return karta hai.\"\"\"\n    _require_raw_admin(disk_path)\n    sector_num = int(sector_num)\n    sectors = max(1, int(sectors))\n    offset = sector_num * SECTOR_SIZE\n    data = _read_raw_at(disk_path, offset, sectors * SECTOR_SIZE)\n    if not data:\n        raise OSError(f\"No bytes read at sector {sector_num}. Source/sector may be invalid or access is blocked.\")\n    checksum = sum(data) &amp; 0xFFFFFFFF\n    non_zero = sum(1 for b in data if b)\n    lines = [\n        f\"Disk: {disk_path}\",\n        f\"REAL RAW READ: open/read from disk device, not simulated\",\n        f\"Sector: {sector_num}  Offset: 0x{offset:016X}  Bytes: {len(data)}  NonZero: {non_zero}  Checksum32: 0x{checksum:08X}\",\n        \"-\" * 78,\n    ]\n    for i in range(0, len(data), bytes_per_line):\n        chunk = data[i:i + bytes_per_line]\n        hex_part = \" \".join(f\"{b:02X}\" for b in chunk)\n        hex_part = hex_part.ljust(bytes_per_line * 3 - 1)\n        ascii_part = \"\".join(chr(b) if 32 &lt;= b &lt; 127 else \".\" for b in chunk)\n        lines.append(f\"{offset + i:016X}  {hex_part}  |{ascii_part}|\")\n    return \"\\n\".join(lines)\n\n# ---------------------------------------------------------------------\n# PHOTOREC-STYLE DEEP SCAN ENGINE\n# ---------------------------------------------------------------------\nPHOTOREC_SIGNATURES = {\n    b\"\\xFF\\xD8\\xFF\": (\"jpg\", b\"\\xFF\\xD9\"),\n    b\"\\x89PNG\\r\\n\\x1A\\n\": (\"png\", b\"IEND\"),\n    b\"%PDF-\": (\"pdf\", b\"%%EOF\"),\n    b\"PK\\x03\\x04\": (\"zip\", b\"PK\\x05\\x06\"),\n    b\"MZ\": (\"exe\", None),\n    b\"GIF87a\": (\"gif\", b\"\\x3B\"),\n    b\"GIF89a\": (\"gif\", b\"\\x3B\"),\n    b\"BM\": (\"bmp\", None),\n    b\"RIFF\": (\"riff\", None),\n    b\"ID3\": (\"mp3\", None),\n    b\"\\xFF\\xFB\": (\"mp3\", None),\n    b\"fLaC\": (\"flac\", None),\n    b\"OggS\": (\"ogg\", None),\n    b\"\\x1F\\x8B\\x08\": (\"gz\", None),\n    b\"BZh\": (\"bz2\", None),\n    b\"\\xFD7zXZ\\x00\": (\"xz\", b\"YZ\"),\n    b\"7z\\xBC\\xAF\\x27\\x1C\": (\"7z\", None),\n    b\"Rar!\\x1A\\x07\\x00\": (\"rar\", None),\n    b\"Rar!\\x1A\\x07\\x01\\x00\": (\"rar5\", None),\n    b\"\\xD0\\xCF\\x11\\xE0\\xA1\\xB1\\x1A\\xE1\": (\"ole\", None),\n    b\"{\\\\rtf\": (\"rtf\", b\"}\"),\n    b\"SQLite format 3\\x00\": (\"sqlite\", None),\n    b\"\\x00\\x00\\x01\\x00\": (\"ico\", None),\n    b\"8BPS\": (\"psd\", None),\n    b\"MSCF\": (\"cab\", None),\n    b\"\\x25!PS\": (\"ps\", b\"%%EOF\"),\n    b\"FLV\\x01\": (\"flv\", None),\n    b\"\\x1A\\x45\\xDF\\xA3\": (\"mkv\", None),\n    b\"\\x00\\x00\\x01\\xBA\": (\"mpg\", None),\n    b\"\\x00\\x00\\x01\\xB3\": (\"mpg\", None),\n}\n\nSIGNATURE_BYTES = PHOTOREC_SIGNATURES\n\nPHOTOREC_REGEX_SIGNATURES = [\n    (re.compile(br\"\\x00\\x00\\x00[\\x08-\\xFF]ftyp\"), \"mp4\", None),\n]\n\nPHOTOREC_EXT_MAP = {\n    \"riff\": \"wav\",\n    \"ole\": \"doc\",\n    \"rar5\": \"rar\",\n}\n\ndef _load_custom_signature_config():\n    base_dir = os.path.join(os.environ.get(\"APPDATA\", \"\"), \"GodawariOptimizer\")\n    cfg_path = os.path.join(base_dir, \"custom_signatures.json\")\n    if not os.path.isfile(cfg_path):\n        return 0\n    loaded = 0\n    try:\n        with open(cfg_path, \"r\", encoding=\"utf-8\") as f:\n            payload = json.load(f)\n        items = payload if isinstance(payload, list) else payload.get(\"signatures\", [])\n        for item in items:\n            if not isinstance(item, dict):\n                continue\n            header_hex = str(item.get(\"header_hex\", \"\")).replace(\" \", \"\")\n            file_type = str(item.get(\"file_type\", \"\")).strip().lower()\n            if not header_hex or not file_type:\n                continue\n            try:\n                header = bytes.fromhex(header_hex)\n            except Exception:\n                continue\n            footer_hex = str(item.get(\"footer_hex\", \"\") or \"\").replace(\" \", \"\")\n            footer = bytes.fromhex(footer_hex) if footer_hex else None\n            PHOTOREC_SIGNATURES[header] = (file_type, footer)\n            loaded += 1\n    except Exception:\n        return 0\n    return loaded\n\nCUSTOM_SIGNATURE_COUNT = _load_custom_signature_config()\n\ndef _photorec_progress(progress_callback, message):\n    _safe_callback(progress_callback, message)\n\ndef _normalize_recovery_type(file_type):\n    file_type = str(file_type).lower().strip(\".\")\n    return PHOTOREC_EXT_MAP.get(file_type, file_type)\n\ndef _next_recup_dir(output_dir):\n    os.makedirs(output_dir, exist_ok=True)\n    idx = 1\n    while True:\n        path = os.path.join(output_dir, f\"recup_dir.{idx}\")\n        if not os.path.exists(path):\n            os.makedirs(path, exist_ok=True)\n            return path\n        idx += 1\n\ndef _disk_source_size(disk_path):\n    try:\n        if os.path.isfile(disk_path):\n            return os.path.getsize(disk_path)\n    except Exception:\n        pass\n    vol = re.match(r\"^\\\\\\\\\\.\\\\([A-Z]):$\", str(disk_path), re.I)\n    if vol:\n        letter = vol.group(1).upper() + \":\"\n        script = f\"$d=Get-CimInstance Win32_LogicalDisk -Filter \\\"DeviceID='{letter}'\\\"; if($d){{[string]$d.Size}}\"\n        out, rc = powershell_helper(script, timeout=20)\n        if rc == 0:\n            try:\n                return int(out.strip().splitlines()[-1])\n            except Exception:\n                pass\n    m = re.match(r\"^\\\\\\\\\\.\\\\PhysicalDrive(\\d+)$\", str(disk_path), re.I)\n    if m:\n        script = (\n            f\"$d=Get-CimInstance Win32_DiskDrive | Where-Object {{$_.Index -eq {int(m.group(1))}}}; \"\n            \"if($d){[string]$d.Size}\"\n        )\n        out, rc = powershell_helper(script, timeout=20)\n        if rc == 0:\n            try:\n                return int(out.strip().splitlines()[-1])\n            except Exception:\n                pass\n    return None\n\ndef _auto_detect_block_size(disk_path):\n    path = str(disk_path)\n    vol = re.match(r\"^\\\\\\\\\\.\\\\([A-Z]):$\", path, re.I)\n    if vol:\n        out, rc = powershell_helper(f\"fsutil fsinfo ntfsinfo {vol.group(1)}:\", timeout=20)\n        if rc == 0:\n            m = re.search(r\"Bytes Per Cluster\\s*:\\s*(\\d+)\", out, re.I)\n            if m:\n                return int(m.group(1))\n    phy = re.match(r\"^\\\\\\\\\\.\\\\PhysicalDrive(\\d+)$\", path, re.I)\n    if phy:\n        script = (\n            f\"$d=Get-CimInstance Win32_DiskDrive | Where-Object {{$_.Index -eq {int(phy.group(1))}}}; \"\n            \"if($d){[string]$d.BytesPerSector}\"\n        )\n        out, rc = powershell_helper(script, timeout=20)\n        if rc == 0:\n            try:\n                sector = int(out.strip().splitlines()[-1])\n                return 4096 if sector &gt;= 4096 else 512\n            except Exception:\n                pass\n    try:\n        sample = _read_raw_at(path, 0, 4 * 1024 * 1024)\n        offsets = []\n        for sig in PHOTOREC_SIGNATURES:\n            pos = sample.find(sig)\n            if pos &gt; 0:\n                offsets.append(pos)\n        for pattern, _, _ in PHOTOREC_REGEX_SIGNATURES:\n            match = pattern.search(sample)\n            if match:\n                offsets.append(match.start())\n        if offsets and all(pos % 4096 == 0 for pos in offsets):\n            return 4096\n    except Exception:\n        pass\n    return 512\n\ndef _detect_photorec_signature(buffer, absolute_base, aligned_only=False, block_size=512):\n    hits = []\n    for sig, (file_type, footer) in PHOTOREC_SIGNATURES.items():\n        start = 0\n        while True:\n            pos = buffer.find(sig, start)\n            if pos &lt; 0:\n                break\n            absolute = absolute_base + pos\n            if not aligned_only or absolute % block_size == 0:\n                hits.append((absolute, _normalize_recovery_type(file_type), sig, footer))\n            start = pos + 1\n    for pattern, file_type, footer in PHOTOREC_REGEX_SIGNATURES:\n        for match in pattern.finditer(buffer):\n            absolute = absolute_base + match.start()\n            if not aligned_only or absolute % block_size == 0:\n                hits.append((absolute, _normalize_recovery_type(file_type), match.group(0), footer))\n    hits.sort(key=lambda item: item[0])\n    return hits\n\ndef detect_file_boundaries(chunk, sig_type):\n    sig_type = _normalize_recovery_type(sig_type)\n    if sig_type == \"jpg\":\n        pos = chunk.find(b\"\\xFF\\xD9\", 2)\n        return pos + 2 if pos &gt;= 0 else None\n    if sig_type == \"png\":\n        pos = chunk.find(b\"IEND\")\n        return pos + 8 if pos &gt;= 0 else None\n    if sig_type == \"pdf\":\n        match = re.search(br\"%%EOF[\\r\\n\\t ]*\", chunk)\n        return match.end() if match else None\n    if sig_type == \"zip\":\n        pos = chunk.rfind(b\"PK\\x05\\x06\")\n        if pos &gt;= 0 and len(chunk) &gt;= pos + 22:\n            try:\n                comment_len = struct.unpack_from(\"I4s\", chunk[total:total + 8])\n            except Exception:\n                break\n            header_len = 8\n            if boxes == 0 and box_type != b\"ftyp\":\n                return None\n            if box_size == 1 and total + 16 &lt;= len(chunk):\n                box_size = struct.unpack(\"&gt;Q\", chunk[total + 8:total + 16])[0]\n                header_len = 16\n            elif box_size == 0:\n                return total if total else None\n            if box_size &lt; header_len or total + box_size &gt; len(chunk):\n                return None\n            total += box_size\n            boxes += 1\n            if box_type in (b\"mdat\", b\"moov\") and boxes &gt; 1:\n                continue\n        return total if total else None\n    if sig_type in (\"exe\", \"dll\"):\n        return _estimate_exe_size_from_bytes(chunk)\n    if sig_type == \"bmp\" and len(chunk) &gt;= 6:\n        size = struct.unpack_from(\" 14 else None\n    if sig_type == \"wav\" and chunk.startswith(b\"RIFF\") and len(chunk) &gt;= 8:\n        return struct.unpack_from(\"= 0 else None\n    return None\n\ndef _estimate_exe_size_from_bytes(data):\n    if len(data) &lt; 0x40 or data[:2] != b\"MZ\":\n        return None\n    try:\n        pe_offset = struct.unpack_from(\" len(data) or data[pe_offset:pe_offset + 4] != b\"PE\\0\\0\":\n            return None\n        sections = struct.unpack_from(\" len(data):\n                return None\n            raw_size = struct.unpack_from(\" 0 else None\n    except Exception:\n        return None\n\ndef validate_file(data, file_type):\n    file_type = _normalize_recovery_type(file_type)\n    try:\n        if file_type == \"jpg\":\n            if not (data.startswith(b\"\\xFF\\xD8\\xFF\") and b\"\\xFF\\xD9\" in data[-4096:]):\n                return False\n            pos = 2\n            while pos + 4 &lt; len(data):\n                if data[pos] != 0xFF:\n                    pos += 1\n                    continue\n                marker = data[pos + 1]\n                if marker == 0xD9:\n                    return True\n                if marker in (0x01,) or 0xD0 &lt;= marker &lt;= 0xD8:\n                    pos += 2\n                    continue\n                seg_len = struct.unpack(\"&gt;H\", data[pos + 2:pos + 4])[0]\n                if seg_len &lt; 2:\n                    return False\n                pos += 2 + seg_len\n            return False\n        if file_type == \"png\":\n            if not data.startswith(b\"\\x89PNG\\r\\n\\x1A\\n\"):\n                return False\n            pos = 8\n            while pos + 12 &lt;= len(data):\n                length = struct.unpack(\"&gt;I\", data[pos:pos + 4])[0]\n                ctype = data[pos + 4:pos + 8]\n                end = pos + 12 + length\n                if end &gt; len(data):\n                    return False\n                payload = data[pos + 4:pos + 8 + length]\n                expected = struct.unpack(\"&gt;I\", data[pos + 8 + length:end])[0]\n                if zlib.crc32(payload) &amp; 0xFFFFFFFF != expected:\n                    return False\n                pos = end\n                if ctype == b\"IEND\":\n                    return True\n            return False\n        if file_type == \"pdf\":\n            return data.startswith(b\"%PDF-\") and b\"%%EOF\" in data[-8192:]\n        if file_type == \"zip\":\n            if not data.startswith(b\"PK\\x03\\x04\"):\n                return False\n            import zipfile\n            with zipfile.ZipFile(io.BytesIO(data)) as zf:\n                return zf.testzip() is None\n        if file_type == \"mp4\":\n            return detect_file_boundaries(data, \"mp4\") is not None\n        if file_type == \"exe\":\n            return _estimate_exe_size_from_bytes(data) is not None\n        if file_type == \"gif\":\n            return data.startswith((b\"GIF87a\", b\"GIF89a\")) and data.endswith(b\"\\x3B\")\n        if file_type == \"bmp\":\n            return data.startswith(b\"BM\") and detect_file_boundaries(data, \"bmp\") == len(data)\n        if file_type == \"wav\":\n            return data.startswith(b\"RIFF\") and data[8:12] in (b\"WAVE\", b\"AVI \")\n        if file_type in (\"gz\", \"bz2\", \"xz\", \"7z\", \"rar\", \"flac\", \"ogg\", \"sqlite\", \"ico\", \"psd\", \"cab\", \"ps\", \"flv\", \"mkv\", \"mpg\", \"doc\", \"rtf\"):\n            return len(data) &gt; 16\n    except Exception:\n        return False\n    return len(data) &gt; 0\n\ndef _read_file_candidate(disk_path, offset, file_type, search_limit=None, progress_callback=None):\n    file_type = _normalize_recovery_type(file_type)\n    first = _read_raw_at(disk_path, offset, 16 * 1024 * 1024)\n    boundary = detect_file_boundaries(first, file_type)\n    if boundary:\n        return first[:boundary]\n    if file_type in (\"mp4\", \"exe\", \"bmp\", \"wav\") and boundary is None:\n        return None\n    data = bytearray(first)\n    read_pos = offset + len(first)\n    while True:\n        if search_limit is not None and len(data) &gt;= search_limit:\n            break\n        to_read = 16 * 1024 * 1024\n        if search_limit is not None:\n            to_read = min(to_read, search_limit - len(data))\n            if to_read &lt;= 0:\n                break\n        chunk = _read_raw_at(disk_path, read_pos, to_read)\n        if not chunk:\n            break\n        data.extend(chunk)\n        boundary = detect_file_boundaries(bytes(data[-(len(chunk) + 8192):]), file_type)\n        if boundary:\n            real_end = len(data) - (len(chunk) + 8192) + boundary\n            if real_end &gt; 0:\n                return bytes(data[:real_end])\n        read_pos += len(chunk)\n        _photorec_progress(progress_callback, f\"Boundary search: offset 0x{offset:X}, {len(data)//(1024*1024)} MB read\")\n    return bytes(data) if validate_file(bytes(data), file_type) else None\n\ndef _write_recovered_candidate(recup_dir, offset, file_type, data, counter, source=None):\n    safety = get_recovery_safety()\n    recup_dir = safety.validate_output_dir(recup_dir, source)\n    ext = _normalize_recovery_type(file_type)\n    name = f\"f{counter:07d}_off_{offset:012X}.{ext}\"\n    path = safety.validate_write_path(os.path.join(recup_dir, name), source)\n    with open(path, \"wb\") as out:\n        out.write(data)\n    return path\n\ndef _fragment_reassemble_nearby(disk_path, offset, file_type, block_size, progress_callback=None):\n    # Best-effort fragmented recovery: read a larger nearby window and validate candidate.\n    start = max(0, offset - block_size)\n    data = _read_raw_at(disk_path, start, block_size * 512)\n    rel = offset - start\n    if rel &lt; 0 or rel &gt;= len(data):\n        return None\n    candidate = data[rel:]\n    boundary = detect_file_boundaries(candidate, file_type)\n    if boundary:\n        candidate = candidate[:boundary]\n    if validate_file(candidate, file_type):\n        _photorec_progress(progress_callback, f\"Fragment reassembly OK: offset 0x{offset:X}\")\n        return candidate\n    return None\n\ndef _scan_pass(disk_path, recup_dir, block_size, pass_num, aligned_only, seen_offsets, progress_callback=None):\n    source_size = _disk_source_size(disk_path)\n    chunk_size, pause_s = _scan_chunk_profile(disk_path, block_size)\n    overlap = RAW_SCAN_OVERLAP\n    offset = 0\n    recovered = []\n    counter = len(seen_offsets) + 1\n    previous_tail = b\"\"\n    last_pct = -1\n    last_report_offset = -RAW_SCAN_PROGRESS_STEP\n    while True:\n        chunk = _read_raw_at(disk_path, offset, chunk_size)\n        if not chunk:\n            break\n        scan_buffer = previous_tail + chunk\n        scan_base = offset - len(previous_tail)\n        hits = _detect_photorec_signature(scan_buffer, scan_base, aligned_only=aligned_only, block_size=block_size)\n        for hit_offset, file_type, _sig, _footer in hits:\n            if hit_offset &lt; 0 or hit_offset in seen_offsets:\n                continue\n            seen_offsets.add(hit_offset)\n            try:\n                data = _read_file_candidate(disk_path, hit_offset, file_type, progress_callback=progress_callback)\n                if data is None or not validate_file(data, file_type):\n                    data = _fragment_reassemble_nearby(disk_path, hit_offset, file_type, block_size, progress_callback=progress_callback)\n                if data and validate_file(data, file_type):\n                    path = _write_recovered_candidate(recup_dir, hit_offset, file_type, data, counter, source=disk_path)\n                    counter += 1\n                    recovered.append({\"path\": path, \"offset\": hit_offset, \"file_type\": file_type, \"bytes\": len(data), \"pass\": pass_num})\n                    _photorec_progress(progress_callback, f\"Pass {pass_num}: recovered {os.path.basename(path)}\")\n            except Exception as e:\n                _photorec_progress(progress_callback, f\"Pass {pass_num}: offset 0x{hit_offset:X} skip ({e})\")\n        offset += len(chunk)\n        previous_tail = scan_buffer[-overlap:]\n        if source_size:\n            pct = min(100, int((offset / source_size) * 100))\n            if pct != last_pct:\n                last_pct = pct\n                _photorec_progress(progress_callback, f\"Pass {pass_num}: {pct}% complete\")\n        elif (offset - last_report_offset) &gt;= RAW_SCAN_PROGRESS_STEP:\n            last_report_offset = offset\n            _photorec_progress(progress_callback, f\"Pass {pass_num}: {_human_size(offset)} scanned\")\n        if pause_s:\n            time.sleep(pause_s)\n    return recovered\n\ndef multi_pass_recovery(disk_path, output_dir, block_size=None, progress_callback=None):\n    _require_raw_admin(disk_path)\n    output_dir = get_recovery_safety().validate_output_dir(output_dir, disk_path)\n    block_size = int(block_size or _auto_detect_block_size(disk_path))\n    recup_base = _next_recup_dir(output_dir)\n    seen_offsets = set()\n    all_recovered = []\n    _photorec_progress(progress_callback, f\"Block size auto-detected: {block_size} bytes\")\n    if CUSTOM_SIGNATURE_COUNT:\n        _photorec_progress(progress_callback, f\"Custom signature engine active: {CUSTOM_SIGNATURE_COUNT} extra signatures\")\n    if _is_raw_device_path(disk_path):\n        _photorec_progress(progress_callback, f\"Low-impact mode active: {RAW_SCAN_DEVICE_CHUNK // (1024 * 1024)} MB buffered reads + {RAW_SCAN_DEVICE_PAUSE_MS} ms pause\")\n    _photorec_progress(progress_callback, \"Pass 1: block-aligned carving start\")\n    all_recovered.extend(_scan_pass(disk_path, recup_base, block_size, 1, True, seen_offsets, progress_callback))\n    _photorec_progress(progress_callback, \"Pass 2: unaligned signature carving start\")\n    all_recovered.extend(_scan_pass(disk_path, recup_base, block_size, 2, False, seen_offsets, progress_callback))\n    _photorec_progress(progress_callback, f\"Carving complete: {len(all_recovered)} files (2 passes + validation)\")\n    return {\"recup_dir\": recup_base, \"block_size\": block_size, \"files\": all_recovered}\n\ndef deep_scan_disk(disk_path, output_dir):\n    \"\"\"PhotoRec-style main scanner: raw disk access, auto block size, multi-pass carving.\"\"\"\n    _require_raw_admin(disk_path)\n    return multi_pass_recovery(disk_path, output_dir, block_size=None, progress_callback=print)\n\n# \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n#  CORPORATE PROFESSIONAL COLOR SCHEME - Enterprise-Grade Theme\n#  Modern, clean, professional appearance for business environments\n# \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\nC = {\n    \"bg\":         \"#0A0F1A\",\n    \"panel\":      \"#121826\",\n    \"card\":       \"#182032\",\n    \"border\":     \"#2A3A5A\",\n    \"accent\":     \"#FFB347\",\n    \"accent2\":    \"#4CAF50\",\n    \"accent3\":    \"#F44336\",\n    \"accent4\":    \"#FF9800\",\n    \"text\":       \"#F0F4FA\",\n    \"text_dim\":   \"#A0B0C8\",\n    \"text_dark\":  \"#3A4A6A\",\n    \"btn\":        \"#2E5A9C\",\n    \"btn_hover\":  \"#1E4A8C\",\n    \"btn_danger\": \"#D32F2F\",\n    \"btn_info\":   \"#1976D2\",\n    \"btn_warn\":   \"#FF8C00\",\n    \"btn_hw\":     \"#6A1B9A\",\n    \"btn_chip\":   \"#00838F\",\n    \"header_bg\":  \"#0A0F1A\",\n    \"sidebar\":    \"#0E1422\",\n    \"progress\":   \"#FFB347\",\n    \"success\":    \"#4CAF50\",\n    \"warning\":    \"#FF9800\",\n    \"error\":      \"#F44336\",\n    \"hw_accent\":  \"#CE93D8\",\n}\n\n\n  # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n  #  CORPORATE PROFESSIONAL FONTS - Enterprise-Grade Typography\n  #  Clean, readable, professional font hierarchy\n  # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\nFONTS = {\n    \"title\":    (\"Segoe UI\", 20, \"bold\"),\n    \"heading\":  (\"Segoe UI\", 13, \"bold\"),\n    \"subhead\":  (\"Segoe UI\", 11, \"bold\"),\n    \"body\":     (\"Segoe UI\", 10),\n    \"small\":    (\"Segoe UI\", 9),\n    \"xsmall\":   (\"Segoe UI\", 8),\n    \"mono\":     (\"Consolas\", 9),\n}\n\nSIDEBAR_CATEGORIES = [\n    (\"\ud83d\udee0 SHOP WORKFLOW\", \"accent4\", [\n        (\"shop\", \"\ud83d\udee0\", \"Repair Shop Mode\"),\n    ]),\n    (\"\u26a1 PERFORMANCE\", \"accent\", [\n        (\"cleaner\", \"\ud83e\uddf9\", \"Junk Cleaner\"),\n        (\"memory\", \"\ud83e\udde0\", \"RAM + Services\"),\n        (\"startup\", \"\ud83d\ude80\", \"Startup + Scheduler\"),\n        (\"boost\", \"\u26a1\", \"Power Boost\"),\n    ]),\n    (\"\ud83d\udd27 SYSTEM REPAIR\", \"warning\", [\n        (\"registry\", \"\ud83d\udcdd\", \"Registry + Group Policy\"),\n        (\"network\", \"\ud83c\udf10\", \"Network + Troubleshooter\"),\n        (\"power\", \"\ud83d\udd0b\", \"Power Plan\"),\n        (\"hdd_repair\", \"\ud83d\udcbe\", \"HDD/SSD + File Recovery\"),\n        (\"data_recovery\", \"\ud83d\udd2c\", \"Data Recovery\"),\n        (\"activation\", \"\ud83d\udd11\", \"Windows Activation\"),\n    ]),\n    (\"\ud83d\udee0 RESCUE &amp; RECOVERY\", \"warning\", [\n        (\"rescue_center\", \"\ud83d\udee0\", \"Rescue &amp; Recovery Center\"),\n    ]),\n    (\"\ud83d\udd0d SECURITY &amp; AUDIT\", \"accent3\", [\n        (\"suspicion\", \"\ud83d\udd34\", \"Process Scanner\"),\n        (\"realtime_security\", \"\ud83d\udee1\", \"Realtime Security\"),\n        (\"eventviewer\", \"\ud83d\udccb\", \"Event Viewer\"),\n        (\"log\", \"\ud83d\udcc4\", \"Activity Log\"),\n    ]),\n    (\"\ud83d\uddc2 TOOLS\", \"accent2\", [\n        (\"printer\", \"\ud83d\udda8\", \"Printer + Driver\"),\n        (\"uninstall\", \"\ud83d\uddd1\", \"Uninstall + Backup\"),\n        (\"dupfinder\", \"\ud83d\udd0d\", \"Dup Finder + Report\"),\n    ]),\n    (\"\ud83d\udcc1 OFFICE &amp; FILES\", \"hw_accent\", [\n        (\"office_tools\", \"\ud83d\udcc4\", \"PDF &amp; Doc Tools\"),\n        (\"excel_tools\", \"\ud83d\udcca\", \"Excel Tools\"),\n        (\"image_tools\", \"\ud83d\uddbc\", \"Image Tools\"),\n        (\"file_tools\", \"\ud83d\uddc2\", \"File Manager\"),\n    ]),\n]\n\n\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n#  MAIN APPLICATION\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nSIDEBAR_CATEGORIES.append((\"\ud83d\udd27 ADVANCED TOOLS\", \"accent3\", [\n    (\"partition_manager\",\"\ud83d\udcbd\", \"Partition Manager\"),\n    (\"easy_driver\",      \"\ud83d\udda5\", \"Easy Driver\"),\n    (\"driver_manager\",    \"\ud83d\udda5\",  \"Driver Manager\"),\n    (\"svc_presets\",       \"\u2699\",  \"Services Preset Manager\"),\n    (\"disk_analyzer\",     \"\ud83d\udcca\", \"Disk Space Analyzer\"),\n    (\"bsod_history\",      \"\ud83d\udc80\", \"BSOD History\"),\n    (\"corrupt_wizard\",    \"\ud83d\udd28\", \"Corrupt Windows Wizard\"),\n    (\"password_audit\",    \"\ud83d\udd10\", \"Password &amp; Security Audit\"),\n    (\"auto_backup\",       \"\ud83d\udcbe\", \"Auto Backup\"),\n]))\n\nclass GodawariUltimateOptimizer(tk.Tk):\n    def __init__(self):\n        super().__init__()\n        self.title(\"Godawari Computers Ultimate Optimizer Pro v11.0 | Safety &amp; Recovery Edition\")\n        self.geometry(\"1400x850\")\n        self.minsize(1120, 680)\n        self.configure(bg=C[\"bg\"])\n        self.resizable(True, True)\n\n        self.active_section = tk.StringVar(value=\"dashboard\")\n        self.log_lines = []\n        self.current_theme = \"dark\"\n        self.settings_file = os.path.join(os.environ.get(\"APPDATA\", \"\"), \"GodawariOptimizer\", \"settings.json\")\n        self.reg_vars = {}\n        self.gp_vars = {}\n        self.clean_vars = {}\n        self._restore_prompt_count = 0\n        self.uninst_data = []\n        self._recovery_stop_flag = False\n        self._recovery_pause_flag = False\n        self._clean_job_running = False\n        self._clean_job_cancel_event = threading.Event()\n        self._clean_job_summary = {}\n        self._recovery_active = False\n        self._partition_op_lock = threading.Lock()\n        self._partition_operation_active = False\n        self._partition_operation_session = None\n        self._partition_cancel_event = threading.Event()\n        self._partition_operation_log = []\n        self._partition_operation_start_time = None\n        self._job_lock = threading.Lock()\n        self._jobs = {}\n        self._job_counter = 0\n        self._task_manager = {}\n        self._task_counter = 0\n        self._event_bus = collections.defaultdict(list)\n        self.system_health = {\n            \"disk\": 100,\n            \"ram\": 100,\n            \"startup\": 100,\n            \"security\": 100,\n            \"windows\": 100,\n            \"drivers\": 100,\n            \"network\": 100,\n        }\n        self._health_trend = {key: 100 for key in self.system_health}\n        self._rollback_points = []\n        self._security_alerts = []\n        self._security_watch_running = False\n        self._security_watch_thread = None\n        self._security_baselines = {}\n        self._last_security_snapshot = {}\n        self._enterprise_log_dir = os.path.join(os.environ.get(\"APPDATA\", \"\"), \"GodawariOptimizer\", \"logs\")\n        self._enterprise_log_file = os.path.join(self._enterprise_log_dir, \"enterprise.log\")\n        self._enterprise_error_log = os.path.join(self._enterprise_log_dir, \"errors.log\")\n        self._enterprise_forensic_log = os.path.join(self._enterprise_log_dir, \"forensic.log\")\n        self._ensure_enterprise_logs()\n        self.backup_config_file = os.path.join(os.environ.get(\"APPDATA\",\"\"), \"GodawariOptimizer\", \"backup_config.json\")\n        self.backup_sources = []\n        self.backup_dest_var = tk.StringVar()\n        self.backup_schedule_var = tk.StringVar(value=\"Manual Only\")\n        self.backup_time_var = tk.StringVar(value=\"02:00\")\n        self.backup_overwrite_mode = tk.StringVar(value=\"mirror\")\n        self.backup_keep_n = tk.IntVar(value=3)\n        self.regback_enabled = tk.BooleanVar(value=True)\n        self._corrupt_wizard_step = 0\n        self._corrupt_wizard_running = False\n\n        # \u2500\u2500 Thread-safe UI update queue \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        # Background threads put (msg_type, payload) tuples here.\n        # The main thread drains this queue every ~50 ms via _poll_ui_queue().\n        # This is the ONLY safe way to touch Tkinter widgets from threads.\n        self._ui_queue = _queue_module.Queue()\n        # Specialized metric queues for RAM/Services, Registry/Group Policy and HDD/Recovery menus.\n        self._ram_service_metrics_queue = _queue_module.Queue()\n        self._ram_service_last_dispatch = time.time()\n        self._ram_service_metrics_lock = threading.Lock()\n        self._ram_service_pending_metrics = None\n        self._registry_gp_metrics_queue = _queue_module.Queue()\n        self._registry_gp_last_dispatch = time.time()\n        self._hdd_recovery_metrics_queue = _queue_module.Queue()\n        self._hdd_recovery_last_dispatch = time.monotonic()\n        self._hdd_recovery_pending_metrics = None\n        self._hdd_recovery_metrics_lock = threading.Lock()\n        self._hdd_recovery_job_lock = threading.Lock()\n        # Dedicated printer action queue and metrics throttling for the Printer + Driver menu.\n        self._printer_metrics_queue = _queue_module.Queue()\n        self._printer_metrics_last_dispatch = time.monotonic()\n        self._printer_metrics_pending = None\n        self._printer_metrics_lock = threading.Lock()\n        self._printer_action_buttons = []\n        self._printer_action_lock = threading.Lock()\n        self._printer_action_running = False\n        # Threading Event: set by _stop_file_recovery() so the scan loop\n        # can check it without touching any Tk widget from a background thread.\n        self._scan_stop_event = threading.Event()\n        # \u2500\u2500 PHASE 2: Atomic debounce lock for File Recovery menu \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        self._recovery_is_processing = False          # atomic boolean guard\n        self._rec_integrity_lock     = threading.Lock()\n        self._rec_timeline_lock      = threading.Lock()\n        self._rec_integrity_queue    = _queue_module.Queue()\n        self._rec_timeline_queue     = _queue_module.Queue()\n        self._rec_integrity_last_dispatch  = time.monotonic()\n        self._rec_timeline_last_dispatch   = time.monotonic()\n\n        try:\n            os.makedirs(os.path.dirname(self.settings_file), exist_ok=True)\n        except:\n            pass\n        self._init_backend_reliability()\n        self.worker_manager = TkWorkerManager(self, workers=3, logger=getattr(self, \"structured_logger\", None))\n        self.recovery_manager = RecoveryManager(workers=3, callback=self._on_recovery_task_update, logger=getattr(self, \"structured_logger\", None))\n        self.recovery_results = RecoveryResultStore()\n        self._recovery_progress_panels = {}\n        self._recovery_live_stats = {}\n\n        self._build_style()\n        self._build_header()\n        self._build_body()\n        self._build_statusbar()\n        self._build_footer()\n        self._load_settings()\n        self._show_section(\"dashboard\")\n        # Startup fast karo: dashboard refresh aur graph deferred\n        self.after(800, self._refresh_dashboard)\n        self.after(1500, self._start_real_time_graph)\n\n        # Start the UI queue poller \u2014 drains _ui_queue on the main thread\n        self._poll_ui_queue()\n        self._poll_ram_service_metrics()\n        self._poll_registry_gp_metrics()\n        self._poll_hdd_recovery_metrics()\n        self._poll_printer_metrics()\n        self._tick_printer_action_timer()\n\n        if not is_admin():\n            self._set_status(\"\u26a0\ufe0f Admin rights required! Some features may not work.\", C[\"warning\"])\n            self._log(\"Not running as Administrator. Right-click -&gt; Run as Administrator.\", \"WARN\")\n\n        self.after(1200, self._check_crash_recovery_startup)\n        self.after(1600, self._prompt_admin_elevation)\n        self.protocol(\"WM_DELETE_WINDOW\", self._on_app_close)\n\n    def _on_app_close(self):\n        try:\n            if hasattr(self, \"crash_recovery\"):\n                self.crash_recovery.clear_running()\n        except Exception:\n            pass\n        self.destroy()\n\n    def _check_crash_recovery_startup(self):\n        try:\n            orphans = self.crash_recovery.orphaned_sessions()\n            if not orphans:\n                return\n            lines = []\n            for s in orphans[:5]:\n                lines.append(\n                    f\"\u2022 {s.get('kind', 'job')} \u2014 started {s.get('started', '?')}\"\n                )\n            self._log(\n                \"Crash recovery detected unfinished sessions on startup. \"\n                + \"Review in Safety Center if needed. \"\n                + \" | \".join(lines),\n                \"WARN\",\n            )\n        except Exception:\n            pass\n\n    def _prompt_admin_elevation(self):\n        try:\n            if is_admin() or not _admin_elevation_enabled():\n                return\n            if messagebox.askyesno(\n                \"Administrator Required\",\n                \"Some recovery and repair features require elevated privileges. Relaunch elevated now?\",\n            ):\n                run_as_admin()\n        except Exception:\n            pass\n\n    def _init_backend_reliability(self):\n        if _GODAWARI_BACKEND:\n            try:\n                self._backend = create_backend()\n                base_dir = self._backend.config.get(\"app\", default={})  # noqa \u2014 paths via package\n                from godawari import paths as _paths\n                self.audit_dir = _paths.audit_dir()\n                self.backup_dir = _paths.backup_dir()\n                self.rollback_dir = _paths.rollback_dir()\n                self.recovery_sessions_dir = _paths.sessions_dir()\n                self.crash_marker_file = _paths.crash_marker_path()\n                self.audit_file = _paths.legacy_audit_path()\n                self.structured_log_file = _paths.structured_log_path()\n                self.structured_logger = self._backend.logger\n                self.event_bus = self._backend.event_bus\n                self.telemetry_store = self._backend.telemetry_store\n                self.job_manager = self._backend.job_manager\n                self.change_coordinator = self._backend.change_coordinator\n                self.policy_engine = self._backend.policy_engine\n                self.system_adapters = self._backend.system_adapters\n                self.restore_point_manager = self._backend.restore_points\n                self.rollback_vault = self._backend.rollback_vault\n                self.recovery_session_manager = self._backend.recovery_sessions\n                self.health_engine = self._backend.health_engine\n                self.menu_introspection_engine = self._backend.menu_introspection\n                self.product_audit_engine = self._backend.product_audit\n                self.recommendation_engine = self._backend.recommendations\n                self.maintenance_profile_engine = self._backend.maintenance_profiles\n                self.preflight_engine = self._backend.preflight\n                self.secure_powershell = self._backend.secure_powershell\n                self.crash_recovery = self._backend.crash_recovery\n                self.task_queue_manager = self._backend.task_queue\n                self.audit_store = self._backend.audit_store\n                self.app_config = self._backend.config\n                self.crash_recovery.mark_running()\n                self._last_health_report = None\n                return\n            except Exception:\n                pass\n        base_dir = os.path.join(os.environ.get(\"APPDATA\", \"\"), \"GodawariOptimizer\")\n        self.audit_dir = os.path.join(base_dir, \"audit\")\n        self.backup_dir = os.path.join(base_dir, \"backups\")\n        self.rollback_dir = os.path.join(base_dir, \"rollback_vault\")\n        self.recovery_sessions_dir = os.path.join(base_dir, \"recovery_sessions\")\n        self.crash_marker_file = os.path.join(base_dir, \"runtime.marker\")\n        try:\n            os.makedirs(self.audit_dir, exist_ok=True)\n            os.makedirs(self.backup_dir, exist_ok=True)\n            os.makedirs(self.rollback_dir, exist_ok=True)\n            os.makedirs(self.recovery_sessions_dir, exist_ok=True)\n            self.audit_file = os.path.join(self.audit_dir, \"actions.jsonl\")\n            self.structured_log_file = os.path.join(self.audit_dir, \"structured_runtime.jsonl\")\n        except Exception:\n            self.audit_file = \"\"\n            self.structured_log_file = \"\"\n        # Initialize structured logger and backend helpers\n        try:\n            from godawari.services.logger import StructuredLogger as _StructuredLogger\n            from godawari.jobs.manager import JobManager as _JobManager\n            from godawari.events.bus import EventBus as _EventBus\n            from godawari.telemetry.store import TelemetryStore as _TelemetryStore\n            from godawari.change_coordinator import ChangeCoordinator as _ChangeCoordinator\n            from godawari.policies.engine import PolicyEngine as _PolicyEngine\n            from godawari.system.adapters import RegistryAdapter, ServiceAdapter, DiskAdapter\n        except Exception:\n            _StructuredLogger = globals().get(\"StructuredLogger\")\n            _JobManager = None\n            _EventBus = None\n            _TelemetryStore = None\n            _ChangeCoordinator = None\n            _PolicyEngine = None\n            RegistryAdapter = ServiceAdapter = DiskAdapter = None\n\n        self.event_bus = _EventBus.get_instance() if _EventBus else None\n        self.telemetry_store = _TelemetryStore(db_path=_paths.database_path()) if _TelemetryStore else None\n        self.structured_logger = _StructuredLogger(getattr(self, \"structured_log_file\", \"\"))\n        self.restore_point_manager = RestorePointManager(\n            base_dir,\n            self.structured_logger,\n            event_bus=self.event_bus,\n            telemetry=self.telemetry_store,\n        )\n        self.rollback_vault = OperationRollbackVault(\n            self.rollback_dir,\n            self.structured_logger,\n            event_bus=self.event_bus,\n            telemetry=self.telemetry_store,\n        )\n        self.recovery_session_manager = RecoverySessionManager(\n            self.recovery_sessions_dir, self.structured_logger\n        )\n        # EventBus and JobManager\n        try:\n            self.job_manager = _JobManager(db_path=_paths.database_path(), workers=3, logger=self.structured_logger, event_bus=self.event_bus, telemetry=self.telemetry_store) if _JobManager else None\n            self.change_coordinator = _ChangeCoordinator(self.restore_point_manager, self.rollback_vault, logger=self.structured_logger, job_manager=self.job_manager, event_bus=self.event_bus, telemetry_store=self.telemetry_store) if _ChangeCoordinator else None\n            self.policy_engine = _PolicyEngine(logger=self.structured_logger) if _PolicyEngine else None\n            self.system_adapters = {\n                \"registry\": RegistryAdapter() if RegistryAdapter else None,\n                \"service\": ServiceAdapter() if ServiceAdapter else None,\n                \"disk\": DiskAdapter() if DiskAdapter else None,\n            }\n        except Exception:\n            self.job_manager = None\n            self.change_coordinator = None\n            self.policy_engine = None\n            self.system_adapters = {}\n        self.health_engine = SystemHealthEngine()\n        self.menu_introspection_engine = MenuIntrospectionEngine()\n        self.product_audit_engine = ProductAuditEngine()\n        self.recommendation_engine = RecommendationEngine()\n        self.maintenance_profile_engine = MaintenanceProfileEngine()\n        self.preflight_engine = OperationPreflightEngine()\n        self.secure_powershell = SecurePowerShellEngine(self.structured_logger)\n        self.crash_recovery = CrashRecoveryCoordinator(\n            self.recovery_session_manager, self.crash_marker_file)\n        self.crash_recovery.mark_running()\n        self._last_health_report = None\n\n    def _ensure_enterprise_logs(self):\n        try:\n            os.makedirs(self._enterprise_log_dir, exist_ok=True)\n            for path in (self._enterprise_log_file, self._enterprise_error_log, self._enterprise_forensic_log):\n                if not os.path.exists(path):\n                    with open(path, \"a\", encoding=\"utf-8\"):\n                        pass\n        except Exception:\n            pass\n\n    def _write_enterprise_log(self, path, message, level=\"INFO\"):\n        try:\n            os.makedirs(self._enterprise_log_dir, exist_ok=True)\n            if os.path.exists(path) and os.path.getsize(path) &gt; (1024 * 1024):\n                suffix = datetime.datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n                rotated = f\"{path}.{suffix}\"\n                try:\n                    os.replace(path, rotated)\n                except Exception:\n                    pass\n            timestamp = datetime.datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\")\n            with open(path, \"a\", encoding=\"utf-8\") as handle:\n                handle.write(f\"[{timestamp}] [{level}] {message}\\n\")\n        except Exception:\n            pass\n\n    def _log_module(self, module, message, level=\"INFO\"):\n        try:\n            module_path = os.path.join(self._enterprise_log_dir, f\"{module}.log\")\n            self._write_enterprise_log(module_path, message, level)\n        except Exception:\n            pass\n\n    def _register_event(self, event_name, callback):\n        try:\n            self._event_bus.setdefault(str(event_name), []).append(callback)\n            return True\n        except Exception:\n            return False\n\n    def _emit_event(self, event_name, data=None):\n        try:\n            for callback in list(self._event_bus.get(str(event_name), [])):\n                try:\n                    callback(data)\n                except Exception:\n                    pass\n            if getattr(self, \"event_bus\", None) is not None:\n                try:\n                    self.event_bus.emit(str(event_name), data)\n                except Exception:\n                    pass\n            return True\n        except Exception:\n            return False\n\n    def _set_health_score(self, key, value, note=\"\"):\n        try:\n            previous = self.system_health.get(key, 100)\n            self._health_trend[key] = previous\n            self.system_health[key] = max(0, min(100, int(value)))\n            if note:\n                self._log_module(\"health\", f\"{key}: {self.system_health[key]} ({note})\", \"INFO\")\n        except Exception:\n            pass\n\n    def _calculate_global_health(self):\n        try:\n            scores = [max(0, min(100, int(v))) for v in self.system_health.values()]\n            global_score = int(sum(scores) / len(scores)) if scores else 100\n            if global_score &gt;= 85:\n                grade, color = \"Excellent\", C[\"success\"]\n            elif global_score &gt;= 70:\n                grade, color = \"Good\", C[\"accent4\"]\n            elif global_score &gt;= 50:\n                grade, color = \"Fair\", C[\"warning\"]\n            else:\n                grade, color = \"Critical\", C[\"error\"]\n            trend = {key: f\"{('\u25b2' if self.system_health[key] &gt;= self._health_trend.get(key, self.system_health[key]) else '\u25bc')} {abs(self.system_health[key] - self._health_trend.get(key, self.system_health[key]))}\" for key in self.system_health}\n            return {\n                \"score\": global_score,\n                \"grade\": grade,\n                \"color\": color,\n                \"per_category\": dict(self.system_health),\n                \"trend\": trend,\n            }\n        except Exception:\n            return {\"score\": 100, \"grade\": \"Excellent\", \"color\": C[\"success\"], \"per_category\": dict(self.system_health), \"trend\": {}}\n\n    def _refresh_health_snapshot(self):\n        try:\n            vm = psutil.virtual_memory()\n            du = psutil.disk_usage(\"C:\")\n            proc_count = len(list(psutil.process_iter(['pid'])))\n            startup_path = os.path.join(os.environ.get(\"APPDATA\", \"\"), \"Microsoft\", \"Windows\", \"Start Menu\", \"Programs\", \"Startup\")\n            startup_items = len([name for name in os.listdir(startup_path) if os.path.isfile(os.path.join(startup_path, name))]) if os.path.isdir(startup_path) else 0\n            self._set_health_score(\"ram\", max(0, 100 - int(vm.percent)), \"RAM usage\")\n            self._set_health_score(\"disk\", max(0, 100 - int(du.percent)), \"Disk usage\")\n            self._set_health_score(\"startup\", max(20, 100 - min(80, startup_items * 2)), \"Startup items\")\n            self._set_health_score(\"network\", 100 if self._last_security_snapshot.get(\"network\", {}).get(\"status\") == \"healthy\" else 70)\n            driver_cmd = 'powershell -NoProfile -Command \"Get-WmiObject Win32_PnPSignedDriver | Select-Object -ExpandProperty DeviceName\"'\n            out, rc = self._run_cmd(driver_cmd, timeout=20)\n            if rc == 0:\n                driver_count = len([line for line in out.splitlines() if line.strip()])\n                self._set_health_score(\"drivers\", max(40, 100 - min(60, driver_count // 20)), \"Driver inventory\")\n            security_status = self._last_security_snapshot.get(\"defender\", {})\n            sec_score = 100\n            if not security_status.get(\"enabled\", False):\n                sec_score = 0\n            if not security_status.get(\"realtime\", True):\n                sec_score = max(0, sec_score - 20)\n            self._set_health_score(\"security\", sec_score, \"Defender status\")\n            windows_score = 100\n            health_report = getattr(self, \"_last_health_report\", None)\n            if health_report and isinstance(health_report, dict):\n                windows_score = int(health_report.get(\"score\", 100))\n            self._set_health_score(\"windows\", windows_score, \"Windows health\")\n            self._last_security_snapshot[\"process_count\"] = proc_count\n            self._last_security_snapshot[\"disk_percent\"] = int(du.percent)\n            self._last_security_snapshot[\"ram_percent\"] = int(vm.percent)\n            return self._calculate_global_health()\n        except Exception:\n            return self._calculate_global_health()\n\n    def _task_start(self, title, progress=0, metadata=None):\n        try:\n            self._task_counter += 1\n            task_id = f\"task-{self._task_counter}\"\n            self._task_manager[task_id] = {\n                \"id\": task_id,\n                \"title\": str(title),\n                \"status\": \"running\",\n                \"progress\": max(0, min(100, int(progress))),\n                \"metadata\": metadata or {},\n                \"cancel_requested\": False,\n                \"pause_requested\": False,\n                \"cancel_event\": threading.Event(),\n                \"pause_event\": threading.Event(),\n                \"started_at\": datetime.datetime.now().isoformat(timespec=\"seconds\"),\n            }\n            self._task_manager[task_id][\"pause_event\"].set()\n            self._log_module(\"tasks\", f\"Started {task_id}: {title}\", \"INFO\")\n            if hasattr(self, \"task_center_tree\"):\n                self.after(0, self._refresh_task_center)\n            return task_id\n        except Exception:\n            return \"task-0\"\n\n    def _task_status(self, task_id):\n        return dict(self._task_manager.get(str(task_id), {})) if str(task_id) in self._task_manager else {}\n\n    def _task_update_progress(self, task_id, progress, status=None):\n        try:\n            record = self._task_manager.get(str(task_id))\n            if record is None:\n                return False\n            record[\"progress\"] = max(0, min(100, int(progress)))\n            if status:\n                record[\"status\"] = str(status)\n            if hasattr(self, \"task_center_tree\"):\n                self.after(0, self._refresh_task_center)\n            return True\n        except Exception:\n            return False\n\n    def _task_cancel(self, task_id):\n        try:\n            record = self._task_manager.get(str(task_id))\n            if record is None:\n                return False\n            record[\"cancel_requested\"] = True\n            record[\"status\"] = \"cancelled\"\n            if record.get(\"cancel_event\") is not None:\n                record[\"cancel_event\"].set()\n            self._log_module(\"tasks\", f\"Cancelled {task_id}\", \"WARNING\")\n            if hasattr(self, \"task_center_tree\"):\n                self.after(0, self._refresh_task_center)\n            return True\n        except Exception:\n            return False\n\n    def _task_pause(self, task_id):\n        try:\n            record = self._task_manager.get(str(task_id))\n            if record is None:\n                return False\n            record[\"pause_requested\"] = True\n            record[\"status\"] = \"paused\"\n            if record.get(\"pause_event\") is not None:\n                record[\"pause_event\"].clear()\n            if hasattr(self, \"task_center_tree\"):\n                self.after(0, self._refresh_task_center)\n            return True\n        except Exception:\n            return False\n\n    def _task_resume(self, task_id):\n        try:\n            record = self._task_manager.get(str(task_id))\n            if record is None:\n                return False\n            record[\"pause_requested\"] = False\n            record[\"status\"] = \"running\"\n            if record.get(\"pause_event\") is not None:\n                record[\"pause_event\"].set()\n            if hasattr(self, \"task_center_tree\"):\n                self.after(0, self._refresh_task_center)\n            return True\n        except Exception:\n            return False\n\n    def _task_wait_if_paused(self, task_id, timeout=0.1):\n        record = self._task_manager.get(str(task_id))\n        if not record:\n            return\n        pause_event = record.get(\"pause_event\")\n        cancel_event = record.get(\"cancel_event\")\n        if pause_event is None:\n            return\n        while not pause_event.wait(timeout=timeout):\n            if cancel_event is not None and cancel_event.is_set():\n                raise RuntimeError(\"Task cancelled\")\n\n    def _task_is_cancelled(self, task_id):\n        record = self._task_manager.get(str(task_id))\n        return bool(record and record.get(\"cancel_requested\"))\n\n    def _refresh_task_center(self):\n        tree = getattr(self, \"task_center_tree\", None)\n        if tree is None:\n            return\n        for iid in tree.get_children():\n            tree.delete(iid)\n        for record in sorted(self._task_manager.values(), key=lambda item: item.get(\"started_at\", \"\"), reverse=True):\n            status = record.get(\"status\", \"running\")\n            tag = \"running\" if status == \"running\" else \"cancelled\"\n            tree.insert(\n                \"\",\n                \"end\",\n                values=(record.get(\"id\", \"\"), record.get(\"title\", \"\"), status, f\"{record.get('progress', 0)}%\"),\n                tags=(tag,),\n            )\n        try:\n            tree.tag_configure(\"running\", foreground=C[\"success\"])\n            tree.tag_configure(\"cancelled\", foreground=C[\"warning\"])\n        except Exception:\n            pass\n\n    def _record_rollback_point(self, action, details=None, snapshot_path=None):\n        try:\n            point = {\n                \"action\": str(action),\n                \"details\": details or {},\n                \"snapshot_path\": snapshot_path or \"\", \n                \"timestamp\": datetime.datetime.now().isoformat(timespec=\"seconds\"),\n            }\n            self._rollback_points.append(point)\n            self._log_module(\"rollback\", f\"Rollback point captured: {action}\", \"INFO\")\n            return point\n        except Exception:\n            return None\n\n    def _restore_last_rollback(self):\n        try:\n            if not self._rollback_points:\n                return False, \"No rollback points available\"\n            point = self._rollback_points[-1]\n            snapshot = point.get(\"snapshot_path\")\n            details = point.get(\"details\") or {}\n            if snapshot and os.path.exists(snapshot) and os.path.isdir(snapshot):\n                if point.get(\"action\") == \"partition_merge\":\n                    target_letter = details.get(\"source_letter\")\n                    if target_letter and os.path.isdir(f\"{target_letter}:\\\\\"):\n                        copy_cmd = [\"robocopy\", snapshot, f\"{target_letter}:\\\\\", \"/MIR\", \"/R:2\", \"/W:2\", \"/NFL\"]\n                        result = safe_run(copy_cmd, timeout=7200)\n                        if result.returncode &lt; 8:\n                            return True, f\"Rollback restored backup to {target_letter}:\"\n                        return False, f\"Rollback failed during restore copy (rc={result.returncode})\"\n                return True, f\"Rollback point available for {point.get('action')} \u2014 backup exists at {snapshot}\"\n            return True, f\"Rollback point prepared for {point.get('action')}\"\n        except Exception:\n            return False, \"Rollback restore failed\"\n\n    # \u2500\u2500 UI Queue Poller \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _poll_ui_queue(self):\n        \"\"\"\n        Main-thread poller: drains _ui_queue every 50 ms.\n\n        Background threads NEVER touch Tkinter widgets directly.\n        They put (msg_type, payload) into self._ui_queue and this method\n        applies all pending updates in one go, keeping the GUI responsive.\n\n        Supported message types\n        \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        (\"progress_label\",  str)           \u2013 raw_progress_label text\n        (\"log_line\",        str)           \u2013 append line to raw_progress_log\n        (\"progress_pct\",   float)         \u2013 set raw_progress_var (0-100)\n        (\"status\",         (str, color))  \u2013 bottom status bar\n        (\"tree_row\",       (row, entry))  \u2013 insert row into rec_tree\n        (\"scan_mode\",      (str, color))  \u2013 scan_mode_label update\n        (\"rec_stats\",      None)          \u2013 refresh rec_stats_label\n        (\"finish_op\",      None)          \u2013 call _finish_recovery_operation\n        (\"progress_bar_mode\", str)        \u2013 \"indeterminate\" or \"determinate\"\n        (\"progress_bar_start\", int)       \u2013 start indeterminate animation\n        (\"progress_bar_stop\",  None)      \u2013 stop animation\n        \"\"\"\n        try:\n            processed = 0\n            while not self._ui_queue.empty() and processed &lt; 100:\n                msg_type, payload = self._ui_queue.get_nowait()\n                processed += 1\n\n                if msg_type == \"progress_label\":\n                    if hasattr(self, \"raw_progress_label\"):\n                        self.raw_progress_label.config(text=str(payload)[:200])\n\n                elif msg_type == \"log_line\":\n                    if hasattr(self, \"raw_progress_log\"):\n                        try:\n                            self.raw_progress_log.config(state=\"normal\")\n                            self.raw_progress_log.insert(\"end\", self._fix_text(str(payload)) + \"\\n\")\n                            # Keep log from growing unbounded\n                            lines = float(self.raw_progress_log.index(\"end-1c\").split(\".\")[0])\n                            if lines &gt; 300:\n                                self.raw_progress_log.delete(\"1.0\", \"100.0\")\n                            self.raw_progress_log.see(\"end\")\n                            self.raw_progress_log.config(state=\"disabled\")\n                        except Exception:\n                            pass\n\n                elif msg_type == \"progress_pct\":\n                    if hasattr(self, \"raw_progress_var\") and hasattr(self, \"raw_progress_bar\"):\n                        try:\n                            self.raw_progress_bar.stop()\n                        except Exception:\n                            pass\n                        self.raw_progress_bar.config(mode=\"determinate\")\n                        self.raw_progress_var.set(max(0.0, min(100.0, float(payload))))\n\n                elif msg_type == \"status\":\n                    msg, color = payload\n                    self._set_status(msg, color)\n\n                elif msg_type == \"tree_row\":\n                    row, entry = payload\n                    if hasattr(self, \"rec_tree\"):\n                        try:\n                            iid = self.rec_tree.insert(\"\", \"end\", values=row, tags=(\"found\",))\n                            if not hasattr(self, \"rec_found_files\") or not isinstance(self.rec_found_files, dict):\n                                self.rec_found_files = {}\n                            self.rec_found_files[iid] = entry\n                        except Exception:\n                            pass\n\n                elif msg_type == \"scan_mode\":\n                    text, color = payload\n                    if hasattr(self, \"scan_mode_label\"):\n                        self.scan_mode_label.config(text=text, fg=color or C[\"accent4\"])\n\n                elif msg_type == \"rec_stats\":\n                    self._on_rec_select()\n\n                elif msg_type == \"recovery_queue\":\n                    self._refresh_recovery_queue_tree()\n\n                elif msg_type == \"recovery_refresh\":\n                    self._refresh_recovery_tree(getattr(self, \"quick_recovery_tree\", None), category=\"Quick Recovery\")\n                    self._refresh_recovery_tree(getattr(self, \"deep_recovery_tree\", None), category=\"Deep Recovery\")\n\n                elif msg_type == \"photorec_tree_row\":\n                    if hasattr(self, \"photorec_tree\"):\n                        try:\n                            self.photorec_tree.insert(\"\", \"end\", values=payload)\n                        except Exception:\n                            pass\n\n                elif msg_type == \"mft_tree_row\":\n                    if hasattr(self, \"mft_tree\"):\n                        try:\n                            self.mft_tree.insert(\"\", \"end\", values=payload)\n                        except Exception:\n                            pass\n\n                elif msg_type == \"recovery_log\":\n                    self._append_recovery_log(str(payload))\n\n                elif msg_type == \"recovery_scan_stats\":\n                    self._apply_recovery_scan_stats(payload)\n\n                elif msg_type == \"clone_progress\":\n                    # payload: (pct:int, text:str, mode:str)\n                    try:\n                        if isinstance(payload, (list, tuple)) and len(payload) &gt;= 3:\n                            pct, text, mode = payload[0], payload[1], payload[2]\n                        elif isinstance(payload, (list, tuple)) and len(payload) &gt;= 2:\n                            pct, text, mode = payload[0], payload[1], \"clone\"\n                        else:\n                            pct, text, mode = int(payload), None, \"clone\"\n                    except Exception:\n                        try:\n                            pct = int(payload)\n                        except Exception:\n                            pct = 0\n                        text = None\n                        mode = \"clone\"\n                    if mode == \"partition\":\n                        if hasattr(self, \"partition_progress_bar\"):\n                            try:\n                                if pct is not None and float(pct) &gt; 0:\n                                    self.partition_progress_bar.stop()\n                                    self.partition_progress_bar.config(mode=\"determinate\")\n                                elif text is not None:\n                                    self.partition_progress_bar.config(mode=\"indeterminate\")\n                                    self.partition_progress_bar.start(10)\n                            except Exception:\n                                pass\n                        if hasattr(self, \"partition_progress_var\"):\n                            try:\n                                self.partition_progress_var.set(max(0.0, min(100.0, float(pct))))\n                            except Exception:\n                                pass\n                        if hasattr(self, \"partition_status_label\") and text is not None:\n                            try:\n                                self.partition_status_label.config(text=str(text)[:200])\n                            except Exception:\n                                pass\n                    else:\n                        if hasattr(self, \"clone_progress_bar\"):\n                            try:\n                                if pct is not None and float(pct) &gt; 0:\n                                    self.clone_progress_bar.stop()\n                                    self.clone_progress_bar.config(mode=\"determinate\")\n                                elif text is not None:\n                                    self.clone_progress_bar.config(mode=\"indeterminate\")\n                                    self.clone_progress_bar.start(10)\n                            except Exception:\n                                pass\n                        if hasattr(self, \"clone_progress_var\"):\n                            try:\n                                self.clone_progress_var.set(max(0.0, min(100.0, float(pct))))\n                            except Exception:\n                                pass\n                        if hasattr(self, \"clone_status_label\") and text is not None:\n                            try:\n                                self.clone_status_label.config(text=str(text)[:200])\n                            except Exception:\n                                pass\n\n                elif msg_type == \"finish_op\":\n                    self._finish_recovery_operation()\n                    self._on_rec_select()\n\n                elif msg_type == \"progress_bar_mode\":\n                    if hasattr(self, \"raw_progress_bar\"):\n                        try:\n                            self.raw_progress_bar.stop()\n                        except Exception:\n                            pass\n                        self.raw_progress_bar.config(mode=str(payload))\n\n                elif msg_type == \"progress_bar_start\":\n                    if hasattr(self, \"raw_progress_bar\"):\n                        try:\n                            self.raw_progress_bar.stop()\n                        except Exception:\n                            pass\n                        self.raw_progress_bar.config(mode=\"indeterminate\")\n                        self.raw_progress_bar.start(int(payload))\n\n                elif msg_type == \"progress_bar_stop\":\n                    if hasattr(self, \"raw_progress_bar\"):\n                        try:\n                            self.raw_progress_bar.stop()\n                        except Exception:\n                            pass\n                        self.raw_progress_bar.config(mode=\"determinate\")\n\n        except _queue_module.Empty:\n            pass\n        except Exception:\n            pass\n        finally:\n            # Re-schedule \u2014 always keep polling while the app is alive\n            self.after(50, self._poll_ui_queue)\n\n    def _poll_ram_service_metrics(self):\n        latest = None\n        try:\n            while not self._ram_service_metrics_queue.empty():\n                latest = self._ram_service_metrics_queue.get_nowait()\n        except Exception:\n            latest = None\n        if latest is not None:\n            try:\n                self._update_ram_service_metrics_ui(latest)\n            except Exception:\n                pass\n        self.after(35, self._poll_ram_service_metrics)\n\n    def _poll_hdd_recovery_metrics(self):\n        latest = None\n        try:\n            while not self._hdd_recovery_metrics_queue.empty():\n                latest = self._hdd_recovery_metrics_queue.get_nowait()\n        except Exception:\n            latest = None\n        if latest is not None:\n            try:\n                self._update_hdd_recovery_metrics_ui(latest)\n            except Exception:\n                pass\n        self._hdd_recovery_flush_pending_metrics()\n        self.after(30, self._poll_hdd_recovery_metrics)\n\n    def _hdd_recovery_flush_pending_metrics(self):\n        try:\n            with self._hdd_recovery_metrics_lock:\n                if self._hdd_recovery_pending_metrics is None:\n                    return\n                now = time.monotonic()\n                if now - self._hdd_recovery_last_dispatch &gt;= 0.120:\n                    self._hdd_recovery_last_dispatch = now\n                    self._hdd_recovery_metrics_queue.put(self._hdd_recovery_pending_metrics.copy())\n                    self._hdd_recovery_pending_metrics = None\n        except Exception:\n            pass\n\n    def _update_hdd_recovery_metrics_ui(self, data):\n        try:\n            if hasattr(self, \"raw_progress_var\") and data.get(\"progress_pct\") is not None:\n                self.raw_progress_var.set(max(0.0, min(100.0, float(data[\"progress_pct\"]))))\n            if hasattr(self, \"raw_progress_label\") and data.get(\"status_text\") is not None:\n                self.raw_progress_label.config(text=self._fix_text(str(data[\"status_text\"])))\n            if hasattr(self, \"scan_mode_label\") and data.get(\"scan_mode\") is not None:\n                self.scan_mode_label.config(text=self._fix_text(str(data[\"scan_mode\"])))\n            if hasattr(self, \"rec_stats_label\") and data.get(\"files_found\") is not None:\n                total = int(data.get(\"files_found\", 0))\n                selected = len(self.rec_tree.selection()) if hasattr(self, \"rec_tree\") else 0\n                self.rec_stats_label.config(text=f\"{total} files found | {selected} selected\")\n            if hasattr(self, \"hdd_resource_delta_lbl\") and data.get(\"delta_mb\") is not None:\n                before_mb = int(data.get(\"resource_before_mb\", 0))\n                after_mb = int(data.get(\"resource_after_mb\", 0))\n                delta_mb = int(data.get(\"delta_mb\", 0))\n                self.hdd_resource_delta_lbl.config(\n                    text=f\"Memory Delta: {self._fmt_size(delta_mb)} ({before_mb} MB \u2192 {after_mb} MB)\")\n            if hasattr(self, \"hdd_service_status_lbl\") and data.get(\"service_control\") is not None:\n                self.hdd_service_status_lbl.config(text=self._fix_text(str(data.get(\"service_control\"))))\n            if hasattr(self, \"ram_execution_log\") and data.get(\"log_line\") is not None:\n                self._append_log(self.ram_execution_log, str(data[\"log_line\"]), C[\"text\"])\n        except Exception:\n            pass\n\n    def _hdd_recovery_emit_metrics(self, batch):\n        try:\n            if not isinstance(batch, dict):\n                batch = {\"status_text\": str(batch)}\n            batch = {**batch, \"ts\": datetime.datetime.now().isoformat(timespec=\"milliseconds\")}\n            now = time.monotonic()\n            with self._hdd_recovery_metrics_lock:\n                self._hdd_recovery_pending_metrics = batch.copy()\n                if now - self._hdd_recovery_last_dispatch &gt;= 0.120:\n                    self._hdd_recovery_last_dispatch = now\n                    self._hdd_recovery_metrics_queue.put(batch.copy())\n                    self._hdd_recovery_pending_metrics = None\n        except Exception:\n            pass\n\n    def _ram_service_emit_metrics(self, batch, force=False):\n        try:\n            if not isinstance(batch, dict):\n                batch = {\"status_text\": str(batch)}\n            batch = {**batch, \"ts\": datetime.datetime.now().isoformat(timespec=\"milliseconds\")}\n            now = time.monotonic()\n            with self._ram_service_metrics_lock:\n                self._ram_service_pending_metrics = batch.copy()\n                if force or now - self._ram_service_last_dispatch &gt;= 0.120:\n                    self._ram_service_last_dispatch = now\n                    self._ram_service_metrics_queue.put(batch.copy())\n                    self._ram_service_pending_metrics = None\n        except Exception:\n            pass\n\n    def _snapshot_resource_state(self):\n        try:\n            vm = psutil.virtual_memory()\n            return {\n                \"available_mb\": int(vm.available / 1024**2),\n                \"used_mb\": int((vm.total - vm.available) / 1024**2),\n                \"total_mb\": int(vm.total / 1024**2),\n                \"percent\": round(vm.percent, 2),\n            }\n        except Exception:\n            return None\n\n    def _reclaim_memory(self):\n        try:\n            gc.collect()\n        except Exception:\n            pass\n        try:\n            kernel32 = ctypes.windll.kernel32\n            psapi = ctypes.windll.psapi\n            handle = kernel32.GetCurrentProcess()\n            psapi.EmptyWorkingSet(handle)\n        except Exception:\n            pass\n\n    def _submit_ram_service_job(self, name, target, *args, **kwargs):\n        jm = getattr(self, \"job_manager\", None)\n        if jm is not None and hasattr(jm, \"submit_callable\"):\n            try:\n                jm.submit_callable(name, target, *args, **kwargs)\n                return True\n            except Exception:\n                pass\n        manager = getattr(self, \"worker_manager\", None)\n        if manager is not None and hasattr(manager, \"submit\"):\n            try:\n                manager.submit(name, target, *args, **kwargs)\n                return True\n            except Exception:\n                pass\n        try:\n            threading.Thread(target=target, args=args, kwargs=kwargs, daemon=True).start()\n            return True\n        except Exception:\n            return False\n\n    def _ram_service_action_submit(self, name, target, button=None, *args, **kwargs):\n        if not hasattr(self, \"_ram_service_action_lock\"):\n            self._ram_service_action_lock = threading.Lock()\n            self._ram_service_action_running = False\n        with self._ram_service_action_lock:\n            if getattr(self, \"_ram_service_action_running\", False):\n                if hasattr(self, \"ram_log\"):\n                    self._append_log(self.ram_log, \"\u26a0\ufe0f RAM/Service action already running \u2014 duplicate request skipped\", C[\"warning\"])\n                return False\n            self._ram_service_action_running = True\n            if button is not None:\n                try:\n                    button.config(state=\"disabled\")\n                except Exception:\n                    pass\n\n        def _wrapped(*args, **kwargs):\n            try:\n                return target(*args, **kwargs)\n            finally:\n                with self._ram_service_action_lock:\n                    self._ram_service_action_running = False\n                if button is not None:\n                    try:\n                        button.config(state=\"normal\")\n                    except Exception:\n                        pass\n                try:\n                    gc.collect()\n                except Exception:\n                    pass\n\n        return self._submit_ram_service_job(name, _wrapped, *args, **kwargs)\n\n    def _submit_printer_job(self, name, target, *args, **kwargs):\n        jm = getattr(self, \"job_manager\", None)\n        if jm is not None and hasattr(jm, \"submit_callable\"):\n            try:\n                jm.submit_callable(name, target, *args, **kwargs)\n                return True\n            except Exception:\n                pass\n        manager = getattr(self, \"worker_manager\", None)\n        if manager is not None and hasattr(manager, \"submit\"):\n            try:\n                manager.submit(name, target, *args, **kwargs)\n                return True\n            except Exception:\n                pass\n        try:\n            threading.Thread(target=target, args=args, kwargs=kwargs, daemon=True).start()\n            return True\n        except Exception:\n            return False\n\n    def _set_printer_action_controls_enabled(self, enabled):\n        for btn in getattr(self, \"_printer_action_buttons\", []):\n            try:\n                btn.config(state=\"normal\" if enabled else \"disabled\")\n            except Exception:\n                pass\n\n    def _printer_action_submit(self, name, target, *args, button=None, **kwargs):\n        with self._printer_action_lock:\n            if getattr(self, \"_printer_action_running\", False):\n                self._printer_log(\"\u26a0\ufe0f Printer action already running \u2014 duplicate request skipped\", C[\"warning\"])\n                return False\n            self._printer_action_running = True\n            self._printer_action_started_at = time.time()\n            self._printer_action_name = name\n            self._set_printer_action_controls_enabled(False)\n            if button is not None:\n                try:\n                    button.config(state=\"disabled\")\n                except Exception:\n                    pass\n\n        def _wrapped(*args, **kwargs):\n            try:\n                self._printer_emit_metrics({\"status_text\": f\"{name} running... elapsed 00:00\"})\n                return target(*args, **kwargs)\n            finally:\n                with self._printer_action_lock:\n                    self._printer_action_running = False\n                    self._printer_action_started_at = None\n                    self._printer_action_name = \"\"\n                self._printer_emit_metrics({\"status_text\": f\"{name} finished\"})\n                self._set_printer_action_controls_enabled(True)\n                if button is not None:\n                    try:\n                        button.config(state=\"normal\")\n                    except Exception:\n                        pass\n                try:\n                    gc.collect()\n                except Exception:\n                    pass\n\n        return self._submit_printer_job(name, _wrapped, *args, **kwargs)\n\n    def _tick_printer_action_timer(self):\n        try:\n            if getattr(self, \"_printer_action_running\", False) and getattr(self, \"_printer_action_started_at\", None):\n                elapsed = time.time() - float(self._printer_action_started_at)\n                name = getattr(self, \"_printer_action_name\", \"Printer action\") or \"Printer action\"\n                if hasattr(self, \"printer_exec_time_lbl\"):\n                    self.printer_exec_time_lbl.config(text=f\"Elapsed: {self._format_seconds(elapsed)} | ETA: depends on Windows service response\")\n                if hasattr(self, \"printer_exec_status_lbl\"):\n                    self.printer_exec_status_lbl.config(text=f\"{name} running...\")\n            elif hasattr(self, \"printer_exec_time_lbl\"):\n                self.printer_exec_time_lbl.config(text=\"Elapsed: 00:00 | ETA: --\")\n        except Exception:\n            pass\n        self.after(1000, self._tick_printer_action_timer)\n\n    def _poll_printer_metrics(self):\n        latest = None\n        try:\n            while not self._printer_metrics_queue.empty():\n                latest = self._printer_metrics_queue.get_nowait()\n        except Exception:\n            latest = None\n        if latest is not None:\n            try:\n                self._update_printer_metrics_ui(latest)\n            except Exception:\n                pass\n        self.after(30, self._poll_printer_metrics)\n\n    def _update_printer_metrics_ui(self, data):\n        try:\n            if hasattr(self, \"printer_exec_status_lbl\") and data.get(\"status_text\") is not None:\n                self.printer_exec_status_lbl.config(text=self._fix_text(str(data[\"status_text\"])), fg=C.get(\"accent4\", C[\"text\"]))\n            if hasattr(self, \"spooler_status_lbl\") and data.get(\"service_status\") is not None:\n                self.spooler_status_lbl.config(text=self._fix_text(str(data.get(\"service_status\"))))\n            if hasattr(self, \"printer_log\") and data.get(\"log_line\") is not None:\n                self._append_log(self.printer_log, str(data[\"log_line\"]), data.get(\"log_color\", C[\"text\"]))\n            if hasattr(self, \"printer_trace_log\") and data.get(\"trace_line\") is not None:\n                self._append_log(self.printer_trace_log, str(data[\"trace_line\"]), data.get(\"trace_color\", C[\"text_dim\"]))\n        except Exception:\n            pass\n\n    def _printer_emit_metrics(self, batch, force=False):\n        try:\n            if not isinstance(batch, dict):\n                batch = {\"status_text\": str(batch)}\n            batch = {**batch, \"ts\": datetime.datetime.now().isoformat(timespec=\"milliseconds\")}\n            with self._printer_metrics_lock:\n                self._printer_metrics_queue.put(batch.copy())\n        except Exception:\n            pass\n\n    def _printer_log(self, msg, color=C[\"text\"]):\n        self._printer_emit_metrics({\"log_line\": msg, \"log_color\": color})\n\n    def _printer_trace(self, msg, color=C[\"text_dim\"]):\n        self._printer_emit_metrics({\"trace_line\": msg, \"trace_color\": color})\n\n    def _submit_registry_gp_job(self, name, target, *args, **kwargs):\n        jm = getattr(self, \"job_manager\", None)\n        if jm is not None and hasattr(jm, \"submit_callable\"):\n            try:\n                jm.submit_callable(name, target, *args, **kwargs)\n                return True\n            except Exception:\n                pass\n        manager = getattr(self, \"worker_manager\", None)\n        if manager is not None and hasattr(manager, \"submit\"):\n            try:\n                manager.submit(name, target, *args, **kwargs)\n                return True\n            except Exception:\n                pass\n        try:\n            threading.Thread(target=target, args=args, kwargs=kwargs, daemon=True).start()\n            return True\n        except Exception:\n            return False\n\n    def _poll_registry_gp_metrics(self):\n        latest = None\n        try:\n            while not self._registry_gp_metrics_queue.empty():\n                latest = self._registry_gp_metrics_queue.get_nowait()\n        except Exception:\n            latest = None\n        if latest is not None:\n            try:\n                self._update_registry_gp_metrics_ui(latest)\n            except Exception:\n                pass\n        self.after(40, self._poll_registry_gp_metrics)\n\n    def _update_registry_gp_metrics_ui(self, data):\n        try:\n            if hasattr(self, \"reg_progress_var\") and data.get(\"progress_pct\") is not None:\n                self.reg_progress_var.set(max(0.0, min(100.0, float(data[\"progress_pct\"]))))\n            if hasattr(self, \"reg_status_lbl\") and data.get(\"status_text\") is not None:\n                self.reg_status_lbl.config(text=self._fix_text(str(data[\"status_text\"])))\n            if hasattr(self, \"reg_keys_changed_var\") and data.get(\"keys_changed\") is not None:\n                self.reg_keys_changed_var.set(str(int(data[\"keys_changed\"])))\n            if hasattr(self, \"reg_predicted_impact_var\") and data.get(\"predicted_impact\") is not None:\n                self.reg_predicted_impact_var.set(str(int(data.get(\"predicted_impact\", 0))))\n            if hasattr(self, \"reg_confidence_var\") and data.get(\"confidence_score\") is not None:\n                self.reg_confidence_var.set(f\"{int(data.get('confidence_score', 0))}%\")\n            if hasattr(self, \"gp_progress_var\") and data.get(\"progress_pct\") is not None:\n                self.gp_progress_var.set(max(0.0, min(100.0, float(data[\"progress_pct\"]))))\n            if hasattr(self, \"gp_status_lbl\") and data.get(\"status_text\") is not None:\n                self.gp_status_lbl.config(text=self._fix_text(str(data[\"status_text\"])))\n            if hasattr(self, \"gp_action_count_var\") and data.get(\"actions_done\") is not None:\n                self.gp_action_count_var.set(str(int(data[\"actions_done\"])))\n            if hasattr(self, \"gp_policy_score_var\") and data.get(\"policy_score\") is not None:\n                self.gp_policy_score_var.set(f\"{int(data[\"policy_score\"])}%\")\n            if hasattr(self, \"gp_restart_risk_var\") and data.get(\"restart_risk\") is not None:\n                self.gp_restart_risk_var.set(str(data[\"restart_risk\"]))\n        except Exception:\n            pass\n\n    # \u2500\u2500 Thread-safe queue helpers (called from background threads) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _q(self, msg_type, payload=None):\n        \"\"\"Thread-safe: enqueue a UI update message.\"\"\"\n        try:\n            self._ui_queue.put_nowait((msg_type, payload))\n        except Exception:\n            pass\n\n    def _q_progress(self, text, pct=None):\n        \"\"\"Enqueue a progress label + optional percentage update.\"\"\"\n        self._q(\"progress_label\", text)\n        if pct is not None:\n            self._q(\"progress_pct\", pct)\n\n    def _q_log(self, text):\n        \"\"\"Enqueue a log line append.\"\"\"\n        self._q(\"log_line\", text)\n\n    def _q_tree_row(self, row, entry):\n        \"\"\"Enqueue a tree row insertion.\"\"\"\n        self._q(\"tree_row\", (row, entry))\n\n    # \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _safe_json(self, value):\n        try:\n            json.dumps(value)\n            return value\n        except Exception:\n            return str(value)\n\n    def _audit_event(self, event_type, payload):\n        try:\n            if not getattr(self, \"audit_file\", \"\"):\n                return\n            rec = {\n                \"ts\": datetime.datetime.now().isoformat(timespec=\"seconds\"),\n                \"event\": str(event_type),\n                \"payload\": self._safe_json(payload),\n            }\n            with open(self.audit_file, \"a\", encoding=\"utf-8\") as f:\n                f.write(json.dumps(rec, ensure_ascii=False) + \"\\n\")\n            try:\n                if hasattr(self, \"structured_logger\"):\n                    self.structured_logger.event(\"legacy_app\", str(event_type), legacy_payload=payload)\n                store = getattr(self, \"audit_store\", None)\n                if store is not None:\n                    store.append(\"legacy_app\", str(event_type), payload)\n            except Exception:\n                pass\n        except Exception:\n            pass\n\n    def _snapshot_system_state(self):\n        try:\n            vm = psutil.virtual_memory()\n            du = psutil.disk_usage(\"C:\\\\\")\n            cpu = psutil.cpu_percent(interval=None)\n            proc_count = len(list(psutil.process_iter([\"pid\"])))\n            return {\n                \"cpu_percent\": round(cpu, 2),\n                \"ram_percent\": round(vm.percent, 2),\n                \"disk_percent\": round(du.percent, 2),\n                \"process_count\": proc_count,\n                \"ts\": datetime.datetime.now().isoformat(timespec=\"seconds\"),\n            }\n        except Exception as e:\n            return {\"error\": str(e)}\n\n    def _launch_job(self, name, target, *args, **kwargs):\n        with self._job_lock:\n            self._job_counter += 1\n            jid = f\"job-{self._job_counter}\"\n            self._jobs[jid] = {\n                \"name\": name,\n                \"status\": \"queued\",\n                \"started_at\": datetime.datetime.now().isoformat(timespec=\"seconds\"),\n            }\n\n        task_id = self._task_start(name, progress=0, metadata={\"job_id\": jid})\n\n        def runner():\n            with self._job_lock:\n                if jid in self._jobs:\n                    self._jobs[jid][\"status\"] = \"running\"\n            self._audit_event(\"job_started\", {\"job_id\": jid, \"name\": name, \"task_id\": task_id})\n            try:\n                target_kwargs = dict(kwargs)\n                try:\n                    sig = inspect.signature(target)\n                    if \"task_id\" in sig.parameters:\n                        target_kwargs[\"task_id\"] = task_id\n                except Exception:\n                    pass\n                target(*args, **target_kwargs)\n                with self._job_lock:\n                    if jid in self._jobs:\n                        self._jobs[jid][\"status\"] = \"done\"\n                        self._jobs[jid][\"ended_at\"] = datetime.datetime.now().isoformat(timespec=\"seconds\")\n                task_record = self._task_manager.get(task_id)\n                if task_record is not None and not task_record.get(\"cancel_requested\", False) and task_record.get(\"status\") != \"failed\":\n                    task_record[\"progress\"] = 100\n                    task_record[\"status\"] = \"done\"\n            except Exception as e:\n                with self._job_lock:\n                    if jid in self._jobs:\n                        self._jobs[jid][\"status\"] = \"failed\"\n                        self._jobs[jid][\"error\"] = str(e)\n                if task_id in self._task_manager:\n                    self._task_manager[task_id][\"status\"] = \"failed\"\n                    self._task_manager[task_id][\"error\"] = str(e)\n                self._audit_event(\"job_failed\", {\"job_id\": jid, \"name\": name, \"error\": str(e), \"task_id\": task_id})\n                self.after(0, lambda: self._log(f\"Background job failed [{name}]: {e}\", \"ERR\"))\n            finally:\n                with self._job_lock:\n                    if jid in self._jobs and \"ended_at\" not in self._jobs[jid]:\n                        self._jobs[jid][\"ended_at\"] = datetime.datetime.now().isoformat(timespec=\"seconds\")\n                self._audit_event(\"job_finished\", {\"job_id\": jid, \"name\": name, \"task_id\": task_id})\n                if hasattr(self, \"task_center_tree\"):\n                    self.after(0, self._refresh_task_center)\n\n        manager = getattr(self, \"worker_manager\", None)\n        jm = getattr(self, \"job_manager\", None)\n        if jm is not None and hasattr(jm, \"submit_callable\"):\n            try:\n                jm.submit_callable(name, runner)\n                return task_id\n            except Exception:\n                pass\n        if manager is not None and hasattr(manager, \"submit\"):\n            try:\n                manager.submit(name, runner)\n            except Exception:\n                threading.Thread(target=runner, daemon=True).start()\n        else:\n            threading.Thread(target=runner, daemon=True).start()\n        return task_id\n    \n    def _create_tooltip(self, widget, text, delay=430):\n        \"\"\"Attach a small hover tooltip to a widget.\"\"\"\n        if not widget or not text:\n            return\n        tipdata = {\"id\": None, \"window\": None}\n\n        def _show(event=None):\n            if tipdata[\"window\"] or not text:\n                return\n            try:\n                x = widget.winfo_rootx() + 18\n                y = widget.winfo_rooty() + widget.winfo_height() + 6\n                win = tk.Toplevel(widget)\n                win.wm_overrideredirect(True)\n                win.attributes(\"-topmost\", True)\n                win.config(bg=C[\"text_dark\"])\n                lbl = tk.Label(win, text=text, justify=\"left\", bg=C[\"text_dark\"], fg=C[\"text\"],\n                               font=FONTS[\"xsmall\"], wraplength=320, relief=\"solid\", bd=1, padx=6, pady=4)\n                lbl.pack()\n                win.wm_geometry(f\"+{x}+{y}\")\n                tipdata[\"window\"] = win\n            except Exception:\n                tipdata[\"window\"] = None\n\n        def _hide(event=None):\n            try:\n                if tipdata[\"id\"]:\n                    self.after_cancel(tipdata[\"id\"])\n                    tipdata[\"id\"] = None\n                if tipdata[\"window\"]:\n                    tipdata[\"window\"].destroy()\n                    tipdata[\"window\"] = None\n            except Exception:\n                pass\n\n        def _schedule(event=None):\n            _hide()\n            try:\n                tipdata[\"id\"] = self.after(delay, _show)\n            except Exception:\n                tipdata[\"id\"] = None\n\n        widget.bind(\"\", _schedule)\n        widget.bind(\"\", _hide)\n        widget.bind(\"\", _hide)\n        return tipdata\n\n    # ---------- STYLE ----------\n    def _build_style(self):\n        self.style = ttk.Style(self)\n        self.style.theme_use(\"clam\")\n        self.style.configure(\"TFrame\", background=C[\"bg\"])\n        self.style.configure(\"Card.TFrame\", background=C[\"card\"])\n        self.style.configure(\"Panel.TFrame\", background=C[\"panel\"])\n        self.style.configure(\"Sidebar.TFrame\", background=C[\"sidebar\"])\n        self.style.configure(\"TProgressbar\", troughcolor=C[\"border\"], background=C[\"accent\"], thickness=6)\n        self.style.configure(\"TNotebook\", background=C[\"bg\"], borderwidth=0)\n        self.style.configure(\"TNotebook.Tab\", background=C[\"panel\"], foreground=C[\"text_dim\"], padding=[16, 6], borderwidth=0)\n        self.style.map(\"TNotebook.Tab\",\n                        background=[(\"selected\", C[\"card\"]), (\"active\", C[\"panel\"]), (\"!active\", C[\"panel\"])],\n                        foreground=[(\"selected\", C[\"accent\"]), (\"active\", C[\"text\"]), (\"!active\", C[\"text_dim\"])])\n        self.style.configure(\"Custom.Treeview\", background=C[\"card\"], foreground=C[\"text\"],\n                             fieldbackground=C[\"card\"], rowheight=22, font=FONTS[\"small\"])\n        self.style.configure(\"Custom.Treeview.Heading\", background=C[\"panel\"],\n                             foreground=C[\"accent\"], font=FONTS[\"small\"])\n\n    # ---------- HEADER ----------\n    def _build_header(self):\n        hdr = tk.Frame(self, bg=C[\"header_bg\"], height=62)\n        hdr.pack(side=\"top\", fill=\"x\")\n        hdr.pack_propagate(False)\n        tk.Frame(hdr, bg=C[\"accent\"], height=2).pack(side=\"bottom\", fill=\"x\")\n\n        logo_frame = tk.Frame(hdr, bg=C[\"header_bg\"])\n        logo_frame.pack(side=\"left\", padx=20, pady=8)\n        tk.Label(logo_frame, text=\"\u26a1\", font=(\"Segoe UI\", 24), fg=C[\"accent\"], bg=C[\"header_bg\"]).pack(side=\"left\", padx=(0,8))\n        tk.Label(logo_frame, text=\"Godawari\", font=(\"Segoe UI\", 18, \"bold\"), fg=C[\"text\"], bg=C[\"header_bg\"]).pack(side=\"left\")\n        tk.Label(logo_frame, text=\" Computers\", font=(\"Segoe UI\", 18, \"bold\"), fg=C[\"accent\"], bg=C[\"header_bg\"]).pack(side=\"left\")\n        tk.Label(logo_frame, text=\"  Optimizer Pro v11.0\", font=(\"Segoe UI\", 10, \"bold\"), fg=C[\"accent2\"], bg=C[\"header_bg\"]).pack(side=\"left\", pady=(6,0))\n        tk.Label(logo_frame, text=f\"  |  Last Updated: {SCRIPT_LAST_UPDATED}\", font=(\"Segoe UI\", 9), fg=C[\"text_dim\"], bg=C[\"header_bg\"]).pack(side=\"left\", pady=(6,0))\n\n        right = tk.Frame(hdr, bg=C[\"header_bg\"])\n        right.pack(side=\"right\", padx=20, pady=10)\n        self.clock_lbl = tk.Label(right, font=FONTS[\"small\"], fg=C[\"accent\"], bg=C[\"header_bg\"])\n        self.clock_lbl.pack(side=\"right\")\n        tk.Label(right, text=f\"  {platform.node()}  |  {platform.system()} {platform.release()}  |  \",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"header_bg\"]).pack(side=\"right\")\n        self._tick_clock()\n\n        badge_color = C[\"success\"] if is_admin() else C[\"error\"]\n        badge_text = \"\u25cf ADMIN MODE ON\" if is_admin() else \"\u25cf USER MODE (Admin required!)\"\n        tk.Label(hdr, text=badge_text, font=FONTS[\"small\"], fg=badge_color, bg=C[\"header_bg\"]).pack(side=\"right\", padx=12)\n\n        self.theme_btn = tk.Button(hdr, text=\"\ud83c\udf19\", font=(\"Segoe UI\", 10), bg=C[\"panel\"],\n                                   fg=C[\"accent\"], bd=0, padx=6, cursor=\"hand2\", command=self._toggle_theme)\n        self.theme_btn.pack(side=\"right\", padx=10)\n        tk.Label(hdr, text=\"Shravan Shrimali\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"header_bg\"]).pack(side=\"right\", padx=10)\n\n    def _tick_clock(self):\n        self.clock_lbl.config(text=datetime.datetime.now().strftime(\"%d/%m/%Y  %H:%M:%S\"))\n        self.after(1000, self._tick_clock)\n\n    # ---------- BODY ----------\n    # Section builder map \u2014 lazy loading ke liye\n    _SECTION_BUILDERS = {\n        \"dashboard\":      \"_build_dashboard\",\n        \"shop\":           \"_build_shop_mode\",\n        \"cleaner\":        \"_build_cleaner\",\n        \"services\":       \"_build_services\",\n        \"memory\":         \"_build_memory_services_merged\",\n        \"startup\":        \"_build_startup_scheduler_merged\",\n        \"registry\":       \"_build_registry_gp_merged\",\n        \"network\":        \"_build_network_troubleshooter_merged\",\n        \"hdd_repair\":     \"_build_hdd_recovery_merged\",\n        \"data_recovery\":  \"_build_data_recovery\",\n        \"rescue_center\":  \"_build_rescue_recovery_center\",\n        \"printer\":        \"_build_printer_driver_merged\",\n        \"uninstall\":      \"_build_uninstall_backup_merged\",\n        \"dupfinder\":      \"_build_dup_report_merged\",\n        \"grouppolicy\":    \"_build_grouppolicy\",\n        \"scheduler\":      \"_build_scheduler\",\n        \"troubleshooter\": \"_build_troubleshooter\",\n        \"power\":          \"_build_power\",\n        \"driver\":         \"_build_driver\",\n        \"backup\":         \"_build_backup\",\n        \"report\":         \"_build_report\",\n        \"log\":            \"_build_log\",\n        \"boost\":          \"_build_boost_section\",\n        \"suspicion\":      \"_build_suspicion_scanner\",\n        \"realtime_security\": \"_build_realtime_security\",\n        \"activation\":     \"_build_activation\",\n        \"eventviewer\":    \"_build_event_viewer\",\n        \"office_tools\":   \"_build_office_tools\",\n        \"excel_tools\":    \"_build_excel_tools\",\n        \"image_tools\":    \"_build_image_tools\",\n        \"file_tools\":     \"_build_file_tools\",\n        \"safety_center\":  \"_build_safety_center\",\n        \"driver_manager\": \"_build_driver_manager\",\n        \"partition_manager\": \"_build_partition_manager\",\n        \"easy_driver\":    \"_build_easy_driver_clone\",\n        \"svc_presets\":    \"_build_svc_presets\",\n        \"disk_analyzer\":  \"_build_disk_analyzer\",\n        \"bsod_history\":   \"_build_bsod_history\",\n        \"corrupt_wizard\": \"_build_corrupt_wizard\",\n        \"password_audit\": \"_build_password_audit\",\n        \"auto_backup\":    \"_build_auto_backup\",\n    }\n\n    def _build_body(self):\n        body = tk.Frame(self, bg=C[\"bg\"])\n        body.pack(fill=\"both\", expand=True)\n        self.sidebar = tk.Frame(body, bg=C[\"sidebar\"], width=260)\n        self.sidebar.pack(side=\"left\", fill=\"y\")\n        self.sidebar.pack_propagate(False)\n        tk.Frame(self.sidebar, bg=C[\"border\"], width=1).pack(side=\"right\", fill=\"y\")\n        self._build_sidebar()\n        self.main = tk.Frame(body, bg=C[\"bg\"])\n        self.main.pack(side=\"left\", fill=\"both\", expand=True)\n        self.sections = {}\n        self._sections_built = set()\n        self._build_queue = []\n\n        # Sirf dashboard abhi banaao \u2014 baki lazy load honge\n        self.sections[\"dashboard\"] = self._build_dashboard(self.main)\n        self._sections_built.add(\"dashboard\")\n\n        # Baki ke liye placeholder frames\n        for key in self._SECTION_BUILDERS:\n            if key == \"dashboard\":\n                continue\n            ph = tk.Frame(self.main, bg=C[\"bg\"])\n            tk.Label(ph, text=\"\u23f3\", font=(\"Segoe UI\", 28),\n                     fg=C[\"accent\"], bg=C[\"bg\"]).place(relx=0.5, rely=0.42, anchor=\"center\")\n            tk.Label(ph, text=\"Loading...\", font=FONTS[\"heading\"],\n                     fg=C[\"text_dim\"], bg=C[\"bg\"]).place(relx=0.5, rely=0.52, anchor=\"center\")\n            self.sections[key] = ph\n            self._build_queue.append(key)\n\n        # Keep startup fast: sections are built when the user opens them.\n        self.after(600, self._sanitize_ui_texts)\n\n    def _lazy_build_next(self):\n        if not self._build_queue:\n            return\n        key = self._build_queue.pop(0)\n        try:\n            real = getattr(self, self._SECTION_BUILDERS[key])(self.main)\n            self.sections[key] = real\n            self._sections_built.add(key)\n            if self.active_section.get() == key:\n                for s in self.sections.values():\n                    s.pack_forget()\n                real.pack(fill=\"both\", expand=True)\n        except Exception as e:\n            import traceback\n            err_detail = traceback.format_exc()\n            self._log(f\"Lazy build [{key}] ERROR: {err_detail}\", \"WARN\")\n            # Replace placeholder with error frame so user knows something failed\n            err_frame = tk.Frame(self.main, bg=C[\"bg\"])\n            tk.Label(err_frame, text=f\"\u274c '{key}' section load nahi hua\",\n                     font=FONTS[\"heading\"], fg=C[\"error\"], bg=C[\"bg\"]).place(relx=0.5, rely=0.40, anchor=\"center\")\n            tk.Label(err_frame, text=str(e)[:200],\n                     font=FONTS[\"small\"], fg=C[\"warning\"], bg=C[\"bg\"], wraplength=500).place(relx=0.5, rely=0.50, anchor=\"center\")\n            tk.Button(err_frame, text=\"\ud83d\udd04 Retry\",\n                      font=FONTS[\"body\"], bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=16, pady=8,\n                      cursor=\"hand2\",\n                      command=lambda k=key: (self._sections_built.discard(k),\n                                              self._show_section(k))).place(relx=0.5, rely=0.62, anchor=\"center\")\n            self.sections[key] = err_frame\n        if self._build_queue:\n            self.after(40, self._lazy_build_next)\n\n    def _build_sidebar(self):\n        canvas = tk.Canvas(self.sidebar, bg=C[\"sidebar\"], highlightthickness=0)\n        scrollbar = tk.Scrollbar(self.sidebar, orient=\"vertical\", command=canvas.yview)\n        self.sidebar_frame = tk.Frame(canvas, bg=C[\"sidebar\"])\n        self.sidebar_frame.bind(\"\", lambda e: canvas.configure(scrollregion=canvas.bbox(\"all\")))\n        sidebar_window = canvas.create_window((0, 0), window=self.sidebar_frame, anchor=\"nw\")\n        canvas.configure(yscrollcommand=scrollbar.set)\n        scrollbar.pack(side=\"right\", fill=\"y\")\n        canvas.pack(side=\"left\", fill=\"both\", expand=True)\n\n        def _sidebar_resize(event=None):\n            canvas.itemconfig(sidebar_window, width=event.width)\n            canvas.configure(scrollregion=canvas.bbox(\"all\"))\n        canvas.bind(\"\", _sidebar_resize)\n\n        self._bind_scoped_mousewheel(self.sidebar_frame, canvas)\n\n        tk.Label(self.sidebar_frame, text=\"GODAWARI COMPUTERS\", font=(\"Segoe UI\", 10, \"bold\"),\n                 fg=C[\"accent\"], bg=C[\"sidebar\"]).pack(pady=(12,2), padx=14, anchor=\"w\")\n        tk.Label(self.sidebar_frame, text=\"Optimizer Pro v11.0\", font=FONTS[\"small\"],\n                 fg=C[\"text_dim\"], bg=C[\"sidebar\"]).pack(pady=(0,8), padx=14, anchor=\"w\")\n\n        categories = SIDEBAR_CATEGORIES\n        self.nav_btns = {}\n        for heading, color_key, items in categories:\n            color = C[color_key]\n            # Category separator line\n            tk.Frame(self.sidebar_frame, bg=C[\"border\"], height=1).pack(fill=\"x\", padx=10, pady=(8,0))\n            tk.Label(self.sidebar_frame, text=heading, font=(\"Segoe UI\", 8, \"bold\"), fg=color, bg=C[\"sidebar\"]).pack(pady=(4,3), padx=14, anchor=\"w\")\n            for key, icon, label in items:\n                frame = tk.Frame(self.sidebar_frame, bg=C[\"sidebar\"], cursor=\"hand2\")\n                frame.pack(fill=\"x\", padx=8, pady=1)\n                hw_keys = set()\n                icon_fg = C[\"hw_accent\"] if key in hw_keys else C[\"accent\"]\n                tk.Label(frame, text=icon, font=(\"Segoe UI\", 8, \"bold\"), bg=C[\"sidebar\"], fg=icon_fg, width=5, anchor=\"center\").pack(side=\"left\", padx=(8,6), pady=6)\n                tk.Label(frame, text=label, font=FONTS[\"body\"], bg=C[\"sidebar\"], fg=C[\"text\"], anchor=\"w\").pack(side=\"left\", fill=\"x\", expand=True)\n                def on_enter(e, k=key, f=frame): \n                    if self.active_section.get() != k:\n                        f.config(bg=C[\"card\"])\n                        for w in f.winfo_children():\n                            w.config(bg=C[\"card\"])\n                def on_leave(e, k=key, f=frame): \n                    if self.active_section.get() != k:\n                        f.config(bg=C[\"sidebar\"])\n                        for w in f.winfo_children():\n                            w.config(bg=C[\"sidebar\"])\n                def on_click(e, k=key):\n                    self._show_section(k)\n                frame.bind(\"\", on_enter)\n                frame.bind(\"\", on_leave)\n                frame.bind(\"\", on_click)\n                for child in frame.winfo_children():\n                    child.bind(\"\", on_enter)\n                    child.bind(\"\", on_leave)\n                    child.bind(\"\", on_click)\n                self.nav_btns[key] = frame\n\n        tk.Frame(self.sidebar_frame, bg=C[\"border\"], height=1).pack(fill=\"x\", padx=10, pady=10)\n        info = tk.Frame(self.sidebar_frame, bg=C[\"panel\"])\n        info.pack(fill=\"x\", padx=10, pady=(0,10))\n        ram_gb = round(psutil.virtual_memory().total / (1024**3), 1)\n        for line in [f\"CPU: {psutil.cpu_count()} cores\", f\"RAM: {ram_gb} GB\", f\"OS: Windows {platform.release()}\"]:\n            tk.Label(info, text=line, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(anchor=\"w\", padx=8, pady=2)\n\n    def _show_section(self, key):\n        if key not in self.sections:\n            return\n        # On-demand build agar abhi tak nahi bana\n        if hasattr(self, \"_sections_built\") and key not in self._sections_built:\n            if key in getattr(self, \"_build_queue\", []):\n                self._build_queue.remove(key)\n            try:\n                real = getattr(self, self._SECTION_BUILDERS[key])(self.main)\n                self.sections[key] = real\n                self._sections_built.add(key)\n                self.after(50, self._sanitize_ui_texts)\n            except Exception as e:\n                import traceback\n                err_msg = traceback.format_exc()\n                self._log(f\"On-demand build [{key}]: {e}\", \"WARN\")\n                # Show error frame instead of silent loading screen\n                err_frame = tk.Frame(self.main, bg=C[\"bg\"])\n                tk.Label(err_frame, text=\"\u274c Section load nahi hua\",\n                         font=FONTS[\"heading\"], fg=C[\"error\"], bg=C[\"bg\"]).place(relx=0.5, rely=0.40, anchor=\"center\")\n                tk.Label(err_frame, text=str(e)[:200],\n                         font=FONTS[\"small\"], fg=C[\"warning\"], bg=C[\"bg\"], wraplength=500).place(relx=0.5, rely=0.50, anchor=\"center\")\n                tk.Button(err_frame, text=\"\ud83d\udd04 Retry\", font=FONTS[\"body\"],\n                          bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=16, pady=8,\n                          cursor=\"hand2\",\n                          command=lambda k=key: (self._sections_built.discard(k),\n                                                  self._show_section(k))).place(relx=0.5, rely=0.62, anchor=\"center\")\n                self.sections[key] = err_frame\n        old = self.active_section.get()\n        if old in self.nav_btns:\n            self.nav_btns[old].config(bg=C[\"sidebar\"])\n            for w in self.nav_btns[old].winfo_children():\n                w.config(bg=C[\"sidebar\"])\n        self.active_section.set(key)\n        if key in self.nav_btns:\n            self.nav_btns[key].config(bg=C[\"btn_info\"])\n            for w in self.nav_btns[key].winfo_children():\n                w.config(bg=C[\"btn_info\"])\n        for k, sec in self.sections.items():\n            sec.pack_forget()\n        self.sections[key].pack(fill=\"both\", expand=True)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  MERGED SECTION BUILDERS \u2014 2 sections ek tabbed view mein\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _build_tabbed_merger(self, parent, tabs):\n        \"\"\"\n        tabs = [(tab_label, builder_method_name), ...]\n        Ek frame return karta hai jisme top mein tab buttons hain,\n        niche active tab ka content.\n        \"\"\"\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        tab_bar = tk.Frame(frame, bg=C[\"panel\"])\n        tab_bar.pack(fill=\"x\")\n        content_area = tk.Frame(frame, bg=C[\"bg\"])\n        content_area.pack(fill=\"both\", expand=True)\n\n        built = {}\n        active_btn = [None]\n\n        def show_tab(idx, btn):\n            if active_btn[0]:\n                active_btn[0].config(bg=C[\"panel\"], fg=C[\"text_dim\"])\n            btn.config(bg=C[\"accent\"], fg=C[\"bg\"])\n            active_btn[0] = btn\n            for w in content_area.winfo_children():\n                w.pack_forget()\n            key = tabs[idx][0]\n            if key not in built:\n                built[key] = getattr(self, tabs[idx][1])(content_area)\n            built[key].pack(fill=\"both\", expand=True)\n\n        btns = []\n        for i, (label, _) in enumerate(tabs):\n            b = tk.Button(tab_bar, text=label, font=FONTS[\"subhead\"],\n                          bg=C[\"panel\"], fg=C[\"text_dim\"], bd=0, padx=20, pady=8,\n                          cursor=\"hand2\", relief=\"flat\",\n                          command=lambda idx=i: show_tab(idx, btns[idx]))\n            b.pack(side=\"left\")\n            btns.append(b)\n        tk.Frame(tab_bar, bg=C[\"border\"], height=2).pack(side=\"bottom\", fill=\"x\")\n\n        # Default: first tab\n        frame.after(10, lambda: show_tab(0, btns[0]))\n        return frame\n\n    def _build_memory_services_merged(self, parent):\n        return self._build_tabbed_merger(parent, [\n            (\"\ud83e\udde0  RAM Optimizer\", \"_build_memory\"),\n            (\"\u2699\ufe0f  Smart Services\", \"_build_services\"),\n        ])\n\n    def _build_startup_scheduler_merged(self, parent):\n        return self._build_tabbed_merger(parent, [\n            (\"\ud83d\ude80  Startup Manager\", \"_build_startup\"),\n            (\"\ud83d\udcc5  Task Scheduler\", \"_build_scheduler\"),\n        ])\n\n    def _build_registry_gp_merged(self, parent):\n        return self._build_tabbed_merger(parent, [\n            (\"\ud83d\udcdd  Registry Tweaks\", \"_build_registry\"),\n            (\"\ud83d\udee1  Group Policy\", \"_build_grouppolicy\"),\n        ])\n\n    def _build_network_troubleshooter_merged(self, parent):\n        return self._build_tabbed_merger(parent, [\n            (\"\ud83c\udf10  Network Optimizer\", \"_build_network\"),\n            (\"\ud83d\udd27  System Troubleshooter\", \"_build_troubleshooter\"),\n        ])\n\n    def _build_hdd_recovery_merged(self, parent):\n        return self._build_tabbed_merger(parent, [\n            (\"\ud83d\udcbe  HDD/SSD Repair\", \"_build_hdd_repair\"),\n            (\"\ud83d\udcc2  File Recovery\", \"_build_recovery_center\"),\n        ])\n\n    def _build_data_recovery(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(\n            frame,\n            \"\ud83d\udd2c Data Recovery\",\n            \"Forensic-grade imaging, deep carving, partition recovery, and raw sector inspection.\",\n        )\n\n        self._data_recovery_state = getattr(self, \"_data_recovery_state\", {\n            \"running\": False,\n            \"paused\": False,\n            \"cancelled\": False,\n            \"last_img\": \"\",\n            \"last_report\": \"\",\n            \"preview\": [],\n            \"scan_mode\": \"quick\",\n            \"history\": [],\n            \"queue\": [],\n            \"task_id\": None,\n            \"session_id\": None,\n        })\n\n        hero = tk.Frame(frame, bg=C[\"panel\"], highlightbackground=C[\"border\"], highlightthickness=1)\n        hero.pack(fill=\"x\", padx=16, pady=(8, 10))\n        hero.columnconfigure(0, weight=2)\n        hero.columnconfigure(1, weight=1)\n\n        left = tk.Frame(hero, bg=C[\"panel\"])\n        left.grid(row=0, column=0, sticky=\"nsew\", padx=(16, 10), pady=16)\n        tk.Label(\n            left,\n            text=\"Godawari Ultimate Optimizer v11 \u2014 Data Recovery\",\n            font=(\"Segoe UI\", 18, \"bold\"),\n            fg=C[\"text\"],\n            bg=C[\"panel\"],\n        ).pack(anchor=\"w\")\n        tk.Label(\n            left,\n            text=\"Forensic-grade imaging, deep carving, partition recovery, and safe raw-sector inspection in one premium control center.\",\n            font=FONTS[\"small\"],\n            fg=C[\"text_dim\"],\n            bg=C[\"panel\"],\n            justify=\"left\",\n            wraplength=760,\n        ).pack(anchor=\"w\", pady=(4, 10))\n\n        chip_row = tk.Frame(left, bg=C[\"panel\"])\n        chip_row.pack(fill=\"x\")\n        for text, color in [(\"Quick Recovery\", C[\"accent2\"]), (\"Deep Carve\", C[\"warning\"]), (\"Partition Audit\", C[\"hw_accent\"]), (\"Sector Imaging\", C[\"accent\"]), (\"Audit Report\", C[\"btn_info\"]), (\"Evidence Safe\", C[\"success\"])]:\n            chip = tk.Frame(chip_row, bg=color, height=20)\n            chip.pack(side=\"left\", padx=(0, 8), pady=2)\n            tk.Label(chip, text=text, font=FONTS[\"xsmall\"], fg=\"#0A0F1A\", bg=color, padx=8, pady=2).pack()\n\n        right = tk.Frame(hero, bg=C[\"panel\"])\n        right.grid(row=0, column=1, sticky=\"nsew\", padx=(10, 16), pady=16)\n        tk.Label(\n            right,\n            text=\"Recovery Flow\",\n            font=FONTS[\"subhead\"],\n            fg=C[\"accent\"],\n            bg=C[\"panel\"],\n        ).pack(anchor=\"w\")\n        tk.Label(\n            right,\n            text=\"1. Select source \u2022 2. Validate target \u2022 3. Recover or image \u2022 4. Export report\",\n            font=FONTS[\"small\"],\n            fg=C[\"text\"],\n            bg=C[\"panel\"],\n            justify=\"left\",\n            wraplength=320,\n        ).pack(anchor=\"w\", pady=(4, 10))\n        tk.Frame(right, bg=C[\"border\"], height=1).pack(fill=\"x\", pady=(0, 8))\n        tk.Label(\n            right,\n            text=\"Live status: Ready for a new evidence session.\",\n            font=FONTS[\"small\"],\n            fg=C[\"text_dim\"],\n            bg=C[\"panel\"],\n            anchor=\"w\",\n        ).pack(fill=\"x\")\n\n        safety = tk.Frame(frame, bg=C[\"card\"], highlightbackground=C[\"warning\"], highlightthickness=1)\n        safety.pack(fill=\"x\", padx=16, pady=(0, 10))\n        top_bar = tk.Frame(safety, bg=C[\"card\"])\n        top_bar.pack(fill=\"x\", padx=12, pady=(12, 6))\n        tk.Label(\n            top_bar,\n            text=\"\u26a0\ufe0f Safety Gate \u2014 Raw Operations\",\n            font=FONTS[\"subhead\"],\n            fg=C[\"warning\"],\n            bg=C[\"card\"],\n        ).pack(anchor=\"w\")\n        tk.Label(\n            safety,\n            text=\"Raw disk access, sector imaging, and partition recovery can alter evidence and metadata. Use only on authorized disks and always image first.\",\n            font=FONTS[\"small\"],\n            fg=C[\"text\"],\n            bg=C[\"card\"],\n            justify=\"left\",\n            wraplength=1100,\n        ).pack(anchor=\"w\", padx=12, pady=(0, 12))\n\n        summary = tk.Frame(frame, bg=C[\"bg\"])\n        summary.pack(fill=\"x\", padx=16, pady=(0, 8))\n        for idx in range(4):\n            summary.columnconfigure(idx, weight=1)\n\n        self._data_recovery_summary_labels = getattr(self, \"_data_recovery_summary_labels\", {})\n        for idx, (label, value, fg) in enumerate([\n            (\"Source\", \"Ready\", C[\"accent\"]),\n            (\"Recovered\", \"0 files\", C[\"accent2\"]),\n            (\"Chance\", \"Low\", C[\"warning\"]),\n            (\"Image\", \"No image yet\", C[\"hw_accent\"]),\n        ]):\n            if label not in self._data_recovery_summary_labels:\n                card = tk.Frame(summary, bg=C[\"card\"], highlightbackground=C[\"border\"], highlightthickness=1)\n                card.grid(row=0, column=idx, padx=5, pady=0, sticky=\"nsew\")\n                tk.Label(card, text=label, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=10, pady=(8, 2))\n                lbl = tk.Label(card, text=value, font=FONTS[\"heading\"], fg=fg, bg=C[\"card\"])\n                lbl.pack(anchor=\"w\", padx=10, pady=(0, 8))\n                self._data_recovery_summary_labels[label] = lbl\n            else:\n                self._data_recovery_summary_labels[label].config(text=value, fg=fg)\n\n        explain = tk.Frame(frame, bg=C[\"panel\"])\n        explain.pack(fill=\"x\", padx=16, pady=(0, 10))\n        tk.Label(explain, text=\"Quick Recovery \u2014 Fast file recovery / \u0924\u094d\u0935\u0930\u093f\u0924 \u092b\u093c\u093e\u0907\u0932 \u0930\u093f\u0915\u0935\u0930\u0940\", font=FONTS[\"small\"], fg=C[\"accent\"], bg=C[\"panel\"]).pack(anchor=\"w\", padx=10, pady=(6, 0))\n        tk.Label(explain, text=\"Deep Recovery \u2014 Signature carving and raw scan / \u0938\u093f\u0917\u094d\u0928\u0947\u091a\u0930-\u0906\u0927\u093e\u0930\u093f\u0924 \u0917\u0939\u0930\u0940 \u0916\u094b\u091c\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(anchor=\"w\", padx=10, pady=(0, 6))\n\n        notebook = ttk.Notebook(frame)\n        notebook.pack(fill=\"both\", expand=True, padx=16, pady=(0, 12))\n\n        quick_tab = tk.Frame(notebook, bg=C[\"bg\"])\n        notebook.add(quick_tab, text=\"Quick Recovery\")\n        quick_body = self._scrollable_section_body(quick_tab)\n        quick_card = tk.LabelFrame(\n            quick_body,\n            text=\"\ud83d\udcc1 Quick Recovery \u2014 Existing Files / \u092e\u094c\u091c\u0942\u0926\u093e \u092b\u093c\u093e\u0907\u0932\u094b\u0902 \u0915\u0940 \u0924\u094d\u0935\u0930\u093f\u0924 \u0930\u093f\u0915\u0935\u0930\u0940\",\n            font=FONTS[\"subhead\"],\n            fg=C[\"accent2\"],\n            bg=C[\"card\"],\n            bd=1,\n            relief=\"flat\",\n        )\n        quick_card.pack(fill=\"x\", padx=14, pady=10)\n        quick_card.columnconfigure(1, weight=1)\n\n        self._data_recovery_quick_disk_var = tk.StringVar(value=\"\")\n        self._data_recovery_filter_var = tk.StringVar(value=\"All\")\n        self._data_recovery_quick_output_var = tk.StringVar(value=os.path.join(os.path.expanduser(\"~\"), \"Desktop\", \"Godawari_DataRecovery_Quick\"))\n        self._data_recovery_quick_disk_combo = ttk.Combobox(quick_card, textvariable=self._data_recovery_quick_disk_var, values=[], width=42, state=\"readonly\")\n        self._data_recovery_quick_disk_combo.pack_forget()\n\n        quick_rows = tk.Frame(quick_card, bg=C[\"card\"])\n        quick_rows.pack(fill=\"x\", padx=10, pady=(8, 2))\n        tk.Label(quick_rows, text=\"Disk / Volume:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._data_recovery_quick_disk_combo = ttk.Combobox(quick_rows, textvariable=self._data_recovery_quick_disk_var, values=[], width=42, state=\"readonly\")\n        self._data_recovery_quick_disk_combo.pack(side=\"left\", padx=(8, 12))\n        tk.Label(quick_rows, text=\"Output Folder:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\")\n        tk.Entry(quick_rows, textvariable=self._data_recovery_quick_output_var, width=48, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).pack(side=\"left\", padx=(8, 8))\n        tk.Button(\n            quick_rows,\n            text=\"Browse\",\n            font=FONTS[\"small\"],\n            bg=C[\"panel\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=10,\n            pady=5,\n            cursor=\"hand2\",\n            command=lambda: self._data_recovery_choose_output(self._data_recovery_quick_output_var),\n        ).pack(side=\"left\")\n\n        filter_row = tk.Frame(quick_card, bg=C[\"card\"])\n        filter_row.pack(fill=\"x\", padx=10, pady=(6, 8))\n        tk.Label(filter_row, text=\"File type filter:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._data_recovery_filter_buttons = {}\n        for icon, label in [(\"\ud83d\uddbc\ufe0f\", \"Photos\"), (\"\ud83c\udfac\", \"Videos\"), (\"\ud83d\udcc4\", \"Documents\"), (\"\ud83d\udddc\ufe0f\", \"Archives\"), (\"\ud83d\udce6\", \"All\")]:\n            btn = tk.Button(\n                filter_row,\n                text=f\"{icon} {label}\",\n                font=FONTS[\"small\"],\n                bg=C[\"panel\"] if label != \"All\" else C[\"btn_chip\"],\n                fg=C[\"text\"],\n                bd=0,\n                padx=10,\n                pady=5,\n                cursor=\"hand2\",\n                command=lambda l=label: self._data_recovery_set_filter(l),\n            )\n            btn.pack(side=\"left\", padx=4)\n            self._data_recovery_filter_buttons[label] = btn\n\n        controls = tk.Frame(quick_card, bg=C[\"card\"])\n        controls.pack(fill=\"x\", padx=10, pady=(6, 8))\n        self._data_recovery_quick_pause_btn = tk.Button(\n            controls,\n            text=\"\u23f8 Pause Scan\",\n            font=FONTS[\"small\"],\n            bg=C[\"warning\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_pause_resume_scan,\n        )\n        self._data_recovery_quick_pause_btn.pack(side=\"left\", padx=(0, 8))\n        self._data_recovery_quick_cancel_btn = tk.Button(\n            controls,\n            text=\"\u2716 Cancel\",\n            font=FONTS[\"small\"],\n            bg=C[\"btn_danger\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_cancel_scan,\n        )\n        self._data_recovery_quick_cancel_btn.pack(side=\"left\", padx=4)\n        self._data_recovery_quick_start_btn = tk.Button(\n            controls,\n            text=\"\u25b6 Start Quick Recovery\",\n            font=FONTS[\"subhead\"],\n            bg=C[\"accent2\"],\n            fg=\"#0A0F1A\",\n            bd=0,\n            padx=14,\n            pady=8,\n            cursor=\"hand2\",\n            command=self._data_recovery_start_quick_recovery,\n        )\n        self._data_recovery_quick_start_btn.pack(side=\"left\", padx=4)\n        tk.Button(\n            controls,\n            text=\"\ud83d\udee0 Auto Repair\",\n            font=FONTS[\"small\"],\n            bg=C[\"btn_chip\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_run_auto_repair,\n        ).pack(side=\"left\", padx=4)\n        tk.Button(\n            controls,\n            text=\"\ud83d\udccb Export HTML Report\",\n            font=FONTS[\"small\"],\n            bg=C[\"btn_info\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_export_report,\n        ).pack(side=\"left\", padx=4)\n\n        self._data_recovery_quick_preview = ttk.Treeview(\n            quick_body,\n            columns=(\"Type\", \"Path\", \"Size\", \"Chance\"),\n            show=\"headings\",\n            height=10,\n            style=\"Custom.Treeview\",\n        )\n        for col, title, width in [(\"Type\", \"Type\", 90), (\"Path\", \"Recovered Path\", 320), (\"Size\", \"Size\", 90), (\"Chance\", \"Chance\", 90)]:\n            self._data_recovery_quick_preview.heading(col, text=title)\n            self._data_recovery_quick_preview.column(col, width=width)\n        self._data_recovery_quick_preview.pack(fill=\"both\", expand=True, padx=14, pady=(0, 10))\n\n        quick_progress = tk.LabelFrame(quick_body, text=\"\ud83d\udcc8 Quick Recovery Progress / \u0928\u093f\u0937\u094d\u0915\u094d\u0930\u093f\u092f \u0938\u094d\u0915\u0948\u0928 \u092a\u094d\u0930\u0917\u0924\u093f\", font=FONTS[\"small\"], fg=C[\"accent2\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        quick_progress.pack(fill=\"x\", padx=14, pady=(0, 10))\n        self._data_recovery_quick_status = tk.Label(quick_progress, text=\"Ready \u2014 choose a source and start the scan.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], anchor=\"w\")\n        self._data_recovery_quick_status.pack(fill=\"x\", padx=10, pady=(8, 2))\n        self._data_recovery_quick_speed = tk.Label(quick_progress, text=\"Speed: 0 MB/s | ETA: --\", font=FONTS[\"small\"], fg=C[\"accent\"], bg=C[\"card\"], anchor=\"w\")\n        self._data_recovery_quick_speed.pack(fill=\"x\", padx=10, pady=(0, 4))\n        self._data_recovery_quick_progress = ttk.Progressbar(quick_progress, maximum=100.0, mode=\"determinate\")\n        self._data_recovery_quick_progress.pack(fill=\"x\", padx=10, pady=(0, 10))\n\n        deep_tab = tk.Frame(notebook, bg=C[\"bg\"])\n        notebook.add(deep_tab, text=\"Deep Recovery\")\n        deep_body = self._scrollable_section_body(deep_tab)\n        deep_card = tk.LabelFrame(\n            deep_body,\n            text=\"\ud83e\uddec Deep Recovery (PhotoRec Style) / \u0917\u0939\u0930\u0940 \u0930\u093f\u0915\u0935\u0930\u0940\",\n            font=FONTS[\"subhead\"],\n            fg=C[\"warning\"],\n            bg=C[\"card\"],\n            bd=1,\n            relief=\"flat\",\n        )\n        deep_card.pack(fill=\"x\", padx=14, pady=10)\n\n        self._data_recovery_deep_source_var = tk.StringVar(value=\"\")\n        self._data_recovery_deep_output_var = tk.StringVar(value=os.path.join(os.path.expanduser(\"~\"), \"Desktop\", \"Godawari_DataRecovery_Deep\"))\n        self._data_recovery_deep_chunk_var = tk.StringVar(value=\"4\")\n        self._data_recovery_deep_depth_var = tk.StringVar(value=\"High\")\n        self._data_recovery_deep_source_combo = ttk.Combobox(deep_card, textvariable=self._data_recovery_deep_source_var, values=[], width=42, state=\"readonly\")\n        self._data_recovery_deep_source_combo.pack_forget()\n\n        deep_rows = tk.Frame(deep_card, bg=C[\"card\"])\n        deep_rows.pack(fill=\"x\", padx=10, pady=(8, 2))\n        tk.Label(deep_rows, text=\"Source:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._data_recovery_deep_source_combo = ttk.Combobox(deep_rows, textvariable=self._data_recovery_deep_source_var, values=[], width=42, state=\"readonly\")\n        self._data_recovery_deep_source_combo.pack(side=\"left\", padx=(8, 12))\n        tk.Label(deep_rows, text=\"Output Folder:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\")\n        tk.Entry(deep_rows, textvariable=self._data_recovery_deep_output_var, width=48, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).pack(side=\"left\", padx=(8, 8))\n        tk.Button(\n            deep_rows,\n            text=\"Browse\",\n            font=FONTS[\"small\"],\n            bg=C[\"panel\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=10,\n            pady=5,\n            cursor=\"hand2\",\n            command=lambda: self._data_recovery_choose_output(self._data_recovery_deep_output_var),\n        ).pack(side=\"left\")\n\n        filters = tk.Frame(deep_card, bg=C[\"card\"])\n        filters.pack(fill=\"x\", padx=10, pady=(6, 8))\n        tk.Label(filters, text=\"Carving targets:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._data_recovery_deep_flags = {\n            \"Photos\": tk.BooleanVar(value=True),\n            \"Videos\": tk.BooleanVar(value=True),\n            \"Documents\": tk.BooleanVar(value=True),\n            \"Archives\": tk.BooleanVar(value=True),\n        }\n        for label in (\"Photos\", \"Videos\", \"Documents\", \"Archives\"):\n            ttk.Checkbutton(filters, text=label, variable=self._data_recovery_deep_flags[label]).pack(side=\"left\", padx=6)\n\n        deep_controls = tk.Frame(deep_card, bg=C[\"card\"])\n        deep_controls.pack(fill=\"x\", padx=10, pady=(6, 8))\n        self._data_recovery_deep_start_btn = tk.Button(\n            deep_controls,\n            text=\"\ud83e\uddec Start Deep Carve\",\n            font=FONTS[\"subhead\"],\n            bg=C[\"warning\"],\n            fg=\"#0A0F1A\",\n            bd=0,\n            padx=14,\n            pady=8,\n            cursor=\"hand2\",\n            command=self._data_recovery_start_deep_recovery,\n        )\n        self._data_recovery_deep_start_btn.pack(side=\"left\", padx=(0, 8))\n        self._data_recovery_deep_pause_btn = tk.Button(\n            deep_controls,\n            text=\"\u23f8 Pause Scan\",\n            font=FONTS[\"small\"],\n            bg=C[\"btn_info\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_pause_resume_scan,\n        )\n        self._data_recovery_deep_pause_btn.pack(side=\"left\", padx=4)\n        self._data_recovery_deep_cancel_btn = tk.Button(\n            deep_controls,\n            text=\"\u2716 Cancel\",\n            font=FONTS[\"small\"],\n            bg=C[\"btn_danger\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_cancel_scan,\n        )\n        self._data_recovery_deep_cancel_btn.pack(side=\"left\", padx=4)\n        tk.Button(\n            deep_controls,\n            text=\"\ud83e\udde9 Preview Candidate\",\n            font=FONTS[\"small\"],\n            bg=C[\"panel\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_preview_selected_candidate,\n        ).pack(side=\"left\", padx=4)\n\n        self._data_recovery_deep_preview = ttk.Treeview(\n            deep_body,\n            columns=(\"Signature\", \"Offset\", \"Size\", \"Chance\"),\n            show=\"headings\",\n            height=8,\n            style=\"Custom.Treeview\",\n        )\n        for col, title, width in [(\"Signature\", \"Signature\", 120), (\"Offset\", \"Offset\", 140), (\"Size\", \"Size\", 100), (\"Chance\", \"Chance\", 100)]:\n            self._data_recovery_deep_preview.heading(col, text=title)\n            self._data_recovery_deep_preview.column(col, width=width)\n        self._data_recovery_deep_preview.pack(fill=\"both\", expand=True, padx=14, pady=(0, 10))\n\n        deep_progress = tk.LabelFrame(deep_body, text=\"\ud83d\udcca Deep Scan Progress / \u0917\u0939\u0930\u0947 \u0938\u094d\u0915\u0948\u0928 \u0915\u0940 \u092a\u094d\u0930\u0917\u0924\u093f\", font=FONTS[\"small\"], fg=C[\"warning\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        deep_progress.pack(fill=\"x\", padx=14, pady=(0, 10))\n        self._data_recovery_deep_status = tk.Label(deep_progress, text=\"Ready \u2014 choose a source and start the scan.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], anchor=\"w\")\n        self._data_recovery_deep_status.pack(fill=\"x\", padx=10, pady=(8, 2))\n        self._data_recovery_deep_speed = tk.Label(deep_progress, text=\"Speed: 0 MB/s | ETA: --\", font=FONTS[\"small\"], fg=C[\"accent\"], bg=C[\"card\"], anchor=\"w\")\n        self._data_recovery_deep_speed.pack(fill=\"x\", padx=10, pady=(0, 4))\n        self._data_recovery_deep_progress = ttk.Progressbar(deep_progress, maximum=100.0, mode=\"determinate\")\n        self._data_recovery_deep_progress.pack(fill=\"x\", padx=10, pady=(0, 10))\n\n        part_tab = tk.Frame(notebook, bg=C[\"bg\"])\n        notebook.add(part_tab, text=\"Partition Recovery\")\n        part_body = self._scrollable_section_body(part_tab)\n        part_card = tk.LabelFrame(\n            part_body,\n            text=\"\ud83d\uddc2\ufe0f Formatted / Lost Partition Recovery / \u092b\u093c\u0949\u0930\u094d\u092e\u0947\u091f\u0947\u0921 \u092f\u093e \u0916\u094b\u0908 \u0939\u0941\u0908 partition \u0930\u093f\u0915\u0935\u0930\u0940\",\n            font=FONTS[\"subhead\"],\n            fg=C[\"accent\"],\n            bg=C[\"card\"],\n            bd=1,\n            relief=\"flat\",\n        )\n        part_card.pack(fill=\"x\", padx=14, pady=10)\n        self._data_recovery_partition_tree = ttk.Treeview(\n            part_body,\n            columns=(\"Partition\", \"Start\", \"End\", \"Type\", \"Status\"),\n            show=\"headings\",\n            height=12,\n            style=\"Custom.Treeview\",\n        )\n        for col, title in [(\"Partition\", \"Partition\"), (\"Start\", \"Start Sector\"), (\"End\", \"End Sector\"), (\"Type\", \"Type\"), (\"Status\", \"Status\")]:\n            self._data_recovery_partition_tree.heading(col, text=title)\n        self._data_recovery_partition_tree.pack(fill=\"both\", expand=True, padx=14, pady=(0, 10))\n        part_controls = tk.Frame(part_card, bg=C[\"card\"])\n        part_controls.pack(fill=\"x\", padx=10, pady=(6, 8))\n        tk.Button(\n            part_controls,\n            text=\"\ud83d\udd0e Refresh Partitions\",\n            font=FONTS[\"small\"],\n            bg=C[\"btn_info\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_refresh_partition_list,\n        ).pack(side=\"left\", padx=(0, 8))\n        tk.Button(\n            part_controls,\n            text=\"\ud83d\udee1 Recover Lost Partition\",\n            font=FONTS[\"small\"],\n            bg=C[\"accent2\"],\n            fg=\"#0A0F1A\",\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_recover_partition_table,\n        ).pack(side=\"left\", padx=4)\n        tk.Button(\n            part_controls,\n            text=\"\ud83d\udccd Verify MBR/GPT\",\n            font=FONTS[\"small\"],\n            bg=C[\"panel\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_verify_partition_table,\n        ).pack(side=\"left\", padx=4)\n\n        adv_tab = tk.Frame(notebook, bg=C[\"bg\"])\n        notebook.add(adv_tab, text=\"Advanced Tools &amp; Imaging\")\n        adv_body = self._scrollable_section_body(adv_tab)\n        adv_card = tk.LabelFrame(\n            adv_body,\n            text=\"\ud83d\udcbe DiskGenius Style Sector Utility / \u0938\u0947\u0915\u094d\u091f\u0930-\u0938\u094d\u0924\u0930\u0940\u092f \u0907\u092e\u0947\u091c\u093f\u0902\u0917 \u091f\u0942\u0932\",\n            font=FONTS[\"subhead\"],\n            fg=C[\"hw_accent\"],\n            bg=C[\"card\"],\n            bd=1,\n            relief=\"flat\",\n        )\n        adv_card.pack(fill=\"x\", padx=14, pady=10)\n\n        self._data_recovery_imaging_disk_var = tk.StringVar(value=\"\")\n        self._data_recovery_start_sector_var = tk.StringVar(value=\"0\")\n        self._data_recovery_end_sector_var = tk.StringVar(value=\"1023\")\n        self._data_recovery_img_output_var = tk.StringVar(value=os.path.join(os.path.expanduser(\"~\"), \"Desktop\", \"Godawari_DataRecovery_Image.img\"))\n        self._data_recovery_imaging_disk_combo = ttk.Combobox(adv_card, textvariable=self._data_recovery_imaging_disk_var, values=[], width=42, state=\"readonly\")\n        self._data_recovery_imaging_disk_combo.pack_forget()\n\n        imaging_rows = tk.Frame(adv_card, bg=C[\"card\"])\n        imaging_rows.pack(fill=\"x\", padx=10, pady=(8, 2))\n        tk.Label(imaging_rows, text=\"Disk:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._data_recovery_imaging_disk_combo = ttk.Combobox(imaging_rows, textvariable=self._data_recovery_imaging_disk_var, values=[], width=42, state=\"readonly\")\n        self._data_recovery_imaging_disk_combo.pack(side=\"left\", padx=(8, 12))\n        tk.Label(imaging_rows, text=\"Start Sector:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\")\n        tk.Entry(imaging_rows, textvariable=self._data_recovery_start_sector_var, width=12, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).pack(side=\"left\", padx=(8, 12))\n        tk.Label(imaging_rows, text=\"End Sector:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\")\n        tk.Entry(imaging_rows, textvariable=self._data_recovery_end_sector_var, width=12, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).pack(side=\"left\", padx=(8, 12))\n        tk.Label(imaging_rows, text=\"Output:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\")\n        tk.Entry(imaging_rows, textvariable=self._data_recovery_img_output_var, width=46, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).pack(side=\"left\", padx=(8, 8))\n        tk.Button(\n            imaging_rows,\n            text=\"Browse\",\n            font=FONTS[\"small\"],\n            bg=C[\"panel\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=10,\n            pady=5,\n            cursor=\"hand2\",\n            command=lambda: self._data_recovery_choose_output(self._data_recovery_img_output_var),\n        ).pack(side=\"left\")\n\n        adv_controls = tk.Frame(adv_card, bg=C[\"card\"])\n        adv_controls.pack(fill=\"x\", padx=10, pady=(6, 8))\n        self._data_recovery_hex_load_btn = tk.Button(\n            adv_controls,\n            text=\"\ud83d\udd0e Load Sector / Hex\",\n            font=FONTS[\"small\"],\n            bg=C[\"btn_info\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_load_sector_hex,\n        )\n        self._data_recovery_hex_load_btn.pack(side=\"left\", padx=(0, 8))\n        tk.Button(\n            adv_controls,\n            text=\"\ud83d\udcbe Create Range .img\",\n            font=FONTS[\"small\"],\n            bg=C[\"accent2\"],\n            fg=\"#0A0F1A\",\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_create_range_img,\n        ).pack(side=\"left\", padx=4)\n        tk.Button(\n            adv_controls,\n            text=\"\ud83d\udda5\ufe0f Full Disk .img\",\n            font=FONTS[\"small\"],\n            bg=C[\"warning\"],\n            fg=\"#0A0F1A\",\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_create_full_disk_img,\n        ).pack(side=\"left\", padx=4)\n        tk.Button(\n            adv_controls,\n            text=\"\ud83d\udcc2 Open Output Folder\",\n            font=FONTS[\"small\"],\n            bg=C[\"panel\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_open_last_output,\n        ).pack(side=\"left\", padx=4)\n        tk.Button(\n            adv_controls,\n            text=\"\ud83e\uddea Use in Existing Recovery\",\n            font=FONTS[\"small\"],\n            bg=C[\"hw_accent\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_route_img_to_existing_recovery,\n        ).pack(side=\"left\", padx=4)\n\n        self._data_recovery_hex_view = scrolledtext.ScrolledText(\n            adv_body,\n            font=FONTS[\"mono\"],\n            bg=C[\"bg\"],\n            fg=C[\"text\"],\n            insertbackground=C[\"text\"],\n            wrap=\"word\",\n            height=18,\n            bd=0,\n            relief=\"flat\",\n        )\n        self._data_recovery_hex_view.pack(fill=\"both\", expand=True, padx=14, pady=(0, 10))\n\n        self._data_recovery_image_chance = tk.Label(\n            adv_card,\n            text=\"Recovery Chance: Low \u2014 image not loaded yet\",\n            font=FONTS[\"small\"],\n            fg=C[\"warning\"],\n            bg=C[\"card\"],\n            anchor=\"w\",\n        )\n        self._data_recovery_image_chance.pack(fill=\"x\", padx=10, pady=(6, 0))\n        self._data_recovery_auto_repair_label = tk.Label(\n            adv_card,\n            text=\"Auto Repair: Ready for JPG / PNG / PDF / DOCX headers\",\n            font=FONTS[\"small\"],\n            fg=C[\"text_dim\"],\n            bg=C[\"card\"],\n            anchor=\"w\",\n        )\n        self._data_recovery_auto_repair_label.pack(fill=\"x\", padx=10, pady=(2, 8))\n\n        self._data_recovery_refresh_disk_sources()\n        self._data_recovery_refresh_partition_list()\n        self._data_recovery_set_filter(\"All\")\n        self._data_recovery_set_recovery_chance(\"Low\")\n        self._data_recovery_update_summary(\"Source\", \"Ready\")\n        self._data_recovery_update_summary(\"Recovered\", \"0 files\")\n        self._data_recovery_update_summary(\"Image\", \"No image yet\")\n\n        return frame\n\n    def _data_recovery_refresh_disk_sources(self):\n        try:\n            self._populate_recovery_disks()\n        except Exception:\n            pass\n\n        disk_values = list(getattr(self, \"_recovery_disk_map\", {}).keys())\n        if not disk_values:\n            disk_values = self._get_recovery_disk_values()\n\n        uniq = []\n        for src in disk_values:\n            if src not in uniq:\n                uniq.append(src)\n\n        for combo in (\n            getattr(self, \"_data_recovery_quick_disk_combo\", None),\n            getattr(self, \"_data_recovery_deep_source_combo\", None),\n            getattr(self, \"_data_recovery_imaging_disk_combo\", None),\n        ):\n            if combo is not None:\n                combo.config(values=uniq)\n\n        current = uniq[0] if uniq else \"\"\n        if current:\n            self._data_recovery_quick_disk_var.set(current)\n            self._data_recovery_deep_source_var.set(current)\n            self._data_recovery_imaging_disk_var.set(current)\n\n    def _data_recovery_set_filter(self, label):\n        self._data_recovery_filter_var.set(label)\n        self._data_recovery_quick_status.config(text=f\"Filter updated to {label}.\")\n        for name, btn in getattr(self, \"_data_recovery_filter_buttons\", {}).items():\n            bg = C[\"btn_chip\"] if name == label else C[\"panel\"]\n            try:\n                btn.config(bg=bg)\n            except Exception:\n                pass\n        if label == \"All\":\n            self._data_recovery_set_recovery_chance(\"Medium\")\n        elif label in (\"Photos\", \"Videos\"):\n            self._data_recovery_set_recovery_chance(\"High\")\n        else:\n            self._data_recovery_set_recovery_chance(\"Medium\")\n\n    def _data_recovery_update_summary(self, key, value):\n        if key in self._data_recovery_summary_labels:\n            self._data_recovery_summary_labels[key].config(text=value)\n\n    def _data_recovery_set_recovery_chance(self, level):\n        color = C[\"success\"] if level == \"High\" else C[\"warning\"] if level == \"Medium\" else C[\"error\"]\n        self._data_recovery_summary_labels[\"Chance\"].config(text=level, fg=color)\n        if hasattr(self, \"_data_recovery_image_chance\"):\n            self._data_recovery_image_chance.config(text=f\"Recovery Chance: {level}\", fg=color)\n\n    def _data_recovery_choose_output(self, var):\n        path = filedialog.asksaveasfilename(defaultextension=\".img\", filetypes=[(\"Image File\", \"*.img\"), (\"All Files\", \"*.*\")], title=\"Choose output file\")\n        if path:\n            var.set(path)\n\n    def _data_recovery_get_source_path(self, source_value):\n        source_value = (source_value or \"\").strip()\n        if not source_value:\n            return \"\"\n        if hasattr(self, \"_resolve_disk_path\"):\n            return self._resolve_disk_path(source_value)\n        return source_value.split(\" (\")[0]\n\n    def _data_recovery_refresh_partition_list(self):\n        if not hasattr(self, \"_data_recovery_partition_tree\"):\n            return\n        for iid in self._data_recovery_partition_tree.get_children():\n            self._data_recovery_partition_tree.delete(iid)\n        source = self._data_recovery_get_source_path(self._data_recovery_imaging_disk_var.get() or self._data_recovery_quick_disk_var.get())\n        if not source:\n            return\n        partitions = self._data_recovery_parse_partitions(source)\n        if not partitions:\n            self._data_recovery_partition_tree.insert(\"\", \"end\", values=(\"No partition table detected\", \"\", \"\", \"\", \"Unknown\"))\n            if hasattr(self, \"partition_tree\"):\n                self.partition_tree.delete(*self.partition_tree.get_children())\n            return\n        for part in partitions:\n            self._data_recovery_partition_tree.insert(\"\", \"end\", values=(part[\"name\"], part[\"start\"], part[\"end\"], part[\"type\"], part[\"status\"]))\n        if hasattr(self, \"partition_tree\"):\n            for iid in self.partition_tree.get_children():\n                self.partition_tree.delete(iid)\n            for part in partitions:\n                self.partition_tree.insert(\"\", \"end\", values=(part[\"name\"], part[\"start\"], part[\"end\"], part[\"type\"], part[\"status\"]))\n\n    def _data_recovery_parse_partitions(self, source_path):\n        source_path = self._data_recovery_get_source_path(source_path)\n        try:\n            first_sector = self._forensic_read_at(source_path, 0, 512)\n        except Exception:\n            return []\n        if len(first_sector) &lt; 512 or first_sector[510:512] != b\"\\x55\\xAA\":\n            return []\n        partitions = []\n        for idx in range(4):\n            entry = first_sector[446 + idx * 16:446 + (idx + 1) * 16]\n            part_type = entry[4]\n            start = int.from_bytes(entry[8:12], \"little\")\n            size = int.from_bytes(entry[12:16], \"little\")\n            if part_type and size:\n                partitions.append({\n                    \"name\": f\"Partition {idx + 1}\",\n                    \"start\": str(start),\n                    \"end\": str(start + size - 1),\n                    \"type\": f\"0x{part_type:02X}\",\n                    \"status\": \"Candidate\",\n                })\n        return partitions\n\n    def _data_recovery_read_sector_bytes(self, source_path, start_sector, end_sector):\n        try:\n            start_sector = int(start_sector)\n            end_sector = int(end_sector)\n            if end_sector &lt; start_sector:\n                start_sector, end_sector = end_sector, start_sector\n            source_path = self._data_recovery_get_source_path(source_path)\n            raw = self._forensic_read_at(source_path, start_sector * 512, (end_sector - start_sector + 1) * 512)\n            return raw\n        except Exception as exc:\n            messagebox.showerror(\"Sector Read Error\", str(exc))\n            return b\"\"\n\n    def _data_recovery_format_hex_dump(self, raw_bytes):\n        if not raw_bytes:\n            return \"No bytes available.\"\n        lines = []\n        for offset in range(0, len(raw_bytes), 16):\n            chunk = raw_bytes[offset:offset + 16]\n            hex_text = \" \".join(f\"{b:02X}\" for b in chunk)\n            ascii_text = \"\".join(chr(b) if 32 &lt;= b &lt; 127 else \".\" for b in chunk)\n            lines.append(f\"{offset:08X}  {hex_text:&lt;47}  {ascii_text}\")\n        return \"\\n\".join(lines)\n\n    def _data_recovery_load_sector_hex(self):\n        source = self._data_recovery_imaging_disk_var.get()\n        if not source:\n            messagebox.showwarning(\"No Disk Selected\", \"Select a disk or raw volume first.\")\n            return\n        try:\n            start = int(self._data_recovery_start_sector_var.get())\n            end = int(self._data_recovery_end_sector_var.get())\n        except Exception:\n            messagebox.showwarning(\"Invalid Sector Range\", \"Enter numeric start and end sectors.\")\n            return\n        sector_count = abs(end - start) + 1\n        if sector_count &gt; 4096:\n            messagebox.showwarning(\n                \"Range Too Large\",\n                \"Hex preview ek baar me max 4096 sectors (2 MB) read karega.\\n\"\n                \"Bade range ke liye 'Create Range IMG' use karein.\"\n            )\n            return\n\n        def load_hex():\n            try:\n                if hasattr(self, \"_data_recovery_hex_load_btn\"):\n                    self.after(0, lambda: self._data_recovery_hex_load_btn.config(state=\"disabled\"))\n                raw = self._data_recovery_read_sector_bytes(source, start, end)\n                formatted = self._data_recovery_format_hex_dump(raw)\n                self.after(0, lambda: self._data_recovery_hex_view.delete(\"1.0\", tk.END))\n                self.after(0, lambda: self._data_recovery_hex_view.insert(tk.END, formatted))\n                self.after(0, lambda: self._data_recovery_update_summary(\"Image\", f\"{start} -&gt; {end}\"))\n                self.after(0, lambda: self._data_recovery_set_recovery_chance(\"Medium\"))\n            finally:\n                if hasattr(self, \"_data_recovery_hex_load_btn\"):\n                    self.after(0, lambda: self._data_recovery_hex_load_btn.config(state=\"normal\"))\n\n        self._launch_job(\"data_recovery_load_hex\", load_hex)\n\n    def _data_recovery_create_sector_range_img(self, source_path, start_sector, end_sector, output_path, progress_callback=None, confirm=True):\n        if not source_path or not output_path:\n            return {\"ok\": False, \"message\": \"Source or output path missing.\"}\n        try:\n            start_sector = int(start_sector)\n            end_sector = int(end_sector)\n            if end_sector &lt; start_sector:\n                start_sector, end_sector = end_sector, start_sector\n        except Exception:\n            return {\"ok\": False, \"message\": \"Invalid sector values.\"}\n        if confirm and not messagebox.askyesno(\"Raw Imaging Confirmation\", \"This will create a raw sector image from the selected range. Continue only if you have authorization.\"):\n            return {\"ok\": False, \"message\": \"User cancelled imaging.\"}\n\n        source_path = self._data_recovery_get_source_path(source_path)\n        if _is_raw_device_path(source_path) and not self._ensure_admin_for_raw_recovery(source_path):\n            return {\"ok\": False, \"message\": \"Administrator rights required for raw imaging.\"}\n\n        output_path = os.path.abspath(output_path)\n        os.makedirs(os.path.dirname(output_path) or \".\", exist_ok=True)\n        try:\n            start_byte = start_sector * 512\n            end_byte = (end_sector + 1) * 512\n            remaining = max(0, end_byte - start_byte)\n            total_bytes = remaining\n            copied = 0\n            current = start_byte\n            file_source = source_path and os.path.exists(source_path) and not _is_raw_device_path(source_path)\n            src = open(source_path, \"rb\") if file_source else None\n            try:\n                if src:\n                    src.seek(start_byte)\n                with open(output_path, \"wb\") as dst:\n                    while remaining &gt; 0:\n                        if self._data_recovery_state.get(\"cancelled\", False):\n                            return {\"ok\": False, \"message\": \"Imaging cancelled by user.\"}\n                        while self._data_recovery_state.get(\"paused\", False):\n                            time.sleep(0.12)\n                            if self._data_recovery_state.get(\"cancelled\", False):\n                                return {\"ok\": False, \"message\": \"Imaging cancelled by user.\"}\n                        chunk_len = min(1024 * 1024, remaining)\n                        chunk = src.read(chunk_len) if src else self._forensic_read_at(source_path, current, chunk_len)\n                        if not chunk:\n                            break\n                        dst.write(chunk)\n                        current += len(chunk)\n                        remaining -= len(chunk)\n                        copied += len(chunk)\n                        if progress_callback:\n                            progress_callback(copied, total_bytes, output_path)\n            finally:\n                if src:\n                    src.close()\n            if remaining &gt; 0:\n                return {\"ok\": False, \"message\": \"Imaging stopped early: source shorter than requested range.\"}\n            self._data_recovery_state[\"last_img\"] = output_path\n            return {\"ok\": True, \"message\": f\"Image created: {output_path}\", \"path\": output_path}\n        except Exception as exc:\n            return {\"ok\": False, \"message\": str(exc)}\n\n    def _data_recovery_create_range_img(self):\n        source = self._data_recovery_imaging_disk_var.get()\n        output_path = self._data_recovery_img_output_var.get()\n        start_sector = self._data_recovery_start_sector_var.get()\n        end_sector = self._data_recovery_end_sector_var.get()\n        if not source:\n            messagebox.showwarning(\"No Disk Selected\", \"Select a disk or raw volume first.\")\n            return\n        if not output_path:\n            messagebox.showwarning(\"No Output Path\", \"Choose an output image path.\")\n            return\n        if self._data_recovery_state.get(\"running\", False):\n            messagebox.showwarning(\"Data Recovery Busy\", \"Ek recovery/imaging job already chal raha hai. Pehle usko cancel/complete hone dein.\")\n            return\n        if not messagebox.askyesno(\"Raw Imaging Confirmation\", \"This will create a raw sector image from the selected range. Continue only if you have authorization?\"):\n            return\n        self._data_recovery_state[\"running\"] = True\n        self._data_recovery_state[\"paused\"] = False\n        self._data_recovery_state[\"cancelled\"] = False\n        self._data_recovery_quick_progress[\"value\"] = 0\n        self._data_recovery_quick_status.config(text=\"Range imaging queued...\")\n        self._launch_job(\"data_recovery_range_img\", self._data_recovery_img_worker, source, start_sector, end_sector, output_path, \"Range Image\")\n\n    def _data_recovery_img_worker(self, source, start_sector, end_sector, output_path, label):\n        started = time.time()\n\n        def progress(copied, total, path):\n            pct = (copied / total * 100.0) if total else 0.0\n            elapsed = max(0.1, time.time() - started)\n            speed = copied / elapsed\n            remaining = max(0, total - copied)\n            eta = int(remaining / speed) if speed &gt; 0 else 0\n            msg = (\n                f\"{label}: {pct:.1f}% | {self._fmt_size(copied)} / {self._fmt_size(total)} | \"\n                f\"Elapsed {self._format_seconds(elapsed)} | Left {self._format_seconds(eta)}\"\n            )\n            self.after(0, lambda m=msg, p=pct: (\n                self._data_recovery_quick_progress.config(value=p),\n                self._data_recovery_deep_progress.config(value=p),\n                self._data_recovery_quick_status.config(text=m),\n                self._data_recovery_deep_status.config(text=m),\n                self._data_recovery_quick_speed.config(text=f\"Speed: {self._fmt_size(speed)}/s | ETA: {self._format_seconds(eta)}\"),\n                self._data_recovery_deep_speed.config(text=f\"Speed: {self._fmt_size(speed)}/s | ETA: {self._format_seconds(eta)}\"),\n            ))\n\n        result = self._data_recovery_create_sector_range_img(\n            source, start_sector, end_sector, output_path,\n            progress_callback=progress,\n            confirm=False,\n        )\n        if result[\"ok\"]:\n            self.after(0, lambda: (\n                self._data_recovery_update_summary(\"Image\", os.path.basename(result[\"path\"])),\n                self._data_recovery_quick_progress.config(value=100),\n                self._data_recovery_deep_progress.config(value=100),\n                self._data_recovery_quick_status.config(text=result[\"message\"]),\n                self._data_recovery_deep_status.config(text=result[\"message\"]),\n                messagebox.showinfo(f\"{label} Created\", result[\"message\"]),\n            ))\n        else:\n            self.after(0, lambda: (\n                self._data_recovery_quick_status.config(text=result[\"message\"]),\n                self._data_recovery_deep_status.config(text=result[\"message\"]),\n                messagebox.showerror(f\"{label} Failed\", result[\"message\"]),\n            ))\n        self._data_recovery_state[\"running\"] = False\n\n    def _data_recovery_create_full_disk_img(self):\n        source = self._data_recovery_imaging_disk_var.get() or self._data_recovery_quick_disk_var.get()\n        output_path = self._data_recovery_img_output_var.get()\n        if not source:\n            messagebox.showwarning(\"No Disk Selected\", \"Select a disk or raw volume first.\")\n            return\n        if not output_path:\n            messagebox.showwarning(\"No Output Path\", \"Choose an output image path.\")\n            return\n        if self._data_recovery_state.get(\"running\", False):\n            messagebox.showwarning(\"Data Recovery Busy\", \"Ek recovery/imaging job already chal raha hai. Pehle usko cancel/complete hone dein.\")\n            return\n        try:\n            source_path = self._data_recovery_get_source_path(source)\n            size = _disk_source_size(source_path)\n        except Exception:\n            size = None\n        if not size:\n            messagebox.showwarning(\"Size Error\", \"Unable to determine disk size.\")\n            return\n        if not messagebox.askyesno(\"Full Disk Imaging\", f\"Create a full raw image of {source}? This is a raw disk operation and should only be done with authorization.\"):\n            return\n        self._data_recovery_state[\"running\"] = True\n        self._data_recovery_state[\"paused\"] = False\n        self._data_recovery_state[\"cancelled\"] = False\n        self._data_recovery_quick_progress[\"value\"] = 0\n        self._data_recovery_quick_status.config(text=\"Full disk imaging queued...\")\n        self._launch_job(\"data_recovery_full_img\", self._data_recovery_img_worker, source, 0, max(0, size // 512 - 1), output_path, \"Full Disk Image\")\n\n    def _data_recovery_open_last_output(self):\n        path = self._data_recovery_state.get(\"last_img\", \"\")\n        if not path or not os.path.exists(path):\n            messagebox.showwarning(\"No Image\", \"Create or load an image first.\")\n            return\n        try:\n            subprocess.Popen([\"explorer\", os.path.dirname(path)])\n        except Exception as exc:\n            messagebox.showerror(\"Open Failed\", str(exc))\n\n    def _data_recovery_route_img_to_existing_recovery(self):\n        if not self._data_recovery_state.get(\"last_img\"):\n            messagebox.showwarning(\"No Image\", \"Create or load a .img first.\")\n            return\n        img_path = self._data_recovery_state.get(\"last_img\", \"\")\n        routed = []\n        for attr in (\"raw_disk_var\", \"deep_recovery_source_var\", \"photorec_source_var\", \"mft_source_var\"):\n            var = getattr(self, attr, None)\n            if var is not None:\n                try:\n                    var.set(img_path)\n                    routed.append(attr)\n                except Exception:\n                    pass\n        messagebox.showinfo(\n            \"Use in Existing Recovery\",\n            f\"Image route ho gayi:\\n{img_path}\\n\\nUpdated fields: {', '.join(routed) if routed else 'HDD/File Recovery section open hote hi source set karein.'}\"\n        )\n        self._show_section(\"hdd_repair\")\n\n    def _data_recovery_signature_map(self, kind):\n        return {\n            \"Photos\": [b\"\\xff\\xd8\\xff\", b\"\\x89PNG\\r\\n\\x1a\\n\", b\"GIF87a\", b\"GIF89a\"],\n            \"Videos\": [b\"RIFF\", b\"\\x00\\x00\\x00\\x18ftyp\", b\"\\x1A\\x45\\xDF\\xA3\"],\n            \"Documents\": [b\"%PDF-\", b\"PK\\x03\\x04\", b\"Microsoft Word\", b\"\\xd0\\xcf\\x11\\xe0\\xa1\\xb1\\x1a\\xe1\"],\n            \"Archives\": [b\"PK\\x03\\x04\", b\"Rar!\", b\"7z\\xBC\\xAF\\x27\\x1C\", b\"\\x42\\x5A\\x68\"],\n        }.get(kind, [])\n\n    def _data_recovery_find_signature_offsets(self, data, kind):\n        offsets = []\n        for signature in self._data_recovery_signature_map(kind):\n            start = 0\n            while True:\n                idx = data.find(signature, start)\n                if idx == -1:\n                    break\n                offsets.append((idx, signature))\n                start = idx + 1\n        return offsets\n\n    def _data_recovery_carve_candidate(self, source_path, offset, signature, kind):\n        try:\n            with open(self._data_recovery_get_source_path(source_path), \"rb\") as handle:\n                handle.seek(max(0, offset))\n                payload = handle.read(512 * 1024)\n        except Exception:\n            return None\n        if not payload:\n            return None\n        ext = \".bin\"\n        if kind == \"Photos\":\n            ext = \".jpg\" if signature == b\"\\xff\\xd8\\xff\" else \".png\" if signature == b\"\\x89PNG\\r\\n\\x1a\\n\" else \".gif\"\n        elif kind == \"Videos\":\n            ext = \".mp4\" if signature == b\"\\x00\\x00\\x00\\x18ftyp\" else \".avi\" if signature == b\"RIFF\" else \".mkv\"\n        elif kind == \"Documents\":\n            if signature == b\"%PDF-\":\n                ext = \".pdf\"\n            elif signature == b\"PK\\x03\\x04\":\n                ext = \".docx\"\n            elif signature == b\"\\xd0\\xcf\\x11\\xe0\\xa1\\xb1\\x1a\\xe1\":\n                ext = \".doc\"\n        elif kind == \"Archives\":\n            if signature == b\"PK\\x03\\x04\":\n                ext = \".zip\"\n            elif signature == b\"Rar!\":\n                ext = \".rar\"\n            elif signature == b\"7z\\xBC\\xAF\\x27\\x1C\":\n                ext = \".7z\"\n            elif signature == b\"\\x42\\x5A\\x68\":\n                ext = \".bz2\"\n        return payload, ext\n\n    def _data_recovery_add_preview_row(self, mode, kind, offset, size, path):\n        tree = self._data_recovery_quick_preview if mode == \"quick\" else self._data_recovery_deep_preview\n        tree.insert(\"\", \"end\", values=(kind, f\"0x{offset:X}\", self._fmt_size(size), \"Medium\"))\n        self._data_recovery_last_preview_path = path\n        self._data_recovery_state.setdefault(\"preview\", []).append({\n            \"kind\": kind,\n            \"offset\": offset,\n            \"size\": size,\n            \"path\": path,\n        })\n        # Update recovered counters and UI summary\n        recovered_count = len(tree.get_children())\n        self._data_recovery_update_summary(\"Recovered\", f\"{recovered_count} files\")\n        if mode == \"deep\":\n            # maintain a numeric recovered counter for deep scans for progress reporting\n            try:\n                self._data_recovery_state[\"recovered\"] = int(self._data_recovery_state.get(\"recovered\", 0)) + 1\n            except Exception:\n                self._data_recovery_state[\"recovered\"] = recovered_count\n\n    def _data_recovery_preview_selected_candidate(self):\n        path = getattr(self, \"_data_recovery_last_preview_path\", \"\")\n        if not path or not os.path.exists(path):\n            messagebox.showwarning(\"Preview\", \"Select a recovered candidate first.\")\n            return\n        try:\n            subprocess.Popen([\"explorer\", path])\n        except Exception as exc:\n            messagebox.showerror(\"Preview Error\", str(exc))\n\n    def _data_recovery_run_auto_repair(self):\n        path = getattr(self, \"_data_recovery_last_preview_path\", \"\")\n        if not path or not os.path.exists(path):\n            messagebox.showwarning(\"No Candidate\", \"Run a recovery scan first to create a candidate.\")\n            return\n        repaired = self._data_recovery_auto_repair_file(path)\n        if repaired:\n            self._data_recovery_auto_repair_label.config(text=f\"Auto Repair: repaired -&gt; {os.path.basename(repaired)}\")\n            messagebox.showinfo(\"Auto Repair\", f\"Repair complete:\\n{repaired}\")\n        else:\n            messagebox.showwarning(\"Auto Repair\", \"No repair rule matched the recovered file.\")\n\n    def _data_recovery_auto_repair_file(self, path):\n        try:\n            data = Path(path).read_bytes()\n        except Exception:\n            return None\n        ext = Path(path).suffix.lower()\n        if ext == \".jpg\" and not data.endswith(b\"\\xff\\xd9\"):\n            data += b\"\\xff\\xd9\"\n        elif ext == \".png\" and b\"IEND\" not in data:\n            data += b\"\\x00\\x00\\x00\\x00IEND\\xaeB`\\x82\"\n        elif ext == \".pdf\" and b\"%%EOF\" not in data:\n            data += b\"\\n%%EOF\\n\"\n        elif ext == \".zip\" and not data.endswith(b\"PK\\x05\\x06\"):\n            data += b\"PK\\x05\\x06\\x00\\x00\\x00\\x00\"\n        else:\n            return None\n        repaired_path = str(Path(path).with_name(Path(path).stem + \"_repaired\" + ext))\n        Path(repaired_path).write_bytes(data)\n        return repaired_path\n\n    def _data_recovery_pause_resume_scan(self):\n        state = self._data_recovery_state\n        if not state.get(\"running\", False):\n            return\n        state[\"paused\"] = not state.get(\"paused\", False)\n        label = \"\u25b6 Resume Scan\" if state[\"paused\"] else \"\u23f8 Pause Scan\"\n        if hasattr(self, \"_data_recovery_quick_pause_btn\"):\n            self._data_recovery_quick_pause_btn.config(text=label)\n        if hasattr(self, \"_data_recovery_deep_pause_btn\"):\n            self._data_recovery_deep_pause_btn.config(text=label)\n        if state[\"paused\"]:\n            self._data_recovery_quick_status.config(text=\"Scan paused.\")\n            self._data_recovery_deep_status.config(text=\"Scan paused.\")\n            self._data_recovery_record_history(\"pause_scan\", {\"task_id\": self._data_recovery_state.get(\"task_id\")})\n        else:\n            self._data_recovery_quick_status.config(text=\"Scan resumed.\")\n            self._data_recovery_deep_status.config(text=\"Scan resumed.\")\n            self._data_recovery_record_history(\"resume_scan\", {\"task_id\": self._data_recovery_state.get(\"task_id\")})\n        task_id = self._data_recovery_state.get(\"task_id\")\n        if task_id:\n            if state[\"paused\"]:\n                self._task_pause(task_id)\n            else:\n                self._task_resume(task_id)\n\n    def _data_recovery_cancel_scan(self):\n        state = self._data_recovery_state\n        if not state.get(\"running\", False):\n            return\n        state[\"cancelled\"] = True\n        state[\"paused\"] = False\n        self._data_recovery_quick_status.config(text=\"Scan cancellation requested...\")\n        self._data_recovery_deep_status.config(text=\"Scan cancellation requested...\")\n        if hasattr(self, \"_data_recovery_quick_pause_btn\"):\n            self._data_recovery_quick_pause_btn.config(text=\"\u25b6 Resume Scan\", state=\"disabled\")\n        if hasattr(self, \"_data_recovery_deep_pause_btn\"):\n            self._data_recovery_deep_pause_btn.config(text=\"\u25b6 Resume Scan\", state=\"disabled\")\n        if hasattr(self, \"_data_recovery_quick_cancel_btn\"):\n            self._data_recovery_quick_cancel_btn.config(state=\"disabled\")\n        if hasattr(self, \"_data_recovery_deep_cancel_btn\"):\n            self._data_recovery_deep_cancel_btn.config(state=\"disabled\")\n        task_id = self._data_recovery_state.get(\"task_id\")\n        if task_id:\n            self._task_cancel(task_id)\n        self._data_recovery_record_history(\"cancel_scan\", {\"task_id\": task_id})\n\n    def _data_recovery_record_history(self, action, details=None):\n        entry = {\n            \"timestamp\": datetime.datetime.now().isoformat(timespec=\"seconds\"),\n            \"action\": action,\n            \"details\": details or {},\n        }\n        self._data_recovery_state.setdefault(\"history\", []).append(entry)\n        self._data_recovery_state.setdefault(\"queue\", []).append(entry)\n\n    def _data_recovery_run_quick_scan_worker(self, source_path, output_folder, filter_label, task_id=None):\n        cancelled = False\n        try:\n            source_path = self._data_recovery_get_source_path(source_path)\n            if not source_path or not os.path.exists(source_path):\n                raise RuntimeError(\"Selected quick recovery source is missing.\")\n            if _is_raw_device_path(source_path):\n                raise PermissionError(\"Quick Recovery works on mounted volumes. Use Deep Recovery for raw disk sources.\")\n\n            def _should_stop():\n                nonlocal cancelled\n                if self._data_recovery_state.get(\"cancelled\", False) or self._task_is_cancelled(task_id):\n                    cancelled = True\n                    return True\n                return False\n\n            def _wait_for_resume():\n                if task_id:\n                    try:\n                        self._task_wait_if_paused(task_id)\n                    except RuntimeError:\n                        nonlocal cancelled\n                        cancelled = True\n                        return True\n                return False\n\n            allowed = None\n            if filter_label == \"Photos\":\n                allowed = {\"jpg\", \"jpeg\", \"png\", \"gif\", \"bmp\", \"tif\", \"tiff\"}\n            elif filter_label == \"Videos\":\n                allowed = {\"mp4\", \"mov\", \"mkv\", \"avi\", \"wmv\", \"flv\", \"mpeg\", \"mpg\"}\n            elif filter_label == \"Documents\":\n                allowed = {\"pdf\", \"doc\", \"docx\", \"xls\", \"xlsx\", \"ppt\", \"pptx\", \"txt\", \"rtf\", \"csv\", \"json\"}\n            elif filter_label == \"Archives\":\n                allowed = {\"zip\", \"7z\", \"rar\", \"tar\", \"gz\", \"bz2\", \"xz\"}\n\n            start = time.time()\n            processed = 0\n            scanned = 0\n            copied = 0\n            total_candidates = 0\n            last_ui = 0\n            skip_dirs = {\"$recycle.bin\", \"system volume information\", \"windows\", \"program files\", \"program files (x86)\"}\n            for root, dirs, files in os.walk(source_path):\n                if _should_stop():\n                    return\n                if _wait_for_resume():\n                    return\n                while self._data_recovery_state.get(\"paused\", False):\n                    if _should_stop():\n                        return\n                    if _wait_for_resume():\n                        return\n                    time.sleep(0.12)\n                dirs[:] = [\n                    d for d in dirs\n                    if not d.startswith(\".\") and d.lower() not in skip_dirs\n                    and not os.path.islink(os.path.join(root, d))\n                ]\n                total_candidates += len(files)\n                for name in files:\n                    if _should_stop():\n                        return\n                    if _wait_for_resume():\n                        return\n                    while self._data_recovery_state.get(\"paused\", False):\n                        if _should_stop():\n                            return\n                        if _wait_for_resume():\n                            return\n                        time.sleep(0.12)\n                    src_path = os.path.join(root, name)\n                    scanned += 1\n                    try:\n                        size_bytes = os.path.getsize(src_path)\n                    except Exception:\n                        continue\n                    ext = os.path.splitext(name)[1].lstrip(\".\").lower()\n                    if allowed is not None and ext not in allowed:\n                        now = time.time()\n                        if now - last_ui &gt;= 1.0:\n                            elapsed = max(0.1, now - start)\n                            speed = (processed / (1024 * 1024)) / elapsed\n                            pct = min(99.0, (scanned / max(1, total_candidates)) * 100.0)\n                            self.after(0, lambda p=pct, s=speed, r=copied: self._data_recovery_update_scan_ui(\"quick\", p, r, s, \"--\"))\n                            if task_id:\n                                self._task_update_progress(task_id, pct)\n                            last_ui = now\n                        continue\n                    rel_path = os.path.relpath(src_path, source_path)\n                    out_path = os.path.join(output_folder, rel_path)\n                    os.makedirs(os.path.dirname(out_path), exist_ok=True)\n                    if not os.path.exists(out_path):\n                        with open(src_path, \"rb\") as src, open(out_path, \"wb\") as dst:\n                            while True:\n                                if _should_stop():\n                                    return\n                                if _wait_for_resume():\n                                    return\n                                while self._data_recovery_state.get(\"paused\", False):\n                                    if _should_stop():\n                                        return\n                                    if _wait_for_resume():\n                                        return\n                                    time.sleep(0.12)\n                                chunk = src.read(1024 * 1024)\n                                if not chunk:\n                                    break\n                                dst.write(chunk)\n                                processed += len(chunk)\n                                now = time.time()\n                                if now - last_ui &gt;= 1.0:\n                                    elapsed = max(0.1, now - start)\n                                    speed = (processed / (1024 * 1024)) / elapsed\n                                    pct = min(99.0, (scanned / max(1, total_candidates)) * 100.0)\n                                    self.after(0, lambda p=pct, s=speed, r=copied: self._data_recovery_update_scan_ui(\"quick\", p, r, s, \"--\"))\n                                    if task_id:\n                                        self._task_update_progress(task_id, pct)\n                                    last_ui = now\n                        try:\n                            shutil.copystat(src_path, out_path)\n                        except Exception:\n                            pass\n                    else:\n                        processed += size_bytes\n                    copied += 1\n                    self.after(0, lambda _kind=ext.upper() or \"FILE\", _offset=0, _size=size_bytes, _path=out_path: self._data_recovery_add_preview_row(\"quick\", _kind, _offset, _size, _path))\n                    if copied % 10 == 0:\n                        elapsed = max(0.1, time.time() - start)\n                        speed = (processed / (1024 * 1024)) / elapsed\n                        file_rate = copied / elapsed\n                        remaining = max(0, total_candidates - copied)\n                        eta = \"--\" if file_rate &lt;= 0 else f\"{max(0, int(remaining / file_rate))} s\"\n                        pct = min(100.0, (copied / max(1, total_candidates)) * 100.0)\n                        self.after(0, lambda p=pct, s=speed, e=eta, r=copied: self._data_recovery_update_scan_ui(\"quick\", p, r, s, e))\n                        if task_id:\n                            self._task_update_progress(task_id, pct)\n            self.after(0, lambda c=copied: self._data_recovery_finish_scan(\"quick\", c))\n        except Exception as exc:\n            self.after(0, lambda e=exc: messagebox.showerror(\"Quick Recovery Error\", str(e)))\n        finally:\n            if cancelled:\n                self.after(0, lambda c=copied: self._data_recovery_finish_scan(\"quick\", c, cancelled=True))\n\n    def _data_recovery_start_quick_recovery(self):\n        source = self._data_recovery_get_source_path(self._data_recovery_quick_disk_var.get())\n        if not source:\n            messagebox.showwarning(\"No Source\", \"Select a disk or volume first.\")\n            return\n        if not os.path.exists(source):\n            messagebox.showwarning(\"No Source\", \"The selected source path does not exist.\")\n            return\n        if _is_raw_device_path(source):\n            messagebox.showwarning(\"Quick Recovery\", \"Quick Recovery works on mounted volumes. Use Deep Recovery for raw disk sources.\")\n            return\n        if self._data_recovery_state.get(\"running\", False):\n            messagebox.showwarning(\"Data Recovery Busy\", \"Ek recovery/imaging job already chal raha hai. Pehle usko cancel/complete hone dein.\")\n            return\n        if not messagebox.askyesno(\"Quick Recovery Warning\", \"Quick recovery will copy matching files to the selected destination. Continue only on an authorized target.\"):\n            return\n        output_folder = self._data_recovery_quick_output_var.get()\n        os.makedirs(output_folder, exist_ok=True)\n        self._data_recovery_state[\"running\"] = True\n        self._data_recovery_state[\"paused\"] = False\n        self._data_recovery_state[\"cancelled\"] = False\n        self._data_recovery_state[\"session_id\"] = self.recovery_session_manager.start(\"data_recovery_quick\", {\n            \"source\": source,\n            \"output\": output_folder,\n            \"filter\": self._data_recovery_filter_var.get(),\n        })\n        self._data_recovery_state[\"history\"] = self._data_recovery_state.get(\"history\", [])\n        self._data_recovery_quick_preview.delete(*self._data_recovery_quick_preview.get_children())\n        self._data_recovery_quick_status.config(text=\"Quick recovery started.\")\n        self._data_recovery_quick_progress.config(value=0)\n        self._data_recovery_quick_speed.config(text=\"Speed: 0 MB/s | ETA: --\")\n        self._data_recovery_update_summary(\"Source\", source)\n        self._data_recovery_update_summary(\"Recovered\", \"0 files\")\n        if hasattr(self, \"_data_recovery_quick_start_btn\"):\n            try:\n                self._data_recovery_quick_start_btn.config(state=\"disabled\")\n            except Exception:\n                pass\n        if hasattr(self, \"_data_recovery_quick_pause_btn\"):\n            self._data_recovery_quick_pause_btn.config(state=\"normal\", text=\"\u23f8 Pause Scan\")\n        if hasattr(self, \"_data_recovery_quick_cancel_btn\"):\n            self._data_recovery_quick_cancel_btn.config(state=\"normal\")\n        task_id = self._launch_job(\"data_recovery_quick_scan\", self._data_recovery_run_quick_scan_worker, source, output_folder, self._data_recovery_filter_var.get())\n        self._data_recovery_state[\"task_id\"] = task_id\n        self._data_recovery_record_history(\"start_quick_recovery\", {\"task_id\": task_id, \"session_id\": self._data_recovery_state.get(\"session_id\")})\n\n    def _data_recovery_run_deep_scan_worker(self, source_path, output_folder, filters, task_id=None):\n        cancelled = False\n        try:\n            source_path = self._data_recovery_get_source_path(source_path)\n            if not source_path:\n                raise RuntimeError(\"Deep recovery source missing.\")\n            if _is_raw_device_path(source_path) and not self._ensure_admin_for_raw_recovery(source_path):\n                return\n\n            def _should_stop():\n                nonlocal cancelled\n                if self._data_recovery_state.get(\"cancelled\", False) or self._task_is_cancelled(task_id):\n                    cancelled = True\n                    return True\n                return False\n\n            def _wait_for_resume():\n                if task_id:\n                    try:\n                        self._task_wait_if_paused(task_id)\n                    except RuntimeError:\n                        nonlocal cancelled\n                        cancelled = True\n                        return True\n                return False\n\n            recovered = 0\n            self._data_recovery_state[\"recovered\"] = 0\n\n            def progress_cb(message):\n                text = str(message or \"\")[:180]\n                pct = 0\n                try:\n                    m = re.search(r\"(\\d{1,3})%\", text)\n                    if m:\n                        pct = int(m.group(1))\n                except Exception:\n                    pct = 0\n                self.after(0, lambda: self._data_recovery_update_scan_ui(\"deep\", pct, recovered, 0.0, \"--\"))\n                self.after(0, lambda: self._data_recovery_deep_status.config(text=text))\n                if task_id:\n                    self._task_update_progress(task_id, pct)\n\n            result = multi_pass_recovery(source_path, output_folder, progress_callback=progress_cb)\n            recovered = 0\n            for entry in result.get(\"files\", []):\n                if _should_stop():\n                    return\n                if _wait_for_resume():\n                    return\n                path = entry.get(\"path\")\n                if not path or not os.path.exists(path):\n                    continue\n                size = os.path.getsize(path)\n                kind = entry.get(\"file_type\") or os.path.splitext(path)[1].lstrip(\".\").upper() or \"BIN\"\n                offset = entry.get(\"offset\", 0)\n                recovered += 1\n                self.after(0, lambda _kind=kind, _offset=offset, _size=size, _path=path: self._data_recovery_add_preview_row(\"deep\", _kind, _offset, _size, _path))\n            self.after(0, lambda c=recovered: self._data_recovery_finish_scan(\"deep\", c))\n        except Exception as exc:\n            self.after(0, lambda e=exc: messagebox.showerror(\"Deep Scan Error\", str(e)))\n        finally:\n            if cancelled:\n                self.after(0, lambda c=recovered: self._data_recovery_finish_scan(\"deep\", c, cancelled=True))\n\n    def _data_recovery_start_deep_recovery(self):\n        source = self._data_recovery_get_source_path(self._data_recovery_deep_source_var.get())\n        if not source:\n            messagebox.showwarning(\"No Source\", \"Select a disk or volume first.\")\n            return\n        if not os.path.exists(source) and not _is_raw_device_path(source):\n            messagebox.showwarning(\"No Source\", \"The selected source path does not exist.\")\n            return\n        if _is_raw_device_path(source) and not self._ensure_admin_for_raw_recovery(source):\n            return\n        if self._data_recovery_state.get(\"running\", False):\n            messagebox.showwarning(\"Data Recovery Busy\", \"Ek recovery/imaging job already chal raha hai. Pehle usko cancel/complete hone dein.\")\n            return\n        filters = [kind for kind, var in self._data_recovery_deep_flags.items() if var.get()]\n        output_folder = self._data_recovery_deep_output_var.get()\n        os.makedirs(output_folder, exist_ok=True)\n        self._data_recovery_state[\"running\"] = True\n        self._data_recovery_state[\"paused\"] = False\n        self._data_recovery_state[\"cancelled\"] = False\n        self._data_recovery_state[\"session_id\"] = self.recovery_session_manager.start(\"data_recovery_deep\", {\n            \"source\": source,\n            \"output\": output_folder,\n            \"filters\": filters,\n        })\n        self._data_recovery_deep_preview.delete(*self._data_recovery_deep_preview.get_children())\n        self._data_recovery_deep_status.config(text=\"Deep carve started.\")\n        self._data_recovery_deep_progress.config(value=0)\n        self._data_recovery_deep_speed.config(text=\"Speed: 0 MB/s | ETA: --\")\n        self._data_recovery_update_summary(\"Source\", source)\n        self._data_recovery_update_summary(\"Recovered\", \"0 files\")\n        if hasattr(self, \"_data_recovery_deep_start_btn\"):\n            try:\n                self._data_recovery_deep_start_btn.config(state=\"disabled\")\n            except Exception:\n                pass\n        if hasattr(self, \"_data_recovery_deep_pause_btn\"):\n            self._data_recovery_deep_pause_btn.config(state=\"normal\", text=\"\u23f8 Pause Scan\")\n        if hasattr(self, \"_data_recovery_deep_cancel_btn\"):\n            self._data_recovery_deep_cancel_btn.config(state=\"normal\")\n        task_id = self._launch_job(\"data_recovery_deep_scan\", self._data_recovery_run_deep_scan_worker, source, output_folder, filters)\n        self._data_recovery_state[\"task_id\"] = task_id\n        self._data_recovery_record_history(\"start_deep_recovery\", {\"task_id\": task_id, \"session_id\": self._data_recovery_state.get(\"session_id\")})\n\n    def _data_recovery_update_scan_ui(self, mode, pct, found, speed, eta):\n        if mode == \"quick\":\n            self._data_recovery_quick_progress.config(value=max(0, min(100.0, pct)))\n            self._data_recovery_quick_status.config(text=f\"Recovered {found} candidates.\")\n            self._data_recovery_quick_speed.config(text=f\"Speed: {speed:.2f} MB/s | ETA: {eta}\")\n        else:\n            self._data_recovery_deep_progress.config(value=max(0, min(100.0, pct)))\n            self._data_recovery_deep_status.config(text=f\"Recovered {found} candidates.\")\n            self._data_recovery_deep_speed.config(text=f\"Speed: {speed:.2f} MB/s | ETA: {eta}\")\n        self._data_recovery_update_summary(\"Recovered\", f\"{found} files\")\n\n    def _data_recovery_finish_scan(self, mode, found, cancelled=False):\n        self._data_recovery_state[\"running\"] = False\n        display_text = \"\"\n        if cancelled:\n            display_text = f\"Scan cancelled. {found} candidate(s) recovered before stop.\"\n        elif mode == \"quick\":\n            display_text = f\"Quick scan complete. {found} candidate(s) recovered.\"\n        else:\n            display_text = f\"Deep carve complete. {found} candidate(s) recovered.\"\n\n        if mode == \"quick\":\n            self._data_recovery_quick_status.config(text=display_text)\n            if not cancelled:\n                self._data_recovery_quick_progress.config(value=100.0 if found &gt;= 1 else 0)\n            if hasattr(self, \"_data_recovery_quick_start_btn\"):\n                try:\n                    self._data_recovery_quick_start_btn.config(state=\"normal\")\n                except Exception:\n                    pass\n            if hasattr(self, \"_data_recovery_quick_pause_btn\"):\n                self._data_recovery_quick_pause_btn.config(state=\"disabled\", text=\"\u23f8 Pause Scan\")\n            if hasattr(self, \"_data_recovery_quick_cancel_btn\"):\n                self._data_recovery_quick_cancel_btn.config(state=\"disabled\")\n        else:\n            self._data_recovery_deep_status.config(text=display_text)\n            if not cancelled:\n                self._data_recovery_deep_progress.config(value=100.0 if found &gt;= 1 else 0)\n            if hasattr(self, \"_data_recovery_deep_start_btn\"):\n                try:\n                    self._data_recovery_deep_start_btn.config(state=\"normal\")\n                except Exception:\n                    pass\n            if hasattr(self, \"_data_recovery_deep_pause_btn\"):\n                self._data_recovery_deep_pause_btn.config(state=\"disabled\", text=\"\u23f8 Pause Scan\")\n            if hasattr(self, \"_data_recovery_deep_cancel_btn\"):\n                self._data_recovery_deep_cancel_btn.config(state=\"disabled\")\n\n        self._data_recovery_state[\"cancelled\"] = False\n        self._data_recovery_state[\"task_id\"] = None\n        self._data_recovery_record_history(\n            \"finish_scan\",\n            {\n                \"mode\": mode,\n                \"found\": found,\n                \"cancelled\": cancelled,\n                \"session_id\": self._data_recovery_state.get(\"session_id\"),\n            },\n        )\n        self._data_recovery_set_recovery_chance(\"High\" if found &gt;= 1 else \"Low\")\n        self._data_recovery_generate_report_html()\n\n    def _data_recovery_recover_partition_table(self):\n        source = self._data_recovery_imaging_disk_var.get() or self._data_recovery_quick_disk_var.get()\n        if not source:\n            messagebox.showwarning(\"No Disk\", \"Select a disk or raw volume first.\")\n            return\n        if not messagebox.askyesno(\"Partition Recovery Warning\", \"Recovering partition metadata is a forensic operation. Continue only if authorized and an image exists.\"):\n            return\n        partitions = self._data_recovery_parse_partitions(self._data_recovery_get_source_path(source))\n        if not partitions:\n            messagebox.showinfo(\"Partition Recovery\", \"No partition candidates detected.\")\n            return\n        self._data_recovery_refresh_partition_list()\n        messagebox.showinfo(\"Partition Recovery\", f\"Recovered {len(partitions)} partition candidate(s).\")\n\n    def _data_recovery_verify_partition_table(self):\n        source = self._data_recovery_get_source_path(self._data_recovery_imaging_disk_var.get() or self._data_recovery_quick_disk_var.get())\n        if not source:\n            messagebox.showwarning(\"No Disk\", \"Select a disk or raw volume first.\")\n            return\n        partitions = self._data_recovery_parse_partitions(source)\n        self._data_recovery_refresh_partition_list()\n        if partitions:\n            messagebox.showinfo(\"Partition Verification\", f\"Partition table appears present: {len(partitions)} candidate entry/entries found.\")\n        else:\n            messagebox.showwarning(\"Partition Verification\", \"No valid MBR signature found.\")\n\n    def _data_recovery_export_report(self):\n        report_path = os.path.join(os.path.expanduser(\"~\"), \"Desktop\", \"Godawari_DataRecovery_Report.html\")\n        try:\n            self._data_recovery_generate_report_html(report_path)\n            self._data_recovery_state[\"last_report\"] = report_path\n            messagebox.showinfo(\"Report Saved\", f\"HTML report saved to:\\n{report_path}\")\n        except Exception as exc:\n            messagebox.showerror(\"Report Error\", str(exc))\n\n    def _data_recovery_generate_report_html(self, output_path=None):\n        output_path = output_path or os.path.join(os.path.expanduser(\"~\"), \"Desktop\", \"Godawari_DataRecovery_Report.html\")\n        os.makedirs(os.path.dirname(output_path), exist_ok=True)\n        preview = self._data_recovery_state.get(\"preview\", [])\n        total = len(preview)\n        pie = f\"conic-gradient({C['accent']} 0% 45%, {C['accent2']} 45% 75%, {C['warning']} 75% 92%, {C['hw_accent']} 92% 100%)\"\n        html_doc = f\"\"\"\n\n\n\n\nGodawari Data Recovery Report\n\nbody {{ font-family: Segoe UI, Arial, sans-serif; background:#0A0F1A; color:#F0F4FA; margin:0; padding:20px; }}\nh1 {{ color:#FFB347; }}\n.card {{ background:#121826; border:1px solid #2A3A5A; border-radius:12px; padding:16px; margin-bottom:16px; }}\n.summary {{ display:flex; gap:16px; flex-wrap:wrap; }}\n.metric {{ background:#182032; border-radius:12px; padding:14px 18px; min-width:160px; }}\n.metric strong {{ display:block; font-size:20px; margin-top:6px; }}\n.chart {{ width:240px; height:240px; border-radius:50%; background:{pie}; }}\ntable {{ width:100%; border-collapse:collapse; margin-top:10px; }}\nth, td {{ border-bottom:1px solid #2A3A5A; padding:8px; text-align:left; }}\nth {{ color:#FFB347; }}\n\n\n\n\n\n  \nGodawari Data Recovery Report\n  \nGenerated on {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}.\n\n\n\n  \nRecovered Candidates{total}\n  \nRecovery ChanceHigh\n  \nLast Image{os.path.basename(self._data_recovery_state.get('last_img', 'none'))}\n\n\n\nRecovery Distribution\n\n\n\nCandidate Table\nTypeOffsetSizePath\n\"\"\"\n        for item in preview:\n            html_doc += f\"{html.escape(str(item.get('kind', '')))}{item.get('offset', 0)}{self._fmt_size(item.get('size', 0))}{html.escape(str(item.get('path', '')))}\"\n        html_doc += \"\"\n        Path(output_path).write_text(html_doc, encoding=\"utf-8\")\n        self._data_recovery_state[\"last_report\"] = output_path\n        return output_path\n\n    def _build_printer_driver_merged(self, parent):\n        return self._build_tabbed_merger(parent, [\n            (\"\ud83d\udda8  Printer Fixer + Sharing\", \"_build_printer\"),\n            (\"\ud83d\udce6  Driver Checker\", \"_build_driver\"),\n        ])\n\n    def _build_uninstall_backup_merged(self, parent):\n        return self._build_tabbed_merger(parent, [\n            (\"\ud83d\uddd1  Batch Uninstall\", \"_build_uninstaller\"),\n            (\"\ud83d\udcbe  Backup / Restore\", \"_build_backup\"),\n        ])\n\n    def _build_realtime_security(self, parent):\n        return self._build_tabbed_merger(parent, [\n            (\"Security Audit\", \"_build_password_audit\"),\n            (\"Process Scanner\", \"_build_suspicion_scanner\"),\n        ])\n\n    def _build_dup_report_merged(self, parent):\n        return self._build_tabbed_merger(parent, [\n            (\"\ud83d\udd0d  Duplicate Finder\", \"_build_dupfinder\"),\n            (\"\ud83d\udcca  Export Report\", \"_build_report\"),\n        ])\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  END MERGED SECTION BUILDERS\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _build_statusbar(self):\n        sb = tk.Frame(self, bg=C[\"panel\"], height=28)\n        sb.pack(side=\"bottom\", fill=\"x\")\n        tk.Frame(sb, bg=C[\"accent\"], height=1).pack(side=\"top\", fill=\"x\")\n        self.status_lbl = tk.Label(sb, text=\"\u25cf Ready\", font=FONTS[\"small\"], fg=C[\"accent\"], bg=C[\"panel\"])\n        self.status_lbl.pack(side=\"left\", padx=12)\n        self.cpu_lbl = tk.Label(sb, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"])\n        self.ram_lbl = tk.Label(sb, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"])\n        self.disk_lbl = tk.Label(sb, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"])\n        self.security_lbl = tk.Label(sb, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"])\n        self.task_lbl = tk.Label(sb, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"])\n        self.task_lbl.pack(side=\"right\", padx=12)\n        self.security_lbl.pack(side=\"right\", padx=12)\n        self.disk_lbl.pack(side=\"right\", padx=12)\n        self.ram_lbl.pack(side=\"right\", padx=4)\n        self.cpu_lbl.pack(side=\"right\", padx=4)\n        self._update_statusbar()\n\n    def _update_statusbar(self):\n        try:\n            cpu = psutil.cpu_percent(interval=None)\n            ram = psutil.virtual_memory().percent\n            disk = psutil.disk_usage(\"C:\\\\\").percent\n            health = self._calculate_global_health()\n            security_status = \"Secure\" if health[\"per_category\"].get(\"security\", 100) &gt;= 80 else \"Alert\"\n            active_tasks = len([t for t in self._task_manager.values() if t.get(\"status\") == \"running\"])\n            self.cpu_lbl.config(text=f\"CPU: {cpu:.1f}%\", fg=C[\"error\"] if cpu &gt; 80 else C[\"text_dim\"])\n            self.ram_lbl.config(text=f\"RAM: {ram:.1f}%\", fg=C[\"error\"] if ram &gt; 85 else C[\"text_dim\"])\n            self.disk_lbl.config(text=f\"Disk: {disk:.1f}%\", fg=C[\"warning\"] if disk &gt; 85 else C[\"text_dim\"])\n            self.security_lbl.config(text=f\"Security: {security_status}\", fg=C[\"success\"] if security_status == \"Secure\" else C[\"error\"])\n            self.task_lbl.config(text=f\"Active Tasks: {active_tasks}\", fg=C[\"accent\"] if active_tasks else C[\"text_dim\"])\n        except Exception:\n            pass\n        self.after(2000, self._update_statusbar)\n\n    def _build_footer(self):\n        footer = tk.Frame(self, bg=C[\"header_bg\"], height=24)\n        footer.pack(side=\"bottom\", fill=\"x\")\n        tk.Label(footer, text=\"\u00a9 2025 Godawari Computers | v11.0 Safety &amp; Recovery | Developer: Shravan Shrimali\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"header_bg\"]).pack(pady=3)\n\n    # ---------- CORE HELPERS ----------\n    def _set_status(self, msg, color=None):\n        self.status_lbl.config(text=f\"\u25cf {msg}\", fg=color or C[\"accent\"])\n\n    def _log(self, msg, level=\"INFO\", path=None, size=None):\n        ts = datetime.datetime.now().strftime(\"%H:%M:%S\")\n        colors = {\"INFO\": C[\"text\"], \"OK\": C[\"success\"], \"WARN\": C[\"warning\"], \"ERR\": C[\"error\"], \"CRITICAL\": C[\"error\"]}\n        color = colors.get(level, C[\"text\"])\n        if path:\n            msg += f\"\\n   \ud83d\udccd Path: {path}\"\n        if size:\n            msg += f\"\\n   \ud83d\udce6 Size: {size}\"\n        line = self._fix_text(f\"[{ts}] [{level:4s}] {msg}\")\n        self.log_lines.append((line, color))\n        if hasattr(self, \"log_text\"):\n            self.log_text.config(state=\"normal\")\n            self.log_text.insert(\"end\", line + \"\\n\", f\"lvl_{level}\")\n            self.log_text.tag_config(f\"lvl_{level}\", foreground=color)\n            self.log_text.see(\"end\")\n            self.log_text.config(state=\"disabled\")\n        try:\n            self._write_enterprise_log(self._enterprise_log_file, line, level)\n            if level in (\"ERR\", \"CRITICAL\"):\n                self._write_enterprise_log(self._enterprise_error_log, line, level)\n        except Exception:\n            pass\n        # Structured logging to runtime store\n        try:\n            if getattr(self, \"structured_logger\", None):\n                try:\n                    self.structured_logger.log(level, msg, {\"path\": path, \"size\": size})\n                except Exception:\n                    pass\n        except Exception:\n            pass\n\n    def _fix_text(self, value):\n        if not isinstance(value, str):\n            return value\n        if any(t in value for t in (\"\\u00e2\", \"\\u00f0\", \"\\u00c2\", \"\u00c3\u00a2\", \"\u00c3\u00b0\", \"\u00c3\u201a\")):\n            try:\n                return value.encode(\"cp1252\", errors=\"ignore\").decode(\"utf-8\", errors=\"ignore\")\n            except:\n                return value\n        return value\n\n    def _sanitize_ui_texts(self):\n        def walk(widget):\n            try:\n                text = widget.cget(\"text\")\n                fixed = self._fix_text(text)\n                if fixed != text:\n                    widget.config(text=fixed)\n            except:\n                pass\n            for child in widget.winfo_children():\n                walk(child)\n        walk(self)\n\n    def _dpi_px(self, value):\n        try:\n            scaling = float(self.tk.call(\"tk\", \"scaling\"))\n            factor = max(0.85, min(1.45, scaling / 1.3333333333))\n            return max(1, int(round(value * factor)))\n        except Exception:\n            return int(value)\n\n    def _bind_scoped_mousewheel(self, widget, canvas, units=3):\n        if not getattr(self, \"_scroll_mousewheel_targets\", None):\n            self._scroll_mousewheel_targets = {}\n\n        self._scroll_mousewheel_targets[widget] = (canvas, units)\n        self._scroll_mousewheel_targets[canvas] = (canvas, units)\n\n        def _wheel(event):\n            target = event.widget\n            targets = getattr(self, \"_scroll_mousewheel_targets\", {})\n            while target is not None:\n                if target in targets:\n                    canvas_target, unit_target = targets[target]\n                    try:\n                        if getattr(event, \"num\", None) == 4:\n                            canvas_target.yview_scroll(-unit_target, \"units\")\n                        elif getattr(event, \"num\", None) == 5:\n                            canvas_target.yview_scroll(unit_target, \"units\")\n                        else:\n                            step = int(-1 * (event.delta / 120))\n                            canvas_target.yview_scroll(step * unit_target, \"units\")\n                    except Exception:\n                        pass\n                    return \"break\"\n                target = getattr(target, \"master\", None)\n            return None\n\n        if not getattr(self, \"_mousewheel_binding_installed\", False):\n            self._mousewheel_binding_installed = True\n            self.bind_all(\"\", _wheel, add=\"+\")\n            self.bind_all(\"\", _wheel, add=\"+\")\n            self.bind_all(\"\", _wheel, add=\"+\")\n\n    def _scrollable_section_body(self, parent, bg=None):\n        \"\"\"Create a responsive scrollable section with proper width management.\n        \n        ENGINEERING FIX #4: Improved canvas+scrollbar layout to prevent content clipping.\n        Uses the same pattern as the fixed sidebar for consistency.\n        \"\"\"\n        bg = bg or C[\"bg\"]\n        outer = tk.Frame(parent, bg=bg)\n        outer.pack(fill=\"both\", expand=True)\n        \n        # Create canvas and scrollbar\n        canvas = tk.Canvas(outer, bg=bg, highlightthickness=0, borderwidth=0)\n        yscroll = ttk.Scrollbar(outer, orient=\"vertical\", command=canvas.yview)\n        \n        # Create body frame with proper sizing\n        body = tk.Frame(canvas, bg=bg)\n        \n        # Embed body in canvas\n        win = canvas.create_window((0, 0), window=body, anchor=\"nw\")\n\n        def _on_body_configure(event=None):\n            \"\"\"Update scroll region when body content changes.\"\"\"\n            try:\n                canvas.configure(scrollregion=canvas.bbox(\"all\"))\n                # Get available width (canvas width, not including scrollbar)\n                available_width = canvas.winfo_width()\n                if available_width &gt; 1:\n                    # Set window width to match canvas width\n                    canvas.itemconfig(win, width=available_width)\n            except tk.TclError:\n                pass  # Canvas destroyed\n\n        def _on_canvas_configure(event):\n            \"\"\"Update scroll region when canvas is resized.\"\"\"\n            try:\n                # Ensure window width matches available canvas space\n                canvas.itemconfig(win, width=event.width)\n                canvas.configure(scrollregion=canvas.bbox(\"all\"))\n            except tk.TclError:\n                pass  # Canvas destroyed\n\n        # Bind configuration events\n        body.bind(\"\", _on_body_configure)\n        canvas.bind(\"\", _on_canvas_configure)\n        \n        # Configure canvas scrolling\n        canvas.configure(yscrollcommand=yscroll.set)\n        \n        # Pack scrollbar first (right), then canvas (left) for proper z-ordering\n        yscroll.pack(side=\"right\", fill=\"y\", expand=False)  # expand=False prevents scrollbar from stretching\n        canvas.pack(side=\"left\", fill=\"both\", expand=True)\n        \n        # Setup mousewheel scrolling\n        self._bind_scoped_mousewheel(body, canvas)\n        body._scroll_canvas = canvas\n        body._scroll_outer = outer\n        return body\n\n    def _set_uninst_progress(self, pct=None, text=None, color=None):\n        def _do():\n            try:\n                if pct is not None and hasattr(self, \"uninst_progress_var\"):\n                    pct_float = max(0, min(100, float(pct)))\n                    self.uninst_progress_var.set(pct_float)\n                    if pct_float &lt;= 0 or not getattr(self, \"_uninst_progress_started_at\", None):\n                        self._uninst_progress_started_at = time.time()\n                    elapsed = max(0.0, time.time() - float(getattr(self, \"_uninst_progress_started_at\", time.time())))\n                    if pct_float &gt; 0:\n                        total_est = elapsed / (pct_float / 100.0)\n                        left = max(0.0, total_est - elapsed)\n                        total_txt = self._format_seconds(total_est)\n                        left_txt = self._format_seconds(left)\n                    else:\n                        total_txt = \"--\"\n                        left_txt = \"--\"\n                    if hasattr(self, \"uninst_timing_lbl\"):\n                        self.uninst_timing_lbl.config(\n                            text=f\"Elapsed: {self._format_seconds(elapsed)} | Left: {left_txt} | Total: {total_txt}\"\n                        )\n                    if pct_float &gt;= 100:\n                        self._uninst_progress_started_at = None\n                if text is not None and hasattr(self, \"uninst_status\"):\n                    self.uninst_status.config(text=\"  \" + self._fix_text(str(text)), fg=color or C[\"accent2\"])\n            except Exception:\n                pass\n\n        if threading.current_thread() is threading.main_thread():\n            _do()\n        else:\n            self.after(0, _do)\n\n    def _check_uninst_control(self):\n        if getattr(self, \"_uninst_cancel_flag\", False):\n            raise InterruptedError(\"User cancelled uninstall scan\")\n        paused_notice = False\n        while getattr(self, \"_uninst_pause_flag\", False):\n            if getattr(self, \"_uninst_cancel_flag\", False):\n                raise InterruptedError(\"User cancelled uninstall scan\")\n            if not paused_notice:\n                paused_notice = True\n                self._set_uninst_progress(text=\"Scan paused. Press Resume to continue.\", color=C[\"warning\"])\n            time.sleep(0.15)\n\n    def _pause_resume_uninst_scan(self):\n        self._uninst_pause_flag = not getattr(self, \"_uninst_pause_flag\", False)\n        if hasattr(self, \"uninst_pause_btn\"):\n            self.uninst_pause_btn.config(text=\"Resume Scan\" if self._uninst_pause_flag else \"Pause Scan\")\n        self._set_uninst_progress(\n            text=\"Scan paused. Press Resume to continue.\" if self._uninst_pause_flag else \"Scan resumed.\",\n            color=C[\"warning\"] if self._uninst_pause_flag else C[\"accent4\"],\n        )\n\n    def _stop_uninst_scan(self):\n        self._uninst_cancel_flag = True\n        self._set_uninst_progress(text=\"Stop requested. Current safe checkpoint will finish first.\", color=C[\"warning\"])\n\n    def _leftover_record(self, ftype, path, confidence=70, risk=None, source=\"\", action=\"delete\", meta=None):\n        ftype = str(ftype or \"ITEM\").upper()\n        path = str(path or \"\")\n        if risk is None:\n            if ftype in {\"REG\", \"SERVICE\", \"TASK\", \"STARTUP\"}:\n                risk = \"Risky\"\n            elif ftype in {\"SHORTCUT\"}:\n                risk = \"Safe\"\n            else:\n                risk = \"Safe\"\n        try:\n            confidence = int(confidence)\n        except Exception:\n            confidence = 60\n        return {\n            \"type\": ftype,\n            \"path\": path,\n            \"risk\": risk,\n            \"confidence\": max(0, min(100, confidence)),\n            \"source\": source,\n            \"action\": action,\n            \"meta\": meta or {},\n        }\n\n    def _leftover_parts(self, item):\n        if isinstance(item, dict):\n            return (\n                str(item.get(\"type\", \"ITEM\")),\n                str(item.get(\"path\", \"\")),\n                str(item.get(\"risk\", \"\")),\n                int(item.get(\"confidence\", 0) or 0),\n                item.get(\"meta\", {}) or {},\n            )\n        try:\n            ftype, path = item\n            return str(ftype), str(path), \"Risky\" if str(ftype).upper() == \"REG\" else \"Safe\", 60, {}\n        except Exception:\n            return \"ITEM\", str(item), \"Risky\", 0, {}\n\n    def _add_leftover_item(self, found, seen, ftype, path, confidence=70, risk=None, source=\"\", action=\"delete\", meta=None):\n        if not path:\n            return\n        key = (str(ftype).upper(), str(path).lower())\n        if key in seen:\n            return\n        seen.add(key)\n        found.append(self._leftover_record(ftype, path, confidence, risk, source, action, meta))\n\n    def _native_delete_file(self, path):\n        try:\n            from ctypes import wintypes\n            ctypes.windll.kernel32.DeleteFileW.argtypes = [wintypes.LPCWSTR]\n            ctypes.windll.kernel32.DeleteFileW.restype = wintypes.BOOL\n            return bool(ctypes.windll.kernel32.DeleteFileW(str(path)))\n        except Exception:\n            return False\n\n    def _native_remove_empty_dir(self, path):\n        try:\n            from ctypes import wintypes\n            ctypes.windll.kernel32.RemoveDirectoryW.argtypes = [wintypes.LPCWSTR]\n            ctypes.windll.kernel32.RemoveDirectoryW.restype = wintypes.BOOL\n            return bool(ctypes.windll.kernel32.RemoveDirectoryW(str(path)))\n        except Exception:\n            return False\n\n    def _native_delete_service(self, service_name):\n        try:\n            from ctypes import wintypes\n            advapi = ctypes.windll.advapi32\n            advapi.OpenSCManagerW.argtypes = [wintypes.LPCWSTR, wintypes.LPCWSTR, wintypes.DWORD]\n            advapi.OpenSCManagerW.restype = wintypes.HANDLE\n            advapi.OpenServiceW.argtypes = [wintypes.HANDLE, wintypes.LPCWSTR, wintypes.DWORD]\n            advapi.OpenServiceW.restype = wintypes.HANDLE\n            advapi.DeleteService.argtypes = [wintypes.HANDLE]\n            advapi.DeleteService.restype = wintypes.BOOL\n            advapi.CloseServiceHandle.argtypes = [wintypes.HANDLE]\n            advapi.CloseServiceHandle.restype = wintypes.BOOL\n            SC_MANAGER_CONNECT = 0x0001\n            DELETE = 0x00010000\n            SERVICE_STOP = 0x0020\n            SERVICE_QUERY_STATUS = 0x0004\n            scm = advapi.OpenSCManagerW(None, None, SC_MANAGER_CONNECT)\n            if not scm:\n                return False, \"OpenSCManagerW failed\"\n            try:\n                svc = advapi.OpenServiceW(scm, str(service_name), DELETE | SERVICE_STOP | SERVICE_QUERY_STATUS)\n                if not svc:\n                    return False, \"OpenServiceW failed\"\n                try:\n                    ok = bool(advapi.DeleteService(svc))\n                    return ok, \"\" if ok else \"DeleteService failed\"\n                finally:\n                    advapi.CloseServiceHandle(svc)\n            finally:\n                advapi.CloseServiceHandle(scm)\n        except Exception as e:\n            return False, str(e)\n\n    def _delete_leftover_path(self, path, ftype):\n        ftype = str(ftype or \"\").upper()\n        if ftype == \"FOLDER\":\n            blocked, reason = _is_dangerous_cleanup_target(path)\n            if blocked:\n                raise PermissionError(reason)\n            if self._native_remove_empty_dir(path):\n                return\n            shutil.rmtree(path, ignore_errors=False)\n            return\n        if ftype in {\"FILE\", \"SHORTCUT\"}:\n            if self._native_delete_file(path):\n                return\n            os.remove(path)\n\n    def _normalize_uninstall_command(self, item, quiet=True):\n        cmd = (item.get(\"quiet\") if quiet else \"\") or item.get(\"uninst\", \"\") or \"\"\n        cmd = str(cmd).strip()\n        if not cmd:\n            return \"\"\n        low = cmd.lower()\n        if \"msiexec\" in low:\n            product = re.search(r\"\\{[0-9a-fA-F\\-]{36}\\}\", cmd)\n            if product:\n                cmd = f\"msiexec.exe /x {product.group(0)}\"\n            elif \" /i\" in low or low.endswith(\"/i\"):\n                cmd = re.sub(r\"(?i)\\s/i\\s*\", \" /x \", cmd)\n            if quiet and \"/qn\" not in cmd.lower() and \"/quiet\" not in cmd.lower():\n                cmd += \" /qn\"\n            if quiet and \"/norestart\" not in cmd.lower():\n                cmd += \" /norestart\"\n        return cmd\n\n    def _command_requires_shell(self, cmd):\n        if not isinstance(cmd, str):\n            return False\n        text = cmd.strip()\n        lower = text.lower()\n        metachars = (\"|\", \"&amp;&amp;\", \"||\", \"&gt;\", \"&lt;\")\n        builtins = (\"start \", \"rd \", \"del \", \"copy \", \"move \", \"echo \")\n        return (\n            any(token in text for token in metachars)\n            or lower.startswith(builtins)\n            or \"%\" in text\n        )\n\n    def _run_cmd(self, cmd, shell=None, timeout=120):\n        if shell is None:\n            shell = True\n        started = time.time()\n        if isinstance(cmd, (list, tuple)):\n            try:\n                result = safe_run(cmd, timeout=timeout)\n                self._audit_event(\"safe_command\", {\n                    \"cmd\": result.args[:20],\n                    \"rc\": result.returncode,\n                    \"timeout_s\": timeout,\n                    \"elapsed_ms\": result.elapsed_ms,\n                    \"timed_out\": result.timed_out,\n                    \"output_tail\": result.output[-300:],\n                })\n                return result.output, result.returncode\n            except Exception as e:\n                return str(e), -1\n        actual_shell = bool(shell and self._command_requires_shell(cmd))\n        if shell and actual_shell:\n            self._audit_event(\"restricted_shell_command_legacy\", {\n                \"cmd\": str(cmd)[:500],\n                \"note\": \"Shell kept only for legacy commands that require cmd.exe semantics.\",\n            })\n        elif shell:\n            self._audit_event(\"legacy_string_command_safened\", {\n                \"cmd\": str(cmd)[:500],\n                \"note\": \"Shell bypassed; migrate caller to list args/safe_run.\",\n            })\n        try:\n            startupinfo = None\n            creationflags = 0\n            if sys.platform == \"win32\":\n                startupinfo = subprocess.STARTUPINFO()\n                startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW\n                creationflags = subprocess.CREATE_NO_WINDOW\n            result = subprocess.run(\n                cmd,\n                shell=actual_shell,\n                capture_output=True,\n                text=True,\n                timeout=timeout,\n                encoding=\"utf-8\",\n                errors=\"replace\",\n                startupinfo=startupinfo,\n                creationflags=creationflags,\n            )\n            output = (result.stdout or \"\").strip()\n            err = (result.stderr or \"\").strip()\n            if err:\n                output = f\"{output}\\n{err}\".strip()\n            self._audit_event(\"command\", {\n                \"cmd\": str(cmd)[:500],\n                \"rc\": result.returncode,\n                \"timeout_s\": timeout,\n                \"elapsed_ms\": int((time.time() - started) * 1000),\n                \"output_tail\": output[-300:],\n            })\n            return output, result.returncode\n        except subprocess.TimeoutExpired:\n            self._audit_event(\"command_timeout\", {\n                \"cmd\": str(cmd)[:500],\n                \"timeout_s\": timeout,\n                \"elapsed_ms\": int((time.time() - started) * 1000),\n            })\n            return f\"Command timed out: {cmd}\", -1\n        except Exception as e:\n            self._audit_event(\"command_error\", {\n                \"cmd\": str(cmd)[:500],\n                \"error\": str(e),\n                \"elapsed_ms\": int((time.time() - started) * 1000),\n            })\n            return str(e), -1\n\n    def _run_powershell(self, script, timeout=120):\n        \"\"\"PowerShell ko EncodedCommand se run karta hai taaki quoting issues na aayein.\"\"\"\n        try:\n            result = safe_powershell(script, timeout=timeout)\n            self._audit_event(\"safe_powershell\", {\n                \"rc\": result.returncode,\n                \"timeout_s\": timeout,\n                \"elapsed_ms\": result.elapsed_ms,\n                \"timed_out\": result.timed_out,\n                \"output_tail\": result.output[-300:],\n            })\n            return result.output, result.returncode\n        except Exception as e:\n            return str(e), -1\n\n    def _stream_cmd_to_log(self, cmd, log_widget, timeout_s=1800, stop_attr=\"_repair_stop_flag\"):\n        \"\"\"\n        Existing logging ko use karke command output live stream karta hai.\n        Return: (full_output, rc, timed_out, stopped)\n        \"\"\"\n        output = []\n        started = time.time()\n        timed_out = False\n        stopped = False\n        proc = None\n        try:\n            setattr(self, stop_attr, False)\n            startupinfo = None\n            creationflags = 0\n            if sys.platform == \"win32\":\n                startupinfo = subprocess.STARTUPINFO()\n                startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW\n                creationflags = subprocess.CREATE_NO_WINDOW\n            proc = subprocess.Popen(\n                cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,\n                text=True, encoding=\"utf-8\", errors=\"replace\",\n                startupinfo=startupinfo,\n                creationflags=creationflags,\n            )\n            if stop_attr == \"_repair_stop_flag\":\n                self._repair_proc = proc\n            for line in iter(proc.stdout.readline, \"\"):\n                if not line and proc.poll() is not None:\n                    break\n                clean = line.rstrip(\"\\n\")\n                if clean:\n                    output.append(clean)\n                    self._append_log(log_widget, clean, C[\"text_dim\"])\n                if getattr(self, stop_attr, False):\n                    stopped = True\n                    try:\n                        proc.terminate()\n                    except Exception:\n                        pass\n                    break\n                if timeout_s and (time.time() - started) &gt; timeout_s:\n                    timed_out = True\n                    try:\n                        proc.terminate()\n                    except Exception:\n                        pass\n                    break\n            try:\n                rc = proc.wait(timeout=5)\n            except Exception:\n                rc = -1\n        except Exception as e:\n            output.append(str(e))\n            rc = -1\n            self._append_log(log_widget, f\"Command stream failed: {e}\", C[\"error\"])\n        finally:\n            if stop_attr == \"_repair_stop_flag\":\n                self._repair_proc = None\n        return \"\\n\".join(output), rc, timed_out, stopped\n\n    # ---------- CONFIRMATION WITH BEFORE/AFTER ----------\n    def _operation_preflight_summary(self, title, commands=None):\n        engine = getattr(self, \"preflight_engine\", None)\n        if not engine:\n            return None\n        try:\n            return engine.analyze(title, commands or [])\n        except Exception:\n            return None\n\n    def _format_preflight_for_dialog(self, preflight):\n        if not preflight:\n            return \"Preflight: unavailable\"\n        lines = [\n            f\"Risk: {str(preflight.risk).upper()} ({preflight.score}/100)\",\n            f\"Admin required: {'yes' if preflight.requires_admin else 'no'}\",\n            f\"Restore point required: {'yes' if preflight.requires_restore_point else 'no'}\",\n            f\"Rollback snapshot required: {'yes' if preflight.requires_rollback_snapshot else 'no'}\",\n            f\"Dry-run recommended: {'yes' if preflight.dry_run_recommended else 'no'}\",\n        ]\n        for finding in getattr(preflight, \"findings\", [])[:3]:\n            lines.append(f\"- {finding.message} Recommendation: {finding.recommendation}\")\n        return \"\\n\".join(lines)\n\n    def _confirm_and_run(self, title, description, before_callback, action_callback, after_callback=None):\n        before_info = before_callback() if before_callback else \"No before data\"\n        preflight = self._operation_preflight_summary(title)\n        msg = (\n            f\"{description}\\n\\n\"\n            f\"SAFETY PREFLIGHT:\\n{self._format_preflight_for_dialog(preflight)}\\n\\n\"\n            f\"\ud83d\udcca BEFORE:\\n{before_info}\\n\\nDo you want to proceed?\"\n        )\n        if not messagebox.askyesno(title, msg):\n            self._audit_event(\"action_cancelled\", {\"title\": title})\n            return False\n        if preflight and getattr(preflight, \"typed_confirmation\", False):\n            token = str(title).strip()[:24]\n            typed = simpledialog.askstring(\n                \"Critical Confirmation\",\n                f\"Type this action name to continue:\\n\\n{token}\",\n            )\n            if typed != token:\n                self._audit_event(\"action_cancelled\", {\"title\": title, \"reason\": \"typed_confirmation_failed\"})\n                return False\n        risky_words = (\"delete\", \"clean\", \"disable\", \"registry\", \"policy\", \"remove\", \"repair\", \"force\")\n        lower_title = str(title).lower()\n        if any(w in lower_title for w in risky_words) or (preflight and preflight.requires_restore_point):\n            try:\n                self._create_restore_point(f\"Pre-Action: {title}\")\n            except Exception:\n                pass\n\n        state_before = self._snapshot_system_state()\n        self._audit_event(\"action_started\", {\n            \"title\": title,\n            \"before_info\": str(before_info)[:800],\n            \"state\": state_before,\n            \"preflight\": {\n                \"risk\": getattr(preflight, \"risk\", \"\"),\n                \"score\": getattr(preflight, \"score\", 0),\n                \"restore_point\": getattr(preflight, \"requires_restore_point\", False),\n                \"rollback_snapshot\": getattr(preflight, \"requires_rollback_snapshot\", False),\n            },\n        })\n        self._set_status(f\"Executing: {title}...\", C[\"accent4\"])\n        action_result = action_callback()\n        success_guess = True\n        if isinstance(action_result, dict) and action_result.get(\"ok\") is False:\n            success_guess = False\n        if after_callback:\n            after_info = after_callback()\n            diff_msg = f\"\\n\\n\ud83d\udcc8 AFTER:\\n{after_info}\"\n            if isinstance(action_result, dict) and action_result.get(\"message\"):\n                messagebox.showinfo(\"Complete\", f\"{action_result['message']}{diff_msg}\")\n            else:\n                messagebox.showinfo(\"Complete\", f\"{title} completed successfully.{diff_msg}\")\n        else:\n            if isinstance(action_result, dict) and action_result.get(\"message\"):\n                box_title = \"Already Done\" if action_result.get(\"already_done\") else \"Complete\"\n                messagebox.showinfo(box_title, action_result[\"message\"])\n            else:\n                messagebox.showinfo(\"Complete\", f\"{title} completed.\")\n            after_info = \"No after data\"\n        state_after = self._snapshot_system_state()\n        self._audit_event(\"action_finished\", {\n            \"title\": title,\n            \"success\": success_guess,\n            \"after_info\": str(after_info)[:800],\n            \"state_before\": state_before,\n            \"state_after\": state_after,\n        })\n        self._set_status(\"Ready\", C[\"success\"])\n        return True\n\n    def _confirm_and_launch_job(self, title, description, before_callback, job_name, target, *args):\n        before_info = before_callback() if before_callback else \"No before data\"\n        preflight = self._operation_preflight_summary(title)\n        msg = (\n            f\"{description}\\n\\n\"\n            f\"SAFETY PREFLIGHT:\\n{self._format_preflight_for_dialog(preflight)}\\n\\n\"\n            f\"\ud83d\udcca BEFORE:\\n{before_info}\\n\\nDo you want to proceed?\"\n        )\n        if not messagebox.askyesno(title, msg):\n            self._audit_event(\"action_cancelled\", {\"title\": title})\n            return False\n        risky_words = (\"delete\", \"clean\", \"disable\", \"registry\", \"policy\", \"remove\", \"repair\", \"force\")\n        lower_title = str(title).lower()\n        if any(w in lower_title for w in risky_words) or (preflight and preflight.requires_restore_point):\n            try:\n                self._create_restore_point(f\"Pre-Action: {title}\")\n            except Exception:\n                pass\n\n        state_before = self._snapshot_system_state()\n        self._audit_event(\"action_started\", {\n            \"title\": title,\n            \"before_info\": str(before_info)[:800],\n            \"state\": state_before,\n            \"preflight\": {\n                \"risk\": getattr(preflight, \"risk\", \"\"),\n                \"score\": getattr(preflight, \"score\", 0),\n                \"restore_point\": getattr(preflight, \"requires_restore_point\", False),\n                \"rollback_snapshot\": getattr(preflight, \"requires_rollback_snapshot\", False),\n            },\n        })\n        self._set_status(f\"Queued: {title}...\", C[\"accent4\"])\n        jid = self._launch_job(job_name, target, *args)\n        self._audit_event(\"action_launched\", {\"title\": title, \"job_id\": jid, \"name\": job_name})\n        return jid\n\n    def _set_clean_job_state(self, running=False, export_ready=False):\n        self._clean_job_running = bool(running)\n        try:\n            if hasattr(self, \"clean_cancel_btn\"):\n                self.clean_cancel_btn.config(state=\"normal\" if running else \"disabled\")\n        except Exception:\n            pass\n        try:\n            if hasattr(self, \"clean_report_btn\"):\n                self.clean_report_btn.config(state=\"normal\" if export_ready and not running else \"disabled\")\n        except Exception:\n            pass\n\n    def _cancel_clean_job(self):\n        if not getattr(self, \"_clean_job_running\", False):\n            return\n        self._clean_job_cancel_event.set()\n        self._set_status(\"Clean operation cancellation requested...\", C[\"warning\"])\n        self._append_log(self.clean_log, \"\u23f9 Requested cancellation of current clean operation.\", C[\"warning\"])\n        self.after(1500, lambda: self._set_clean_job_state(running=False, export_ready=False))\n\n    def _export_clean_report(self):\n        summary = getattr(self, \"_clean_job_summary\", {}) or {}\n        if not summary:\n            messagebox.showwarning(\"No Report\", \"Run a scan or clean operation first, then export the report.\")\n            return\n        fpath = filedialog.asksaveasfilename(defaultextension=\".txt\", filetypes=[(\"Text Report\",\"*.txt\")], title=\"Save Cleaner Report\")\n        if not fpath:\n            return\n        try:\n            report_lines = [\"Godawari Cleaner Report\", f\"Date: {datetime.datetime.now()}\", \"\"]\n            report_lines.append(\"Junk Cleaner Summary:\")\n            report_lines.append(f\"Targets processed: {summary.get('processed', 0)} / {summary.get('total_paths', 0)}\")\n            if summary.get('total_size') is not None:\n                report_lines.append(f\"Total junk found: {self._fmt_size(summary.get('total_size', 0))}\")\n            if summary.get('freed') is not None:\n                report_lines.append(f\"Freed: {self._fmt_size(summary.get('freed', 0))}\")\n                report_lines.append(f\"Remaining junk: {self._fmt_size(summary.get('remaining', 0))}\")\n            if summary.get('preview'):\n                report_lines.append(\"Preview mode: yes\")\n            if summary.get('canceled'):\n                report_lines.append(\"Canceled: yes\")\n            report_lines.append(f\"Errors: {summary.get('errors', 0)}\")\n            report_lines.append(\"\")\n            report_lines.append(\"Detailed Clean Log:\")\n            try:\n                log_text = self.clean_log.get(\"1.0\", \"end\").strip()\n            except Exception:\n                log_text = \"[Log unavailable]\"\n            report_lines.append(log_text)\n            with open(fpath, \"w\", encoding=\"utf-8\") as f:\n                f.write(\"\\n\".join(report_lines))\n            self._append_log(self.clean_log, f\"\u2705 Exported cleaner report: {fpath}\", C[\"success\"])\n        except Exception as e:\n            messagebox.showerror(\"Export Failed\", str(e))\n\n    def _finalize_clean_job(self, job_type, summary):\n        try:\n            self._set_clean_job_state(running=False, export_ready=True)\n            self._clean_job_summary = summary\n            canceled = summary.get(\"canceled\", False)\n            total_paths = summary.get(\"total_paths\", 0)\n            processed = summary.get(\"processed\", 0)\n            summary_lines = [f\"{job_type.title()} Summary:\"]\n            summary_lines.append(f\"Targets processed: {processed} / {total_paths}\")\n            if job_type == \"scan\":\n                total_size = summary.get(\"total_size\", 0)\n                summary_lines.append(f\"Total junk found: {self._fmt_size(total_size)}\")\n                self.clean_size_lbl.config(text=f\"Total junk found: {self._fmt_size(total_size)}\")\n                self.clean_progress_lbl.config(text=f\"Scan complete: {self._fmt_size(total_size)}\")\n            else:\n                freed = summary.get(\"freed\", 0)\n                remaining = summary.get(\"remaining\", 0)\n                summary_lines.append(f\"Freed: {self._fmt_size(freed)}\")\n                summary_lines.append(f\"Remaining junk: {self._fmt_size(remaining)}\")\n                if summary.get(\"preview\"):\n                    summary_lines.append(\"Preview mode: no files were deleted.\")\n                self.clean_size_lbl.config(text=f\"Total junk found: {self._fmt_size(remaining)} remaining\")\n                self.clean_progress_lbl.config(text=f\"Clean complete: {self._fmt_size(freed)} freed\")\n            if summary.get(\"errors\", 0):\n                summary_lines.append(f\"Errors: {summary.get('errors', 0)}\")\n            if canceled:\n                summary_lines.append(\"Operation canceled by user.\")\n                self._set_status(f\"{job_type.title()} canceled.\", C[\"warning\"])\n            else:\n                self._set_status(f\"{job_type.title()} complete.\", C[\"success\"])\n            if hasattr(self, \"clean_progress_bar\"):\n                try:\n                    if total_paths &gt; 0:\n                        self.clean_progress_bar.config(value=min(processed, total_paths))\n                except Exception:\n                    pass\n            self._append_log(self.clean_log, \"\\n\".join(summary_lines), C[\"accent\"])\n            messagebox.showinfo(f\"{job_type.title()} Complete\", \"\\n\".join(summary_lines))\n        except Exception:\n            pass\n\n    # ---------- DASHBOARD ----------\n    def _build_dashboard(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        tb = tk.Frame(frame, bg=C[\"panel\"])\n        tb.pack(fill=\"x\")\n        tk.Label(tb, text=\"  System Dashboard\", font=FONTS[\"heading\"], fg=C[\"accent\"], bg=C[\"panel\"]).pack(side=\"left\", pady=10, padx=8)\n        tk.Button(tb, text=\"\u27f3 Refresh\", font=FONTS[\"small\"], bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=10, pady=4, cursor=\"hand2\", command=self._refresh_dashboard).pack(side=\"right\", padx=12, pady=8)\n        tk.Button(tb, text=\"\ud83d\ude80 Live Internet Speed Test\", font=FONTS[\"small\"], bg=C[\"btn_warn\"], fg=C[\"text\"], bd=0, padx=10, pady=4, cursor=\"hand2\", command=self._live_speed_test).pack(side=\"right\", padx=5, pady=8)\n        tk.Button(tb, text=\"\ud83d\udd0d One-Click Health Scan\", font=FONTS[\"small\"], bg=C[\"btn_warn\"], fg=C[\"text\"], bd=0, padx=10, pady=4, cursor=\"hand2\", command=self._one_click_health_scan).pack(side=\"right\", padx=5, pady=8)\n        grid = tk.Frame(frame, bg=C[\"bg\"])\n        grid.pack(fill=\"x\", padx=16, pady=(12,0))\n        self.dash_cards = {}\n        cards_def = [(\"cpu\",\"CPU Usage\",C[\"accent\"],\"0%\"), (\"ram\",\"RAM Usage\",C[\"success\"],\"0%\"),\n                     (\"disk\",\"Disk Usage\",C[\"accent4\"],\"0%\"), (\"health\",\"Health Score\",C[\"accent2\"],\"--\"),\n                     (\"uptime\",\"Uptime\",C[\"accent2\"],\"--\")]\n        for i, (k, title, color, val) in enumerate(cards_def):\n            card = self._stat_card(grid, title, val, color)\n            card.grid(row=0, column=i, padx=6, pady=6, sticky=\"ew\")\n            grid.columnconfigure(i, weight=1)\n            self.dash_cards[k] = card\n        self.after(2000, self._refresh_health_score_card)\n        graph_frame = tk.Frame(frame, bg=C[\"card\"])\n        graph_frame.pack(fill=\"x\", padx=16, pady=6)\n        tk.Label(graph_frame, text=\"  Live CPU/RAM History (60s)\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8,4), padx=8)\n        self.graph_canvas = tk.Canvas(graph_frame, bg=C[\"bg\"], height=self._dpi_px(82), highlightthickness=0)\n        self.graph_canvas.pack(fill=\"x\", padx=8, pady=8)\n        self.graph_data = {\"cpu\": [], \"ram\": []}\n\n        rec_panel = tk.Frame(frame, bg=C[\"card\"])\n        rec_panel.pack(fill=\"x\", padx=16, pady=(0, 8))\n        rec_head = tk.Frame(rec_panel, bg=C[\"card\"])\n        rec_head.pack(fill=\"x\", padx=8, pady=(8, 4))\n        tk.Label(rec_head, text=\"  Intelligent Recommendations\", font=FONTS[\"subhead\"],\n                 fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._btn(rec_head, \"Refresh\", C[\"btn_info\"], self._refresh_intelligent_recommendations).pack(side=\"right\")\n        rec_cols = (\"Priority\", \"Menu\", \"Action\")\n        self.dashboard_recommendation_tree = ttk.Treeview(\n            rec_panel, columns=rec_cols, show=\"headings\", height=5, style=\"Custom.Treeview\")\n        for col, w in zip(rec_cols, (90, 210, 720)):\n            self.dashboard_recommendation_tree.heading(col, text=col)\n            self.dashboard_recommendation_tree.column(col, width=w, anchor=\"w\")\n        self.dashboard_recommendation_tree.pack(fill=\"x\", padx=8, pady=(0, 8))\n        self.dashboard_recommendation_tree.bind(\"\", lambda _e: self._show_section(\"safety_center\"))\n        self.after(2600, self._refresh_intelligent_recommendations)\n\n        lower = tk.Frame(frame, bg=C[\"bg\"])\n        lower.pack(fill=\"both\", expand=True, padx=16, pady=10)\n        lower.columnconfigure(0, weight=5)\n        lower.columnconfigure(1, weight=2)\n        lower.rowconfigure(0, weight=1)\n        proc_frame = tk.Frame(lower, bg=C[\"card\"])\n        proc_frame.grid(row=0, column=0, sticky=\"nsew\", padx=(0,6))\n        proc_frame.rowconfigure(1, weight=1)\n        proc_frame.columnconfigure(0, weight=1)\n        tk.Label(proc_frame, text=\"  Process Center - Top CPU Processes\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=0, column=0, columnspan=2, sticky=\"w\", pady=(8,4), padx=8)\n        cols = (\"PID\",\"Name\",\"CPU%\",\"RAM MB\",\"Status\")\n        self.proc_tree = ttk.Treeview(proc_frame, columns=cols, show=\"headings\", height=24, style=\"Custom.Treeview\")\n        for col, w in zip(cols, [60,200,70,80,80]):\n            self.proc_tree.heading(col, text=col)\n            self.proc_tree.column(col, width=w, anchor=\"center\")\n        sb2 = ttk.Scrollbar(proc_frame, orient=\"vertical\", command=self.proc_tree.yview)\n        xsb2 = ttk.Scrollbar(proc_frame, orient=\"horizontal\", command=self.proc_tree.xview)\n        self.proc_tree.configure(yscrollcommand=sb2.set, xscrollcommand=xsb2.set)\n        self.proc_tree.grid(row=1, column=0, sticky=\"nsew\", padx=(8,0), pady=(0,0))\n        sb2.grid(row=1, column=1, sticky=\"ns\", pady=(0,0), padx=(0,8))\n        xsb2.grid(row=2, column=0, sticky=\"ew\", padx=(8,0), pady=(0,8))\n        self._bind_tree_responsive_columns(self.proc_tree, [\n            (\"PID\", 60, 0), (\"Name\", 220, 5), (\"CPU%\", 70, 1), (\"RAM MB\", 90, 1), (\"Status\", 100, 2)\n        ])\n        qa = tk.Frame(lower, bg=C[\"card\"])\n        qa.grid(row=0, column=1, sticky=\"nsew\", padx=(6,0))\n        tk.Label(qa, text=\"  Quick Actions\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8,6), padx=8)\n        self._action_card_grid(qa, [\n            (\"\ud83e\uddf9\", \"Clean + RAM\",         \"Temp clean + RAM optimize\",        C[\"btn\"],      self._quick_clean_and_ram),\n            (\"\u2699\",  \"Services + Registry\", \"Services + Registry tweaks\",       C[\"btn_info\"], self._quick_services_and_registry),\n            (\"\ud83d\udd0d\", \"Full Health Scan\",    \"Poora system scan karo\",           C[\"btn\"],      self._full_scan),\n            (\"\u26a1\", \"One-Click ALL\",        \"Sabhi boosts ek saath chalao\",     C[\"accent4\"],  self._one_click_all_boosts),\n            (\"\ud83d\udee1\", \"Safety Center\",        \"Health, rollback, sessions\",       C[\"btn_chip\"], lambda: self._show_section(\"safety_center\")),\n        ], cols=2)\n\n        workflow = tk.Frame(lower, bg=C[\"card\"])\n        workflow.grid(row=1, column=0, columnspan=2, sticky=\"ew\", pady=(8,0))\n        tk.Label(workflow, text=\"  Guided Workflows\", font=FONTS[\"subhead\"], fg=C[\"accent2\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=8, pady=(8,4))\n        self.dashboard_workflow_lbl = tk.Label(\n            workflow,\n            text=\"Health scan not run yet \u2014 use One-Click Health Scan or Safety Center to generate guided actions.\",\n            font=FONTS[\"small\"],\n            fg=C[\"text_dim\"],\n            bg=C[\"card\"],\n            justify=\"left\",\n            wraplength=1150,\n            anchor=\"w\",\n        )\n        self.dashboard_workflow_lbl.pack(fill=\"x\", padx=8, pady=(0,8))\n        wf_actions = tk.Frame(workflow, bg=C[\"card\"])\n        wf_actions.pack(fill=\"x\", padx=8, pady=(0,8))\n        for label, color, cmd in [\n            (\"\ud83d\udee1 Safety + Restore\", C[\"btn_warn\"], lambda: (self._show_section(\"safety_center\"), self._create_restore_point(\"Guided workflow\"))),\n            (\"\ud83c\udf10 Network + Repair\", C[\"btn_info\"], lambda: self._show_section(\"network\")),\n            (\"\ud83d\udcbe Recovery + Rescue\", C[\"btn_chip\"], lambda: self._show_section(\"rescue_center\")),\n            (\"\ud83e\uddf9 Clean + RAM\", C[\"btn\"], self._quick_clean_and_ram),\n        ]:\n            tk.Button(wf_actions, text=label, font=FONTS[\"small\"], bg=color, fg=C[\"text\"], bd=0, padx=12, pady=8,\n                      cursor=\"hand2\", command=cmd).pack(side=\"left\", padx=4, pady=4)\n        return frame\n\n    def _build_safety_center(self, parent):\n        \"\"\"Professional safety hub: health scoring, rollback vault, sessions, timeline.\"\"\"\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(\n            frame,\n            \"\ud83d\udee1 Safety &amp; Recovery Center\",\n            \"Health scoring \u2022 Restore Point Manager \u2022 Rollback vault \u2022 Operation timeline\",\n        )\n\n        canvas = tk.Canvas(frame, bg=C[\"bg\"], highlightthickness=0)\n        scrollbar = ttk.Scrollbar(frame, orient=\"vertical\", command=canvas.yview)\n        content = tk.Frame(canvas, bg=C[\"bg\"])\n        content.bind(\"\", lambda e: canvas.configure(scrollregion=canvas.bbox(\"all\")))\n        canvas_window = canvas.create_window((0, 0), window=content, anchor=\"nw\")\n        canvas.configure(yscrollcommand=scrollbar.set)\n        canvas.pack(side=\"left\", fill=\"both\", expand=True)\n        scrollbar.pack(side=\"right\", fill=\"y\")\n\n        def _resize_content(event):\n            try:\n                canvas.itemconfigure(canvas_window, width=event.width)\n                canvas.configure(scrollregion=canvas.bbox(\"all\"))\n            except Exception:\n                pass\n\n        canvas.bind(\"\", _resize_content)\n        self._bind_scoped_mousewheel(content, canvas)\n\n        top = tk.Frame(content, bg=C[\"card\"])\n        top.pack(fill=\"x\", padx=16, pady=10)\n        self.safety_health_lbl = tk.Label(\n            top, text=\"Health: analyzing\u2026\",\n            font=(\"Segoe UI\", 22, \"bold\"), fg=C[\"accent\"], bg=C[\"card\"])\n        self.safety_health_lbl.pack(side=\"left\", padx=12, pady=10)\n        btn_row = tk.Frame(top, bg=C[\"card\"])\n        btn_row.pack(side=\"right\", padx=12)\n        self._btn(btn_row, \"\ud83d\udd0d Run Health Scan\", C[\"btn_warn\"], self._one_click_health_scan).pack(side=\"left\", padx=4)\n        self._btn(btn_row, \"\ud83d\udcbe Create Restore Point\", C[\"btn_info\"],\n                  lambda: self._create_restore_point(\"Safety Center manual\")).pack(side=\"left\", padx=4)\n        self._btn(btn_row, \"Generate Audit\", C[\"accent4\"], self._safety_export_product_audit).pack(side=\"left\", padx=4)\n        self._btn(btn_row, \"Export Menu Map\", C[\"btn_chip\"], self._safety_export_menu_map).pack(side=\"left\", padx=4)\n        self._btn(btn_row, \"\ud83d\udd04 Refresh\", C[\"btn\"], self._safety_refresh_all).pack(side=\"left\", padx=4)\n\n        mid = tk.Frame(content, bg=C[\"bg\"])\n        mid.pack(fill=\"x\", padx=16, pady=(0, 10))\n        mid.columnconfigure(0, weight=1)\n        mid.columnconfigure(1, weight=1)\n\n        # Rollback vault\n        rb_card = tk.LabelFrame(mid, text=\" Rollback Vault \", font=FONTS[\"subhead\"],\n                                fg=C[\"accent\"], bg=C[\"card\"])\n        rb_card.grid(row=0, column=0, sticky=\"nsew\", padx=(0, 6), pady=(0, 6))\n        rb_cols = (\"Session\", \"Items\", \"Created\")\n        self.safety_rollback_tree = ttk.Treeview(\n            rb_card, columns=rb_cols, show=\"headings\", height=8, style=\"Custom.Treeview\")\n        for col, w in zip(rb_cols, (200, 60, 160)):\n            self.safety_rollback_tree.heading(col, text=col)\n            self.safety_rollback_tree.column(col, width=w)\n        self.safety_rollback_tree.pack(fill=\"both\", expand=True, padx=8, pady=8)\n        rb_btns = tk.Frame(rb_card, bg=C[\"card\"])\n        rb_btns.pack(fill=\"x\", padx=8, pady=(0, 8))\n        self._btn(rb_btns, \"\u21a9 Restore Selected\", C[\"btn_warn\"], self._safety_restore_rollback).pack(side=\"left\", padx=4)\n        self._btn(rb_btns, \"\ud83d\udcc2 Open Vault Folder\", C[\"btn_chip\"], self._safety_open_rollback_dir).pack(side=\"left\", padx=4)\n\n        # Recovery sessions\n        rs_card = tk.LabelFrame(mid, text=\" Recovery Sessions \", font=FONTS[\"subhead\"],\n                                fg=C[\"accent4\"], bg=C[\"card\"])\n        rs_card.grid(row=0, column=1, sticky=\"nsew\", padx=(6, 0), pady=(0, 6))\n        rs_cols = (\"ID\", \"Kind\", \"Status\", \"Started\")\n        self.safety_session_tree = ttk.Treeview(\n            rs_card, columns=rs_cols, show=\"headings\", height=8, style=\"Custom.Treeview\")\n        for col, w in zip(rs_cols, (120, 100, 80, 140)):\n            self.safety_session_tree.heading(col, text=col)\n            self.safety_session_tree.column(col, width=w)\n        self.safety_session_tree.pack(fill=\"both\", expand=True, padx=8, pady=8)\n        rs_btns = tk.Frame(rs_card, bg=C[\"card\"])\n        rs_btns.pack(fill=\"x\", padx=8, pady=(0, 8))\n        self._btn(rs_btns, \"\u2713 Mark Completed\", C[\"btn_info\"], self._safety_clear_session).pack(side=\"left\", padx=4)\n        self._btn(rs_btns, \"\ud83e\uddf9 Clear Crash Flag\", C[\"btn\"], self._safety_clear_crash_marker).pack(side=\"left\", padx=4)\n\n        rp_card = tk.LabelFrame(mid, text=\" Restore Point Manager \", font=FONTS[\"subhead\"],\n                                fg=C[\"accent4\"], bg=C[\"card\"])\n        rp_card.grid(row=1, column=0, columnspan=2, sticky=\"ew\", pady=(6, 0), padx=(0,0))\n        rp_toolbar = tk.Frame(rp_card, bg=C[\"card\"])\n        rp_toolbar.pack(fill=\"x\", padx=8, pady=(8, 0))\n        tk.Label(rp_toolbar, text=\"Recent Restore Points\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._btn(rp_toolbar, \"Refresh\", C[\"btn\"], self._safety_refresh_restore_points).pack(side=\"right\", padx=4)\n        self._btn(rp_toolbar, \"Open System Restore\", C[\"btn_warn\"], self._open_system_restore).pack(side=\"right\", padx=4)\n        rp_cols = (\"Sequence\", \"Description\", \"Created\")\n        self.safety_restore_tree = ttk.Treeview(\n            rp_card, columns=rp_cols, show=\"headings\", height=5, style=\"Custom.Treeview\")\n        for col, w in zip(rp_cols, (100, 420, 180)):\n            self.safety_restore_tree.heading(col, text=col)\n            self.safety_restore_tree.column(col, width=w, anchor=\"w\")\n        self.safety_restore_tree.pack(fill=\"both\", expand=True, padx=8, pady=8)\n\n        tl_card = tk.LabelFrame(mid, text=\" Operation Timeline (structured log) \", font=FONTS[\"subhead\"],\n                                fg=C[\"accent2\"], bg=C[\"card\"])\n        tl_card.grid(row=2, column=0, columnspan=2, sticky=\"ew\", pady=(6, 0))\n        self.safety_timeline = self._scrolled_text(tl_card, height=12)\n        self.safety_timeline.pack(fill=\"both\", expand=True, padx=8, pady=8)\n\n        # Recommendations\n        rec_card = tk.LabelFrame(mid, text=\" Smart Recommendations \", font=FONTS[\"subhead\"],\n                                 fg=C[\"hw_accent\"], bg=C[\"card\"])\n        rec_card.grid(row=3, column=0, columnspan=2, sticky=\"ew\", pady=(6, 0))\n        self.safety_recommendations = tk.Label(\n            rec_card, text=\"Run a health scan for personalized recommendations.\",\n            font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"],\n            anchor=\"w\", justify=\"left\", wraplength=1100)\n        self.safety_recommendations.pack(fill=\"x\", padx=12, pady=10)\n\n        map_card = tk.LabelFrame(mid, text=\" Detected Software Map \", font=FONTS[\"subhead\"],\n                                 fg=C[\"accent2\"], bg=C[\"card\"])\n        map_card.grid(row=4, column=0, columnspan=2, sticky=\"ew\", pady=(6, 0))\n        map_cols = (\"Category\", \"Menu\", \"Tabs\", \"Buttons\", \"Options\")\n        self.safety_menu_map_tree = ttk.Treeview(\n            map_card, columns=map_cols, show=\"headings\", height=8, style=\"Custom.Treeview\")\n        for col, w in zip(map_cols, (210, 230, 70, 80, 80)):\n            self.safety_menu_map_tree.heading(col, text=col)\n            self.safety_menu_map_tree.column(col, width=w, anchor=\"w\")\n        self.safety_menu_map_tree.pack(fill=\"x\", padx=8, pady=8)\n\n        prof_card = tk.LabelFrame(mid, text=\" Guided Maintenance Profiles \", font=FONTS[\"subhead\"],\n                                  fg=C[\"accent4\"], bg=C[\"card\"])\n        prof_card.grid(row=5, column=0, columnspan=2, sticky=\"ew\", pady=(6, 0))\n        prof_cols = (\"Profile\", \"Risk\", \"Minutes\", \"Menus\")\n        self.safety_profile_tree = ttk.Treeview(\n            prof_card, columns=prof_cols, show=\"headings\", height=5, style=\"Custom.Treeview\")\n        for col, w in zip(prof_cols, (190, 80, 80, 520)):\n            self.safety_profile_tree.heading(col, text=col)\n            self.safety_profile_tree.column(col, width=w, anchor=\"w\")\n        self.safety_profile_tree.pack(fill=\"both\", expand=True, padx=8, pady=8)\n        prof_btns = tk.Frame(prof_card, bg=C[\"card\"])\n        prof_btns.pack(fill=\"x\", padx=8, pady=(0, 8))\n        self._btn(prof_btns, \"View Workflow\", C[\"btn_info\"], self._safety_show_selected_profile).pack(side=\"left\", padx=4)\n        self._btn(prof_btns, \"Open First Menu\", C[\"btn_chip\"], self._safety_open_selected_profile_menu).pack(side=\"left\", padx=4)\n\n        audit_card = tk.LabelFrame(mid, text=\" Product Audit Heat Map \", font=FONTS[\"subhead\"],\n                                   fg=C[\"accent\"], bg=C[\"card\"])\n        audit_card.grid(row=6, column=0, columnspan=2, sticky=\"ew\", pady=(6, 0))\n        audit_cols = (\"Menu\", \"Maturity\", \"Risk\", \"Top upgrade\")\n        self.safety_audit_tree = ttk.Treeview(\n            audit_card, columns=audit_cols, show=\"headings\", height=7, style=\"Custom.Treeview\")\n        for col, w in zip(audit_cols, (220, 80, 70, 520)):\n            self.safety_audit_tree.heading(col, text=col)\n            self.safety_audit_tree.column(col, width=w, anchor=\"w\")\n        self.safety_audit_tree.pack(fill=\"both\", expand=True, padx=8, pady=8)\n\n        self.after(300, self._safety_refresh_all)\n        return frame\n\n    def _build_recommendations_payload(self, limit=10):\n        engine = getattr(self, \"recommendation_engine\", None)\n        audit_engine = getattr(self, \"product_audit_engine\", None)\n        if not engine or not audit_engine:\n            return {\"items\": []}\n        try:\n            return engine.build(\n                getattr(self, \"_last_health_report\", None),\n                audit_engine.list_audits(),\n                limit=limit,\n            )\n        except Exception:\n            return {\"items\": []}\n\n    def _refresh_intelligent_recommendations(self):\n        tree = getattr(self, \"dashboard_recommendation_tree\", None)\n        if not tree:\n            return\n        for iid in tree.get_children():\n            tree.delete(iid)\n        payload = self._build_recommendations_payload(limit=8)\n        for item in payload.get(\"items\", []):\n            tree.insert(\n                \"\", \"end\",\n                values=(\n                    str(item.get(\"priority\", \"\")).upper(),\n                    item.get(\"menu\", \"\"),\n                    item.get(\"action\", \"\"),\n                ),\n            )\n\n    def _recommendations_as_text(self, limit=12):\n        payload = self._build_recommendations_payload(limit=limit)\n        lines = []\n        for item in payload.get(\"items\", []):\n            lines.append(\n                f\"[{str(item.get('priority', '')).upper()}] {item.get('menu', '')}: \"\n                f\"{item.get('title', '')} - {item.get('action', '')}\"\n            )\n        return \"\\n\".join(lines) if lines else \"No recommendations yet. Run a health scan first.\"\n\n    def _safety_refresh_all(self):\n        self._refresh_health_score_card()\n        self._safety_refresh_rollback_tree()\n        self._safety_refresh_restore_points()\n        self._safety_refresh_sessions_tree()\n        self._safety_refresh_timeline()\n        self._safety_refresh_menu_map()\n        self._safety_refresh_product_audit()\n        self._safety_refresh_profiles()\n        if hasattr(self, \"dashboard_recommendation_tree\"):\n            self._refresh_intelligent_recommendations()\n        if self._last_health_report and self._last_health_report.get(\"recommendations\"):\n            text = \"\\n\".join(f\"\u2022 {r}\" for r in self._last_health_report[\"recommendations\"])\n            self.safety_recommendations.config(text=text, fg=C[\"text\"])\n        elif hasattr(self, \"safety_recommendations\"):\n            self.safety_recommendations.config(text=self._recommendations_as_text(limit=6), fg=C[\"text\"])\n\n    def _safety_refresh_menu_map(self):\n        if not hasattr(self, \"safety_menu_map_tree\"):\n            return\n        for iid in self.safety_menu_map_tree.get_children():\n            self.safety_menu_map_tree.delete(iid)\n        engine = getattr(self, \"menu_introspection_engine\", None)\n        if not engine:\n            return\n        try:\n            data = engine.scan()\n        except Exception:\n            return\n        for menu in data.get(\"menus\", []):\n            self.safety_menu_map_tree.insert(\n                \"\", \"end\",\n                values=(\n                    getattr(menu, \"category\", \"\"),\n                    getattr(menu, \"label\", \"\"),\n                    len(getattr(menu, \"tabs\", []) or []),\n                    len(getattr(menu, \"buttons\", []) or []),\n                    len(getattr(menu, \"options\", []) or []),\n                ),\n            )\n\n    def _safety_export_menu_map(self):\n        engine = getattr(self, \"menu_introspection_engine\", None)\n        if not engine:\n            messagebox.showerror(\"Menu Map\", \"Menu introspection engine is unavailable.\")\n            return\n        fpath = filedialog.asksaveasfilename(\n            defaultextension=\".md\",\n            filetypes=[(\"Markdown Report\", \"*.md\"), (\"Text Report\", \"*.txt\")],\n            title=\"Save Detected Software Menu Map\",\n        )\n        if not fpath:\n            return\n        try:\n            with open(fpath, \"w\", encoding=\"utf-8\") as f:\n                f.write(engine.to_markdown())\n            self._audit_event(\"menu_map_exported\", {\"path\": fpath})\n            messagebox.showinfo(\"Menu Map Exported\", f\"Detected software map saved:\\n\\n{fpath}\")\n            self._set_status(\"Detected software map exported.\", C[\"success\"])\n        except Exception as e:\n            messagebox.showerror(\"Export Failed\", str(e))\n\n    def _safety_refresh_profiles(self):\n        if not hasattr(self, \"safety_profile_tree\"):\n            return\n        for iid in self.safety_profile_tree.get_children():\n            self.safety_profile_tree.delete(iid)\n        engine = getattr(self, \"maintenance_profile_engine\", None)\n        if not engine:\n            return\n        for profile in engine.list_profiles():\n            self.safety_profile_tree.insert(\n                \"\", \"end\",\n                iid=profile.key,\n                values=(\n                    profile.name,\n                    str(profile.risk).upper(),\n                    profile.estimated_minutes,\n                    \", \".join(profile.menus),\n                ),\n            )\n\n    def _safety_selected_profile(self):\n        tree = getattr(self, \"safety_profile_tree\", None)\n        engine = getattr(self, \"maintenance_profile_engine\", None)\n        if not tree or not engine:\n            return None\n        sel = tree.selection()\n        if not sel:\n            messagebox.showwarning(\"Maintenance Profile\", \"Select a profile first.\")\n            return None\n        return engine.get(sel[0])\n\n    def _safety_show_selected_profile(self):\n        profile = self._safety_selected_profile()\n        if not profile:\n            return\n        msg = [\n            f\"{profile.name}\",\n            \"\",\n            profile.purpose,\n            \"\",\n            f\"Risk: {profile.risk.upper()}\",\n            f\"Estimated time: {profile.estimated_minutes} minutes\",\n            \"\",\n            \"Workflow:\",\n        ]\n        msg.extend(f\"- {action}\" for action in profile.actions)\n        msg.append(\"\")\n        msg.append(\"Protections:\")\n        msg.extend(f\"- {item}\" for item in profile.protections)\n        messagebox.showinfo(\"Guided Maintenance Profile\", \"\\n\".join(msg))\n\n    def _safety_open_selected_profile_menu(self):\n        profile = self._safety_selected_profile()\n        if not profile or not profile.menus:\n            return\n        menu_name = profile.menus[0]\n        mapping = {\n            \"Dashboard\": \"dashboard\",\n            \"Junk Cleaner\": \"cleaner\",\n            \"Safety Center\": \"safety_center\",\n            \"RAM + Services\": \"memory\",\n            \"Startup + Scheduler\": \"startup\",\n            \"Power Plan\": \"power\",\n            \"Printer + Driver\": \"printer\",\n            \"HDD/SSD + File Recovery\": \"hdd_repair\",\n            \"Event Viewer\": \"events\",\n        }\n        self._show_section(mapping.get(menu_name, \"safety_center\"))\n\n    def _safety_refresh_product_audit(self):\n        if not hasattr(self, \"safety_audit_tree\"):\n            return\n        for iid in self.safety_audit_tree.get_children():\n            self.safety_audit_tree.delete(iid)\n        engine = getattr(self, \"product_audit_engine\", None)\n        if not engine:\n            return\n        for audit in sorted(engine.list_audits(), key=lambda a: a.risk_score(), reverse=True):\n            self.safety_audit_tree.insert(\n                \"\", \"end\",\n                values=(\n                    audit.title,\n                    audit.maturity_score(),\n                    audit.risk_score(),\n                    audit.redesign_plan[0] if audit.redesign_plan else audit.final_design,\n                ),\n            )\n\n    def _safety_export_product_audit(self):\n        engine = getattr(self, \"product_audit_engine\", None)\n        if not engine:\n            messagebox.showerror(\"Audit\", \"Product audit engine is unavailable.\")\n            return\n        fpath = filedialog.asksaveasfilename(\n            defaultextension=\".md\",\n            filetypes=[(\"Markdown Report\", \"*.md\"), (\"Text Report\", \"*.txt\")],\n            title=\"Save Professional Product Audit\",\n        )\n        if not fpath:\n            return\n        try:\n            with open(fpath, \"w\", encoding=\"utf-8\") as f:\n                f.write(engine.to_markdown())\n            self._audit_event(\"product_audit_exported\", {\"path\": fpath})\n            messagebox.showinfo(\"Audit Exported\", f\"Professional product audit saved:\\n\\n{fpath}\")\n            self._set_status(\"Professional product audit exported.\", C[\"success\"])\n        except Exception as e:\n            messagebox.showerror(\"Export Failed\", str(e))\n\n    def _safety_refresh_rollback_tree(self):\n        if not hasattr(self, \"safety_rollback_tree\"):\n            return\n        for iid in self.safety_rollback_tree.get_children():\n            self.safety_rollback_tree.delete(iid)\n        vault = getattr(self, \"rollback_vault\", None)\n        if not vault:\n            return\n        for s in vault.list_sessions(40):\n            self.safety_rollback_tree.insert(\n                \"\", \"end\",\n                values=(s.get(\"id\", \"\"), s.get(\"items\", 0), s.get(\"created\", \"\")),\n            )\n\n    def _safety_refresh_sessions_tree(self):\n        if not hasattr(self, \"safety_session_tree\"):\n            return\n        for iid in self.safety_session_tree.get_children():\n            self.safety_session_tree.delete(iid)\n        mgr = getattr(self, \"recovery_session_manager\", None)\n        if not mgr:\n            return\n        for s in mgr.list_sessions(include_completed=True, limit=40):\n            self.safety_session_tree.insert(\n                \"\", \"end\",\n                values=(\n                    (s.get(\"id\", \"\") or \"\")[:12] + \"\u2026\",\n                    s.get(\"kind\", \"\"),\n                    s.get(\"status\", \"\"),\n                    s.get(\"started\", \"\"),\n                ),\n            )\n\n    def _safety_refresh_restore_points(self):\n        if not hasattr(self, \"safety_restore_tree\"):\n            return\n        for iid in self.safety_restore_tree.get_children():\n            self.safety_restore_tree.delete(iid)\n        mgr = getattr(self, \"restore_point_manager\", None)\n        if not mgr:\n            self.safety_restore_tree.insert(\"\", \"end\", values=(\"N/A\", \"Restore point manager unavailable\", \"\"))\n            return\n        points = mgr.list_recent(12)\n        if not points:\n            self.safety_restore_tree.insert(\"\", \"end\", values=(\"None\", \"No recent restore points found\", \"\"))\n            return\n        for p in points:\n            self.safety_restore_tree.insert(\n                \"\", \"end\",\n                values=(\n                    str(p.get(\"SequenceNumber\", \"\")),\n                    str(p.get(\"Description\", \"\")),\n                    str(p.get(\"Created\", \"\")),\n                ),\n            )\n\n    def _open_system_restore(self):\n        try:\n            if sys.platform != \"win32\":\n                messagebox.showwarning(\"System Restore\", \"System Restore is only available on Windows.\")\n                return\n            self._run_cmd(\"rstrui.exe\", timeout=10)\n            self._set_status(\"System Restore wizard opened.\", C[\"success\"])\n        except Exception as e:\n            messagebox.showerror(\"System Restore\", f\"Unable to open System Restore: {e}\")\n            self._set_status(\"Failed to open System Restore.\", C[\"error\"])\n\n    def _safety_refresh_timeline(self):\n        if not hasattr(self, \"safety_timeline\"):\n            return\n        logger = getattr(self, \"structured_logger\", None)\n        rows = logger.read_recent(80) if logger else []\n        self.safety_timeline.config(state=\"normal\")\n        self.safety_timeline.delete(\"1.0\", \"end\")\n        for rec in reversed(rows):\n            ts = rec.get(\"ts\", \"\")\n            action = rec.get(\"action\") or rec.get(\"type\") or rec.get(\"message\", \"\")\n            cat = rec.get(\"category\", rec.get(\"event\", \"\"))\n            line = f\"[{ts}] {cat}/{action}\\n\"\n            self.safety_timeline.insert(\"end\", line)\n        self.safety_timeline.config(state=\"disabled\")\n\n    def _safety_restore_rollback(self):\n        sel = self.safety_rollback_tree.selection() if hasattr(self, \"safety_rollback_tree\") else ()\n        if not sel:\n            messagebox.showwarning(\"Rollback\", \"Select a rollback session first.\")\n            return\n        sid = self.safety_rollback_tree.item(sel[0])[\"values\"][0]\n        if not messagebox.askyesno(\n            \"Restore Rollback\",\n            f\"Restore files/registry from session?\\n\\n{sid}\\n\\nThis overwrites current data.\",\n        ):\n            return\n        ok, msg = self.rollback_vault.restore_session(sid)\n        color = C[\"success\"] if ok else C[\"error\"]\n        messagebox.showinfo(\"Rollback\", msg)\n        self._audit_event(\"rollback_restored\", {\"session\": sid, \"ok\": ok})\n        self._set_status(msg, color)\n\n    def _safety_open_rollback_dir(self):\n        path = getattr(self, \"rollback_dir\", \"\")\n        if path and os.path.isdir(path):\n            os.startfile(path)\n        else:\n            messagebox.showinfo(\"Rollback Vault\", \"Vault folder not initialized yet.\")\n\n    def _safety_clear_session(self):\n        sel = self.safety_session_tree.selection() if hasattr(self, \"safety_session_tree\") else ()\n        if not sel:\n            messagebox.showwarning(\"Sessions\", \"Select a session row first.\")\n            return\n        short_id = str(self.safety_session_tree.item(sel[0])[\"values\"][0]).replace(\"\u2026\", \"\")\n        mgr = self.recovery_session_manager\n        for s in mgr.list_sessions(include_completed=True, limit=100):\n            if (s.get(\"id\") or \"\").startswith(short_id):\n                mgr.complete(s[\"id\"], status=\"completed\")\n                break\n        self._safety_refresh_sessions_tree()\n        self._set_status(\"Session marked completed\", C[\"success\"])\n\n    def _safety_clear_crash_marker(self):\n        try:\n            self.crash_recovery.clear_running()\n            self._log(\"Crash recovery marker cleared silently.\", \"OK\")\n            self._set_status(\"Crash recovery marker cleared\", C[\"success\"])\n        except Exception as e:\n            messagebox.showerror(\"Error\", str(e))\n\n    def _build_activation(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udd11 Windows Activation\", \"Real status check + legal activation actions\")\n        top = tk.Frame(frame, bg=C[\"card\"])\n        top.pack(fill=\"x\", padx=16, pady=10)\n        self.activation_status_lbl = tk.Label(\n            top, text=\"Activation status: checking...\",\n            font=FONTS[\"subhead\"], fg=C[\"accent4\"], bg=C[\"card\"], anchor=\"w\", justify=\"left\"\n        )\n        self.activation_status_lbl.pack(fill=\"x\", padx=10, pady=(8, 4))\n        self.activation_detail_lbl = tk.Label(\n            top, text=\"\",\n            font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], anchor=\"w\", justify=\"left\", wraplength=900\n        )\n        self.activation_detail_lbl.pack(fill=\"x\", padx=10, pady=(0, 8))\n\n        key_row = tk.Frame(top, bg=C[\"card\"])\n        key_row.pack(fill=\"x\", padx=10, pady=(0, 8))\n        tk.Label(key_row, text=\"Product Key (XXXXX-XXXXX-XXXXX-XXXXX-XXXXX):\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\", padx=(0, 8))\n        self.activation_key_entry = tk.Entry(key_row, width=40, font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"])\n        self.activation_key_entry.pack(side=\"left\", padx=(0, 8))\n        self._btn(key_row, \"Install Key\", C[\"btn_warn\"], self._activation_install_key).pack(side=\"left\", padx=4)\n        self._btn(key_row, \"Activate Online\", C[\"btn_info\"], self._activation_online).pack(side=\"left\", padx=4)\n\n        self._action_card_grid(frame, [\n            (\"\ud83d\udd04\", \"Refresh Status\",         \"Activation status check karo\",     C[\"btn\"],      self._refresh_activation_status),\n            (\"\u2699\",  \"Open Settings\",          \"Windows activation settings kholo\",C[\"btn_info\"], self._open_activation_settings),\n        ], cols=2)\n\n        log_wrap = tk.Frame(frame, bg=C[\"card\"])\n        log_wrap.pack(fill=\"both\", expand=True, padx=16, pady=(0, 10))\n        tk.Label(log_wrap, text=\"  Activation Log\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8, 4), padx=8)\n        self.activation_log = self._scrolled_text(log_wrap, height=16)\n        self.after(100, self._refresh_activation_status)\n        return frame\n\n    def _refresh_activation_status(self):\n        self._set_status(\"Checking Windows activation status...\", C[\"accent4\"])\n        self._launch_job(\"activation_status_refresh\", self._do_refresh_activation_status)\n\n    def _do_refresh_activation_status(self):\n        try:\n            ps_cmd = (\n                'powershell -NoProfile -ExecutionPolicy Bypass -Command \"'\n                '$lic=Get-CimInstance SoftwareLicensingProduct | '\n                'Where-Object {$_.PartialProductKey -and $_.ApplicationID -eq ''55c92734-d682-4d71-983e-d6ec3f16059f''} | '\n                'Select-Object -First 1 Name,Description,LicenseStatus,PartialProductKey; '\n                'if($lic){'\n                '$map=@{0=''Unlicensed'';1=''Licensed'';2=''OOBGrace'';3=''OOTGrace'';4=''NonGenuineGrace'';5=''Notification'';6=''ExtendedGrace''}; '\n                '$status=if($map.ContainsKey([int]$lic.LicenseStatus)){$map[[int]$lic.LicenseStatus]}else{''Unknown''}; '\n                'Write-Output (''STATUS=''+$status); '\n                'Write-Output (''NAME=''+$lic.Name); '\n                'Write-Output (''CHANNEL=''+$lic.Description); '\n                'Write-Output (''PARTIAL=''+$lic.PartialProductKey)'\n                '} else { Write-Output ''STATUS=Unknown'' }\"'\n            )\n            out, code = self._run_cmd(ps_cmd, timeout=90)\n            status_line = \"Unknown\"\n            name_line = \"\"\n            channel_line = \"\"\n            partial_line = \"\"\n            for ln in (out or \"\").splitlines():\n                s = ln.strip()\n                if s.startswith(\"STATUS=\"):\n                    status_line = s.split(\"=\", 1)[1].strip() or \"Unknown\"\n                elif s.startswith(\"NAME=\"):\n                    name_line = s.split(\"=\", 1)[1].strip()\n                elif s.startswith(\"CHANNEL=\"):\n                    channel_line = s.split(\"=\", 1)[1].strip()\n                elif s.startswith(\"PARTIAL=\"):\n                    partial_line = s.split(\"=\", 1)[1].strip()\n\n            color = C[\"warning\"]\n            if status_line.lower() == \"licensed\":\n                color = C[\"success\"]\n            elif status_line.lower() in (\"notification\", \"unlicensed\", \"nongenuinegrace\"):\n                color = C[\"error\"]\n\n            detail_parts = []\n            if name_line:\n                detail_parts.append(f\"Edition: {name_line}\")\n            if channel_line:\n                detail_parts.append(f\"Channel: {channel_line}\")\n            if partial_line:\n                detail_parts.append(f\"Partial key: *****-*****-*****-*****-{partial_line}\")\n            if code not in (0, None):\n                detail_parts.append(f\"(Status command exit code: {code})\")\n            details = \"\\n\".join(detail_parts) if detail_parts else \"No detailed activation data available.\"\n\n            self.after(0, lambda: self.activation_status_lbl.config(text=f\"Activation status: {status_line}\", fg=color))\n            self.after(0, lambda: self.activation_detail_lbl.config(text=details))\n            self.after(0, lambda: self._append_log(self.activation_log, f\"Status refreshed: {status_line}\", color))\n            self.after(0, lambda: self._set_status(\"Activation status updated\", C[\"success\"]))\n        except Exception as e:\n            self.after(0, lambda: self._append_log(self.activation_log, f\"Status check failed: {e}\", C[\"error\"]))\n            self.after(0, lambda: self._set_status(\"Activation status check failed\", C[\"error\"]))\n\n    def _activation_install_key(self):\n        key = (self.activation_key_entry.get() if hasattr(self, \"activation_key_entry\") else \"\").strip().upper()\n        if not re.match(r\"^[A-Z0-9]{5}(?:-[A-Z0-9]{5}){4}$\", key):\n            messagebox.showerror(\"Invalid Key\", \"Valid 25-char key format enter karein:\\nXXXXX-XXXXX-XXXXX-XXXXX-XXXXX\")\n            return\n        if not messagebox.askyesno(\"Install Product Key\", f\"Install this key?\\n\\n{key}\\n\\nProceed only if this is your legal license key.\"):\n            return\n        self._set_status(\"Installing product key...\", C[\"accent4\"])\n        self._launch_job(\"activation_install_key\", self._do_activation_install_key, key)\n\n    def _do_activation_install_key(self, key):\n        cmd = f'cscript //nologo \"%windir%\\\\system32\\\\slmgr.vbs\" /ipk {key}'\n        out, code = self._run_cmd(cmd, timeout=180)\n        color = C[\"success\"] if code == 0 else C[\"error\"]\n        msg = out.strip() if out else (\"Product key installed.\" if code == 0 else \"Product key install failed.\")\n        self.after(0, lambda: self._append_log(self.activation_log, msg, color))\n        self.after(0, lambda: self._set_status(\"Product key installed\" if code == 0 else \"Product key install failed\", color))\n        if code == 0:\n            self.after(500, self._refresh_activation_status)\n\n    def _activation_online(self):\n        if not messagebox.askyesno(\"Activate Windows\", \"Try online activation now? Internet connection required.\"):\n            return\n        self._set_status(\"Activating Windows...\", C[\"accent4\"])\n        self._launch_job(\"activation_online\", self._do_activation_online)\n\n    def _do_activation_online(self):\n        cmd = 'cscript //nologo \"%windir%\\\\system32\\\\slmgr.vbs\" /ato'\n        out, code = self._run_cmd(cmd, timeout=240)\n        color = C[\"success\"] if code == 0 else C[\"error\"]\n        msg = out.strip() if out else (\"Activation attempt finished.\" if code == 0 else \"Activation attempt failed.\")\n        self.after(0, lambda: self._append_log(self.activation_log, msg, color))\n        self.after(0, lambda: self._set_status(\"Activation completed\" if code == 0 else \"Activation failed\", color))\n        self.after(500, self._refresh_activation_status)\n\n    def _open_activation_settings(self):\n        out, code = self._run_cmd(\"start ms-settings:activation\")\n        if code == 0:\n            self._append_log(self.activation_log, \"Opened Windows Activation settings.\", C[\"success\"])\n        else:\n            self._append_log(self.activation_log, f\"Could not open settings: {out}\", C[\"error\"])\n\n    def _live_speed_test(self):\n        self._set_status(\"Checking Internet Speed...\", C[\"accent4\"])\n        self._launch_job(\"speed_test\", self._do_speed_test)\n\n    def _do_speed_test(self):\n        import urllib.request\n        import urllib.error\n        targets = [\n            (\"http://speedtest.tele2.net/10MB.zip\", 10),\n            (\"http://ipv4.download.thinkbroadband.com/10MB.zip\", 10),\n            (\"http://proof.ovh.net/files/10Mb.dat\", 10),\n            (\"http://speedtest.tele2.net/1MB.zip\", 1),\n        ]\n        tmp_file = os.path.join(tempfile.gettempdir(), \"godawari_speedtest.tmp\")\n        self._log(\"Starting internet speed test...\", \"INFO\")\n        self._set_status(\"Running speed test...\", C[\"accent4\"])\n        for url, expected_mb in targets:\n            try:\n                start = time.perf_counter()\n                with urllib.request.urlopen(url, timeout=30) as response, open(tmp_file, \"wb\") as out_file:\n                    downloaded = 0\n                    while True:\n                        chunk = response.read(65536)\n                        if not chunk:\n                            break\n                        out_file.write(chunk)\n                        downloaded += len(chunk)\n                elapsed = time.perf_counter() - start\n                if elapsed &lt; 0.1:\n                    continue\n                actual_mb = downloaded / (1024 * 1024)\n                speed_mbps = (actual_mb * 8) / elapsed\n                try:\n                    os.remove(tmp_file)\n                except Exception:\n                    pass\n                msg = (f\"\u2705 Download Speed: {speed_mbps:.2f} Mbps \"\n                       f\"({actual_mb:.1f} MB in {elapsed:.1f}s from {url.split('/')[2]})\")\n                self._set_status(msg, C[\"success\"])\n                self._log(msg, \"OK\")\n                return speed_mbps\n            except Exception as e:\n                self._log(f\"Speed test URL failed ({url}): {e}\", \"WARN\")\n                continue\n        self._set_status(\"Speed test failed \u2014 Internet check karo\", C[\"error\"])\n        self._log(\"All speed test URLs failed.\", \"ERR\")\n        return 0.0\n\n    def _refresh_dashboard(self):\n        def task():\n            try:\n                cpu = psutil.cpu_percent(interval=None)\n                vm = psutil.virtual_memory()\n                du = psutil.disk_usage(\"/\")\n                up = time.time() - psutil.boot_time()\n                up_str = str(datetime.timedelta(seconds=int(up)))\n                self.dash_cards[\"cpu\"]._value_lbl.config(text=f\"{cpu:.1f}%\")\n                self.dash_cards[\"cpu\"]._bar.config(value=cpu)\n                self.dash_cards[\"ram\"]._value_lbl.config(text=f\"{vm.percent:.1f}%\")\n                self.dash_cards[\"ram\"]._bar.config(value=vm.percent)\n                self.dash_cards[\"disk\"]._value_lbl.config(text=f\"{du.percent:.1f}%\")\n                self.dash_cards[\"disk\"]._bar.config(value=du.percent)\n                self.dash_cards[\"uptime\"]._value_lbl.config(text=up_str)\n                if hasattr(self, \"dashboard_workflow_lbl\"):\n                    report = getattr(self, \"_last_health_report\", None)\n                    if report:\n                        score = report.get(\"score\")\n                        recs = report.get(\"recommendations\", []) or []\n                        rollout = [f\"Health {score}/100\" if score is not None else \"Health scan ready\"]\n                        if recs:\n                            rollout.append(f\"{len(recs)} action(s) ready\")\n                            rollout.append(recs[0])\n                        self.dashboard_workflow_lbl.config(text=\" \u2022 \".join(rollout), fg=C[\"text\"])\n                    else:\n                        self.dashboard_workflow_lbl.config(\n                            text=\"Health scan not run yet \u2014 use One-Click Health Scan or Safety Center to generate guided actions.\",\n                            fg=C[\"text_dim\"],\n                        )\n                for item in self.proc_tree.get_children():\n                    self.proc_tree.delete(item)\n                procs = sorted(psutil.process_iter(['pid','name','cpu_percent','memory_info','status']),\n                               key=lambda p: p.info.get('cpu_percent',0) or 0, reverse=True)\n                for p in procs[:25]:\n                    try:\n                        mem = round((p.info.get('memory_info') or psutil.Process(p.info['pid']).memory_info()).rss / (1024**2), 1)\n                        self.proc_tree.insert(\"\", \"end\", values=(p.info['pid'], p.info['name'] or \"?\", f\"{p.info.get('cpu_percent',0):.1f}%\", f\"{mem} MB\", p.info.get('status','?')))\n                    except:\n                        pass\n            except Exception as e:\n                self._log(str(e), \"ERR\")\n        self._launch_job(\"dashboard_refresh\", task)\n\n    def _start_real_time_graph(self):\n        def update_graph():\n            try:\n                cpu = psutil.cpu_percent(interval=None)\n                ram = psutil.virtual_memory().percent\n                self.graph_data[\"cpu\"].append(cpu)\n                self.graph_data[\"ram\"].append(ram)\n                if len(self.graph_data[\"cpu\"]) &gt; 60:\n                    self.graph_data[\"cpu\"].pop(0)\n                    self.graph_data[\"ram\"].pop(0)\n                self._draw_graph()\n            except:\n                pass\n            self.after(2000, update_graph)\n        update_graph()\n\n    def _draw_graph(self):\n        try:\n            self.graph_canvas.delete(\"all\")\n            w = self.graph_canvas.winfo_width()\n            h = 80\n            if w &lt; 10:\n                return\n            n = len(self.graph_data[\"cpu\"])\n            if n &lt; 2:\n                return\n            step = w / max(1, n - 1)\n            cpu_pts = [(i*step, h - (self.graph_data[\"cpu\"][i]/100)*h) for i in range(n)]\n            ram_pts = [(i*step, h - (self.graph_data[\"ram\"][i]/100)*h) for i in range(n)]\n            self.graph_canvas.create_line(cpu_pts, fill=C[\"accent\"], width=2, smooth=True)\n            self.graph_canvas.create_line(ram_pts, fill=C[\"success\"], width=2, smooth=True)\n            self.graph_canvas.create_text(5, 5, anchor=\"nw\", text=f\"CPU (Gold): {self.graph_data['cpu'][-1]:.1f}%  |  RAM (Green): {self.graph_data['ram'][-1]:.1f}%\",\n                                          fill=C[\"text_dim\"], font=FONTS[\"small\"])\n        except:\n            pass\n\n    # ---------- SHOP MODE ----------\n    def _build_shop_mode(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udee0 Repair Shop Mode\", \"Real Customer diagnosis &amp; tune-up\")\n        top = tk.Frame(frame, bg=C[\"card\"])\n        top.pack(fill=\"x\", padx=16, pady=8)\n        self.shop_customer_name = tk.Entry(top, width=24, font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"])\n        self.shop_customer_mobile = tk.Entry(top, width=18, font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"])\n        self.shop_issue = tk.Entry(top, width=55, font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"])\n        for label, widget in [(\"Customer\", self.shop_customer_name), (\"Mobile\", self.shop_customer_mobile), (\"Issue\", self.shop_issue)]:\n            tk.Label(top, text=label, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\", padx=(8,3))\n            widget.pack(side=\"left\", padx=(0,8), pady=8)\n        self.shop_issue.insert(0, \"System hang / slow\")\n        self._action_card_grid(frame, [\n            (\"\u25b6\",  \"Start Job\",              \"Naya customer job shuru karo\",               C[\"btn_info\"],   self._shop_start_job),\n            (\"\ud83d\udd0d\", \"Diagnose Slow PC\",        \"CPU, RAM, Startup, Disk check\",              C[\"btn_danger\"], self._shop_slow_pc_diagnosis),\n            (\"\u26a1\", \"One-Click Tune-Up\",       \"Cache clear + RAM boost + Restore point\",    C[\"btn_warn\"],   self._shop_one_click_tuneup),\n            (\"\ud83d\udd34\", \"Malware + Driver Scan\",   \"Malware scan + Driver repair ek saath\",      C[\"btn_chip\"],   self._shop_malware_driver_combo),\n            (\"\ud83d\udcbe\", \"Disk Health + Backup\",    \"SMART check + Backup combo\",                 C[\"btn_danger\"], self._shop_disk_backup_combo),\n            (\"\ud83c\udf10\", \"Browser + Update Repair\", \"Browser reset + Windows update fix\",         C[\"btn_info\"],   self._shop_browser_update_combo),\n            (\"\u2699\",  \"Service Preset Apply\",   \"Recommended service config lagao\",           C[\"btn_hw\"],     self._shop_service_preset),\n            (\"\ud83d\udcc4\", \"Export Customer Report\",  \"Customer job report save karo\",              C[\"accent2\"],    self._shop_export_customer_report),\n        ], cols=5)\n        self.shop_log = self._scrolled_text(frame, height=23)\n        self.shop_findings = []\n        return frame\n\n    def _shop_start_job(self):\n        self.shop_findings = []\n        self.shop_log.config(state=\"normal\")\n        self.shop_log.delete(\"1.0\",\"end\")\n        self.shop_log.config(state=\"disabled\")\n        self._shop_log(f\"Job started | Customer: {self.shop_customer_name.get()} | Issue: {self.shop_issue.get()}\", \"OK\")\n\n    def _shop_log(self, msg, level=\"INFO\"):\n        color = {\"INFO\": C[\"text\"], \"OK\": C[\"success\"], \"WARN\": C[\"warning\"], \"ERR\": C[\"error\"]}.get(level, C[\"text\"])\n        line = f\"[{datetime.datetime.now().strftime('%H:%M:%S')}] {msg}\"\n        self.shop_findings.append(line)\n        self._append_log(self.shop_log, line, color)\n        self._log(msg, level)\n\n    def _shop_slow_pc_diagnosis(self):\n        self._shop_log(\"\ud83d\udd0d Slow PC Auto Diagnosis started...\", \"INFO\")\n        self._launch_job(\"shop_slow_pc_diagnosis\", self._do_shop_slow_pc_diagnosis)\n\n    def _do_shop_slow_pc_diagnosis(self):\n        self._shop_log(\"1. Checking CPU &amp; RAM Load...\", \"INFO\")\n        cpu = psutil.cpu_percent(interval=None)\n        ram = psutil.virtual_memory()\n        if cpu &gt; 80:\n            self._shop_log(f\"   \u26a0 HIGH CPU USAGE DETECTED: {cpu}%\", \"ERR\")\n        else:\n            self._shop_log(f\"   \u2705 CPU Usage Normal: {cpu}%\", \"OK\")\n        if ram.percent &gt; 85:\n            self._shop_log(f\"   \u26a0 HIGH RAM USAGE DETECTED: {ram.percent}% (Free: {self._fmt_size(ram.available)})\", \"ERR\")\n        else:\n            self._shop_log(f\"   \u2705 RAM Usage Normal: {ram.percent}%\", \"OK\")\n        self._shop_log(\"2. Checking Startup Bloatwares...\", \"INFO\")\n        bloat_count = 0\n        try:\n            key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, r\"Software\\Microsoft\\Windows\\CurrentVersion\\Run\", 0, winreg.KEY_READ)\n            i = 0\n            while True:\n                try:\n                    name, value, _ = winreg.EnumValue(key, i)\n                    if any(x in value.lower() for x in ['zoom', 'skype', 'spotify', 'discord', 'teams']):\n                        self._shop_log(f\"   \u26a0 Bloatware Found: {name}\", \"WARN\")\n                        bloat_count += 1\n                    i += 1\n                except OSError:\n                    break\n            winreg.CloseKey(key)\n        except:\n            pass\n        if bloat_count == 0:\n            self._shop_log(\"   \u2705 No major bloatware in startup\", \"OK\")\n        self._shop_log(\"3. Checking Disk Health (SMART)...\", \"INFO\")\n        out, _ = self._run_cmd(\"wmic diskdrive get status,model /format:list\")\n        if \"OK\" in out:\n            self._shop_log(\"   \u2705 Disk SMART Status: OK\", \"OK\")\n        else:\n            self._shop_log(f\"   \u26a0 Disk Status Check: {out[:100]}\", \"WARN\")\n        self._shop_log(\"\ud83c\udf89 Diagnosis Complete!\", \"OK\")\n\n    def _shop_one_click_tuneup(self):\n        if messagebox.askyesno(\"One Click Shop Tune-Up\", \"Restore point + cache clear + RAM boost run karna hai?\"):\n            if self._create_restore_point(\"One Click Shop Tune-Up se pehle\"):\n                self._shop_log(\"One Click Tune-Up started\", \"INFO\")\n                self._launch_job(\"shop_tuneup\", self._do_shop_tuneup)\n\n    def _do_shop_tuneup(self):\n        self._shop_log(\"Step 1: Clearing Temp Files...\", \"INFO\")\n        self._delete_folder_contents(os.environ.get(\"TEMP\", \"\"))\n        self._delete_folder_contents(r\"C:\\Windows\\Temp\")\n        self._shop_log(\"Step 2: Boosting RAM...\", \"INFO\")\n        gc.collect()\n        try:\n            kernel32 = ctypes.windll.kernel32\n            psapi = ctypes.windll.psapi\n            for proc in psutil.process_iter(['pid']):\n                pid = proc.info.get('pid')\n                if pid and pid not in (0,4):\n                    handle = kernel32.OpenProcess(0x0400|0x0100|0x0010, False, int(pid))\n                    if handle:\n                        psapi.EmptyWorkingSet(handle)\n                        kernel32.CloseHandle(handle)\n        except:\n            pass\n        self._shop_log(\"Step 3: Disabling heavy services...\", \"INFO\")\n        self._run_cmd('sc stop \"SysMain\"')\n        self._shop_log(\"\u2705 Tune-Up complete!\", \"OK\")\n\n    def _shop_malware_pup_scan(self):\n        self._shop_log(\"\ud83d\udd0d Scanning for Malware Clues &amp; PUPs...\", \"INFO\")\n        self._launch_job(\"shop_malware_scan\", self._do_malware_scan)\n\n    def _do_malware_scan(self):\n        suspicious_exts = ['.exe', '.bat', '.cmd', '.ps1', '.vbs', '.js']\n        risk_paths = [os.environ.get('TEMP', ''), os.environ.get('APPDATA', ''), os.path.join(os.environ.get('LOCALAPPDATA', ''), 'Temp')]\n        threats = 0\n        for r_path in risk_paths:\n            if not os.path.exists(r_path):\n                continue\n            for root, dirs, files in os.walk(r_path):\n                if threats &gt; 20:\n                    break\n                for f in files:\n                    if os.path.splitext(f)[1].lower() in suspicious_exts:\n                        full_path = os.path.join(root, f)\n                        if 'microsoft' in full_path.lower():\n                            continue\n                        self._shop_log(f\"\u26a0 Suspicious Script/Exe: {full_path}\", \"WARN\")\n                        threats += 1\n        if threats == 0:\n            self._shop_log(\"\u2705 No immediate Malware/PUP clues found.\", \"OK\")\n        else:\n            self._shop_log(f\"\u26a0 Found {threats} suspicious files. Delete them manually from paths above.\", \"ERR\")\n\n    def _shop_disk_health_risk(self):\n        self._shop_log(\"Checking Disk Health...\", \"INFO\")\n        out, _ = self._run_cmd(\"wmic diskdrive get model,status,size,mediaType /format:list\")\n        self._shop_log(out[:500], \"OK\")\n\n    def _shop_customer_backup(self):\n        dest = filedialog.askdirectory(title=\"Select Backup Destination Folder\")\n        if dest:\n            self._launch_job(\"shop_customer_backup\", self._do_customer_backup, dest)\n\n    def _do_customer_backup(self, dest):\n        self._shop_log(\"Backing up Desktop, Documents, Pictures...\", \"INFO\")\n        user_profile = os.environ.get(\"USERPROFILE\", \"\")\n        total_files = 0\n        for folder in [\"Desktop\", \"Documents\", \"Pictures\", \"Downloads\"]:\n            src = os.path.join(user_profile, folder)\n            if os.path.exists(src):\n                try:\n                    dst = os.path.join(dest, folder)\n                    if os.path.exists(dst):\n                        shutil.rmtree(dst)\n                    shutil.copytree(src, dst)\n                    count = sum(len(files) for _, _, files in os.walk(dst))\n                    total_files += count\n                    self._shop_log(f\"\u2705 Backed up {folder} ({count} files)\", \"OK\")\n                except Exception as e:\n                    self._shop_log(f\"\u274c Failed {folder}: {e}\", \"ERR\")\n        self._shop_log(f\"\ud83c\udf89 Backup Complete! Total Files Saved: {total_files}\", \"OK\")\n\n    def _shop_driver_repair_pack(self):\n        self._shop_log(\"Exporting list of non-microsoft drivers...\", \"INFO\")\n        out, _ = self._run_cmd('driverquery /FO CSV /V')\n        lines = [l for l in out.splitlines() if \"Microsoft\" not in l]\n        fpath = os.path.join(os.path.expanduser(\"~\"), \"Desktop\", \"Godawari_Drivers_List.csv\")\n        with open(fpath, \"w\") as f:\n            f.write(\"\\n\".join(lines))\n        self._shop_log(f\"\u2705 Driver list saved to Desktop\", \"OK\")\n\n    def _shop_windows_update_repair(self):\n        self._shop_log(\"Resetting Windows Update Components...\", \"INFO\")\n        self._launch_job(\"shop_wu_repair\", self._do_wu_repair)\n\n    def _do_wu_repair(self):\n        cmds = ['net stop wuauserv', 'net stop bits', r'ren %systemroot%\\SoftwareDistribution SoftwareDistribution.bak', r'ren %systemroot%\\system32\\catroot2 catroot2.bak', 'net start wuauserv', 'net start bits']\n        for cmd in cmds:\n            self._run_cmd(cmd)\n        self._shop_log(\"\u2705 Windows Update Repair Done.\", \"OK\")\n\n    def _shop_browser_repair(self):\n        self._shop_log(\"Killing browsers and clearing caches...\", \"INFO\")\n        for exe in [\"chrome\",\"msedge\",\"firefox\"]:\n            self._run_cmd(f'taskkill /IM {exe}.exe /F')\n        local = os.environ.get(\"LOCALAPPDATA\",\"\")\n        for p in [os.path.join(local,\"Google\\\\Chrome\\\\User Data\\\\Default\\\\Cache\"), os.path.join(local,\"Microsoft\\\\Edge\\\\User Data\\\\Default\\\\Cache\")]:\n            self._delete_folder_contents(p)\n        self._shop_log(\"\u2705 Browser Repair done.\", \"OK\")\n\n    def _shop_service_preset(self):\n        results = [\n            self._service_config_checked(\"SysMain\", \"disabled\"),\n            self._service_stop_checked(\"SysMain\"),\n        ]\n        summary = self._action_summary(\"Service Preset\", results)\n        self._shop_log(\"Already done: Service Preset\" if summary[\"already_done\"] else \"Service Preset Applied.\", \"OK\")\n\n    def _shop_export_customer_report(self):\n        fpath = filedialog.asksaveasfilename(defaultextension=\".html\", filetypes=[(\"HTML Report\",\"*.html\")])\n        if fpath:\n            html = f\"\"\"Godawari Shop Reportbody{{font-family:Arial;background:#f4f4f4;padding:20px}}.box{{background:white;padding:15px;margin:10px 0;border-radius:5px;box-shadow:1px 1px 3px grey}}\n            \nGodawari Computers - Customer Report\n\nCustomer: {self.shop_customer_name.get()}\nIssue: {self.shop_issue.get()}\nDate: {datetime.datetime.now()}\n            \n\nDiagnosis Findings:\n{''.join(self.shop_findings)}\"\"\"\n            with open(fpath,\"w\", encoding=\"utf-8\") as f:\n                f.write(html)\n            self._shop_log(f\"Report exported: {fpath}\", \"OK\")\n            os.startfile(fpath)\n\n    def _shop_malware_driver_combo(self):\n        \"\"\"Malware scan + Driver repair \u2014 dono ek saath\"\"\"\n        self._shop_malware_pup_scan()\n        self.after(500, self._shop_driver_repair_pack)\n\n    def _shop_disk_backup_combo(self):\n        \"\"\"Disk health check + Customer backup \u2014 dono ek saath\"\"\"\n        self._shop_disk_health_risk()\n        self.after(500, self._shop_customer_backup)\n\n    def _shop_browser_update_combo(self):\n        \"\"\"Browser repair + Windows update repair \u2014 dono ek saath\"\"\"\n        self._shop_browser_repair()\n        self.after(500, self._shop_windows_update_repair)\n\n    # ---------- PROFESSIONAL JUNK CLEANER ----------\n    def _build_cleaner(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83e\uddf9 Junk Cleaner\", \"Scan \u2192 review \u2192 delete\")\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        #  ROOT: left (260px fixed) | right (expand)\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        content = tk.Frame(frame, bg=C[\"bg\"])\n        content.pack(fill=\"both\", expand=True, padx=14, pady=(6, 10))\n        content.columnconfigure(0, minsize=260, weight=0)\n        content.columnconfigure(1, weight=1)\n        content.rowconfigure(0, weight=1)\n\n        # \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        #  LEFT COLUMN\n        # \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        left_col = tk.Frame(content, bg=C[\"bg\"])\n        left_col.grid(row=0, column=0, sticky=\"nsew\", padx=(0, 8))\n        left_col.rowconfigure(1, weight=1)\n        left_col.columnconfigure(0, weight=1)\n\n        # \u2500\u2500 Card 1: Scan Targets \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        scan_card = tk.Frame(left_col, bg=C[\"card\"], relief=\"flat\", bd=0)\n        scan_card.grid(row=0, column=0, sticky=\"ew\", pady=(0, 6))\n        scan_card.columnconfigure(0, weight=1)\n\n        # Header row\n        hdr_row = tk.Frame(scan_card, bg=C[\"card\"])\n        hdr_row.pack(fill=\"x\", padx=10, pady=(8, 4))\n        tk.Label(hdr_row, text=\"Scan targets\", font=FONTS[\"small\"],\n                 fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\")\n\n        # 2-column checkbox grid\n        cb_outer = tk.Frame(scan_card, bg=C[\"card\"])\n        cb_outer.pack(fill=\"x\", padx=10, pady=(0, 6))\n        cb_outer.columnconfigure(0, weight=1)\n        cb_outer.columnconfigure(1, weight=1)\n\n        targets = [\n            (\"temp\",         \"Windows Temp\"),\n            (\"user_temp\",    \"User Temp\"),\n            (\"recycle\",      \"Recycle Bin\"),\n            (\"update\",       \"WU Cache\"),\n            (\"thumbnail\",    \"Thumbnail Cache\"),\n            (\"errreport\",    \"Error Reports\"),\n            (\"logs\",         \"Windows Logs\"),\n            (\"dumps\",        \"Memory Dumps\"),\n            (\"browser_office\",\"Browser Caches\"),\n            (\"delivery\",     \"Delivery Opt.\"),\n            (\"prefetch\",     \"Prefetch\"),\n        ]\n        for idx, (k, label) in enumerate(targets):\n            var = tk.BooleanVar(value=(k != \"prefetch\"))\n            self.clean_vars[k] = var\n            row_i, col_i = divmod(idx, 2)\n            cb = tk.Checkbutton(\n                cb_outer, text=label, variable=var,\n                font=FONTS[\"xsmall\"], fg=C[\"text\"], bg=C[\"card\"],\n                activebackground=C[\"card\"], selectcolor=C[\"panel\"],\n                bd=0, cursor=\"hand2\",\n            )\n            cb.grid(row=row_i, column=col_i, sticky=\"w\", padx=2, pady=1)\n\n        # Scan / Delete button row\n        btn_row = tk.Frame(scan_card, bg=C[\"card\"])\n        btn_row.pack(fill=\"x\", padx=10, pady=(2, 6))\n        btn_row.columnconfigure(0, weight=1)\n        btn_row.columnconfigure(1, weight=1)\n\n        tk.Button(\n            btn_row, text=\"\ud83d\udd0d  Scan\", font=FONTS[\"small\"],\n            bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, pady=6,\n            cursor=\"hand2\", relief=\"flat\",\n            command=self._professional_scan,\n        ).grid(row=0, column=0, sticky=\"ew\", padx=(0, 3))\n\n        tk.Button(\n            btn_row, text=\"\ud83d\uddd1  Delete\", font=FONTS[\"small\"],\n            bg=C[\"btn_danger\"], fg=C[\"text\"], bd=0, pady=6,\n            cursor=\"hand2\", relief=\"flat\",\n            command=self._professional_clean,\n        ).grid(row=0, column=1, sticky=\"ew\", padx=(3, 0))\n\n        # Progress + status\n        prog_frame = tk.Frame(scan_card, bg=C[\"card\"])\n        prog_frame.pack(fill=\"x\", padx=10, pady=(0, 4))\n\n        self.clean_size_lbl = tk.Label(\n            prog_frame, text=\"Total junk found: \u2014\",\n            font=FONTS[\"xsmall\"], fg=C[\"accent4\"], bg=C[\"card\"], anchor=\"w\")\n        self.clean_size_lbl.pack(fill=\"x\")\n\n        self.clean_progress_var = tk.DoubleVar(value=0.0)\n        self.clean_progress_bar = ttk.Progressbar(\n            prog_frame, variable=self.clean_progress_var,\n            maximum=100.0, mode=\"determinate\")\n        self.clean_progress_bar.pack(fill=\"x\", pady=(3, 2))\n\n        self.clean_progress_lbl = tk.Label(\n            prog_frame, text=\"Ready\",\n            font=FONTS[\"xsmall\"], fg=C[\"text_dim\"], bg=C[\"card\"], anchor=\"w\")\n        self.clean_progress_lbl.pack(fill=\"x\")\n\n        # Preview checkbox\n        sep1 = tk.Frame(scan_card, bg=C[\"border\"], height=1)\n        sep1.pack(fill=\"x\", padx=10, pady=(4, 3))\n\n        self.clean_preview_var = tk.BooleanVar(value=False)\n        tk.Checkbutton(\n            scan_card, text=\"Preview only (no delete)\",\n            variable=self.clean_preview_var,\n            font=FONTS[\"xsmall\"], fg=C[\"text_dim\"], bg=C[\"card\"],\n            activebackground=C[\"card\"], selectcolor=C[\"panel\"], bd=0,\n        ).pack(anchor=\"w\", padx=10, pady=(0, 8))\n\n        # \u2500\u2500 Card 2: Cleanup Tools (tabbed 2\u00d72 grid) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        tools_card = tk.Frame(left_col, bg=C[\"card\"], relief=\"flat\", bd=0)\n        tools_card.grid(row=1, column=0, sticky=\"nsew\")\n        tools_card.columnconfigure(0, weight=1)\n\n        tk.Label(tools_card, text=\"Cleanup tools\", font=FONTS[\"small\"],\n                 fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=10, pady=(8, 4))\n\n        # Tab bar\n        tab_bar = tk.Frame(tools_card, bg=C[\"card\"])\n        tab_bar.pack(fill=\"x\", padx=10, pady=(0, 6))\n\n        tool_panels = {}\n        _active_tab = tk.StringVar(value=\"browser\")\n\n        def _make_tab(parent, label, key):\n            def _switch():\n                _active_tab.set(key)\n                for k2, p in tool_panels.items():\n                    p.pack_forget()\n                tool_panels[key].pack(fill=\"x\", padx=10, pady=(0, 8))\n                for w in tab_bar.winfo_children():\n                    w.config(relief=\"flat\",\n                             bg=C[\"accent\"] if w._tab_key == key else C[\"panel\"],\n                             fg=C[\"bg\"]     if w._tab_key == key else C[\"text_dim\"])\n            btn = tk.Button(tab_bar, text=label, font=FONTS[\"xsmall\"],\n                            bg=C[\"panel\"], fg=C[\"text_dim\"],\n                            bd=0, padx=10, pady=3, cursor=\"hand2\",\n                            relief=\"flat\", command=_switch)\n            btn._tab_key = key\n            btn.pack(side=\"left\", padx=(0, 4))\n            return btn\n\n        tab_browser = _make_tab(tab_bar, \"Browser\", \"browser\")\n        tab_system  = _make_tab(tab_bar, \"System\",  \"system\")\n        tab_files   = _make_tab(tab_bar, \"Files\",   \"files\")\n\n        # Helper: build a 2-col tool card grid\n        def _tool_grid(parent, items):\n            \"\"\"items = list of (icon_char, title, subtitle, command)\"\"\"\n            g = tk.Frame(parent, bg=C[\"card\"])\n            g.columnconfigure(0, weight=1)\n            g.columnconfigure(1, weight=1)\n            for idx, (icon, title, sub, cmd) in enumerate(items):\n                ri, ci = divmod(idx, 2)\n                cell = tk.Frame(g, bg=C[\"panel\"], cursor=\"hand2\")\n                cell.grid(row=ri, column=ci, sticky=\"nsew\",\n                          padx=(0 if ci else 0, 3 if ci == 0 else 0),\n                          pady=(0, 3))\n                cell.columnconfigure(0, weight=1)\n                tk.Label(cell, text=icon, font=(\"Segoe UI Emoji\", 14),\n                         bg=C[\"panel\"], fg=C[\"text\"]).pack(anchor=\"w\", padx=8, pady=(7, 1))\n                tk.Label(cell, text=title, font=FONTS[\"xsmall\"],\n                         fg=C[\"text\"], bg=C[\"panel\"]).pack(anchor=\"w\", padx=8)\n                tk.Label(cell, text=sub, font=(\"Segoe UI\", 8),\n                         fg=C[\"text_dim\"], bg=C[\"panel\"],\n                         wraplength=108, justify=\"left\").pack(anchor=\"w\", padx=8, pady=(0, 7))\n                cell.bind(\"\", lambda e, c=cmd: c())\n                for child in cell.winfo_children():\n                    child.bind(\"\", lambda e, c=cmd: c())\n                cell.bind(\"\", lambda e, w=cell: w.config(bg=C[\"card\"]))\n                cell.bind(\"\", lambda e, w=cell: w.config(bg=C[\"panel\"]))\n            return g\n\n        # Browser tab\n        tool_panels[\"browser\"] = _tool_grid(tools_card, [\n            (\"\ud83c\udf10\", \"Browser boost\",   \"Cache, shader, all browsers\",   self._open_browser_boost_window),\n            (\"\u26a1\", \"Launch flags\",    \"Startup speed flags\",            self._open_browser_speed_flags_window),\n            (\"\ud83d\uddc4\", \"DB vacuum\",       \"SQLite VACUUM (Chrome/Edge)\",\n             lambda: self._confirm_and_launch_job(\n                 \"Browser DB Turbo Vacuum\",\n                 \"Vacuum browser SQLite DBs and purge shader caches.\",\n                 None, \"browser_turbo\", self._do_browser_turbo_boost)),\n            (\"\ud83d\udcac\", \"Social cache\",   \"Discord, Telegram, WhatsApp\",\n             lambda: self._confirm_and_launch_job(\n                 \"Social Media Cache Purge\",\n                 \"Wipe Discord and Telegram desktop caches.\",\n                 None, \"social_cache\", self._do_social_media_cache_purge)),\n        ])\n\n        # System tab\n        tool_panels[\"system\"] = _tool_grid(tools_card, [\n            (\"\ud83d\uddc2\", \"Installer orphans\", \"Scan \u2192 review \u2192 delete\",       self._open_installer_orphan_scanner),\n            (\"\ud83c\udfae\", \"DirectX cache\",     \"GPU shader cache purge\",\n             lambda: self._confirm_and_launch_job(\n                 \"DirectX Shader Cache Purger\",\n                 \"Purge D3DSCache and DirectX WebCache.\",\n                 None, \"directx_shader\", self._do_purge_directx_shader_cache)),\n            (\"\ud83d\udca5\", \"Crash dumps\",       \"Review before delete\",          self._do_trim_system_crash_dumps),\n            (\"\u2699\", \"Prefetch\",          \"Age-based review\",              self._do_clean_prefetch),\n            (\"\ud83d\ude9a\", \"Delivery opt.\",     \"WU download cache\",\n             lambda: self._confirm_and_launch_job(\n                 \"Delivery Optimization Cleaner\",\n                 \"Purge Windows update cache safely (requires admin).\",\n                 None, \"delivery_opt\", self._do_purge_delivery_optimization)),\n        ])\n\n        # Files tab\n        tool_panels[\"files\"] = _tool_grid(tools_card, [\n            (\"\ud83d\udcc1\", \"Empty folders\",  \"Find &amp; remove empty dirs\",   self._open_empty_folder_finder),\n            (\"\ud83d\udd0d\", \"0-byte files\",   \"Scanner\",                    self._open_zero_byte_finder),\n        ])\n\n        # Show default tab\n        tool_panels[\"browser\"].pack(fill=\"x\", padx=10, pady=(0, 8))\n        tab_browser.config(bg=C[\"accent\"], fg=C[\"bg\"])\n\n        # \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        #  RIGHT COLUMN\n        # \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        right_col = tk.Frame(content, bg=C[\"bg\"])\n        right_col.grid(row=0, column=1, sticky=\"nsew\")\n        right_col.rowconfigure(1, weight=1)\n        right_col.columnconfigure(0, weight=1)\n\n        # \u2500\u2500 Stat cards row \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        stats_row = tk.Frame(right_col, bg=C[\"bg\"])\n        stats_row.grid(row=0, column=0, sticky=\"ew\", pady=(0, 6))\n        for i in range(3):\n            stats_row.columnconfigure(i, weight=1)\n\n        def _stat_card(parent, col, label):\n            card = tk.Frame(parent, bg=C[\"card\"], relief=\"flat\", bd=0)\n            card.grid(row=0, column=col, sticky=\"nsew\",\n                      padx=(0 if col == 0 else 4, 4 if col &lt; 2 else 0))\n            val_lbl = tk.Label(card, text=\"\u2014\", font=FONTS[\"subhead\"],\n                               fg=C[\"text\"], bg=C[\"card\"])\n            val_lbl.pack(anchor=\"w\", padx=10, pady=(8, 0))\n            tk.Label(card, text=label, font=FONTS[\"xsmall\"],\n                     fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=10, pady=(0, 8))\n            return val_lbl\n\n        self._stat_junk_lbl   = _stat_card(stats_row, 0, \"Junk found\")\n        self._stat_freed_lbl  = _stat_card(stats_row, 1, \"Freed this session\")\n        self._stat_files_lbl  = _stat_card(stats_row, 2, \"Files removed\")\n\n        # \u2500\u2500 Log card \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        log_card = tk.Frame(right_col, bg=C[\"card\"], relief=\"flat\", bd=0)\n        log_card.grid(row=1, column=0, sticky=\"nsew\")\n        log_card.rowconfigure(1, weight=1)\n        log_card.columnconfigure(0, weight=1)\n\n        # Log header\n        log_hdr = tk.Frame(log_card, bg=C[\"card\"])\n        log_hdr.grid(row=0, column=0, sticky=\"ew\", padx=10, pady=(8, 4))\n        tk.Label(log_hdr, text=\"Activity log\", font=FONTS[\"small\"],\n                 fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\")\n\n        # Action buttons \u2014 right side of log header\n        btn_area = tk.Frame(log_hdr, bg=C[\"card\"])\n        btn_area.pack(side=\"right\")\n        self.clean_report_btn = self._btn(btn_area, \"Export\", C[\"btn_chip\"], self._export_clean_report)\n        self.clean_report_btn.pack(side=\"left\", padx=(0, 4))\n        self.clean_cancel_btn = self._btn(btn_area, \"Cancel\", C[\"btn_warn\"], self._cancel_clean_job)\n        self.clean_cancel_btn.pack(side=\"left\")\n        self.clean_cancel_btn.config(state=\"disabled\")\n        self.clean_report_btn.config(state=\"disabled\")\n\n        # Log text widget\n        log_inner = tk.Frame(log_card, bg=C[\"card\"])\n        log_inner.grid(row=1, column=0, sticky=\"nsew\", padx=10, pady=(0, 10))\n        log_inner.rowconfigure(0, weight=1)\n        log_inner.columnconfigure(0, weight=1)\n\n        clean_log_widget = tk.Text(\n            log_inner,\n            wrap=\"word\",\n            font=FONTS.get(\"mono\", (\"Consolas\", 9)),\n            bg=C[\"bg\"], fg=C[\"text\"],\n            insertbackground=C[\"text\"],\n            relief=\"flat\", bd=0,\n            state=\"disabled\",\n            padx=8, pady=8,\n        )\n        clean_log_sb = ttk.Scrollbar(log_inner, orient=\"vertical\",\n                                     command=clean_log_widget.yview)\n        clean_log_widget.configure(yscrollcommand=clean_log_sb.set)\n        clean_log_widget.grid(row=0, column=0, sticky=\"nsew\")\n        clean_log_sb.grid(row=0, column=1, sticky=\"ns\")\n        self.clean_log = clean_log_widget\n\n        return frame\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  SUPER BOOST ALL BROWSERS \u2014 Browser Junk Cleaner (Popup Window)\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    # Protected file stems \u2014 KABHI TOUCH NAHI KARNA\n    _BROWSER_PROTECTED_STEMS = frozenset({\n        \"Login Data\", \"Login Data For Account\", \"Bookmarks\", \"Cookies\",\n        \"Web Data\", \"Preferences\", \"Secure Preferences\", \"Favicons\",\n        \"History\", \"Top Sites\", \"Extension State\",\n        \"Local Extension Settings\", \"Extensions\",\n    })\n    _BROWSER_CHROMIUM_CACHE_DIRS = (\n        \"GPUCache\", \"Code Cache\", \"Crashpad\", \"ShaderCache\",\n        \"GrShaderCache\", \"DawnCache\", \"blob_storage\",\n        \"Service Worker\", \"Service Worker/CacheStorage\", \"Service Worker/ScriptCache\",\n        \"Code Cache/js\", \"Cache\", \"Application Cache\",\n    )\n    _BROWSER_FIREFOX_CACHE_DIRS = (\"startupCache\", \"shader-cache\", \"cache2\")\n    _BROWSER_SAFE_EXTS  = (\".tmp\", \".old\", \".bak\", \".log\", \".dmp\", \".temp\")\n    _BROWSER_SQLITE_EXT = (\"-wal\", \"-journal\", \"-shm\", \".wal\", \".journal\", \".shm\")\n    _BROWSER_SPEED_FLAGS = (\n        \"--no-first-run\",\n        \"--no-default-browser-check\",\n        \"--disable-background-networking\",\n        \"--disable-translate\",\n        \"--disable-features=TranslateUI,MediaRouter\",\n        \"--enable-features=NetworkServiceInProcess\",\n    )\n\n    def _browser_is_protected(self, path):\n        \"\"\"Return True if path must NEVER be touched.\"\"\"\n        import pathlib\n        p = pathlib.Path(path)\n        name, stem = p.name, p.stem\n        if name in self._BROWSER_PROTECTED_STEMS or stem in self._BROWSER_PROTECTED_STEMS:\n            return True\n        for ext in self._BROWSER_SQLITE_EXT:\n            if name.endswith(ext):\n                base = name[: -len(ext)]\n                if base in self._BROWSER_PROTECTED_STEMS:\n                    return True\n        for part in p.parts:\n            if part in (\"Extensions\", \"Local Extension Settings\", \"Extension State\"):\n                return True\n        return False\n\n    def _browser_dir_size(self, path):\n        total = 0\n        try:\n            for root_d, _, files in os.walk(path):\n                for f in files:\n                    try:\n                        total += os.path.getsize(os.path.join(root_d, f))\n                    except Exception:\n                        continue\n        except Exception:\n            return total\n        return total\n\n    def _browser_detect_all(self):\n        \"\"\"Detect all installed browsers and return list of profile dicts.\"\"\"\n        local   = os.environ.get(\"LOCALAPPDATA\", \"\")\n        appdata = os.environ.get(\"APPDATA\", \"\")\n        profiles = []\n\n        chromium_defs = [\n            (\"Google Chrome\",      os.path.join(local,   \"Google\", \"Chrome\", \"User Data\")),\n            (\"Google Chrome Beta\", os.path.join(local,   \"Google\", \"Chrome Beta\", \"User Data\")),\n            (\"Google Chrome Canary\", os.path.join(local, \"Google\", \"Chrome SxS\", \"User Data\")),\n            (\"Microsoft Edge\",     os.path.join(local,   \"Microsoft\", \"Edge\", \"User Data\")),\n            (\"Microsoft Edge Beta\", os.path.join(local,  \"Microsoft\", \"Edge Beta\", \"User Data\")),\n            (\"Microsoft Edge Dev\", os.path.join(local,   \"Microsoft\", \"Edge Dev\", \"User Data\")),\n            (\"Microsoft Edge Canary\", os.path.join(local, \"Microsoft\", \"Edge Canary\", \"User Data\")),\n            (\"Brave Browser\",      os.path.join(local,   \"BraveSoftware\", \"Brave-Browser\", \"User Data\")),\n            (\"Brave Browser Beta\", os.path.join(local,   \"BraveSoftware\", \"Brave-Browser Beta\", \"User Data\")),\n            (\"Chromium\",           os.path.join(local,   \"Chromium\", \"User Data\")),\n            (\"Opera\",              os.path.join(appdata, \"Opera Software\", \"Opera Stable\")),\n            (\"Opera GX\",           os.path.join(appdata, \"Opera Software\", \"Opera GX Stable\")),\n            (\"Vivaldi\",            os.path.join(local,   \"Vivaldi\", \"User Data\")),\n        ]\n\n        for bname, base in chromium_defs:\n            if not os.path.isdir(base):\n                continue\n            candidates = [os.path.join(base, \"Default\")]\n            try:\n                for entry in os.scandir(base):\n                    if entry.is_dir() and entry.name.startswith(\"Profile \"):\n                        candidates.append(entry.path)\n            except Exception:\n                pass\n            for prof_path in candidates:\n                if not os.path.isdir(prof_path):\n                    continue\n                caches = []\n                # Caches are INSIDE the profile folder (Default\\GPUCache etc.)\n                for cdir in self._BROWSER_CHROMIUM_CACHE_DIRS:\n                    c = os.path.join(prof_path, cdir)\n                    if os.path.isdir(c):\n                        caches.append(c)\n                # Also check Cache folder variants\n                for extra in (\"Cache\", \"cache\", \"Application Cache\", \"Service Worker\",\n                              \"ScriptCache\", \"JumpListIconsOld\"):\n                    c = os.path.join(prof_path, extra)\n                    if os.path.isdir(c):\n                        caches.append(c)\n                profiles.append({\n                    \"browser\": bname, \"profile\": prof_path, \"caches\": caches\n                })\n\n        # Firefox wildcard profile detection\n        ff_root = os.path.join(appdata, \"Mozilla\", \"Firefox\", \"Profiles\")\n        if os.path.isdir(ff_root):\n            seen = set()\n            for pattern in (\"*.default-release\", \"*.default\", \"*.release\", \"*\"):\n                try:\n                    import glob\n                    for match in glob.glob(os.path.join(ff_root, pattern)):\n                        if not os.path.isdir(match) or match in seen:\n                            continue\n                        seen.add(match)\n                        caches = []\n                        for cdir in self._BROWSER_FIREFOX_CACHE_DIRS:\n                            c = os.path.join(match, cdir)\n                            if os.path.isdir(c):\n                                caches.append(c)\n                        ff_local_cache = os.path.join(\n                            local, \"Mozilla\", \"Firefox\", \"Profiles\",\n                            os.path.basename(match))\n                        if os.path.isdir(ff_local_cache):\n                            caches.append(ff_local_cache)\n                        profiles.append({\n                            \"browser\": \"Firefox\", \"profile\": match, \"caches\": caches\n                        })\n                except Exception:\n                    pass\n        return profiles\n\n    def _browser_scan_profile(self, prof_dict):\n        \"\"\"Scan one profile for junk. Returns list of (path, size, reason).\"\"\"\n        items = []\n\n        def record(p, reason):\n            if self._browser_is_protected(p):\n                return\n            try:\n                sz = os.path.getsize(p) if os.path.isfile(p) else self._browser_dir_size(p)\n                items.append((p, sz, reason))\n            except Exception:\n                pass\n\n        for cache_dir in prof_dict[\"caches\"]:\n            if os.path.isdir(cache_dir) and not self._browser_is_protected(cache_dir):\n                record(cache_dir, \"Rendering/GPU cache\")\n\n        prof = prof_dict[\"profile\"]\n        for ext in self._BROWSER_SQLITE_EXT:\n            try:\n                for root_d, _, files in os.walk(prof):\n                    for f in files:\n                        if f.endswith(ext):\n                            fp = os.path.join(root_d, f)\n                            if not self._browser_is_protected(fp):\n                                record(fp, f\"SQLite fragment ({ext})\")\n            except Exception:\n                pass\n\n        for ext in self._BROWSER_SAFE_EXTS:\n            try:\n                for root_d, _, files in os.walk(prof):\n                    for f in files:\n                        if f.endswith(ext):\n                            fp = os.path.join(root_d, f)\n                            if not self._browser_is_protected(fp):\n                                record(fp, f\"Temp/junk ({ext})\")\n            except Exception:\n                pass\n\n        return items\n\n    def _browser_speed_flag_list(self):\n        return \" \".join(self._BROWSER_SPEED_FLAGS)\n\n    def _browser_update_shortcuts_with_speed_flags(self):\n        if not sys.platform.startswith(\"win\"):\n            return False, \"Windows required for shortcut flags.\"\n        flags = self._browser_speed_flag_list()\n        safe_names = [\"chrome.exe\", \"msedge.exe\", \"brave.exe\", \"opera.exe\", \"vivaldi.exe\", \"firefox.exe\", \"chromium.exe\"]\n        ps_paths = [\n            '$HOME\\\\Desktop',\n            '$env:APPDATA\\\\Microsoft\\\\Windows\\\\Start Menu\\\\Programs',\n            '$env:PROGRAMDATA\\\\Microsoft\\\\Windows\\\\Start Menu\\\\Programs',\n        ]\n        ps = [\n            '$w = New-Object -ComObject WScript.Shell',\n            '$updated = 0',\n            '$skipped = 0',\n            '$lines = @()'\n        ]\n        for root in ps_paths:\n            ps.append(f'if (Test-Path {root}) {{ Get-ChildItem -Path {root} -Filter *.lnk -Recurse -ErrorAction SilentlyContinue | ForEach-Object {{'\n                      ' try {'\n                      ' $sc = $w.CreateShortcut($_.FullName);'\n                      ' $target = $sc.TargetPath;'\n                      ' if ($target) {'\n                      '   $lc = $target.ToLower();'\n                      f'   if ({\" -or \".join([f\"$lc.EndsWith(\\\\\\\"{name}\\\\\\\")\" for name in safe_names])}) {{'\n                      '     $existing = $sc.Arguments;'\n                      '     if ($existing -notmatch \"--no-first-run\") {'\n                      f'       $sc.Arguments = ($existing + \" {flags}\").Trim();'\n                      '       $sc.Save();'\n                      '       $updated += 1;'\n                      '       $lines += $_.FullName;'\n                      '     } else { $skipped += 1 }'\n                      '   }'\n                      ' }'\n                      ' } catch { }'\n                      ' } }')\n        ps.append('Write-Output \"$updated|$skipped\"')\n        ps.append('$lines | ForEach-Object { Write-Output $_ }')\n        script = \"; \".join(ps)\n        out, rc = powershell_helper(script, timeout=60)\n        if rc != 0:\n            return False, out.strip()\n        lines = [line.strip() for line in out.splitlines() if line.strip()]\n        if not lines:\n            return False, \"No browser shortcuts found or nothing changed.\"\n        summary = lines[0]\n        changed = lines[1:]\n        return True, f\"Updated shortcuts: {summary}.\\n\" + \"\\n\".join(changed)\n\n    def _open_browser_speed_flags_window(self):\n        win = tk.Toplevel(self)\n        win.title(\"\u26a1 Advanced Browser Launch Flags \u2014 Godawari Optimizer Pro\")\n        try:\n            screen_w = win.winfo_screenwidth()\n            screen_h = win.winfo_screenheight()\n            win.geometry(f\"{max(900, int(screen_w*0.75))}x{max(600, int(screen_h*0.72))}\")\n        except Exception:\n            win.geometry(\"920x620\")\n        win.minsize(780, 520)\n        win.configure(bg=C[\"bg\"])\n        win.grab_set()\n        self._append_log(self.clean_log, \"\u2501\"*52, C[\"border\"])\n        self._append_log(self.clean_log, \"\u26a1  Advanced Browser Launch Flags \u2014 window opened\", C[\"accent\"])\n        self._append_log(self.clean_log, \"\u2501\"*52, C[\"border\"])\n\n        header = tk.Frame(win, bg=C[\"panel\"], pady=10)\n        header.pack(fill=\"x\")\n        tk.Label(header, text=\"\u26a1 Advanced Browser Launch Flags\", font=(\"Segoe UI\", 13, \"bold\"), bg=C[\"panel\"], fg=C[\"accent\"]).pack(side=\"left\", padx=18)\n        tk.Label(header, text=\"This advanced mode only changes browser shortcut startup flags, not your saved passwords or bookmarks.\",\n                 font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text_dim\"]).pack(side=\"right\", padx=18)\n        tk.Frame(header, bg=C[\"accent\"], height=2).pack(side=\"bottom\", fill=\"x\")\n\n        body = tk.Frame(win, bg=C[\"bg\"])\n        body.pack(fill=\"both\", expand=True, padx=12, pady=10)\n        body.columnconfigure(0, weight=1)\n        body.rowconfigure(1, weight=1)\n\n        expl = tk.Label(body, text=(\n            \"Advanced browser launch flags can improve startup speed and reduce background work while preserving passwords/bookmarks. \"\n            \"This is separate from the regular junk cleaner because it changes how the browser starts, not which files are deleted.\"\n        ), font=FONTS[\"small\"], fg=C[\"text\"], bg=C[\"bg\"], wraplength=820, justify=\"left\")\n        expl.grid(row=0, column=0, sticky=\"w\", pady=(0,12))\n\n        flags_frame = tk.Frame(body, bg=C[\"card\"], bd=1, relief=\"solid\")\n        flags_frame.grid(row=1, column=0, sticky=\"nsew\")\n        flags_frame.columnconfigure(0, weight=1)\n        tk.Label(flags_frame, text=\"Recommended Safe Startup Flags\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=12, pady=(12,4))\n        tk.Label(flags_frame, text=self._browser_speed_flag_list(), font=FONTS[\"small\"], fg=C[\"text\"], bg=C[\"card\"], wraplength=800, justify=\"left\").pack(fill=\"x\", padx=12, pady=(0,12))\n\n        info = tk.Label(flags_frame,\n            text=\"These flags are safe for launch shortcuts and avoid touching password or bookmark storage.\",\n            font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=800, justify=\"left\"\n        )\n        info.pack(fill=\"x\", padx=12, pady=(0,14))\n\n        result_box = scrolledtext.ScrolledText(flags_frame, height=12, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"], relief=\"flat\", bd=0, state=\"disabled\", wrap=\"word\")\n        result_box.pack(fill=\"both\", expand=True, padx=12, pady=(0,10))\n\n        def append_result(text, tag=None):\n            result_box.configure(state=\"normal\")\n            result_box.insert(\"end\", text + \"\\n\")\n            if tag:\n                result_box.tag_add(tag, \"end-2l\", \"end-1c\")\n            result_box.see(\"end\")\n            result_box.configure(state=\"disabled\")\n            # Mirror to main clean log\n            tag_color_map = {\"ok\": C[\"success\"], \"warn\": C[\"warning\"], \"err\": C[\"error\"], \"muted\": C[\"text_dim\"]}\n            self._append_log(self.clean_log, text, tag_color_map.get(tag, C[\"text\"]))\n\n        def apply_flags():\n            append_result(\"Starting advanced browser shortcut optimization...\", \"muted\")\n            def _worker():\n                ok, message = self._browser_update_shortcuts_with_speed_flags()\n                if ok:\n                    win.after(0, lambda: append_result(\"\u2705 Advanced flags applied successfully.\", \"ok\"))\n                    win.after(0, lambda: append_result(message, \"muted\"))\n                else:\n                    win.after(0, lambda: append_result(\"\u26a0 Failed to apply advanced flags.\", \"err\"))\n                    win.after(0, lambda: append_result(message, \"err\"))\n            threading.Thread(target=_worker, daemon=True).start()\n\n        result_box.tag_configure(\"ok\", foreground=C[\"success\"])\n        result_box.tag_configure(\"warn\", foreground=C[\"warning\"])\n        result_box.tag_configure(\"err\", foreground=C[\"error\"])\n        result_box.tag_configure(\"muted\", foreground=C[\"text_dim\"])\n\n        button_row = tk.Frame(win, bg=C[\"bg\"], pady=10)\n        button_row.pack(fill=\"x\", side=\"bottom\")\n        tk.Button(button_row, text=\"Apply Advanced Browser Launch Flags\", bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=14, pady=8,\n                  cursor=\"hand2\", command=apply_flags).pack(side=\"left\", padx=12)\n        tk.Button(button_row, text=\"Close\", bg=C[\"panel\"], fg=C[\"text\"], bd=0, padx=14, pady=8,\n                  cursor=\"hand2\", command=win.destroy).pack(side=\"right\", padx=12)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # ENTERPRISE-GRADE BROWSER OPTIMIZATION HELPERS\n    # SQLite, Profile Integrity, Extensions, GPU, Performance Metrics, Memory\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _browser_sqlite_analyze(self, db_path):\n        \"\"\"Analyze SQLite database fragmentation and corruption.\"\"\"\n        try:\n            if not os.path.isfile(db_path):\n                return 0, 0, 0, \"not_found\"\n            conn = sqlite3.connect(f\"file:{db_path}?mode=ro\", uri=True, timeout=5)\n            cursor = conn.cursor()\n            cursor.execute(\"PRAGMA page_count\")\n            page_count = cursor.fetchone()[0] or 0\n            cursor.execute(\"PRAGMA freelist_count\")\n            free_pages = cursor.fetchone()[0] or 0\n            fragmentation = round((free_pages / max(1, page_count)) * 100, 2) if page_count &gt; 0 else 0\n            conn.close()\n            return page_count, free_pages, fragmentation, \"ok\"\n        except Exception as e:\n            return 0, 0, 0, f\"error\"\n\n    def _browser_profile_integrity_check(self, profile_path, browser_type=\"chromium\"):\n        \"\"\"Check browser profile for corruption and critical file issues.\"\"\"\n        issues = []\n        try:\n            if not os.path.isdir(profile_path):\n                return [(\"profile_missing\", \"critical\", \"Profile not found\")]\n            if browser_type.lower() in (\"chromium\", \"chrome\", \"edge\", \"brave\", \"opera\"):\n                critical = [\"Preferences\", \"Web Data\", \"History\"]\n                for cf in critical:\n                    cpath = os.path.join(profile_path, cf)\n                    if not os.path.exists(cpath):\n                        issues.append((f\"missing_{cf.lower()}\", \"warning\", f\"{cf} missing\"))\n                    elif cf in (\"Web Data\", \"History\"):\n                        pages, free, frag, status = self._browser_sqlite_analyze(cpath)\n                        if frag &gt; 30:\n                            issues.append((f\"fragmented_{cf.lower()}\", \"warning\", f\"{frag}% fragmented\"))\n        except Exception:\n            pass\n        return issues\n\n    def _browser_extension_analysis(self, profile_path, browser_type=\"chromium\"):\n        \"\"\"Analyze installed extensions.\"\"\"\n        extensions = []\n        try:\n            if browser_type.lower() in (\"chromium\", \"chrome\", \"edge\", \"brave\"):\n                ext_dir = os.path.join(profile_path, \"Extensions\")\n                if os.path.isdir(ext_dir):\n                    for ext_id in os.listdir(ext_dir):\n                        ext_path = os.path.join(ext_dir, ext_id)\n                        if os.path.isdir(ext_path):\n                            size = self._browser_dir_size(ext_path)\n                            name = ext_id\n                            try:\n                                manifest_path = os.path.join(ext_path, \"manifest.json\")\n                                if os.path.isfile(manifest_path):\n                                    with open(manifest_path, 'r', encoding='utf-8', errors='replace') as f:\n                                        manifest = json.load(f)\n                                        name = manifest.get(\"name\", ext_id)\n                            except:\n                                pass\n                            extensions.append({\"id\": ext_id, \"name\": name, \"size_bytes\": size})\n        except Exception:\n            pass\n        return extensions\n\n    def _browser_gpu_acceleration_check(self):\n        \"\"\"Check GPU availability and driver version.\"\"\"\n        try:\n            script = \"Get-WmiObject Win32_VideoController -ErrorAction SilentlyContinue | Select-Object Name, DriverVersion | ConvertTo-Json\"\n            result = safe_powershell(script, timeout=20)\n            try:\n                data = json.loads(result.output)\n                if data:\n                    driver = data.get(\"DriverVersion\", \"\") if isinstance(data, dict) else \"\"\n                    return True, True, driver\n            except:\n                pass\n            return False, False, \"\"\n        except Exception:\n            return False, False, \"\"\n\n    def _browser_startup_performance_measure(self, browser_name):\n        \"\"\"Measure browser startup time and memory usage.\"\"\"\n        try:\n            exe_map = {\"chrome\": \"chrome.exe\", \"edge\": \"msedge.exe\", \"brave\": \"brave.exe\", \"firefox\": \"firefox.exe\"}\n            exe = exe_map.get(browser_name.lower())\n            if not exe:\n                return 0, 0, \"unknown\"\n            result = subprocess.run([\"where\", exe], capture_output=True, text=True, timeout=10)\n            if result.returncode != 0:\n                return 0, 0, \"not_installed\"\n            browser_exe = result.stdout.strip().split('\\n')[0]\n            started = time.time()\n            proc = subprocess.Popen([browser_exe, \"--no-first-run\", \"--no-default-browser-check\"],\n                                   stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)\n            time.sleep(2)\n            startup_ms = int((time.time() - started) * 1000)\n            try:\n                if hasattr(proc, 'pid') and proc.pid:\n                    browser_proc = psutil.Process(proc.pid)\n                    mem = browser_proc.memory_info().rss / (1024**2)\n                else:\n                    mem = 0\n            except Exception:\n                mem = 0\n            try:\n                proc.terminate()\n                proc.wait(timeout=5)\n            except Exception:\n                try:\n                    proc.kill()\n                except Exception:\n                    pass\n            return startup_ms, mem, \"ok\"\n        except Exception:\n            return 0, 0, \"error\"\n\n    def _browser_memory_profile_analysis(self, profile_path):\n        \"\"\"Analyze profile size and cache memory.\"\"\"\n        try:\n            profile_size = self._browser_dir_size(profile_path) / (1024**2)\n            cache_size = 0\n            for cache_dir in (\"Cache\", \"cache\", \"GPUCache\", \"Code Cache\"):\n                cache_path = os.path.join(profile_path, cache_dir)\n                if os.path.isdir(cache_path):\n                    cache_size += self._browser_dir_size(cache_path) / (1024**2)\n            return round(profile_size, 2), round(cache_size, 2)\n        except Exception:\n            return 0, 0\n\n    def _browser_comprehensive_report(self, profile_dict):\n        \"\"\"Generate comprehensive browser optimization report.\"\"\"\n        report = {\n            \"browser\": profile_dict.get(\"browser\", \"unknown\"),\n            \"profile_path\": profile_dict.get(\"profile\", \"\"),\n            \"profile_size_mb\": 0,\n            \"cache_size_mb\": 0,\n            \"extensions_count\": 0,\n            \"extensions\": [],\n            \"startup_time_ms\": 0,\n            \"memory_usage_mb\": 0,\n            \"integrity_issues\": [],\n            \"optimization_score\": 100,\n        }\n        try:\n            profile_size, cache_size = self._browser_memory_profile_analysis(profile_dict.get(\"profile\", \"\"))\n            report[\"profile_size_mb\"] = profile_size\n            report[\"cache_size_mb\"] = cache_size\n            browser_type = \"firefox\" if \"Firefox\" in report[\"browser\"] else \"chromium\"\n            issues = self._browser_profile_integrity_check(profile_dict.get(\"profile\", \"\"), browser_type)\n            report[\"integrity_issues\"] = issues\n            exts = self._browser_extension_analysis(profile_dict.get(\"profile\", \"\"), browser_type)\n            report[\"extensions\"] = exts\n            report[\"extensions_count\"] = len(exts)\n            score = 100 - min(20, cache_size / 50) - min(15, len(issues) * 5) - min(15, max(0, (len(exts) - 50) / 5))\n            report[\"optimization_score\"] = max(0, int(score))\n        except Exception:\n            pass\n        return report\n\n    def _open_browser_boost_window(self):\n        \"\"\"ENTERPRISE-GRADE BROWSER OPTIMIZATION ENGINE\n        \n        Requirements met:\n        - Real SQLite analysis (fragmentation, corruption detection)\n        - Profile integrity checking\n        - Extension performance analysis\n        - GPU acceleration status\n        - Startup performance measurement\n        - Memory profiling\n        - Corrupted profile detection and repair\n        - Before/after measurement (startup time, memory, cache size)\n        - Comprehensive browser benchmark comparison\n        - Absolute safety: NO modification to passwords, bookmarks, logins, profiles\n        - Dry-run reports before actual cleanup\n        - Full restoration capability via journaling\n        \"\"\"\n        win = tk.Toplevel(self)\n        win.title(\"\ud83d\ude80 Enterprise Browser Optimization Engine \u2014 Godawari Optimizer Pro\")\n        try:\n            screen_w = win.winfo_screenwidth()\n            screen_h = win.winfo_screenheight()\n            win.geometry(f\"{max(1200, int(screen_w*0.90))}x{max(800, int(screen_h*0.88))}\")\n        except Exception:\n            win.geometry(\"1220x820\")\n        win.minsize(1000, 680)\n        win.configure(bg=C[\"bg\"])\n        win.grab_set()\n        self._append_log(self.clean_log, \"\\u2501\"*52, C[\"border\"])\n        self._append_log(self.clean_log, \"\\U0001f310  Super Boost All Browsers \\u2014 window opened\", C[\"accent\"])\n        self._append_log(self.clean_log, \"\\u2501\"*52, C[\"border\"])\n\n        # State holders\n        profiles_holder = {\"data\": []}\n        analysis_holder = {\"data\": {}}\n        cleanup_journal = []\n        cleanup_backup_root = os.path.join(os.getenv(\"TEMP\", os.getenv(\"TMP\", \"C:\\\\Windows\\\\Temp\")), \"GodawariBrowserCleanup\")\n        os.makedirs(cleanup_backup_root, exist_ok=True)\n\n        # Header\n        hdr = tk.Frame(win, bg=C[\"panel\"], pady=12)\n        hdr.pack(fill=\"x\")\n        tk.Label(hdr, text=\"\ud83d\ude80 Enterprise Browser Optimization Engine\",\n                 font=(\"Segoe UI\", 14, \"bold\"), bg=C[\"panel\"], fg=C[\"accent\"]).pack(side=\"left\", padx=18)\n        tk.Label(hdr, text=\"Complete Analysis \u2022 Safe Optimization \u2022 Reversible Changes\",\n                 font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text_dim\"]).pack(side=\"right\", padx=18)\n        tk.Frame(hdr, bg=C[\"accent\"], height=2).pack(side=\"bottom\", fill=\"x\")\n\n        # Main paned layout\n        paned = tk.PanedWindow(win, orient=\"horizontal\", bg=C[\"bg\"], sashwidth=5, sashrelief=\"flat\")\n        paned.pack(fill=\"both\", expand=True, padx=8, pady=6)\n\n        # LEFT: Profile tree\n        left_frame = tk.Frame(paned, bg=C[\"bg\"])\n        paned.add(left_frame, width=550, minsize=400)\n\n        tk.Label(left_frame, text=\"\ud83d\udd0d Browser Profiles &amp; Analysis\",\n                 font=FONTS[\"small\"], fg=C[\"accent\"], bg=C[\"bg\"]).pack(anchor=\"w\", padx=4, pady=(4,2))\n\n        tree_host = tk.Frame(left_frame, bg=C[\"border\"], bd=1)\n        tree_host.pack(fill=\"both\", expand=True, padx=2)\n\n        tree = ttk.Treeview(tree_host, columns=(\"metric\", \"value\"), style=\"Custom.Treeview\", selectmode=\"browse\")\n        tree.heading(\"#0\", text=\"Profile / Analysis\")\n        tree.heading(\"metric\", text=\"Metric\")\n        tree.heading(\"value\", text=\"Value\")\n        tree.column(\"#0\", width=300, minwidth=200)\n        tree.column(\"metric\", width=150, minwidth=100)\n        tree.column(\"value\", width=100, minwidth=80, anchor=\"e\")\n\n        vsb = ttk.Scrollbar(tree_host, orient=\"vertical\", command=tree.yview)\n        hsb = ttk.Scrollbar(tree_host, orient=\"horizontal\", command=tree.xview)\n        tree.configure(yscrollcommand=vsb.set, xscrollcommand=hsb.set)\n        vsb.pack(side=\"right\", fill=\"y\")\n        hsb.pack(side=\"bottom\", fill=\"x\")\n        tree.pack(fill=\"both\", expand=True)\n\n        # RIGHT: Analysis report\n        right_frame = tk.Frame(paned, bg=C[\"bg\"])\n        paned.add(right_frame, minsize=400)\n\n        tk.Label(right_frame, text=\"\ud83d\udcca Analysis Report\",\n                 font=FONTS[\"small\"], fg=C[\"accent\"], bg=C[\"bg\"]).pack(anchor=\"w\", padx=4, pady=(4,2))\n\n        report_host = tk.Frame(right_frame, bg=C[\"border\"], bd=1)\n        report_host.pack(fill=\"both\", expand=True, padx=2)\n\n        report_txt = scrolledtext.ScrolledText(report_host, height=20, font=FONTS[\"mono\"],\n                                             bg=C[\"card\"], fg=C[\"text\"], relief=\"flat\", bd=0,\n                                             state=\"disabled\", wrap=\"word\")\n        report_txt.pack(fill=\"both\", expand=True)\n\n        # Text tags\n        for tag, fg in [(\"hdr\", C[\"accent\"]), (\"ok\", C[\"success\"]), (\"warn\", C[\"warning\"]),\n                       (\"err\", C[\"error\"]), (\"path\", \"#79c0ff\"), (\"muted\", C[\"text_dim\"]),\n                       (\"bold\", C[\"text\"])]:\n            report_txt.tag_configure(tag, foreground=fg,\n                                    font=(\"Consolas\", 8, \"bold\") if tag == \"bold\" else (\"Consolas\", 8))\n\n        def append_report(msg, tag=\"\"):\n            report_txt.configure(state=\"normal\")\n            report_txt.insert(\"end\", msg + \"\\n\", tag)\n            report_txt.see(\"end\")\n            report_txt.configure(state=\"disabled\")\n            # Mirror to main clean log\n            tag_color_map = {\"ok\": C[\"success\"], \"warn\": C[\"warning\"], \"err\": C[\"error\"],\n                             \"hdr\": C[\"accent\"], \"path\": \"#79c0ff\", \"muted\": C[\"text_dim\"], \"bold\": C[\"text\"]}\n            self._append_log(self.clean_log, msg, tag_color_map.get(tag, C[\"text\"]))\n\n        # Status bar\n        status_var = tk.StringVar(value=\"Ready. Click 'Analyze' to begin.\")\n        status_bar = tk.Frame(win, bg=C[\"panel\"], pady=7)\n        status_bar.pack(fill=\"x\", side=\"bottom\")\n        tk.Label(status_bar, textvariable=status_var, font=FONTS[\"small\"],\n                bg=C[\"panel\"], fg=C[\"text_dim\"]).pack(side=\"left\", padx=14)\n\n        def set_status(msg):\n            try:\n                status_var.set(msg)\n                win.update_idletasks()\n            except:\n                pass\n\n        # Buttons\n        btn_frame = tk.Frame(win, bg=C[\"panel\"], pady=8)\n        btn_frame.pack(fill=\"x\", side=\"bottom\")\n\n        _bc = dict(font=(\"Segoe UI\", 9, \"bold\"), relief=\"flat\", cursor=\"hand2\", padx=12, pady=6, bd=0)\n\n        btn_analyze = tk.Button(btn_frame, text=\"\ud83d\udcca  Analyze All Browsers\", bg=C[\"btn_info\"], fg=C[\"text\"], **_bc)\n        btn_analyze.pack(side=\"left\", padx=(10,5))\n\n        btn_repair = tk.Button(btn_frame, text=\"\ud83d\udd27  Repair Profiles\", bg=C[\"btn_warn\"], fg=C[\"text\"],\n                              state=\"disabled\", **_bc)\n        btn_repair.pack(side=\"left\", padx=5)\n\n        btn_optimize = tk.Button(btn_frame, text=\"\u26a1  Optimize &amp; Clean\", bg=\"#1a6b3a\", fg=C[\"text\"],\n                                state=\"disabled\", **_bc)\n        btn_optimize.pack(side=\"left\", padx=5)\n\n        btn_rollback = tk.Button(btn_frame, text=\"\u21a9\ufe0f  Rollback Last\", bg=C[\"panel\"], fg=C[\"text\"],\n                                state=\"disabled\", **_bc)\n        btn_rollback.pack(side=\"left\", padx=5)\n\n        # ANALYZE \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        def do_analyze():\n            btn_analyze.config(state=\"disabled\")\n            btn_repair.config(state=\"disabled\")\n            btn_optimize.config(state=\"disabled\")\n            report_txt.configure(state=\"normal\")\n            report_txt.delete(\"1.0\", \"end\")\n            report_txt.configure(state=\"disabled\")\n            tree.delete(*tree.get_children())\n            set_status(\"Analyzing browsers\u2026\")\n\n            def worker():\n                try:\n                    profiles = self._browser_detect_all()\n                    profiles_holder[\"data\"] = profiles\n                    analysis = {}\n\n                    append_report(\"\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\", \"hdr\")\n                    append_report(\"\u2551  ENTERPRISE BROWSER ANALYSIS REPORT    \u2551\", \"hdr\")\n                    append_report(\"\u255a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255d\\n\", \"hdr\")\n\n                    for prof in profiles:\n                        bname = prof.get(\"browser\", \"unknown\")\n                        profile_path = prof.get(\"profile\", \"\")\n                        append_report(f\"\\n\u2550\u2550\u2550 {bname} \u2550\u2550\u2550\", \"bold\")\n\n                        # Comprehensive report\n                        report = self._browser_comprehensive_report(prof)\n                        analysis[bname] = report\n\n                        # Profile size\n                        psize = report.get(\"profile_size_mb\", 0)\n                        csize = report.get(\"cache_size_mb\", 0)\n                        append_report(f\"Profile Size    : {psize} MB\", \"path\")\n                        append_report(f\"Cache Size      : {csize} MB\", \"path\")\n\n                        # Integrity issues\n                        issues = report.get(\"integrity_issues\", [])\n                        if issues:\n                            append_report(f\"Integrity Issues: {len(issues)} found\", \"warn\")\n                            for issue_type, severity, desc in issues[:5]:\n                                append_report(f\"  \u2022 [{severity}] {desc}\", \"muted\")\n                        else:\n                            append_report(\"Integrity      : \u2713 OK\", \"ok\")\n\n                        # Extensions\n                        exts = report.get(\"extensions\", [])\n                        append_report(f\"Extensions      : {len(exts)} installed\", \"path\")\n                        for ext in exts[:3]:\n                            size_kb = ext.get(\"size_bytes\", 0) / 1024\n                            append_report(f\"  \u2022 {ext.get('name', 'unknown')} ({size_kb:.0f} KB)\", \"muted\")\n\n                        # Optimization score\n                        score = report.get(\"optimization_score\", 0)\n                        tag = \"ok\" if score &gt;= 80 else (\"warn\" if score &gt;= 50 else \"err\")\n                        append_report(f\"Optimization Score: {score}/100\", tag)\n\n                        # Add to tree\n                        b_node = tree.insert(\"\", \"end\", text=f\"  {bname}\", values=(\"\", \"\"))\n                        tree.insert(b_node, \"end\", text=f\"Profile Size\", values=(\"\", f\"{psize} MB\"))\n                        tree.insert(b_node, \"end\", text=f\"Cache Size\", values=(\"\", f\"{csize} MB\"))\n                        tree.insert(b_node, \"end\", text=f\"Extensions\", values=(\"\", f\"{len(exts)}\"))\n                        tree.insert(b_node, \"end\", text=f\"Issues\", values=(\"\", f\"{len(issues)}\"))\n                        tree.insert(b_node, \"end\", text=f\"Score\", values=(\"\", f\"{score}/100\"))\n\n                    analysis_holder[\"data\"] = analysis\n                    append_report(\"\\n\u2713 Analysis complete!\", \"ok\")\n\n                    win.after(0, lambda: (\n                        btn_analyze.config(state=\"normal\"),\n                        btn_repair.config(state=\"normal\" if any(analysis.get(b, {}).get(\"integrity_issues\") for b in analysis) else \"disabled\"),\n                        btn_optimize.config(state=\"normal\"),\n                        set_status(\"Analysis complete. Review results above.\"),\n                    ))\n                except Exception as e:\n                    append_report(f\"\u2717 Analysis failed: {str(e)[:100]}\", \"err\")\n                    win.after(0, lambda: btn_analyze.config(state=\"normal\"))\n\n            self._launch_job(\"browser_analyze\", worker)\n\n        # REPAIR \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        def do_repair():\n            btn_repair.config(state=\"disabled\")\n            set_status(\"Attempting profile repairs\u2026\")\n            repaired = 0\n\n            def worker():\n                nonlocal repaired\n                try:\n                    analysis = analysis_holder.get(\"data\", {})\n                    for bname, report in analysis.items():\n                        issues = report.get(\"integrity_issues\", [])\n                        if not issues:\n                            continue\n                        profile_path = report.get(\"profile_path\", \"\")\n                        if not profile_path:\n                            for prof in profiles_holder.get(\"data\", []):\n                                if prof.get(\"browser\") == bname:\n                                    profile_path = prof.get(\"profile\", \"\")\n                                    break\n                        if profile_path:\n                            success, message, repairs = self._browser_corrupted_profile_repair(profile_path)\n                            if success:\n                                repaired += len(repairs)\n                                append_report(f\"\u2713 {bname}: {message}\", \"ok\")\n                            else:\n                                append_report(f\"\u26a0 {bname}: {message}\", \"warn\")\n                    append_report(f\"\\n\u2713 Repair complete: {repaired} issues fixed\", \"ok\")\n                except Exception as e:\n                    append_report(f\"\u2717 Repair failed: {str(e)[:100]}\", \"err\")\n                finally:\n                    win.after(0, lambda: btn_repair.config(state=\"normal\"))\n\n            self._launch_job(\"browser_repair\", worker)\n\n        # OPTIMIZE \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        def do_optimize():\n            btn_optimize.config(state=\"disabled\")\n            set_status(\"Optimizing and cleaning\u2026\")\n\n            def worker():\n                try:\n                    append_report(\"\\n\u2550\u2550\u2550 OPTIMIZATION &amp; CLEANUP \u2550\u2550\u2550\\n\", \"bold\")\n                    total_freed = 0\n\n                    for prof in profiles_holder.get(\"data\", []):\n                        bname = prof.get(\"browser\")\n                        items_to_clean = self._browser_scan_profile(prof)\n                        append_report(f\"{bname}: {len(items_to_clean)} junk items\", \"path\")\n\n                        for path, sz, reason in items_to_clean:\n                            if self._browser_is_protected(path):\n                                append_report(f\"  \u2713 Protected: {os.path.basename(path)}\", \"muted\")\n                                continue\n                            try:\n                                backup_name = os.path.basename(path)\n                                backup_path = os.path.join(cleanup_backup_root, f\"{int(time.time())}_{backup_name}\")\n                                if os.path.isdir(path):\n                                    shutil.copytree(path, backup_path, dirs_exist_ok=True)\n                                    shutil.rmtree(path, ignore_errors=True)\n                                elif os.path.isfile(path):\n                                    os.makedirs(os.path.dirname(backup_path), exist_ok=True)\n                                    shutil.copy2(path, backup_path)\n                                    os.remove(path)\n                                total_freed += sz\n                                cleanup_journal.append({\"original\": path, \"backup\": backup_path, \"size\": sz})\n                                append_report(f\"  \u2713 Cleaned: {os.path.basename(path)}\", \"muted\")\n                            except Exception as e:\n                                append_report(f\"  \u26a0 Failed to clean {os.path.basename(path)}: {e}\", \"warn\")\n\n                    append_report(f\"\\n\u2713 Optimization complete: {self._fmt_size(total_freed)} freed\", \"ok\")\n                    win.after(0, lambda: btn_rollback.config(state=\"normal\" if cleanup_journal else \"disabled\"))\n                except Exception as e:\n                    append_report(f\"\u2717 Optimization failed: {str(e)}\", \"err\")\n                finally:\n                    win.after(0, lambda: btn_optimize.config(state=\"normal\"))\n\n            self._launch_job(\"browser_optimize\", worker)\n\n        def do_rollback():\n            btn_rollback.config(state=\"disabled\")\n            set_status(\"Rolling back browser cleanup\u2026\")\n            append_report(\"\\n\u2550\u2550\u2550 ROLLBACK RESTORATION \u2550\u2550\u2550\", \"bold\")\n            restored = 0\n\n            def worker():\n                nonlocal restored\n                try:\n                    for entry in reversed(cleanup_journal):\n                        orig = entry.get(\"original\")\n                        backup = entry.get(\"backup\")\n                        if not orig or not backup:\n                            continue\n                        try:\n                            if os.path.isdir(backup):\n                                shutil.copytree(backup, orig, dirs_exist_ok=True)\n                                restored += 1\n                            elif os.path.isfile(backup):\n                                os.makedirs(os.path.dirname(orig), exist_ok=True)\n                                shutil.copy2(backup, orig)\n                                restored += 1\n                        except Exception as e:\n                            append_report(f\"  \u26a0 Failed to restore {orig}: {e}\", \"warn\")\n                    append_report(f\"\\n\u2713 Rollback complete: restored {restored} items\", \"ok\")\n                except Exception as e:\n                    append_report(f\"\u2717 Rollback failed: {str(e)[:100]}\", \"err\")\n                finally:\n                    win.after(0, lambda: btn_rollback.config(state=\"normal\" if restored else \"disabled\"))\n\n            self._launch_job(\"browser_rollback\", worker)\n\n        btn_analyze.config(command=do_analyze)\n        btn_repair.config(command=do_repair)\n        btn_optimize.config(command=do_optimize)\n        btn_rollback.config(command=do_rollback)\n\n        # Auto-analyze on open\n        win.after(300, do_analyze)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  END BROWSER BOOST\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _apply_clean_profile(self):\n        # Profile selection removed in favor of All-In-One Master Purge.\n        try:\n            self._append_log(self.clean_log, \"\u26a0 Cleaner profiles removed. Use All-In-One Master Purge.\", C[\"warning\"])\n        except Exception:\n            pass\n\n    def _large_file_finder_dialog(self):\n        root = filedialog.askdirectory(title=\"Select Folder for Large File Finder\")\n        if not root:\n            return\n        self._launch_job(\"large_file_finder\", self._do_large_file_finder, root)\n\n    def _do_large_file_finder(self, root):\n        def L(msg, color=None): self._append_log(self.clean_log, msg, color or C[\"text\"])\n        L(\"\u2501\"*52, C[\"border\"])\n        L(f\"\ud83d\udce6  Large File Finder \u2014 scanning: {root}\", C[\"accent4\"])\n        L(\"\u2501\"*52, C[\"border\"])\n        try:\n            top = []\n            scanned = 0\n            for dirpath, _, filenames in os.walk(root):\n                for fn in filenames:\n                    full = os.path.join(dirpath, fn)\n                    try:\n                        sz = os.path.getsize(full)\n                        if len(top) &lt; 50:\n                            top.append((sz, full))\n                            top.sort(key=lambda x: x[0], reverse=True)\n                        elif sz &gt; top[-1][0]:\n                            top[-1] = (sz, full)\n                            top.sort(key=lambda x: x[0], reverse=True)\n                    except Exception:\n                        continue\n                scanned += 1\n                if scanned % 300 == 0:\n                    L(f\"  \u2026 {scanned} folders scanned so far\u2026\", C[\"text_dim\"])\n            L(f\"\u2705 Top {len(top)} largest files:\", C[\"success\"])\n            for i, (sz, p) in enumerate(top, 1):\n                L(f\"  {i:02d}. {self._fmt_size(sz):&lt;10s}  {p}\", C[\"text\"])\n            L(\"\u2501\"*52, C[\"border\"])\n            L(f\"\u2705 Large File Finder complete \u2014 {len(top)} files found in {scanned} folders\", C[\"success\"])\n            self._set_status(\"Large file finder complete\", C[\"success\"])\n        except Exception as e:\n            L(f\"\u274c Large File Finder failed: {e}\", C[\"error\"])\n\n    def _open_empty_folder_finder(self):\n        root = filedialog.askdirectory(title=\"Select folder to scan for empty directories\")\n        if not root:\n            return\n        self._launch_job(\"empty_folder_finder\", self._do_empty_folder_finder, root)\n\n    def _do_empty_folder_finder(self, root):\n        def L(msg, color=None): self._append_log(self.clean_log, msg, color or C[\"text\"])\n        L(\"\u2501\"*52, C[\"border\"])\n        L(f\"\ud83d\udcc1  Empty Folder Finder \u2014 scanning: {root}\", C[\"accent4\"])\n        L(\"\u2501\"*52, C[\"border\"])\n        try:\n            empty_dirs = []\n            for dirpath, dirnames, filenames in os.walk(root, topdown=False):\n                if self._clean_job_cancel_event.is_set():\n                    L(\"\u23f9 Cancelled by user.\", C[\"warning\"])\n                    return\n                if not dirnames and not filenames:\n                    empty_dirs.append(dirpath)\n                    L(f\"  \ud83d\udcc2 Empty: {dirpath}\", C[\"text\"])\n            L(f\"  Found {len(empty_dirs)} empty folders\", C[\"text_dim\"])\n            if empty_dirs and messagebox.askyesno(\"Delete Empty Folders\", f\"{len(empty_dirs)} empty folders mili hain.\\nDelete karna chahte hain? (Safe hai)\"):\n                deleted = 0\n                for d in empty_dirs:\n                    try:\n                        os.rmdir(d)\n                        deleted += 1\n                        L(f\"  \ud83d\uddd1 Deleted: {d}\", C[\"success\"])\n                    except Exception as e:\n                        L(f\"  \u26a0\ufe0f  {d}: {e}\", C[\"warning\"])\n                L(\"\u2501\"*52, C[\"border\"])\n                L(f\"\u2705 Empty Folder Finder complete \u2014 {deleted}/{len(empty_dirs)} folders deleted\", C[\"success\"])\n            else:\n                L(\"\u2501\"*52, C[\"border\"])\n                L(f\"\u2705 Empty Folder Finder complete \u2014 {len(empty_dirs)} found, none deleted\", C[\"text_dim\"])\n            self._set_status(\"Empty folder scan complete\", C[\"success\"])\n        except Exception as e:\n            L(f\"\u274c Empty Folder Finder failed: {e}\", C[\"error\"])\n\n    def _open_zero_byte_finder(self):\n        root = filedialog.askdirectory(title=\"Select folder to scan for zero-byte files\")\n        if not root:\n            return\n        self._launch_job(\"zero_byte_finder\", self._do_zero_byte_finder, root)\n\n    def _do_zero_byte_finder(self, root):\n        def L(msg, color=None): self._append_log(self.clean_log, msg, color or C[\"text\"])\n        try:\n            L(\"\u2501\"*52, C[\"border\"])\n            L(f\"\ud83d\udd0e  0-Byte File Scanner \u2014 scanning: {root}\", C[\"accent4\"])\n            L(\"\u2501\"*52, C[\"border\"])\n            found = []\n            for dirpath, _, filenames in os.walk(root):\n                if self._clean_job_cancel_event.is_set():\n                    self._append_log(self.clean_log, \"\u26a0\ufe0f Zero-byte scan cancelled.\", C[\"warning\"])\n                    return\n                for name in filenames:\n                    path = os.path.join(dirpath, name)\n                    try:\n                        if os.path.getsize(path) == 0:\n                            found.append(path)\n                            self._append_log(self.clean_log, f\"  0-byte: {path}\", C[\"text\"])\n                    except Exception:\n                        continue\n            self._append_log(self.clean_log, f\"\u2705 Zero-byte files found: {len(found)}\", C[\"success\"])\n            if found and messagebox.askyesno(\"Delete Zero-byte Files\", f\"Delete {len(found)} zero-byte files? This is usually safe.\"):\n                deleted = 0\n                for path in found:\n                    try:\n                        os.remove(path)\n                        deleted += 1\n                    except Exception:\n                        pass\n                self._append_log(self.clean_log, f\"\u2705 Deleted zero-byte files: {deleted}\", C[\"success\"])\n            self._set_status(\"Zero-byte scan complete\", C[\"success\"])\n        except Exception as e:\n            self._append_log(self.clean_log, f\"\u274c Zero-byte finder failed: {e}\", C[\"error\"])\n\n    def _professional_scan(self):\n        if getattr(self, \"_clean_job_running\", False):\n            messagebox.showwarning(\"Busy\", \"A clean operation is already running. Please wait or cancel it first.\")\n            return\n        self._clean_job_cancel_event.clear()\n        self._set_clean_job_state(running=True)\n        self._set_status(\"Scanning junk\u2026\", C[\"accent4\"])\n        self._master_purge_scan()\n\n    def _professional_clean(self):\n        if getattr(self, \"_clean_job_running\", False):\n            messagebox.showwarning(\"Busy\", \"A clean operation is already running. Please wait or cancel it first.\")\n            return\n        preview = getattr(self, \"clean_preview_var\", tk.BooleanVar(value=False)).get()\n        label = \"Preview Deletions\" if preview else \"Delete Junk\"\n        msg = (\n            f\"{'PREVIEW MODE \u2014 koi file delete nahi hogi.' if preview else 'Selected junk files PERMANENTLY DELETE honge.'}\\n\\n\"\n            \"Proceed karna chahte hain?\"\n        )\n        if not messagebox.askyesno(label, msg):\n            return\n        self._clean_job_cancel_event.clear()\n        self._set_clean_job_state(running=True)\n        self._set_status(f\"{label} started\u2026\", C[\"accent4\"])\n        self._master_purge_all(preview=preview)\n\n    def _calculate_total_junk_size(self):\n        total = 0\n        for label, path in self._get_clean_paths():\n            if not path or not os.path.exists(path):\n                continue\n            total += self._folder_size(path)\n        return total\n\n    def _do_clean_scan(self):\n        paths = list(self._get_clean_paths())\n        total_paths = len(paths)\n\n        def _append_scan_entry(label, size, path, current_total, processed):\n            self._append_log(self.clean_log, f\"\ud83d\udcc1 {label:&lt;30s}  {self._fmt_size(size)}\", C[\"text\"])\n            self._append_log(self.clean_log, f\"      \ud83d\udccd {path}\", C[\"text_dim\"])\n            self.clean_size_lbl.config(text=f\"Total junk found: {self._fmt_size(current_total)}\")\n            self.clean_progress_var.set(processed)\n            self.clean_progress_lbl.config(text=f\"Scanning {processed}/{total_paths} targets\")\n\n        def _append_scan_error(label, error_text, processed):\n            self._append_log(self.clean_log, f\"  \u274c {label:&lt;30s}  [Error: {error_text}]\", C[\"error\"])\n            self.clean_progress_var.set(processed)\n            self.clean_progress_lbl.config(text=f\"Scanning {processed}/{total_paths} targets\")\n\n        self.after(0, lambda: self._set_status(\"Scanning junk...\", C[\"accent4\"]))\n        self.after(0, lambda: self.clean_progress_bar.config(mode=\"determinate\", maximum=max(1, total_paths)))\n        self.after(0, lambda: self.clean_progress_var.set(0))\n        total_size = 0\n        scanned = 0\n        errors = 0\n        canceled = False\n        if total_paths == 0:\n            self.after(0, lambda: self.clean_size_lbl.config(text=\"Total junk found: --\"))\n            self.after(0, self._finalize_clean_job, \"scan\", {\"total_paths\": 0, \"processed\": 0, \"total_size\": 0, \"errors\": 0, \"canceled\": False})\n            return\n\n        for label, path in paths:\n            if self._clean_job_cancel_event.is_set():\n                canceled = True\n                break\n            if not path or not os.path.exists(path):\n                errors += 1\n                scanned += 1\n                _lbl, _sc = label, scanned\n                self.after(0, lambda l=_lbl, s=_sc: _append_scan_error(l, \"Path missing or inaccessible\", s))\n                continue\n            try:\n                size = self._folder_size(path)\n                total_size += size\n                scanned += 1\n                _lbl, _sz, _p, _t, _sc = label, size, path, total_size, scanned\n                self.after(0, lambda l=_lbl, s=_sz, p=_p, t=_t, c=_sc: _append_scan_entry(l, s, p, t, c))\n            except Exception as e:\n                errors += 1\n                scanned += 1\n                _lbl, _e, _sc = label, str(e), scanned\n                self.after(0, lambda l=_lbl, e=_e, s=_sc: _append_scan_error(l, e, s))\n\n        self.after(0, self._finalize_clean_job, \"scan\", {\n            \"total_paths\": total_paths,\n            \"processed\": scanned,\n            \"total_size\": total_size,\n            \"errors\": errors,\n            \"canceled\": canceled,\n        })\n\n    def _do_clean(self):\n        paths = list(self._get_clean_paths())\n        total_paths = len(paths)\n        preview = getattr(self, \"clean_preview_var\", tk.BooleanVar(value=False)).get()\n\n        def _append_clean_entry(label, freed, processed):\n            verb = \"Previewed\" if preview else \"Cleaned\"\n            self._append_log(self.clean_log, f\"\u2705 {verb}: {label} ({self._fmt_size(freed)} freed)\", C[\"success\"])\n            self.clean_progress_var.set(processed)\n            self.clean_progress_lbl.config(text=f\"{verb} {processed}/{total_paths} targets\")\n\n        def _append_clean_error(label, error_text, processed):\n            self._append_log(self.clean_log, f\"  \u274c {label:&lt;30s}  [Error: {error_text}]\", C[\"error\"])\n            self.clean_progress_var.set(processed)\n            self.clean_progress_lbl.config(text=f\"Processing {processed}/{total_paths} targets\")\n\n        self.after(0, lambda: self._set_status(\"Deleting junk...\" if not preview else \"Previewing deletions...\", C[\"accent4\"]))\n        self.after(0, lambda: self.clean_progress_bar.config(mode=\"determinate\", maximum=max(1, total_paths)))\n        self.after(0, lambda: self.clean_progress_var.set(0))\n        total_removed = 0\n        processed = 0\n        errors = 0\n        canceled = False\n        if total_paths == 0:\n            self.after(0, lambda: self.clean_size_lbl.config(text=\"Total junk found: -- (no targets)\"))\n            self.after(0, self._finalize_clean_job, \"clean\", {\n                \"total_paths\": 0,\n                \"processed\": 0,\n                \"freed\": 0,\n                \"remaining\": 0,\n                \"errors\": 0,\n                \"canceled\": False,\n                \"preview\": preview,\n            })\n            return\n\n        for label, path in paths:\n            if self._clean_job_cancel_event.is_set():\n                canceled = True\n                break\n            if not path or not os.path.exists(path):\n                errors += 1\n                processed += 1\n                _lbl, _p = label, processed\n                self.after(0, lambda l=_lbl, p=_p: _append_clean_error(l, \"Path missing or inaccessible\", p))\n                continue\n            try:\n                if preview:\n                    freed = 0\n                    _lbl = label\n                    self.after(0, lambda l=_lbl: self._append_log(self.clean_log, f\"\ud83d\udd0e Preview: {l} would be cleaned\", C[\"accent\"]))\n                else:\n                    freed = self._delete_folder_contents(path)\n                total_removed += freed\n                processed += 1\n                _lbl, _f, _p = label, freed, processed\n                self.after(0, lambda l=_lbl, f=_f, p=_p: _append_clean_entry(l, f, p))\n            except Exception as e:\n                errors += 1\n                processed += 1\n                _lbl, _e, _p = label, str(e), processed\n                self.after(0, lambda l=_lbl, e=_e, p=_p: _append_clean_error(l, e, p))\n\n        remaining = self._calculate_total_junk_size() if not preview else total_removed\n        self.after(0, self._finalize_clean_job, \"clean\", {\n            \"total_paths\": total_paths,\n            \"processed\": processed,\n            \"freed\": total_removed,\n            \"remaining\": remaining,\n            \"errors\": errors,\n            \"canceled\": canceled,\n            \"preview\": preview,\n        })\n\n    # ---------------- All-In-One Master Purge Engine -----------------\n    def _master_purge_estimate(self):\n        \"\"\"Estimate total bytes across all master purge targets.\"\"\"\n        total = 0\n        targets = self._master_purge_targets()\n        for label, path in targets:\n            try:\n                if os.path.exists(path):\n                    total += self._folder_size(path)\n            except Exception:\n                continue\n        return total\n\n    def _master_purge_targets(self):\n        \"\"\"Return list of (label, path) tuples to purge.\"\"\"\n        local = os.environ.get(\"LOCALAPPDATA\", \"\")\n        roaming = os.environ.get(\"APPDATA\", \"\")\n        user = os.path.expanduser(\"~\")\n        targets = []\n        # Browser user data roots (all profiles will be discovered)\n        targets.append((\"Chrome User Data\", os.path.join(local, \"Google\", \"Chrome\", \"User Data\")))\n        targets.append((\"Edge User Data\", os.path.join(local, \"Microsoft\", \"Edge\", \"User Data\")))\n        targets.append((\"Brave User Data\", os.path.join(local, \"BraveSoftware\", \"Brave-Browser\", \"User Data\")))\n        # Delivery Optimization\n        targets.append((\"WU Download Cache\", r\"C:\\Windows\\SoftwareDistribution\\Download\"))\n        # Windows Installer cache\n        targets.append((\"Windows Installer\", r\"C:\\Windows\\Installer\"))\n        # Discord / Telegram\n        targets.append((\"Discord Local\", os.path.join(local, \"Discord\")))\n        targets.append((\"Telegram Roaming\", os.path.join(roaming, \"Telegram Desktop\")))\n        # DirectX shader caches\n        targets.append((\"D3D Shader Cache\", os.path.join(user, \"AppData\", \"Local\", \"D3DSCache\")))\n        targets.append((\"DirectX WebCache\", os.path.join(local, \"Microsoft\", \"DirectX\", \"WebCache\")))\n        # Crash dumps and CBS logs\n        targets.append((\"Minidump\", r\"C:\\Windows\\Minidump\"))\n        targets.append((\"CBS Logs\", r\"C:\\Windows\\Logs\\CBS\"))\n        # Prefetch\n        targets.append((\"Prefetch\", r\"C:\\Windows\\Prefetch\"))\n        return targets\n\n    def _master_purge_all(self, preview=False):\n        \"\"\"Master purge engine \u2014 background thread mein chalta hai taaki log live dikhe.\"\"\"\n\n        def _log(msg, color=None):\n            try:\n                self._append_log(self.clean_log, msg, color)\n            except Exception:\n                pass\n\n        def _set_prog(text):\n            try:\n                self.after(0, lambda t=text: self.clean_progress_lbl.config(text=t))\n            except Exception:\n                pass\n\n        def _set_size(text):\n            try:\n                self.after(0, lambda t=text: self.clean_size_lbl.config(text=t))\n            except Exception:\n                pass\n\n        def _run():\n            try:\n                preview_mode = preview or getattr(self, \"clean_preview_var\", tk.BooleanVar(value=False)).get()\n                verb = \"Preview\" if preview_mode else \"Delete Junk\"\n\n                _log(\"=\" * 54, C.get(\"border\", \"#444\"))\n                _log(f\"\ud83d\uddd1  {verb} \u2014 starting\u2026\", C.get(\"accent4\", \"#4fc3f7\"))\n                _log(\"=\" * 54, C.get(\"border\", \"#444\"))\n\n                # Admin check \u2014 sirf warn karo, rok mat\n                if not is_admin():\n                    _log(\"\u26a0\ufe0f  Not running as admin \u2014 system folders may be skipped.\", C.get(\"warning\", \"#ff9800\"))\n\n                removed_total = 0\n                errors = 0\n\n                # \u2500\u2500 Checkbox-selected targets (user ne jo select kiye) \u2500\u2500\u2500\u2500\u2500\u2500\n                selected_paths = list(self._get_clean_paths())\n                total = len(selected_paths)\n                _log(f\"\ud83d\udccb {total} targets selected by checkboxes\", C.get(\"text_dim\", \"#888\"))\n\n                for i, (label, path) in enumerate(selected_paths):\n                    if getattr(self, \"_clean_job_cancel_event\", None) and self._clean_job_cancel_event.is_set():\n                        _log(\"\u23f9 Cancelled by user.\", C.get(\"warning\", \"#ff9800\"))\n                        break\n                    _set_prog(f\"Processing {i+1}/{total}: {label}\")\n                    if not path or not os.path.exists(path):\n                        _log(f\"  \u2b1c {label:&lt;32s}  [path missing]\", C.get(\"text_dim\", \"#888\"))\n                        continue\n                    try:\n                        size_before = self._folder_size(path)\n                        if size_before == 0:\n                            _log(f\"  \u2705 {label:&lt;32s}  Already clean\", C.get(\"text_dim\", \"#888\"))\n                            continue\n                        _log(f\"  \ud83d\uddd1 {label:&lt;32s}  {self._fmt_size(size_before)}\", C.get(\"text\", \"#eee\"))\n                        _log(f\"      \ud83d\udccd {path}\", C.get(\"text_dim\", \"#888\"))\n                        if not preview_mode:\n                            freed = self._delete_folder_contents(path)\n                            removed_total += freed\n                            _log(f\"      \u2705 Freed: {self._fmt_size(freed)}\", C.get(\"success\", \"#4caf50\"))\n                        else:\n                            _log(f\"      \ud83d\udd0e Preview \u2014 would free ~{self._fmt_size(size_before)}\", C.get(\"accent\", \"#29b6f6\"))\n                    except Exception as e:\n                        errors += 1\n                        _log(f\"      \u274c Error: {e}\", C.get(\"error\", \"#f44336\"))\n\n                # \u2500\u2500 Browser shader/code caches \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n                _log(\"\u2500\" * 40, C.get(\"border\", \"#444\"))\n                _log(\"\ud83c\udf10  Browser caches\u2026\", C.get(\"accent4\", \"#4fc3f7\"))\n                try:\n                    profiles = self._browser_detect_all()\n                    for prof in profiles:\n                        ppath = prof.get(\"profile\")\n                        if not ppath or not os.path.isdir(ppath):\n                            continue\n                        for cache_name in (\"Cache\", \"Cache2\", \"Code Cache\", \"ShaderCache\", \"GrShaderCache\", \"GPUCache\"):\n                            cdir = os.path.join(ppath, cache_name)\n                            if not os.path.isdir(cdir):\n                                continue\n                            try:\n                                sz = self._folder_size(cdir)\n                                if sz == 0:\n                                    continue\n                                _log(f\"  \ud83d\uddd1 {cache_name:&lt;20s}  {self._fmt_size(sz)}  ({ppath[-40:]})\", C.get(\"text\", \"#eee\"))\n                                if not preview_mode:\n                                    shutil.rmtree(cdir, ignore_errors=True)\n                                    removed_total += sz\n                                    _log(f\"      \u2705 Removed\", C.get(\"success\", \"#4caf50\"))\n                            except Exception as e:\n                                errors += 1\n                                _log(f\"      \u274c {cdir}: {e}\", C.get(\"error\", \"#f44336\"))\n                except Exception as e:\n                    _log(f\"  \u274c Browser cache error: {e}\", C.get(\"error\", \"#f44336\"))\n\n                _log(\"=\" * 54, C.get(\"border\", \"#444\"))\n                if preview_mode:\n                    _log(f\"\ud83d\udd0e Preview complete \u2014 no files deleted\", C.get(\"accent\", \"#29b6f6\"))\n                else:\n                    _log(f\"\u2705 Done \u2014 Freed: {self._fmt_size(removed_total)} | Errors: {errors}\", C.get(\"success\", \"#4caf50\"))\n                _set_prog(f\"{'Preview' if preview_mode else 'Done'} \u2014 {self._fmt_size(removed_total)} freed, {errors} errors\")\n                _set_size(f\"Total freed: {self._fmt_size(removed_total)}\")\n\n                self._clean_job_summary = {\n                    \"total_paths\": len(selected_paths),\n                    \"processed\": len(selected_paths),\n                    \"freed\": removed_total,\n                    \"remaining\": 0,\n                    \"errors\": errors,\n                    \"canceled\": False,\n                    \"preview\": preview_mode,\n                }\n                try:\n                    self.after(0, lambda: self._set_clean_job_state(running=False, export_ready=True))\n                except Exception:\n                    pass\n\n            except Exception as ex:\n                _log(f\"\u274c Master purge failed: {ex}\", C.get(\"error\", \"#f44336\"))\n                _set_prog(\"Error \u2014 see log\")\n\n        threading.Thread(target=_run, daemon=True).start()\n\n    def _master_purge_scan(self):\n        \"\"\"Scan-only mode \u2014 har target ka size log mein dikhao, kuch delete nahi karo.\"\"\"\n        def _log(msg, color=None):\n            try:\n                self._append_log(self.clean_log, msg, color)\n            except Exception:\n                pass\n\n        def _run():\n            try:\n                self.after(0, lambda: self.clean_progress_lbl.config(text=\"Scanning\u2026\"))\n                self.after(0, lambda: self.clean_size_lbl.config(text=\"Total junk found: scanning\u2026\"))\n                _log(\"=\" * 52, C.get(\"border\", \"#444\"))\n                _log(\"\ud83d\udd0d  Junk Scan Starting \u2014 koi file delete nahi hogi\", C.get(\"accent4\", \"#4fc3f7\"))\n                _log(\"=\" * 52, C.get(\"border\", \"#444\"))\n\n                targets = self._master_purge_targets()\n                # Checkbox se selected targets bhi add karo\n                extra_paths = self._get_clean_paths()\n                seen = {p for _, p in targets}\n                for label, path in extra_paths:\n                    if path not in seen:\n                        targets.append((label, path))\n                        seen.add(path)\n\n                total = 0\n                found = 0\n                for i, (label, path) in enumerate(targets):\n                    if not path:\n                        continue\n                    self.after(0, lambda i=i, n=len(targets): self.clean_progress_lbl.config(\n                        text=f\"Scanning {i+1}/{n}\u2026\"))\n                    try:\n                        if not os.path.exists(path):\n                            _log(f\"  \u2b1c {label:&lt;32s}  [path missing]\", C.get(\"text_dim\", \"#888\"))\n                            continue\n                        size = self._folder_size(path)\n                        if size == 0:\n                            _log(f\"  \u2705 {label:&lt;32s}  Already clean\", C.get(\"text_dim\", \"#888\"))\n                        else:\n                            total += size\n                            found += 1\n                            _log(f\"  \ud83d\uddd1 {label:&lt;32s}  {self._fmt_size(size)}\", C.get(\"text\", \"#eee\"))\n                            _log(f\"      \ud83d\udccd {path}\", C.get(\"text_dim\", \"#888\"))\n                    except Exception as e:\n                        _log(f\"  \u274c {label:&lt;32s}  Error: {e}\", C.get(\"error\", \"#f44\"))\n\n                _log(\"=\" * 52, C.get(\"border\", \"#444\"))\n                _log(f\"\u2705 Scan complete \u2014 {found} locations, {self._fmt_size(total)} reclaimable\", C.get(\"success\", \"#4caf50\"))\n                self.after(0, lambda: self.clean_size_lbl.config(text=f\"Total junk found: {self._fmt_size(total)}\"))\n                self.after(0, lambda: self.clean_progress_lbl.config(text=f\"Scan complete \u2014 {found} locations found\"))\n                self.after(0, lambda: self._set_clean_job_state(running=False, export_ready=True))\n            except Exception as ex:\n                _log(f\"\u274c Scan failed: {ex}\", C.get(\"error\", \"#f44\"))\n                self.after(0, lambda: self.clean_progress_lbl.config(text=\"Scan error\"))\n                self.after(0, lambda: self._set_clean_job_state(running=False, export_ready=False))\n\n        threading.Thread(target=_run, daemon=True).start()\n\n    # ---------------- Specific Cleaner Implementations ----------------\n    def _do_browser_turbo_boost(self):\n        \"\"\"Vacuum IndexedDB/SQLite and purge shader caches for Chromium-based browsers.\"\"\"\n        def L(msg, color=None): self._append_log(self.clean_log, msg, color or C[\"text\"])\n        L(\"\u2501\"*52, C[\"border\"])\n        L(\"\u26a1  Browser Turbo Booster \u2014 starting\", C[\"accent4\"])\n        L(\"\u2501\"*52, C[\"border\"])\n        try:\n            profiles = self._browser_detect_all()\n            if not profiles:\n                L(\"  \u2b1c Koi browser profile nahi mila.\", C[\"text_dim\"])\n            total_freed = 0\n            vacuumed = 0\n            for prof in profiles:\n                prof_path = prof.get(\"profile\")\n                bname = prof.get(\"browser\", \"Browser\")\n                if not prof_path or not os.path.isdir(prof_path):\n                    continue\n                L(f\"  \ud83c\udf10 {bname}\", C[\"accent\"])\n                L(f\"      \ud83d\udccd {prof_path}\", C[\"text_dim\"])\n                # VACUUM IndexedDB/SQLite\n                for root_d, dirs, files in os.walk(prof_path):\n                    if \"IndexedDB\" in root_d or root_d.lower().endswith(\"indexdb\"):\n                        for f in files:\n                            if f.lower().endswith((\".sqlite\", \".db\")):\n                                fp = os.path.join(root_d, f)\n                                try:\n                                    conn = sqlite3.connect(fp, timeout=5)\n                                    conn.execute(\"VACUUM\")\n                                    conn.close()\n                                    vacuumed += 1\n                                    L(f\"      \u2705 VACUUMed: {f}\", C[\"success\"])\n                                except Exception as e:\n                                    L(f\"      \u26a0\ufe0f  VACUUM skip ({f}): {e}\", C[\"warning\"])\n                # Shader/GPU caches\n                for sc in (\"ShaderCache\", \"GrShaderCache\", \"GPUCache\", \"Code Cache\"):\n                    cdir = os.path.join(prof_path, sc)\n                    if not os.path.isdir(cdir):\n                        continue\n                    try:\n                        sz = self._folder_size(cdir)\n                        shutil.rmtree(cdir, ignore_errors=True)\n                        total_freed += sz\n                        L(f\"      \ud83d\uddd1 {sc} \u2014 {self._fmt_size(sz)} freed\", C[\"success\"])\n                    except Exception as e:\n                        L(f\"      \u274c {sc} remove failed: {e}\", C[\"error\"])\n            L(\"\u2501\"*52, C[\"border\"])\n            L(f\"\u2705 Browser Turbo complete \u2014 {vacuumed} DBs vacuumed, {self._fmt_size(total_freed)} freed\", C[\"success\"])\n        except Exception as e:\n            L(f\"\u274c Browser Turbo Booster failed: {e}\", C[\"error\"])\n\n    def _do_purge_delivery_optimization(self):\n        \"\"\"Purge SoftwareDistribution\\\\\\\\Download safely by stopping services, clearing, and restarting.\"\"\"\n        def L(msg, color=None): self._append_log(self.clean_log, msg, color or C[\"text\"])\n        L(\"\u2501\"*52, C[\"border\"])\n        L(\"\ud83e\udde9  Windows Component Trimmer (Delivery Optimization) \u2014 starting\", C[\"accent4\"])\n        L(\"\u2501\"*52, C[\"border\"])\n        if not is_admin():\n            L(\"  \u26a0\ufe0f  Administrator rights required. As admin run karo.\", C[\"warning\"])\n            L(\"\u2501\"*52, C[\"border\"])\n            return\n        path = r\"C:\\Windows\\SoftwareDistribution\\Download\"\n        freed = 0\n        try:\n            sz_before = self._folder_size(path) if os.path.isdir(path) else 0\n            L(f\"  \ud83d\udce6 Cache size before: {self._fmt_size(sz_before)}\", C[\"text_dim\"])\n            L(\"  \u23f8  Stopping Windows Update services\u2026\", C[\"accent4\"])\n            try:\n                safe_run([\"net\", \"stop\", \"wuauserv\"], timeout=60)\n                L(\"      \u2705 wuauserv stopped\", C[\"success\"])\n            except Exception as e:\n                L(f\"      \u26a0\ufe0f  wuauserv: {e}\", C[\"warning\"])\n            try:\n                safe_run([\"net\", \"stop\", \"bits\"], timeout=60)\n                L(\"      \u2705 bits stopped\", C[\"success\"])\n            except Exception as e:\n                L(f\"      \u26a0\ufe0f  bits: {e}\", C[\"warning\"])\n            if os.path.isdir(path):\n                for entry in os.scandir(path):\n                    try:\n                        p = entry.path\n                        try:\n                            esz = os.path.getsize(p) if entry.is_file() else self._folder_size(p)\n                        except Exception:\n                            esz = 0\n                        if entry.is_file():\n                            os.remove(p)\n                        elif entry.is_dir():\n                            shutil.rmtree(p, ignore_errors=True)\n                        freed += esz\n                    except Exception as e:\n                        L(f\"      \u26a0\ufe0f  Skip: {entry.name} \u2014 {e}\", C[\"warning\"])\n                L(f\"  \u2705 Cleared: {path}\", C[\"success\"])\n                L(f\"  \ud83d\udce6 Freed: {self._fmt_size(freed)}\", C[\"success\"])\n            else:\n                L(f\"  \u2b1c Path missing: {path}\", C[\"text_dim\"])\n        except Exception as e:\n            L(f\"  \u274c Error: {e}\", C[\"error\"])\n        finally:\n            L(\"  \u25b6\ufe0f  Restarting Windows Update services\u2026\", C[\"accent4\"])\n            try:\n                safe_run([\"net\", \"start\", \"wuauserv\"], timeout=60)\n                L(\"      \u2705 wuauserv started\", C[\"success\"])\n            except Exception as e:\n                L(f\"      \u26a0\ufe0f  wuauserv: {e}\", C[\"warning\"])\n            try:\n                safe_run([\"net\", \"start\", \"bits\"], timeout=60)\n                L(\"      \u2705 bits started\", C[\"success\"])\n            except Exception as e:\n                L(f\"      \u26a0\ufe0f  bits: {e}\", C[\"warning\"])\n        L(\"\u2501\"*52, C[\"border\"])\n        L(f\"\u2705 Delivery Optimization complete \u2014 {self._fmt_size(freed)} freed\", C[\"success\"])\n\n    # \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    #  INSTALLER ORPHAN SCANNER  \u2014  Scan first, user decides, then delete\n    # \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _open_installer_orphan_scanner(self):\n        \"\"\"\n        Popup window:\n          1. Scan C:\\\\Windows\\\\Installer for .msi/.msp files\n          2. For each file, resolve software name from registry (DisplayName),\n             show size + age in days + installed/orphan status\n          3. User checks boxes \u2014 only selected files get deleted\n        No automatic deletion. No blind 180-day cutoff.\n        \"\"\"\n        if not is_admin():\n            messagebox.showwarning(\n                \"Admin Required\",\n                \"Installer folder ko access karne ke liye Administrator rights chahiye.\\n\"\n                \"App ko as Administrator run karo.\"\n            )\n            return\n\n        win = tk.Toplevel(self)\n        win.title(\"\ud83d\uddc2 Installer Orphan Scanner\")\n        win.configure(bg=C[\"bg\"])\n        win.geometry(\"1020x640\")\n        win.resizable(True, True)\n        win.grab_set()\n\n        # \u2500\u2500 Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        hdr = tk.Frame(win, bg=C[\"card\"], pady=8)\n        hdr.pack(fill=\"x\", padx=0, pady=0)\n        tk.Label(hdr, text=\"\ud83d\uddc2  Installer Orphan Scanner\",\n                 font=FONTS[\"title\"], fg=C[\"accent4\"], bg=C[\"card\"]).pack(side=\"left\", padx=16)\n        tk.Label(hdr,\n                 text=\"Scan karo \u2192 naam/size/age dekho \u2192 jo genuinely orphan lage wohi select karo \u2192 Delete\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\", padx=8)\n\n        # \u2500\u2500 Treeview with checkboxes (simulated via tag + click) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        cols_frame = tk.Frame(win, bg=C[\"bg\"])\n        cols_frame.pack(fill=\"both\", expand=True, padx=12, pady=(8, 0))\n\n        columns = (\"sel\", \"filename\", \"software_name\", \"size\", \"age_days\", \"status\")\n        col_headers = (\"\u2611\", \"File\", \"Software (Registry)\", \"Size\", \"Age (days)\", \"Status\")\n        col_widths   = (30, 180, 280, 80, 90, 110)\n\n        style = ttk.Style()\n        style.configure(\"Orphan.Treeview\", rowheight=22,\n                        background=C[\"bg\"], foreground=C[\"text\"],\n                        fieldbackground=C[\"bg\"], borderwidth=0)\n        style.configure(\"Orphan.Treeview.Heading\",\n                        background=C[\"card\"], foreground=C[\"accent4\"],\n                        font=FONTS[\"small\"])\n        style.map(\"Orphan.Treeview\", background=[(\"selected\", C[\"accent\"])])\n\n        tree = ttk.Treeview(cols_frame, columns=columns, show=\"headings\",\n                            height=18, style=\"Orphan.Treeview\", selectmode=\"none\")\n        for col, hdr_text, w in zip(columns, col_headers, col_widths):\n            tree.heading(col, text=hdr_text)\n            tree.column(col, width=w, anchor=\"center\" if col in (\"sel\", \"size\", \"age_days\") else \"w\",\n                        stretch=(col == \"software_name\"))\n\n        vsb = ttk.Scrollbar(cols_frame, orient=\"vertical\", command=tree.yview)\n        tree.configure(yscrollcommand=vsb.set)\n        hsb = ttk.Scrollbar(cols_frame, orient=\"horizontal\", command=tree.xview)\n        tree.configure(xscrollcommand=hsb.set)\n        tree.grid(row=0, column=0, sticky=\"nsew\")\n        vsb.grid(row=0, column=1, sticky=\"ns\")\n        hsb.grid(row=1, column=0, sticky=\"ew\")\n        cols_frame.rowconfigure(0, weight=1)\n        cols_frame.columnconfigure(0, weight=1)\n\n        # Tag colors\n        tree.tag_configure(\"orphan\",    background=\"#2A1A1A\", foreground=\"#FF8080\")\n        tree.tag_configure(\"installed\", background=\"#1A2A1A\", foreground=\"#80D080\")\n        tree.tag_configure(\"checked\",   background=\"#1A2050\", foreground=\"#A0C0FF\")\n\n        # Internal state: iid \u2192 {path, checked, is_orphan, size}\n        _rows = {}\n\n        def _toggle(event):\n            iid = tree.identify_row(event.y)\n            if not iid or iid not in _rows:\n                return\n            d = _rows[iid]\n            d[\"checked\"] = not d[\"checked\"]\n            cur = list(tree.item(iid, \"values\"))\n            cur[0] = \"\u2611\" if d[\"checked\"] else \"\u2610\"\n            tree.item(iid, values=cur,\n                      tags=(\"checked\",) if d[\"checked\"] else\n                           (\"orphan\" if d[\"is_orphan\"] else \"installed\",))\n            _refresh_status()\n\n        tree.bind(\"\", _toggle)\n\n        # \u2500\u2500 Status bar \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        status_var = tk.StringVar(value=\"Scan karo pehle.\")\n        status_bar = tk.Label(win, textvariable=status_var,\n                              font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"], anchor=\"w\")\n        status_bar.pack(fill=\"x\", padx=14, pady=2)\n\n        def _refresh_status():\n            total   = len(_rows)\n            orphans = sum(1 for d in _rows.values() if d[\"is_orphan\"])\n            checked = sum(1 for d in _rows.values() if d[\"checked\"])\n            sel_sz  = sum(d[\"size\"] for d in _rows.values() if d[\"checked\"])\n            status_var.set(\n                f\"Total: {total} files  |  Orphan (likely): {orphans}  |  \"\n                f\"Selected: {checked}  |  Selected size: {self._fmt_size(sel_sz)}\"\n            )\n\n        # \u2500\u2500 Registry lookup helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        def _build_registry_map():\n            \"\"\"\n            Returns two dicts:\n              guid_to_name  : {'{GUID-lower}': 'DisplayName'}\n              path_to_name  : {'c:\\\\\\\\path\\\\\\\\to\\\\\\\\file.msi': 'DisplayName'}\n            Scans all three Uninstall hives + Components key.\n            \"\"\"\n            guid_to_name = {}\n            path_to_name = {}\n\n            uninstall_hives = [\n                (winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\"),\n                (winreg.HKEY_CURRENT_USER,  r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\"),\n                (winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\"),\n            ]\n            for hive, rpath in uninstall_hives:\n                try:\n                    key = winreg.OpenKey(hive, rpath, 0, winreg.KEY_READ | winreg.KEY_WOW64_64KEY)\n                    i = 0\n                    while True:\n                        try:\n                            sub_name = winreg.EnumKey(key, i); i += 1\n                        except OSError:\n                            break\n                        try:\n                            sub_key = winreg.OpenKey(key, sub_name, 0,\n                                                     winreg.KEY_READ | winreg.KEY_WOW64_64KEY)\n                            try:\n                                disp_name = winreg.QueryValueEx(sub_key, \"DisplayName\")[0]\n                            except FileNotFoundError:\n                                disp_name = sub_name  # fallback: GUID itself\n\n                            # Map GUID \u2192 name\n                            guid_to_name[sub_name.lower()] = disp_name\n\n                            # Map any installer path listed in the key \u2192 name\n                            for val_name in (\"InstallSource\", \"InstallLocation\"):\n                                try:\n                                    val = winreg.QueryValueEx(sub_key, val_name)[0]\n                                    if val:\n                                        path_to_name[val.lower()] = disp_name\n                                except FileNotFoundError:\n                                    pass\n                            winreg.CloseKey(sub_key)\n                        except Exception:\n                            pass\n                    winreg.CloseKey(key)\n                except Exception:\n                    pass\n            return guid_to_name, path_to_name\n\n        def _file_guid(filename):\n            \"\"\"Extract {GUID} pattern from filename if present.\"\"\"\n            m = re.search(r'\\{([0-9A-Fa-f\\-]{36})\\}', filename)\n            if m:\n                return '{' + m.group(1).upper() + '}'\n            # Also handle packed GUIDs (32 hex chars, no dashes)\n            m2 = re.match(r'^([0-9a-fA-F]{32})\\.(msi|msp)$', filename, re.IGNORECASE)\n            if m2:\n                h = m2.group(1)\n                # Reverse-transform packed GUID to standard form\n                try:\n                    def _unpack(s):\n                        return (s[7::-1] + '-' + s[11:7:-1] + '-' + s[15:11:-1] + '-' +\n                                s[17:15:-1] + s[19:17:-1] + '-' +\n                                s[21:19:-1] + s[23:21:-1] + s[25:23:-1] +\n                                s[27:25:-1] + s[29:27:-1] + s[31:29:-1]).upper()\n                    unpacked = _unpack(h)\n                    return '{' + unpacked + '}'\n                except Exception:\n                    return None\n            return None\n\n        def _resolve_name(filename, guid_to_name, path_to_name, full_path):\n            \"\"\"Return (software_name, is_installed).\"\"\"\n            # 1. Try GUID from filename\n            guid = _file_guid(filename)\n            if guid:\n                name = guid_to_name.get(guid.lower())\n                if name:\n                    return name, True\n                # GUID exists but not in uninstall keys \u2192 likely orphan\n                return f\"[GUID: {guid}]\", False\n\n            # 2. Try full path match\n            fp_lower = full_path.lower()\n            for p, n in path_to_name.items():\n                if fp_lower.startswith(p.lower()):\n                    return n, True\n\n            # 3. Try filename substring match against known names\n            fname_lower = filename.lower().replace('.msi', '').replace('.msp', '')\n            for g, n in guid_to_name.items():\n                if fname_lower and fname_lower in n.lower():\n                    return n, True\n\n            return \"[Unknown \u2014 no registry match]\", False\n\n        # \u2500\u2500 Scan \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        def _do_scan():\n            btn_scan.config(state=\"disabled\", text=\"\u23f3 Scanning\u2026\")\n            btn_delete.config(state=\"disabled\")\n            btn_select_all.config(state=\"disabled\")\n            btn_clear.config(state=\"disabled\")\n            tree.delete(*tree.get_children())\n            _rows.clear()\n            status_var.set(\"Scanning\u2026\")\n\n            def _worker():\n                inst_dir = r\"C:\\Windows\\Installer\"\n                result = []\n\n                try:\n                    guid_to_name, path_to_name = _build_registry_map()\n                except Exception as e:\n                    win.after(0, lambda: status_var.set(f\"Registry scan error: {e}\"))\n                    guid_to_name, path_to_name = {}, {}\n\n                if not os.path.isdir(inst_dir):\n                    win.after(0, lambda: status_var.set(\n                        f\"\u274c Folder nahi mili: {inst_dir}\"))\n                    win.after(0, lambda: btn_scan.config(state=\"normal\", text=\"\ud83d\udd0d Scan\"))\n                    return\n\n                now = time.time()\n                for entry in os.scandir(inst_dir):\n                    try:\n                        if not entry.name.lower().endswith(('.msi', '.msp')):\n                            continue\n                        try:\n                            sz = entry.stat().st_size\n                        except Exception:\n                            sz = 0\n                        try:\n                            mtime = entry.stat().st_mtime\n                            age_days = int((now - mtime) / 86400)\n                        except Exception:\n                            age_days = -1\n\n                        sw_name, is_installed = _resolve_name(\n                            entry.name, guid_to_name, path_to_name, entry.path)\n                        is_orphan = not is_installed\n\n                        result.append({\n                            \"path\":         entry.path,\n                            \"filename\":     entry.name,\n                            \"software\":     sw_name,\n                            \"size\":         sz,\n                            \"age_days\":     age_days,\n                            \"is_installed\": is_installed,\n                            \"is_orphan\":    is_orphan,\n                            \"checked\":      False,\n                        })\n                    except Exception:\n                        pass\n\n                # Sort: orphans first, then by size desc\n                result.sort(key=lambda r: (not r[\"is_orphan\"], -r[\"size\"]))\n\n                def _populate():\n                    for d in result:\n                        age_str    = f\"{d['age_days']}d\" if d['age_days'] &gt;= 0 else \"?\"\n                        status_str = \"\u26a0 Orphan\" if d[\"is_orphan\"] else \"\u2705 Installed\"\n                        tag        = \"orphan\" if d[\"is_orphan\"] else \"installed\"\n                        iid = tree.insert(\"\", \"end\", values=(\n                            \"\u2610\",\n                            d[\"filename\"],\n                            d[\"software\"],\n                            self._fmt_size(d[\"size\"]),\n                            age_str,\n                            status_str,\n                        ), tags=(tag,))\n                        _rows[iid] = d\n                    btn_scan.config(state=\"normal\", text=\"\ud83d\udd0d Scan\")\n                    btn_select_all.config(state=\"normal\")\n                    btn_clear.config(state=\"normal\")\n                    _refresh_status()\n\n                win.after(0, _populate)\n\n            threading.Thread(target=_worker, daemon=True).start()\n\n        # \u2500\u2500 Select helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        def _select_all_orphans():\n            for iid, d in _rows.items():\n                if d[\"is_orphan\"]:\n                    d[\"checked\"] = True\n                    cur = list(tree.item(iid, \"values\"))\n                    cur[0] = \"\u2611\"\n                    tree.item(iid, values=cur, tags=(\"checked\",))\n            _refresh_status()\n\n        def _clear_all():\n            for iid, d in _rows.items():\n                d[\"checked\"] = False\n                cur = list(tree.item(iid, \"values\"))\n                cur[0] = \"\u2610\"\n                tree.item(iid, values=cur,\n                          tags=(\"orphan\" if d[\"is_orphan\"] else \"installed\",))\n            _refresh_status()\n\n        # \u2500\u2500 Delete selected \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        def _delete_selected():\n            to_delete = [(iid, d) for iid, d in _rows.items() if d[\"checked\"]]\n            if not to_delete:\n                messagebox.showinfo(\"Nothing selected\", \"Pehle files select karo (checkbox click karo).\")\n                return\n            total_sz = sum(d[\"size\"] for _, d in to_delete)\n            names_preview = \"\\n\".join(\n                f\"  \u2022 {d['filename']}  ({d['software']})\"\n                for _, d in to_delete[:12]\n            )\n            if len(to_delete) &gt; 12:\n                names_preview += f\"\\n  \u2026 aur {len(to_delete) - 12} files\"\n\n            confirm = messagebox.askyesno(\n                \"Confirm Delete\",\n                f\"{len(to_delete)} files permanently delete honge \"\n                f\"({self._fmt_size(total_sz)} free \u0939\u094b\u0917\u093e):\\n\\n\"\n                f\"{names_preview}\\n\\n\"\n                \"UNDO POSSIBLE NAHI. Proceed?\"\n            )\n            if not confirm:\n                return\n\n            deleted = 0\n            failed  = 0\n            freed   = 0\n            for iid, d in to_delete:\n                try:\n                    os.remove(d[\"path\"])\n                    freed += d[\"size\"]\n                    deleted += 1\n                    tree.delete(iid)\n                    del _rows[iid]\n                except Exception as e:\n                    failed += 1\n                    # Mark as failed in tree\n                    cur = list(tree.item(iid, \"values\"))\n                    cur[5] = f\"\u274c Failed\"\n                    tree.item(iid, values=cur)\n\n            # Log to main clean_log\n            self._append_log(self.clean_log,\n                f\"\ud83d\uddc2 Installer Orphan Scanner: {deleted} deleted, \"\n                f\"{failed} failed, {self._fmt_size(freed)} freed.\",\n                C[\"success\"] if not failed else C[\"warning\"])\n\n            messagebox.showinfo(\n                \"Done!\",\n                f\"\u2705 {deleted} files deleted ({self._fmt_size(freed)} freed)\"\n                + (f\"\\n\u26a0 {failed} files delete nahi hue (locked/permission error).\" if failed else \"\")\n            )\n            _refresh_status()\n\n        # \u2500\u2500 Button bar \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        btn_frame = tk.Frame(win, bg=C[\"bg\"])\n        btn_frame.pack(fill=\"x\", padx=12, pady=(4, 10))\n\n        btn_scan = tk.Button(btn_frame, text=\"\ud83d\udd0d Scan\", font=FONTS[\"body\"],\n                             bg=C[\"accent\"], fg=C[\"bg\"], bd=0, padx=14, pady=7,\n                             cursor=\"hand2\", command=_do_scan)\n        btn_scan.pack(side=\"left\", padx=(0, 6))\n\n        btn_select_all = tk.Button(btn_frame, text=\"\u26a0 Select All Orphans\", font=FONTS[\"body\"],\n                                   bg=C[\"btn_warn\"], fg=C[\"text\"], bd=0, padx=12, pady=7,\n                                   cursor=\"hand2\", command=_select_all_orphans, state=\"disabled\")\n        btn_select_all.pack(side=\"left\", padx=(0, 6))\n\n        btn_clear = tk.Button(btn_frame, text=\"\u2610 Clear Selection\", font=FONTS[\"body\"],\n                              bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=12, pady=7,\n                              cursor=\"hand2\", command=_clear_all, state=\"disabled\")\n        btn_clear.pack(side=\"left\", padx=(0, 6))\n\n        btn_delete = tk.Button(btn_frame, text=\"\ud83d\uddd1 Delete Selected\", font=FONTS[\"body\"],\n                               bg=C[\"error\"], fg=C[\"text\"], bd=0, padx=14, pady=7,\n                               cursor=\"hand2\", command=_delete_selected, state=\"normal\")\n        btn_delete.pack(side=\"left\", padx=(0, 6))\n\n        tk.Button(btn_frame, text=\"\u2716 Close\", font=FONTS[\"body\"],\n                  bg=C[\"card\"], fg=C[\"text\"], bd=0, padx=12, pady=7,\n                  cursor=\"hand2\", command=win.destroy).pack(side=\"right\")\n\n        # Info label\n        tk.Label(btn_frame,\n                 text=\"\ud83d\udca1 Green = software installed hai  |  Red = orphan (no registry match)  |  Click row to toggle \u2611\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"]).pack(side=\"left\", padx=10)\n\n    def _do_clean_installer_orphans(self):\n        \"\"\"Legacy stub \u2014 replaced by _open_installer_orphan_scanner popup.\"\"\"\n        self._open_installer_orphan_scanner()\n\n    def _do_social_media_cache_purge(self):\n        def L(msg, color=None): self._append_log(self.clean_log, msg, color or C[\"text\"])\n        L(\"\u2501\"*52, C[\"border\"])\n        L(\"\ud83d\udde8  Social Media Cache Purge \u2014 starting\", C[\"accent4\"])\n        L(\"\u2501\"*52, C[\"border\"])\n        local   = os.environ.get(\"LOCALAPPDATA\", \"\")\n        roaming = os.environ.get(\"APPDATA\", \"\")\n        app_targets = [\n            (\"Discord\",          os.path.join(local,   \"Discord\")),\n            (\"Telegram (local)\", os.path.join(local,   \"Telegram Desktop\")),\n            (\"Telegram (roam)\",  os.path.join(roaming, \"Telegram Desktop\")),\n            (\"WhatsApp\",         os.path.join(local,   \"WhatsApp\")),\n        ]\n        # \u26a0\ufe0f  \"storage\" hataya gaya \u2014 WhatsApp/Telegram ke storage folder mein\n        #     user ka actual downloaded media hota hai, sirf cache nahi.\n        #     \"media\" bhi hataya \u2014 Telegram ke Media folder mein user files hoti hain.\n        cache_keywords = (\"cache\", \"cachev2\", \"gpu\", \"tmp\", \"logs\", \"voice\", \"voice-cache\")\n        removed = 0\n        freed   = 0\n        for app_name, path in app_targets:\n            if not path or not os.path.isdir(path):\n                L(f\"  \u2b1c {app_name:&lt;18s}  [not installed]\", C[\"text_dim\"])\n                continue\n            app_freed = 0\n            app_removed = 0\n            L(f\"  \ud83d\udcf1 {app_name}\", C[\"accent\"])\n            for root_d, dirs, files in os.walk(path):\n                for d in list(dirs):\n                    if any(x in d.lower() for x in cache_keywords):\n                        p = os.path.join(root_d, d)\n                        try:\n                            sz = self._folder_size(p)\n                            shutil.rmtree(p, ignore_errors=True)\n                            app_freed += sz\n                            app_removed += 1\n                            L(f\"      \ud83d\uddd1 {d}  ({self._fmt_size(sz)})\", C[\"success\"])\n                            dirs.remove(d)\n                        except Exception as e:\n                            L(f\"      \u26a0\ufe0f  {d}: {e}\", C[\"warning\"])\n            L(f\"      \u2705 {app_name}: {app_removed} dirs, {self._fmt_size(app_freed)} freed\", C[\"success\"])\n            freed   += app_freed\n            removed += app_removed\n        L(\"\u2501\"*52, C[\"border\"])\n        L(f\"\u2705 Social Media Cache Purge complete \u2014 {removed} dirs removed, {self._fmt_size(freed)} freed\", C[\"success\"])\n\n    def _do_purge_directx_shader_cache(self):\n        def L(msg, color=None): self._append_log(self.clean_log, msg, color or C[\"text\"])\n        L(\"\u2501\"*52, C[\"border\"])\n        L(\"\ud83c\udfae  DirectX Shader Cache Purger \u2014 starting\", C[\"accent4\"])\n        L(\"\u2501\"*52, C[\"border\"])\n        user  = os.path.expanduser(\"~\")\n        local = os.environ.get(\"LOCALAPPDATA\", \"\")\n        targets = [\n            (\"D3D Shader Cache\",    os.path.join(user, \"AppData\", \"Local\", \"D3DSCache\")),\n            (\"DirectX WebCache\",    os.path.join(local, \"Microsoft\", \"DirectX\", \"WebCache\")),\n            (\"NVIDIA DXCache\",      os.path.join(local, \"NVIDIA\", \"DXCache\")),\n            (\"AMD DXCache\",         os.path.join(local, \"AMD\", \"DXCache\")),\n        ]\n        removed = 0\n        freed   = 0\n        for label, path in targets:\n            if not path or not os.path.isdir(path):\n                L(f\"  \u2b1c {label:&lt;22s}  [not found]\", C[\"text_dim\"])\n                continue\n            sz_before = self._folder_size(path)\n            L(f\"  \ud83c\udfae {label:&lt;22s}  {self._fmt_size(sz_before)}\", C[\"text\"])\n            for entry in os.scandir(path):\n                try:\n                    esz = os.path.getsize(entry.path) if entry.is_file() else self._folder_size(entry.path)\n                    if entry.is_file():\n                        os.remove(entry.path)\n                    elif entry.is_dir():\n                        shutil.rmtree(entry.path, ignore_errors=True)\n                    freed   += esz\n                    removed += 1\n                except Exception as e:\n                    L(f\"      \u26a0\ufe0f  {entry.name}: {e}\", C[\"warning\"])\n            L(f\"      \u2705 Cleared \u2014 {self._fmt_size(sz_before)} freed\", C[\"success\"])\n        L(\"\u2501\"*52, C[\"border\"])\n        L(f\"\u2705 DirectX Shader Purge complete \u2014 {removed} items, {self._fmt_size(freed)} freed\", C[\"success\"])\n\n    def _do_trim_system_crash_dumps(self):\n        \"\"\"\n        Crash Dump &amp; Log Trimmer \u2014 scan-first popup.\n        Minidumps useful hote hain debugging ke liye \u2014 user ko list dikha ke decide karne do.\n        \"\"\"\n        win = tk.Toplevel(self)\n        win.title(\"\ud83d\udca5 System Crash Dump &amp; Log Trimmer\")\n        win.configure(bg=C[\"bg\"])\n        win.geometry(\"860x540\")\n        win.resizable(True, True)\n        win.grab_set()\n\n        hdr = tk.Frame(win, bg=C[\"card\"], pady=8)\n        hdr.pack(fill=\"x\")\n        tk.Label(hdr, text=\"\ud83d\udca5  Crash Dump &amp; Log Trimmer\",\n                 font=FONTS[\"title\"], fg=C[\"accent4\"], bg=C[\"card\"]).pack(side=\"left\", padx=16)\n        tk.Label(hdr,\n                 text=\"\u26a0 Minidumps crash analysis ke liye useful hain \u2014 review karke delete karo\",\n                 font=FONTS[\"small\"], fg=\"#FFB347\", bg=C[\"card\"]).pack(side=\"left\", padx=8)\n\n        info_frame = tk.Frame(win, bg=C[\"panel\"], pady=4)\n        info_frame.pack(fill=\"x\", padx=12, pady=(6, 0))\n        tk.Label(info_frame,\n                 text=\"\ud83d\udca1  .dmp files: Windows crash dumps (IT/developer ko chahiye ho sakta hai)  |  \"\n                      \".log files: CBS logs (generally safe to delete)  |  \"\n                      \"WER: Windows Error Reports\",\n                 font=FONTS[\"xsmall\"], fg=C[\"text_dim\"], bg=C[\"panel\"],\n                 wraplength=820, justify=\"left\").pack(anchor=\"w\", padx=8, pady=2)\n\n        cols_frame = tk.Frame(win, bg=C[\"bg\"])\n        cols_frame.pack(fill=\"both\", expand=True, padx=12, pady=(6, 0))\n\n        columns  = (\"sel\", \"type\",  \"filename\",  \"size\",  \"age_days\")\n        col_hdrs = (\"\u2611\",  \"Type\",   \"File\",       \"Size\",  \"Age (days)\")\n        col_ws   = (30,    100,       360,           70,      90)\n\n        style = ttk.Style()\n        style.configure(\"Dump.Treeview\", rowheight=22,\n                        background=C[\"bg\"], foreground=C[\"text\"],\n                        fieldbackground=C[\"bg\"], borderwidth=0)\n        style.configure(\"Dump.Treeview.Heading\",\n                        background=C[\"card\"], foreground=C[\"accent4\"],\n                        font=FONTS[\"small\"])\n\n        tree = ttk.Treeview(cols_frame, columns=columns, show=\"headings\",\n                            height=14, style=\"Dump.Treeview\", selectmode=\"none\")\n        for col, h, w in zip(columns, col_hdrs, col_ws):\n            tree.heading(col, text=h)\n            tree.column(col, width=w, anchor=\"center\" if col in (\"sel\",\"size\",\"age_days\") else \"w\",\n                        stretch=(col == \"filename\"))\n        vsb = ttk.Scrollbar(cols_frame, orient=\"vertical\", command=tree.yview)\n        tree.configure(yscrollcommand=vsb.set)\n        tree.grid(row=0, column=0, sticky=\"nsew\"); vsb.grid(row=0, column=1, sticky=\"ns\")\n        cols_frame.rowconfigure(0, weight=1); cols_frame.columnconfigure(0, weight=1)\n\n        tree.tag_configure(\"dump\",    background=\"#2A1A1A\", foreground=\"#FF9060\")\n        tree.tag_configure(\"log\",     background=\"#1A1A2A\", foreground=\"#8080D0\")\n        tree.tag_configure(\"wer\",     background=\"#1A2A2A\", foreground=\"#60C0B0\")\n        tree.tag_configure(\"checked\", background=\"#1A2050\", foreground=\"#A0C0FF\")\n\n        _rows = {}\n        now = time.time()\n\n        scan_targets = [\n            (\"Minidump (.dmp)\", r\"C:\\Windows\\Minidump\",\n             lambda n: n.lower().endswith(\".dmp\"), \"dump\"),\n            (\"CBS Log (.log)\",  r\"C:\\Windows\\Logs\\CBS\",\n             lambda n: n.lower().endswith(\".log\"), \"log\"),\n            (\"WER Report\",\n             os.path.join(os.environ.get(\"LOCALAPPDATA\",\"\"),\n                          r\"Microsoft\\Windows\\WER\\ReportArchive\"),\n             None, \"wer\"),\n        ]\n\n        for type_label, scan_path, ext_filter, tag in scan_targets:\n            if not os.path.isdir(scan_path):\n                continue\n            for entry in os.scandir(scan_path):\n                try:\n                    if entry.is_file():\n                        if ext_filter and not ext_filter(entry.name):\n                            continue\n                        sz  = entry.stat().st_size\n                        age = int((now - entry.stat().st_mtime) / 86400)\n                        _rows[tree.insert(\"\", \"end\", values=(\n                            \"\u2610\", type_label, entry.name,\n                            self._fmt_size(sz), str(age)), tags=(tag,))] = {\n                            \"path\": entry.path, \"size\": sz, \"age_days\": age,\n                            \"checked\": False, \"is_dir\": False}\n                    elif entry.is_dir() and tag == \"wer\":\n                        try:\n                            sz  = self._folder_size(entry.path)\n                            age = int((now - entry.stat().st_mtime) / 86400)\n                        except Exception:\n                            sz = 0; age = 0\n                        _rows[tree.insert(\"\", \"end\", values=(\n                            \"\u2610\", type_label, entry.name + \"/\",\n                            self._fmt_size(sz), str(age)), tags=(tag,))] = {\n                            \"path\": entry.path, \"size\": sz, \"age_days\": age,\n                            \"checked\": False, \"is_dir\": True}\n                except Exception:\n                    pass\n\n        def _toggle(event):\n            iid = tree.identify_row(event.y)\n            if not iid or iid not in _rows: return\n            d = _rows[iid]; d[\"checked\"] = not d[\"checked\"]\n            cur = list(tree.item(iid, \"values\")); cur[0] = \"\u2611\" if d[\"checked\"] else \"\u2610\"\n            orig_tag = tree.item(iid, \"tags\")\n            tree.item(iid, values=cur,\n                      tags=(\"checked\",) if d[\"checked\"] else orig_tag)\n            _refresh_status()\n        tree.bind(\"\", _toggle)\n\n        status_var = tk.StringVar(value=\"\")\n        tk.Label(win, textvariable=status_var, font=FONTS[\"small\"],\n                 fg=C[\"text_dim\"], bg=C[\"bg\"], anchor=\"w\").pack(fill=\"x\", padx=14, pady=2)\n\n        def _refresh_status():\n            total   = len(_rows)\n            checked = sum(1 for d in _rows.values() if d[\"checked\"])\n            sel_sz  = sum(d[\"size\"] for d in _rows.values() if d[\"checked\"])\n            status_var.set(f\"Total: {total}  |  Selected: {checked}  |  \"\n                           f\"Selected size: {self._fmt_size(sel_sz)}\")\n        _refresh_status()\n\n        def _select_logs_wer():\n            \"\"\"Only select .log and WER \u2014 skip minidumps by default (more useful)\"\"\"\n            for iid, d in _rows.items():\n                tags = tree.item(iid, \"tags\")\n                if \"dump\" not in tags:\n                    d[\"checked\"] = True\n                    cur = list(tree.item(iid, \"values\")); cur[0] = \"\u2611\"\n                    tree.item(iid, values=cur, tags=(\"checked\",))\n            _refresh_status()\n\n        def _select_all():\n            for iid, d in _rows.items():\n                d[\"checked\"] = True\n                cur = list(tree.item(iid, \"values\")); cur[0] = \"\u2611\"\n                tree.item(iid, values=cur, tags=(\"checked\",))\n            _refresh_status()\n\n        def _clear_all():\n            for iid, d in _rows.items():\n                d[\"checked\"] = False\n                cur = list(tree.item(iid, \"values\")); cur[0] = \"\u2610\"\n                # restore original tag from type\n                orig = \"dump\" if \"Minidump\" in cur[1] else (\"wer\" if \"WER\" in cur[1] else \"log\")\n                tree.item(iid, values=cur, tags=(orig,))\n            _refresh_status()\n\n        def _delete_selected():\n            to_del = [(iid, d) for iid, d in _rows.items() if d[\"checked\"]]\n            if not to_del:\n                messagebox.showinfo(\"Nothing selected\", \"Pehle files select karo.\"); return\n            total_sz = sum(d[\"size\"] for _, d in to_del)\n            if not messagebox.askyesno(\"Confirm Delete\",\n                    f\"{len(to_del)} items delete honge ({self._fmt_size(total_sz)}).\\n\\n\"\n                    \"Minidumps delete karne se crash analysis possible nahi hoga.\\n\"\n                    \"Proceed?\"):\n                return\n            deleted = failed = freed = 0\n            for iid, d in to_del:\n                try:\n                    if d[\"is_dir\"]:\n                        shutil.rmtree(d[\"path\"], ignore_errors=True)\n                    else:\n                        os.remove(d[\"path\"])\n                    freed += d[\"size\"]; deleted += 1\n                    tree.delete(iid); del _rows[iid]\n                except Exception:\n                    failed += 1\n                    cur = list(tree.item(iid, \"values\")); cur[4] = \"\u274c Failed\"\n                    tree.item(iid, values=cur)\n            self._append_log(self.clean_log,\n                f\"\ud83d\udca5 Crash Dump Trimmer: {deleted} deleted, {failed} failed, \"\n                f\"{self._fmt_size(freed)} freed.\",\n                C[\"success\"] if not failed else C[\"warning\"])\n            messagebox.showinfo(\"Done!\",\n                f\"\u2705 {deleted} items deleted ({self._fmt_size(freed)} freed)\"\n                + (f\"\\n\u26a0 {failed} failed.\" if failed else \"\"))\n            _refresh_status()\n\n        btn_frame = tk.Frame(win, bg=C[\"bg\"])\n        btn_frame.pack(fill=\"x\", padx=12, pady=(4, 10))\n        tk.Button(btn_frame, text=\"\ud83d\udccb Select Logs+WER (skip dumps)\", font=FONTS[\"body\"],\n                  bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=12, pady=7,\n                  cursor=\"hand2\", command=_select_logs_wer).pack(side=\"left\", padx=(0,6))\n        tk.Button(btn_frame, text=\"\u26a0 Select All\", font=FONTS[\"body\"],\n                  bg=C[\"btn_warn\"], fg=C[\"text\"], bd=0, padx=12, pady=7,\n                  cursor=\"hand2\", command=_select_all).pack(side=\"left\", padx=(0,6))\n        tk.Button(btn_frame, text=\"\u2610 Clear\", font=FONTS[\"body\"],\n                  bg=C[\"card\"], fg=C[\"text\"], bd=0, padx=10, pady=7,\n                  cursor=\"hand2\", command=_clear_all).pack(side=\"left\", padx=(0,6))\n        tk.Button(btn_frame, text=\"\ud83d\uddd1 Delete Selected\", font=FONTS[\"body\"],\n                  bg=C[\"error\"], fg=C[\"text\"], bd=0, padx=14, pady=7,\n                  cursor=\"hand2\", command=_delete_selected).pack(side=\"left\", padx=(0,6))\n        tk.Button(btn_frame, text=\"\u2716 Close\", font=FONTS[\"body\"],\n                  bg=C[\"card\"], fg=C[\"text\"], bd=0, padx=12, pady=7,\n                  cursor=\"hand2\", command=win.destroy).pack(side=\"right\")\n\n    def _do_clean_prefetch(self):\n        \"\"\"\n        Prefetch Cleaner \u2014 scan-first popup.\n        Windows prefetch (.pf) files startup speed improve karte hain.\n        User ko pehle list dikhao: naam, size, age \u2014 tabhi select karke delete.\n        \"\"\"\n        if not is_admin():\n            messagebox.showwarning(\n                \"Admin Required\",\n                \"Prefetch folder access ke liye Administrator rights chahiye.\\n\"\n                \"App ko as Administrator run karo.\"\n            )\n            return\n\n        path = r\"C:\\Windows\\Prefetch\"\n        if not os.path.isdir(path):\n            messagebox.showinfo(\"Prefetch Cleaner\", f\"Prefetch folder nahi mila:\\n{path}\")\n            return\n\n        win = tk.Toplevel(self)\n        win.title(\"\u2699 Prefetch Cleaner\")\n        win.configure(bg=C[\"bg\"])\n        win.geometry(\"820x520\")\n        win.resizable(True, True)\n        win.grab_set()\n\n        # Header with warning\n        hdr = tk.Frame(win, bg=C[\"card\"], pady=8)\n        hdr.pack(fill=\"x\")\n        tk.Label(hdr, text=\"\u2699  Prefetch Cleaner\",\n                 font=FONTS[\"title\"], fg=C[\"accent4\"], bg=C[\"card\"]).pack(side=\"left\", padx=16)\n        tk.Label(hdr,\n                 text=\"\u26a0 Prefetch files startup speed improve karte hain \u2014 sirf purani files delete karo\",\n                 font=FONTS[\"small\"], fg=\"#FFB347\", bg=C[\"card\"]).pack(side=\"left\", padx=8)\n\n        # Info bar\n        info_frame = tk.Frame(win, bg=C[\"panel\"], pady=4)\n        info_frame.pack(fill=\"x\", padx=12, pady=(6, 0))\n        tk.Label(info_frame,\n                 text=\"\ud83d\udca1  30 din se purani .pf files generally safe hain delete karne ke liye. \"\n                      \"Fresh files (&lt; 30 din) Windows currently use kar raha hai \u2014 unhe chhodna behtar hai.\",\n                 font=FONTS[\"xsmall\"], fg=C[\"text_dim\"], bg=C[\"panel\"],\n                 wraplength=780, justify=\"left\").pack(anchor=\"w\", padx=8, pady=2)\n\n        # Treeview\n        cols_frame = tk.Frame(win, bg=C[\"bg\"])\n        cols_frame.pack(fill=\"both\", expand=True, padx=12, pady=(6, 0))\n\n        columns  = (\"sel\", \"filename\", \"size\", \"age_days\", \"hint\")\n        col_hdrs = (\"\u2611\",  \"File (.pf)\",  \"Size\",  \"Age (days)\", \"Suggestion\")\n        col_ws   = (30,    360,            70,       90,           120)\n\n        style = ttk.Style()\n        style.configure(\"Prefetch.Treeview\", rowheight=22,\n                        background=C[\"bg\"], foreground=C[\"text\"],\n                        fieldbackground=C[\"bg\"], borderwidth=0)\n        style.configure(\"Prefetch.Treeview.Heading\",\n                        background=C[\"card\"], foreground=C[\"accent4\"],\n                        font=FONTS[\"small\"])\n\n        tree = ttk.Treeview(cols_frame, columns=columns, show=\"headings\",\n                            height=14, style=\"Prefetch.Treeview\", selectmode=\"none\")\n        for col, h, w in zip(columns, col_hdrs, col_ws):\n            tree.heading(col, text=h)\n            tree.column(col, width=w, anchor=\"center\" if col in (\"sel\",\"size\",\"age_days\") else \"w\",\n                        stretch=(col == \"filename\"))\n        vsb = ttk.Scrollbar(cols_frame, orient=\"vertical\", command=tree.yview)\n        tree.configure(yscrollcommand=vsb.set)\n        tree.grid(row=0, column=0, sticky=\"nsew\"); vsb.grid(row=0, column=1, sticky=\"ns\")\n        cols_frame.rowconfigure(0, weight=1); cols_frame.columnconfigure(0, weight=1)\n\n        tree.tag_configure(\"old\",   background=\"#2A1A1A\", foreground=\"#FF8080\")\n        tree.tag_configure(\"fresh\", background=\"#1A2A1A\", foreground=\"#80D080\")\n        tree.tag_configure(\"checked\", background=\"#1A2050\", foreground=\"#A0C0FF\")\n\n        _rows = {}\n        now = time.time()\n\n        def _toggle(event):\n            iid = tree.identify_row(event.y)\n            if not iid or iid not in _rows: return\n            d = _rows[iid]; d[\"checked\"] = not d[\"checked\"]\n            cur = list(tree.item(iid, \"values\")); cur[0] = \"\u2611\" if d[\"checked\"] else \"\u2610\"\n            tree.item(iid, values=cur, tags=(\"checked\",) if d[\"checked\"] else\n                      (\"old\" if d[\"age_days\"] &gt;= 30 else \"fresh\",))\n            _refresh_status()\n        tree.bind(\"\", _toggle)\n\n        status_var = tk.StringVar(value=\"\")\n        tk.Label(win, textvariable=status_var, font=FONTS[\"small\"],\n                 fg=C[\"text_dim\"], bg=C[\"bg\"], anchor=\"w\").pack(fill=\"x\", padx=14, pady=2)\n\n        def _refresh_status():\n            total   = len(_rows)\n            old_ct  = sum(1 for d in _rows.values() if d[\"age_days\"] &gt;= 30)\n            checked = sum(1 for d in _rows.values() if d[\"checked\"])\n            sel_sz  = sum(d[\"size\"] for d in _rows.values() if d[\"checked\"])\n            status_var.set(f\"Total: {total}  |  30+ din purani: {old_ct}  |  \"\n                           f\"Selected: {checked}  |  Selected size: {self._fmt_size(sel_sz)}\")\n\n        # Populate\n        entries = []\n        for entry in os.scandir(path):\n            try:\n                if not entry.is_file() or not entry.name.lower().endswith(\".pf\"):\n                    continue\n                sz = entry.stat().st_size\n                age = int((now - entry.stat().st_mtime) / 86400)\n                entries.append({\"path\": entry.path, \"filename\": entry.name,\n                                 \"size\": sz, \"age_days\": age, \"checked\": False})\n            except Exception:\n                pass\n        entries.sort(key=lambda r: -r[\"age_days\"])\n        for d in entries:\n            hint = \"\u26a0 Purani (safe to delete)\" if d[\"age_days\"] &gt;= 30 else \"\u2705 Fresh (rakhna better)\"\n            tag  = \"old\" if d[\"age_days\"] &gt;= 30 else \"fresh\"\n            iid  = tree.insert(\"\", \"end\", values=(\n                \"\u2610\", d[\"filename\"], self._fmt_size(d[\"size\"]),\n                str(d[\"age_days\"]), hint), tags=(tag,))\n            _rows[iid] = d\n        _refresh_status()\n\n        def _select_old():\n            for iid, d in _rows.items():\n                if d[\"age_days\"] &gt;= 30:\n                    d[\"checked\"] = True\n                    cur = list(tree.item(iid, \"values\")); cur[0] = \"\u2611\"\n                    tree.item(iid, values=cur, tags=(\"checked\",))\n            _refresh_status()\n\n        def _clear_all():\n            for iid, d in _rows.items():\n                d[\"checked\"] = False\n                cur = list(tree.item(iid, \"values\")); cur[0] = \"\u2610\"\n                tree.item(iid, values=cur, tags=(\"old\" if d[\"age_days\"] &gt;= 30 else \"fresh\",))\n            _refresh_status()\n\n        def _delete_selected():\n            to_del = [(iid, d) for iid, d in _rows.items() if d[\"checked\"]]\n            if not to_del:\n                messagebox.showinfo(\"Nothing selected\", \"Pehle files select karo.\"); return\n            total_sz = sum(d[\"size\"] for _, d in to_del)\n            if not messagebox.askyesno(\"Confirm Delete\",\n                    f\"{len(to_del)} prefetch files delete honge \"\n                    f\"({self._fmt_size(total_sz)}).\\n\\n\"\n                    \"Windows inhe dobara banayega jab programs run honge.\\n\"\n                    \"Proceed?\"):\n                return\n            deleted = failed = freed = 0\n            for iid, d in to_del:\n                try:\n                    os.remove(d[\"path\"]); freed += d[\"size\"]; deleted += 1\n                    tree.delete(iid); del _rows[iid]\n                except Exception as e:\n                    failed += 1\n                    cur = list(tree.item(iid, \"values\")); cur[4] = \"\u274c Failed\"\n                    tree.item(iid, values=cur)\n            self._append_log(self.clean_log,\n                f\"\u2699 Prefetch Cleaner: {deleted} deleted, {failed} failed, \"\n                f\"{self._fmt_size(freed)} freed.\",\n                C[\"success\"] if not failed else C[\"warning\"])\n            messagebox.showinfo(\"Done!\",\n                f\"\u2705 {deleted} files deleted ({self._fmt_size(freed)} freed)\"\n                + (f\"\\n\u26a0 {failed} failed.\" if failed else \"\"))\n            _refresh_status()\n\n        btn_frame = tk.Frame(win, bg=C[\"bg\"])\n        btn_frame.pack(fill=\"x\", padx=12, pady=(4, 10))\n        tk.Button(btn_frame, text=\"\u26a0 Select 30+ Day Old\", font=FONTS[\"body\"],\n                  bg=C[\"btn_warn\"], fg=C[\"text\"], bd=0, padx=12, pady=7,\n                  cursor=\"hand2\", command=_select_old).pack(side=\"left\", padx=(0,6))\n        tk.Button(btn_frame, text=\"\u2610 Clear\", font=FONTS[\"body\"],\n                  bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=12, pady=7,\n                  cursor=\"hand2\", command=_clear_all).pack(side=\"left\", padx=(0,6))\n        tk.Button(btn_frame, text=\"\ud83d\uddd1 Delete Selected\", font=FONTS[\"body\"],\n                  bg=C[\"error\"], fg=C[\"text\"], bd=0, padx=14, pady=7,\n                  cursor=\"hand2\", command=_delete_selected).pack(side=\"left\", padx=(0,6))\n        tk.Button(btn_frame, text=\"\u2716 Close\", font=FONTS[\"body\"],\n                  bg=C[\"card\"], fg=C[\"text\"], bd=0, padx=12, pady=7,\n                  cursor=\"hand2\", command=win.destroy).pack(side=\"right\")\n\n\n    def _get_clean_paths(self):\n        v = self.clean_vars\n        paths = []\n        if v.get(\"temp\") and v[\"temp\"].get():\n            paths.append((\"Windows Temp\", r\"C:\\Windows\\Temp\"))\n        if v.get(\"user_temp\") and v[\"user_temp\"].get():\n            paths.append((\"User Temp\", os.environ.get(\"TEMP\", \"\")))\n        if v.get(\"prefetch\") and v[\"prefetch\"].get():\n            paths.append((\"Prefetch\", r\"C:\\Windows\\Prefetch\"))\n        if v.get(\"recycle\") and v[\"recycle\"].get():\n            paths.append((\"Recycle Bin\", r\"C:\\$Recycle.Bin\"))\n        if v.get(\"logs\") and v[\"logs\"].get():\n            paths.append((\"Windows Logs\", r\"C:\\Windows\\Logs\"))\n        if v.get(\"thumbnail\") and v[\"thumbnail\"].get():\n            paths.append((\"Thumbnails\", os.path.join(os.environ.get(\"LOCALAPPDATA\",\"\"), r\"Microsoft\\Windows\\Explorer\")))\n        if v.get(\"update\") and v[\"update\"].get():\n            paths.append((\"WU Cache\", r\"C:\\Windows\\SoftwareDistribution\\Download\"))\n        if v.get(\"dumps\") and v[\"dumps\"].get():\n            paths.append((\"Memory Dumps\", r\"C:\\Windows\\Minidump\"))\n        if v.get(\"errreport\") and v[\"errreport\"].get():\n            paths.append((\"Error Reports\", os.path.join(os.environ.get(\"LOCALAPPDATA\",\"\"), r\"Microsoft\\Windows\\WER\")))\n        if v.get(\"delivery\") and v[\"delivery\"].get():\n            paths.append((\"DO Cache\", os.path.join(os.environ.get(\"PROGRAMDATA\",\"\"), r\"Microsoft\\Windows\\DeliveryOptimization\\Cache\")))\n        if v.get(\"browser_office\") and v[\"browser_office\"].get():\n            local = os.environ.get(\"LOCALAPPDATA\",\"\")\n            roaming = os.environ.get(\"APPDATA\",\"\")\n            paths.extend([\n                # Browsers (primary caches)\n                (\"Chrome Cache\", os.path.join(local, \"Google\\\\Chrome\\\\User Data\\\\Default\\\\Cache\")),\n                (\"Chrome Code Cache\", os.path.join(local, \"Google\\\\Chrome\\\\User Data\\\\Default\\\\Code Cache\")),\n                (\"Edge Cache\", os.path.join(local, \"Microsoft\\\\Edge\\\\User Data\\\\Default\\\\Cache\")),\n                (\"Edge Code Cache\", os.path.join(local, \"Microsoft\\\\Edge\\\\User Data\\\\Default\\\\Code Cache\")),\n                (\"Firefox Cache\", os.path.join(local, \"Mozilla\\\\Firefox\\\\Profiles\")),\n                # Microsoft apps\n                (\"Office File Cache\", os.path.join(local, \"Microsoft\\\\Office\\\\16.0\\\\OfficeFileCache\")),\n                (\"Teams Cache\", os.path.join(roaming, \"Microsoft\\\\Teams\")),\n                (\"Teams (new) Cache\", os.path.join(local, \"Packages\\\\MSTeams_8wekyb3d8bbwe\\\\LocalCache\")),\n                (\"OneDrive Logs\", os.path.join(local, \"Microsoft\\\\OneDrive\\\\logs\")),\n                # Common app temp\n                (\"INetCache\", os.path.join(local, \"Microsoft\\\\Windows\\\\INetCache\")),\n                # Messaging app caches\n                (\"Discord Cache\", os.path.join(local, \"Discord\\\\Cache\")),\n                (\"Discord GPUCache\", os.path.join(local, \"Discord\\\\GPUCache\")),\n                (\"Telegram Desktop\", os.path.join(roaming, \"Telegram Desktop\")),\n            ])\n        return paths\n\n    def _is_reparse_point(self, path):\n        try:\n            st = os.stat(path, follow_symlinks=False)\n            attrs = getattr(st, \"st_file_attributes\", 0)\n            # FILE_ATTRIBUTE_REPARSE_POINT = 0x400 (junction/symlink)\n            return bool(attrs &amp; 0x400)\n        except Exception:\n            return False\n\n    def _safe_scandir(self, path):\n        try:\n            with os.scandir(path) as it:\n                for entry in it:\n                    yield entry\n        except Exception:\n            return\n\n    def _folder_size(self, path):\n        def _walk(p):\n            total = 0\n            try:\n                if not p or not os.path.exists(p):\n                    return 0\n                if os.path.isfile(p):\n                    try:\n                        return os.path.getsize(p)\n                    except Exception:\n                        return 0\n                if self._is_reparse_point(p):\n                    return 0\n                for ent in self._safe_scandir(p):\n                    try:\n                        if ent.is_symlink():\n                            continue\n                        if ent.is_file(follow_symlinks=False):\n                            try:\n                                total += ent.stat(follow_symlinks=False).st_size\n                            except Exception:\n                                pass\n                        elif ent.is_dir(follow_symlinks=False):\n                            if self._is_reparse_point(ent.path):\n                                continue\n                            total += _walk(ent.path)\n                    except Exception:\n                        continue\n            except Exception:\n                return total\n            return total\n        return _walk(path)\n\n    def _delete_folder_contents(self, path):\n        removed = 0\n        try:\n            if not path or not os.path.exists(path):\n                return 0\n            if os.path.isfile(path):\n                try:\n                    removed = os.path.getsize(path)\n                except Exception:\n                    removed = 0\n                try:\n                    os.remove(path)\n                except Exception:\n                    return 0\n                return removed\n            # Safety: never delete a reparse-point directory target\n            if self._is_reparse_point(path):\n                return 0\n\n            for ent in self._safe_scandir(path):\n                try:\n                    if ent.is_symlink():\n                        continue\n                    if ent.is_file(follow_symlinks=False):\n                        try:\n                            sz = ent.stat(follow_symlinks=False).st_size\n                        except Exception:\n                            sz = 0\n                        try:\n                            os.remove(ent.path)\n                            removed += sz\n                        except Exception:\n                            continue\n                    elif ent.is_dir(follow_symlinks=False):\n                        if self._is_reparse_point(ent.path):\n                            continue\n                        try:\n                            sz = self._folder_size(ent.path)\n                        except Exception:\n                            sz = 0\n                        try:\n                            shutil.rmtree(ent.path, ignore_errors=True)\n                            removed += sz\n                        except Exception:\n                            continue\n                except Exception:\n                    continue\n        except Exception:\n            return removed\n        return removed\n\n    # ---------- SERVICES (unchanged but with confirm wrappers) ----------\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  SERVICE KNOWLEDGE BASE\n    #  Category:  \"critical\"  = Windows ka dil \u2014 kabhi band mat karo\n    #             \"important\" = Windows ka kaam rukta hai \u2014 soch ke karo\n    #             \"optional\"  = Disable kar sakte ho \u2014 performance badhegi\n    #             \"thirdparty\"= Third-party software ki service\n    #  safe_to_stop: True/False \u2014 kya sirf stop safe hai\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    SVC_DB = {\n        # \u2500\u2500 CRITICAL \u2014 kabhi mat chhuo \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        \"lsass\":         {\"cat\":\"critical\",\"safe_to_stop\":False,\n                          \"desc\":\"Windows Login &amp; Security Authority. Isko band karna = Blue Screen ya instant shutdown.\",\n                          \"display\":\"Local Security Authority Process\"},\n        \"wininit\":       {\"cat\":\"critical\",\"safe_to_stop\":False,\n                          \"desc\":\"Windows Initialization. System start ke liye zaroori hai.\",\n                          \"display\":\"Windows Start-Up Application\"},\n        \"services\":      {\"cat\":\"critical\",\"safe_to_stop\":False,\n                          \"desc\":\"Saari services ka manager. Isko band karna = system crash.\",\n                          \"display\":\"Services and Controller app\"},\n        \"rpcss\":         {\"cat\":\"critical\",\"safe_to_stop\":False,\n                          \"desc\":\"RPC (Remote Procedure Call). Saare Windows components isko use karte hain.\",\n                          \"display\":\"Remote Procedure Call (RPC)\"},\n        \"dcomlaunch\":    {\"cat\":\"critical\",\"safe_to_stop\":False,\n                          \"desc\":\"COM Server launch. Explorer, taskbar sab band ho jaayenge.\",\n                          \"display\":\"DCOM Server Process Launcher\"},\n        \"plugplay\":      {\"cat\":\"critical\",\"safe_to_stop\":False,\n                          \"desc\":\"Hardware detect karta hai. USB, keyboard, mouse sab band ho jaayenge.\",\n                          \"display\":\"Plug and Play\"},\n        \"windefend\":     {\"cat\":\"critical\",\"safe_to_stop\":False,\n                          \"desc\":\"Windows Defender Antivirus. Virus protection band ho jaayegi.\",\n                          \"display\":\"Windows Defender Antivirus Service\"},\n        \"mpssvc\":        {\"cat\":\"critical\",\"safe_to_stop\":False,\n                          \"desc\":\"Windows Firewall. Internet security band ho jaayegi.\",\n                          \"display\":\"Windows Defender Firewall\"},\n        \"eventlog\":      {\"cat\":\"critical\",\"safe_to_stop\":False,\n                          \"desc\":\"System Event Log. Band karne se system instability aa sakti hai.\",\n                          \"display\":\"Windows Event Log\"},\n        \"nsi\":           {\"cat\":\"critical\",\"safe_to_stop\":False,\n                          \"desc\":\"Network Store Interface. Internet/network band ho jaayega.\",\n                          \"display\":\"Network Store Interface Service\"},\n        \"dhcp\":          {\"cat\":\"critical\",\"safe_to_stop\":False,\n                          \"desc\":\"IP Address automatic milti hai isse. Band = no internet.\",\n                          \"display\":\"DHCP Client\"},\n        \"dnscache\":      {\"cat\":\"critical\",\"safe_to_stop\":False,\n                          \"desc\":\"DNS Cache. Band karne se websites nahi khulengi.\",\n                          \"display\":\"DNS Client\"},\n        \"cryptsvc\":      {\"cat\":\"critical\",\"safe_to_stop\":False,\n                          \"desc\":\"Windows Updates aur certificates ke liye zaroori hai.\",\n                          \"display\":\"Cryptographic Services\"},\n        \"wuauserv\":      {\"cat\":\"critical\",\"safe_to_stop\":True,\n                          \"desc\":\"Windows Update. Stop kar sakte ho lekin security risk hai. Disable mat karo permanently.\",\n                          \"display\":\"Windows Update\"},\n        \"bits\":          {\"cat\":\"important\",\"safe_to_stop\":True,\n                          \"desc\":\"Background download manager. Windows updates isi se aate hain.\",\n                          \"display\":\"Background Intelligent Transfer Service\"},\n        \"spooler\":       {\"cat\":\"important\",\"safe_to_stop\":True,\n                          \"desc\":\"Printer service. Agar printer nahi use karte to stop kar sakte ho.\",\n                          \"display\":\"Print Spooler\"},\n        \"audiosrv\":      {\"cat\":\"important\",\"safe_to_stop\":False,\n                          \"desc\":\"Sound service. Band karne se koi awaz nahi aayegi.\",\n                          \"display\":\"Windows Audio\"},\n        \"audioendpointbuilder\":{\"cat\":\"important\",\"safe_to_stop\":False,\n                          \"desc\":\"Audio devices manager. Band = no sound.\",\n                          \"display\":\"Windows Audio Endpoint Builder\"},\n        \"netlogon\":      {\"cat\":\"important\",\"safe_to_stop\":True,\n                          \"desc\":\"Domain/network login ke liye. Home PC pe stop kar sakte ho.\",\n                          \"display\":\"Netlogon\"},\n        \"lanmanworkstation\":{\"cat\":\"important\",\"safe_to_stop\":True,\n                          \"desc\":\"Network shared folders access. Agar network nahi use karte to stop kar sakte ho.\",\n                          \"display\":\"Workstation\"},\n        \"lanmanserver\":  {\"cat\":\"important\",\"safe_to_stop\":True,\n                          \"desc\":\"Apni files share karne ke liye. Home use mein stop kar sakte ho.\",\n                          \"display\":\"Server\"},\n        \"themes\":        {\"cat\":\"important\",\"safe_to_stop\":True,\n                          \"desc\":\"Windows visual theme. Band karne se plain grey Windows dikhegi.\",\n                          \"display\":\"Themes\"},\n        \"winmgmt\":       {\"cat\":\"important\",\"safe_to_stop\":False,\n                          \"desc\":\"WMI \u2014 Hardware info, monitoring tools isi se kaam karte hain.\",\n                          \"display\":\"Windows Management Instrumentation\"},\n        \"schedule\":      {\"cat\":\"important\",\"safe_to_stop\":False,\n                          \"desc\":\"Task Scheduler. Band karne se system tasks nahi chalenge.\",\n                          \"display\":\"Task Scheduler\"},\n        \"seclogon\":      {\"cat\":\"important\",\"safe_to_stop\":True,\n                          \"desc\":\"Secondary Logon. Multiple user accounts ke liye. Home PC pe safe to stop.\",\n                          \"display\":\"Secondary Logon\"},\n        \"usermanager\":   {\"cat\":\"important\",\"safe_to_stop\":False,\n                          \"desc\":\"User account manager. Band karne se login problems.\",\n                          \"display\":\"User Manager\"},\n        # \u2500\u2500 OPTIONAL \u2014 safely disable kar sakte ho \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        \"sysmain\":       {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Superfetch/Prefetch \u2014 RAM mein programs preload karta hai. SSD pe disable karo \u2014 speed badhegi.\",\n                          \"display\":\"SysMain (Superfetch)\"},\n        \"wsearch\":       {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Windows Search Indexing \u2014 continuously disk scan karta hai. Agar search use nahi karte to disable karo.\",\n                          \"display\":\"Windows Search\"},\n        \"diagtrack\":     {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Microsoft Telemetry \u2014 aapki usage data Microsoft ko bhejta hai. Safely disable kar sakte ho.\",\n                          \"display\":\"Connected User Experiences and Telemetry\"},\n        \"dmwappushservice\":{\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"WAP Push Message Routing \u2014 zyada tar unnecessary hai. Safe to disable.\",\n                          \"display\":\"Device Management WAP Push message Routing Service\"},\n        \"xblAuthmanager\":{\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Xbox Live Authentication \u2014 gaming nahi karte to bilkul disable karo.\",\n                          \"display\":\"Xbox Live Auth Manager\"},\n        \"xboxnetapitsvc\":{\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Xbox networking \u2014 Xbox use nahi karte to disable karo.\",\n                          \"display\":\"Xbox Live Networking Service\"},\n        \"xblgamesave\":   {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Xbox game save sync \u2014 Xbox nahi use karte to disable.\",\n                          \"display\":\"Xbox Live Game Save\"},\n        \"retaildemo\":    {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Retail Demo Mode \u2014 shop display ke liye hai. Home PC pe bilkul disable karo.\",\n                          \"display\":\"Retail Demo Service\"},\n        \"mapsbrok\":      {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Windows Maps offline download. Maps use nahi karte to disable.\",\n                          \"display\":\"Downloaded Maps Manager\"},\n        \"fax\":           {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Fax service \u2014 2024 mein fax kaun karta hai? Disable karo.\",\n                          \"display\":\"Fax\"},\n        \"remoteregistry\":{\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Remote Registry access \u2014 Security risk! Disable karo immediately.\",\n                          \"display\":\"Remote Registry\"},\n        \"remoteaccess\":  {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Remote Access \u2014 agar koi remotely connect nahi karta to disable karo.\",\n                          \"display\":\"Routing and Remote Access\"},\n        \"wersvc\":        {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Windows Error Reporting \u2014 crash reports Microsoft ko bhejta hai. Disable kar sakte ho.\",\n                          \"display\":\"Windows Error Reporting Service\"},\n        \"printnotify\":   {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Printer notifications \u2014 printer nahi hai to disable karo.\",\n                          \"display\":\"Printer Extensions and Notifications\"},\n        \"sharedaccess\":  {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Internet Connection Sharing \u2014 router hai to ye zaruri nahi. Disable karo.\",\n                          \"display\":\"Internet Connection Sharing (ICS)\"},\n        \"sensrsvc\":      {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Sensor Service \u2014 laptop sensors (gyroscope etc). Desktop pe disable karo.\",\n                          \"display\":\"Sensor Service\"},\n        \"wbiosrvc\":      {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Windows Biometric (fingerprint/face ID). Use nahi karte to disable.\",\n                          \"display\":\"Windows Biometric Service\"},\n        \"tabletinputservice\":{\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Touch/Pen Input. Touchscreen/stylus nahi hai to disable karo.\",\n                          \"display\":\"Touch Keyboard and Handwriting Panel Service\"},\n        \"stisvc\":        {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Scanner/Camera service. Use nahi karte to disable.\",\n                          \"display\":\"Windows Image Acquisition (WIA)\"},\n    }\n\n    # Tag colors per category\n    SVC_TAG_COLORS = {\n        \"critical\":   \"#FF4444\",   # Lal \u2014 danger\n        \"important\":  \"#FF9800\",   # Orange \u2014 warning\n        \"optional\":   \"#4CAF50\",   # Green \u2014 safe to touch\n        \"thirdparty\": \"#CE93D8\",   # Purple \u2014 third party\n        \"highcpu\":    \"#FF6B35\",   # Deep orange \u2014 high CPU\n        \"highmem\":    \"#FFD700\",   # Gold \u2014 high RAM\n    }\n\n    def _build_services(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\u2699\ufe0f Smart Services Manager\",\n                             \"Color-coded \u2014 Critical / Important / Optional / Third-Party\")\n\n        self._action_card_grid(frame, [\n            (\"\ud83d\udd0d\", \"Scan All Services\",    \"Saari services scan karo\",            C[\"btn_info\"],   self._scan_impacting_services),\n            (\"\u26d4\", \"Stop Selected\",        \"Selected services band karo\",          C[\"btn_danger\"], lambda: self._svc_action_safe(\"stop\")),\n            (\"\u2705\", \"Start Selected\",       \"Selected services shuru karo\",         C[\"btn\"],        lambda: self._with_confirm(\"Start Services\",\"Start selected services?\", self._start_services)),\n            (\"\ud83d\udeab\", \"Disable Selected\",     \"Selected services disable karo\",       C[\"btn_warn\"],   lambda: self._svc_action_safe(\"disable\")),\n            (\"\u26a1\", \"Disable All Optional\", \"Saari optional services ek click mein\",C[\"btn_chip\"],   self._disable_all_optional),\n            (\"\ud83d\udcbb\", \"Pack: SSD Laptop\",     \"SSD laptop ke liye best preset\",       C[\"btn_chip\"],   lambda: self._svc_apply_pack(\"ssd_laptop\")),\n            (\"\ud83d\udda5\",  \"Pack: HDD Desktop\",   \"HDD desktop ke liye best preset\",      C[\"btn_chip\"],   lambda: self._svc_apply_pack(\"hdd_desktop\")),\n            (\"\u21a9\",  \"Restore Snapshot\",    \"Pehle wali state wapas lao\",           C[\"btn_info\"],   self._svc_restore_snapshot),\n        ], cols=4)\n\n        # \u2500\u2500 Legend \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        leg = tk.Frame(frame, bg=C[\"bg\"])\n        leg.pack(fill=\"x\", padx=16, pady=(4,0))\n        legends = [\n            (\"\ud83d\udd34 Critical \u2014 Kabhi band mat karo\",     \"#FF4444\"),\n            (\"\ud83d\udfe0 Important \u2014 Soch ke band karo\",      \"#FF9800\"),\n            (\"\ud83d\udfe2 Optional \u2014 Safely disable kar sakte\", \"#4CAF50\"),\n            (\"\ud83d\udfe3 Third-Party Software\",                \"#CE93D8\"),\n            (\"\ud83d\udfe1 High RAM Use\",                        \"#FFD700\"),\n            (\"\ud83d\udd36 High CPU Use\",                        \"#FF6B35\"),\n        ]\n        for i, (txt, col) in enumerate(legends):\n            tk.Label(leg, text=txt, font=FONTS[\"small\"], fg=col,\n                     bg=C[\"bg\"]).grid(row=i//3, column=i%3, sticky=\"w\", padx=12, pady=1)\n\n        # \u2500\u2500 Filter bar \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        fbar = tk.Frame(frame, bg=C[\"bg\"])\n        fbar.pack(fill=\"x\", padx=16, pady=(4,2))\n        tk.Label(fbar, text=\"Filter:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"]).pack(side=\"left\")\n        self.svc_search = tk.Entry(fbar, width=22, font=FONTS[\"body\"],\n                                   bg=C[\"card\"], fg=C[\"text\"],\n                                   insertbackground=C[\"text\"], relief=\"flat\", bd=4)\n        self.svc_search.pack(side=\"left\", padx=6)\n        self.svc_search.bind(\"\", self._filter_services)\n        for lbl, val in [(\"All\",\"all\"),(\"\ud83d\udd34 Critical\",\"critical\"),\n                         (\"\ud83d\udfe0 Important\",\"important\"),(\"\ud83d\udfe2 Optional\",\"optional\"),\n                         (\"\ud83d\udfe3 3rd Party\",\"thirdparty\"),(\"\ud83d\udfe1 High RAM\",\"highmem\"),\n                         (\"\ud83d\udd36 High CPU\",\"highcpu\")]:\n            tk.Button(fbar, text=lbl, font=FONTS[\"small\"],\n                      bg=C[\"card\"], fg=C[\"text\"], bd=0, padx=8, pady=3,\n                      cursor=\"hand2\",\n                      command=lambda v=val: self._filter_by_cat(v)).pack(side=\"left\", padx=2)\n\n        self.svc_count_lbl = tk.Label(fbar, text=\"\", font=FONTS[\"small\"],\n                                      fg=C[\"accent\"], bg=C[\"bg\"])\n        self.svc_count_lbl.pack(side=\"right\", padx=8)\n\n        metric_bar = tk.Frame(frame, bg=C[\"bg\"])\n        metric_bar.pack(fill=\"x\", padx=16, pady=(4,4))\n        self.svc_scan_status_lbl = tk.Label(metric_bar, text=\"Ready to scan services\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"])\n        self.svc_scan_status_lbl.pack(side=\"left\")\n        self.svc_risk_score_var = tk.StringVar(value=\"--\")\n        self.svc_potential_free_var = tk.StringVar(value=\"--\")\n        for label, var in [(\"Risk Score\", self.svc_risk_score_var), (\"Potential RAM\", self.svc_potential_free_var)]:\n            card = tk.Frame(metric_bar, bg=C[\"card\"], padx=8, pady=6)\n            card.pack(side=\"right\", padx=4)\n            tk.Label(card, text=label, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\")\n            tk.Label(card, textvariable=var, font=(\"Segoe UI\", 13, \"bold\"), fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\")\n\n        # \u2500\u2500 Paned layout \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        paned = tk.Frame(frame, bg=C[\"bg\"])\n        paned.pack(fill=\"both\", expand=True, padx=16, pady=(4,8))\n        paned.columnconfigure(0, weight=3)\n        paned.columnconfigure(1, weight=2)\n        paned.rowconfigure(0, weight=1)\n\n        # Left \u2014 service list\n        left = tk.Frame(paned, bg=C[\"card\"])\n        left.grid(row=0, column=0, sticky=\"nsew\", padx=(0,6))\n        cols = (\"Cat\",\"Name\",\"Display Name\",\"Status\",\"CPU%\",\"RAM MB\",\"Safe Stop?\")\n        self.svc_tree = ttk.Treeview(left, columns=cols, show=\"headings\",\n                                     height=22, style=\"Custom.Treeview\",\n                                     selectmode=\"extended\")\n        widths = [28, 160, 210, 75, 55, 70, 80]\n        for col, w in zip(cols, widths):\n            self.svc_tree.heading(col, text=col,\n                                  command=lambda c=col: self._sort_svc(c))\n            self.svc_tree.column(col, width=w,\n                                 anchor=\"center\" if col in (\"Cat\",\"Status\",\"CPU%\",\"RAM MB\",\"Safe Stop?\") else \"w\")\n\n        # Color tags\n        for tag, color in self.SVC_TAG_COLORS.items():\n            self.svc_tree.tag_configure(tag, foreground=color)\n        self.svc_tree.tag_configure(\"highcpu_bg\", background=\"#2A1500\")\n        self.svc_tree.tag_configure(\"highmem_bg\", background=\"#1A1A00\")\n\n        vsb = ttk.Scrollbar(left, orient=\"vertical\", command=self.svc_tree.yview)\n        self.svc_tree.configure(yscrollcommand=vsb.set)\n        self.svc_tree.pack(side=\"left\", fill=\"both\", expand=True, padx=(4,0), pady=4)\n        vsb.pack(side=\"right\", fill=\"y\", pady=4)\n        self.svc_tree.bind(\"&lt;&gt;\", self._on_svc_select)\n\n        # Right \u2014 detail panel\n        right = tk.Frame(paned, bg=C[\"card\"])\n        right.grid(row=0, column=1, sticky=\"nsew\")\n        right.rowconfigure(1, weight=1)\n        right.columnconfigure(0, weight=1)\n\n        tk.Label(right, text=\"  \ud83d\udccb Service Detail &amp; Risk Info\",\n                 font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(\n                 anchor=\"w\", pady=(8,4), padx=8)\n\n        self.svc_detail = scrolledtext.ScrolledText(\n            right, font=(\"Consolas\", 9), bg=\"#0D1117\", fg=C[\"text\"],\n            height=16, bd=0, relief=\"flat\", state=\"disabled\", wrap=\"word\")\n        self.svc_detail.pack(fill=\"both\", expand=True, padx=8, pady=(0,6))\n        self.svc_action_log = self.svc_detail\n\n        # Risk summary cards at bottom of right panel\n        rsum = tk.Frame(right, bg=C[\"card\"])\n        rsum.pack(fill=\"x\", padx=8, pady=(0,8))\n        self.svc_summary_vars = {}\n        for i, (k, lbl, col) in enumerate([\n            (\"critical\",   \"Critical\",    \"#FF4444\"),\n            (\"important\",  \"Important\",   \"#FF9800\"),\n            (\"optional\",   \"Optional\",    \"#4CAF50\"),\n            (\"thirdparty\", \"3rd Party\",   \"#CE93D8\"),\n        ]):\n            rsum.columnconfigure(i, weight=1)\n            card = tk.Frame(rsum, bg=C[\"bg\"], padx=6, pady=6)\n            card.grid(row=0, column=i, padx=3, sticky=\"ew\")\n            tk.Label(card, text=lbl, font=FONTS[\"small\"],\n                     fg=col, bg=C[\"bg\"]).pack(anchor=\"w\")\n            v = tk.StringVar(value=\"--\")\n            self.svc_summary_vars[k] = v\n            tk.Label(card, textvariable=v, font=(\"Segoe UI\",15,\"bold\"),\n                     fg=col, bg=C[\"bg\"]).pack(anchor=\"w\")\n\n        # Internal state\n        self._svc_all_rows = []   # (values_tuple, tags_tuple, meta_dict)\n        self._svc_cur_filter_cat = \"all\"\n        self._svc_sort_col = \"\"\n        self._svc_sort_rev = False\n        return frame\n\n    def _with_confirm(self, title, msg, action):\n        if messagebox.askyesno(title, msg):\n            action()\n\n    # \u2500\u2500 Service scan \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _scan_impacting_services(self):\n        self._set_status(\"Queued: Scanning services...\", C[\"accent4\"])\n        self._submit_ram_service_job(\"service_scan\", self._do_scan_services)\n\n    def _do_scan_services(self):\n        try:\n            self.after(0, lambda: [self.svc_tree.delete(i) for i in self.svc_tree.get_children()])\n        except Exception:\n            pass\n\n        pid_cpu, pid_mem = {}, {}\n        try:\n            for p in psutil.process_iter(['pid','cpu_percent','memory_info']):\n                try:\n                    pid_cpu[p.info['pid']] = p.info['cpu_percent'] or 0\n                    mem = p.info.get('memory_info')\n                    pid_mem[p.info['pid']] = round(mem.rss/(1024**2),1) if mem else 0\n                except Exception:\n                    pass\n        except Exception:\n            pass\n\n        THIRD_PARTY_PATHS = {\n            \"nvidia\",\"amd\",\"intel graphics\",\"realtek\",\"qualcomm\",\"broadcom\",\n            \"avast\",\"avg\",\"kaspersky\",\"mcafee\",\"norton\",\"malwarebytes\",\"bitdefender\",\n            \"adobe\",\"acrobat\",\"google\",\"chrome\",\"dropbox\",\"onedrive\",\"teams\",\n            \"skype\",\"zoom\",\"spotify\",\"discord\",\"steam\",\"epic games\",\"origin\",\n            \"vmware\",\"virtualbox\",\"ccleaner\",\"iobit\",\"razer\",\"corsair\",\"logitech\",\n            \"hp\",\"dell\",\"lenovo\",\"asus\",\"acer\",\"samsung\",\"brother\",\"canon\",\"epson\",\n        }\n\n        try:\n            services = list(psutil.win_service_iter())\n        except Exception:\n            services = []\n        total_services = max(1, len(services))\n\n        rows = []\n        cat_counts = {\"critical\":0,\"important\":0,\"optional\":0,\"thirdparty\":0}\n        batch = {\n            \"phase\":\"service_scan\",\n            \"status_text\":\"Scanning services...\",\n            \"progress_pct\":0,\n            \"services_scanned\":0,\n            \"high_cpu\":0,\n            \"high_mem\":0,\n            \"critical\":0,\n            \"important\":0,\n            \"optional\":0,\n            \"thirdparty\":0,\n            \"estimated_ram_mb\":0,\n            \"risk_score\":0,\n        }\n        last_dispatch = time.time()\n\n        def dispatch_metrics():\n            try:\n                points = (batch[\"critical\"] * 6 + batch[\"important\"] * 4 + batch[\"thirdparty\"] * 2 + batch[\"high_cpu\"] * 3 + batch[\"high_mem\"] * 3)\n                max_points = max(1, total_services * 6)\n                batch[\"risk_score\"] = min(100, int((points / max_points) * 100))\n                batch[\"progress_pct\"] = min(100.0, (batch[\"services_scanned\"] / total_services) * 100.0)\n                batch[\"status_text\"] = f\"Scanning services... {batch['services_scanned']}/{total_services}\"\n                self._ram_service_metrics_queue.put(batch.copy())\n            except Exception:\n                pass\n\n        for svc in services:\n            try:\n                info = svc.as_dict()\n                name = info.get('name', '')\n                dname = info.get('display_name', '')\n                pid = info.get('pid', 0) or 0\n                cpu_p = pid_cpu.get(pid, 0)\n                mem_mb = pid_mem.get(pid, 0)\n                status = info.get('status', '')\n                start = info.get('start_type', '')\n\n                name_lo = name.lower()\n                in_db = name_lo in self.SVC_DB\n                high_cpu = cpu_p &gt; 10\n                high_mem = mem_mb &gt; 150\n\n                if not in_db and not high_cpu and not high_mem:\n                    continue\n\n                if in_db:\n                    meta = self.SVC_DB[name_lo]\n                    cat = meta[\"cat\"]\n                    safe = meta[\"safe_to_stop\"]\n                    desc = meta[\"desc\"]\n                else:\n                    dname_lo = dname.lower()\n                    is_third = any(tp in dname_lo for tp in THIRD_PARTY_PATHS)\n                    if is_third:\n                        cat = \"thirdparty\"\n                        safe = True\n                        desc = (f\"Third-party service: '{dname}'.\\n\"\n                                \"Yeh kisi installed software ki service hai.\\n\"\n                                \"Agar woh software uninstall kar diya hai to safely disable kar sakte ho.\\n\"\n                                \"Agar software use karte ho to band mat karo.\")\n                    else:\n                        cat = \"optional\"\n                        safe = True\n                        desc = (\"Yeh service hamare database mein nahi hai.\\n\"\n                                \"Stop karne se pehle naam search karo Google pe.\\n\"\n                                \"High resource use ho raha hai \u2014 monitor karein.\")\n\n                tags = [cat]\n                if high_cpu:\n                    tags.append(\"highcpu\")\n                if high_mem:\n                    tags.append(\"highmem\")\n\n                safe_txt = \"\u2705 Haan\" if safe else \"\u274c Nahi\"\n                cat_icon = {\"critical\":\"\ud83d\udd34\",\"important\":\"\ud83d\udfe0\",\n                            \"optional\":\"\ud83d\udfe2\",\"thirdparty\":\"\ud83d\udfe3\"}.get(cat, \"\u26aa\")\n\n                row = (cat_icon, name, dname[:42], status,\n                       f\"{cpu_p:.1f}\", f\"{mem_mb:.1f}\", safe_txt)\n                meta_full = {\n                    \"name\": name, \"dname\": dname, \"cat\": cat,\n                    \"safe\": safe, \"desc\": desc, \"cpu\": cpu_p,\n                    \"mem\": mem_mb, \"status\": status, \"start\": start, \"pid\": pid\n                }\n                rows.append((row, tuple(tags), meta_full))\n                if cat in cat_counts:\n                    cat_counts[cat] += 1\n                batch[\"services_scanned\"] += 1\n                batch[\"high_cpu\"] += 1 if high_cpu else 0\n                batch[\"high_mem\"] += 1 if high_mem else 0\n                batch[cat] += 1\n                batch[\"estimated_ram_mb\"] += mem_mb if high_mem else 0\n            except Exception:\n                pass\n            if time.time() - last_dispatch &gt;= 0.12:\n                dispatch_metrics()\n                last_dispatch = time.time()\n\n        dispatch_metrics()\n        batch[\"status_text\"] = f\"Service scan complete \u2014 {len(rows)} relevant services\"\n        batch[\"progress_pct\"] = 100.0\n        self._ram_service_metrics_queue.put(batch.copy())\n\n        self._svc_all_rows = rows\n\n        def insert():\n            self._render_svc_rows(rows)\n            for k, v in cat_counts.items():\n                self.svc_summary_vars[k].set(str(v))\n            self._set_status(\n                f\"Scan done \u2014 {len(rows)} services | \"\n                f\"\ud83d\udd34{cat_counts['critical']} Critical | \"\n                f\"\ud83d\udfe0{cat_counts['important']} Important | \"\n                f\"\ud83d\udfe2{cat_counts['optional']} Optional | \"\n                f\"\ud83d\udfe3{cat_counts['thirdparty']} 3rd-Party\",\n                C[\"success\"])\n        self.after(0, insert)\n\n    def _render_svc_rows(self, rows):\n        for i in self.svc_tree.get_children():\n            self.svc_tree.delete(i)\n        for row, tags, _ in rows:\n            self.svc_tree.insert(\"\", \"end\", values=row, tags=tags)\n        self.svc_count_lbl.config(text=f\"{len(rows)} services\")\n\n    # \u2500\u2500 Filter / Sort \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _filter_services(self, event=None):\n        text = self.svc_search.get().lower()\n        cat  = self._svc_cur_filter_cat\n        filtered = [\n            r for r in self._svc_all_rows\n            if (cat == \"all\" or cat in r[1])\n            and (not text or text in r[2][\"name\"].lower()\n                 or text in r[2][\"dname\"].lower())\n        ]\n        self._render_svc_rows(filtered)\n\n    def _filter_by_cat(self, cat):\n        self._svc_cur_filter_cat = cat\n        self._filter_services()\n\n    def _sort_svc(self, col):\n        col_map = {\"Cat\":0,\"Name\":1,\"Display Name\":2,\"Status\":3,\n                   \"CPU%\":4,\"RAM MB\":5,\"Safe Stop?\":6}\n        idx = col_map.get(col, 1)\n        if self._svc_sort_col == col:\n            self._svc_sort_rev = not self._svc_sort_rev\n        else:\n            self._svc_sort_col = col\n            self._svc_sort_rev = False\n        try:\n            self._svc_all_rows.sort(\n                key=lambda r: float(r[0][idx]) if r[0][idx].replace('.','').isdigit()\n                              else r[0][idx],\n                reverse=self._svc_sort_rev)\n        except: pass\n        self._filter_services()\n\n    # \u2500\u2500 Selection detail panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _on_svc_select(self, event=None):\n        sel = self.svc_tree.selection()\n        if not sel:\n            return\n        iid = sel[0]\n        idx = self.svc_tree.index(iid)\n        # Find matching meta from filtered list\n        visible = [r for r in self._svc_all_rows\n                   if self._svc_cur_filter_cat == \"all\"\n                   or self._svc_cur_filter_cat in r[1]]\n        search_txt = self.svc_search.get().lower()\n        if search_txt:\n            visible = [r for r in visible\n                       if search_txt in r[2][\"name\"].lower()\n                       or search_txt in r[2][\"dname\"].lower()]\n        if idx &gt;= len(visible):\n            return\n        meta = visible[idx][2]\n\n        cat     = meta[\"cat\"]\n        safe    = meta[\"safe\"]\n        desc    = meta[\"desc\"]\n        cpu     = meta[\"cpu\"]\n        mem     = meta[\"mem\"]\n        status  = meta[\"status\"]\n        name    = meta[\"name\"]\n        dname   = meta[\"dname\"]\n\n        cat_label = {\n            \"critical\":   \"\ud83d\udd34 CRITICAL \u2014 Kabhi band mat karo\",\n            \"important\":  \"\ud83d\udfe0 IMPORTANT \u2014 Soch ke band karo\",\n            \"optional\":   \"\ud83d\udfe2 OPTIONAL \u2014 Safely disable kar sakte ho\",\n            \"thirdparty\": \"\ud83d\udfe3 THIRD-PARTY \u2014 Software ki service\",\n        }.get(cat, \"\u26aa Unknown\")\n\n        stop_warning = {\n            \"critical\": (\n                \"\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\\n\"\n                \"\u2551  \u26d4 DANGER \u2014 IS SERVICE KO BAND MAT KARO \u2551\\n\"\n                \"\u255a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255d\\n\"\n                \"Yeh Windows ka core component hai.\\n\"\n                \"Band karne se BLUE SCREEN / CRASH / FREEZE ho sakta hai!\\n\"\n            ),\n            \"important\": (\n                \"\u26a0\ufe0f  SAWDHAN \u2014 Band karne se Windows ka koi feature\\n\"\n                \"   kaam karna band kar sakta hai. Pehle samjho\\n\"\n                \"   kya hoga, phir decide karo.\\n\"\n            ),\n            \"optional\": (\n                \"\u2705 SAFE \u2014 Yeh service band kar sakte ho.\\n\"\n                \"   Performance behtar hogi. System harm nahi hoga.\\n\"\n            ),\n            \"thirdparty\": (\n                \"\ud83d\udfe3 THIRD-PARTY \u2014 Kisi installed software ki service hai.\\n\"\n                \"   Agar woh software use karte ho: BAND MAT KARO.\\n\"\n                \"   Agar woh software uninstall ho gaya hai: Safely disable karo.\\n\"\n            ),\n        }.get(cat, \"\")\n\n        lines = [\n            f\"Service Name  : {name}\",\n            f\"Display Name  : {dname}\",\n            f\"Category      : {cat_label}\",\n            f\"Current Status: {status}\",\n            f\"CPU Usage     : {cpu:.1f}%{'  \u26a0 HIGH!' if cpu&gt;10 else ''}\",\n            f\"RAM Usage     : {mem:.1f} MB{'  \u26a0 HIGH!' if mem&gt;150 else ''}\",\n            f\"Safe to Stop? : {'\u2705 Haan \u2014 band kar sakte ho' if safe else '\u274c Nahi \u2014 band karna dangerous hai'}\",\n            \"\",\n            \"\u2500\"*50,\n            \"\",\n            \"\ud83d\udcd6 DESCRIPTION:\",\n            desc,\n            \"\",\n            \"\u2500\"*50,\n            \"\",\n            \"\u26a0\ufe0f  STOP/DISABLE KARNE SE KYA HOGA:\",\n            stop_warning,\n        ]\n        if cpu &gt; 10:\n            lines += [\"\",\"\ud83d\udd36 HIGH CPU ALERT:\",\n                      f\"   Yeh service {cpu:.1f}% CPU le rahi hai.\",\n                      \"   Agar zaroori nahi to stop karo.\"]\n        if mem &gt; 150:\n            lines += [\"\",\"\ud83d\udfe1 HIGH RAM ALERT:\",\n                      f\"   Yeh service {mem:.1f} MB RAM use kar rahi hai.\",\n                      \"   Stop karne se RAM free hogi.\"]\n\n        self.svc_detail.config(state=\"normal\")\n        self.svc_detail.delete(\"1.0\",\"end\")\n        # Color different parts\n        self.svc_detail.tag_configure(\"red\",    foreground=\"#FF4444\")\n        self.svc_detail.tag_configure(\"orange\", foreground=\"#FF9800\")\n        self.svc_detail.tag_configure(\"green\",  foreground=\"#4CAF50\")\n        self.svc_detail.tag_configure(\"purple\", foreground=\"#CE93D8\")\n        self.svc_detail.tag_configure(\"gold\",   foreground=\"#FFD700\")\n        self.svc_detail.tag_configure(\"dim\",    foreground=\"#A0B0C8\")\n        self.svc_detail.tag_configure(\"bold\",   foreground=C[\"text\"])\n\n        for line in lines:\n            color_tag = \"bold\"\n            if \"DANGER\" in line or \"\u274c\" in line:     color_tag = \"red\"\n            elif \"SAWDHAN\" in line or \"\u26a0\ufe0f\" in line:  color_tag = \"orange\"\n            elif \"SAFE\" in line or \"\u2705\" in line:     color_tag = \"green\"\n            elif \"THIRD-PARTY\" in line or \"\ud83d\udfe3\" in line: color_tag = \"purple\"\n            elif \"HIGH\" in line and \"ALERT\" in line: color_tag = \"gold\"\n            elif line.startswith(\"\u2500\"):               color_tag = \"dim\"\n            self.svc_detail.insert(\"end\", line+\"\\n\", color_tag)\n        self.svc_detail.config(state=\"disabled\")\n\n    # \u2500\u2500 Safe stop/disable with category warning \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _svc_action_safe(self, action):\n        sel = self.svc_tree.selection()\n        if not sel:\n            messagebox.showinfo(\"No Selection\", \"Pehle ek service select karo.\")\n            return\n        # Check all selected for critical/important\n        block = []\n        warn  = []\n        names = []\n        visible = self._get_visible_svc_rows()\n        for iid in sel:\n            idx = self.svc_tree.index(iid)\n            if idx &gt;= len(visible): continue\n            meta = visible[idx][2]\n            cat  = meta[\"cat\"]\n            name = meta[\"name\"]\n            safe = meta[\"safe\"]\n            names.append(name)\n            if not safe:\n                block.append(f\"  \ud83d\udd34 {name} ({meta['dname']}) \u2014 CRITICAL, band NAHI karna chahiye!\")\n            elif cat == \"important\":\n                warn.append(f\"  \ud83d\udfe0 {name} ({meta['dname']}) \u2014 Important service, dhyan se!\")\n\n        if block:\n            messagebox.showerror(\"\u26d4 KHATARNAK SERVICE SELECTED!\",\n                \"Neeche di gayi services CRITICAL hain.\\n\"\n                \"Inhe band karne se system crash ho sakta hai!\\n\\n\"\n                + \"\\n\".join(block) +\n                \"\\n\\nIn services ko DESELECT karo aur dubara try karo.\")\n            return\n\n        confirm_msg = f\"{'Disable' if action=='disable' else 'Stop'} karne se ye services band ho jaayengi:\\n\\n\"\n        confirm_msg += \"\\n\".join(f\"  \u2022 {n}\" for n in names)\n        if warn:\n            confirm_msg += \"\\n\\n\u26a0\ufe0f SAWDHAN \u2014 Ye services Important hain:\\n\" + \"\\n\".join(warn)\n        # Dependency awareness: show dependents (services that rely on this one)\n        dep_warn = []\n        dep_block = []\n        for n in names:\n            deps = self._service_dependents(n)\n            if not deps:\n                continue\n            running = []\n            for dn in deps[:12]:\n                st, _ = self._service_state(dn)\n                if st and st != \"STOPPED\":\n                    running.append(dn)\n            if action == \"disable\":\n                dep_warn.append(f\"  \u26a0 {n} ke dependents: {', '.join(deps[:8])}\" + (\"...\" if len(deps) &gt; 8 else \"\"))\n            else:\n                if running:\n                    dep_block.append(f\"  \u26d4 {n} ke running dependents: {', '.join(running[:8])}\" + (\"...\" if len(running) &gt; 8 else \"\"))\n                else:\n                    dep_warn.append(f\"  \u26a0 {n} ke dependents: {', '.join(deps[:8])}\" + (\"...\" if len(deps) &gt; 8 else \"\"))\n        if dep_block:\n            messagebox.showerror(\n                \"\u26d4 Dependent Services Running\",\n                \"Selected service(s) par kuch services dependent hain aur abhi RUNNING hain.\\n\"\n                \"Pehle dependents stop karo (ya unko deselect karo), phir try karo.\\n\\n\"\n                + \"\\n\".join(dep_block)\n            )\n            return\n        if dep_warn:\n            confirm_msg += \"\\n\\n\ud83d\udd17 DEPENDENCY WARNING:\\n\" + \"\\n\".join(dep_warn)\n        confirm_msg += f\"\\n\\n{'Disable karne se ye restart pe nahi chalegi.' if action=='disable' else 'Stop karne se ye tab tak nahi chalegi jab tak restart nahi karte.'}\\n\\nAage badhein?\"\n\n        if not messagebox.askyesno(\n                \"\u26a0\ufe0f Confirm \u2014 Service \" + (\"Disable\" if action==\"disable\" else \"Stop\"),\n                confirm_msg):\n            return\n\n        results = []\n        if action == \"disable\":\n            self._svc_save_start_mode_snapshot(names)\n        for name in names:\n            if action == \"stop\":\n                results.append(self._service_stop_checked(name))\n            else:\n                results.append(self._service_config_checked(name, \"disabled\"))\n                results.append(self._service_stop_checked(name))\n        summary = self._action_summary(\"Service \" + (\"Disable\" if action == \"disable\" else \"Stop\"), results)\n        messagebox.showinfo(\"Already Done\" if summary[\"already_done\"] else \"Done\", summary[\"message\"])\n        self._scan_impacting_services()\n\n    def _get_visible_svc_rows(self):\n        cat = self._svc_cur_filter_cat\n        txt = self.svc_search.get().lower() if hasattr(self,'svc_search') else \"\"\n        rows = self._svc_all_rows\n        if cat != \"all\":\n            rows = [r for r in rows if cat in r[1]]\n        if txt:\n            rows = [r for r in rows if txt in r[2][\"name\"].lower()\n                    or txt in r[2][\"dname\"].lower()]\n        return rows\n\n    def _disable_all_optional(self):\n        optional = [r for r in self._svc_all_rows if \"optional\" in r[1]]\n        if not optional:\n            messagebox.showinfo(\"Koi Service Nahi\",\n                \"Pehle 'Scan All Services' karo.\")\n            return\n        names = [r[2][\"name\"] for r in optional]\n        msg = (f\"Neeche di gayi {len(names)} Optional services disable ho jaayengi:\\n\\n\"\n               + \"\\n\".join(f\"  \ud83d\udfe2 {n}\" for n in names[:15])\n               + (f\"\\n  ...aur {len(names)-15} aur\" if len(names)&gt;15 else \"\")\n               + \"\\n\\nYe sab safely disable ho sakti hain.\\nKya aage badhein?\")\n        if messagebox.askyesno(\"\u26a1 Disable All Optional\", msg):\n            results = []\n            self._svc_save_start_mode_snapshot(names)\n            for name in names:\n                results.append(self._service_config_checked(name, \"disabled\"))\n                results.append(self._service_stop_checked(name))\n            summary = self._action_summary(\"Optional Services\", results)\n            messagebox.showinfo(\"Already Done\" if summary[\"already_done\"] else \"Done!\", summary[\"message\"] + \"\\nRestart karo best results ke liye.\")\n            self._scan_impacting_services()\n\n    def _stop_services(self):\n        results = []\n        for iid in self.svc_tree.selection():\n            name = self.svc_tree.item(iid, \"values\")[1]\n            results.append(self._service_stop_checked(name))\n        if results:\n            summary = self._action_summary(\"Service Stop\", results)\n            messagebox.showinfo(\"Already Done\" if summary[\"already_done\"] else \"Done\", summary[\"message\"])\n        self._scan_impacting_services()\n\n    def _start_services(self):\n        results = []\n        for iid in self.svc_tree.selection():\n            name = self.svc_tree.item(iid, \"values\")[1]\n            results.append(self._service_start_checked(name))\n        if results:\n            summary = self._action_summary(\"Service Start\", results)\n            messagebox.showinfo(\"Already Done\" if summary[\"already_done\"] else \"Done\", summary[\"message\"])\n        self._scan_impacting_services()\n\n    def _disable_services(self):\n        results = []\n        for iid in self.svc_tree.selection():\n            name = self.svc_tree.item(iid, \"values\")[1]\n            results.append(self._service_config_checked(name, \"disabled\"))\n        if results:\n            summary = self._action_summary(\"Service Disable\", results)\n            messagebox.showinfo(\"Already Done\" if summary[\"already_done\"] else \"Done\", summary[\"message\"])\n        self._scan_impacting_services()\n\n    # ---------- RAM OPTIMIZER (with Before/After) ----------\n    def _build_memory(self, parent):\n        root = tk.Frame(parent, bg=C[\"bg\"])\n        canvas = tk.Canvas(root, bg=C[\"bg\"], highlightthickness=0)\n        scrollbar = ttk.Scrollbar(root, orient=\"vertical\", command=canvas.yview)\n        inner = tk.Frame(canvas, bg=C[\"bg\"])\n        inner.bind(\"\", lambda e: canvas.configure(scrollregion=canvas.bbox(\"all\")))\n        inner_window = canvas.create_window((0, 0), window=inner, anchor=\"nw\")\n        canvas.configure(yscrollcommand=scrollbar.set)\n        scrollbar.pack(side=\"right\", fill=\"y\")\n        canvas.pack(side=\"left\", fill=\"both\", expand=True)\n\n        def _resize_inner(event):\n            try:\n                canvas.itemconfigure(inner_window, width=event.width)\n                canvas.configure(scrollregion=canvas.bbox(\"all\"))\n            except Exception:\n                pass\n\n        canvas.bind(\"\", _resize_inner)\n        self._bind_scoped_mousewheel(inner, canvas)\n\n        frame = inner\n        self._section_header(frame, \"\ud83e\udde0 RAM Optimizer\", \"Free up RAM memory - WORKING\")\n        stats = tk.Frame(frame, bg=C[\"bg\"])\n        stats.pack(fill=\"x\", padx=16, pady=8)\n        self.ram_cards = {}\n        for i, (k, lbl, color) in enumerate([(\"total\",\"Total RAM\",C[\"text\"]), (\"used\",\"Used RAM\",C[\"error\"]), (\"free\",\"Free RAM\",C[\"success\"]), (\"cached\",\"Cache\",C[\"accent4\"])]):\n            card = self._stat_card(stats, lbl, \"--\", color)\n            card.grid(row=0, column=i, padx=6, sticky=\"ew\")\n            stats.columnconfigure(i, weight=1)\n            self.ram_cards[k] = card\n        monitor = tk.Frame(frame, bg=C[\"bg\"])\n        monitor.pack(fill=\"x\", padx=16, pady=(0,8))\n        self.ram_operation_progress_var = tk.DoubleVar(value=0.0)\n        self.ram_operation_progress_bar = ttk.Progressbar(monitor,\n                                                         variable=self.ram_operation_progress_var,\n                                                         maximum=100, mode=\"determinate\")\n        self.ram_operation_progress_bar.pack(fill=\"x\", padx=2, pady=(0,4))\n        self.ram_operation_status_lbl = tk.Label(monitor, text=\"Ready\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"])\n        self.ram_operation_status_lbl.pack(anchor=\"w\", pady=(0,4))\n        metrics = tk.Frame(monitor, bg=C[\"bg\"])\n        metrics.pack(fill=\"x\")\n        self.ram_predicted_free_var = tk.StringVar(value=\"--\")\n        self.ram_confidence_var = tk.StringVar(value=\"--\")\n        self.ram_delta_var = tk.StringVar(value=\"--\")\n        for label, var, fg in [\n            (\"Predicted Free\", self.ram_predicted_free_var, C[\"success\"]),\n            (\"Confidence\", self.ram_confidence_var, C[\"accent4\"]),\n            (\"Delta\", self.ram_delta_var, C[\"warning\"]),\n        ]:\n            card = tk.Frame(metrics, bg=C[\"card\"], padx=8, pady=8)\n            card.pack(side=\"left\", fill=\"x\", expand=True, padx=3)\n            tk.Label(card, text=label, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\")\n            tk.Label(card, textvariable=var, font=(\"Segoe UI\", 14, \"bold\"), fg=fg, bg=C[\"card\"]).pack(anchor=\"w\")\n        mid = tk.Frame(frame, bg=C[\"bg\"])\n        mid.pack(fill=\"both\", expand=True, padx=16, pady=8)\n        mid.columnconfigure(0, weight=1)\n        mid.columnconfigure(1, weight=1)\n        left = tk.Frame(mid, bg=C[\"card\"])\n        left.grid(row=0, column=0, sticky=\"nsew\", padx=(0,6))\n        tk.Label(left, text=\"  RAM Tools\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8,6), padx=8)\n        self._action_card_grid(left, [\n            (\"\ud83d\ude80\", \"Aggressive RAM Boost\",  \"Full RAM free karo\",            C[\"btn_info\"], self._ram_boost_with_confirm),\n            (\"\ud83d\udd04\", \"Empty Working Sets\",    \"Working sets clear karo\",       C[\"btn_info\"], self._ram_empty_with_confirm),\n            (\"\ud83d\udcbe\", \"Clear Standby Cache\",   \"Standby list flush karo\",       C[\"btn_info\"], self._clear_standby_with_confirm),\n            (\"\ud83d\udcca\", \"Show Heavy Processes\",  \"RAM zyada use karne wale show\", C[\"btn_info\"], self._ram_show_heavy),\n        ], cols=2)\n\n        advanced = tk.Frame(left, bg=C[\"card\"])\n        advanced.pack(fill=\"x\", padx=12, pady=(8,4))\n        tk.Label(advanced, text=\"  Advanced OS Controls\", font=FONTS[\"small\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(0,6), padx=2)\n        adv_grid = tk.Frame(advanced, bg=C[\"card\"])\n        adv_grid.pack(fill=\"x\")\n        adv_grid.columnconfigure(0, weight=1)\n        adv_grid.columnconfigure(1, weight=1)\n\n        self._kernel_trim_btn = self._btn(\n            adv_grid, \"\ud83d\udd25 Kernel Trim\", C[\"btn_info\"],\n            lambda: self._ram_service_action_submit(\"kernel_trim\", self._kernel_working_set_trim, self._kernel_trim_btn)\n        )\n        self._kernel_trim_btn.grid(row=0, column=0, sticky=\"ew\", padx=3, pady=2)\n\n        self._priority_demote_btn = self._btn(\n            adv_grid, \"\ud83d\udc22 Priority Demotion\", C[\"btn_warn\"],\n            lambda: self._ram_service_action_submit(\"priority_demotion\", self._background_priority_demotion, self._priority_demote_btn)\n        )\n        self._priority_demote_btn.grid(row=0, column=1, sticky=\"ew\", padx=3, pady=2)\n\n        self._standby_flush_btn = self._btn(\n            adv_grid, \"\ud83c\udf0a Standby Flusher\", C[\"btn_chip\"],\n            lambda: self._ram_service_action_submit(\"standby_flusher\", self._flush_standby_list, self._standby_flush_btn)\n        )\n        self._standby_flush_btn.grid(row=1, column=0, sticky=\"ew\", padx=3, pady=2)\n\n        self._sysmain_toggle_btn = self._btn(\n            adv_grid, \"\ud83d\udee1 SysMain Toggle\", C[\"btn_chip\"],\n            lambda: self._ram_service_action_submit(\"sysmain_toggle\", self._toggle_sysmain_service, self._sysmain_toggle_btn)\n        )\n        self._sysmain_toggle_btn.grid(row=1, column=1, sticky=\"ew\", padx=3, pady=2)\n\n        # Auto RAM Free (every 15 minutes) \u2014 requested feature\n        row = tk.Frame(left, bg=C[\"card\"])\n        row.pack(fill=\"x\", padx=12, pady=(6, 2))\n        tk.Label(row, text=\"Interval:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ram_auto_interval_var = tk.StringVar(value=\"15\")\n        ttk.Combobox(row, values=[\"15\", \"30\", \"60\"], textvariable=self._ram_auto_interval_var,\n                     width=6, font=FONTS[\"small\"], state=\"readonly\").pack(side=\"left\", padx=6)\n        tk.Label(row, text=\"min\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ram_auto_btn = self._btn(left, \"\u23f1 Auto RAM Free (15 min): OFF\", C[\"btn_warn\"], self._ram_auto_toggle)\n        self._ram_auto_btn.pack(fill=\"x\", padx=12, pady=3)\n        right = tk.Frame(mid, bg=C[\"card\"])\n        right.grid(row=0, column=1, sticky=\"nsew\", padx=(6,0))\n        tk.Label(right, text=\"  Memory Log\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8,4), padx=8)\n        self.ram_log = self._scrolled_text(right, height=18)\n        self.ram_execution_log = self.ram_log\n        if not hasattr(self, \"_ram_auto_enabled\"):\n            self._ram_auto_enabled = False\n        if not hasattr(self, \"_ram_auto_after_id\"):\n            self._ram_auto_after_id = None\n        self._ram_update_stats()\n        return root\n\n    def _ram_update_stats(self):\n        try:\n            vm = psutil.virtual_memory()\n            self.ram_cards[\"total\"]._value_lbl.config(text=self._fmt_size(vm.total))\n            self.ram_cards[\"used\"]._value_lbl.config(text=f\"{vm.percent:.1f}%\")\n            self.ram_cards[\"used\"]._bar.config(value=vm.percent)\n            self.ram_cards[\"free\"]._value_lbl.config(text=self._fmt_size(vm.available))\n            self.ram_cards[\"cached\"]._value_lbl.config(text=self._fmt_size(getattr(vm, 'cached', 0) or 0))\n        except:\n            pass\n        self.after(3000, self._ram_update_stats)\n\n    def _ram_boost_with_confirm(self):\n        def before():\n            return f\"Free RAM before: {self._fmt_size(psutil.virtual_memory().available)}\"\n        def action():\n            self._do_ram_optimize(aggressive=True)\n        def after():\n            return f\"Free RAM after: {self._fmt_size(psutil.virtual_memory().available)}\"\n        self._confirm_and_launch_job(\"Aggressive RAM Boost\", \"This will aggressively free up RAM by trimming working sets and clearing caches.\\nMay cause slight lag for a moment.\",\n                                    before, \"ram_boost\", self._do_ram_optimize, True)\n\n    def _ram_empty_with_confirm(self):\n        def before():\n            return f\"Free RAM before: {self._fmt_size(psutil.virtual_memory().available)}\"\n        def action():\n            self._do_ram_optimize(aggressive=False)\n        def after():\n            return f\"Free RAM after: {self._fmt_size(psutil.virtual_memory().available)}\"\n        self._confirm_and_launch_job(\"Empty Working Sets\", \"This will safely empty working sets of all processes.\\nTypically frees RAM without harming performance.\",\n                                    before, \"ram_empty\", self._do_ram_optimize, False)\n\n    def _clear_standby_with_confirm(self):\n        def before():\n            return f\"Standby cache size before: {self._fmt_size(psutil.virtual_memory().available)}\"\n        def action():\n            self._purge_memory_lists()\n        def after():\n            return f\"Standby cache size after: {self._fmt_size(psutil.virtual_memory().available)}\"\n        self._confirm_and_launch_job(\"Clear Standby Cache\", \"This clears the standby memory list (cached RAM).\\nIt can free up RAM that is being held unnecessarily.\",\n                                    before, \"ram_clear_standby\", self._purge_memory_lists)\n\n    def _do_ram_optimize(self, aggressive=False):\n        if not hasattr(self, \"_ram_opt_lock\"):\n            self._ram_opt_lock = threading.Lock()\n        with self._ram_opt_lock:\n            if getattr(self, \"_ram_opt_running\", False):\n                self._append_log(self.ram_log, \"\u26a0\ufe0f RAM optimize already running \u2014 skipping\", C[\"warning\"])\n                return\n            self._ram_opt_running = True\n        try:\n            before = psutil.virtual_memory()\n            gc.collect()\n            kernel32 = ctypes.windll.kernel32\n            psapi = ctypes.windll.psapi\n\n            batch = {\n                \"phase\": \"ram_optimize\",\n                \"status_text\": \"Optimizing RAM...\",\n                \"progress_pct\": 0.0,\n                \"processes_scanned\": 0,\n                \"errors\": 0,\n                \"freed_mb\": 0,\n                \"predicted_free_mb\": int(before.available / (1024**2) * 0.05),\n                \"confidence_score\": min(95, max(30, int((before.percent / 100.0) * 90 + 10))),\n                \"delta_mb\": 0,\n            }\n            last_dispatch = time.time()\n\n            def dispatch_metrics(force=False):\n                try:\n                    batch[\"progress_pct\"] = min(100.0, (batch[\"processes_scanned\"] / max(1, psutil.cpu_count(logical=False) * 10)) * 100.0)\n                    batch[\"status_text\"] = f\"Optimizing RAM... {batch['processes_scanned']} processes scanned\"\n                    self._ram_service_emit_metrics(batch.copy(), force=force)\n                except Exception:\n                    pass\n\n            for proc in psutil.process_iter(['pid']):\n                batch[\"processes_scanned\"] += 1\n                pid = proc.info.get('pid')\n                if not pid or pid in (0, 4):\n                    continue\n                try:\n                    handle = kernel32.OpenProcess(0x0400 | 0x0100 | 0x0010, False, int(pid))\n                    if handle:\n                        try:\n                            try:\n                                psapi.EmptyWorkingSet(handle)\n                            except (PermissionError, psutil.AccessDenied):\n                                batch[\"errors\"] += 1\n                            except Exception:\n                                batch[\"errors\"] += 1\n                        finally:\n                            kernel32.CloseHandle(handle)\n                except (PermissionError, psutil.AccessDenied):\n                    batch[\"errors\"] += 1\n                except Exception:\n                    batch[\"errors\"] += 1\n                if time.time() - last_dispatch &gt;= 0.12:\n                    dispatch_metrics()\n                    last_dispatch = time.time()\n\n            self._purge_memory_lists()\n            if aggressive:\n                try:\n                    ctypes.windll.kernel32.SetSystemFileCacheSize(-1, -1, 0)\n                except Exception:\n                    pass\n\n            after = psutil.virtual_memory()\n            freed = after.available - before.available\n            batch[\"freed_mb\"] = int(freed / (1024**2))\n            batch[\"delta_mb\"] = int((after.available - before.available) / (1024**2))\n            batch[\"status_text\"] = f\"RAM optimize complete \u2014 freed {self._fmt_size(freed)}\"\n            batch[\"progress_pct\"] = 100.0\n            self._ram_service_emit_metrics(batch.copy(), force=True)\n\n            if freed &gt;= 0:\n                self._append_log(self.ram_log, f\"\u2705 RAM Freed: {self._fmt_size(freed)}\", C[\"success\"])\n            else:\n                self._append_log(self.ram_log, f\"\u2139 RAM change: {self._fmt_size(freed)} (cache re-allocated)\", C[\"warning\"])\n        except Exception as e:\n            self._append_log(self.ram_log, f\"RAM optimize failed: {e}\", C[\"error\"])\n        finally:\n            with self._ram_opt_lock:\n                self._ram_opt_running = False\n\n    def _kernel_working_set_trim(self):\n        before = self._snapshot_resource_state() or {}\n        batch = {\n            \"phase\": \"kernel_trim\",\n            \"status_text\": \"Kernel working set trim running...\",\n            \"progress_pct\": 0.0,\n            \"trimmed_processes\": 0,\n            \"errors\": 0,\n            \"delta_mb\": 0,\n        }\n        self._ram_service_emit_metrics(batch)\n        try:\n            kernel32 = ctypes.windll.kernel32\n            psapi = ctypes.windll.psapi\n            last_dispatch = time.monotonic()\n            for proc in psutil.process_iter(['pid', 'name']):\n                try:\n                    pid = int(proc.info.get('pid') or 0)\n                    if pid &lt;= 0 or pid == os.getpid():\n                        continue\n                    handle = kernel32.OpenProcess(0x001F0FFF, False, pid)\n                    if not handle:\n                        continue\n                    try:\n                        if psapi.EmptyWorkingSet(handle):\n                            batch[\"trimmed_processes\"] += 1\n                        try:\n                            kernel32.SetProcessWorkingSetSize(handle, -1, -1)\n                        except Exception:\n                            pass\n                    finally:\n                        kernel32.CloseHandle(handle)\n                except (PermissionError, psutil.AccessDenied):\n                    batch[\"errors\"] += 1\n                except Exception:\n                    batch[\"errors\"] += 1\n                if time.monotonic() - last_dispatch &gt;= 0.120:\n                    batch[\"status_text\"] = f\"Kernel trim active \u2014 {batch['trimmed_processes']} trimmed\"\n                    batch[\"progress_pct\"] = min(100.0, (batch[\"trimmed_processes\"] / max(1, psutil.cpu_count(logical=False) * 2)) * 100.0)\n                    self._ram_service_emit_metrics(batch.copy())\n                    last_dispatch = time.monotonic()\n            after = psutil.virtual_memory()\n            batch[\"delta_mb\"] = int((after.available - before.get(\"available_mb\", 0)) / 1024**2)\n            batch[\"status_text\"] = f\"Kernel trim complete \u2014 freed {self._fmt_size(batch['delta_mb'] * 1024**2)}\"\n            batch[\"progress_pct\"] = 100.0\n            self._ram_service_emit_metrics(batch.copy(), force=True)\n            self._append_log(self.ram_log, f\"\u2705 Kernel working set trim complete \u2014 freed {self._fmt_size(batch['delta_mb'] * 1024**2)}\", C[\"success\"])\n        except Exception as e:\n            self._append_log(self.ram_log, f\"Kernel trim failed: {e}\", C[\"error\"])\n\n    def _background_priority_demotion(self):\n        before = psutil.virtual_memory()\n        batch = {\n            \"phase\": \"priority_demotion\",\n            \"status_text\": \"Background process priority demotion running...\",\n            \"progress_pct\": 0.0,\n            \"scanned\": 0,\n            \"demoted\": 0,\n            \"errors\": 0,\n            \"delta_mb\": 0,\n        }\n        self._ram_service_emit_metrics(batch)\n        idle_class = getattr(psutil, 'IDLE_PRIORITY_CLASS', getattr(psutil, 'BELOW_NORMAL_PRIORITY_CLASS', 64))\n        keep_names = {\n            'explorer.exe', 'taskmgr.exe', 'chrome.exe', 'firefox.exe', 'msedge.exe',\n            'dwm.exe', 'svchost.exe', 'services.exe', 'lsass.exe', 'wininit.exe',\n            'winlogon.exe', 'csrss.exe', 'system', 'idle', 'spoolsv.exe', 'steam.exe',\n        }\n        last_dispatch = time.monotonic()\n        for proc in psutil.process_iter(['pid', 'name', 'username', 'nice']):\n            batch[\"scanned\"] += 1\n            try:\n                pid = int(proc.info.get('pid') or 0)\n                if pid &lt;= 0 or pid == os.getpid():\n                    continue\n                name = str(proc.info.get('name') or '').lower()\n                username = str(proc.info.get('username') or '').lower()\n                if name in keep_names or any(term in name for term in ('microsoft', 'windows', 'service', 'system', 'sql', 'svchost')):\n                    continue\n                if username in ('nt authority\\\\system', 'local service', 'network service'):\n                    continue\n                current = proc.info.get('nice')\n                if current == idle_class:\n                    continue\n                try:\n                    proc.nice(idle_class)\n                    batch[\"demoted\"] += 1\n                except (PermissionError, psutil.AccessDenied):\n                    batch[\"errors\"] += 1\n                except Exception:\n                    batch[\"errors\"] += 1\n            except (PermissionError, psutil.AccessDenied):\n                batch[\"errors\"] += 1\n            except Exception:\n                batch[\"errors\"] += 1\n            if time.monotonic() - last_dispatch &gt;= 0.120:\n                batch[\"status_text\"] = f\"Demoting background apps... {batch['demoted']} demoted\"\n                batch[\"progress_pct\"] = min(100.0, (batch[\"scanned\"] / max(1, psutil.cpu_count(logical=False) * 10)) * 100.0)\n                self._ram_service_emit_metrics(batch.copy())\n                last_dispatch = time.monotonic()\n        after = psutil.virtual_memory()\n        batch[\"delta_mb\"] = int((after.available - before.available) / 1024**2)\n        batch[\"status_text\"] = f\"Priority demotion complete \u2014 {batch['demoted']} apps demoted\"\n        batch[\"progress_pct\"] = 100.0\n        self._ram_service_emit_metrics(batch.copy(), force=True)\n        self._append_log(self.ram_log, f\"\u2705 Background priority demotion complete \u2014 {batch['demoted']} processes\", C[\"success\"])\n\n    def _flush_standby_list(self):\n        before = psutil.virtual_memory()\n        batch = {\n            \"phase\": \"standby_flush\",\n            \"status_text\": \"Standby list flush running...\",\n            \"progress_pct\": 0.0,\n            \"errors\": 0,\n            \"delta_mb\": 0,\n        }\n        self._ram_service_emit_metrics(batch)\n        try:\n            self._purge_memory_lists()\n            try:\n                ctypes.windll.kernel32.SetSystemFileCacheSize(-1, -1, 0)\n            except (PermissionError, psutil.AccessDenied):\n                batch[\"errors\"] += 1\n            except Exception:\n                pass\n            try:\n                kernel32 = ctypes.windll.kernel32\n                psapi = ctypes.windll.psapi\n                handle = kernel32.GetCurrentProcess()\n                psapi.EmptyWorkingSet(handle)\n            except Exception:\n                pass\n            after = psutil.virtual_memory()\n            batch[\"delta_mb\"] = int((after.available - before.available) / 1024**2)\n            batch[\"status_text\"] = f\"Standby flush complete \u2014 freed {self._fmt_size(batch['delta_mb'] * 1024**2)}\"\n            batch[\"progress_pct\"] = 100.0\n            self._ram_service_emit_metrics(batch.copy(), force=True)\n            self._append_log(self.ram_log, f\"\u2705 Standby list flushed \u2014 freed {self._fmt_size(batch['delta_mb'] * 1024**2)}\", C[\"success\"])\n        except Exception as e:\n            self._append_log(self.ram_log, f\"Standby flush failed: {e}\", C[\"error\"])\n\n    def _toggle_sysmain_service(self):\n        batch = {\n            \"phase\": \"sysmain_toggle\",\n            \"status_text\": \"SysMain toggle running...\",\n            \"progress_pct\": 0.0,\n            \"action\": \"pending\",\n        }\n        self._ram_service_emit_metrics(batch)\n        try:\n            svc = psutil.win_service_get(\"SysMain\")\n            status = svc.status().lower()\n            if status == \"running\":\n                try:\n                    svc.stop()\n                    svc.wait(15)\n                    batch[\"action\"] = \"stopped\"\n                except (PermissionError, psutil.AccessDenied):\n                    batch[\"action\"] = \"permission_denied\"\n                    batch[\"status_text\"] = \"SysMain stop denied\"\n                    batch[\"progress_pct\"] = 100.0\n                    self._ram_service_emit_metrics(batch.copy(), force=True)\n                    self._append_log(self.ram_log, \"\u26a0\ufe0f SysMain stop denied by permissions\", C[\"warning\"])\n                    return\n                except Exception:\n                    batch[\"action\"] = \"stop_failed\"\n            else:\n                try:\n                    svc.start()\n                    svc.wait(15)\n                    batch[\"action\"] = \"started\"\n                except (PermissionError, psutil.AccessDenied):\n                    batch[\"action\"] = \"permission_denied\"\n                    batch[\"status_text\"] = \"SysMain start denied\"\n                    batch[\"progress_pct\"] = 100.0\n                    self._ram_service_emit_metrics(batch.copy(), force=True)\n                    self._append_log(self.ram_log, \"\u26a0\ufe0f SysMain start denied by permissions\", C[\"warning\"])\n                    return\n                except Exception:\n                    batch[\"action\"] = \"start_failed\"\n            batch[\"status_text\"] = f\"SysMain {batch['action']}\"\n            batch[\"progress_pct\"] = 100.0\n            self._ram_service_emit_metrics(batch.copy(), force=True)\n            self._append_log(self.ram_log, f\"\u2705 SysMain {batch['action']}\", C[\"success\"])\n        except Exception as e:\n            self._append_log(self.ram_log, f\"SysMain toggle failed: {e}\", C[\"error\"])\n\n    def _ram_auto_toggle(self):\n        enabled = not bool(getattr(self, \"_ram_auto_enabled\", False))\n        self._ram_auto_enabled = enabled\n        try:\n            if hasattr(self, \"_ram_auto_btn\") and self._ram_auto_btn:\n                self._ram_auto_btn.config(\n                    text=(\"\u23f1 Auto RAM Free (15 min): ON\" if enabled else \"\u23f1 Auto RAM Free (15 min): OFF\"),\n                    bg=(C[\"btn_info\"] if enabled else C[\"btn_warn\"])\n                )\n        except Exception:\n            pass\n        if enabled:\n            mins = self._ram_auto_interval_minutes()\n            self._append_log(self.ram_log, f\"\u23f1 Auto RAM Free enabled \u2014 every {mins} minutes\", C[\"accent4\"])\n            self._ram_auto_schedule(immediate=False)\n        else:\n            self._append_log(self.ram_log, \"\u23f1 Auto RAM Free disabled\", C[\"warning\"])\n            self._ram_auto_cancel()\n\n    def _ram_auto_cancel(self):\n        try:\n            aid = getattr(self, \"_ram_auto_after_id\", None)\n            if aid:\n                self.after_cancel(aid)\n        except Exception:\n            pass\n        self._ram_auto_after_id = None\n\n    def _ram_auto_schedule(self, immediate=False):\n        self._ram_auto_cancel()\n        if not getattr(self, \"_ram_auto_enabled\", False):\n            return\n        mins = self._ram_auto_interval_minutes()\n        delay = 1000 if immediate else (mins * 60 * 1000)\n        self._ram_auto_after_id = self.after(delay, self._ram_auto_tick)\n\n    def _ram_auto_interval_minutes(self):\n        try:\n            v = int((getattr(self, \"_ram_auto_interval_var\", None).get() if hasattr(self, \"_ram_auto_interval_var\") else \"15\") or \"15\")\n            if v in (15, 30, 60):\n                return v\n        except Exception:\n            pass\n        return 15\n\n    def _ram_auto_tick(self):\n        if not getattr(self, \"_ram_auto_enabled\", False):\n            return\n        # Avoid lag when system is busy\n        try:\n            if psutil.cpu_percent(interval=0.1) &gt; 75:\n                self._append_log(self.ram_log, \"\u23f1 Auto RAM Free skipped (CPU high)\", C[\"warning\"])\n                self._ram_auto_schedule(immediate=False)\n                return\n        except Exception:\n            pass\n        self._submit_ram_service_job(\"ram_auto_boost\", self._do_ram_optimize, True)\n        self._ram_auto_schedule(immediate=False)\n\n    def _purge_memory_lists(self):\n        try:\n            ntdll = ctypes.windll.ntdll\n            cleared = False\n            for val in (2, 3, 4, 5):\n                try:\n                    # NtSetSystemInformation returns an NTSTATUS; failure raises in some contexts\n                    ntdll.NtSetSystemInformation(80, ctypes.byref(ctypes.c_int(val)), 4)\n                    cleared = True\n                except Exception:\n                    continue\n            if cleared:\n                try:\n                    self._append_log(self.ram_log, \"\u2705 Standby cleared\", C[\"success\"])\n                except Exception:\n                    pass\n                return True\n\n            # Fallback: try to reduce system file cache size\n            try:\n                ctypes.windll.kernel32.SetSystemFileCacheSize(-1, -1, 0)\n                try:\n                    self._append_log(self.ram_log, \"\u2705 Standby cleared via SetSystemFileCacheSize\", C[\"success\"])\n                except Exception:\n                    pass\n                return True\n            except Exception:\n                try:\n                    self._append_log(self.ram_log, \"\u26a0 Could not clear standby lists (insufficient permissions?)\", C[\"warning\"])\n                except Exception:\n                    pass\n                return False\n\n        except Exception as e:\n            try:\n                self._append_log(self.ram_log, f\"Standby clear failed: {e}\", C[\"error\"])\n            except Exception:\n                pass\n            return False\n\n    def _ram_show_heavy(self):\n        \"\"\"RAM heavy processes ko popup window mein dikhao with Kill/Stop buttons\"\"\"\n        win = tk.Toplevel(self)\n        win.title(\"\ud83d\udd34 RAM Heavy Processes \u2014 Kill / Stop\")\n        win.geometry(\"820x500\")\n        win.configure(bg=C[\"bg\"])\n        win.resizable(True, True)\n\n        tk.Label(win, text=\"\ud83d\udd34  RAM Heavy Processes\", font=FONTS[\"subhead\"],\n                 fg=C[\"error\"], bg=C[\"bg\"]).pack(anchor=\"w\", padx=16, pady=(12, 4))\n        tk.Label(win, text=\"Process select karo \u2192 Kill (force) ya Terminate (graceful)\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"]).pack(anchor=\"w\", padx=16)\n\n        # --- treeview ---\n        cols = (\"PID\", \"Name\", \"RAM (MB)\", \"CPU %\", \"Status\")\n        tree_frame = tk.Frame(win, bg=C[\"bg\"])\n        tree_frame.pack(fill=\"both\", expand=True, padx=16, pady=8)\n        tree = ttk.Treeview(tree_frame, columns=cols, show=\"headings\",\n                            height=14, style=\"Custom.Treeview\", selectmode=\"extended\")\n        for col, w in zip(cols, [70, 260, 90, 70, 90]):\n            tree.heading(col, text=col)\n            tree.column(col, width=w, anchor=\"w\")\n        vsb = ttk.Scrollbar(tree_frame, orient=\"vertical\", command=tree.yview)\n        tree.configure(yscrollcommand=vsb.set)\n        tree.pack(side=\"left\", fill=\"both\", expand=True)\n        vsb.pack(side=\"right\", fill=\"y\")\n\n        status_lbl = tk.Label(win, text=\"Loading\u2026\", font=FONTS[\"small\"],\n                              fg=C[\"text_dim\"], bg=C[\"bg\"])\n        status_lbl.pack(anchor=\"w\", padx=16)\n\n        # --- buttons ---\n        btn_row = tk.Frame(win, bg=C[\"bg\"])\n        btn_row.pack(fill=\"x\", padx=16, pady=(4, 12))\n\n        def _refresh():\n            tree.delete(*tree.get_children())\n            status_lbl.config(text=\"Refreshing\u2026\", fg=C[\"text_dim\"])\n            try:\n                procs = sorted(\n                    psutil.process_iter(['pid', 'name', 'memory_info', 'cpu_percent', 'status']),\n                    key=lambda p: (p.info.get('memory_info') or type('', (), {'rss': 0})()).rss,\n                    reverse=True\n                )\n                count = 0\n                for p in procs[:30]:\n                    try:\n                        mem = p.info.get('memory_info')\n                        mb = round(mem.rss / (1024 ** 2), 1) if mem else 0\n                        cpu = p.info.get('cpu_percent', 0.0) or 0.0\n                        st = p.info.get('status', '?') or '?'\n                        tree.insert(\"\", \"end\", iid=str(p.info['pid']),\n                                    values=(p.info['pid'], p.info.get('name', '?'), mb, f\"{cpu:.1f}\", st))\n                        count += 1\n                    except Exception:\n                        pass\n                status_lbl.config(text=f\"\u2705 {count} processes loaded \u2014 multiple select ke liye Ctrl+Click\",\n                                  fg=C[\"success\"])\n            except Exception as ex:\n                status_lbl.config(text=f\"\u274c Error: {ex}\", fg=C[\"error\"])\n\n        def _kill_selected(graceful=False):\n            selected = tree.selection()\n            if not selected:\n                messagebox.showwarning(\"Select karo\", \"Pehle ek ya zyada processes select karo\", parent=win)\n                return\n            names = [tree.item(s)[\"values\"][1] for s in selected]\n            action = \"Terminate (graceful)\" if graceful else \"Kill (force)\"\n            if not messagebox.askyesno(\n                f\"Confirm \u2014 {action}\",\n                f\"{len(selected)} process(es) {action} karna hai?\\n\\n\" +\n                \"\\n\".join(str(n) for n in names[:10]) +\n                (\"\\n...\" if len(names) &gt; 10 else \"\") +\n                \"\\n\\nUnsaved data loss ho sakta hai!\",\n                parent=win\n            ):\n                return\n            done = 0\n            errs = []\n            for iid in selected:\n                try:\n                    pid = int(iid)\n                    proc = psutil.Process(pid)\n                    if graceful:\n                        proc.terminate()\n                    else:\n                        proc.kill()\n                    tree.delete(iid)\n                    done += 1\n                except psutil.NoSuchProcess:\n                    tree.delete(iid)\n                    done += 1\n                except Exception as ex:\n                    errs.append(f\"PID {iid}: {ex}\")\n            msg = f\"\u2705 {done} process(es) {action} kiye\"\n            if errs:\n                msg += f\"\\n\u26a0\ufe0f {len(errs)} errors: \" + \"; \".join(errs[:3])\n            status_lbl.config(text=msg, fg=C[\"success\"] if not errs else C[\"warning\"])\n            self._append_log(self.ram_log, msg, C[\"success\"] if not errs else C[\"warning\"])\n\n        tk.Button(btn_row, text=\"\ud83d\udd04 Refresh\", font=FONTS[\"body\"],\n                  bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=12, pady=6,\n                  cursor=\"hand2\", command=_refresh).pack(side=\"left\", padx=(0, 6))\n        tk.Button(btn_row, text=\"\u26a1 Terminate (Graceful)\", font=FONTS[\"body\"],\n                  bg=C[\"warning\"], fg=C[\"bg\"], bd=0, padx=12, pady=6,\n                  cursor=\"hand2\", command=lambda: _kill_selected(graceful=True)).pack(side=\"left\", padx=(0, 6))\n        tk.Button(btn_row, text=\"\ud83d\udc80 Kill (Force)\", font=FONTS[\"body\"],\n                  bg=C[\"error\"], fg=C[\"text\"], bd=0, padx=12, pady=6,\n                  cursor=\"hand2\", command=lambda: _kill_selected(graceful=False)).pack(side=\"left\", padx=(0, 6))\n        tk.Button(btn_row, text=\"\u2716 Close\", font=FONTS[\"body\"],\n                  bg=C[\"card\"], fg=C[\"text\"], bd=0, padx=12, pady=6,\n                  cursor=\"hand2\", command=win.destroy).pack(side=\"right\")\n\n        win.after(100, _refresh)  # auto load on open\n\n    def _do_ram_show_heavy(self):\n        try:\n            procs = sorted(psutil.process_iter(['pid','name','memory_info']),\n                           key=lambda p: (p.info.get('memory_info') or type('',(),{'rss':0})()).rss,\n                           reverse=True)\n            self._append_log(self.ram_log, \"\ud83d\udd34 Top 10 RAM-heavy processes:\", C[\"accent\"])\n            for p in procs[:10]:\n                try:\n                    mem = p.info.get('memory_info')\n                    mb = round(mem.rss/(1024**2),1) if mem else 0\n                    self._append_log(self.ram_log, f\"  PID {p.info['pid']:6d}  {p.info['name']:&lt;30s}  {mb} MB\", C[\"text\"])\n                except Exception:\n                    pass\n        except Exception:\n            self._append_log(self.ram_log, \"\u26a0\ufe0f Unable to enumerate RAM-heavy processes right now.\", C[\"warning\"])\n\n    # ---------- STARTUP MANAGER (unchanged except confirm) ----------\n    def _build_startup(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\ude80 Startup Manager\", \"Manage startup programs\")\n        self._action_card_grid(frame, [\n            (\"\ud83d\udd0d\", \"Refresh\",          \"Startup entries reload karo\",          C[\"btn_info\"], self._refresh_startup),\n            (\"\u26d4\", \"Disable Selected\", \"Selected entries boot pe nahi chalenge\",C[\"btn_warn\"], lambda: self._with_confirm(\"Disable Startup\", \"Disable selected startup entries? They won't run on boot.\", self._disable_startup)),\n            (\"\u2705\", \"Enable Selected\",  \"Selected entries wapas enable karo\",   C[\"btn\"],      lambda: self._with_confirm(\"Enable Startup\", \"Enable selected startup entries?\", self._enable_startup)),\n            (\"\ud83d\udce4\", \"Export List\",      \"Startup entries export karo\",        C[\"btn_chip\"], self._export_startup_list),\n            (\"\ud83d\udd0e\", \"Find Orphans\",     \"Missing target files ke startup entries\", C[\"btn_warn\"], self._find_orphan_startup_entries),\n        ], cols=5)\n        self.startup_tree = ttk.Treeview(frame, columns=(\"Name\", \"Command\", \"Location\", \"Status\"), show=\"headings\", height=20, style=\"Custom.Treeview\")\n        for col, w in zip((\"Name\", \"Command\", \"Location\", \"Status\"), [200,300,150,80]):\n            self.startup_tree.heading(col, text=col)\n            self.startup_tree.column(col, width=w, anchor=\"w\")\n        vsb = ttk.Scrollbar(frame, orient=\"vertical\", command=self.startup_tree.yview)\n        self.startup_tree.configure(yscrollcommand=vsb.set)\n        self.startup_tree.pack(side=\"left\", fill=\"both\", expand=True, padx=16, pady=8)\n        vsb.pack(side=\"right\", fill=\"y\", pady=8, padx=(0,8))\n        return frame\n\n    def _collect_startup_entries(self):\n        disabled_prefix = \"__GodawariDisabled__\"\n        seen = set()\n        entries = []\n        reg_locations = [\n            (\"HKCU\", winreg.HKEY_CURRENT_USER, r\"Software\\Microsoft\\Windows\\CurrentVersion\\Run\"),\n            (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"Software\\Microsoft\\Windows\\CurrentVersion\\Run\"),\n            (\"HKCU\", winreg.HKEY_CURRENT_USER, r\"Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce\"),\n            (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce\"),\n            (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"Software\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Run\"),\n            (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"Software\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\RunOnce\"),\n        ]\n        for hive_name, hive, reg_path in reg_locations:\n            try:\n                key = winreg.OpenKey(hive, reg_path, 0, winreg.KEY_READ)\n                i = 0\n                while True:\n                    try:\n                        name, value, _ = winreg.EnumValue(key, i)\n                        status = \"Disabled\" if name.startswith(disabled_prefix) else \"Enabled\"\n                        shown_name = name.replace(disabled_prefix, \"\", 1)\n                        dedupe_key = (shown_name.lower(), str(value).lower(), f\"{hive_name}|REG|{reg_path}\")\n                        if dedupe_key not in seen:\n                            seen.add(dedupe_key)\n                            entries.append({\n                                \"display_name\": shown_name,\n                                \"raw_name\": name,\n                                \"command\": str(value),\n                                \"location\": f\"{hive_name}|REG|{reg_path}\",\n                                \"status\": status,\n                                \"kind\": \"registry\",\n                                \"hive\": hive,\n                                \"reg_path\": reg_path,\n                                \"value\": value,\n                            })\n                        i += 1\n                    except OSError:\n                        break\n                winreg.CloseKey(key)\n            except Exception:\n                pass\n\n        startup_folders = [\n            (os.path.join(os.environ.get(\"APPDATA\", \"\"), r\"Microsoft\\Windows\\Start Menu\\Programs\\Startup\"), \"User Startup\"),\n            (os.path.join(os.environ.get(\"PROGRAMDATA\", \"\"), r\"Microsoft\\Windows\\Start Menu\\Programs\\StartUp\"), \"Common Startup\"),\n        ]\n        for folder, label in startup_folders:\n            if not folder or not os.path.exists(folder):\n                continue\n            try:\n                for f in Path(folder).glob(\"*\"):\n                    if not f.is_file():\n                        continue\n                    status = \"Disabled\" if f.name.endswith(\".disabled\") else \"Enabled\"\n                    shown_name = f.name[:-9] if status == \"Disabled\" else f.name\n                    dedupe_key = (shown_name.lower(), str(f).lower(), f\"{label}|FOLDER|{folder}\")\n                    if dedupe_key in seen:\n                        continue\n                    seen.add(dedupe_key)\n                    entries.append({\n                        \"display_name\": shown_name,\n                        \"raw_name\": f.name,\n                        \"command\": str(f),\n                        \"location\": f\"{label}|FOLDER|{folder}\",\n                        \"status\": status,\n                        \"kind\": \"folder\",\n                        \"path\": str(f),\n                    })\n            except Exception:\n                pass\n        return entries\n\n    def _refresh_startup(self):\n        self.startup_tree.delete(*self.startup_tree.get_children())\n        for entry in self._collect_startup_entries():\n            self.startup_tree.insert(\"\", \"end\", values=(entry[\"display_name\"], entry[\"command\"], entry[\"location\"], entry[\"status\"]))\n\n    def _refresh_registry_startup(self):\n        if not hasattr(self, \"registry_startup_tree\"):\n            return\n        self.registry_startup_tree.delete(*self.registry_startup_tree.get_children())\n        self._registry_startup_items = {}\n        for entry in self._collect_startup_entries():\n            uid = f\"startup-{len(self._registry_startup_items) + 1}\"\n            self._registry_startup_items[uid] = entry\n            self.registry_startup_tree.insert(\"\", \"end\", iid=uid, values=(entry[\"display_name\"], entry[\"command\"], entry[\"location\"], entry[\"status\"]))\n\n    def _delete_startup_entry(self, entry):\n        if not entry:\n            return False\n        try:\n            if entry[\"kind\"] == \"registry\":\n                key = winreg.OpenKey(entry[\"hive\"], entry[\"reg_path\"], 0, winreg.KEY_SET_VALUE | winreg.KEY_READ)\n                try:\n                    winreg.DeleteValue(key, entry[\"raw_name\"])\n                finally:\n                    winreg.CloseKey(key)\n                return True\n            path = Path(entry.get(\"path\") or entry.get(\"command\") or \"\")\n            if not path.exists():\n                return False\n            if path.is_dir():\n                shutil.rmtree(path, ignore_errors=True)\n            else:\n                path.unlink()\n            return True\n        except Exception:\n            return False\n\n    def _delete_registry_startup_selected(self):\n        if not hasattr(self, \"registry_startup_tree\"):\n            return\n        selected = self.registry_startup_tree.selection()\n        if not selected:\n            messagebox.showwarning(\"Nothing Selected\", \"Delete karne ke liye startup item select karo.\")\n            return\n        if not messagebox.askyesno(\"Delete Selected Startup Items\", f\"{len(selected)} selected startup item(s) delete karein? This affects boot behavior.\"):\n            return\n        deleted = 0\n        failed = 0\n        for iid in selected:\n            entry = self._registry_startup_items.get(iid)\n            if self._delete_startup_entry(entry):\n                deleted += 1\n                self.registry_startup_tree.delete(iid)\n                self._append_log(self.reg_log, f\"\ud83d\uddd1 Deleted startup item: {entry['display_name']}\", C[\"success\"])\n            else:\n                failed += 1\n                self._append_log(self.reg_log, f\"\u26a0 Could not delete startup item: {entry['display_name']}\", C[\"warning\"])\n        if deleted:\n            self._append_log(self.reg_log, f\"\u2705 Deleted {deleted} startup item(s).\", C[\"success\"])\n        if failed:\n            self._append_log(self.reg_log, f\"\u26a0 Failed to delete {failed} startup item(s).\", C[\"warning\"])\n\n    def _disable_startup(self):\n        for item in self.startup_tree.selection():\n            vals = self.startup_tree.item(item, \"values\")\n            if len(vals) &lt; 4 or vals[3] == \"Disabled\":\n                continue\n            name, command, loc = vals[0], vals[1], vals[2]\n            parts = loc.split(\"|\", 2)\n            if len(parts) &gt;= 3 and parts[1] == \"REG\":\n                hive = winreg.HKEY_CURRENT_USER if parts[0] == \"HKCU\" else winreg.HKEY_LOCAL_MACHINE\n                key = winreg.OpenKey(hive, parts[2], 0, winreg.KEY_SET_VALUE | winreg.KEY_READ)\n                value, vtype = winreg.QueryValueEx(key, name)\n                winreg.SetValueEx(key, \"__GodawariDisabled__\" + name, 0, vtype, value)\n                winreg.DeleteValue(key, name)\n                winreg.CloseKey(key)\n            elif len(parts) &gt;= 3 and parts[1] == \"FOLDER\":\n                src = Path(command)\n                dest = src.with_name(src.name + \".disabled\")\n                if src.exists():\n                    if dest.exists():\n                        dest.unlink()\n                    src.rename(dest)\n        self._refresh_startup()\n\n    def _enable_startup(self):\n        for item in self.startup_tree.selection():\n            vals = self.startup_tree.item(item, \"values\")\n            if len(vals) &lt; 4 or vals[3] == \"Enabled\":\n                continue\n            name, command, loc = vals[0], vals[1], vals[2]\n            parts = loc.split(\"|\", 2)\n            if len(parts) &gt;= 3 and parts[1] == \"REG\":\n                hive = winreg.HKEY_CURRENT_USER if parts[0] == \"HKCU\" else winreg.HKEY_LOCAL_MACHINE\n                key = winreg.OpenKey(hive, parts[2], 0, winreg.KEY_SET_VALUE | winreg.KEY_READ)\n                value, vtype = winreg.QueryValueEx(key, \"__GodawariDisabled__\" + name)\n                winreg.SetValueEx(key, name, 0, vtype, value)\n                winreg.DeleteValue(key, \"__GodawariDisabled__\" + name)\n                winreg.CloseKey(key)\n            elif len(parts) &gt;= 3 and parts[1] == \"FOLDER\":\n                src = Path(command)\n                if src.name.endswith(\".disabled\") and src.exists():\n                    dest = src.with_name(src.name[:-9])\n                    if dest.exists():\n                        dest.unlink()\n                    src.rename(dest)\n        self._refresh_startup()\n\n    def _startup_command_to_path(self, command):\n        if not command:\n            return \"\"\n        command = command.strip()\n        m = re.match(r'^\"([^\"]+)\"', command)\n        if m:\n            return m.group(1)\n        m = re.match(r'^([^\\s]+)', command)\n        return m.group(1) if m else \"\"\n\n    def _export_startup_list(self):\n        items = []\n        for item in self.startup_tree.get_children():\n            vals = self.startup_tree.item(item, \"values\")\n            if len(vals) &lt; 4:\n                continue\n            items.append(vals)\n        if not items:\n            messagebox.showinfo(\"No Startup Entries\", \"Koi startup entry export karne ko nahin mila.\")\n            return\n        path = filedialog.asksaveasfilename(defaultextension=\".csv\",\n                                            filetypes=[(\"CSV files\", \"*.csv\")],\n                                            initialfile=\"Startup_Entries.csv\",\n                                            title=\"Save Startup List\")\n        if not path:\n            return\n        try:\n            import csv\n            with open(path, \"w\", newline=\"\", encoding=\"utf-8\") as f:\n                writer = csv.writer(f)\n                writer.writerow([\"Name\", \"Command\", \"Location\", \"Status\"])\n                writer.writerows(items)\n            messagebox.showinfo(\"Exported\", f\"Startup list saved to:\\n{path}\")\n            self._append_log(self.clean_log, f\"\ud83d\udcbe Startup list exported: {path}\", C[\"success\"])\n        except Exception as e:\n            messagebox.showerror(\"Export Failed\", str(e))\n            self._append_log(self.clean_log, f\"\u274c Startup export failed: {e}\", C[\"error\"])\n\n    def _find_orphan_startup_entries(self):\n        orphaned = 0\n        for iid in self.startup_tree.get_children():\n            vals = self.startup_tree.item(iid, \"values\")\n            if len(vals) &lt; 3:\n                continue\n            path = self._startup_command_to_path(vals[1])\n            exists = os.path.exists(path) if path else False\n            if path and not exists:\n                orphaned += 1\n                self.startup_tree.item(iid, tags=(\"orphan\",))\n            else:\n                self.startup_tree.item(iid, tags=())\n        self.startup_tree.tag_configure(\"orphan\", background=\"#3D1D1D\")\n        if orphaned:\n            messagebox.showinfo(\"Orphaned Startup Entries\", f\"{orphaned} orphaned startup entries found. Check the list for missing targets.\")\n            self._append_log(self.clean_log, f\"\ud83d\udd0e Found {orphaned} orphaned startup entries.\", C[\"warning\"])\n        else:\n            messagebox.showinfo(\"No Orphans\", \"No missing startup targets detected.\")\n            self._append_log(self.clean_log, \"\u2705 No orphaned startup entries found.\", C[\"success\"])\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  TASK SCHEDULER \u2014 Knowledge Base\n    #  cat: \"danger\"   = Kabhi disable mat karo \u2014 system toot jayega\n    #       \"caution\"  = Soch ke karo \u2014 Windows feature affected hoga\n    #       \"safe\"     = Safely disable \u2014 performance badhegi\n    #       \"telemetry\"= Microsoft ko data bhejta hai \u2014 disable karo\n    #       \"thirdparty\"= Software ka auto-update/check task\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    TASK_DB = {\n        # \u2500\u2500 DANGER \u2014 kabhi mat chhuo \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        r\"\\Microsoft\\Windows\\UpdateOrchestrator\\Schedule Scan\":\n            (\"danger\", False, \"Windows Update scan \u2014 disable karne se security patches nahi aayenge. Bahut zaroori hai.\"),\n        r\"\\Microsoft\\Windows\\WindowsUpdate\\Scheduled Start\":\n            (\"danger\", False, \"Windows Update start task \u2014 disable = updates nahi hoge, security risk.\"),\n        r\"\\Microsoft\\Windows\\Defrag\\ScheduledDefrag\":\n            (\"caution\", True, \"HDD defragmentation \u2014 SSD pe disable karo (SSD ko defrag ki zarurat nahi). HDD pe rakho.\"),\n        r\"\\Microsoft\\Windows\\Diagnosis\\Scheduled\":\n            (\"caution\", True, \"Windows auto-diagnosis \u2014 system problems detect karta hai. Home pe safe to disable.\"),\n        r\"\\Microsoft\\Windows\\Chkdsk\\ProactiveScan\":\n            (\"caution\", True, \"Disk error check \u2014 SSD pe disable karo. HDD pe useful hai.\"),\n        r\"\\Microsoft\\Windows\\MemoryDiagnostic\\ProcessMemoryDiagnosticEvents\":\n            (\"caution\", True, \"RAM diagnostic events \u2014 home use pe disable kar sakte ho.\"),\n        r\"\\Microsoft\\Windows\\MemoryDiagnostic\\RunFullMemoryDiagnostic\":\n            (\"caution\", True, \"Full RAM scan \u2014 randomly chalta hai, system slow karta hai. Disable safe hai.\"),\n        # \u2500\u2500 TELEMETRY \u2014 Microsoft ko data bhejta hai \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        r\"\\Microsoft\\Windows\\Application Experience\\Microsoft Compatibility Appraiser\":\n            (\"telemetry\", True, \"CompatTelRunner.exe \u2014 CPU 100% kar deta hai! Microsoft ko compatibility data bhejta hai. DISABLE KARO.\"),\n        r\"\\Microsoft\\Windows\\Application Experience\\ProgramDataUpdater\":\n            (\"telemetry\", True, \"Application Experience data Microsoft ko bhejta hai. Disable karo.\"),\n        r\"\\Microsoft\\Windows\\Application Experience\\StartupAppTask\":\n            (\"telemetry\", True, \"Startup apps track karta hai \u2014 disable safe hai.\"),\n        r\"\\Microsoft\\Windows\\Application Experience\\AitAgent\":\n            (\"telemetry\", True, \"Application Impact Telemetry \u2014 Microsoft ko usage data bhejta hai. Disable karo.\"),\n        r\"\\Microsoft\\Windows\\Autochk\\Proxy\":\n            (\"telemetry\", True, \"AutoChk telemetry proxy \u2014 Microsoft ko data bhejta hai. Disable karo.\"),\n        r\"\\Microsoft\\Windows\\Customer Experience Improvement Program\\Consolidator\":\n            (\"telemetry\", True, \"CEIP data collector \u2014 Microsoft ko aapka usage data bhejta hai. Disable karo.\"),\n        r\"\\Microsoft\\Windows\\Customer Experience Improvement Program\\KernelCeipTask\":\n            (\"telemetry\", True, \"Kernel level CEIP \u2014 system ke andar se data collect karta hai. Disable karo.\"),\n        r\"\\Microsoft\\Windows\\Customer Experience Improvement Program\\UsbCeip\":\n            (\"telemetry\", True, \"USB devices ka usage data bhejta hai Microsoft ko. Disable karo.\"),\n        r\"\\Microsoft\\Windows\\Customer Experience Improvement Program\\Uploader\":\n            (\"telemetry\", True, \"CEIP data upload task \u2014 internet bandwidth use karta hai. Disable karo.\"),\n        r\"\\Microsoft\\Windows\\DiskFootprint\\Diagnostics\":\n            (\"telemetry\", True, \"Disk usage diagnostics data bhejta hai. Disable karo.\"),\n        r\"\\Microsoft\\Windows\\Feedback\\Siuf\\DmClient\":\n            (\"telemetry\", True, \"Windows Feedback \u2014 aapke opinions collect karta hai Microsoft ke liye. Disable karo.\"),\n        r\"\\Microsoft\\Windows\\Feedback\\Siuf\\DmClientOnScenarioDownload\":\n            (\"telemetry\", True, \"Feedback scenario download \u2014 disable karo.\"),\n        r\"\\Microsoft\\Windows\\NetTrace\\GatherNetworkInfo\":\n            (\"telemetry\", True, \"Network diagnostics data collect karta hai. Disable karo.\"),\n        r\"\\Microsoft\\Windows\\Power Efficiency Diagnostics\\AnalyzeSystem\":\n            (\"telemetry\", True, \"Power usage analysis \u2014 battery/power data bhejta hai. Disable karo.\"),\n        r\"\\Microsoft\\Windows\\Shell\\FamilySafetyMonitor\":\n            (\"telemetry\", True, \"Family Safety monitoring \u2014 use nahi karte to disable karo.\"),\n        r\"\\Microsoft\\Windows\\Shell\\FamilySafetyRefresh\":\n            (\"telemetry\", True, \"Family Safety data refresh \u2014 disable karo.\"),\n        r\"\\Microsoft\\Windows\\WS\\WSTask\":\n            (\"telemetry\", True, \"Windows Store telemetry \u2014 disable karo.\"),\n        # \u2500\u2500 SAFE TO DISABLE \u2014 performance badhegi \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        r\"\\Microsoft\\Windows\\DiskCleanup\\SilentCleanup\":\n            (\"safe\", True, \"Background disk cleanup \u2014 randomly disk scan karta hai, disk I/O badh jaati hai. Disable karo, manual cleanup use karo.\"),\n        r\"\\Microsoft\\Windows\\Maintenance\\WinSAT\":\n            (\"safe\", True, \"Windows System Assessment Tool \u2014 PC benchmark \u2014 randomly chalta hai, resources waste karta hai. Disable karo.\"),\n        r\"\\Microsoft\\Windows\\Maps\\MapsUpdateTask\":\n            (\"safe\", True, \"Windows Maps offline update \u2014 maps use nahi karte to disable karo.\"),\n        r\"\\Microsoft\\Windows\\Maps\\MapsToastTask\":\n            (\"safe\", True, \"Maps toast notification \u2014 disable karo.\"),\n        r\"\\Microsoft\\Windows\\Offline Files\\Background Synchronization\":\n            (\"safe\", True, \"Offline file sync \u2014 network shared files use nahi karte to disable karo.\"),\n        r\"\\Microsoft\\Windows\\Offline Files\\Logon Synchronization\":\n            (\"safe\", True, \"Offline files login sync \u2014 home PC pe disable karo.\"),\n        r\"\\Microsoft\\Windows\\RemoteAssistance\\RemoteAssistanceTask\":\n            (\"safe\", True, \"Remote Assistance \u2014 koi aapke PC par remotely connect nahi karta to disable karo.\"),\n        r\"\\Microsoft\\Windows\\RetailDemo\\CleanupOfflineContent\":\n            (\"safe\", True, \"Retail Demo cleanup \u2014 shop display ke liye hai. Home PC pe immediately disable karo.\"),\n        r\"\\Microsoft\\Windows\\SettingSync\\BackgroundUploadTask\":\n            (\"safe\", True, \"Settings cloud sync \u2014 OneDrive/Microsoft account sync. Privacy ke liye disable karo.\"),\n        r\"\\Microsoft\\Windows\\SettingSync\\NetworkStateChangeTask\":\n            (\"safe\", True, \"Settings sync on network change \u2014 disable karo.\"),\n        r\"\\Microsoft\\Windows\\FileHistory\\File History (maintenance mode)\":\n            (\"safe\", True, \"File History maintenance \u2014 use nahi karte to disable karo.\"),\n        r\"\\Microsoft\\Windows\\Ras\\MobilityManager\":\n            (\"safe\", True, \"Mobile broadband manager \u2014 WiFi/ethernet use karte ho to disable karo.\"),\n        r\"\\Microsoft\\Windows\\Location\\Notifications\":\n            (\"safe\", True, \"Location notifications \u2014 privacy ke liye disable karo.\"),\n        r\"\\Microsoft\\Windows\\Location\\WindowsActionDialog\":\n            (\"safe\", True, \"Location access dialog \u2014 disable karo.\"),\n        r\"\\Microsoft\\Windows\\.NET Framework\\.NET Framework NGEN v4.0.30319\":\n            (\"safe\", True, \".NET optimization \u2014 ek baar chalta hai, phir dobara nahi chahiye. Disable karo.\"),\n        r\"\\Microsoft\\Windows\\.NET Framework\\.NET Framework NGEN v4.0.30319 64\":\n            (\"safe\", True, \".NET 64-bit optimization \u2014 disable karo.\"),\n        r\"\\Microsoft\\Windows\\WDI\\ResolutionHost\":\n            (\"safe\", True, \"Windows Diagnostic Infrastructure \u2014 resource heavy. Disable karo.\"),\n    }\n\n    TASK_CAT_COLOR = {\n        \"danger\":     \"#FF4444\",\n        \"caution\":    \"#FF9800\",\n        \"safe\":       \"#4CAF50\",\n        \"telemetry\":  \"#CE93D8\",\n        \"thirdparty\": \"#64B5F6\",\n    }\n    TASK_CAT_ICON = {\n        \"danger\":\"\ud83d\udd34\",\"caution\":\"\ud83d\udfe0\",\"safe\":\"\ud83d\udfe2\",\"telemetry\":\"\ud83d\udfe3\",\"thirdparty\":\"\ud83d\udd35\"\n    }\n\n    # \u2500\u2500 Preset packs \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    TASK_PRESETS = {\n        \"\u26a1 Telemetry Pack (Privacy)\": {\n            \"desc\": \"Saari Microsoft telemetry tasks disable ho jaayengi \u2014 privacy behtar hogi, CPU spikes khatam.\",\n            \"cats\": {\"telemetry\"}\n        },\n        \"\ud83d\ude80 Performance Pack\": {\n            \"desc\": \"Performance wali tasks disable \u2014 DiskCleanup, WinSAT, .NET NGEN, offline sync sab band.\",\n            \"cats\": {\"safe\"}\n        },\n        \"\u2622\ufe0f Full Nuke (Telemetry + Safe)\": {\n            \"desc\": \"Sabse aggressive \u2014 telemetry + safe tasks dono disable. Maximum performance.\",\n            \"cats\": {\"telemetry\",\"safe\"}\n        },\n    }\n\n    def _build_scheduler(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udcc5 Smart Task Scheduler\",\n                             \"Color-coded \u2014 Danger / Caution / Safe / Telemetry / 3rd Party\")\n\n        # \u2500\u2500 Compact top toolbar (1 row: buttons + filter + legend inline) \u2500\u2500\n        toolbar = tk.Frame(frame, bg=C[\"card\"])\n        toolbar.pack(fill=\"x\", padx=0, pady=0)\n\n        # Action buttons \u2014 inline, compact\n        btn_row = tk.Frame(toolbar, bg=C[\"card\"])\n        btn_row.pack(fill=\"x\", padx=10, pady=4)\n\n        for txt, color, cmd in [\n            (\"\ud83d\udd0d Scan Tasks\",      C[\"btn_info\"],   self._scan_tasks),\n            (\"\u26d4 Disable\",         C[\"btn_warn\"],   self._task_disable_safe),\n            (\"\u2705 Enable\",          C[\"btn\"],        lambda: self._with_confirm(\"Enable Tasks\",\"Enable selected tasks?\", self._enable_task)),\n            (\"\ud83d\uddd1 Delete\",          C[\"btn_danger\"], self._task_delete_safe),\n            (\"\ud83d\udcbe Backup\",          C[\"btn_chip\"],   self._backup_tasks),\n            (\"\ud83d\udd12 Telemetry Pack\",  C[\"btn_hw\"],     lambda: self._apply_task_preset(self.TASK_PRESETS[\"\u26a1 Telemetry Pack (Privacy)\"])),\n            (\"\ud83d\ude80 Perf Pack\",       C[\"btn_hw\"],     lambda: self._apply_task_preset(self.TASK_PRESETS[\"\ud83d\ude80 Performance Pack\"])),\n            (\"\u2622 Full Nuke\",        C[\"btn_hw\"],     lambda: self._apply_task_preset(self.TASK_PRESETS[\"\u2622\ufe0f Full Nuke (Telemetry + Safe)\"])),\n        ]:\n            tk.Button(btn_row, text=txt, font=FONTS[\"small\"], bg=color,\n                      fg=C[\"text\"], bd=0, padx=9, pady=4, cursor=\"hand2\",\n                      command=cmd).pack(side=\"left\", padx=2)\n\n        # \u2500\u2500 Compact: filter + stat counts + legend \u2014 single row \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        mid = tk.Frame(frame, bg=C[\"bg\"])\n        mid.pack(fill=\"x\", padx=10, pady=(2,0))\n\n        # Filter\n        tk.Label(mid, text=\"\ud83d\udd0e\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"]).pack(side=\"left\", padx=(4,2))\n        self.task_search = tk.Entry(mid, width=16, font=FONTS[\"small\"],\n                                    bg=C[\"card\"], fg=C[\"text\"],\n                                    insertbackground=C[\"text\"], relief=\"flat\", bd=3)\n        self.task_search.pack(side=\"left\", padx=(0,4))\n        self.task_search.bind(\"\", self._filter_tasks)\n\n        for lbl, val in [(\"All\",\"all\"),(\"\ud83d\udd34\",\"danger\"),(\"\ud83d\udfe0\",\"caution\"),\n                         (\"\ud83d\udfe2\",\"safe\"),(\"\ud83d\udfe3\",\"telemetry\"),(\"\ud83d\udd35\",\"thirdparty\"),(\"\u26a0\",\"highcpu\")]:\n            tk.Button(mid, text=lbl, font=FONTS[\"small\"],\n                      bg=C[\"card\"], fg=C[\"text\"], bd=0, padx=5, pady=2,\n                      cursor=\"hand2\",\n                      command=lambda v=val: self._filter_task_cat(v)).pack(side=\"left\", padx=1)\n\n        # Stat counts inline\n        tk.Frame(mid, bg=C[\"border\"], width=1).pack(side=\"left\", fill=\"y\", padx=6)\n        self.task_stat_vars = {}\n        for k, lbl, col in [\n            (\"danger\",\"\ud83d\udd34 Danger\",\"#FF4444\"),(\"caution\",\"\ud83d\udfe0 Caution\",\"#FF9800\"),\n            (\"safe\",\"\ud83d\udfe2 Safe\",\"#4CAF50\"),(\"telemetry\",\"\ud83d\udfe3 Telem\",\"#CE93D8\"),\n            (\"thirdparty\",\"\ud83d\udd35 3rd\",\"#64B5F6\"),(\"total\",\"Total\",C[\"accent\"]),\n        ]:\n            v = tk.StringVar(value=\"--\")\n            self.task_stat_vars[k] = v\n            f = tk.Frame(mid, bg=C[\"card\"], padx=5, pady=2)\n            f.pack(side=\"left\", padx=2)\n            tk.Label(f, text=lbl, font=(FONTS[\"small\"][0], 7), fg=col, bg=C[\"card\"]).pack()\n            tk.Label(f, textvariable=v, font=(FONTS[\"small\"][0], 9, \"bold\"), fg=col, bg=C[\"card\"]).pack()\n\n        self.task_count_lbl = tk.Label(mid, text=\"\", font=FONTS[\"small\"],\n                                        fg=C[\"accent\"], bg=C[\"bg\"])\n        self.task_count_lbl.pack(side=\"right\", padx=8)\n\n        # \u2500\u2500 Full-width task list \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        list_frame = tk.Frame(frame, bg=C[\"card\"])\n        list_frame.pack(fill=\"both\", expand=True, padx=16, pady=(4,0))\n        list_frame.rowconfigure(0, weight=1)\n        list_frame.columnconfigure(0, weight=1)\n\n        cols = (\"Cat\",\"Task Name\",\"Path\",\"Status\",\"Last Run\",\"Safe?\")\n        self.task_tree = ttk.Treeview(list_frame, columns=cols, show=\"headings\",\n                                      height=28, style=\"Custom.Treeview\",\n                                      selectmode=\"extended\")\n        widths = [28, 280, 340, 80, 120, 65]\n        for col, w in zip(cols, widths):\n            self.task_tree.heading(col, text=col,\n                                   command=lambda c=col: self._sort_tasks(c))\n            self.task_tree.column(col, width=w,\n                                  anchor=\"center\" if col in (\"Cat\",\"Status\",\"Safe?\") else \"w\")\n        for cat, color in self.TASK_CAT_COLOR.items():\n            self.task_tree.tag_configure(cat, foreground=color)\n        self.task_tree.tag_configure(\"highcpu\", background=\"#2A1500\")\n        vsb = ttk.Scrollbar(list_frame, orient=\"vertical\", command=self.task_tree.yview)\n        hsb = ttk.Scrollbar(list_frame, orient=\"horizontal\", command=self.task_tree.xview)\n        self.task_tree.configure(yscrollcommand=vsb.set, xscrollcommand=hsb.set)\n        self.task_tree.grid(row=0, column=0, sticky=\"nsew\", padx=(4,0), pady=(4,0))\n        vsb.grid(row=0, column=1, sticky=\"ns\", pady=(4,0))\n        hsb.grid(row=1, column=0, sticky=\"ew\", padx=(4,0))\n        self.task_tree.bind(\"&lt;&gt;\", self._on_task_select)\n\n        # \u2500\u2500 Bottom collapsible detail + action log strip \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        bot = tk.Frame(frame, bg=C[\"panel\"])\n        bot.pack(fill=\"x\", padx=16, pady=(2,8))\n        bot.columnconfigure(0, weight=3)\n        bot.columnconfigure(1, weight=1)\n\n        # Detail box (left-bottom)\n        detail_wrap = tk.Frame(bot, bg=C[\"card\"])\n        detail_wrap.grid(row=0, column=0, sticky=\"nsew\", padx=(0,4), pady=4)\n        detail_wrap.rowconfigure(1, weight=1)\n        detail_wrap.columnconfigure(0, weight=1)\n\n        hdr_d = tk.Frame(detail_wrap, bg=C[\"card\"])\n        hdr_d.grid(row=0, column=0, sticky=\"ew\", padx=6, pady=(4,2))\n        tk.Label(hdr_d, text=\"  \ud83d\udccb Task Detail &amp; Risk Info\",\n                 font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\")\n        tk.Label(hdr_d, text=\"(koi bhi task click karo \u2014 detail yahan dikhe gi)\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\", padx=6)\n\n        self.task_detail = scrolledtext.ScrolledText(\n            detail_wrap, font=(\"Consolas\", 9), bg=\"#0D1117\", fg=C[\"text\"],\n            height=8, bd=0, relief=\"flat\", state=\"disabled\", wrap=\"word\")\n        self.task_detail.grid(row=1, column=0, sticky=\"nsew\", padx=6, pady=(0,4))\n\n        # Action log (right-bottom)\n        log_wrap = tk.Frame(bot, bg=C[\"card\"])\n        log_wrap.grid(row=0, column=1, sticky=\"nsew\", padx=(4,0), pady=4)\n        log_wrap.rowconfigure(1, weight=1)\n        log_wrap.columnconfigure(0, weight=1)\n        tk.Label(log_wrap, text=\"  \ud83d\udcdd Action Log\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).grid(\n                 row=0, column=0, sticky=\"w\", padx=6, pady=(4,2))\n        self.task_action_log = scrolledtext.ScrolledText(\n            log_wrap, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"],\n            insertbackground=C[\"text\"], height=8, bd=0, wrap=\"word\",\n            relief=\"flat\", state=\"disabled\")\n        self.task_action_log.grid(row=1, column=0, sticky=\"nsew\", padx=6, pady=(0,4))\n\n        # Internal state\n        self._task_all_rows = []\n        self._task_cur_cat = \"all\"\n        self._task_sort_col = \"\"\n        self._task_sort_rev = False\n        return frame\n\n    def _scan_tasks(self):\n        self._set_status(\"Scanning scheduled tasks...\", C[\"accent4\"])\n        if hasattr(self, \"_task_scan_status\"):\n            self._task_scan_status.config(text=\"  \u23f3 Scan chal rahi hai...\", fg=C[\"accent4\"])\n        self._launch_job(\"scan_tasks\", self._do_scan_tasks)\n\n    def _do_scan_tasks_legacy(self):\n        self.after(0, lambda: [self.task_tree.delete(i) for i in self.task_tree.get_children()])\n\n        # schtasks /query /fo CSV /v \u2014 fastest method\n        out, _ = self._run_cmd('schtasks /query /fo CSV /v', timeout=25)\n\n        # Third-party path indicators\n        THIRD_PARTY_ROOTS = {\n            \"google\",\"mozilla\",\"adobe\",\"java\",\"dropbox\",\"spotify\",\"discord\",\n            \"steam\",\"nvidia\",\"amd\",\"intel\",\"realtek\",\"logitech\",\"corsair\",\n            \"razer\",\"zoom\",\"teams\",\"skype\",\"ccleaner\",\"iobit\",\"malwarebytes\",\n            \"avast\",\"avg\",\"kaspersky\",\"mcafee\",\"norton\",\"bitdefender\",\n        }\n\n        counts = {k:0 for k in (\"danger\",\"caution\",\"safe\",\"telemetry\",\"thirdparty\",\"total\")}\n        seen   = set()\n        rows   = []\n\n        for line in out.splitlines():\n            line = line.strip().replace('\"','')\n            parts = line.split(',')\n            if len(parts) &lt; 7 or parts[0] == \"TaskName\":\n                continue\n            task_full = parts[0].strip()\n            status    = parts[3].strip() if len(parts) &gt; 3 else \"\"\n            last_run  = parts[5].strip() if len(parts) &gt; 5 else \"\"\n            if not task_full or task_full in seen:\n                continue\n            seen.add(task_full)\n\n            # Path split\n            if \"\\\\\" in task_full:\n                tpath = task_full.rsplit(\"\\\\\",1)[0] + \"\\\\\"\n                tname = task_full.rsplit(\"\\\\\",1)[1]\n            else:\n                tpath = \"\\\\\"\n                tname = task_full\n\n            if not tname:\n                continue\n\n            # Lookup DB\n            if task_full in self.TASK_DB:\n                cat, safe, desc = self.TASK_DB[task_full]\n            else:\n                tpath_low = tpath.lower()\n                tname_low = tname.lower()\n                full_low  = task_full.lower()\n                is_third = any(tp in full_low for tp in THIRD_PARTY_ROOTS)\n                if is_third:\n                    cat  = \"thirdparty\"\n                    safe = True\n                    desc = (f\"'{tname}' \u2014 Third-party software task.\\n\"\n                            \"Agar woh software use karte ho: disable mat karo.\\n\"\n                            \"Agar uninstall ho gaya: disable kar sakte ho.\")\n                elif \"\\\\microsoft\\\\windows\\\\\" in full_low:\n                    # Skip system tasks not in DB \u2014 they're likely safe/necessary\n                    if status.lower() == \"disabled\":\n                        continue\n                    cat  = \"caution\"\n                    safe = False\n                    desc = (f\"'{tname}' \u2014 Windows system task (hamare database mein nahi).\\n\"\n                            \"Google karo pehle, phir decide karo.\")\n                else:\n                    cat  = \"safe\"\n                    safe = True\n                    desc = (f\"'{tname}' \u2014 Unknown task, root folder mein hai.\\n\"\n                            \"Likely kisi software ka task hai. Safe to disable if unrecognized.\")\n\n            if status.lower() == \"disabled\":\n                continue\n\n            icon = self.TASK_CAT_ICON.get(cat,\"\u26aa\")\n            safe_txt = \"\u2705\" if safe else \"\u274c\"\n            row = (icon, tname, tpath, status, last_run[:16], safe_txt)\n            meta = {\"cat\":cat,\"safe\":safe,\"desc\":desc,\n                    \"full\":task_full,\"name\":tname,\"path\":tpath,\"status\":status,\n                    \"last_run\":last_run[:16] if last_run else \"N/A\"}\n            rows.append((row, (cat,), meta))\n            if cat in counts:\n                counts[cat] += 1\n            counts[\"total\"] += 1\n\n        self._task_all_rows = rows\n\n        def insert():\n            self._render_task_rows(rows)\n            for k,v in counts.items():\n                if k in self.task_stat_vars:\n                    self.task_stat_vars[k].set(str(v))\n            self._set_status(\n                f\"Scan done \u2014 {counts['total']} tasks | \"\n                f\"\ud83d\udfe3{counts['telemetry']} Telemetry | \"\n                f\"\ud83d\udfe2{counts['safe']} Safe | \"\n                f\"\ud83d\udfe0{counts['caution']} Caution | \"\n                f\"\ud83d\udd35{counts['thirdparty']} 3rd-Party\",\n                C[\"success\"])\n            if hasattr(self, \"_task_scan_status\"):\n                self._task_scan_status.config(\n                    text=f\"  \u2705 {counts['total']} tasks mile \u2014 task pe click karo detail dekhne ke liye\",\n                    fg=C[\"success\"])\n        self.after(0, insert)\n\n    def _do_scan_tasks(self):\n        self.after(0, lambda: [self.task_tree.delete(i) for i in self.task_tree.get_children()])\n        out, _ = self._run_cmd('schtasks /query /fo CSV /v', timeout=25)\n        third_party_roots = {\n            \"google\",\"mozilla\",\"adobe\",\"java\",\"dropbox\",\"spotify\",\"discord\",\n            \"steam\",\"nvidia\",\"amd\",\"intel\",\"realtek\",\"logitech\",\"corsair\",\n            \"razer\",\"zoom\",\"teams\",\"skype\",\"ccleaner\",\"iobit\",\"malwarebytes\",\n            \"avast\",\"avg\",\"kaspersky\",\"mcafee\",\"norton\",\"bitdefender\",\n        }\n        counts = {k: 0 for k in (\"danger\",\"caution\",\"safe\",\"telemetry\",\"thirdparty\",\"total\")}\n        seen = set()\n        rows = []\n        for record in self._task_records_from_schtasks(out):\n            task_full = (record.get(\"TaskName\") or record.get(\"Task Name\") or \"\").strip()\n            scheduled_state = (record.get(\"Scheduled Task State\") or \"\").strip()\n            status = (record.get(\"Status\") or scheduled_state or \"\").strip()\n            last_run = (record.get(\"Last Run Time\") or record.get(\"LastRunTime\") or \"\").strip()\n            run_cmd = (record.get(\"Task To Run\") or \"\").strip()\n            if not task_full or task_full in seen:\n                continue\n            seen.add(task_full)\n            if \"\\\\\" in task_full:\n                tpath = task_full.rsplit(\"\\\\\", 1)[0] + \"\\\\\"\n                tname = task_full.rsplit(\"\\\\\", 1)[1]\n            else:\n                tpath = \"\\\\\"\n                tname = task_full\n            if not tname:\n                continue\n            if task_full in self.TASK_DB:\n                cat, safe, desc = self.TASK_DB[task_full]\n            else:\n                full_low = task_full.lower()\n                is_third = any(tp in full_low for tp in third_party_roots)\n                if is_third:\n                    cat = \"thirdparty\"\n                    safe = True\n                    desc = (f\"'{tname}' - Third-party software task.\\n\"\n                            \"Agar woh software use karte ho: disable mat karo.\\n\"\n                            \"Agar uninstall ho gaya: disable kar sakte ho.\")\n                elif \"\\\\microsoft\\\\windows\\\\\" in full_low:\n                    if status.lower() == \"disabled\" or scheduled_state.lower() == \"disabled\":\n                        continue\n                    cat = \"caution\"\n                    safe = False\n                    desc = (f\"'{tname}' - Windows system task (database mein nahi).\\n\"\n                            \"Google karo pehle, phir decide karo.\")\n                else:\n                    cat = \"safe\"\n                    safe = True\n                    desc = (f\"'{tname}' - Unknown task, root folder mein hai.\\n\"\n                            \"Likely kisi software ka task hai. Safe to disable if unrecognized.\")\n            if status.lower() == \"disabled\" or scheduled_state.lower() == \"disabled\":\n                continue\n            icon = self.TASK_CAT_ICON.get(cat, \"*\")\n            safe_txt = \"\u2705\" if safe else \"\u274c\"\n            row = (icon, tname, tpath, status, last_run[:16], safe_txt)\n            meta = {\"cat\": cat, \"safe\": safe, \"desc\": desc,\n                    \"full\": task_full, \"name\": tname, \"path\": tpath, \"status\": status,\n                    \"last_run\": last_run[:16] if last_run else \"N/A\",\n                    \"run_cmd\": run_cmd or \"N/A\",\n                    \"scheduled_state\": scheduled_state or \"N/A\"}\n            rows.append((row, (cat,), meta))\n            if cat in counts:\n                counts[cat] += 1\n            counts[\"total\"] += 1\n        self._task_all_rows = rows\n\n        def insert():\n            self._render_task_rows(rows)\n            for k, v in counts.items():\n                if k in self.task_stat_vars:\n                    self.task_stat_vars[k].set(str(v))\n            self._set_status(\n                f\"Scan done - {counts['total']} tasks | \"\n                f\"{counts['telemetry']} Telemetry | \"\n                f\"{counts['safe']} Safe | \"\n                f\"{counts['caution']} Caution | \"\n                f\"{counts['thirdparty']} 3rd-Party\",\n                C[\"success\"])\n            if hasattr(self, \"_task_scan_status\"):\n                self._task_scan_status.config(\n                    text=f\"  {counts['total']} tasks mile - task pe click karo detail dekhne ke liye\",\n                    fg=C[\"success\"])\n        self.after(0, insert)\n\n    def _render_task_rows(self, rows):\n        for i in self.task_tree.get_children():\n            self.task_tree.delete(i)\n        for row, tags, _ in rows:\n            self.task_tree.insert(\"\",\"end\", values=row, tags=tags)\n        self.task_count_lbl.config(text=f\"{len(rows)} tasks\")\n\n    def _filter_tasks(self, event=None):\n        txt = self.task_search.get().lower() if hasattr(self,\"task_search\") else \"\"\n        cat = self._task_cur_cat\n        filtered = [r for r in self._task_all_rows\n                    if (cat==\"all\" or cat in r[1])\n                    and (not txt or txt in r[2][\"name\"].lower()\n                         or txt in r[2][\"path\"].lower())]\n        self._render_task_rows(filtered)\n\n    def _filter_task_cat(self, cat):\n        self._task_cur_cat = cat\n        self._filter_tasks()\n\n    def _sort_tasks(self, col):\n        col_map = {\"Cat\":0,\"Task Name\":1,\"Path\":2,\"Status\":3,\"Last Run\":4,\"Safe?\":5}\n        idx = col_map.get(col,1)\n        if self._task_sort_col == col:\n            self._task_sort_rev = not self._task_sort_rev\n        else:\n            self._task_sort_col = col\n            self._task_sort_rev = False\n        self._task_all_rows.sort(key=lambda r: r[0][idx], reverse=self._task_sort_rev)\n        self._filter_tasks()\n\n    def _on_task_select(self, event=None):\n        sel = self.task_tree.selection()\n        if not sel:\n            return\n        iid = sel[0]\n        idx = self.task_tree.index(iid)\n        visible = self._get_visible_task_rows()\n        if idx &gt;= len(visible):\n            return\n        meta = visible[idx][2]\n        cat  = meta[\"cat\"]\n        safe = meta[\"safe\"]\n        desc = meta[\"desc\"]\n        icon = self.TASK_CAT_ICON.get(cat,\"\u26aa\")\n        col  = self.TASK_CAT_COLOR.get(cat, C[\"text\"])\n\n        cat_label = {\n            \"danger\":    \"\ud83d\udd34 DANGER \u2014 Kabhi disable mat karo\",\n            \"caution\":   \"\ud83d\udfe0 CAUTION \u2014 Soch ke disable karo\",\n            \"safe\":      \"\ud83d\udfe2 SAFE \u2014 Disable karne se performance badhegi\",\n            \"telemetry\": \"\ud83d\udfe3 TELEMETRY \u2014 Microsoft ko data bhejta hai\",\n            \"thirdparty\":\"\ud83d\udd35 THIRD-PARTY \u2014 Software ka task\",\n        }.get(cat,\"\u26aa Unknown\")\n\n        risk_box = {\n            \"danger\":   (\"\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\\n\"\n                         \"\u2551 \u26d4 DISABLE MAT KARO \u2014 SYSTEM TOOTEGA \u2551\\n\"\n                         \"\u255a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255d\\n\"),\n            \"caution\":  \"\u26a0\ufe0f  SAWDHAN \u2014 Pehle Google karo, phir disable karo.\\n\",\n            \"safe\":     \"\u2705 DISABLE KARO \u2014 Safe hai, performance badhegi.\\n\",\n            \"telemetry\":(\"\ud83d\udfe3 DISABLE KARO \u2014 Ye task Microsoft ko aapka data bhejta hai.\\n\"\n                         \"   Privacy aur CPU ke liye disable karna better hai.\\n\"),\n            \"thirdparty\":(\"\ud83d\udd35 THIRD-PARTY \u2014 Agar software use karte ho: chhodo.\\n\"\n                          \"   Agar software remove ho gaya: Disable karo.\\n\"),\n        }.get(cat,\"\")\n\n        lines = [\n            f\"Task Name  : {meta['name']}\",\n            f\"Full Path  : {meta['full']}\",\n            f\"Category   : {cat_label}\",\n            f\"Status     : {meta['status']}\",\n            f\"Process    : {meta.get('run_cmd', 'N/A')}\",\n            f\"Last Run   : {meta.get('last_run', 'N/A')}\",\n            f\"Safe Disable: {'\u2705 Haan' if safe else '\u274c Nahi'}\",\n            \"\", \"\u2500\"*52, \"\",\n            \"\ud83d\udcd6 DESCRIPTION:\",\n            desc,\n            \"\", \"\u2500\"*52, \"\",\n            \"\u26a0\ufe0f  DISABLE KARNE SE KYA HOGA:\",\n            risk_box,\n            \"\ud83d\udca1 TIP:\",\n            {\n                \"danger\":    \"Isko chhod do \u2014 Windows ke kaam ka hai.\",\n                \"caution\":   \"SSD pe defrag/chkdsk disable karo \u2014 warna safe mat karo.\",\n                \"safe\":      f\"schtasks /Change /TN \\\"{meta['full']}\\\" /Disable\",\n                \"telemetry\": f\"schtasks /Change /TN \\\"{meta['full']}\\\" /Disable\",\n                \"thirdparty\":\"Software se hi manage karo ya uninstall karo.\",\n            }.get(cat,\"\"),\n        ]\n\n        self.task_detail.config(state=\"normal\")\n        self.task_detail.delete(\"1.0\",\"end\")\n        self.task_detail.tag_configure(\"red\",    foreground=\"#FF4444\")\n        self.task_detail.tag_configure(\"orange\", foreground=\"#FF9800\")\n        self.task_detail.tag_configure(\"green\",  foreground=\"#4CAF50\")\n        self.task_detail.tag_configure(\"purple\", foreground=\"#CE93D8\")\n        self.task_detail.tag_configure(\"blue\",   foreground=\"#64B5F6\")\n        self.task_detail.tag_configure(\"dim\",    foreground=\"#A0B0C8\")\n        for line in lines:\n            tag = \"dim\"\n            if \"DISABLE MAT\" in line or \"\u26d4\" in line: tag = \"red\"\n            elif \"SAWDHAN\" in line or \"\u26a0\ufe0f\" in line:   tag = \"orange\"\n            elif \"\u2705\" in line and \"DISABLE KARO\" in line: tag = \"green\"\n            elif \"\ud83d\udfe3\" in line:                         tag = \"purple\"\n            elif \"\ud83d\udd35\" in line:                         tag = \"blue\"\n            elif line.startswith(\"\u2500\"):                 tag = \"dim\"\n            elif line.startswith(\"Task\") or line.startswith(\"Full\") or line.startswith(\"Status\"): tag = \"dim\"\n            self.task_detail.insert(\"end\", line+\"\\n\", tag)\n        self.task_detail.config(state=\"disabled\")\n\n    def _get_visible_task_rows(self):\n        cat = self._task_cur_cat\n        txt = self.task_search.get().lower() if hasattr(self,\"task_search\") else \"\"\n        rows = self._task_all_rows\n        if cat != \"all\":\n            rows = [r for r in rows if cat in r[1]]\n        if txt:\n            rows = [r for r in rows\n                    if txt in r[2][\"name\"].lower() or txt in r[2][\"path\"].lower()]\n        return rows\n\n    def _task_disable_safe(self):\n        sel = self.task_tree.selection()\n        if not sel:\n            messagebox.showinfo(\"No Selection\",\"Pehle ek task select karo.\")\n            return\n        visible = self._get_visible_task_rows()\n        block, warn, targets = [], [], []\n        for iid in sel:\n            idx = self.task_tree.index(iid)\n            if idx &gt;= len(visible): continue\n            meta = visible[idx][2]\n            if meta[\"cat\"] == \"danger\" and not meta[\"safe\"]:\n                block.append(f\"  \ud83d\udd34 {meta['name']} \u2014 DANGER!\")\n            elif meta[\"cat\"] == \"caution\":\n                warn.append(f\"  \ud83d\udfe0 {meta['name']} \u2014 Caution task\")\n            targets.append(meta)\n\n        if block:\n            messagebox.showerror(\"\u26d4 KHATARNAK!\",\n                \"Ye tasks KABHI disable mat karo \u2014 system crash ho sakta hai!\\n\\n\"\n                + \"\\n\".join(block) + \"\\n\\nDeselect karo aur dubara try karo.\")\n            return\n        msg = f\"Disable karne se ye {len(targets)} tasks band ho jaayenge:\\n\\n\"\n        msg += \"\\n\".join(f\"  {self.TASK_CAT_ICON.get(t['cat'],'\u2022')} {t['name']}\" for t in targets[:15])\n        if len(targets) &gt; 15:\n            msg += f\"\\n  ...aur {len(targets)-15} aur\"\n        if warn:\n            msg += \"\\n\\n\u26a0\ufe0f CAUTION tasks included:\\n\" + \"\\n\".join(warn)\n        msg += \"\\n\\nAage badhein?\"\n        if not messagebox.askyesno(\"Confirm Disable\", msg):\n            return\n        disabled = 0\n        for meta in targets:\n            out, rc = self._run_cmd(f'schtasks /Change /TN \"{meta[\"full\"]}\" /Disable')\n            if rc == 0:\n                disabled += 1\n                self._append_log(self.task_action_log, f\"\u2705 Disabled: {meta['name']}\", C[\"success\"])\n            else:\n                self._append_log(self.task_action_log, f\"\u274c Failed: {meta['name']} \u2014 {out[:60]}\", C[\"error\"])\n        self._set_status(f\"Disabled {disabled}/{len(targets)} tasks\", C[\"success\"])\n        self._scan_tasks()\n\n    def _enable_task(self):\n        visible = self._get_visible_task_rows()\n        for iid in self.task_tree.selection():\n            idx = self.task_tree.index(iid)\n            if idx &gt;= len(visible): continue\n            meta = visible[idx][2]\n            self._run_cmd(f'schtasks /Change /TN \"{meta[\"full\"]}\" /Enable')\n            self._append_log(self.task_action_log, f\"\u2705 Enabled: {meta['name']}\", C[\"success\"])\n        self._scan_tasks()\n\n    def _task_delete_safe(self):\n        sel = self.task_tree.selection()\n        if not sel:\n            messagebox.showinfo(\"No Selection\",\"Pehle task select karo.\")\n            return\n        visible = self._get_visible_task_rows()\n        block, targets = [], []\n        for iid in sel:\n            idx = self.task_tree.index(iid)\n            if idx &gt;= len(visible): continue\n            meta = visible[idx][2]\n            if meta[\"cat\"] == \"danger\":\n                block.append(f\"  \ud83d\udd34 {meta['name']}\")\n            else:\n                targets.append(meta)\n        if block:\n            messagebox.showerror(\"\u26d4 KHATARNAK!\",\n                \"Ye tasks DELETE NAHI karne chahiye:\\n\\n\" + \"\\n\".join(block))\n            return\n        if not targets:\n            return\n        if not messagebox.askyesno(\"Confirm DELETE\",\n                f\"Permanently delete {len(targets)} tasks?\\n\"\n                \"\u26a0\ufe0f Delete ke baad wapas nahi aayenge!\\n\\n\"\n                \"Pehle Backup Tasks karo.\"):\n            return\n        for meta in targets:\n            self._run_cmd(f'schtasks /Delete /TN \"{meta[\"full\"]}\" /F')\n            self._append_log(self.task_action_log, f\"\ud83d\uddd1 Deleted: {meta['name']}\", C[\"warning\"])\n        self._scan_tasks()\n\n    def _disable_task(self):\n        visible = self._get_visible_task_rows()\n        for iid in self.task_tree.selection():\n            idx = self.task_tree.index(iid)\n            if idx &gt;= len(visible): continue\n            meta = visible[idx][2]\n            self._run_cmd(f'schtasks /Change /TN \"{meta[\"full\"]}\" /Disable')\n        self._scan_tasks()\n\n    def _delete_task(self):\n        visible = self._get_visible_task_rows()\n        for iid in self.task_tree.selection():\n            idx = self.task_tree.index(iid)\n            if idx &gt;= len(visible): continue\n            meta = visible[idx][2]\n            self._run_cmd(f'schtasks /Delete /TN \"{meta[\"full\"]}\" /F')\n        self._scan_tasks()\n\n    def _apply_task_preset(self, pack):\n        if not self._task_all_rows:\n            messagebox.showinfo(\"Pehle Scan Karo\",\"Pehle 'Scan All Tasks' click karo.\")\n            return\n        cats   = pack[\"cats\"]\n        desc   = pack[\"desc\"]\n        targets = [r[2] for r in self._task_all_rows if r[2][\"cat\"] in cats and r[2][\"safe\"]]\n        if not targets:\n            messagebox.showinfo(\"Koi Task Nahi\",f\"Is preset ke liye koi task nahi mila.\\nPehle Scan karo.\")\n            return\n        msg = (f\"{desc}\\n\\n\"\n               f\"{len(targets)} tasks disable ho jaayengi:\\n\\n\"\n               + \"\\n\".join(f\"  {self.TASK_CAT_ICON.get(t['cat'],'\u2022')} {t['name']}\"\n                            for t in targets[:20])\n               + (f\"\\n  ...aur {len(targets)-20} aur\" if len(targets)&gt;20 else \"\")\n               + \"\\n\\nAage badhein?\")\n        if not messagebox.askyesno(\"Confirm Preset\", msg):\n            return\n        done = 0\n        for meta in targets:\n            out, rc = self._run_cmd(f'schtasks /Change /TN \"{meta[\"full\"]}\" /Disable')\n            if rc == 0:\n                done += 1\n                self._append_log(self.task_action_log, f\"\u2705 {meta['name']}\", C[\"success\"])\n        messagebox.showinfo(\"Done!\",\n            f\"\u2705 {done}/{len(targets)} tasks disable ho gayi!\\nRestart karo best results ke liye.\")\n        self._scan_tasks()\n\n    def _backup_tasks(self):\n        dest = filedialog.asksaveasfilename(\n            title=\"Save Task Backup Script\",\n            defaultextension=\".bat\",\n            filetypes=[(\"Batch File\",\"*.bat\"),(\"All Files\",\"*.*\")],\n            initialfile=\"task_backup_restore.bat\")\n        if not dest:\n            return\n        lines = [\"@echo off\",\"echo Restoring disabled tasks...\",\"\"]\n        for row, tags, meta in self._task_all_rows:\n            lines.append(f'schtasks /Change /TN \"{meta[\"full\"]}\" /Enable')\n        lines += [\"\",\"echo Done! All tasks re-enabled.\",\"pause\"]\n        try:\n            with open(dest,\"w\") as f:\n                f.write(\"\\n\".join(lines))\n            messagebox.showinfo(\"Backup Saved\",\n                f\"\u2705 Restore script saved to:\\n{dest}\\n\\n\"\n                \"Agar kuch galat ho jaaye, is .bat file ko Run as Administrator se chalao.\")\n        except Exception as e:\n            messagebox.showerror(\"Error\", str(e))\n\n    # ---------- REGISTRY TWEAKS (with confirm) ----------\n    def _build_registry(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udccb Registry Tweaks\", \"Safe performance tweaks\")\n        content = tk.Frame(frame, bg=C[\"bg\"])\n        content.pack(fill=\"both\", expand=True, padx=16, pady=10)\n        content.columnconfigure(0, weight=1)\n        content.columnconfigure(1, weight=2)\n        left = tk.Frame(content, bg=C[\"card\"])\n        left.grid(row=0, column=0, sticky=\"nsew\", padx=(0,6))\n        tk.Label(left, text=\"  Tweaks\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8,4), padx=8)\n        for k, label in [\n            (\"visual_fx\", \"Disable Visual Effects\"),\n            (\"menu_delay\", \"Reduce Menu Delay\"),\n            (\"search_idx\", \"Disable Search Indexing\"),\n            (\"telemetry\", \"Minimize Telemetry\"),\n            (\"ntfs_last\", \"Disable Last Access Timestamp\"),\n            (\"autorun\", \"Disable Autorun\"),\n            (\"shutdown_fast\", \"Fast Shutdown Speed\"),\n            (\"extreme_visual\", \"Extreme Visual Effects Off (Aero, Shadows, Animations)\"),\n        ]:\n            var = tk.BooleanVar(value=True)\n            self.reg_vars[k] = var\n            tk.Checkbutton(left, text=f\"  {label}\", variable=var, font=FONTS[\"body\"], fg=C[\"text\"], bg=C[\"card\"], activebackground=C[\"card\"], selectcolor=C[\"panel\"], bd=0).pack(anchor=\"w\", padx=12, pady=2)\n        btn_row = tk.Frame(left, bg=C[\"card\"])\n        btn_row.pack(fill=\"x\", padx=12, pady=10)\n        self._btn(btn_row, \"\u2705 Apply Selected Tweaks\", C[\"btn\"], self._apply_registry).pack(fill=\"x\", pady=2)\n        self._btn(btn_row, \"\ud83d\udcbe Export Backup\", C[\"btn_chip\"], self._export_registry_backup).pack(fill=\"x\", pady=2)\n        self._btn(btn_row, \"\u267b\ufe0f Import .reg\", C[\"btn_warn\"], self._import_registry_backup).pack(fill=\"x\", pady=2)\n        right = tk.Frame(content, bg=C[\"card\"])\n        right.grid(row=0, column=1, sticky=\"nsew\", padx=(6,0))\n        tk.Label(right, text=\"  Registry Dashboard\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8,4), padx=8)\n        self.reg_progress_var = tk.DoubleVar(value=0.0)\n        self.reg_progress_bar = ttk.Progressbar(right, variable=self.reg_progress_var, maximum=100, mode=\"determinate\")\n        self.reg_progress_bar.pack(fill=\"x\", padx=12, pady=(0,6))\n        self.reg_status_lbl = tk.Label(right, text=\"Ready for registry optimization\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"])\n        self.reg_status_lbl.pack(anchor=\"w\", padx=12, pady=(0,8))\n        metrics = tk.Frame(right, bg=C[\"card\"])\n        metrics.pack(fill=\"x\", padx=12, pady=(0,6))\n        self.reg_keys_changed_var = tk.StringVar(value=\"0\")\n        self.reg_predicted_impact_var = tk.StringVar(value=\"--\")\n        self.reg_confidence_var = tk.StringVar(value=\"--\")\n        for label, var, fg in [\n            (\"Keys Changed\", self.reg_keys_changed_var, C[\"accent4\"]),\n            (\"Impact Score\", self.reg_predicted_impact_var, C[\"success\"]),\n            (\"Confidence\", self.reg_confidence_var, C[\"warning\"]),\n        ]:\n            card = tk.Frame(metrics, bg=C[\"bg\"], padx=8, pady=8)\n            card.pack(side=\"left\", fill=\"x\", expand=True, padx=3)\n            tk.Label(card, text=label, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"]).pack(anchor=\"w\")\n            tk.Label(card, textvariable=var, font=(\"Segoe UI\", 14, \"bold\"), fg=fg, bg=C[\"bg\"]).pack(anchor=\"w\")\n        tk.Label(right, text=\"  Startup Audit\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8,4), padx=8)\n        startup_btn_row = tk.Frame(right, bg=C[\"card\"])\n        startup_btn_row.pack(fill=\"x\", padx=12, pady=(0,6))\n        self._btn(startup_btn_row, \"\ud83d\udd04 Refresh Audit\", C[\"btn_info\"], self._refresh_registry_startup).pack(side=\"left\", padx=(0,4))\n        self._btn(startup_btn_row, \"\ud83d\uddd1 Delete Selected\", C[\"btn_danger\"], self._delete_registry_startup_selected).pack(side=\"left\")\n        self.registry_startup_tree = ttk.Treeview(right, columns=(\"Name\", \"Command\", \"Location\", \"Status\"), show=\"headings\", height=8, style=\"Custom.Treeview\")\n        for col, w in ((\"Name\", 180), (\"Command\", 280), (\"Location\", 160), (\"Status\", 80)):\n            self.registry_startup_tree.heading(col, text=col)\n            self.registry_startup_tree.column(col, width=w, anchor=\"w\")\n        vsb = ttk.Scrollbar(right, orient=\"vertical\", command=self.registry_startup_tree.yview)\n        self.registry_startup_tree.configure(yscrollcommand=vsb.set)\n        self.registry_startup_tree.pack(side=\"left\", fill=\"both\", expand=True, padx=(12, 0), pady=(0,8))\n        vsb.pack(side=\"right\", fill=\"y\", padx=(0, 12), pady=(0,8))\n        self._registry_startup_items = {}\n        self._refresh_registry_startup()\n        tk.Label(right, text=\"  Execution Log\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8,4), padx=8)\n        self.reg_log = self._scrolled_text(right, height=16)\n        self.reg_exec_log = self.reg_log\n        return frame\n\n    def _apply_registry(self):\n        def before():\n            return \"Registry changes will be applied. A restore point can be created.\"\n        self._confirm_and_launch_job(\"Registry Tweaks\", \"This will apply selected registry tweaks to improve performance.\\nIt is recommended to create a restore point first (will ask).\",\n                                      before, \"registry_tweaks\", self._do_registry)\n        # Note: _do_registry contains the actual registry changes and also creates restore point inside it.\n\n    def _export_registry_backup(self):\n        folder = filedialog.askdirectory(title=\"Select folder for registry backup\")\n        if not folder:\n            return\n        keys = [\n            r\"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\VisualEffects\",\n            r\"HKCU\\Control Panel\\Desktop\",\n            r\"HKLM\\SOFTWARE\\Policies\\Microsoft\\Windows\\DataCollection\",\n            r\"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer\",\n            r\"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Multimedia\\SystemProfile\",\n        ]\n        try:\n            paths = []\n            for key in keys:\n                safe_key = re.sub(r'[:\\\\]', '_', key)\n                export_path = os.path.join(folder, f\"Godawari_Registry_Backup_{safe_key}.reg\")\n                out, rc = self._run_cmd(f'reg export \"{key}\" \"{export_path}\" /y', timeout=20)\n                if rc != 0:\n                    raise RuntimeError(out.strip() or f\"reg export failed for {key}\")\n                paths.append(export_path)\n            messagebox.showinfo(\"Saved\", f\"Registry backup files exported to:\\n{folder}\")\n            self._append_log(self.reg_log, f\"\ud83d\udcbe Registry backup exported: {', '.join(paths)}\", C[\"success\"])\n        except Exception as e:\n            messagebox.showerror(\"Export Failed\", str(e))\n            self._append_log(self.reg_log, f\"\u274c Registry backup failed: {e}\", C[\"error\"])\n\n    def _import_registry_backup(self):\n        path = filedialog.askopenfilename(filetypes=[(\"Registry files\", \"*.reg\")], title=\"Open Registry Backup\")\n        if not path:\n            return\n        if not messagebox.askyesno(\"Import Registry Backup\", f\"Import registry file? This may change system settings.\\n{path}\"):\n            return\n        out, rc = self._run_cmd(f'reg import \"{path}\"', timeout=30)\n        if rc == 0:\n            messagebox.showinfo(\"Imported\", \"Registry backup imported successfully. Restart recommended.\")\n            self._append_log(self.reg_log, f\"\u2705 Imported registry backup: {path}\", C[\"success\"])\n        else:\n            messagebox.showerror(\"Import Failed\", out[:1000] or \"Unknown error\")\n            self._append_log(self.reg_log, f\"\u274c Registry import failed: {out[:200]}\", C[\"error\"])\n\n    def _do_registry_legacy(self):\n        v = self.reg_vars\n        if v[\"menu_delay\"].get():\n            self._reg_set(winreg.HKEY_CURRENT_USER, r\"Control Panel\\Desktop\", \"MenuShowDelay\", \"0\", winreg.REG_SZ)\n            self._append_log(self.reg_log, \"\u2705 Menu delay 0ms\", C[\"success\"])\n        if v[\"visual_fx\"].get():\n            self._reg_set(winreg.HKEY_CURRENT_USER, r\"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\VisualEffects\", \"VisualFXSetting\", 2, winreg.REG_DWORD)\n            self._append_log(self.reg_log, \"\u2705 Visual effects disabled\", C[\"success\"])\n        if v[\"search_idx\"].get():\n            self._run_cmd('sc config \"WSearch\" start= disabled')\n            self._run_cmd('sc stop \"WSearch\"')\n            self._append_log(self.reg_log, \"\u2705 Search indexing disabled\", C[\"success\"])\n        if v[\"telemetry\"].get():\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Policies\\Microsoft\\Windows\\DataCollection\", \"AllowTelemetry\", 0, winreg.REG_DWORD)\n            self._append_log(self.reg_log, \"\u2705 Telemetry minimized\", C[\"success\"])\n        if v[\"ntfs_last\"].get():\n            self._run_cmd(\"fsutil behavior set disablelastaccess 1\")\n            self._append_log(self.reg_log, \"\u2705 NTFS timestamp disabled\", C[\"success\"])\n        if v[\"autorun\"].get():\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer\", \"NoDriveTypeAutoRun\", 255, winreg.REG_DWORD)\n            self._append_log(self.reg_log, \"\u2705 Autorun disabled\", C[\"success\"])\n        if v.get(\"extreme_visual\") and v[\"extreme_visual\"].get():\n            self._reg_set(winreg.HKEY_CURRENT_USER, r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\VisualEffects\", \"VisualFXSetting\", 2, winreg.REG_DWORD)\n            try:\n                self._reg_set(winreg.HKEY_CURRENT_USER, r\"Control Panel\\Desktop\", \"UserPreferencesMask\", b'\\x9e\\x3e\\x07\\x80\\x12\\x00\\x00\\x00', winreg.REG_BINARY)\n                self._reg_set(winreg.HKEY_CURRENT_USER, r\"Control Panel\\Desktop\", \"MinAnimate\", \"0\", winreg.REG_SZ)\n            except:\n                pass\n            self._append_log(self.reg_log, \"\u2705 Extreme visual effects disabled (Aero, shadows, animations)\", C[\"success\"])\n        self._append_log(self.reg_log, \"\ud83c\udf89 Tweaks applied! Restart recommended.\", C[\"accent\"])\n\n    # ---------- GROUP POLICY (with confirm) ----------\n    def _build_grouppolicy(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udd12 Group Policy Optimizer\", \"Performance policies\")\n        content = tk.Frame(frame, bg=C[\"bg\"])\n        content.pack(fill=\"both\", expand=True, padx=16, pady=10)\n        content.columnconfigure(0, weight=1)\n        content.columnconfigure(1, weight=2)\n        left = tk.Frame(content, bg=C[\"card\"])\n        left.grid(row=0, column=0, sticky=\"nsew\", padx=(0,6))\n        tk.Label(left, text=\"  Policies\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8,4), padx=8)\n        for k, label in [(\"cortana\",\"Disable Cortana\"), (\"ads\",\"Disable Advertising ID\"), (\"consumer\",\"Disable Consumer Features\"), (\"remote\",\"Disable Remote Assistance\")]:\n            var = tk.BooleanVar(value=True)\n            self.gp_vars[k] = var\n            tk.Checkbutton(left, text=f\"  {label}\", variable=var, font=FONTS[\"body\"], fg=C[\"text\"], bg=C[\"card\"], activebackground=C[\"card\"], selectcolor=C[\"panel\"], bd=0).pack(anchor=\"w\", padx=12, pady=2)\n        profile_options = get_group_policy_profiles()\n        self.gp_profile_hint_var = tk.StringVar(value=profile_options[\"Balanced\"][\"summary\"])\n        tk.Label(left, text=\"Quick presets:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=12, pady=(4, 2))\n        profile_bar = tk.Frame(left, bg=C[\"card\"])\n        profile_bar.pack(fill=\"x\", padx=12, pady=(0, 2))\n        for profile_name in profile_options:\n            self._btn(profile_bar, profile_name, C[\"btn_chip\"], lambda name=profile_name: self._apply_gp_profile(name)).pack(fill=\"x\", pady=1)\n        tk.Label(left, textvariable=self.gp_profile_hint_var, font=FONTS[\"xsmall\"], fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=280, justify=\"left\").pack(anchor=\"w\", padx=12, pady=(0, 8))\n        self._btn(left, \"\u2705 Apply Selected Policies\", C[\"btn\"], self._apply_gp).pack(padx=12, pady=(4, 2), fill=\"x\")\n        self._btn(left, \"\ud83d\udcbe Backup GP\", C[\"btn_chip\"], self._gp_backup).pack(fill=\"x\", padx=12, pady=2)\n        self._btn(left, \"\u267b Restore GP\", C[\"btn_info\"], self._gp_restore).pack(fill=\"x\", padx=12, pady=(2, 10))\n        right = tk.Frame(content, bg=C[\"card\"])\n        right.grid(row=0, column=1, sticky=\"nsew\", padx=(6,0))\n        tk.Label(right, text=\"  Policy Dashboard\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8,4), padx=8)\n        self.gp_progress_var = tk.DoubleVar(value=0.0)\n        self.gp_progress_bar = ttk.Progressbar(right, variable=self.gp_progress_var, maximum=100, mode=\"determinate\")\n        self.gp_progress_bar.pack(fill=\"x\", padx=12, pady=(0,6))\n        self.gp_status_lbl = tk.Label(right, text=\"Ready for group policy optimization\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"])\n        self.gp_status_lbl.pack(anchor=\"w\", padx=12, pady=(0,8))\n        metrics = tk.Frame(right, bg=C[\"card\"])\n        metrics.pack(fill=\"x\", padx=12, pady=(0,6))\n        self.gp_action_count_var = tk.StringVar(value=\"0\")\n        self.gp_policy_score_var = tk.StringVar(value=\"--\")\n        self.gp_restart_risk_var = tk.StringVar(value=\"Low\")\n        for label, var, fg in [\n            (\"Actions\", self.gp_action_count_var, C[\"accent4\"]),\n            (\"Policy Score\", self.gp_policy_score_var, C[\"success\"]),\n            (\"Restart Risk\", self.gp_restart_risk_var, C[\"warning\"]),\n        ]:\n            card = tk.Frame(metrics, bg=C[\"bg\"], padx=8, pady=8)\n            card.pack(side=\"left\", fill=\"x\", expand=True, padx=3)\n            tk.Label(card, text=label, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"]).pack(anchor=\"w\")\n            tk.Label(card, textvariable=var, font=(\"Segoe UI\", 14, \"bold\"), fg=fg, bg=C[\"bg\"]).pack(anchor=\"w\")\n        tk.Label(right, text=\"  Execution Log\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8,4), padx=8)\n        self.gp_log = self._scrolled_text(right, height=16)\n        self.gp_action_log = self.gp_log\n        return frame\n\n    def _gp_backup(self):\n        path = filedialog.asksaveasfilename(defaultextension=\".json\", filetypes=[(\"JSON\",\"*.json\")],\n                                            initialfile=\"gp_backup.json\", title=\"Save GP Backup\")\n        if not path:\n            return\n        try:\n            data = {\n                \"ts\": datetime.datetime.now().isoformat(timespec=\"seconds\"),\n                \"values\": {\n                    \"cortana\": self._reg_get(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Policies\\Microsoft\\Windows\\Windows Search\", \"AllowCortana\"),\n                    \"ads\": self._reg_get(winreg.HKEY_CURRENT_USER, r\"Software\\Microsoft\\Windows\\CurrentVersion\\AdvertisingInfo\", \"Enabled\"),\n                    \"consumer\": self._reg_get(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Policies\\Microsoft\\Windows\\CloudContent\", \"DisableWindowsConsumerFeatures\"),\n                    \"remote\": self._reg_get(winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Control\\Remote Assistance\", \"fAllowToGetHelp\"),\n                },\n                \"gp_vars\": {k: bool(v.get()) for k, v in getattr(self, \"gp_vars\", {}).items()},\n            }\n            with open(path, \"w\", encoding=\"utf-8\") as f:\n                json.dump(data, f, ensure_ascii=False, indent=2, default=str)\n            self._append_log(self.gp_log, f\"\u2705 GP backup saved: {path}\", C[\"success\"])\n            messagebox.showinfo(\"Saved\", f\"\u2705 Backup saved:\\n{path}\")\n        except Exception as e:\n            messagebox.showerror(\"Backup Error\", str(e))\n\n    def _gp_restore(self):\n        path = filedialog.askopenfilename(filetypes=[(\"JSON\",\"*.json\")], title=\"Open GP Backup\")\n        if not path:\n            return\n        if not messagebox.askyesno(\"Restore GP\", \"Backup file se Group Policy values restore karein?\"):\n            return\n        try:\n            with open(path, \"r\", encoding=\"utf-8\") as f:\n                data = json.load(f)\n            vals = (data or {}).get(\"values\", {})\n        except Exception as e:\n            messagebox.showerror(\"Restore Error\", str(e))\n            return\n        results = []\n        try:\n            # Each stored value is tuple: (exists, current, type)\n            def apply_reg(key, hive, reg_path, name, default_val, vtype):\n                triple = vals.get(key)\n                if isinstance(triple, list) and len(triple) == 3:\n                    exists, cur, typ = triple\n                    if exists:\n                        return self._reg_set_checked(hive, reg_path, name, cur, typ, f\"Restore {key}\", self.gp_log)\n                return self._reg_set_checked(hive, reg_path, name, default_val, vtype, f\"Restore {key} default\", self.gp_log)\n            results.append(apply_reg(\"cortana\", winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Policies\\Microsoft\\Windows\\Windows Search\", \"AllowCortana\", 1, winreg.REG_DWORD))\n            results.append(apply_reg(\"ads\", winreg.HKEY_CURRENT_USER, r\"Software\\Microsoft\\Windows\\CurrentVersion\\AdvertisingInfo\", \"Enabled\", 1, winreg.REG_DWORD))\n            results.append(apply_reg(\"consumer\", winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Policies\\Microsoft\\Windows\\CloudContent\", \"DisableWindowsConsumerFeatures\", 0, winreg.REG_DWORD))\n            results.append(apply_reg(\"remote\", winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Control\\Remote Assistance\", \"fAllowToGetHelp\", 1, winreg.REG_DWORD))\n        except Exception as e:\n            self._append_log(self.gp_log, f\"\u26a0 Restore apply failed: {e}\", C[\"warning\"])\n        # Refresh policy\n        out, rc = self._run_cmd(\"gpupdate /force\")\n        results.append({\"state\": \"changed\" if rc == 0 else \"failed\", \"label\": \"Group Policy refresh\", \"error\": out[:300] if rc != 0 else \"\"})\n        summary = self._action_summary(\"GP Restore\", results)\n        self._append_log(self.gp_log, summary[\"message\"], C[\"accent\"])\n        messagebox.showinfo(\"Restore Result\", summary[\"message\"])\n\n    def _apply_gp_profile(self, profile_name):\n        profiles = get_group_policy_profiles()\n        profile = profiles.get(profile_name) or profiles.get(\"Balanced\")\n        for key in self.gp_vars:\n            self.gp_vars[key].set(key in profile[\"keys\"])\n        self.gp_profile_hint_var.set(profile[\"summary\"])\n        self._append_log(self.gp_log, f\"\ud83c\udfaf Group Policy preset applied: {profile_name} \u2014 {profile['summary']}\", C[\"success\"])\n\n    def _apply_gp(self):\n        def before():\n            return \"Group Policy changes will be applied.\"\n        self._confirm_and_launch_job(\"Group Policy Optimizer\", \"Apply selected group policy tweaks?\\nSome may require a restart.\",\n                                      before, \"group_policy_optimize\", self._do_gp)\n\n    def _do_gp_legacy(self):\n        v = self.gp_vars\n        if v[\"cortana\"].get():\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Policies\\Microsoft\\Windows\\Windows Search\", \"AllowCortana\", 0, winreg.REG_DWORD)\n            self._append_log(self.gp_log, \"\u2705 Cortana disabled\", C[\"success\"])\n        if v[\"ads\"].get():\n            self._reg_set(winreg.HKEY_CURRENT_USER, r\"Software\\Microsoft\\Windows\\CurrentVersion\\AdvertisingInfo\", \"Enabled\", 0, winreg.REG_DWORD)\n            self._append_log(self.gp_log, \"\u2705 Ad ID disabled\", C[\"success\"])\n        if v[\"consumer\"].get():\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Policies\\Microsoft\\Windows\\CloudContent\", \"DisableWindowsConsumerFeatures\", 1, winreg.REG_DWORD)\n            self._append_log(self.gp_log, \"\u2705 Consumer features disabled\", C[\"success\"])\n        if v[\"remote\"].get():\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Control\\Remote Assistance\", \"fAllowToGetHelp\", 0, winreg.REG_DWORD)\n            self._append_log(self.gp_log, \"\u2705 Remote Assistance disabled\", C[\"success\"])\n        self._run_cmd(\"gpupdate /force\")\n        self._append_log(self.gp_log, \"\u2705 GP Updated\", C[\"success\"])\n\n    def _do_registry(self):\n        v = self.reg_vars\n        selected_actions = [name for name, var in v.items() if var.get()]\n        total_actions = max(1, len(selected_actions))\n        batch = {\n            \"phase\": \"registry\",\n            \"status_text\": \"Initializing registry optimization...\",\n            \"progress_pct\": 0.0,\n            \"actions_total\": total_actions,\n            \"actions_done\": 0,\n            \"keys_changed\": 0,\n            \"errors\": 0,\n            \"predicted_impact\": min(95, 15 + total_actions * 12),\n            \"confidence_score\": min(98, max(30, 20 + total_actions * 10)),\n        }\n        last_dispatch = time.time()\n\n        def dispatch_metrics():\n            nonlocal last_dispatch\n            try:\n                batch[\"progress_pct\"] = min(100.0, (batch[\"actions_done\"] / batch[\"actions_total\"]) * 100.0)\n                batch[\"status_text\"] = f\"Applying registry tweaks ({batch['actions_done']}/{batch['actions_total']})\"\n                self._registry_gp_metrics_queue.put(batch.copy())\n            except Exception:\n                pass\n            last_dispatch = time.time()\n\n        def track(result):\n            try:\n                batch[\"actions_done\"] += 1\n                if isinstance(result, dict) and result.get(\"state\") == \"changed\":\n                    batch[\"keys_changed\"] += 1\n                if isinstance(result, dict) and result.get(\"state\") == \"failed\":\n                    batch[\"errors\"] += 1\n                if time.time() - last_dispatch &gt;= 0.12:\n                    dispatch_metrics()\n            except Exception:\n                pass\n            return result\n\n        results = []\n        try:\n            if v[\"menu_delay\"].get():\n                results.append(track(self._reg_set_checked(winreg.HKEY_CURRENT_USER, r\"Control Panel\\Desktop\", \"MenuShowDelay\", \"0\", winreg.REG_SZ, \"Menu delay 0ms\", self.reg_log)))\n            if v[\"visual_fx\"].get():\n                results.append(track(self._reg_set_checked(winreg.HKEY_CURRENT_USER, r\"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\VisualEffects\", \"VisualFXSetting\", 2, winreg.REG_DWORD, \"Visual effects disabled\", self.reg_log)))\n            if v[\"search_idx\"].get():\n                results.append(track(self._service_config_checked(\"WSearch\", \"disabled\", \"Search indexing service\", self.reg_log)))\n                results.append(track(self._service_stop_checked(\"WSearch\", \"Search indexing service\", self.reg_log)))\n            if v[\"telemetry\"].get():\n                results.append(track(self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Policies\\Microsoft\\Windows\\DataCollection\", \"AllowTelemetry\", 0, winreg.REG_DWORD, \"Telemetry minimized\", self.reg_log)))\n            if v[\"ntfs_last\"].get():\n                results.append(track(self._fsutil_last_access_checked(self.reg_log)))\n            if v[\"autorun\"].get():\n                results.append(track(self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer\", \"NoDriveTypeAutoRun\", 255, winreg.REG_DWORD, \"Autorun disabled\", self.reg_log)))\n            if v.get(\"shutdown_fast\") and v[\"shutdown_fast\"].get():\n                results.append(track(self._reg_set_checked(winreg.HKEY_CURRENT_USER, r\"Control Panel\\Desktop\", \"AutoEndTasks\", \"1\", winreg.REG_SZ, \"AutoEndTasks enabled\", self.reg_log)))\n                results.append(track(self._reg_set_checked(winreg.HKEY_CURRENT_USER, r\"Control Panel\\Desktop\", \"HungAppTimeout\", \"2000\", winreg.REG_SZ, \"HungAppTimeout 2s\", self.reg_log)))\n                results.append(track(self._reg_set_checked(winreg.HKEY_CURRENT_USER, r\"Control Panel\\Desktop\", \"WaitToKillAppTimeout\", \"2000\", winreg.REG_SZ, \"WaitToKillAppTimeout 2s\", self.reg_log)))\n                results.append(track(self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Control\", \"WaitToKillServiceTimeout\", \"2000\", winreg.REG_SZ, \"WaitToKillServiceTimeout 2s\", self.reg_log)))\n            if v.get(\"extreme_visual\") and v[\"extreme_visual\"].get():\n                results.append(track(self._reg_set_checked(winreg.HKEY_CURRENT_USER, r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\VisualEffects\", \"VisualFXSetting\", 2, winreg.REG_DWORD, \"Extreme visual effects base\", self.reg_log)))\n                results.append(track(self._reg_set_checked(winreg.HKEY_CURRENT_USER, r\"Control Panel\\Desktop\", \"UserPreferencesMask\", b'\\x9e\\x3e\\x07\\x80\\x12\\x00\\x00\\x00', winreg.REG_BINARY, \"Extreme visual effects mask\", self.reg_log)))\n                results.append(track(self._reg_set_checked(winreg.HKEY_CURRENT_USER, r\"Control Panel\\Desktop\", \"MinAnimate\", \"0\", winreg.REG_SZ, \"Window animation off\", self.reg_log)))\n        except Exception as e:\n            self._append_log(self.reg_log, f\"\u26a0 Registry optimization failed: {e}\", C[\"error\"])\n            batch[\"errors\"] += 1\n        dispatch_metrics()\n        try:\n            summary = self._action_summary(\"Registry Tweaks\", results)\n            self._append_log(self.reg_log, summary[\"message\"], C[\"accent\"])\n        except Exception as e:\n            self._append_log(self.reg_log, f\"\u26a0 Registry summary failed: {e}\", C[\"error\"])\n            summary = {\"message\": \"Registry completed with issues.\"}\n        batch[\"status_text\"] = \"Registry optimization complete\"\n        batch[\"progress_pct\"] = 100.0\n        batch[\"confidence_score\"] = min(100, batch[\"confidence_score\"] + (batch[\"actions_done\"] * 2))\n        self._registry_gp_metrics_queue.put(batch.copy())\n        return summary\n\n    def _do_gp(self):\n        v = self.gp_vars\n        selected_actions = [name for name, var in v.items() if var.get()]\n        total_actions = max(1, len(selected_actions))\n        batch = {\n            \"phase\": \"grouppolicy\",\n            \"status_text\": \"Initializing group policy optimizer...\",\n            \"progress_pct\": 0.0,\n            \"actions_total\": total_actions,\n            \"actions_done\": 0,\n            \"policy_score\": min(90, 10 + total_actions * 18),\n            \"restart_risk\": \"Low\",\n            \"errors\": 0,\n        }\n        last_dispatch = time.time()\n\n        def dispatch_metrics():\n            nonlocal last_dispatch\n            try:\n                batch[\"progress_pct\"] = min(100.0, (batch[\"actions_done\"] / batch[\"actions_total\"]) * 100.0)\n                batch[\"status_text\"] = f\"Applying group policy ({batch['actions_done']}/{batch['actions_total']})\"\n                self._registry_gp_metrics_queue.put(batch.copy())\n            except Exception:\n                pass\n            last_dispatch = time.time()\n\n        def track(result):\n            try:\n                batch[\"actions_done\"] += 1\n                if isinstance(result, dict) and result.get(\"state\") == \"changed\":\n                    batch[\"policy_score\"] = min(100, batch[\"policy_score\"] + 8)\n                if isinstance(result, dict) and result.get(\"state\") == \"failed\":\n                    batch[\"errors\"] += 1\n                    batch[\"restart_risk\"] = \"Medium\"\n                if time.time() - last_dispatch &gt;= 0.12:\n                    dispatch_metrics()\n            except Exception:\n                pass\n            return result\n\n        results = []\n        try:\n            if v[\"cortana\"].get():\n                results.append(track(self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Policies\\Microsoft\\Windows\\Windows Search\", \"AllowCortana\", 0, winreg.REG_DWORD, \"Cortana disabled\", self.gp_log)))\n            if v[\"ads\"].get():\n                results.append(track(self._reg_set_checked(winreg.HKEY_CURRENT_USER, r\"Software\\Microsoft\\Windows\\CurrentVersion\\AdvertisingInfo\", \"Enabled\", 0, winreg.REG_DWORD, \"Advertising ID disabled\", self.gp_log)))\n            if v[\"consumer\"].get():\n                results.append(track(self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Policies\\Microsoft\\Windows\\CloudContent\", \"DisableWindowsConsumerFeatures\", 1, winreg.REG_DWORD, \"Consumer features disabled\", self.gp_log)))\n            if v[\"remote\"].get():\n                results.append(track(self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Control\\Remote Assistance\", \"fAllowToGetHelp\", 0, winreg.REG_DWORD, \"Remote Assistance disabled\", self.gp_log)))\n            if any(r.get(\"state\") == \"changed\" for r in results):\n                out, rc = self._run_cmd(\"gpupdate /force\")\n                results.append(track({\"state\": \"changed\" if rc == 0 else \"failed\", \"label\": \"Group Policy refresh\", \"error\": out[:300] if rc != 0 else \"\"}))\n                self._append_log(self.gp_log, \"GP Updated\" if rc == 0 else f\"GP update failed: {out[:120]}\", C[\"success\"] if rc == 0 else C[\"error\"])\n                if rc != 0:\n                    batch[\"restart_risk\"] = \"High\"\n            else:\n                self._append_log(self.gp_log, \"Already done: GP update skipped\", C[\"warning\"])\n        except Exception as e:\n            self._append_log(self.gp_log, f\"\u26a0 Group Policy optimization failed: {e}\", C[\"error\"])\n            batch[\"errors\"] += 1\n            batch[\"restart_risk\"] = \"Medium\"\n        dispatch_metrics()\n        try:\n            summary = self._action_summary(\"Group Policy\", results)\n            self._append_log(self.gp_log, summary[\"message\"], C[\"accent\"])\n        except Exception as e:\n            self._append_log(self.gp_log, f\"\u26a0 Group Policy summary failed: {e}\", C[\"error\"])\n            summary = {\"message\": \"Group Policy completed with issues.\"}\n        batch[\"status_text\"] = \"Group Policy optimizer complete\"\n        batch[\"progress_pct\"] = 100.0\n        self._registry_gp_metrics_queue.put(batch.copy())\n        return summary\n\n    # ---------- NETWORK OPTIMIZER (with confirm) ----------\n    def _build_network(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"Network Optimizer\", \"TCP/IP, DNS, cache and bandwidth repair\")\n        self.network_health_status = tk.Label(\n            frame,\n            text=\"Connectivity status: idle\",\n            font=FONTS[\"small\"],\n            fg=C[\"text_dim\"],\n            bg=C[\"bg\"],\n            anchor=\"w\",\n        )\n        self.network_health_status.pack(fill=\"x\", padx=16, pady=(0, 4))\n        body = self._scrollable_section_body(frame)\n        self._action_card_grid(body, [\n            (\"TCP\", \"TCP Optimizations\",          \"TCP/IP tweaks apply karo\",            C[\"btn_info\"],   self._apply_tcp),\n            (\"DNS\", \"Flush DNS\",                  \"DNS cache saaf karo\",                 C[\"btn\"],        self._flush_dns),\n            (\"RST\", \"Reset TCP/IP\",               \"TCP/IP stack reset karo\",             C[\"btn_warn\"],   self._reset_tcpip),\n            (\"CLR\", \"Browser/Office Cache Clear\", \"Browser aur Office cache delete karo\",C[\"btn_danger\"], self._browser_office_cache_clear),\n            (\"NET\", \"Disable Net Throttling\",     \"Network speed limit hatao\",           C[\"btn_chip\"],   self._disable_network_throttling),\n            (\"P2P\", \"Disable Delivery Optim.\",    \"Windows Update bandwidth free karo\",  C[\"btn_warn\"],   self._disable_delivery_optimization),\n            (\"DNS+\", \"Optimize DNS\",              \"Cloudflare + Google DNS lagao\",       C[\"btn_info\"],   self._optimize_dns),\n            (\"ADPT\", \"Adapter-wise DNS\",          \"WiFi / Ethernet DNS alag set karo\",   C[\"btn_info\"],   self._dns_by_adapter_dialog),\n            (\"PING\", \"Ping Internet\",             \"Ping Cloudflare for latency\",        C[\"btn_chip\"],   self._network_ping_test),\n            (\"CHK\", \"Connectivity Audit\",         \"Ping + adapter summary report\",       C[\"btn_chip\"],   self._run_network_health_check),\n            (\"SPD\", \"Speedtest Hook\",             \"Run configured speedtest command\",   C[\"btn_info\"],   self._run_speedtest_hook),\n            (\"SAV\", \"Save Last Audit\",            \"Save latest audit as text\",           C[\"btn\"],        self._export_last_network_audit),\n            (\"RPT\", \"Export Net Report\",          \"Save network config + route report\",  C[\"btn\"],        self._export_network_report),\n        ], cols=4)\n        content = tk.Frame(body, bg=C[\"card\"])\n        content.pack(fill=\"both\", expand=True, padx=16, pady=(8, 12))\n        tk.Label(content, text=\"  Network log\", font=FONTS[\"subhead\"],\n                 fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8, 4), padx=8)\n        self.network_log = self._scrolled_text(content, height=14)\n        return frame\n\n    def _dns_by_adapter_dialog(self):\n        # Best-effort: list adapters and ask for adapter name\n        out, rc = self._run_cmd('powershell -Command \"Get-NetAdapter | Where-Object {$_.Status -eq \\'Up\\'} | Select-Object -ExpandProperty Name\"', timeout=10)\n        adapters = [a.strip() for a in out.splitlines() if a.strip()] if rc == 0 else []\n        if not adapters:\n            messagebox.showwarning(\"Adapters\", \"No active adapters found (or PowerShell blocked).\")\n            return\n        try:\n            import tkinter.simpledialog as simpledialog\n            choice = simpledialog.askstring(\"Adapter Name\",\n                                            \"Active adapters:\\n\" + \"\\n\".join(adapters[:10]) +\n                                            (\"\\n...\" if len(adapters) &gt; 10 else \"\") +\n                                            \"\\n\\nType exact adapter name (Wi-Fi/Ethernet):\")\n        except Exception:\n            choice = None\n        if not choice:\n            return\n        adapter = choice.strip()\n        if not adapter:\n            return\n        if not messagebox.askyesno(\"Set DNS\",\n                                   f\"Adapter: {adapter}\\nDNS: 1.1.1.1 + 8.8.8.8\\n\\nApply?\"):\n            return\n        # Use PowerShell for reliable adapter name handling\n        cmd = (\n            'powershell -Command \"'\n            f'Set-DnsClientServerAddress -InterfaceAlias \\'{adapter}\\' -ServerAddresses (\\'1.1.1.1\\',\\'8.8.8.8\\')\"'\n        )\n        out2, rc2 = self._run_cmd(cmd, timeout=20)\n        if rc2 == 0:\n            self._append_log(self.network_log, f\"\u2705 DNS applied on '{adapter}'\", C[\"success\"])\n        else:\n            self._append_log(self.network_log, f\"\u274c DNS set failed: {out2[:200]}\", C[\"error\"])\n\n    def _run_speedtest_hook(self):\n        \"\"\"\n        Optional hook: set env var GODAWARI_SPEEDTEST_CMD to a command that prints results.\n        Example: setx GODAWARI_SPEEDTEST_CMD \"speedtest --accept-license --accept-gdpr\"\n        \"\"\"\n        cmd = os.environ.get(\"GODAWARI_SPEEDTEST_CMD\", \"\").strip()\n        if not cmd:\n            messagebox.showinfo(\"Speedtest Hook\",\n                                \"Speedtest hook set nahi hai.\\n\\n\"\n                                \"Env var set karo:\\n\"\n                                \"GODAWARI_SPEEDTEST_CMD = \\n\\n\"\n                                \"Example:\\n\"\n                                \"speedtest --accept-license --accept-gdpr\")\n            return\n        self._append_log(self.network_log, f\"\u23f1 Speedtest running: {cmd}\", C[\"accent4\"])\n        out, rc = self._run_cmd(cmd, timeout=120)\n        if rc == 0:\n            self._append_log(self.network_log, out[:1200] if out else \"\u2705 Speedtest done\", C[\"success\"])\n        else:\n            self._append_log(self.network_log, f\"\u274c Speedtest failed (rc={rc}): {out[:300]}\", C[\"error\"])\n\n    def _apply_tcp(self):\n        if messagebox.askyesno(\"TCP Optimizations\", \"Apply TCP tuning for better network performance?\"):\n            for cmd in ['netsh int tcp set global autotuninglevel=normal', 'netsh int tcp set global rss=enabled']:\n                self._run_cmd(cmd)\n            self._append_log(self.network_log, \"\u2705 TCP optimizations applied\", C[\"success\"])\n\n    def _flush_dns(self):\n        if messagebox.askyesno(\"Flush DNS\", \"Flush DNS cache? This can resolve connectivity issues.\"):\n            self._run_cmd('ipconfig /flushdns')\n            self._append_log(self.network_log, \"\u2705 DNS flushed\", C[\"success\"])\n\n    def _reset_tcpip(self):\n        if messagebox.askyesno(\"Reset TCP/IP\", \"This will reset Winsock and TCP/IP stack. A restart will be needed.\"):\n            self._run_cmd('netsh int ip reset')\n            self._append_log(self.network_log, \"\u2705 TCP/IP reset. Restart required.\", C[\"warning\"])\n\n    def _browser_office_cache_clear(self):\n        if messagebox.askyesno(\"Clear Browser/Office Cache\", \"Clear caches for Chrome, Edge, and Office?\\nBrowsers will be closed.\"):\n            self._launch_job(\"browser_clear\", self._do_browser_clear)\n\n    def _do_browser_clear(self):\n        for exe in [\"chrome\",\"msedge\",\"firefox\"]:\n            self._run_cmd(f'taskkill /IM {exe}.exe /F')\n        total = 0\n        local = os.environ.get(\"LOCALAPPDATA\",\"\")\n        for p in [os.path.join(local,\"Google\\\\Chrome\\\\User Data\\\\Default\\\\Cache\"),\n                  os.path.join(local,\"Microsoft\\\\Edge\\\\User Data\\\\Default\\\\Cache\"),\n                  os.path.join(local,\"Microsoft\\\\Office\\\\16.0\\\\OfficeFileCache\")]:\n            if os.path.exists(p):\n                total += self._delete_folder_contents(p)\n        self._append_log(self.network_log, f\"\u2705 Cleared {self._fmt_size(total)} cache\", C[\"success\"])\n\n    def _disable_network_throttling(self):\n        if messagebox.askyesno(\"Disable Network Throttling\", \"This can improve network throughput for multimedia apps.\"):\n            result = self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Multimedia\\SystemProfile\", \"NetworkThrottlingIndex\", 0xffffffff, winreg.REG_DWORD, \"Network throttling disabled\", self.network_log)\n            if result[\"state\"] == \"already\":\n                messagebox.showinfo(\"Already Done\", \"Network throttling already disabled.\")\n\n    def _disable_delivery_optimization(self):\n        if messagebox.askyesno(\"Disable Delivery Optimization\", \"Disable Windows Update P2P sharing? Saves bandwidth.\"):\n            results = [\n                self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\DeliveryOptimization\\Config\", \"DODownloadMode\", 0, winreg.REG_DWORD, \"Delivery Optimization P2P off\", self.network_log),\n                self._service_stop_checked(\"DoSvc\", \"Delivery Optimization service\", self.network_log),\n                self._service_config_checked(\"DoSvc\", \"disabled\", \"Delivery Optimization service\", self.network_log),\n            ]\n            summary = self._action_summary(\"Delivery Optimization\", results)\n            if summary[\"already_done\"]:\n                messagebox.showinfo(\"Already Done\", \"Delivery Optimization already disabled.\")\n\n    def _network_ping_test(self):\n        if not messagebox.askyesno(\"Ping Test\", \"Ping 1.1.1.1 and 8.8.8.8 to check internet latency?\"):\n            return\n        targets = [\"1.1.1.1\", \"8.8.8.8\"]\n        for target in targets:\n            out, rc = self._run_cmd(f\"ping -n 4 {target}\", timeout=20)\n            if rc == 0:\n                self._append_log(self.network_log, f\"\u2705 Ping {target} OK:\\n{out.strip()[:400]}\", C[\"success\"])\n            else:\n                self._append_log(self.network_log, f\"\u274c Ping {target} failed (rc={rc}): {out.strip()[:400]}\", C[\"error\"])\n        self._set_status(\"Ping test complete\", C[\"success\"])\n\n    def _export_network_report(self):\n        path = filedialog.asksaveasfilename(defaultextension=\".txt\",\n                                            filetypes=[(\"Text files\",\"*.txt\")],\n                                            initialfile=\"Network_Report.txt\",\n                                            title=\"Save Network Report\")\n        if not path:\n            return\n        report = []\n        for cmd, label in [\n            (\"ipconfig /all\", \"IP Configuration\"),\n            (\"route print\", \"Route Table\"),\n            (\"netsh interface ipv4 show config\", \"IPv4 Adapter Config\"),\n            (\"netsh interface ipv6 show config\", \"IPv6 Adapter Config\"),\n            (\"netsh interface show interface\", \"Interface Status\"),\n        ]:\n            out, rc = self._run_cmd(cmd, timeout=30)\n            report.append(f\"=== {label} ===\\n\")\n            report.append(out if out else f\"[command failed rc={rc}]\\n\")\n        try:\n            with open(path, \"w\", encoding=\"utf-8\") as f:\n                f.write(\"\\n\".join(report))\n            messagebox.showinfo(\"Saved\", f\"Network report saved to:\\n{path}\")\n            self._append_log(self.network_log, f\"\ud83d\udcbe Network report saved: {path}\", C[\"success\"])\n        except Exception as e:\n            messagebox.showerror(\"Error\", str(e))\n            self._append_log(self.network_log, f\"\u274c Report save failed: {e}\", C[\"error\"])\n\n    def _run_network_health_check(self):\n        if not messagebox.askyesno(\"Connectivity Audit\", \"Run a quick ping + adapter audit now?\"):\n            return\n        self.network_health_status.config(text=\"Connectivity status: running audit\", fg=C[\"accent4\"])\n        self._append_log(self.network_log, \"\ud83d\udd0d Running connectivity audit...\", C[\"accent4\"])\n\n        ping_out, ping_rc = self._run_cmd(\"ping -n 2 1.1.1.1\", timeout=20)\n        ip_out, ip_rc = self._run_cmd(\"ipconfig /all\", timeout=20)\n        route_out, route_rc = self._run_cmd(\"route print\", timeout=20)\n\n        summary_lines = [\n            f\"Ping 1.1.1.1: {'OK' if ping_rc == 0 else 'FAIL'}\",\n            f\"ipconfig /all: {'OK' if ip_rc == 0 else 'FAIL'}\",\n            f\"route print: {'OK' if route_rc == 0 else 'FAIL'}\",\n        ]\n        if ping_rc == 0:\n            self._append_log(self.network_log, f\"\u2705 Ping check passed\\n{ping_out[:300]}\", C[\"success\"])\n        else:\n            self._append_log(self.network_log, f\"\u274c Ping check failed\\n{ping_out[:300]}\", C[\"error\"])\n\n        adapter_lines = [line for line in ip_out.splitlines() if \"DNS Servers\" in line or \"IPv4 Address\" in line or \"Description\" in line or \"Physical Address\" in line]\n        if adapter_lines:\n            self._append_log(self.network_log, \"\ud83d\udce1 Adapter summary:\\n\" + \"\\n\".join(adapter_lines[:20]), C[\"text\"])\n        else:\n            self._append_log(self.network_log, \"\ud83d\udce1 No adapter details captured from ipconfig output.\", C[\"warning\"])\n\n        self._append_log(self.network_log, \"\ud83d\udee3 Route summary:\\n\" + (route_out[:700] if route_out else \"route print unavailable\"), C[\"text\"])\n        self._append_log(self.network_log, \"\u2705 Connectivity audit complete. \" + \" | \".join(summary_lines), C[\"success\"])\n\n        self._last_network_audit = {\n            \"timestamp\": datetime.datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\"),\n            \"ping_rc\": ping_rc,\n            \"ip_rc\": ip_rc,\n            \"route_rc\": route_rc,\n            \"ping_output\": ping_out,\n            \"ip_output\": ip_out,\n            \"route_output\": route_out,\n        }\n        self.network_health_status.config(\n            text=f\"Connectivity status: audit complete at {self._last_network_audit['timestamp']}\",\n            fg=C[\"success\"],\n        )\n        self._set_status(\"Connectivity audit complete\", C[\"success\"])\n\n    def _export_last_network_audit(self):\n        audit = getattr(self, \"_last_network_audit\", None)\n        if not audit:\n            messagebox.showinfo(\"No Audit\", \"Pehle Connectivity Audit run karo.\")\n            return\n        path = filedialog.asksaveasfilename(\n            defaultextension=\".txt\",\n            filetypes=[(\"Text files\", \"*.txt\")],\n            initialfile=f\"Network_Audit_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.txt\",\n            title=\"Save Last Network Audit\",\n        )\n        if not path:\n            return\n        try:\n            lines = [\n                f\"Godawari Network Audit\",\n                f\"Timestamp: {audit['timestamp']}\",\n                f\"Ping rc: {audit['ping_rc']}\",\n                f\"ipconfig rc: {audit['ip_rc']}\",\n                f\"route print rc: {audit['route_rc']}\",\n                \"\",\n                \"--- Ping Output ---\",\n                audit.get(\"ping_output\", \"\"),\n                \"\",\n                \"--- ipconfig Output ---\",\n                audit.get(\"ip_output\", \"\"),\n                \"\",\n                \"--- route print Output ---\",\n                audit.get(\"route_output\", \"\"),\n            ]\n            with open(path, \"w\", encoding=\"utf-8\") as fh:\n                fh.write(\"\\n\".join(lines))\n            self._append_log(self.network_log, f\"\ud83d\udcbe Saved last audit: {path}\", C[\"success\"])\n            messagebox.showinfo(\"Saved\", f\"Last network audit saved to:\\n{path}\")\n        except Exception as e:\n            messagebox.showerror(\"Save Failed\", str(e))\n            self._append_log(self.network_log, f\"\u274c Failed to save audit: {e}\", C[\"error\"])\n\n    def _optimize_dns(self):\n        if messagebox.askyesno(\"Optimize DNS\", \"Set DNS to Cloudflare (1.1.1.1) and Google (8.8.8.8) for faster browsing?\"):\n            out, _ = self._run_cmd('wmic nic where \"NetEnabled=True\" get Index /format:csv')\n            lines = out.splitlines()\n            for line in lines[1:]:\n                if line.strip():\n                    idx = line.split(',')[1].strip()\n                    self._run_cmd(f'netsh interface ip set dns name={idx} static 1.1.1.1 primary')\n                    self._run_cmd(f'netsh interface ip add dns name={idx} 8.8.8.8 index=2')\n            self._append_log(self.network_log, \"\u2705 DNS set to Cloudflare (1.1.1.1) and Google (8.8.8.8)\", C[\"success\"])\n\n    # ---------- TROUBLESHOOTER &amp; POWER PLAN (shortened for length) ----------\n    # I'll include the essential parts. The rest methods are similar structure.\n\n    def _build_troubleshooter(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"System Repair\", \"Guided SFC, DISM, network, crash and driver diagnostics\")\n        body = self._scrollable_section_body(frame)\n\n        guide = tk.Frame(body, bg=C[\"card\"], highlightbackground=C[\"accent2\"], highlightthickness=1)\n        guide.pack(fill=\"x\", padx=16, pady=(10, 6))\n        tk.Label(guide, text=\"Recommended flow\", font=FONTS[\"subhead\"],\n                 fg=C[\"accent2\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=12, pady=(8, 2))\n        tk.Label(\n            guide,\n            text=\"Start with Repair Verification or Network Reset. Use advanced crash, boot, driver and security reports when the basic repair does not explain the issue.\",\n            font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], anchor=\"w\",\n            justify=\"left\", wraplength=self._dpi_px(980)\n        ).pack(fill=\"x\", padx=12, pady=(0, 8))\n\n        self._action_card_grid(body, [\n            (\"NET\", \"Network Reset\",            \"TCP/IP, Winsock and DNS reset\",       C[\"btn_info\"],   self._full_network_reset),\n            (\"SFC\", \"SFC /SCANNOW\",             \"System files scan and repair\",        C[\"btn\"],        self._run_sfc),\n            (\"DISM\", \"DISM RestoreHealth\",      \"Windows image repair\",                C[\"btn_warn\"],   self._run_dism),\n            (\"ALL\", \"Run All Repairs\",          \"Restore point, DISM, SFC and network\",C[\"accent4\"],    self._run_all_repairs),\n            (\"BSOD\", \"BSoD Deep Diagnose\",      \"Stop code, WHEA, driver and dump check\", C[\"accent3\"], self._bsod_deep_diagnose),\n            (\"DMP\", \"Enable Minidump\",          \"Capture future crash proof logs\",     C[\"btn_chip\"],   self._enable_bsod_minidump),\n            (\"DLL\", \"Kernel32/Rundll32 Check\",  \"WER, startup and DLL crash diagnose\", C[\"btn_info\"],   self._rundll32_error_diagnose),\n            (\"DBG\", \"WinDbg Dump Analyze\",      \"Minidump !analyze automation\",        C[\"accent4\"],    self._windbg_dump_analyze),\n            (\"EVT\", \"Event Correlation\",        \"Crash timeline root-cause summary\",   C[\"btn\"],        self._event_correlation_report),\n            (\"DRV\", \"Driver Diagnostics\",       \"Unsigned, recent and outdated drivers\", C[\"btn_warn\"], self._driver_diagnostics_report),\n            (\"HW\", \"Hardware Health\",           \"SMART, NVMe and RAM warning report\",  C[\"hw_accent\"],  self._hardware_health_report),\n            (\"CHK\", \"Repair Verification\",      \"SFC, DISM and event re-check report\", C[\"accent2\"],    self._repair_verification_report),\n            (\"BOOT\", \"Boot Status + BCD\",       \"EFI/BCD analysis and backup\",         C[\"btn_chip\"],   self._boot_status_bcd_backup),\n            (\"OFF\", \"Offline SFC/DISM\",         \"Mounted Windows repair commands\",     C[\"btn_info\"],   self._offline_repair_dialog),\n            (\"SEC\", \"Security Autoruns\",        \"AppInit, hosts and startup risk scan\", C[\"btn_warn\"],  self._security_startup_report),\n            (\"ZIP\", \"Diagnostic ZIP\",           \"HTML, JSON and TXT package export\",   C[\"accent\"],     self._diagnostic_zip_package),\n            (\"WU\", \"Disable Windows Update\",    \"Advanced blocker with warning\",       C[\"btn_danger\"], self._disable_windows_update),\n            (\"STOP\", \"Stop Repair\",             \"Stop the running repair command\",     C[\"btn_danger\"], self._stop_repairs),\n            (\"SAVE\", \"Export Repair Report\",    \"Save the current repair log\",         C[\"btn_chip\"],   self._export_repair_report),\n        ], cols=4)\n\n        content = tk.Frame(body, bg=C[\"card\"])\n        content.pack(fill=\"both\", expand=True, padx=16, pady=(8, 12))\n        tk.Label(content, text=\"  Live repair log\", font=FONTS[\"subhead\"],\n                 fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8, 4), padx=8)\n        self.trouble_log = self._scrolled_text(content, height=12)\n        return frame\n\n    def _stop_repairs(self):\n        self._repair_stop_flag = True\n        try:\n            p = getattr(self, \"_repair_proc\", None)\n            if p and p.poll() is None:\n                try:\n                    p.terminate()\n                except Exception:\n                    pass\n        except Exception:\n            pass\n        self._append_log(self.trouble_log, \"\u23f9 Stop requested for running repair command.\", C[\"warning\"])\n        self._set_status(\"Stop requested...\", C[\"warning\"])\n\n    def _export_repair_report(self):\n        path = filedialog.asksaveasfilename(defaultextension=\".txt\", filetypes=[(\"Text\",\"*.txt\")],\n                                            initialfile=\"SystemRepair_Report.txt\",\n                                            title=\"Save Repair Report\")\n        if not path:\n            return\n        try:\n            txt = \"\"\n            try:\n                txt = self.trouble_log.get(\"1.0\", \"end\")\n            except Exception:\n                txt = \"\"\n            with open(path, \"w\", encoding=\"utf-8\") as f:\n                f.write(txt)\n            messagebox.showinfo(\"Saved\", f\"\u2705 Report saved:\\n{path}\")\n        except Exception as e:\n            messagebox.showerror(\"Error\", str(e))\n\n    def _full_network_reset(self):\n        if messagebox.askyesno(\"Network Reset\", \"Reset Winsock and TCP/IP? Restart required.\"):\n            for cmd in ([\"netsh\", \"winsock\", \"reset\"], [\"netsh\", \"int\", \"ip\", \"reset\"], [\"ipconfig\", \"/flushdns\"]):\n                self._run_cmd(cmd)\n            self._append_log(self.trouble_log, \"\u2705 Network reset complete. Restart.\", C[\"success\"])\n\n    def _run_sfc(self):\n        if messagebox.askyesno(\"System File Checker\", \"Run SFC /SCANNOW? This may take a while.\"):\n            self._append_log(self.trouble_log, \"Running SFC...\", C[\"accent\"])\n            self._launch_job(\"sfc_scan\", self._run_cmd_cancelable, [\"sfc\", \"/scannow\"], 1200)\n\n    def _run_dism(self):\n        if messagebox.askyesno(\"DISM\", \"Run DISM RestoreHealth? This may take a while.\"):\n            self._append_log(self.trouble_log, \"Running DISM...\", C[\"accent\"])\n            self._launch_job(\"dism_restorehealth\", self._run_cmd_cancelable, [\"dism\", \"/online\", \"/cleanup-image\", \"/restorehealth\"], 2400)\n\n    def _run_cmd_cancelable(self, cmd, timeout_s=1800):\n        self._repair_stop_flag = False\n        try:\n            self._repair_proc = subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True,\n                                                 encoding=\"utf-8\", errors=\"replace\")\n            start = time.time()\n            out_lines = []\n            for line in self._repair_proc.stdout:\n                out_lines.append(line.rstrip(\"\\n\"))\n                if len(out_lines) % 25 == 0:\n                    tail = \"\\n\".join(out_lines[-10:])\n                    self.after(0, lambda t=tail: self._append_log(self.trouble_log, t, C[\"text_dim\"]))\n                if getattr(self, \"_repair_stop_flag\", False):\n                    try:\n                        self._repair_proc.terminate()\n                    except Exception:\n                        pass\n                    break\n                if timeout_s and (time.time() - start) &gt; timeout_s:\n                    try:\n                        self._repair_proc.terminate()\n                    except Exception:\n                        pass\n                    break\n            try:\n                rc = self._repair_proc.wait(timeout=5)\n            except Exception:\n                rc = -1\n            tail = \"\\n\".join(out_lines[-30:]) if out_lines else \"\"\n            if getattr(self, \"_repair_stop_flag\", False):\n                self.after(0, lambda: self._append_log(self.trouble_log, \"\u23f9 Repair stopped by user.\", C[\"warning\"]))\n                self.after(0, lambda: self._set_status(\"Repair stopped\", C[\"warning\"]))\n            elif timeout_s and (time.time() - start) &gt; timeout_s:\n                self.after(0, lambda: self._append_log(self.trouble_log, \"\u26a0 Repair timed out.\", C[\"warning\"]))\n                self.after(0, lambda: self._set_status(\"Repair timed out\", C[\"warning\"]))\n            else:\n                self.after(0, lambda: self._append_log(self.trouble_log, f\"\u2705 Command done (rc={rc}).\", C[\"success\"]))\n                if tail:\n                    self.after(0, lambda t=tail: self._append_log(self.trouble_log, t, C[\"text\"]))\n                self.after(0, lambda: self._set_status(\"Repair complete\", C[\"success\"]))\n        except Exception as e:\n            self.after(0, lambda: self._append_log(self.trouble_log, f\"\u274c Repair failed: {e}\", C[\"error\"]))\n        finally:\n            self._repair_proc = None\n\n    def _run_all_repairs(self):\n        if self._create_restore_point(\"Full Repair\"):\n            self._launch_job(\"full_repairs\", lambda: (self._run_dism(), self._run_sfc(), self._full_network_reset()))\n\n    def _disable_windows_update_legacy(self):\n        if messagebox.askyesno(\"Windows Update Blocker\", \"Disable Windows Update services? (Not recommended for security, but boosts performance)\"):\n            self._run_cmd('sc config \"wuauserv\" start= disabled')\n            self._run_cmd('sc stop \"wuauserv\"')\n            self._run_cmd('sc config \"UsoSvc\" start= disabled')\n            self._run_cmd('sc stop \"UsoSvc\"')\n            self._append_log(self.trouble_log, \"\u26a0\ufe0f Windows Update services disabled (Reboot required)\", C[\"warning\"])\n\n    def _disable_windows_update(self):\n        if messagebox.askyesno(\"Windows Update Blocker\", \"Disable Windows Update services? (Not recommended for security, but boosts performance)\"):\n            results = [\n                self._service_config_checked(\"wuauserv\", \"disabled\", \"Windows Update\", self.trouble_log),\n                self._service_stop_checked(\"wuauserv\", \"Windows Update\", self.trouble_log),\n                self._service_config_checked(\"UsoSvc\", \"disabled\", \"Update Orchestrator\", self.trouble_log),\n                self._service_stop_checked(\"UsoSvc\", \"Update Orchestrator\", self.trouble_log),\n            ]\n            summary = self._action_summary(\"Windows Update Blocker\", results)\n            self._append_log(self.trouble_log, summary[\"message\"], C[\"warning\"] if summary[\"already_done\"] else C[\"success\"])\n            messagebox.showinfo(\"Already Done\" if summary[\"already_done\"] else \"Done\", summary[\"message\"])\n\n    def _json_items_from_output(self, output):\n        raw = (output or \"\").strip()\n        if not raw:\n            return []\n        starts = [i for i in (raw.find(\"[\"), raw.find(\"{\")) if i &gt;= 0]\n        if starts:\n            raw = raw[min(starts):]\n        ends = [i for i in (raw.rfind(\"]\"), raw.rfind(\"}\")) if i &gt;= 0]\n        if ends:\n            raw = raw[:max(ends) + 1]\n        try:\n            data = json.loads(raw)\n            if isinstance(data, list):\n                return data\n            if isinstance(data, dict):\n                return [data]\n        except Exception:\n            pass\n        return []\n\n    def _crash_control_values(self):\n        names = [\n            \"CrashDumpEnabled\", \"MinidumpDir\", \"DumpFile\", \"LogEvent\",\n            \"AutoReboot\", \"Overwrite\", \"AlwaysKeepMemoryDump\",\n        ]\n        values = {}\n        for name in names:\n            exists, value, _ = self._reg_get(\n                winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\CrashControl\",\n                name\n            )\n            if exists:\n                values[name] = value\n        return values\n\n    def _bsod_dump_files(self):\n        files = []\n        targets = [\n            (r\"C:\\Windows\\Minidump\", \"*.dmp\", False),\n            (r\"C:\\Windows\\LiveKernelReports\", \"*.dmp\", True),\n        ]\n        for folder, pattern, recursive in targets:\n            try:\n                base = Path(folder)\n                if not base.exists():\n                    continue\n                iterator = base.rglob(pattern) if recursive else base.glob(pattern)\n                for path in iterator:\n                    try:\n                        st = path.stat()\n                        files.append({\n                            \"path\": str(path),\n                            \"name\": path.name,\n                            \"size_kb\": int(st.st_size / 1024),\n                            \"mtime\": datetime.datetime.fromtimestamp(st.st_mtime).strftime(\"%Y-%m-%d %H:%M\"),\n                        })\n                    except Exception:\n                        pass\n            except Exception:\n                pass\n        try:\n            memory_dump = Path(r\"C:\\Windows\\MEMORY.DMP\")\n            if memory_dump.exists():\n                st = memory_dump.stat()\n                files.append({\n                    \"path\": str(memory_dump),\n                    \"name\": memory_dump.name,\n                    \"size_kb\": int(st.st_size / 1024),\n                    \"mtime\": datetime.datetime.fromtimestamp(st.st_mtime).strftime(\"%Y-%m-%d %H:%M\"),\n                })\n        except Exception:\n            pass\n        files.sort(key=lambda item: item.get(\"mtime\", \"\"), reverse=True)\n        return files[:12]\n\n    def _bsod_stop_code_details(self, code):\n        try:\n            number = int(str(code).strip(), 16)\n            key = f\"0x{number:08X}\"\n        except Exception:\n            key = str(code).upper()\n        stop_map = {\n            \"0x0000000A\": (\"IRQL_NOT_LESS_OR_EQUAL\", \"Driver ne galat memory address access kiya.\", \"Recent driver rollback/update karo, RAM test chalao, overclock off rakho.\"),\n            \"0x0000001A\": (\"MEMORY_MANAGEMENT\", \"RAM, pagefile, driver memory leak ya memory corruption.\", \"Windows Memory Diagnostic/MemTest run karo, RAM reseat karo, SFC/DISM run karo.\"),\n            \"0x00000024\": (\"NTFS_FILE_SYSTEM\", \"File system, disk, bad sector ya storage driver issue.\", \"Important data backup karo, SMART check aur chkdsk /f /r run karo.\"),\n            \"0x0000003B\": (\"SYSTEM_SERVICE_EXCEPTION\", \"Driver/system service crash, aksar graphics/security software se.\", \"GPU/network/security driver clean reinstall karo, Windows update complete karo.\"),\n            \"0x00000050\": (\"PAGE_FAULT_IN_NONPAGED_AREA\", \"Bad RAM, bad driver, antivirus filter, ya disk/pagefile issue.\", \"RAM test, driver verifier status check, antivirus/storage driver update karo.\"),\n            \"0x0000007B\": (\"INACCESSIBLE_BOOT_DEVICE\", \"Windows boot disk/controller access nahi kar pa raha.\", \"BIOS SATA mode, storage driver, boot files, chkdsk aur startup repair check karo.\"),\n            \"0x0000007E\": (\"SYSTEM_THREAD_EXCEPTION_NOT_HANDLED\", \"Kernel driver exception handle nahi hui.\", \"Latest installed driver identify karke rollback/update karo; Safe Mode se test karo.\"),\n            \"0x0000007F\": (\"UNEXPECTED_KERNEL_MODE_TRAP\", \"CPU/RAM hardware fault, overheating, ya low-level driver issue.\", \"Temperature, RAM, CPU overclock, BIOS/chipset update check karo.\"),\n            \"0x0000009F\": (\"DRIVER_POWER_STATE_FAILURE\", \"Sleep/shutdown/resume me driver power state atak gaya.\", \"Power management, chipset, Wi-Fi, Bluetooth, GPU drivers update/rollback karo.\"),\n            \"0x000000C2\": (\"BAD_POOL_CALLER\", \"Driver ne memory pool galat tarah use kiya.\", \"Recent driver/app uninstall karo, Driver Verifier culprit ke liye use karo.\"),\n            \"0x000000D1\": (\"DRIVER_IRQL_NOT_LESS_OR_EQUAL\", \"Network/storage/GPU driver ne invalid memory access kiya.\", \"Culprit driver update/rollback karo; dump file WinDbg me analyze karo.\"),\n            \"0x000000EA\": (\"THREAD_STUCK_IN_DEVICE_DRIVER\", \"GPU/display driver loop me phans gaya.\", \"GPU driver clean reinstall, GPU temperature/power check, hardware acceleration test karo.\"),\n            \"0x000000ED\": (\"UNMOUNTABLE_BOOT_VOLUME\", \"Boot volume mount nahi hua; file system/disk problem.\", \"WinRE se chkdsk /f /r, boot repair, disk health check karo.\"),\n            \"0x000000EF\": (\"CRITICAL_PROCESS_DIED\", \"Important Windows process crash ho gaya.\", \"SFC/DISM, malware scan, recent update/driver rollback, disk health check karo.\"),\n            \"0x00000109\": (\"CRITICAL_STRUCTURE_CORRUPTION\", \"Kernel structure corrupt; driver, RAM, malware, overclock possible.\", \"Overclock off, RAM test, malware scan, unsigned drivers check karo.\"),\n            \"0x00000116\": (\"VIDEO_TDR_FAILURE\", \"GPU driver/hardware timeout.\", \"Display driver DDU se clean install, GPU temperature/PSU check, hardware acceleration off test karo.\"),\n            \"0x00000117\": (\"VIDEO_TDR_TIMEOUT_DETECTED\", \"GPU driver ne time par response nahi diya.\", \"Graphics driver update/rollback, temperature/power check karo.\"),\n            \"0x00000124\": (\"WHEA_UNCORRECTABLE_ERROR\", \"Hardware error: CPU, RAM, PCIe, GPU, SSD, PSU ya overheating.\", \"Temps, RAM, SMART, BIOS/chipset update, overclock off, hardware stress test karo.\"),\n            \"0x00000133\": (\"DPC_WATCHDOG_VIOLATION\", \"Driver/SSD controller ne response time exceed kiya.\", \"Storage/NVMe/chipset driver update, SSD firmware, external devices remove test karo.\"),\n            \"0x00000139\": (\"KERNEL_SECURITY_CHECK_FAILURE\", \"Driver/memory corruption ya incompatible software.\", \"Recent driver/app rollback, SFC/DISM, RAM test, malware scan karo.\"),\n        }\n        return key, stop_map.get(key, (\"Unknown stop code\", \"Exact cause dump analysis ke bina confirm nahi hota.\", \"Minidump ko WinDbg/WhoCrashed se analyze karo, phir culprit driver fix karo.\"))\n\n    def _collect_bsod_events(self):\n        script = r\"\"\"\n$ids = @(41,1001,161,6008,17,18,19,1,7,11,51,55,129,153,4101,1101,1102,1201,1202)\n$events = @()\ntry {\n    $events = Get-WinEvent -LogName System -MaxEvents 900 -ErrorAction SilentlyContinue |\n        Where-Object {\n            ($ids -contains $_.Id) -or\n            ($_.ProviderName -match 'BugCheck|Kernel-Power|WHEA|Display|Disk|Ntfs|volmgr|storahci|storport|iaStor|MemoryDiagnostics')\n        } |\n        Select-Object -First 35 `\n            @{n='TimeCreated';e={$_.TimeCreated.ToString('s')}},\n            ProviderName,Id,LevelDisplayName,\n            @{n='Message';e={$_.Message}}\n} catch {}\n$events | ConvertTo-Json -Depth 4\n\"\"\"\n        out, _ = self._run_powershell(script, timeout=60)\n        return self._json_items_from_output(out)\n\n    def _collect_recent_third_party_drivers(self):\n        script = r\"\"\"\n$drivers = @()\ntry {\n    $drivers = Get-CimInstance Win32_PnPSignedDriver -ErrorAction SilentlyContinue |\n        Where-Object { $_.DriverProviderName -and $_.DriverProviderName -notmatch '^Microsoft' } |\n        Sort-Object DriverDate -Descending |\n        Select-Object -First 12 DeviceName,DriverProviderName,DriverVersion,DriverDate\n} catch {}\n$drivers | ConvertTo-Json -Depth 4\n\"\"\"\n        out, _ = self._run_powershell(script, timeout=60)\n        return self._json_items_from_output(out)\n\n    def _build_bsod_deep_report(self):\n        dumps = self._bsod_dump_files()\n        crash_values = self._crash_control_values()\n        events = self._collect_bsod_events()\n        drivers = self._collect_recent_third_party_drivers()\n        verifier_out, _ = self._run_cmd(\"verifier /querysettings\", timeout=25)\n        pagefile_out, _ = self._run_cmd(\"wmic pagefileset get Name,InitialSize,MaximumSize /format:list\", timeout=20)\n\n        findings = []\n        solutions = []\n        stop_codes = []\n\n        for ev in events:\n            msg = str(ev.get(\"Message\", \"\") or \"\")\n            src = str(ev.get(\"ProviderName\", \"\") or \"\")\n            eid = str(ev.get(\"Id\", \"\") or \"\")\n            low = f\"{src} {eid} {msg}\".lower()\n\n            if \"bugcheck\" in low or eid == \"1001\":\n                for found in re.findall(r\"0x[0-9a-fA-F]{1,16}\", msg):\n                    key, (name, reason, solution) = self._bsod_stop_code_details(found)\n                    if key not in [x[0] for x in stop_codes]:\n                        stop_codes.append((key, name, reason, solution))\n                if not re.search(r\"0x[0-9a-fA-F]{1,16}\", msg):\n                    findings.append(\"BugCheck event mila, lekin stop code message me clear nahi tha.\")\n\n            if \"kernel-power\" in low and eid == \"41\":\n                findings.append(\"Kernel-Power 41 mila: PC clean shutdown ke bina restart hua.\")\n                solutions.append(\"Power loss/SMPS/overheating/BSOD path check karo. Agar saath me BugCheck code hai to driver/hardware cause follow karo.\")\n            if \"whea\" in low:\n                findings.append(\"WHEA hardware error event mila: CPU/RAM/PCIe/GPU/SSD side hardware warning possible.\")\n                solutions.append(\"Overclock off, temperature check, BIOS/chipset update, RAM test, SSD SMART, GPU/PCIe seating check karo.\")\n            if \"display\" in low or \"tdr\" in low or eid == \"4101\":\n                findings.append(\"Display/GPU driver reset event mila.\")\n                solutions.append(\"GPU driver clean reinstall/rollback, GPU temperature aur PSU power check karo.\")\n            if any(x in low for x in [\"disk\", \"ntfs\", \"storahci\", \"storport\", \"iastor\"]) or eid in {\"7\", \"11\", \"51\", \"55\", \"129\", \"153\"}:\n                findings.append(\"Disk/storage event mila: storage timeout, NTFS corruption ya bad sector possible.\")\n                solutions.append(\"Important data backup, SMART report, cable/port check, chkdsk /f /r, storage/NVMe driver update karo.\")\n            if \"volmgr\" in low and eid == \"161\":\n                findings.append(\"volmgr 161 mila: crash dump create nahi ho paya.\")\n                solutions.append(\"C: drive free space/pagefile/dump settings check karo; system managed pagefile aur minidump enable karo.\")\n            if \"memorydiagnostics\" in low and (\"hardware problems\" in low or \"detected\" in low):\n                findings.append(\"Memory Diagnostic ne memory problem indicate ki.\")\n                solutions.append(\"RAM sticks reseat karo, single-stick test, MemTest86 4-pass, faulty RAM replace karo.\")\n\n        for key, name, reason, solution in stop_codes:\n            findings.append(f\"Stop Code {key} ({name}): {reason}\")\n            solutions.append(solution)\n\n        dump_enabled = int(crash_values.get(\"CrashDumpEnabled\", -1) or -1)\n        if dump_enabled == 0:\n            findings.append(\"Crash dump disabled hai, isliye future BSOD proof file save nahi hogi.\")\n            solutions.append(\"Enable Minidump button run karo: CrashDumpEnabled=3, MinidumpDir set, AutoReboot off.\")\n        elif dump_enabled not in (1, 2, 3, 7):\n            findings.append(\"Crash dump setting unclear hai; dump capture verify karna chahiye.\")\n\n        if str(crash_values.get(\"AutoReboot\", \"\")).strip() == \"1\":\n            solutions.append(\"AutoReboot off rakhna useful hai, warna blue screen turant restart ho jati hai aur user stop code nahi dekh pata.\")\n\n        if verifier_out and \"No settings\" not in verifier_out and \"not currently enabled\" not in verifier_out:\n            findings.append(\"Driver Verifier active lag raha hai; ye intentionally bad drivers ko BSOD kara sakta hai.\")\n            solutions.append(\"Agar PC boot loop me hai to Safe Mode me `verifier /reset` run karke reboot karo.\")\n\n        lines = []\n        lines.append(\"BSoD Deep Troubleshooting Report (Hinglish)\")\n        lines.append(f\"Generated: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\")\n        lines.append(\"\")\n        lines.append(\"Troubleshoot kya kiya:\")\n        lines.append(\"- C:\\\\Windows\\\\Minidump aur LiveKernelReports me dump files check ki.\")\n        lines.append(\"- Event Viewer me BugCheck, Kernel-Power, WHEA, Display, Disk, NTFS, volmgr events check kiye.\")\n        lines.append(\"- Crash dump registry settings, pagefile setting, Driver Verifier status check kiya.\")\n        lines.append(\"- Recent third-party drivers list kiye, kyunki BSOD ka common cause driver hota hai.\")\n        lines.append(\"\")\n        lines.append(\"Dump files:\")\n        if dumps:\n            for item in dumps[:8]:\n                lines.append(f\"- {item['path']} | {item['mtime']} | {item['size_kb']} KB\")\n        else:\n            lines.append(\"- No dump file found. Ya to recent BSOD nahi hua, ya dump setting/pagefile issue hai.\")\n        lines.append(\"\")\n        lines.append(\"Crash dump settings:\")\n        if crash_values:\n            for key in sorted(crash_values):\n                lines.append(f\"- {key}: {crash_values.get(key)}\")\n        else:\n            lines.append(\"- CrashControl registry read nahi hua. Admin rights required ho sakte hain.\")\n        if pagefile_out.strip():\n            lines.append(\"\")\n            lines.append(\"Pagefile:\")\n            lines.append(pagefile_out.strip()[:900])\n        lines.append(\"\")\n        lines.append(\"Result / likely karan:\")\n        if findings:\n            for item in list(dict.fromkeys(findings))[:14]:\n                lines.append(f\"- {item}\")\n        else:\n            lines.append(\"- Strong BSOD root-cause event nahi mila. Agar issue repeat hota hai to minidump enable karke next crash capture karein.\")\n        lines.append(\"\")\n        lines.append(\"Solution:\")\n        if solutions:\n            for item in list(dict.fromkeys(solutions))[:14]:\n                lines.append(f\"- {item}\")\n        else:\n            lines.append(\"- Windows update complete karo, SFC/DISM run karo, RAM/disk health check karo, aur next dump ko WinDbg/WhoCrashed me analyze karo.\")\n        lines.append(\"\")\n        lines.append(\"Recent matching events:\")\n        if events:\n            for ev in events[:10]:\n                msg = \" \".join(str(ev.get(\"Message\", \"\") or \"\").split())[:240]\n                lines.append(f\"- {ev.get('TimeCreated','')} | {ev.get('ProviderName','')} | ID {ev.get('Id','')} | {msg}\")\n        else:\n            lines.append(\"- No matching Event Viewer data found.\")\n        lines.append(\"\")\n        lines.append(\"Recent non-Microsoft drivers:\")\n        if drivers:\n            for d in drivers[:10]:\n                lines.append(f\"- {d.get('DeviceName','')} | {d.get('DriverProviderName','')} | {d.get('DriverVersion','')} | {d.get('DriverDate','')}\")\n        else:\n            lines.append(\"- Third-party driver list empty/blocked.\")\n        lines.append(\"\")\n        lines.append(\"Customer ko simple explain:\")\n        lines.append(\"Blue screen ka matlab Windows kernel level par serious crash hua. Is report me humne stop code, crash dump, hardware WHEA, disk/NTFS, GPU/display aur driver clues check kiye. Jo clue mila hai uske hisaab se driver update/rollback, RAM/disk test, GPU/storage driver repair, ya minidump enable karna next best step hai.\")\n\n        severity = \"warning\" if findings or dumps else \"success\"\n        return \"\\n\".join(lines), severity, len(findings)\n\n    def _bsod_deep_diagnose(self):\n        if not messagebox.askyesno(\n            \"BSoD Deep Diagnose\",\n            \"Blue screen root-cause diagnosis run karein?\\n\\n\"\n            \"Ye sirf logs/settings check karega. Koi destructive change nahi karega.\"\n        ):\n            return\n        self._append_log(self.trouble_log, \"BSoD Deep Diagnose started...\", C[\"accent3\"])\n        self._set_status(\"BSoD diagnosis running...\", C[\"accent3\"])\n        self._launch_job(\"bsod_deep_diagnose\", self._do_bsod_deep_diagnose)\n\n    def _do_bsod_deep_diagnose(self):\n        try:\n            report, severity, count = self._build_bsod_deep_report()\n            color = C[\"warning\"] if severity == \"warning\" else C[\"success\"]\n            self._append_log(self.trouble_log, \"\\n\" + report + \"\\n\", color)\n            title = \"BSoD Clues Found\" if count else \"BSoD Diagnosis Complete\"\n            msg = (\n                f\"{count} clue(s) found. Full Hinglish report System Repair log me hai.\"\n                if count else\n                \"Strong BSOD clue nahi mila. Full report System Repair log me hai.\"\n            )\n            self.after(0, lambda: messagebox.showwarning(title, msg) if count else messagebox.showinfo(title, msg))\n            self.after(0, lambda: self._set_status(\"BSoD diagnosis complete\", color))\n        except Exception as e:\n            self._append_log(self.trouble_log, f\"BSoD diagnosis failed: {e}\", C[\"error\"])\n            self.after(0, lambda: self._set_status(\"BSoD diagnosis failed\", C[\"error\"]))\n\n    def _enable_bsod_minidump(self):\n        if not messagebox.askyesno(\n            \"Enable Minidump\",\n            \"Future Blue Screen ke proof logs enable karein?\\n\\n\"\n            \"Changes:\\n\"\n            \"- Small memory dump enable\\n\"\n            \"- C:\\\\Windows\\\\Minidump path set\\n\"\n            \"- Event log enable\\n\"\n            \"- Auto restart off, taaki stop code dikhe\\n\\n\"\n            \"Admin rights required.\"\n        ):\n            return\n        self._append_log(self.trouble_log, \"Enabling BSOD minidump settings...\", C[\"accent3\"])\n        try:\n            try:\n                os.makedirs(r\"C:\\Windows\\Minidump\", exist_ok=True)\n            except Exception as e:\n                self._append_log(self.trouble_log, f\"Minidump folder create warning: {e}\", C[\"warning\"])\n            results = [\n                self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Control\\CrashControl\", \"CrashDumpEnabled\", 3, winreg.REG_DWORD, \"Small memory dump enabled\", self.trouble_log),\n                self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Control\\CrashControl\", \"MinidumpDir\", r\"%SystemRoot%\\Minidump\", winreg.REG_EXPAND_SZ, \"Minidump directory set\", self.trouble_log),\n                self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Control\\CrashControl\", \"LogEvent\", 1, winreg.REG_DWORD, \"Crash event logging enabled\", self.trouble_log),\n                self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Control\\CrashControl\", \"AutoReboot\", 0, winreg.REG_DWORD, \"Auto restart after BSOD disabled\", self.trouble_log),\n                self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Control\\CrashControl\", \"Overwrite\", 1, winreg.REG_DWORD, \"Overwrite old dump enabled\", self.trouble_log),\n            ]\n            summary = self._action_summary(\"BSOD Minidump Setup\", results)\n            note = summary[\"message\"] + \"\\n\\nNote: Pagefile system managed hona chahiye, warna dump create fail ho sakta hai.\"\n            self._append_log(self.trouble_log, note, C[\"success\"] if not summary[\"failed\"] else C[\"warning\"])\n            messagebox.showinfo(\"Minidump Setup\", note)\n        except Exception as e:\n            self._append_log(self.trouble_log, f\"Minidump setup failed: {e}\", C[\"error\"])\n            messagebox.showerror(\"Error\", str(e))\n\n    def _collect_rundll32_details(self):\n        sig_script = r\"\"\"\n$paths = @(\"$env:windir\\System32\\rundll32.exe\", \"$env:windir\\SysWOW64\\rundll32.exe\")\n$items = foreach($p in $paths) {\n    $exists = Test-Path $p\n    $sig = $null\n    $file = $null\n    if($exists) {\n        $sig = Get-AuthenticodeSignature $p -ErrorAction SilentlyContinue\n        $file = Get-Item $p -ErrorAction SilentlyContinue\n    }\n    [pscustomobject]@{\n        Path=$p\n        Exists=$exists\n        Length=if($file){$file.Length}else{$null}\n        LastWriteTime=if($file){$file.LastWriteTime.ToString('s')}else{$null}\n        SignatureStatus=if($sig){[string]$sig.Status}else{\"Missing\"}\n        Signer=if($sig -and $sig.SignerCertificate){$sig.SignerCertificate.Subject}else{\"\"}\n    }\n}\n$items | ConvertTo-Json -Depth 4\n\"\"\"\n        startup_script = r\"\"\"\n$items = @()\n$keys = @(\n    'HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Run',\n    'HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce',\n    'HKLM:\\Software\\Microsoft\\Windows\\CurrentVersion\\Run',\n    'HKLM:\\Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce',\n    'HKLM:\\Software\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Run',\n    'HKLM:\\Software\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\RunOnce'\n)\nforeach($k in $keys) {\n    if(Test-Path $k) {\n        $props = Get-ItemProperty $k -ErrorAction SilentlyContinue\n        foreach($p in $props.PSObject.Properties) {\n            if($p.Name -match '^PS') { continue }\n            $v = [string]$p.Value\n            if($v -match 'rundll32|rundell32|rundll32\\.dll|rundell32\\.dll') {\n                $items += [pscustomobject]@{Location=$k;Name=$p.Name;Command=$v}\n            }\n        }\n    }\n}\n$items | ConvertTo-Json -Depth 4\n\"\"\"\n        task_script = r\"\"\"\n$items = @()\ntry {\n    $items = Get-ScheduledTask -ErrorAction SilentlyContinue |\n        Where-Object { ($_.Actions | Out-String) -match 'rundll32|rundell32|rundll32\\.dll|rundell32\\.dll' } |\n        Select-Object -First 30 TaskPath,TaskName,State,@{n='Action';e={($_.Actions | Out-String).Trim()}}\n} catch {}\n$items | ConvertTo-Json -Depth 4\n\"\"\"\n        event_script = r\"\"\"\n$items = @()\nforeach($log in @('Application','System')) {\n    try {\n        $items += Get-WinEvent -LogName $log -MaxEvents 900 -ErrorAction SilentlyContinue |\n            Where-Object {\n                ($_.Message -match 'rundll32|rundell32|rundll32\\.dll|rundell32\\.dll|kernel32\\.dll') -or\n                ($_.ProviderName -match 'SideBySide|Application Error' -and $_.Message -match '\\.dll|module|activation context|kernel32')\n            } |\n            Select-Object -First 25 @{n='Log';e={$log}},@{n='TimeCreated';e={$_.TimeCreated.ToString('s')}},ProviderName,Id,LevelDisplayName,@{n='Message';e={$_.Message}}\n    } catch {}\n}\n$items | Select-Object -First 35 | ConvertTo-Json -Depth 4\n\"\"\"\n        wer_script = r\"\"\"\n$roots = @(\"$env:ProgramData\\Microsoft\\Windows\\WER\\ReportArchive\", \"$env:ProgramData\\Microsoft\\Windows\\WER\\ReportQueue\", \"$env:LOCALAPPDATA\\Microsoft\\Windows\\WER\")\n$items = @()\nforeach($r in $roots) {\n    if(Test-Path $r) {\n        try {\n            $items += Get-ChildItem $r -Recurse -Filter Report.wer -ErrorAction SilentlyContinue |\n                Select-Object -First 80 |\n                ForEach-Object {\n                    $txt = Get-Content $_.FullName -Raw -ErrorAction SilentlyContinue\n                    if($txt -match 'rundll32|rundell32|kernel32\\.dll|Fault Module Name|AppName') {\n                        [pscustomobject]@{Path=$_.FullName;LastWriteTime=$_.LastWriteTime.ToString('s');Text=($txt.Substring(0, [Math]::Min($txt.Length, 2500)))}\n                    }\n                }\n        } catch {}\n    }\n}\n$items | Select-Object -First 30 | ConvertTo-Json -Depth 4\n\"\"\"\n        suspicious_file_script = r\"\"\"\n$paths = @(\n    \"$env:windir\\rundell32.dll\",\n    \"$env:windir\\rundll32.dll\",\n    \"$env:windir\\System32\\rundell32.dll\",\n    \"$env:windir\\System32\\rundll32.dll\",\n    \"$env:windir\\SysWOW64\\rundell32.dll\",\n    \"$env:windir\\SysWOW64\\rundll32.dll\"\n)\n$items = foreach($p in $paths) {\n    if(Test-Path $p) {\n        $f = Get-Item $p -ErrorAction SilentlyContinue\n        [pscustomobject]@{Path=$p;Length=$f.Length;LastWriteTime=$f.LastWriteTime.ToString('s')}\n    }\n}\n$items | ConvertTo-Json -Depth 4\n\"\"\"\n        sig_out, _ = self._run_powershell(sig_script, timeout=35)\n        startup_out, _ = self._run_powershell(startup_script, timeout=35)\n        task_out, _ = self._run_powershell(task_script, timeout=60)\n        event_out, _ = self._run_powershell(event_script, timeout=60)\n        suspicious_file_out, _ = self._run_powershell(suspicious_file_script, timeout=30)\n        wer_out, _ = self._run_powershell(wer_script, timeout=80)\n        where_out, _ = self._run_cmd(\"where rundll32\", timeout=15)\n        return {\n            \"files\": self._json_items_from_output(sig_out),\n            \"startup\": self._json_items_from_output(startup_out),\n            \"tasks\": self._json_items_from_output(task_out),\n            \"events\": self._json_items_from_output(event_out),\n            \"fake\": self._json_items_from_output(suspicious_file_out),\n            \"wer\": self._json_items_from_output(wer_out),\n            \"where\": where_out.strip(),\n        }\n\n    def _build_rundll32_report(self):\n        data = self._collect_rundll32_details()\n        findings = []\n        solutions = []\n\n        for item in data[\"files\"]:\n            path = str(item.get(\"Path\", \"\"))\n            exists = bool(item.get(\"Exists\"))\n            sig = str(item.get(\"SignatureStatus\", \"\"))\n            signer = str(item.get(\"Signer\", \"\"))\n            if not exists:\n                findings.append(f\"{path} missing hai.\")\n                solutions.append(\"System file missing/corrupt ho sakti hai: DISM RestoreHealth aur SFC /SCANNOW run karo.\")\n            elif sig.lower() != \"valid\" or \"microsoft\" not in signer.lower():\n                findings.append(f\"{path} signature suspicious hai: Status={sig}, Signer={signer}\")\n                solutions.append(\"Malware/tampering possible: Defender Offline Scan run karo, phir SFC/DISM se system file repair karo.\")\n\n        if data[\"fake\"]:\n            findings.append(\"rundll32.dll/rundell32.dll naam ki suspicious file mili. Windows ka real file rundll32.exe hota hai.\")\n            solutions.append(\"Suspicious DLL ko direct open/delete na karein. Pehle Defender Offline Scan, then autoruns/startup check karke source remove karein.\")\n\n        typo_hits = []\n        for group in (\"startup\", \"tasks\", \"events\"):\n            for item in data[group]:\n                text = \" \".join(str(v) for v in item.values()).lower()\n                if \"rundell32\" in text or \"rundll32.dll\" in text or \"rundell32.dll\" in text:\n                    typo_hits.append(item)\n        if typo_hits:\n            findings.append(\"rundell32/rundll32.dll typo reference mila. Ye aksar malware ya broken startup entry hoti hai.\")\n            solutions.append(\"Startup/Task Scheduler me us entry ko disable/remove karo, related unknown app uninstall karo, malware scan run karo.\")\n\n        if data[\"startup\"]:\n            findings.append(f\"{len(data['startup'])} startup Run entry rundll32 use kar rahi hai.\")\n            solutions.append(\"Agar error startup par aata hai to listed Run entry ka DLL path check karo; missing DLL ho to entry disable karo ya app reinstall/uninstall karo.\")\n        if data[\"tasks\"]:\n            findings.append(f\"{len(data['tasks'])} scheduled task rundll32 use kar raha hai.\")\n            solutions.append(\"Task Scheduler me listed task ka action verify karo; unknown/publisher-less task disable karke reboot test karo.\")\n\n        for ev in data[\"events\"]:\n            msg = str(ev.get(\"Message\", \"\") or \"\").lower()\n            src = str(ev.get(\"ProviderName\", \"\") or \"\").lower()\n            if \"kernel32.dll\" in msg:\n                findings.append(\"kernel32.dll faulting module event mila.\")\n                solutions.append(\"kernel32.dll aksar victim module hota hai. Real culprit app/plugin/runtime hota hai: affected app repair/reinstall, VC++ runtime repair, SFC/DISM run karo.\")\n            if \"specified module could not be found\" in msg or \"module could not be found\" in msg:\n                findings.append(\"Event log me 'specified module could not be found' mila.\")\n                solutions.append(\"Karan: Windows rundll32.exe se ek DLL load kar raha tha, par DLL missing hai. Solution: startup/task entry remove karo ya related app reinstall karo.\")\n            if \"sidebyside\" in src or \"activation context\" in msg:\n                findings.append(\"SideBySide/activation context DLL error mila.\")\n                solutions.append(\"Karan: app runtime/VC++ dependency mismatch. Solution: affected app reinstall karo aur Microsoft Visual C++ Redistributables repair/install karo.\")\n            if \"faulting application name: rundll32.exe\" in msg:\n                findings.append(\"rundll32.exe crash event mila.\")\n                solutions.append(\"Karan usually loaded DLL/plugin hota hai, rundll32.exe khud nahi. Event message me faulting module/app identify karke us app/driver ko repair karo.\")\n        for wer in data.get(\"wer\", []):\n            text = str(wer.get(\"Text\", \"\") or \"\").lower()\n            if \"kernel32.dll\" in text or \"rundll32\" in text or \"rundell32\" in text:\n                findings.append(\"WER crash report me kernel32/rundll32 related crash evidence mila.\")\n                solutions.append(\"WER report me AppName/Fault Module dekho; us affected app ko repair/reinstall karo aur dependency/runtime issue fix karo.\")\n\n        lines = []\n        lines.append(\"Kernel32 + Rundll32 / Rundell32 DLL Error Troubleshooting Report (Hinglish)\")\n        lines.append(f\"Generated: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\")\n        lines.append(\"\")\n        lines.append(\"Important clarification:\")\n        lines.append(\"- Windows ka real component rundll32.exe hota hai, rundell32.dll nahi.\")\n        lines.append(\"- Error usually tab aata hai jab startup/task/app rundll32.exe ke through ek DLL load karna chahta hai, par DLL missing/corrupt/incompatible hoti hai.\")\n        lines.append(\"\")\n        lines.append(\"Troubleshoot kya kiya:\")\n        lines.append(\"- System32 aur SysWOW64 me rundll32.exe file existence/signature check ki.\")\n        lines.append(\"- where rundll32 se PATH hijack check kiya.\")\n        lines.append(\"- Registry Run/RunOnce startup entries me rundll32/rundell32 references dhoonde.\")\n        lines.append(\"- Scheduled Tasks me rundll32 actions check kiye.\")\n        lines.append(\"- Event Viewer me rundll32, rundell32, kernel32, SideBySide, module/DLL errors check kiye.\")\n        lines.append(\"- WER ReportArchive/ReportQueue me faulting module crash reports check kiye.\")\n        lines.append(\"- Fake/suspicious rundll32.dll/rundell32.dll files common Windows folders me check ki.\")\n        lines.append(\"\")\n        lines.append(\"File status:\")\n        if data[\"files\"]:\n            for item in data[\"files\"]:\n                lines.append(f\"- {item.get('Path','')} | Exists={item.get('Exists')} | Signature={item.get('SignatureStatus')} | Signer={item.get('Signer','')}\")\n        else:\n            lines.append(\"- File signature data read nahi hua.\")\n        lines.append(\"\")\n        lines.append(\"where rundll32:\")\n        lines.append(data[\"where\"] or \"No PATH result.\")\n        lines.append(\"\")\n        lines.append(\"Result / likely karan:\")\n        if findings:\n            for item in list(dict.fromkeys(findings))[:14]:\n                lines.append(f\"- {item}\")\n        else:\n            lines.append(\"- rundll32 related strong problem nahi mila. Agar popup aa raha hai, exact popup text/DLL name note karke startup/task me search karein.\")\n        lines.append(\"\")\n        lines.append(\"Solution:\")\n        if solutions:\n            for item in list(dict.fromkeys(solutions))[:14]:\n                lines.append(f\"- {item}\")\n        else:\n            lines.append(\"- SFC/DISM run karo, unknown startup entries disable karo, affected app reinstall/uninstall karo, malware scan run karo.\")\n        lines.append(\"\")\n        lines.append(\"Startup entries:\")\n        if data[\"startup\"]:\n            for item in data[\"startup\"][:12]:\n                lines.append(f\"- {item.get('Location','')} | {item.get('Name','')} | {item.get('Command','')}\")\n        else:\n            lines.append(\"- No rundll32 startup entry found.\")\n        lines.append(\"\")\n        lines.append(\"Scheduled tasks:\")\n        if data[\"tasks\"]:\n            for item in data[\"tasks\"][:12]:\n                action = \" \".join(str(item.get(\"Action\", \"\")).split())[:260]\n                lines.append(f\"- {item.get('TaskPath','')}{item.get('TaskName','')} | {item.get('State','')} | {action}\")\n        else:\n            lines.append(\"- No rundll32 scheduled task found.\")\n        lines.append(\"\")\n        lines.append(\"Recent related events:\")\n        if data[\"events\"]:\n            for ev in data[\"events\"][:10]:\n                msg = \" \".join(str(ev.get(\"Message\", \"\") or \"\").split())[:260]\n                lines.append(f\"- {ev.get('TimeCreated','')} | {ev.get('ProviderName','')} | ID {ev.get('Id','')} | {msg}\")\n        else:\n            lines.append(\"- No recent related Event Viewer error found.\")\n        lines.append(\"\")\n        lines.append(\"WER reports:\")\n        if data.get(\"wer\"):\n            for wer in data[\"wer\"][:8]:\n                sample = \" \".join(str(wer.get(\"Text\", \"\") or \"\").split())[:260]\n                lines.append(f\"- {wer.get('LastWriteTime','')} | {wer.get('Path','')} | {sample}\")\n        else:\n            lines.append(\"- No related WER crash reports found.\")\n        lines.append(\"\")\n        lines.append(\"Customer ko simple explain:\")\n        lines.append(\"Rundll32.exe Windows ka loader hai aur kernel32.dll core Windows library hai. Popup/crash me inka naam aane ka matlab aksar ye hota hai ki koi app, startup entry, shell extension, driver, ya missing DLL inke through fail ho raha hai. Humne file signature, startup, scheduled task, Event Viewer aur WER crash reports check kiye. Jo entry/app/module culprit ho usko reinstall/uninstall/disable karein, malware scan plus SFC/DISM run karein.\")\n\n        return \"\\n\".join(lines), (\"warning\" if findings else \"success\"), len(findings)\n\n    def _rundll32_error_diagnose(self):\n        if not messagebox.askyesno(\n            \"Rundll32 Error Check\",\n            \"rundll32/rundell32 DLL error diagnosis run karein?\\n\\n\"\n            \"Ye logs, startup entries aur file signature check karega. Koi entry delete nahi karega.\"\n        ):\n            return\n        self._append_log(self.trouble_log, \"Rundll32 Error Check started...\", C[\"btn_info\"])\n        self._set_status(\"Rundll32 diagnosis running...\", C[\"btn_info\"])\n        self._launch_job(\"rundll32_error_diagnose\", self._do_rundll32_error_diagnose)\n\n    def _do_rundll32_error_diagnose(self):\n        try:\n            report, severity, count = self._build_rundll32_report()\n            color = C[\"warning\"] if severity == \"warning\" else C[\"success\"]\n            self._append_log(self.trouble_log, \"\\n\" + report + \"\\n\", color)\n            title = \"Rundll32 Clues Found\" if count else \"Rundll32 Check Complete\"\n            msg = (\n                f\"{count} clue(s) found. Full Hinglish report System Repair log me hai.\"\n                if count else\n                \"Strong rundll32 problem nahi mila. Full report System Repair log me hai.\"\n            )\n            self.after(0, lambda: messagebox.showwarning(title, msg) if count else messagebox.showinfo(title, msg))\n            self.after(0, lambda: self._set_status(\"Rundll32 diagnosis complete\", color))\n        except Exception as e:\n            self._append_log(self.trouble_log, f\"Rundll32 diagnosis failed: {e}\", C[\"error\"])\n            self.after(0, lambda: self._set_status(\"Rundll32 diagnosis failed\", C[\"error\"]))\n\n    def _show_text_report_window(self, title, text):\n        win = tk.Toplevel(self)\n        win.title(title)\n        win.geometry(\"1050x700\")\n        win.configure(bg=C[\"bg\"])\n        viewer = scrolledtext.ScrolledText(\n            win, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"],\n            insertbackground=C[\"text\"], wrap=\"word\"\n        )\n        viewer.pack(fill=\"both\", expand=True, padx=10, pady=10)\n        viewer.insert(\"1.0\", self._fix_text(text))\n        viewer.config(state=\"disabled\")\n\n    def _find_debugger_engine(self):\n        candidates = []\n        for exe in (\"cdb.exe\", \"kd.exe\", \"windbg.exe\"):\n            path = shutil.which(exe)\n            if path:\n                candidates.append(path)\n        roots = [\n            os.environ.get(\"ProgramFiles\", r\"C:\\Program Files\"),\n            os.environ.get(\"ProgramFiles(x86)\", r\"C:\\Program Files (x86)\"),\n        ]\n        rels = [\n            r\"Windows Kits\\10\\Debuggers\\x64\\cdb.exe\",\n            r\"Windows Kits\\10\\Debuggers\\x86\\cdb.exe\",\n            r\"Windows Kits\\10\\Debuggers\\x64\\kd.exe\",\n            r\"Windows Kits\\10\\Debuggers\\x64\\windbg.exe\",\n        ]\n        for root in roots:\n            if not root:\n                continue\n            for rel in rels:\n                p = os.path.join(root, rel)\n                if os.path.exists(p):\n                    candidates.append(p)\n        seen = set()\n        for p in candidates:\n            key = p.lower()\n            if key not in seen:\n                seen.add(key)\n                return p\n        return \"\"\n\n    def _parse_windbg_analysis(self, text):\n        data = {}\n        patterns = {\n            \"bugcheck\": r\"BUGCHECK_CODE:\\s+([^\\r\\n]+)\",\n            \"exception_code\": r\"EXCEPTION_CODE:\\s+\\(?([^\\s\\)]+)\",\n            \"probably_caused_by\": r\"Probably caused by\\s+:\\s+([^\\r\\n]+)\",\n            \"module_name\": r\"MODULE_NAME:\\s+([^\\r\\n]+)\",\n            \"image_name\": r\"IMAGE_NAME:\\s+([^\\r\\n]+)\",\n            \"failure_bucket\": r\"FAILURE_BUCKET_ID:\\s+([^\\r\\n]+)\",\n            \"process_name\": r\"PROCESS_NAME:\\s+([^\\r\\n]+)\",\n        }\n        for key, pat in patterns.items():\n            m = re.search(pat, text, re.I)\n            if m:\n                data[key] = m.group(1).strip()\n        stack = []\n        capture = False\n        for ln in text.splitlines():\n            if ln.strip().upper().startswith(\"STACK_TEXT\"):\n                capture = True\n                continue\n            if capture:\n                if not ln.strip():\n                    if stack:\n                        break\n                    continue\n                if len(stack) &lt; 18:\n                    stack.append(ln.rstrip())\n        data[\"stack\"] = stack\n        return data\n\n    def _build_windbg_report(self, dump_path):\n        dbg = self._find_debugger_engine()\n        if not dbg:\n            return (\n                \"WinDbg automation unavailable.\\n\\n\"\n                \"Debugging Tools for Windows/cdb.exe system me nahi mila.\\n\"\n                \"Install Windows SDK Debugging Tools, phir ye button !analyze -v automation run karega.\\n\\n\"\n                f\"Dump selected: {dump_path}\",\n                \"warning\"\n            )\n        cmd_script = \".symfix;.reload;!analyze -v;lm;k;q\"\n        cmd = f'\"{dbg}\" -z \"{dump_path}\" -c \"{cmd_script}\"'\n        out, rc = self._run_cmd(cmd, timeout=900)\n        parsed = self._parse_windbg_analysis(out)\n        lines = [\n            \"WinDbg Automated Crash Analysis\",\n            f\"Generated: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\",\n            f\"Debugger: {dbg}\",\n            f\"Dump: {dump_path}\",\n            f\"Return code: {rc}\",\n            \"\",\n            \"Commands executed:\",\n            \".symfix\",\n            \".reload\",\n            \"!analyze -v\",\n            \"lm\",\n            \"k\",\n            \"\",\n            \"Parsed result:\",\n        ]\n        if parsed:\n            for k in (\"bugcheck\", \"exception_code\", \"probably_caused_by\", \"module_name\", \"image_name\", \"failure_bucket\", \"process_name\"):\n                if parsed.get(k):\n                    lines.append(f\"- {k}: {parsed[k]}\")\n            if parsed.get(\"bugcheck\"):\n                key, detail = self._bsod_stop_code_details(parsed[\"bugcheck\"])\n                lines.append(f\"- stop code explain: {key} {detail[0]} | {detail[1]}\")\n                lines.append(f\"- solution: {detail[2]}\")\n            if parsed.get(\"probably_caused_by\"):\n                lines.append(\"\")\n                lines.append(\"Suspected driver/app:\")\n                lines.append(f\"- {parsed['probably_caused_by']}\")\n                lines.append(\"- Is driver/app ko update, rollback, ya clean reinstall karke retest karein.\")\n            if parsed.get(\"stack\"):\n                lines.append(\"\")\n                lines.append(\"Stack trace sample:\")\n                lines.extend(parsed[\"stack\"])\n        else:\n            lines.append(\"- WinDbg output parse nahi hua. Raw output neeche diya hai.\")\n        lines.append(\"\")\n        lines.append(\"Raw WinDbg output tail:\")\n        lines.append(out[-6000:] if out else \"No output\")\n        return \"\\n\".join(lines), (\"warning\" if parsed else \"success\")\n\n    def _windbg_dump_analyze(self):\n        dumps = self._bsod_dump_files()\n        if not dumps:\n            messagebox.showinfo(\"No Dump\", \"C:\\\\Windows\\\\Minidump ya MEMORY.DMP me dump file nahi mili.\")\n            return\n        latest = dumps[0][\"path\"]\n        if not messagebox.askyesno(\n            \"WinDbg Dump Analyze\",\n            f\"Latest dump analyze karein?\\n\\n{latest}\\n\\n\"\n            \"Ye WinDbg/cdb.exe available hone par symbols load karke !analyze -v run karega.\"\n        ):\n            return\n        self._append_log(self.trouble_log, f\"WinDbg analysis started: {latest}\", C[\"accent4\"])\n        self._set_status(\"WinDbg dump analysis running...\", C[\"accent4\"])\n        self._launch_job(\"windbg_dump_analyze\", self._do_windbg_dump_analyze, latest)\n\n    def _do_windbg_dump_analyze(self, dump_path):\n        try:\n            report, severity = self._build_windbg_report(dump_path)\n            color = C[\"warning\"] if severity == \"warning\" else C[\"success\"]\n            self._append_log(self.trouble_log, \"\\n\" + report + \"\\n\", color)\n            self.after(0, lambda: self._show_text_report_window(\"WinDbg Dump Analysis\", report))\n            self.after(0, lambda: self._set_status(\"WinDbg analysis complete\", color))\n        except Exception as e:\n            self._append_log(self.trouble_log, f\"WinDbg analysis failed: {e}\", C[\"error\"])\n            self.after(0, lambda: self._set_status(\"WinDbg analysis failed\", C[\"error\"]))\n\n    def _collect_correlation_events(self):\n        script = r\"\"\"\n$ids = @(41,1001,6008,7031,7034,7000,7001,7,11,51,55,129,153,161,17,18,19,4101,1000,1002)\n$all = @()\nforeach($log in @('System','Application')) {\n    try {\n        $all += Get-WinEvent -LogName $log -MaxEvents 700 -ErrorAction SilentlyContinue |\n            Where-Object { ($ids -contains $_.Id) -or $_.LevelDisplayName -match 'Critical|Error' } |\n            Select-Object @{n='Log';e={$log}},@{n='TimeCreated';e={$_.TimeCreated.ToString('s')}},\n                ProviderName,Id,LevelDisplayName,@{n='Message';e={$_.Message}}\n    } catch {}\n}\n$all | Sort-Object TimeCreated -Descending | Select-Object -First 120 | ConvertTo-Json -Depth 4\n\"\"\"\n        out, _ = self._run_powershell(script, timeout=80)\n        return self._json_items_from_output(out)\n\n    def _build_event_correlation_report(self):\n        events = self._collect_correlation_events()\n        categories = {\n            \"Kernel-Power / dirty shutdown\": [],\n            \"BugCheck / BSOD\": [],\n            \"Service crashes\": [],\n            \"Disk / NTFS / storage\": [],\n            \"WHEA hardware\": [],\n            \"Application crashes\": [],\n        }\n        for ev in events:\n            text = f\"{ev.get('ProviderName','')} {ev.get('Id','')} {ev.get('Message','')}\".lower()\n            eid = str(ev.get(\"Id\", \"\"))\n            if \"kernel-power\" in text or eid == \"6008\":\n                categories[\"Kernel-Power / dirty shutdown\"].append(ev)\n            if \"bugcheck\" in text or eid == \"1001\":\n                categories[\"BugCheck / BSOD\"].append(ev)\n            if \"service control manager\" in text or eid in {\"7031\", \"7034\", \"7000\", \"7001\"}:\n                categories[\"Service crashes\"].append(ev)\n            if any(x in text for x in (\"disk\", \"ntfs\", \"storahci\", \"storport\", \"volmgr\")) or eid in {\"7\", \"11\", \"51\", \"55\", \"129\", \"153\", \"161\"}:\n                categories[\"Disk / NTFS / storage\"].append(ev)\n            if \"whea\" in text or eid in {\"17\", \"18\", \"19\"}:\n                categories[\"WHEA hardware\"].append(ev)\n            if \"application error\" in text or eid in {\"1000\", \"1002\"}:\n                categories[\"Application crashes\"].append(ev)\n        lines = [\n            \"Event Correlation Report\",\n            f\"Generated: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\",\n            \"\",\n            \"Troubleshoot kya kiya:\",\n            \"- System/Application logs se critical/error events collect kiye.\",\n            \"- Kernel-Power, BugCheck, service crash, disk/NTFS, WHEA, application crash ko timeline me correlate kiya.\",\n            \"\",\n            \"Root-cause summary:\",\n        ]\n        for name, items in categories.items():\n            lines.append(f\"- {name}: {len(items)} event(s)\")\n        if categories[\"BugCheck / BSOD\"] and categories[\"Kernel-Power / dirty shutdown\"]:\n            lines.append(\"- Probable: dirty shutdown Kernel-Power ke peeche actual BugCheck/BSOD ho sakta hai.\")\n        if categories[\"WHEA hardware\"]:\n            lines.append(\"- Probable: hardware/thermal/PCIe/RAM/SSD issue BSOD ya restart ka source ho sakta hai.\")\n        if categories[\"Disk / NTFS / storage\"]:\n            lines.append(\"- Probable: disk/storage timeout ya NTFS corruption system freeze/BSOD trigger kar sakta hai.\")\n        if categories[\"Service crashes\"] and not categories[\"BugCheck / BSOD\"]:\n            lines.append(\"- Probable: Windows service/app instability hai; service dependencies aur recent updates check karo.\")\n        lines.append(\"\")\n        lines.append(\"Chronological events (latest first):\")\n        for ev in events[:35]:\n            msg = \" \".join(str(ev.get(\"Message\", \"\") or \"\").split())[:220]\n            lines.append(f\"- {ev.get('TimeCreated','')} | {ev.get('Log','')} | {ev.get('ProviderName','')} | ID {ev.get('Id','')} | {msg}\")\n        return \"\\n\".join(lines), (\"warning\" if events else \"success\")\n\n    def _event_correlation_report(self):\n        self._append_log(self.trouble_log, \"Event correlation started...\", C[\"btn\"])\n        self._set_status(\"Event correlation running...\", C[\"btn\"])\n        self._launch_job(\"event_correlation_report\", self._do_event_correlation_report)\n\n    def _do_event_correlation_report(self):\n        try:\n            report, severity = self._build_event_correlation_report()\n            color = C[\"warning\"] if severity == \"warning\" else C[\"success\"]\n            self._append_log(self.trouble_log, \"\\n\" + report + \"\\n\", color)\n            self.after(0, lambda: self._show_text_report_window(\"Event Correlation Report\", report))\n            self.after(0, lambda: self._set_status(\"Event correlation complete\", color))\n        except Exception as e:\n            self._append_log(self.trouble_log, f\"Event correlation failed: {e}\", C[\"error\"])\n\n    def _build_driver_diagnostics_report(self):\n        driverquery_out, _ = self._run_cmd(\"driverquery /v /fo csv\", timeout=80)\n        script = r\"\"\"\n$drivers = @()\ntry {\n    $drivers = Get-CimInstance Win32_PnPSignedDriver -ErrorAction SilentlyContinue |\n        Select-Object DeviceName,DriverProviderName,DriverVersion,DriverDate,InfName,IsSigned |\n        Sort-Object DriverDate -Descending\n} catch {}\n$sys = @()\ntry {\n    $sys = Get-ChildItem \"$env:windir\\System32\\drivers\\*.sys\" -ErrorAction SilentlyContinue |\n        Sort-Object LastWriteTime -Descending |\n        Select-Object -First 80 FullName,Length,LastWriteTime,@{n='Signature';e={(Get-AuthenticodeSignature $_.FullName -ErrorAction SilentlyContinue).Status}}\n} catch {}\n[pscustomobject]@{PnP=$drivers;SysFiles=$sys} | ConvertTo-Json -Depth 5\n\"\"\"\n        out, _ = self._run_powershell(script, timeout=120)\n        items = self._json_items_from_output(out)\n        payload = items[0] if items else {}\n        pnp = payload.get(\"PnP\", []) if isinstance(payload, dict) else []\n        sysfiles = payload.get(\"SysFiles\", []) if isinstance(payload, dict) else []\n        if isinstance(pnp, dict):\n            pnp = [pnp]\n        if isinstance(sysfiles, dict):\n            sysfiles = [sysfiles]\n\n        unsigned = []\n        old = []\n        recent = []\n        now = datetime.datetime.now()\n        for d in pnp:\n            signed = str(d.get(\"IsSigned\", \"\")).lower()\n            provider = str(d.get(\"DriverProviderName\", \"\") or \"\")\n            date_s = str(d.get(\"DriverDate\", \"\") or \"\")\n            if signed in {\"false\", \"0\"}:\n                unsigned.append(d)\n            if provider and \"microsoft\" not in provider.lower():\n                recent.append(d)\n            try:\n                dt = datetime.datetime.fromisoformat(date_s[:19])\n                if (now - dt).days &gt; 1460 and \"microsoft\" not in provider.lower():\n                    old.append(d)\n            except Exception:\n                pass\n        bad_sig = [x for x in sysfiles if str(x.get(\"Signature\", \"\")).lower() not in {\"valid\"}]\n\n        lines = [\n            \"Driver Diagnostics Report\",\n            f\"Generated: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\",\n            \"\",\n            \"Troubleshoot kya kiya:\",\n            \"- driverquery /v output collect kiya.\",\n            \"- Win32_PnPSignedDriver se provider/date/version check kiya.\",\n            \"- .sys driver file signatures check kiye.\",\n            \"\",\n            \"Summary:\",\n            f\"- PnP drivers read: {len(pnp)}\",\n            f\"- Unsigned PnP drivers: {len(unsigned)}\",\n            f\"- Old third-party drivers (&gt;4 years): {len(old)}\",\n            f\"- Suspicious/invalid .sys signatures: {len(bad_sig)}\",\n            \"\",\n            \"Likely BSOD driver clues:\",\n        ]\n        if unsigned:\n            lines.append(\"- Unsigned drivers kernel crash ka risk badhate hain.\")\n        if old:\n            lines.append(\"- Bahut purane third-party drivers Windows update ke baad BSOD de sakte hain.\")\n        if bad_sig:\n            lines.append(\"- Invalid signature .sys file malware/tampering/corruption ka clue ho sakta hai.\")\n        if not (unsigned or old or bad_sig):\n            lines.append(\"- Strong driver risk nahi mila; recent driver changes still verify karein.\")\n        lines.append(\"\")\n        lines.append(\"Unsigned drivers:\")\n        for d in unsigned[:20]:\n            lines.append(f\"- {d.get('DeviceName','')} | {d.get('DriverProviderName','')} | {d.get('DriverVersion','')} | {d.get('InfName','')}\")\n        if not unsigned:\n            lines.append(\"- None detected.\")\n        lines.append(\"\")\n        lines.append(\"Recent third-party drivers:\")\n        for d in recent[:20]:\n            lines.append(f\"- {d.get('DriverDate','')} | {d.get('DeviceName','')} | {d.get('DriverProviderName','')} | {d.get('DriverVersion','')}\")\n        lines.append(\"\")\n        lines.append(\"Driver file signature warnings:\")\n        for f in bad_sig[:20]:\n            lines.append(f\"- {f.get('Signature','')} | {f.get('LastWriteTime','')} | {f.get('FullName','')}\")\n        if not bad_sig:\n            lines.append(\"- None detected.\")\n        lines.append(\"\")\n        lines.append(\"driverquery sample:\")\n        lines.append(driverquery_out[:2500] if driverquery_out else \"driverquery output empty.\")\n        return \"\\n\".join(lines), (\"warning\" if unsigned or old or bad_sig else \"success\")\n\n    def _driver_diagnostics_report(self):\n        self._append_log(self.trouble_log, \"Driver diagnostics started...\", C[\"btn_warn\"])\n        self._launch_job(\"driver_diagnostics_report\", self._do_driver_diagnostics_report)\n\n    def _do_driver_diagnostics_report(self):\n        try:\n            report, severity = self._build_driver_diagnostics_report()\n            color = C[\"warning\"] if severity == \"warning\" else C[\"success\"]\n            self._append_log(self.trouble_log, \"\\n\" + report + \"\\n\", color)\n            self.after(0, lambda: self._show_text_report_window(\"Driver Diagnostics\", report))\n            self.after(0, lambda: self._set_status(\"Driver diagnostics complete\", color))\n        except Exception as e:\n            self._append_log(self.trouble_log, f\"Driver diagnostics failed: {e}\", C[\"error\"])\n\n    def _build_hardware_health_report(self):\n        script = r\"\"\"\n$phys = @()\n$reli = @()\n$disk = @()\n$mem = @()\ntry { $phys = Get-PhysicalDisk | Select FriendlyName,MediaType,HealthStatus,OperationalStatus,Size } catch {}\ntry { $reli = Get-PhysicalDisk | Get-StorageReliabilityCounter | Select DeviceId,Temperature,ReadErrorsTotal,WriteErrorsTotal,Wear,PowerOnHours } catch {}\ntry { $disk = Get-Disk | Select Number,FriendlyName,HealthStatus,OperationalStatus,PartitionStyle,Size } catch {}\ntry {\n    $mem = Get-WinEvent -LogName System -MaxEvents 300 -ErrorAction SilentlyContinue |\n        Where-Object { $_.ProviderName -match 'MemoryDiagnostics|WHEA' } |\n        Select-Object -First 25 @{n='TimeCreated';e={$_.TimeCreated.ToString('s')}},ProviderName,Id,LevelDisplayName,@{n='Message';e={$_.Message}}\n} catch {}\n[pscustomobject]@{PhysicalDisk=$phys;Reliability=$reli;Disk=$disk;HardwareEvents=$mem} | ConvertTo-Json -Depth 5\n\"\"\"\n        out, _ = self._run_powershell(script, timeout=90)\n        wmic_out, _ = self._run_cmd(\"wmic diskdrive get Caption,Model,Status,MediaType,Size /format:list\", timeout=25)\n        smartctl_path = shutil.which(\"smartctl.exe\") or shutil.which(\"smartctl\")\n        smartctl_out = \"\"\n        if smartctl_path:\n            scan, _ = self._run_cmd(f'\"{smartctl_path}\" --scan', timeout=20)\n            smartctl_out += scan + \"\\n\"\n            for ln in scan.splitlines()[:4]:\n                dev = ln.split()[0] if ln.strip() else \"\"\n                if dev:\n                    detail, _ = self._run_cmd(f'\"{smartctl_path}\" -H -A \"{dev}\"', timeout=45)\n                    smartctl_out += f\"\\n--- {dev} ---\\n{detail[:2500]}\\n\"\n        items = self._json_items_from_output(out)\n        payload = items[0] if items else {}\n        warnings = []\n        text_blob = json.dumps(payload, default=str).lower() + \"\\n\" + wmic_out.lower() + \"\\n\" + smartctl_out.lower()\n        for word, msg in [\n            (\"unhealthy\", \"Disk health unhealthy report hua.\"),\n            (\"warning\", \"Disk/hardware warning status mila.\"),\n            (\"pred fail\", \"SMART predicted failure ka clue mila.\"),\n            (\"readerror\", \"Read errors storage surface/controller issue dikha sakte hain.\"),\n            (\"writeerror\", \"Write errors storage media/controller issue dikha sakte hain.\"),\n            (\"whea\", \"WHEA hardware event mila.\"),\n            (\"memorydiagnostics\", \"Memory diagnostic event mila.\"),\n        ]:\n            if word in text_blob:\n                warnings.append(msg)\n        lines = [\n            \"SMART + Hardware Health Report\",\n            f\"Generated: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\",\n            \"\",\n            \"Troubleshoot kya kiya:\",\n            \"- Get-PhysicalDisk, Get-Disk, StorageReliabilityCounter check kiya.\",\n            \"- WMIC diskdrive status collect kiya.\",\n            \"- smartctl available ho to SMART health/attributes read kiye.\",\n            \"- WHEA/MemoryDiagnostics events check kiye.\",\n            \"\",\n            \"Result / warnings:\",\n        ]\n        if warnings:\n            for item in list(dict.fromkeys(warnings)):\n                lines.append(f\"- {item}\")\n        else:\n            lines.append(\"- Strong hardware warning nahi mila, lekin full SMART vendor attributes manually bhi verify karein.\")\n        lines.append(\"\")\n        lines.append(\"PowerShell hardware data:\")\n        lines.append(json.dumps(payload, ensure_ascii=False, indent=2, default=str)[:7000])\n        lines.append(\"\")\n        lines.append(\"WMIC disk status:\")\n        lines.append(wmic_out or \"WMIC output empty.\")\n        lines.append(\"\")\n        lines.append(\"smartctl:\")\n        lines.append(smartctl_out if smartctl_out else \"smartctl installed nahi mila. Install ho to detailed SMART attributes milenge.\")\n        return \"\\n\".join(lines), (\"warning\" if warnings else \"success\")\n\n    def _hardware_health_report(self):\n        self._append_log(self.trouble_log, \"Hardware health report started...\", C[\"hw_accent\"])\n        self._launch_job(\"hardware_health_report\", self._do_hardware_health_report)\n\n    def _do_hardware_health_report(self):\n        try:\n            report, severity = self._build_hardware_health_report()\n            color = C[\"warning\"] if severity == \"warning\" else C[\"success\"]\n            self._append_log(self.trouble_log, \"\\n\" + report + \"\\n\", color)\n            self.after(0, lambda: self._show_text_report_window(\"Hardware Health Report\", report))\n            self.after(0, lambda: self._set_status(\"Hardware health complete\", color))\n        except Exception as e:\n            self._append_log(self.trouble_log, f\"Hardware health failed: {e}\", C[\"error\"])\n\n    def _repair_verification_report(self):\n        if not messagebox.askyesno(\n            \"Repair Verification\",\n            \"Repair verification run karein?\\n\\n\"\n            \"Ye SFC /VERIFYONLY, DISM /ScanHealth aur recent error logs check karega. Time lag sakta hai.\"\n        ):\n            return\n        self._append_log(self.trouble_log, \"Repair verification started...\", C[\"accent2\"])\n        self._set_status(\"Repair verification running...\", C[\"accent2\"])\n        self._launch_job(\"repair_verification_report\", self._do_repair_verification_report)\n\n    def _do_repair_verification_report(self):\n        try:\n            lines = [\n                \"Repair Verification Report\",\n                f\"Generated: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\",\n                \"\",\n                \"Step 1: SFC /VERIFYONLY\",\n            ]\n            sfc, rc_sfc, to_sfc, stop_sfc = self._stream_cmd_to_log([\"sfc\", \"/verifyonly\"], self.trouble_log, timeout_s=1200)\n            lines.append(f\"SFC rc={rc_sfc}, timeout={to_sfc}, stopped={stop_sfc}\")\n            if \"no integrity violations\" in sfc.lower():\n                lines.append(\"SFC Result: Windows protected files clean.\")\n            elif \"integrity violations\" in sfc.lower():\n                lines.append(\"SFC Result: Corruption/violations detected. Run SFC /SCANNOW + DISM RestoreHealth.\")\n            else:\n                lines.append(\"SFC Result: Output manually review karein.\")\n            lines.append(\"\")\n            lines.append(\"Step 2: DISM /ScanHealth\")\n            dism, rc_dism, to_dism, stop_dism = self._stream_cmd_to_log(\n                [\"DISM\", \"/Online\", \"/Cleanup-Image\", \"/ScanHealth\"], self.trouble_log, timeout_s=1800\n            )\n            lines.append(f\"DISM rc={rc_dism}, timeout={to_dism}, stopped={stop_dism}\")\n            if \"no component store corruption detected\" in dism.lower():\n                lines.append(\"DISM Result: Component store clean.\")\n            elif \"repairable\" in dism.lower() or \"corruption\" in dism.lower():\n                lines.append(\"DISM Result: Component store issue detected. RestoreHealth run karein.\")\n            else:\n                lines.append(\"DISM Result: Output manually review karein.\")\n            lines.append(\"\")\n            lines.append(\"Step 3: Recent repair-related events\")\n            events = self._collect_correlation_events()\n            for ev in events[:20]:\n                msg = \" \".join(str(ev.get(\"Message\", \"\") or \"\").split())[:220]\n                lines.append(f\"- {ev.get('TimeCreated','')} | {ev.get('ProviderName','')} | ID {ev.get('Id','')} | {msg}\")\n            report = \"\\n\".join(lines)\n            color = C[\"warning\"] if (\"detected\" in report.lower() and \"clean\" not in report.lower()) else C[\"success\"]\n            self._append_log(self.trouble_log, \"\\n\" + report + \"\\n\", color)\n            self.after(0, lambda: self._show_text_report_window(\"Repair Verification\", report))\n            self.after(0, lambda: self._set_status(\"Repair verification complete\", color))\n        except Exception as e:\n            self._append_log(self.trouble_log, f\"Repair verification failed: {e}\", C[\"error\"])\n            self.after(0, lambda: self._set_status(\"Repair verification failed\", C[\"error\"]))\n\n    def _boot_status_bcd_backup(self):\n        if not messagebox.askyesno(\n            \"Boot Status + BCD Backup\",\n            \"Boot status analyze aur BCD backup create karein?\\n\\n\"\n            \"Ye destructive repair nahi karega. Sirf BCD export + EFI/boot info report banayega.\"\n        ):\n            return\n        self._append_log(self.trouble_log, \"Boot status + BCD backup started...\", C[\"btn_chip\"])\n        self._launch_job(\"boot_status_bcd_backup\", self._do_boot_status_bcd_backup)\n\n    def _do_boot_status_bcd_backup(self):\n        try:\n            os.makedirs(getattr(self, \"backup_dir\", os.getcwd()), exist_ok=True)\n            ts = datetime.datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n            bcd_path = os.path.join(self.backup_dir, f\"BCD_Backup_{ts}.bcd\")\n            enum_out, _ = self._run_cmd([\"bcdedit\", \"/enum\", \"all\"], timeout=40)\n            export_out, rc_export = self._run_cmd([\"bcdedit\", \"/export\", bcd_path], timeout=40)\n            ps = r\"\"\"\n$efi = @()\ntry { $efi = Get-Partition | Where-Object {$_.GptType -match 'c12a7328'} | Select DiskNumber,PartitionNumber,DriveLetter,Size,GptType } catch {}\n$firm = $env:firmware_type\n[pscustomobject]@{Firmware=$firm;EfiPartitions=$efi} | ConvertTo-Json -Depth 4\n\"\"\"\n            efi_out, _ = self._run_powershell(ps, timeout=30)\n            lines = [\n                \"Boot Status + BCD Backup Report\",\n                f\"Generated: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\",\n                f\"BCD backup: {bcd_path if rc_export == 0 else 'FAILED'}\",\n                f\"bcdedit export rc={rc_export}\",\n                \"\",\n                \"EFI / firmware info:\",\n                efi_out.strip() or \"EFI info unavailable.\",\n                \"\",\n                \"bcdedit /enum all:\",\n                enum_out[:9000] if enum_out else \"bcdedit output empty.\",\n                \"\",\n                \"Solution guidance:\",\n                \"- Agar boot fail hai aur BCD corrupt lag raha hai, WinRE me bootrec/bcdboot use karein.\",\n                \"- EFI system me bcdboot C:\\\\Windows /s : /f UEFI carefully use hota hai.\",\n                \"- Advanced boot repair se pehle backup aur exact Windows/EFI drive letters verify karein.\",\n            ]\n            report = \"\\n\".join(lines)\n            self._append_log(self.trouble_log, \"\\n\" + report + \"\\n\", C[\"success\"] if rc_export == 0 else C[\"warning\"])\n            self.after(0, lambda: self._show_text_report_window(\"Boot Status + BCD Backup\", report))\n            self.after(0, lambda: self._set_status(\"Boot status complete\", C[\"success\"] if rc_export == 0 else C[\"warning\"]))\n        except Exception as e:\n            self._append_log(self.trouble_log, f\"Boot status failed: {e}\", C[\"error\"])\n\n    def _offline_repair_dialog(self):\n        win_dir = filedialog.askdirectory(title=\"Offline Windows folder select karo (example: D:\\\\Windows)\")\n        if not win_dir:\n            return\n        if os.path.basename(win_dir).lower() != \"windows\":\n            if not messagebox.askyesno(\"Confirm Folder\", f\"Selected folder Windows naam ka nahi hai:\\n{win_dir}\\n\\nContinue?\"):\n                return\n        image_root = os.path.dirname(win_dir.rstrip(\"\\\\/\"))\n        boot_dir = os.path.splitdrive(image_root)[0] + \"\\\\\"\n        if not messagebox.askyesno(\n            \"Offline SFC/DISM\",\n            f\"Offline repair commands run karein?\\n\\n\"\n            f\"Offbootdir: {boot_dir}\\n\"\n            f\"Offwindir: {win_dir}\\n\"\n            f\"DISM Image: {image_root}\\n\\n\"\n            \"Mounted/offline Windows path galat hua to command fail ho sakti hai.\"\n        ):\n            return\n        self._append_log(self.trouble_log, f\"Offline repair started: {win_dir}\", C[\"btn_info\"])\n        self._launch_job(\"offline_repair\", self._do_offline_repair, boot_dir, win_dir, image_root)\n\n    def _do_offline_repair(self, boot_dir, win_dir, image_root):\n        try:\n            cmds = [\n                [\"sfc\", \"/scannow\", f\"/offbootdir={boot_dir}\", f\"/offwindir={win_dir}\"],\n                [\"DISM\", f\"/Image:{image_root}\", \"/Cleanup-Image\", \"/ScanHealth\"],\n                [\"DISM\", f\"/Image:{image_root}\", \"/Cleanup-Image\", \"/RestoreHealth\"],\n            ]\n            lines = [\"Offline Repair Report\", f\"Generated: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\"]\n            for cmd in cmds:\n                lines.append(\"\")\n                lines.append(f\"Command: {subprocess.list2cmdline(cmd)}\")\n                out, rc, timed_out, stopped = self._stream_cmd_to_log(cmd, self.trouble_log, timeout_s=3600)\n                lines.append(f\"rc={rc}, timeout={timed_out}, stopped={stopped}\")\n                lines.append(out[-1200:] if out else \"No output\")\n            report = \"\\n\".join(lines)\n            self._append_log(self.trouble_log, \"\\n\" + report + \"\\n\", C[\"success\"])\n            self.after(0, lambda: self._show_text_report_window(\"Offline Repair Report\", report))\n            self.after(0, lambda: self._set_status(\"Offline repair complete\", C[\"success\"]))\n        except Exception as e:\n            self._append_log(self.trouble_log, f\"Offline repair failed: {e}\", C[\"error\"])\n\n    def _build_security_startup_report(self):\n        script = r\"\"\"\n$items = @()\n$keys = @(\n 'HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Run',\n 'HKLM:\\Software\\Microsoft\\Windows\\CurrentVersion\\Run',\n 'HKLM:\\Software\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Run',\n 'HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows',\n 'HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon',\n 'HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\AppCertDlls',\n 'HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options'\n)\nforeach($k in $keys) {\n if(Test-Path $k) {\n   try {\n     $props = Get-ItemProperty $k -ErrorAction SilentlyContinue\n     foreach($p in $props.PSObject.Properties) {\n       if($p.Name -match '^PS') { continue }\n       $items += [pscustomobject]@{Location=$k;Name=$p.Name;Value=[string]$p.Value}\n     }\n   } catch {}\n }\n}\n$tasks = @()\ntry {\n $tasks = Get-ScheduledTask -ErrorAction SilentlyContinue |\n   Where-Object { ($_.TaskPath -notmatch '\\\\Microsoft\\\\Windows\\\\') -or (($_.Actions | Out-String) -match 'AppData|Temp|rundll32|powershell|wscript|cscript') } |\n   Select-Object -First 80 TaskPath,TaskName,State,@{n='Action';e={($_.Actions | Out-String).Trim()}}\n} catch {}\n[pscustomobject]@{Registry=$items;Tasks=$tasks} | ConvertTo-Json -Depth 5\n\"\"\"\n        out, _ = self._run_powershell(script, timeout=80)\n        hosts = \"\"\n        try:\n            hosts_path = r\"C:\\Windows\\System32\\drivers\\etc\\hosts\"\n            if os.path.exists(hosts_path):\n                with open(hosts_path, \"r\", encoding=\"utf-8\", errors=\"replace\") as f:\n                    hosts = f.read()[:6000]\n        except Exception as e:\n            hosts = f\"hosts read failed: {e}\"\n        items = self._json_items_from_output(out)\n        payload = items[0] if items else {}\n        reg = payload.get(\"Registry\", []) if isinstance(payload, dict) else []\n        tasks = payload.get(\"Tasks\", []) if isinstance(payload, dict) else []\n        if isinstance(reg, dict):\n            reg = [reg]\n        if isinstance(tasks, dict):\n            tasks = [tasks]\n        risky = []\n        for row in reg:\n            val = str(row.get(\"Value\", \"\"))\n            loc = str(row.get(\"Location\", \"\"))\n            name = str(row.get(\"Name\", \"\"))\n            low = f\"{loc} {name} {val}\".lower()\n            if any(x in low for x in [\"appinit_dlls\", \"debugger\", \"appdata\", \"\\\\temp\\\\\", \"rundll32\", \"powershell\", \"wscript\", \"cscript\", \".dll\"]):\n                risky.append(row)\n        lines = [\n            \"Security + Startup Analysis Report\",\n            f\"Generated: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\",\n            \"\",\n            \"Troubleshoot kya kiya:\",\n            \"- Run/RunOnce, AppInit_DLLs, Winlogon, IFEO Debugger keys inspect ki.\",\n            \"- Non-Microsoft/suspicious Scheduled Tasks check kiye.\",\n            \"- hosts file inspect kiya.\",\n            \"\",\n            \"Summary:\",\n            f\"- Registry autorun items: {len(reg)}\",\n            f\"- Risky autorun indicators: {len(risky)}\",\n            f\"- Scheduled task indicators: {len(tasks)}\",\n            \"\",\n            \"Risky registry indicators:\",\n        ]\n        for r in risky[:30]:\n            lines.append(f\"- {r.get('Location','')} | {r.get('Name','')} | {r.get('Value','')}\")\n        if not risky:\n            lines.append(\"- None detected.\")\n        lines.append(\"\")\n        lines.append(\"Scheduled task indicators:\")\n        for t in tasks[:25]:\n            action = \" \".join(str(t.get(\"Action\", \"\")).split())[:220]\n            lines.append(f\"- {t.get('TaskPath','')}{t.get('TaskName','')} | {t.get('State','')} | {action}\")\n        if not tasks:\n            lines.append(\"- None detected.\")\n        lines.append(\"\")\n        lines.append(\"hosts file sample:\")\n        lines.append(hosts if hosts else \"hosts empty/unavailable.\")\n        lines.append(\"\")\n        lines.append(\"Solution:\")\n        lines.append(\"- Unknown AppData/Temp/rundll32/powershell startup entries ko disable karke reboot test karo.\")\n        lines.append(\"- IFEO Debugger/AppInit_DLLs entries malware persistence ka strong clue ho sakte hain.\")\n        lines.append(\"- Defender Offline Scan + SFC/DISM run karo agar suspicious injection indicator mile.\")\n        return \"\\n\".join(lines), (\"warning\" if risky or tasks else \"success\")\n\n    def _security_startup_report(self):\n        self._append_log(self.trouble_log, \"Security autorun analysis started...\", C[\"btn_warn\"])\n        self._launch_job(\"security_startup_report\", self._do_security_startup_report)\n\n    def _do_security_startup_report(self):\n        try:\n            report, severity = self._build_security_startup_report()\n            color = C[\"warning\"] if severity == \"warning\" else C[\"success\"]\n            self._append_log(self.trouble_log, \"\\n\" + report + \"\\n\", color)\n            self.after(0, lambda: self._show_text_report_window(\"Security Startup Analysis\", report))\n            self.after(0, lambda: self._set_status(\"Security analysis complete\", color))\n        except Exception as e:\n            self._append_log(self.trouble_log, f\"Security analysis failed: {e}\", C[\"error\"])\n\n    def _diagnostic_zip_package(self):\n        path = filedialog.asksaveasfilename(\n            defaultextension=\".zip\",\n            filetypes=[(\"ZIP package\", \"*.zip\")],\n            initialfile=\"Godawari_Diagnostic_Package.zip\",\n            title=\"Save diagnostic package\"\n        )\n        if not path:\n            return\n        if not messagebox.askyesno(\"Diagnostic ZIP\", \"HTML/JSON/TXT diagnostic package generate karein? Kuch checks time le sakte hain.\"):\n            return\n        self._append_log(self.trouble_log, \"Diagnostic ZIP generation started...\", C[\"accent\"])\n        self._launch_job(\"diagnostic_zip_package\", self._do_diagnostic_zip_package, path)\n\n    def _do_diagnostic_zip_package(self, zip_path):\n        try:\n            reports = {}\n            builders = [\n                (\"bsod_report\", self._build_bsod_deep_report),\n                (\"rundll32_kernel32_report\", self._build_rundll32_report),\n                (\"event_correlation\", self._build_event_correlation_report),\n                (\"driver_diagnostics\", self._build_driver_diagnostics_report),\n                (\"hardware_health\", self._build_hardware_health_report),\n                (\"security_startup\", self._build_security_startup_report),\n            ]\n            for name, fn in builders:\n                try:\n                    result = fn()\n                    reports[name] = result[0] if isinstance(result, tuple) else str(result)\n                    self._append_log(self.trouble_log, f\"Report built: {name}\", C[\"text_dim\"])\n                except Exception as e:\n                    reports[name] = f\"FAILED: {e}\"\n            payload = {\n                \"generated\": datetime.datetime.now().isoformat(timespec=\"seconds\"),\n                \"computer\": platform.node(),\n                \"reports\": reports,\n            }\n            html_body = \"Godawari Diagnostic Package\"\n            html_body += \"\nGodawari Diagnostic Package\"\n            for name, text in reports.items():\n                html_body += f\"\n{html.escape(name)}\n{html.escape(text)}\"\n            html_body += \"\"\n            with zipfile.ZipFile(zip_path, \"w\", zipfile.ZIP_DEFLATED) as z:\n                z.writestr(\"diagnostics.json\", json.dumps(payload, ensure_ascii=False, indent=2, default=str))\n                z.writestr(\"diagnostics.html\", html_body)\n                for name, text in reports.items():\n                    z.writestr(f\"{name}.txt\", text)\n                try:\n                    z.writestr(\"current_repair_log.txt\", self.trouble_log.get(\"1.0\", \"end\"))\n                except Exception:\n                    pass\n            self._append_log(self.trouble_log, f\"Diagnostic ZIP saved: {zip_path}\", C[\"success\"])\n            self.after(0, lambda: messagebox.showinfo(\"Diagnostic ZIP\", f\"Saved:\\n{zip_path}\"))\n        except Exception as e:\n            self._append_log(self.trouble_log, f\"Diagnostic ZIP failed: {e}\", C[\"error\"])\n\n    def _build_power(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\u26a1 Power Plan\", \"Change power scheme + Hibernate\")\n        self._action_card_grid(frame, [\n            (\"\ud83d\udd0b\", \"High Performance\",           \"Max speed, zyada bijli\",              C[\"btn_danger\"], lambda: self._set_power(\"8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c\")),\n            (\"\u26a1\", \"Balanced\",                   \"Speed aur battery balance\",           C[\"btn_info\"],   lambda: self._set_power(\"381b4222-f694-41f0-9685-ff5bb260df2e\")),\n            (\"\ud83c\udf3f\", \"Power Saver\",                \"Battery bachao, speed kam\",           C[\"btn\"],        lambda: self._set_power(\"a1841308-3541-4fab-bc81-f71556f20b4a\")),\n            (\"\ud83c\udf19\", \"Disable Hibernate\",          \"Hibernate + Fast Startup band karo\",  C[\"btn_warn\"],   self._disable_hibernate),\n        ], cols=4)\n        content = tk.Frame(frame, bg=C[\"card\"])\n        content.pack(fill=\"x\", padx=16, pady=(4, 10))\n        self.power_status = tk.Label(content, text=\"\", font=FONTS[\"body\"], fg=C[\"accent2\"], bg=C[\"card\"])\n        self.power_status.pack(pady=10)\n        self._refresh_power_status()\n        return frame\n\n    def _refresh_power_status(self):\n        out, _ = self._run_cmd('powercfg /getactivescheme')\n        self.power_status.config(text=f\"Current: {out.strip() if out else 'Unknown'}\")\n        self.after(5000, self._refresh_power_status)\n\n    def _set_power(self, guid):\n        if messagebox.askyesno(\"Set Power Plan\", f\"Set active power plan to {guid}?\"):\n            self._run_cmd(f'powercfg /setactive {guid}')\n            self._refresh_power_status()\n\n    def _disable_hibernate(self):\n        if messagebox.askyesno(\"Disable Hibernate\", \"Turn off hibernate and fast startup? This frees disk space but makes boot slightly slower.\"):\n            self._run_cmd('powercfg -h off')\n            self._append_log(self.power_status.master, \"\u2705 Hibernate disabled + hiberfil.sys removed\", C[\"success\"])\n            self._run_cmd('REG ADD \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Session Manager\\\\Power\" /v HiberbootEnabled /t REG_DWORD /d 0 /f')\n            self._append_log(self.power_status.master, \"\u2705 Fast Startup disabled\", C[\"success\"])\n\n    # ---------- FILE RECOVERY ----------\n    def _build_recovery_safe(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n\n        # \u2500\u2500 Fixed header (outside scroll) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        self._section_header(\n            frame, \"\ud83d\udcc2 File Search &amp; Recovery\",\n            \"Zone A = maujood files dhundo | Zone B = deleted files sector se recover karo\")\n\n        # \u2500\u2500 Scrollable body \u2014 app ka built-in method use karo \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        # _scrollable_section_body returns an inner frame with canvas+scrollbar+\n        # scoped mousewheel already wired \u2014 no conflict with other menus.\n        frame_scroll = self._scrollable_section_body(frame)\n\n        zone_a = tk.Frame(frame_scroll, bg=C[\"card\"], highlightbackground=C[\"accent2\"], highlightthickness=2)\n        zone_a.pack(fill=\"x\", padx=16, pady=(4, 6))\n        tk.Label(zone_a, text=\"\ud83d\udd0d Zone A \u2014 Search Existing Files\",\n                 font=FONTS[\"subhead\"], fg=C[\"accent2\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=12, pady=(8, 2))\n        tk.Label(zone_a,\n                 text=\"Drive pe jo files abhi bhi maujood hain unhe dhundta hai (fast, no admin needed).\\n\"\n                      \"Deleted files ke liye Zone B use karo.\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\").pack(anchor=\"w\", padx=12, pady=(0, 6))\n\n        row_inputs = tk.Frame(zone_a, bg=C[\"card\"])\n        row_inputs.pack(fill=\"x\", padx=8, pady=4)\n        tk.Label(row_inputs, text=\"Drive:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\", padx=(0, 4))\n        drive_values = [f\"{d}\\\\\" for d in \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\" if os.path.exists(f\"{d}:\\\\\")]\n        drive_values += [\"Android\"]\n        self.rec_drive = ttk.Combobox(row_inputs, values=drive_values, width=10, font=FONTS[\"body\"], state=\"readonly\")\n        self.rec_drive.set(\"C:\\\\\")\n        self.rec_drive.pack(side=\"left\", padx=4)\n        tk.Label(row_inputs, text=\"File Types:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\", padx=(8, 4))\n        self.rec_ext = tk.Entry(row_inputs, width=30, font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"],\n                                insertbackground=C[\"text\"])\n        self.rec_ext.insert(0, \"jpg,png,pdf,docx\")\n        self.rec_ext.pack(side=\"left\", padx=4)\n        tk.Label(row_inputs, text=\"Quick:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\", padx=(8, 2))\n        for label, exts in [(\"Photos\", \"jpg,jpeg,png,bmp,gif\"), (\"Docs\", \"pdf,docx,xlsx,pptx,txt\"),\n                            (\"Videos\", \"mp4,avi,mkv,mov\"), (\"All\", \"jpg,png,pdf,docx,mp4,xlsx\")]:\n            tk.Button(row_inputs, text=label, font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text_dim\"],\n                      bd=0, padx=6, pady=2, cursor=\"hand2\",\n                      command=lambda e=exts: (self.rec_ext.delete(0, \"end\"), self.rec_ext.insert(0, e))).pack(side=\"left\", padx=2)\n\n        row_actions = tk.Frame(zone_a, bg=C[\"card\"])\n        row_actions.pack(fill=\"x\", padx=8, pady=(4, 4))\n        tk.Button(row_actions, text=\"\ud83d\udd0d Search Drive\",\n                  font=(\"Segoe UI\", 10, \"bold\"), bg=C[\"accent2\"], fg=\"#000\",\n                  bd=0, padx=16, pady=6, cursor=\"hand2\",\n                  command=self._start_file_recovery).pack(side=\"left\", padx=4)\n        self._rec_stop_btn = tk.Button(row_actions, text=\"\u23f9 Stop\", font=FONTS[\"body\"],\n            bg=C[\"btn_danger\"], fg=C[\"text\"], bd=0, padx=10, pady=5,\n            cursor=\"hand2\", state=\"disabled\", command=self._stop_file_recovery)\n        self._rec_stop_btn.pack(side=\"left\", padx=4)\n        self._rec_pause_btn = tk.Button(row_actions, text=\"\u23f8 Pause\", font=FONTS[\"body\"],\n            bg=C[\"btn_warn\"], fg=C[\"text\"], bd=0, padx=10, pady=5,\n            cursor=\"hand2\", state=\"disabled\", command=self._pause_resume_file_recovery)\n        self._rec_pause_btn.pack(side=\"left\", padx=4)\n\n        row_android = tk.Frame(zone_a, bg=C[\"card\"])\n        row_android.pack(fill=\"x\", padx=8, pady=(0, 8))\n        tk.Label(row_android, text=\"\ud83d\udcf1 Android:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\", padx=(0, 6))\n        tk.Button(row_android, text=\"DCIM Photos Backup\", font=FONTS[\"small\"],\n                  bg=C[\"btn_chip\"], fg=C[\"text\"], bd=0, padx=10, pady=4, cursor=\"hand2\",\n                  command=lambda: self._android_media_preset(\"dcim\")).pack(side=\"left\", padx=3)\n        tk.Button(row_android, text=\"WhatsApp Media\", font=FONTS[\"small\"],\n                  bg=C[\"btn_chip\"], fg=C[\"text\"], bd=0, padx=10, pady=4, cursor=\"hand2\",\n                  command=lambda: self._android_media_preset(\"whatsapp\")).pack(side=\"left\", padx=3)\n        self.adb_status_label = tk.Label(row_android, text=\"ADB Status: Checking...\",\n                                         font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"])\n        self.adb_status_label.pack(side=\"right\", padx=8)\n        tk.Button(row_android, text=\"ADB Refresh\", font=FONTS[\"small\"],\n                  bg=C[\"btn\"], fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=self._refresh_adb_status_label).pack(side=\"right\", padx=3)\n        self.after(150, self._refresh_adb_status_label)\n\n        zone_b = tk.Frame(frame_scroll, bg=C[\"card\"], highlightbackground=C[\"warning\"], highlightthickness=2)\n        zone_b.pack(fill=\"x\", padx=16, pady=(0, 6))\n        tk.Label(zone_b, text=\"\u26a1 Zone B \u2014 Recover Deleted Files (Admin Required)\",\n                 font=FONTS[\"subhead\"], fg=C[\"warning\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=12, pady=(8, 2))\n        tk.Label(zone_b,\n                 text=\"Disk ke sectors seedha scan karta hai. Formatted ya deleted files wapas la sakta hai.\\n\"\n                      \"Admin rights mandatory hain. Recovered data ALAG drive pe save karo.\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\").pack(anchor=\"w\", padx=12, pady=(0, 6))\n\n        row_source = tk.Frame(zone_b, bg=C[\"card\"])\n        row_source.pack(fill=\"x\", padx=8, pady=(0, 4))\n        tk.Label(row_source, text=\"Raw Source:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\", padx=4)\n        raw_values = [DEFAULT_RAW_DISK] + [\"\\\\\\\\.\\\\\" + d + \":\" for d in \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\" if os.path.exists(d + \":\\\\\")]\n        self.raw_disk_var = tk.StringVar(value=DEFAULT_RAW_DISK)\n        self.raw_disk_combo = ttk.Combobox(row_source, values=raw_values, textvariable=self.raw_disk_var, width=22, font=FONTS[\"body\"], state=\"readonly\")\n        self.raw_disk_combo.pack(side=\"left\", padx=4)\n        self.raw_source_badge = tk.Label(row_source, text=\"RAW DEVICE\", font=FONTS[\"small\"], fg=C[\"warning\"], bg=C[\"card\"])\n        self.raw_source_badge.pack(side=\"left\", padx=6)\n        self.raw_disk_combo.bind(\"&lt;&gt;\", lambda e: self._update_raw_source_badge())\n        self.raw_disk_combo.bind(\"\", lambda e: self._update_raw_source_badge())\n        tk.Label(row_source, text=\"Scan MB (0=Full):\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\", padx=(8, 2))\n        self.raw_scan_mb = tk.Entry(row_source, width=6, font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"])\n        self.raw_scan_mb.insert(0, \"0\")\n        self.raw_scan_mb.pack(side=\"left\", padx=2)\n        tk.Label(row_source, text=\"Start Sector:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\", padx=(8, 2))\n        self.raw_sector_num = tk.Entry(row_source, width=8, font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"])\n        self.raw_sector_num.insert(0, \"0\")\n        self.raw_sector_num.pack(side=\"left\", padx=2)\n\n        row_primary = tk.Frame(zone_b, bg=C[\"card\"])\n        row_primary.pack(fill=\"x\", padx=8, pady=(4, 2))\n        for label, color, cmd in [\n            (\"\u2705 AUTO Recovery (Recommended)\", C[\"accent2\"], self._start_auto_raw_recovery),\n            (\"\u26a1 Raw Signature Scan\", C[\"btn_danger\"], self._start_raw_signature_scan),\n            (\"\ud83d\udd0e PhotoRec Deep Scan\", C[\"btn_hw\"], self._start_photorec_deep_scan),\n        ]:\n            tk.Button(row_primary, text=label, font=FONTS[\"small\"], bg=color,\n                      fg=C[\"bg\"] if color == C[\"accent2\"] else C[\"text\"],\n                      bd=0, padx=12, pady=6, cursor=\"hand2\", command=cmd).pack(side=\"left\", padx=3, pady=2)\n\n        tk.Label(zone_b, text=\"Advanced forensic tools:\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=12, pady=(4, 0))\n        row_advanced = tk.Frame(zone_b, bg=C[\"card\"])\n        row_advanced.pack(fill=\"x\", padx=8, pady=(2, 8))\n        for label, color, cmd in [\n            (\"DMDE\", C[\"btn_info\"], self._start_dmde_recovery),\n            (\"Create IMG\", C[\"btn_warn\"], self._create_img_dialog),\n            (\"Import IMG\", C[\"btn_info\"], self._select_img_source),\n            (\"Hex Viewer\", C[\"btn_chip\"], self._show_raw_hex_dialog),\n            (\"Shadow Copies\", C[\"accent2\"], self._shadow_copy_recovery_report),\n            (\"Hash+Verify\", C[\"btn_warn\"], self._forensic_hash_verify_dialog),\n            (\"Session Save\", C[\"btn_chip\"], self._recovery_session_db_save),\n        ]:\n            tk.Button(row_advanced, text=label, font=FONTS[\"small\"], bg=color, fg=C[\"text\"],\n                      bd=0, padx=8, pady=4, cursor=\"hand2\", command=cmd).pack(side=\"left\", padx=3, pady=2)\n\n        prog = tk.Frame(frame_scroll, bg=C[\"card\"], highlightbackground=C[\"border\"], highlightthickness=1)\n        prog.pack(fill=\"x\", padx=16, pady=(0, 6))\n        self.scan_mode_label = tk.Label(prog, text=\"Mode: \u2014\",\n            font=FONTS[\"small\"], fg=C[\"accent4\"], bg=C[\"card\"])\n        self.scan_mode_label.pack(fill=\"x\", padx=12, pady=(10, 2))\n        self.raw_progress_label = tk.Label(prog, text=\"Ready \u2014 scan shuru karo\",\n                                           font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], anchor=\"w\")\n        self.raw_progress_label.pack(fill=\"x\", padx=12, pady=(0, 2))\n        self.hdd_resource_delta_lbl = tk.Label(prog, text=\"Memory Delta: --\",\n                                               font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], anchor=\"w\")\n        self.hdd_resource_delta_lbl.pack(fill=\"x\", padx=12, pady=(0, 2))\n        self.raw_progress_var = tk.DoubleVar(value=0)\n        self.raw_progress_bar = ttk.Progressbar(prog, variable=self.raw_progress_var, maximum=100, mode=\"determinate\")\n        self.raw_progress_bar.pack(fill=\"x\", padx=12, pady=(0, 4))\n        self.raw_progress_log = scrolledtext.ScrolledText(prog, height=5, font=FONTS[\"mono\"],\n                                                           bg=C[\"bg\"], fg=C[\"text\"],\n                                                           insertbackground=C[\"text\"], wrap=\"word\",\n                                                           state=\"disabled\", bd=0)\n        self.raw_progress_log.pack(fill=\"x\", padx=12, pady=(0, 4))\n        prog_btns = tk.Frame(prog, bg=C[\"card\"])\n        prog_btns.pack(fill=\"x\", padx=12, pady=(0, 10))\n        tk.Button(prog_btns, text=\"\ud83d\uddd1 Clear Log\", font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text_dim\"],\n                  bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=self._clear_recovery_progress_log).pack(side=\"left\")\n\n        results_outer = tk.Frame(frame_scroll, bg=C[\"card\"], highlightbackground=C[\"border\"], highlightthickness=1)\n        results_outer.pack(fill=\"x\", padx=16, pady=(0, 10))\n        results_hdr = tk.Frame(results_outer, bg=C[\"card\"])\n        results_hdr.pack(fill=\"x\", padx=12, pady=(10, 4))\n        tk.Label(results_hdr, text=\"\u2463 Milne wali / Recovered files:\",\n                 font=FONTS[\"small\"], fg=C[\"accent2\"], bg=C[\"card\"]).pack(side=\"left\")\n        self.rec_stats_label = tk.Label(results_hdr, text=\"0 files found | 0 selected\",\n            font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"])\n        self.rec_stats_label.pack(side=\"right\")\n\n        tree_wrap = tk.Frame(results_outer, bg=C[\"card\"])\n        tree_wrap.pack(fill=\"both\", expand=True, padx=12, pady=(0, 4))\n        rec_cols = (\"Filename\", \"Type\", \"Size\", \"Status\", \"Location\", \"Integrity\")\n        col_heads = (\"File Name\", \"Type\", \"Size\", \"Status\", \"Location / Sector\", \"Integrity\")\n        self.rec_tree = ttk.Treeview(tree_wrap, columns=rec_cols, show=\"headings\", height=14, style=\"Custom.Treeview\")\n        for col, head, w in zip(rec_cols, col_heads, (230, 55, 90, 145, 230, 75)):\n            self.rec_tree.heading(col, text=head)\n            self.rec_tree.column(col, width=w, anchor=\"w\")\n        self.rec_tree.tag_configure(\"recovered\", foreground=C[\"success\"])\n        self.rec_tree.tag_configure(\"partial\", foreground=C[\"warning\"])\n        self.rec_tree.tag_configure(\"found\", foreground=C[\"text\"])\n        yscroll = ttk.Scrollbar(tree_wrap, orient=\"vertical\", command=self.rec_tree.yview)\n        xscroll = ttk.Scrollbar(tree_wrap, orient=\"horizontal\", command=self.rec_tree.xview)\n        self.rec_tree.configure(yscrollcommand=yscroll.set, xscrollcommand=xscroll.set)\n        self.rec_tree.grid(row=0, column=0, sticky=\"nsew\")\n        yscroll.grid(row=0, column=1, sticky=\"ns\")\n        xscroll.grid(row=1, column=0, sticky=\"ew\")\n        tree_wrap.grid_rowconfigure(0, weight=1)\n        tree_wrap.grid_columnconfigure(0, weight=1)\n        self.rec_tree.bind(\"&lt;&gt;\", self._on_rec_select)\n\n        results_bar = tk.Frame(results_outer, bg=C[\"card\"])\n        results_bar.pack(fill=\"x\", padx=12, pady=(0, 10))\n        self._rec_recover_btn = tk.Button(results_bar, text=\"\ud83d\udcbe Recover Selected\",\n                  font=FONTS[\"body\"], bg=C[\"btn_info\"], fg=C[\"text\"],\n                  bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=self._recover_selected_files)\n        self._rec_recover_btn.pack(side=\"left\", padx=(0, 8))\n        tk.Button(results_bar, text=\"\ud83d\udccb Select All\", font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text\"],\n                  bd=0, padx=10, pady=5, cursor=\"hand2\",\n                  command=lambda: self.rec_tree.selection_set(self.rec_tree.get_children())).pack(side=\"left\", padx=(0, 8))\n        tk.Button(results_bar, text=\"\ud83d\uddd1 Clear List\", font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text_dim\"],\n                  bd=0, padx=10, pady=5, cursor=\"hand2\",\n                  command=self._clear_recovery_results).pack(side=\"left\")\n\n        self.rec_found_files = {}\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # \u2500\u2500 ZONE C \u2500\u2500 Batch Integrity Verifier (NEW FEATURE #1) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        # Real SHA256 hash computation on recovered/existing files.\n        # Runs fully in background thread, 0 fake logic, real OS file reads.\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        zone_c = tk.Frame(frame_scroll, bg=C[\"card\"],\n                          highlightbackground=C.get(\"accent4\", \"#9b59b6\"),\n                          highlightthickness=2)\n        zone_c.pack(fill=\"x\", padx=16, pady=(0, 6))\n        tk.Label(zone_c, text=\"\ud83d\udd10 Zone C \u2014 Batch Integrity Verifier  (SHA256 real-time)\",\n                 font=FONTS[\"subhead\"], fg=C.get(\"accent4\", \"#9b59b6\"), bg=C[\"card\"]\n                 ).pack(anchor=\"w\", padx=12, pady=(8, 2))\n        tk.Label(zone_c,\n                 text=\"Recovered ya kisi bhi folder ki files ko real SHA256 hash se verify karta hai.\\n\"\n                      \"Corrupt / 0-byte / truncated files automatically flag ho jaate hain.\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\"\n                 ).pack(anchor=\"w\", padx=12, pady=(0, 6))\n\n        zc_row1 = tk.Frame(zone_c, bg=C[\"card\"]); zc_row1.pack(fill=\"x\", padx=8, pady=4)\n        tk.Label(zc_row1, text=\"Folder:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\", padx=(0,4))\n        self._integ_dir_var = tk.StringVar()\n        tk.Entry(zc_row1, textvariable=self._integ_dir_var, width=42,\n                 font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"],\n                 insertbackground=C[\"text\"]).pack(side=\"left\", padx=4)\n        tk.Button(zc_row1, text=\"\ud83d\udcc1 Browse\", font=FONTS[\"small\"],\n                  bg=C[\"panel\"], fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=lambda: self._integ_dir_var.set(\n                      filedialog.askdirectory(title=\"Verify karne ka folder\")\n                  )).pack(side=\"left\", padx=4)\n        tk.Button(zc_row1, text=\"\ud83d\udcc2 Use Recovery Dest\", font=FONTS[\"small\"],\n                  bg=C[\"btn_chip\"], fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=lambda: self._integ_use_rec_dest()).pack(side=\"left\", padx=4)\n\n        zc_row2 = tk.Frame(zone_c, bg=C[\"card\"]); zc_row2.pack(fill=\"x\", padx=8, pady=(0,4))\n        self._integ_recurse_var = tk.BooleanVar(value=True)\n        tk.Checkbutton(zc_row2, text=\"Subfolders include\", variable=self._integ_recurse_var,\n                       font=FONTS[\"small\"], bg=C[\"card\"], fg=C[\"text\"],\n                       selectcolor=C[\"bg\"], activebackground=C[\"card\"]).pack(side=\"left\", padx=4)\n        self._integ_export_var = tk.BooleanVar(value=True)\n        tk.Checkbutton(zc_row2, text=\"CSV report export\", variable=self._integ_export_var,\n                       font=FONTS[\"small\"], bg=C[\"card\"], fg=C[\"text\"],\n                       selectcolor=C[\"bg\"], activebackground=C[\"card\"]).pack(side=\"left\", padx=4)\n\n        zc_stats_row = tk.Frame(zone_c, bg=C[\"card\"]); zc_stats_row.pack(fill=\"x\", padx=8)\n        self._integ_stat_lbl = tk.Label(zc_stats_row, text=\"\u2014 Ready \u2014\",\n                                        font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], anchor=\"w\")\n        self._integ_stat_lbl.pack(side=\"left\", fill=\"x\", expand=True)\n        self._integ_prog_var = tk.DoubleVar(value=0)\n        zc_pb = ttk.Progressbar(zone_c, variable=self._integ_prog_var, maximum=100, mode=\"determinate\")\n        zc_pb.pack(fill=\"x\", padx=12, pady=(2, 2))\n        self._integ_prog_bar = zc_pb\n\n        # Scrollable log sub-frame inside Zone C (Phase 2 requirement)\n        self._integ_log = scrolledtext.ScrolledText(zone_c, height=4, font=FONTS[\"mono\"],\n                                                    bg=C[\"bg\"], fg=C[\"text\"],\n                                                    insertbackground=C[\"text\"], wrap=\"word\",\n                                                    state=\"disabled\", bd=0)\n        self._integ_log.pack(fill=\"x\", padx=12, pady=(0, 4))\n\n        zc_btn_row = tk.Frame(zone_c, bg=C[\"card\"]); zc_btn_row.pack(fill=\"x\", padx=8, pady=(0,8))\n        self._integ_run_btn = tk.Button(\n            zc_btn_row, text=\"\ud83d\udd10 Run Integrity Check\",\n            font=(\"Segoe UI\", 10, \"bold\"),\n            bg=C.get(\"accent4\", \"#9b59b6\"), fg=C[\"text\"],\n            bd=0, padx=16, pady=6, cursor=\"hand2\",\n            command=self._start_integrity_verifier)\n        self._integ_run_btn.pack(side=\"left\", padx=4)\n        tk.Button(zc_btn_row, text=\"\ud83d\uddd1 Clear Log\", font=FONTS[\"small\"],\n                  bg=C[\"panel\"], fg=C[\"text_dim\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=lambda: (\n                      self._integ_log.config(state=\"normal\"),\n                      self._integ_log.delete(\"1.0\", \"end\"),\n                      self._integ_log.config(state=\"disabled\"),\n                      self._integ_stat_lbl.config(text=\"\u2014 Cleared \u2014\"),\n                      self._integ_prog_var.set(0),\n                  )).pack(side=\"left\", padx=4)\n\n        return frame\n\n    def _build_recovery_fixed(self, parent):\n        return self._build_recovery_safe(parent)\n\n    def _show_rescue_center(self):\n        try:\n            self._launch_job(\"refresh_rescue_status\", self._refresh_rescue_dashboard_status)\n        except Exception:\n            pass\n\n    def _build_rescue_recovery_center(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(\n            frame,\n            \"\ud83d\udea8 RESCUE &amp; RECOVERY CENTER\",\n            \"Technician-grade Windows rescue workspace with diagnostics, boot repair, media creation and restore safety.\",\n        )\n        tk.Label(frame, text=\"Designed for professional recovery workflows: WinRE checks, boot diagnostics, BitLocker visibility and restore point tracking.\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"], justify=\"left\").pack(fill=\"x\", padx=16, pady=(0, 6))\n\n        notebook = ttk.Notebook(frame)\n        notebook.pack(fill=\"both\", expand=True, padx=16, pady=(4, 12))\n        tabs = [\n            (\"Recovery Dashboard\", self._build_rescue_dashboard_tab),\n            (\"Windows Recovery\", self._build_windows_recovery_tab),\n            (\"Boot Repair\", self._build_boot_repair_tab),\n            (\"Rescue Media\", self._build_rescue_media_creator_tab),\n            (\"Offline Tools\", self._build_offline_recovery_tools_tab),\n            (\"Password Assistant\", self._build_password_recovery_assistant_tab),\n            (\"Recovery Console\", self._build_advanced_recovery_console_tab),\n            (\"Technician Toolkit\", self._build_technician_toolkit_tab),\n        ]\n        for title, builder in tabs:\n            tab = tk.Frame(notebook, bg=C[\"bg\"])\n            notebook.add(tab, text=title)\n            builder(tab)\n\n        self.after(200, self._show_rescue_center)\n        return frame\n\n    def _build_rescue_dashboard_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        status_frame = tk.Frame(body, bg=C[\"card\"])\n        status_frame.pack(fill=\"x\", padx=14, pady=10)\n\n        self.rescue_winre_status = tk.StringVar(value=\"Unknown\")\n        self.rescue_bitlocker_status = tk.StringVar(value=\"Unknown\")\n        self.rescue_restore_status = tk.StringVar(value=\"Unknown\")\n        self.rescue_readiness_status = tk.StringVar(value=\"Pending\")\n        self.rescue_last_sync = tk.StringVar(value=\"Never\")\n\n        for title, var, color in [\n            (\"WinRE Status\", self.rescue_winre_status, C[\"accent\"]),\n            (\"BitLocker Status\", self.rescue_bitlocker_status, C[\"warning\"]),\n            (\"Restore Point\", self.rescue_restore_status, C[\"success\"]),\n            (\"Recovery Readiness\", self.rescue_readiness_status, C[\"accent4\"]),\n            (\"Last Refresh\", self.rescue_last_sync, C[\"text_dim\"]),\n        ]:\n            card = tk.Frame(status_frame, bg=C[\"bg\"], bd=1, relief=\"solid\")\n            card.pack(side=\"left\", expand=True, fill=\"x\", padx=6, pady=6)\n            tk.Label(card, text=title, font=FONTS[\"small\"], fg=color, bg=C[\"bg\"]).pack(anchor=\"w\", padx=8, pady=(8, 2))\n            tk.Label(card, textvariable=var, font=FONTS[\"body\"], fg=C[\"text\"], bg=C[\"bg\"]).pack(anchor=\"w\", padx=8, pady=(0, 8))\n\n        tk.Label(body, text=\"Visible help: Refresh status and create a restore point before risky recovery actions.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=900, justify=\"left\").pack(fill=\"x\", padx=14, pady=(0, 8))\n        btn_row = tk.Frame(body, bg=C[\"bg\"])\n        btn_row.pack(fill=\"x\", padx=14, pady=(0, 10))\n        refresh_btn = tk.Button(btn_row, text=\"\ud83d\udd04 Refresh Dashboard\", font=FONTS[\"small\"], bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=12, pady=8, cursor=\"hand2\",\n              command=lambda: self._launch_job(\"refresh_rescue_status\", self._refresh_rescue_dashboard_status))\n        refresh_btn.pack(side=\"left\", padx=4)\n        self._create_tooltip(refresh_btn, \"Refresh Rescue Dashboard status, WinRE and restore point readiness before running recovery actions.\")\n        restore_btn = tk.Button(btn_row, text=\"\ud83d\udee1 Create Restore Point\", font=FONTS[\"small\"], bg=C[\"btn_hw\"], fg=C[\"text\"], bd=0, padx=12, pady=8, cursor=\"hand2\",\n              command=lambda: self._confirm_and_launch_job(\"Create Restore Point\", \"Create a verified restore point before critical recovery actions.\", None, \"restore_point_rescue\", self._collect_restore_point))\n        restore_btn.pack(side=\"left\", padx=4)\n        self._create_tooltip(restore_btn, \"Create a Windows restore point so you can roll back system changes if recovery actions cause issues.\")\n\n        history_frame = tk.LabelFrame(body, text=\"Recent Rescue Actions &amp; Restore Points\", font=FONTS[\"subhead\"], fg=C[\"accent2\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        history_frame.pack(fill=\"both\", expand=True, padx=14, pady=(0, 10))\n        self.rescue_history_tree = ttk.Treeview(history_frame, columns=(\"ts\", \"event\", \"detail\"), show=\"headings\", height=8, style=\"Custom.Treeview\")\n        for col, width in [(\"ts\", 160), (\"event\", 220), (\"detail\", 420)]:\n            self.rescue_history_tree.heading(col, text=col.title())\n            self.rescue_history_tree.column(col, width=width, anchor=\"w\")\n        self.rescue_history_tree.pack(fill=\"both\", expand=True, padx=8, pady=8)\n        return body\n\n    def _build_windows_recovery_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        lead = tk.Label(body, text=\"WinRE inspection, repair and readiness validation.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\")\n        lead.pack(fill=\"x\", padx=14, pady=(10, 8))\n        tk.Label(body, text=\"Visible help: Check WinRE first; repair only if WinRE is disabled or broken.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=900, justify=\"left\").pack(fill=\"x\", padx=14, pady=(0, 10))\n\n        self.winre_info_text = self._scrolled_text(body, height=14)\n        winre_check_btn = tk.Button(body, text=\"\ud83d\udd0d Check WinRE Status\", font=FONTS[\"small\"], bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=14, pady=8, cursor=\"hand2\",\n              command=lambda: self._confirm_and_launch_job(\"Check WinRE Status\", \"Inspect the Windows Recovery Environment.\", None, \"winre_status\", self._run_winre_status))\n        winre_check_btn.pack(pady=(0, 6), padx=14, anchor=\"w\")\n        self._create_tooltip(winre_check_btn, \"Check whether Windows Recovery Environment is enabled and correctly configured.\")\n        winre_repair_btn = tk.Button(body, text=\"\u2699 Repair WinRE\", font=FONTS[\"small\"], bg=C[\"btn_warn\"], fg=C[\"text\"], bd=0, padx=14, pady=8, cursor=\"hand2\",\n              command=lambda: self._confirm_and_launch_job(\"Repair WinRE\", \"Repair or enable Windows Recovery Environment.\", None, \"winre_repair\", self._run_winre_repair))\n        winre_repair_btn.pack(pady=(0, 14), padx=14, anchor=\"w\")\n        self._create_tooltip(winre_repair_btn, \"Repair or enable WinRE. Only use this if WinRE is missing or broken.\")\n        return body\n\n    def _build_boot_repair_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        desc = tk.Label(body, text=\"Boot diagnostics, BCD recovery and bootloader repair.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\")\n        desc.pack(fill=\"x\", padx=14, pady=(10, 8))\n        tk.Label(body, text=\"Visible help: Collect diagnostics first; repair MBR or rebuild BCD only if diagnostics indicate corruption.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=900, justify=\"left\").pack(fill=\"x\", padx=14, pady=(0, 10))\n        self.boot_repair_log = self._scrolled_text(body, height=16)\n\n        actions = tk.Frame(body, bg=C[\"card\"])\n        actions.pack(fill=\"x\", padx=14, pady=(10, 6))\n        for label, title, target, tip in [\n            (\"\ud83d\udd0d\", \"Collect Boot Diagnostics\", self._run_boot_diagnostics, \"Collect BCD and boot diagnostics to inspect startup configuration without making changes.\"),\n            (\"\ud83d\udee0\", \"Fix MBR\", self._run_boot_fix_mbr, \"Repair the Master Boot Record. Use only when diagnostics indicate MBR corruption.\"),\n            (\"\ud83e\udde9\", \"Rebuild BCD\", self._run_boot_rebuild_bcd, \"Rebuild the Boot Configuration Data store for Windows startup recovery.\"),\n        ]:\n            btn = tk.Button(actions, text=f\"{label} {title}\", font=FONTS[\"small\"], bg=C[\"btn_chip\"], fg=C[\"text\"], bd=0, padx=12, pady=8, cursor=\"hand2\",\n                      command=lambda t=target, n=title: self._confirm_and_launch_job(n, f\"{title} will perform safe boot diagnostics or repair.\", None, f\"boot_{title.replace(' ', '_').lower()}\", t))\n            btn.pack(side=\"left\", padx=4)\n            self._create_tooltip(btn, tip)\n        return body\n\n    def _build_rescue_media_creator_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        tk.Label(body, text=\"Rescue media readiness and removable drive validation.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\").pack(fill=\"x\", padx=14, pady=(10, 8))\n        tk.Label(body, text=\"Visible help: Probe removable drives and validate your target before building a rescue USB.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=900, justify=\"left\").pack(fill=\"x\", padx=14, pady=(0, 10))\n        self.rescue_media_status = self._scrolled_text(body, height=16)\n        probe_btn = tk.Button(body, text=\"\ud83d\udce6 Probe Rescue Media\", font=FONTS[\"small\"], bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=14, pady=8, cursor=\"hand2\",\n              command=lambda: self._confirm_and_launch_job(\"Probe Rescue Media\", \"Scan for removable rescue media targets.\", None, \"probe_rescue_media\", self._run_probe_rescue_media))\n        probe_btn.pack(pady=(0, 6), padx=14, anchor=\"w\")\n        self._create_tooltip(probe_btn, \"Scan removable drives and rescue media readiness before creating or using a bootable USB.\")\n        build_btn = tk.Button(body, text=\"\ud83d\udcbf Build Rescue USB\", font=FONTS[\"small\"], bg=C[\"btn_hw\"], fg=C[\"text\"], bd=0, padx=14, pady=8, cursor=\"hand2\",\n              command=lambda: self._confirm_and_launch_job(\"Build Rescue USB\", \"Create a rescue USB if WinPE tools are available.\", None, \"build_rescue_media\", self._run_build_rescue_media))\n        build_btn.pack(pady=(0, 14), padx=14, anchor=\"w\")\n        self._create_tooltip(build_btn, \"Create a rescue USB drive for offline repair when the system cannot boot.\")\n        return body\n\n    def _build_offline_recovery_tools_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        tk.Label(body, text=\"Offline recovery diagnostics without changing system state.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\").pack(fill=\"x\", padx=14, pady=(10, 8))\n        tk.Label(body, text=\"Visible help: Use offline captures to preserve evidence; avoid writing to the live system.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=900, justify=\"left\").pack(fill=\"x\", padx=14, pady=(0, 10))\n        self.offline_recovery_log = self._scrolled_text(body, height=16)\n        actions = tk.Frame(body, bg=C[\"card\"])\n        actions.pack(fill=\"x\", padx=14, pady=(0, 10))\n        for title, target, tip in [\n            (\"Capture Offline Snapshot\", self._run_offline_snapshot, \"Collect offline snapshot metadata for safe recovery investigations without changing live system state.\"),\n            (\"Collect Offline Registry\", self._run_offline_registry_collect, \"Export SYSTEM registry data for offline recovery analysis and evidence preservation.\"),\n        ]:\n            btn = tk.Button(actions, text=title, font=FONTS[\"small\"], bg=C[\"btn_chip\"], fg=C[\"text\"], bd=0, padx=12, pady=8, cursor=\"hand2\",\n                      command=lambda t=target, n=title: self._confirm_and_launch_job(n, f\"{title} will gather offline recovery artifacts.\", None, f\"offline_{title.replace(' ', '_').lower()}\", t))\n            btn.pack(side=\"left\", padx=4)\n            self._create_tooltip(btn, tip)\n        return body\n\n    def _build_password_recovery_assistant_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        tk.Label(body, text=\"Account diagnostics, SAM backup and BitLocker insight.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\").pack(fill=\"x\", padx=14, pady=(10, 8))\n        tk.Label(body, text=\"Visible help: Collect account and encryption diagnostics before performing password recovery.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=900, justify=\"left\").pack(fill=\"x\", padx=14, pady=(0, 10))\n        self.password_recovery_log = self._scrolled_text(body, height=16)\n        actions = tk.Frame(body, bg=C[\"card\"])\n        actions.pack(fill=\"x\", padx=14, pady=(0, 10))\n        for title, target, tip in [\n            (\"Account Diagnostics\", self._run_account_diagnostics, \"Inspect local user accounts and password recovery options for troubleshooting locked systems.\"),\n            (\"SAM + SYSTEM Backup\", self._run_sam_system_backup, \"Backup SAM and SYSTEM registry hives for password recovery and forensic analysis.\"),\n            (\"BitLocker Info\", self._run_bitlocker_info, \"View BitLocker encryption status for the system drive before recovery operations.\"),\n        ]:\n            btn = tk.Button(actions, text=title, font=FONTS[\"small\"], bg=C[\"btn_chip\"], fg=C[\"text\"], bd=0, padx=12, pady=8, cursor=\"hand2\",\n                      command=lambda t=target, n=title: self._confirm_and_launch_job(n, f\"{title} will gather recovery-sensitive diagnostics.\", None, f\"password_{title.replace(' ', '_').lower()}\", t))\n            btn.pack(side=\"left\", padx=4)\n            self._create_tooltip(btn, tip)\n        return body\n\n    def _build_advanced_recovery_console_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        tk.Label(body, text=\"Recovery console diagnostics, BCD dump and event correlation.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\").pack(fill=\"x\", padx=14, pady=(10, 8))\n        tk.Label(body, text=\"Visible help: Collect configuration and event diagnostics before making low-level recovery changes.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=900, justify=\"left\").pack(fill=\"x\", padx=14, pady=(0, 10))\n        self.recovery_console_log = self._scrolled_text(body, height=16)\n        actions = tk.Frame(body, bg=C[\"card\"])\n        actions.pack(fill=\"x\", padx=14, pady=(0, 10))\n        for title, target, tip in [\n            (\"Dump BCD Configuration\", self._run_bcd_dump, \"Export current BCD configuration for diagnostics before making boot repairs.\"),\n            (\"Collect Event Correlation\", self._run_event_correlation, \"Collect event logs to correlate boot and system errors during recovery.\"),\n            (\"Open Recovery Shell\", self._run_recovery_shell, \"Open a safe recovery shell capture for low-level troubleshooting.\"),\n        ]:\n            btn = tk.Button(actions, text=title, font=FONTS[\"small\"], bg=C[\"btn_chip\"], fg=C[\"text\"], bd=0, padx=12, pady=8, cursor=\"hand2\",\n                      command=lambda t=target, n=title: self._confirm_and_launch_job(n, f\"{title} will collect recovery console diagnostics.\", None, f\"console_{title.replace(' ', '_').lower()}\", t))\n            btn.pack(side=\"left\", padx=4)\n            self._create_tooltip(btn, tip)\n        return body\n\n    def _build_technician_toolkit_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        tk.Label(body, text=\"Technician tools for health checks, log capture and readiness validation.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\").pack(fill=\"x\", padx=14, pady=(10, 8))\n        tk.Label(body, text=\"Visible help: Run health checks and validate restore points before attempting repairs.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=900, justify=\"left\").pack(fill=\"x\", padx=14, pady=(0, 10))\n        self.technician_toolkit_log = self._scrolled_text(body, height=16)\n        actions = tk.Frame(body, bg=C[\"card\"])\n        actions.pack(fill=\"x\", padx=14, pady=(0, 10))\n        for title, target, tip in [\n            (\"Run Health Check\", self._run_technician_health_check, \"Run a system health check to gather recovery readiness diagnostics.\"),\n            (\"Collect System Logs\", self._run_collect_system_logs, \"Collect system event logs for technician troubleshooting.\"),\n            (\"Validate Recovery Readiness\", self._run_recovery_readiness_check, \"Check restore point and recovery safety readiness before repair actions.\"),\n        ]:\n            btn = tk.Button(actions, text=title, font=FONTS[\"small\"], bg=C[\"btn_chip\"], fg=C[\"text\"], bd=0, padx=12, pady=8, cursor=\"hand2\",\n                      command=lambda t=target, n=title: self._confirm_and_launch_job(n, f\"{title} will inspect recovery readiness and capture diagnostics.\", None, f\"tech_{title.replace(' ', '_').lower()}\", t))\n            btn.pack(side=\"left\", padx=4)\n            self._create_tooltip(btn, tip)\n        return body\n\n    def _refresh_rescue_dashboard_status(self):\n        data = {\"winre\": \"Unavailable\", \"bitlocker\": \"Unavailable\", \"restore\": \"Unavailable\", \"readiness\": \"Pending\", \"restore_points\": []}\n        try:\n            out, rc = self._run_cmd(\"reagentc /info\", timeout=18)\n            data[\"winre\"] = out.strip() if rc == 0 else f\"Error ({rc})\"\n        except Exception as e:\n            data[\"winre\"] = f\"Failed: {e}\"\n        try:\n            out, rc = self._run_cmd(\"manage-bde -status C:\", timeout=20)\n            data[\"bitlocker\"] = out.strip() if rc == 0 else f\"Error ({rc})\"\n        except Exception as e:\n            data[\"bitlocker\"] = f\"Failed: {e}\"\n        try:\n            if hasattr(self, \"restore_point_manager\"):\n                recent = self.restore_point_manager.list_recent(3) or []\n                data[\"restore_points\"] = recent\n                data[\"restore\"] = f\"{len(recent)} recent restore point(s)\"\n        except Exception:\n            data[\"restore\"] = \"Failed to enumerate\"\n        try:\n            if any(not v for v in (data[\"winre\"], data[\"bitlocker\"], data[\"restore\"])):\n                data[\"readiness\"] = \"Attention required\"\n            else:\n                data[\"readiness\"] = \"Ready\"\n        except Exception:\n            data[\"readiness\"] = \"Partial\"\n        data[\"ts\"] = datetime.datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\")\n        self.after(0, lambda: self._apply_rescue_dashboard_data(data))\n\n    def _apply_rescue_dashboard_data(self, data):\n        try:\n            self.rescue_winre_status.set(data.get(\"winre\", \"Unknown\"))\n            self.rescue_bitlocker_status.set(data.get(\"bitlocker\", \"Unknown\"))\n            self.rescue_restore_status.set(data.get(\"restore\", \"Unknown\"))\n            self.rescue_readiness_status.set(data.get(\"readiness\", \"Pending\"))\n            self.rescue_last_sync.set(data.get(\"ts\", \"Never\"))\n            if hasattr(self, \"rescue_history_tree\"):\n                self.rescue_history_tree.delete(*self.rescue_history_tree.get_children())\n                for item in data.get(\"restore_points\", []):\n                    self.rescue_history_tree.insert(\"\", \"end\", values=(item.get(\"Created\"), item.get(\"Description\"), item.get(\"SequenceNumber\")))\n        except Exception:\n            pass\n\n    def _collect_restore_point(self):\n        try:\n            if getattr(self, \"change_coordinator\", None):\n                info = self.change_coordinator.create_restore_point(\"Rescue Center checkpoint\")\n                return {\"ok\": bool(info.get(\"ok\")), \"message\": \"Restore point created.\" if info.get(\"ok\") else \"Restore point failed.\"}\n            if getattr(self, \"restore_point_manager\", None):\n                ok = self.restore_point_manager.create(\"Rescue Center checkpoint\", force=True)\n                return {\"ok\": ok, \"message\": \"Restore point created.\" if ok else \"Restore point failed.\"}\n        except Exception as e:\n            return {\"ok\": False, \"message\": str(e)}\n        return {\"ok\": False, \"message\": \"No restore manager available.\"}\n\n    def _run_winre_status(self):\n        out, rc = self._run_cmd(\"reagentc /info\", timeout=18)\n        self._append_log(self.winre_info_text, out or f\"Command failed ({rc})\", C[\"text\"])\n\n    def _run_winre_repair(self):\n        out, rc = self._run_cmd(\"reagentc /enable\", timeout=30)\n        self._append_log(self.winre_info_text, out or f\"Command failed ({rc})\", C[\"success\"] if rc == 0 else C[\"error\"])\n        if getattr(self, \"structured_logger\", None):\n            self.structured_logger.event(\"recovery_center\", \"winre_repair\", rc=rc)\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.winre_repair\", {\"rc\": rc})\n\n    def _run_boot_diagnostics(self):\n        self._append_log(self.boot_repair_log, \"Collecting BCD and boot diagnostics...\", C[\"accent4\"])\n        out, rc = self._run_cmd(\"bcdedit /enum all\", timeout=25)\n        self._append_log(self.boot_repair_log, out or f\"Command failed ({rc})\", C[\"text\"])\n        out2, rc2 = self._run_cmd(\"bootrec /scanos\", timeout=25)\n        self._append_log(self.boot_repair_log, out2 or f\"Command failed ({rc2})\", C[\"text\"])\n        if getattr(self, \"structured_logger\", None):\n            self.structured_logger.event(\"recovery_center\", \"boot_diagnostics\", rc1=rc, rc2=rc2)\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.boot_diagnostics\", {\"rc1\": rc, \"rc2\": rc2})\n\n    def _run_boot_fix_mbr(self):\n        out, rc = self._run_cmd(\"bootrec /fixmbr\", timeout=30)\n        self._append_log(self.boot_repair_log, out or f\"Command failed ({rc})\", C[\"success\"] if rc == 0 else C[\"error\"])\n        if getattr(self, \"structured_logger\", None):\n            self.structured_logger.event(\"recovery_center\", \"boot_fix_mbr\", rc=rc)\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.boot_fix_mbr\", {\"rc\": rc})\n\n    def _run_boot_rebuild_bcd(self):\n        out, rc = self._run_cmd(\"bootrec /rebuildbcd\", timeout=40)\n        self._append_log(self.boot_repair_log, out or f\"Command failed ({rc})\", C[\"success\"] if rc == 0 else C[\"error\"])\n        if getattr(self, \"structured_logger\", None):\n            self.structured_logger.event(\"recovery_center\", \"boot_rebuild_bcd\", rc=rc)\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.boot_rebuild_bcd\", {\"rc\": rc})\n\n    def _run_probe_rescue_media(self):\n        self._append_log(self.rescue_media_status, \"Probing removable drives and rescue media readiness...\", C[\"accent4\"])\n        out, rc = self._run_cmd(\"powershell -NoProfile -Command \\\"Get-Disk | Where-Object MediaType -eq 'Removable' | Select Number,FriendlyName,Size | ConvertTo-Json\\\"\", timeout=25)\n        self._append_log(self.rescue_media_status, out or f\"Command failed ({rc})\", C[\"text\"])\n        if getattr(self, \"structured_logger\", None):\n            self.structured_logger.event(\"recovery_center\", \"probe_rescue_media\", rc=rc)\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.probe_rescue_media\", {\"rc\": rc})\n\n    def _run_build_rescue_media(self):\n        self._append_log(self.rescue_media_status, \"Attempting rescue media build...\", C[\"accent4\"])\n        out, rc = self._run_cmd(\"powershell -NoProfile -Command \\\"if (Get-Command copype -ErrorAction SilentlyContinue) { Write-Output 'WinPE toolchain available' } else { Write-Error 'WinPE toolchain not found' }\\\"\", timeout=20)\n        self._append_log(self.rescue_media_status, out or f\"Command failed ({rc})\", C[\"text\"])\n        if getattr(self, \"structured_logger\", None):\n            self.structured_logger.event(\"recovery_center\", \"build_rescue_media\", rc=rc)\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.build_rescue_media\", {\"rc\": rc})\n\n    def _run_offline_snapshot(self):\n        self._append_log(self.offline_recovery_log, \"Collecting offline snapshot metadata...\", C[\"accent4\"])\n        out, rc = self._run_cmd(\"powershell -NoProfile -Command \\\"Get-ComputerInfo | Select CsName,WindowsVersion,OsBuildNumber,WindowsInstallationType | ConvertTo-Json\\\"\", timeout=25)\n        self._append_log(self.offline_recovery_log, out or f\"Command failed ({rc})\", C[\"text\"])\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.offline_snapshot\", {\"rc\": rc})\n\n    def _run_offline_registry_collect(self):\n        self._append_log(self.offline_recovery_log, \"Collecting offline registry artifacts...\", C[\"accent4\"])\n        out, rc = self._run_cmd(\"reg save HKLM\\\\SYSTEM %TEMP%\\\\SYSTEM_hive_backup /y\", timeout=30)\n        self._append_log(self.offline_recovery_log, out or f\"Command failed ({rc})\", C[\"success\"] if rc == 0 else C[\"error\"])\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.offline_registry_collect\", {\"rc\": rc})\n\n    def _run_account_diagnostics(self):\n        self._append_log(self.password_recovery_log, \"Gathering account diagnostics...\", C[\"accent4\"])\n        out, rc = self._run_cmd(\"net user\", timeout=20)\n        self._append_log(self.password_recovery_log, out or f\"Command failed ({rc})\", C[\"text\"])\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.account_diagnostics\", {\"rc\": rc})\n\n    def _run_sam_system_backup(self):\n        self._append_log(self.password_recovery_log, \"Backing up SAM and SYSTEM hives...\", C[\"accent4\"])\n        backup_dir = os.path.join(os.environ.get(\"TEMP\", \"C:\\\\Temp\"), \"sam_backup\")\n        try:\n            os.makedirs(backup_dir, exist_ok=True)\n        except Exception:\n            pass\n        for hive in [\"SAM\", \"SYSTEM\"]:\n            out, rc = self._run_cmd(f\"reg save HKLM\\\\{hive} {backup_dir}\\\\{hive}.hiv /y\", timeout=30)\n            self._append_log(self.password_recovery_log, out or f\"{hive} save failed ({rc})\", C[\"success\"] if rc == 0 else C[\"error\"])\n            if getattr(self, \"telemetry_store\", None):\n                self.telemetry_store.append(\"recovery.sam_backup\", {\"hive\": hive, \"rc\": rc})\n        if getattr(self, \"structured_logger\", None):\n            self.structured_logger.event(\"recovery_center\", \"sam_system_backup\", path=backup_dir)\n\n    def _run_bitlocker_info(self):\n        self._append_log(self.password_recovery_log, \"Collecting BitLocker status...\", C[\"accent4\"])\n        out, rc = self._run_cmd(\"manage-bde -status C:\", timeout=20)\n        self._append_log(self.password_recovery_log, out or f\"Command failed ({rc})\", C[\"text\"])\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.bitlocker_info\", {\"rc\": rc})\n\n    def _run_bcd_dump(self):\n        self._append_log(self.recovery_console_log, \"Dumping BCD configuration...\", C[\"accent4\"])\n        out, rc = self._run_cmd(\"bcdedit /enum all\", timeout=30)\n        self._append_log(self.recovery_console_log, out or f\"Command failed ({rc})\", C[\"text\"])\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.bcd_dump\", {\"rc\": rc})\n\n    def _run_event_correlation(self):\n        self._append_log(self.recovery_console_log, \"Collecting event correlation data...\", C[\"accent4\"])\n        out, rc = self._run_cmd(\"wevtutil qe System /c:50 /f:text\", timeout=25)\n        self._append_log(self.recovery_console_log, out or f\"Command failed ({rc})\", C[\"text\"])\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.event_correlation\", {\"rc\": rc})\n\n    def _run_recovery_shell(self):\n        self._append_log(self.recovery_console_log, \"Launching safe recovery shell capture...\", C[\"accent4\"])\n        out, rc = self._run_cmd(\"cmd /c echo Recovery shell initialized\", timeout=10)\n        self._append_log(self.recovery_console_log, out or f\"Command failed ({rc})\", C[\"text\"])\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.recovery_shell\", {\"rc\": rc})\n\n    def _run_technician_health_check(self):\n        self._append_log(self.technician_toolkit_log, \"Running technician health check...\", C[\"accent4\"])\n        out, rc = self._run_cmd(\"systeminfo\", timeout=40)\n        self._append_log(self.technician_toolkit_log, out or f\"Command failed ({rc})\", C[\"text\"])\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.health_check\", {\"rc\": rc})\n\n    def _run_collect_system_logs(self):\n        self._append_log(self.technician_toolkit_log, \"Collecting system logs...\", C[\"accent4\"])\n        out, rc = self._run_cmd(\"wevtutil qe System /c:30 /f:text\", timeout=25)\n        self._append_log(self.technician_toolkit_log, out or f\"Command failed ({rc})\", C[\"text\"])\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.collect_system_logs\", {\"rc\": rc})\n\n    def _run_recovery_readiness_check(self):\n        self._append_log(self.technician_toolkit_log, \"Validating recovery readiness...\", C[\"accent4\"])\n        out, rc = self._run_cmd(\"reagentc /info\", timeout=18)\n        self._append_log(self.technician_toolkit_log, out or f\"Command failed ({rc})\", C[\"text\"])\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.readiness_check\", {\"rc\": rc})\n\n    def _build_recovery_modern(self, parent):\n        return self._build_recovery_safe(parent)\n\n    def _on_recovery_task_update(self, task):\n        self._ui_queue.put((\"recovery_queue\", None))\n        self._ui_queue.put((\"recovery_refresh\", None))\n        self._ui_queue.put((\"recovery_log\", f\"[{task.label}] {task.status.upper()} - {task.message or 'No details'}\"))\n        if task.status == \"running\":\n            self._ui_queue.put((\"status\", (f\"Recovery task running: {task.label}\", C[\"accent4\"])))\n        elif task.status == \"completed\":\n            self._ui_queue.put((\"status\", (f\"Recovery task completed: {task.label}\", C[\"success\"])))\n        elif task.status == \"failed\":\n            self._ui_queue.put((\"status\", (f\"Recovery task failed: {task.label}\", C[\"error\"])))\n        elif task.status == \"cancelled\":\n            self._ui_queue.put((\"status\", (f\"Recovery task cancelled: {task.label}\", C[\"warning\"])))\n\n    def _append_recovery_log(self, msg):\n        if not hasattr(self, \"recovery_log_text\"):\n            return\n        try:\n            self.recovery_log_text.config(state=\"normal\")\n            self.recovery_log_text.insert(\"end\", self._fix_text(str(msg)) + \"\\n\")\n            lines = float(self.recovery_log_text.index(\"end-1c\").split(\".\")[0])\n            if lines &gt; 500:\n                self.recovery_log_text.delete(\"1.0\", \"100.0\")\n            self.recovery_log_text.see(\"end\")\n            self.recovery_log_text.config(state=\"disabled\")\n        except Exception:\n            pass\n\n    def _refresh_recovery_tree(self, tree, category=None):\n        if tree is None:\n            return\n        try:\n            for iid in tree.get_children():\n                tree.delete(iid)\n            for item in self.recovery_results.all():\n                if category and item.category != category:\n                    continue\n                tag = \"recovered\" if item.recoverability_score &gt;= 75 else \"partial\" if item.recoverability_score &gt;= 40 else \"failed\"\n                tree.insert(\"\", \"end\", values=(\n                    item.file_name,\n                    item.file_type,\n                    self._fmt_size(item.size_bytes),\n                    item.status,\n                    item.path,\n                    f\"{item.recoverability_score}%\",\n                ), tags=(tag,))\n        except Exception:\n            pass\n\n    def _refresh_recovery_queue_tree(self):\n        tree = getattr(self, \"recovery_queue_tree\", None)\n        if tree is None:\n            return\n        try:\n            for iid in tree.get_children():\n                tree.delete(iid)\n            for task in self.recovery_manager.list_tasks():\n                tree.insert(\"\", \"end\", iid=task.task_id, values=(\n                    task.label,\n                    task.status,\n                    f\"{int(task.progress)}%\",\n                    task.message or \"\",\n                ))\n        except Exception:\n            pass\n\n    def _get_recovery_disk_values(self):\n        drives = [f\"{d}:\\\\\" for d in \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\" if os.path.exists(f\"{d}:\\\\\")]\n        raw_values = [DEFAULT_RAW_DISK] + [f\"\\\\\\\\.\\\\{d}:\" for d in \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\" if os.path.exists(f\"{d}:\\\\\")]\n        return raw_values + drives\n\n    def _resolve_disk_path(self, val):\n        \"\"\"Resolve a displayed combobox value to an actual device path.\n\n        If the value matches an entry in _recovery_disk_map, return the mapped path,\n        otherwise return the raw value or DEFAULT_RAW_DISK.\n        \"\"\"\n        try:\n            if not val:\n                return DEFAULT_RAW_DISK\n            if hasattr(self, \"_recovery_disk_map\") and isinstance(val, str) and val in self._recovery_disk_map:\n                return self._recovery_disk_map.get(val)\n            return val or DEFAULT_RAW_DISK\n        except Exception:\n            return DEFAULT_RAW_DISK\n\n    def _populate_recovery_disks(self):\n        \"\"\"Populate available physical disk display values and map them to device paths.\n\n        Uses PowerShell Get-Disk for friendly names; falls back to basic listing.\n        Updates any recovery combobox widgets if present.\n        \"\"\"\n        try:\n            script = \"Get-Disk | Select-Object Number,FriendlyName,Size,MediaType | ConvertTo-Json -Depth 2\"\n            out, rc = self._run_powershell(script, timeout=6)\n            disks = []\n            if out and out.strip() and out.strip() != \"[]\":\n                try:\n                    payload = json.loads(out)\n                    if isinstance(payload, dict):\n                        payload = [payload]\n                    for d in payload:\n                        num = d.get(\"Number\")\n                        name = d.get(\"FriendlyName\") or d.get(\"Model\") or \"Disk\"\n                        size = int(d.get(\"Size\") or 0)\n                        human = self._fmt_size(size)\n                        label = f\"PhysicalDrive{num} - {name} ({human})\"\n                        path = f\"\\\\\\\\.\\\\PhysicalDrive{num}\"\n                        disks.append((label, path))\n                except Exception:\n                    disks = []\n\n            if not disks:\n                # Fallback: use simple raw device list + letters\n                raw_vals = [DEFAULT_RAW_DISK]\n                for d in \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\":\n                    if os.path.exists(f\"{d}:\\\\\"):\n                        raw_vals.append(f\"\\\\\\\\.\\\\{d}:\")\n                disks = [(v, v) for v in raw_vals]\n\n            # Build map and display values\n            self._recovery_disk_map = {label: path for label, path in disks}\n            display_values = [label for label, _ in disks]\n\n            # Update known comboboxes if they exist\n            try:\n                if hasattr(self, \"partition_source_combo\"):\n                    self.partition_source_combo.configure(values=display_values)\n                if hasattr(self, \"deep_recovery_source_combo\"):\n                    self.deep_recovery_source_combo.configure(values=display_values)\n                if hasattr(self, \"raw_carve_source_combo\"):\n                    self.raw_carve_source_combo.configure(values=display_values)\n                if hasattr(self, \"nand_source_combo\"):\n                    self.nand_source_combo.configure(values=display_values)\n                if hasattr(self, \"dashboard_disk_combo\"):\n                    self.dashboard_disk_combo.configure(values=display_values)\n                if hasattr(self, \"photorec_source_combo\"):\n                    self.photorec_source_combo.configure(values=display_values)\n                if hasattr(self, \"mft_source_combo\"):\n                    self.mft_source_combo.configure(values=display_values)\n                if hasattr(self, \"raw_disk_combo\"):\n                    # raw_disk_combo expects raw/paths; extend with display labels too\n                    try:\n                        cur = list(self.raw_disk_combo.cget(\"values\"))\n                        combined = display_values + [v for v in cur if v not in display_values]\n                        self.raw_disk_combo.configure(values=combined)\n                    except Exception:\n                        pass\n                # Also populate detected disks tree if present\n                try:\n                    if hasattr(self, \"detected_disks_tree\") and self.detected_disks_tree is not None:\n                        try:\n                            for iid in self.detected_disks_tree.get_children():\n                                self.detected_disks_tree.delete(iid)\n                            for label, path in disks:\n                                # extract index from path if PhysicalDrive\n                                m = re.match(r\"\\\\\\\\.\\\\PhysicalDrive(\\d+)\", path)\n                                idx = int(m.group(1)) if m else -1\n                                size = \"\"\n                                try:\n                                    # try to get size by path\n                                    sz = _disk_source_size(path)\n                                    size = self._fmt_size(sz)\n                                except Exception:\n                                    size = \"N/A\"\n                                self.detected_disks_tree.insert(\"\", \"end\", iid=path, values=(idx if idx&gt;=0 else \"-\", label, size))\n                        except Exception:\n                            pass\n                except Exception:\n                    pass\n            except Exception:\n                pass\n        except Exception:\n            pass\n\n    def _emit_recovery_scan_stats(self, stats: dict):\n        try:\n            self._ui_queue.put((\"recovery_scan_stats\", stats))\n        except Exception:\n            pass\n\n    def _apply_recovery_scan_stats(self, stats):\n        if not isinstance(stats, dict):\n            return\n        tab = stats.get(\"tab\", \"global\")\n        pct = float(stats.get(\"pct\", 0) or 0)\n        files = int(stats.get(\"files_found\", 0) or 0)\n        folders = int(stats.get(\"folders_scanned\", 0) or 0)\n        msg = str(stats.get(\"message\", \"\") or \"\")\n        self._recovery_live_stats[tab] = stats\n        panel = self._recovery_progress_panels.get(tab) or self._recovery_progress_panels.get(\"global\")\n        if panel:\n            try:\n                panel[\"pct_var\"].set(max(0.0, min(100.0, pct)))\n                panel[\"bar\"].configure(mode=\"determinate\")\n            except Exception:\n                pass\n            try:\n                panel[\"stats_label\"].config(\n                    text=f\"\ud83d\udcc1 Files: {files:,}  |  \ud83d\udcc2 Folders: {folders:,}  |  {pct:.0f}%\"\n                )\n            except Exception:\n                pass\n            if msg and panel.get(\"status_label\"):\n                panel[\"status_label\"].config(text=msg[:220])\n        if tab == \"deep\" and hasattr(self, \"deep_recovery_status\"):\n            self.deep_recovery_status.config(text=f\"{pct:.0f}% \u2014 {files:,} signatures | {msg[:80]}\", fg=C[\"accent4\"])\n        if tab == \"photorec\" and hasattr(self, \"photorec_status_label\"):\n            rec = int(stats.get(\"files_recovered\", files) or 0)\n            self.photorec_status_label.config(\n                text=f\"PhotoRec: {pct:.0f}% | Recovered: {rec:,} | Found: {files:,}\", fg=C[\"accent2\"])\n        if tab == \"mft\" and hasattr(self, \"mft_status_label\"):\n            self.mft_status_label.config(\n                text=f\"MFT: {pct:.0f}% | Deleted: {files:,} | Recovered: {int(stats.get('files_recovered', 0)):,}\",\n                fg=C[\"accent2\"],\n            )\n        if hasattr(self, \"rec_stats_label\") and tab in (\"photorec\", \"deep\", \"mft\", \"raw\"):\n            self.rec_stats_label.config(text=f\"{files:,} items | Live scan {pct:.0f}%\")\n\n    def _build_recovery_progress_strip(self, parent, tab_key, title=\"Scan Progress\"):\n        strip = tk.LabelFrame(parent, text=title, font=FONTS[\"small\"], fg=C[\"accent2\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        strip.pack(fill=\"x\", padx=10, pady=(6, 8))\n        status_label = tk.Label(strip, text=\"\u0924\u0948\u092f\u093e\u0930 \u2014 scan \u0936\u0941\u0930\u0942 \u0915\u0930\u0947\u0902\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], anchor=\"w\")\n        status_label.pack(fill=\"x\", padx=10, pady=(8, 2))\n        stats_label = tk.Label(strip, text=\"\ud83d\udcc1 Files: 0  |  \ud83d\udcc2 Folders: 0  |  0%\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"], anchor=\"w\")\n        stats_label.pack(fill=\"x\", padx=10, pady=(0, 4))\n        pct_var = tk.DoubleVar(value=0.0)\n        bar = ttk.Progressbar(strip, variable=pct_var, maximum=100.0, mode=\"determinate\")\n        bar.pack(fill=\"x\", padx=10, pady=(0, 10))\n        self._recovery_progress_panels[tab_key] = {\n            \"pct_var\": pct_var,\n            \"bar\": bar,\n            \"stats_label\": stats_label,\n            \"status_label\": status_label,\n        }\n        return strip\n\n    def _reset_recovery_progress(self, tab_key, message=\"Scan \u0936\u0941\u0930\u0942 \u0939\u094b \u0930\u0939\u093e \u0939\u0948...\"):\n        panel = self._recovery_progress_panels.get(tab_key)\n        if panel:\n            panel[\"pct_var\"].set(0)\n            panel[\"status_label\"].config(text=message)\n            panel[\"stats_label\"].config(text=\"\ud83d\udcc1 Files: 0  |  \ud83d\udcc2 Folders: 0  |  0%\")\n\n    def _show_recovery_center(self):\n        if hasattr(self, \"recovery_queue_tree\"):\n            self._refresh_recovery_queue_tree()\n        try:\n            self._launch_job(\"populate_recovery_disks\", self._populate_recovery_disks)\n        except Exception:\n            pass\n\n    def _build_recovery_center(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(\n            frame,\n            \"\ud83d\udcc2 Professional File Recovery\",\n            \"Recuva / EaseUS style workflow \u2014 live progress, PhotoRec carving, NTFS MFT deleted recovery.\",\n        )\n\n        global_strip = tk.Frame(frame, bg=C[\"card\"], highlightbackground=C[\"accent2\"], highlightthickness=2)\n        global_strip.pack(fill=\"x\", padx=16, pady=(4, 8))\n        tk.Label(global_strip, text=\"\ud83d\udda5\ufe0f Live Recovery Status\", font=FONTS[\"subhead\"], fg=C[\"accent2\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=12, pady=(8, 2))\n        self._build_recovery_progress_strip(global_strip, \"global\", \"Overall Progress\")\n\n        notebook = ttk.Notebook(frame)\n        notebook.pack(fill=\"both\", expand=True, padx=16, pady=(4, 12))\n\n        tabs = [\n            (\"\ud83c\udfe0 Dashboard\", self._build_recovery_dashboard_tab),\n            (\"\u26a1 Quick Scan\", self._build_recovery_quick_tab),\n            (\"\ud83d\udd0e Deep / Raw Scan\", self._build_recovery_deep_tab),\n            (\"\ud83e\udde9 PhotoRec Pro\", self._build_recovery_photorec_tab),\n            (\"\ud83d\uddc2\ufe0f MFT Deleted Files\", self._build_recovery_mft_tab),\n            (\"\ud83d\udcbe Partition\", self._build_recovery_partitions_tab),\n            (\"\u26a1 NAND Flash\", self._build_recovery_nand_tab),\n            (\"\ud83d\udccc Queue\", self._build_recovery_queue_tab),\n            (\"\ud83d\udccb Logs\", self._build_recovery_logs_tab),\n            (\"\ud83d\udd58 History\", self._build_recovery_history_tab),\n        ]\n        for title, builder in tabs:\n            tab = tk.Frame(notebook, bg=C[\"bg\"])\n            notebook.add(tab, text=title)\n            builder(tab)\n\n        return frame\n\n    def _build_recovery_dashboard_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        card = tk.LabelFrame(body, text=\"Recovery Dashboard \u2014 Disk select karein\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        card.pack(fill=\"x\", padx=14, pady=10)\n\n        row = tk.Frame(card, bg=C[\"card\"])\n        row.pack(fill=\"x\", padx=10, pady=10)\n        tk.Label(row, text=\"Target Disk:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=0, column=0, sticky=\"w\")\n        self.dashboard_disk_var = tk.StringVar(value=\"\")\n        self.dashboard_disk_combo = ttk.Combobox(row, textvariable=self.dashboard_disk_var, width=42, state=\"readonly\")\n        self.dashboard_disk_combo.grid(row=0, column=1, padx=8, sticky=\"w\")\n        tk.Button(row, text=\"\ud83d\udd04 Refresh Disks\", font=FONTS[\"small\"], bg=C[\"btn\"], fg=C[\"text\"], bd=0, padx=10, pady=6, cursor=\"hand2\",\n              command=lambda: self._launch_job(\"populate_recovery_disks\", self._populate_recovery_disks)).grid(row=0, column=2, padx=4)\n\n        tk.Label(row, text=\"Output Folder:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=1, column=0, sticky=\"w\", pady=(10, 0))\n        self.dashboard_output_var = tk.StringVar(value=os.path.join(os.path.expanduser(\"~\"), \"Desktop\", \"Godawari_Recovery\"))\n        tk.Entry(row, textvariable=self.dashboard_output_var, width=48, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).grid(row=1, column=1, padx=8, pady=(10, 0), sticky=\"w\")\n        tk.Button(row, text=\"Browse\", font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text\"], bd=0, padx=10, pady=6, cursor=\"hand2\",\n                  command=lambda: self._browse_recovery_output(self.dashboard_output_var)).grid(row=1, column=2, padx=4, pady=(10, 0))\n\n        modes = tk.Frame(card, bg=C[\"card\"])\n        modes.pack(fill=\"x\", padx=10, pady=(8, 12))\n        tk.Label(modes, text=\"Scan Mode (professional tools jaisa):\", font=FONTS[\"body\"], fg=C[\"accent2\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(0, 6))\n        btn_row = tk.Frame(modes, bg=C[\"card\"])\n        btn_row.pack(fill=\"x\")\n        for label, color, cmd in [\n            (\"\ud83d\udd0d Quick Scan (Existing Files)\", C[\"accent2\"], self._dashboard_start_quick),\n            (\"\ud83d\udd0e Deep Signature Scan\", C[\"btn_warn\"], self._dashboard_start_deep),\n            (\"\ud83e\udde9 PhotoRec Multi-Pass\", C[\"btn_hw\"], self._dashboard_start_photorec),\n            (\"\ud83d\uddc2\ufe0f MFT Deleted Recovery\", C[\"btn_info\"], self._dashboard_start_mft),\n        ]:\n            tk.Button(btn_row, text=label, font=FONTS[\"small\"], bg=color, fg=C[\"text\"] if color != C[\"accent2\"] else \"#000\",\n                      bd=0, padx=12, pady=10, cursor=\"hand2\", command=cmd).pack(side=\"left\", padx=4, pady=4)\n\n        hint = tk.Label(card,\n            text=\"\ud83d\udca1 Tip: Deleted files ke liye MFT \u092f\u093e PhotoRec use \u0915\u0930\u0947\u0902\u0964 Live progress bar \u0928\u0940\u091a\u0947 \u0939\u0930 tab \u092e\u0947\u0902 \u0926\u093f\u0916\u0947\u0917\u093e\u0964 Output \u0939\u092e\u0947\u0936\u093e \u0905\u0932\u0917 drive \u092a\u0930 \u0930\u0916\u0947\u0902\u0964\",\n            font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\", wraplength=900)\n        hint.pack(fill=\"x\", padx=12, pady=(0, 10))\n        return body\n\n    def _browse_recovery_output(self, var):\n        path = filedialog.askdirectory(title=\"Recovery output folder\")\n        if path:\n            var.set(path)\n\n    def _sync_dashboard_disk_to_tabs(self):\n        disk = self.dashboard_disk_var.get().strip()\n        if not disk:\n            return\n        path = getattr(self, \"_recovery_disk_map\", {}).get(disk, disk)\n        for attr in (\n            \"deep_recovery_source_var\", \"photorec_source_var\", \"mft_source_var\",\n            \"raw_carve_source_var\", \"partition_source_var\", \"nand_source_var\",\n        ):\n            if hasattr(self, attr):\n                getattr(self, attr).set(path if path.startswith(\"\\\\\\\\.\\\\\") else disk)\n\n    def _dashboard_start_quick(self):\n        self._sync_dashboard_disk_to_tabs()\n        if hasattr(self, \"quick_recovery_drive_var\"):\n            d = self.dashboard_disk_var.get()\n            if d and \":\" in d:\n                self.quick_recovery_drive_var.set(d.split(\" - \")[0] if \" - \" in d else d[:3] + \"\\\\\")\n            if hasattr(self, \"quick_recovery_dest_var\"):\n                self.quick_recovery_dest_var.set(self.dashboard_output_var.get())\n        self._start_quick_recovery()\n\n    def _dashboard_start_deep(self):\n        self._sync_dashboard_disk_to_tabs()\n        if hasattr(self, \"deep_recovery_source_var\"):\n            self.deep_recovery_source_var.set(self.dashboard_disk_var.get())\n        self._start_deep_recovery()\n\n    def _dashboard_start_photorec(self):\n        self._sync_dashboard_disk_to_tabs()\n        if hasattr(self, \"photorec_source_var\"):\n            self.photorec_source_var.set(self.dashboard_disk_var.get())\n        if hasattr(self, \"photorec_output_var\"):\n            self.photorec_output_var.set(self.dashboard_output_var.get())\n        self._start_photorec_tab_scan()\n\n    def _dashboard_start_mft(self):\n        self._sync_dashboard_disk_to_tabs()\n        if hasattr(self, \"mft_source_var\"):\n            self.mft_source_var.set(self.dashboard_disk_var.get())\n        if hasattr(self, \"mft_output_var\"):\n            self.mft_output_var.set(os.path.join(self.dashboard_output_var.get(), \"MFT_Recovered\"))\n        self._start_mft_deleted_recovery()\n\n    def _build_recovery_quick_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        self._build_recovery_progress_strip(body, \"quick\", \"Quick Scan \u2014 Live Progress\")\n        card = tk.LabelFrame(body, text=\"\ud83d\udccb Quick Recovery (Existing Files)\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        card.pack(fill=\"x\", padx=14, pady=10)\n\n        drive_values = [f\"{d}:\\\\\" for d in \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\" if os.path.exists(f\"{d}:\\\\\")]\n        self.quick_recovery_drive_var = tk.StringVar(value=drive_values[0] if drive_values else \"C:\\\\\")\n        self.quick_recovery_types_var = tk.StringVar(value=\"jpg,png,pdf,docx,mp4\")\n        self.quick_recovery_dest_var = tk.StringVar(value=os.path.join(os.path.expanduser(\"~\"), \"Desktop\", \"Godawari_Quick_Recovery\"))\n\n        row = tk.Frame(card, bg=C[\"card\"])\n        row.pack(fill=\"x\", padx=10, pady=(10, 8))\n        tk.Label(row, text=\"Drive:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=0, column=0, sticky=\"w\")\n        ttk.Combobox(row, textvariable=self.quick_recovery_drive_var, values=drive_values, width=14, state=\"readonly\").grid(row=0, column=1, padx=6)\n        tk.Label(row, text=\"File Types:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=0, column=2, padx=(14, 4), sticky=\"w\")\n        tk.Entry(row, textvariable=self.quick_recovery_types_var, width=28, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).grid(row=0, column=3, padx=6)\n        tk.Label(row, text=\"Destination:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=1, column=0, pady=(8, 0), sticky=\"w\")\n        tk.Entry(row, textvariable=self.quick_recovery_dest_var, width=60, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).grid(row=1, column=1, columnspan=3, padx=6, pady=(8, 0), sticky=\"w\")\n\n        action_row = tk.Frame(card, bg=C[\"card\"])\n        action_row.pack(fill=\"x\", padx=10, pady=(0, 10))\n        tk.Button(action_row, text=\"\ud83d\udd0d Start Scan\", font=FONTS[\"small\"], bg=C[\"accent2\"], fg=\"#000\", bd=0, padx=14, pady=8, cursor=\"hand2\", command=self._start_quick_recovery).pack(side=\"left\")\n        tk.Button(action_row, text=\"\ud83e\uddf9 Clear Results\", font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text\"], bd=0, padx=14, pady=8, cursor=\"hand2\", command=lambda: (self.recovery_results.clear(), self._refresh_recovery_tree(self.quick_recovery_tree, category=\"Quick Recovery\"))).pack(side=\"left\", padx=8)\n\n        self.quick_recovery_status = tk.Label(card, text=\"Ready for quick recovery scan.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"])\n        self.quick_recovery_status.pack(fill=\"x\", padx=10, pady=(0, 6))\n\n        results_outer = tk.LabelFrame(body, text=\"\ud83d\udcc1 Quick Recovery Results\", font=FONTS[\"subhead\"], fg=C[\"accent2\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        results_outer.pack(fill=\"both\", expand=True, padx=14, pady=(0, 14))\n        cols = (\"Filename\", \"Type\", \"Size\", \"Status\", \"Location\", \"Integrity\")\n        self.quick_recovery_tree = ttk.Treeview(results_outer, columns=cols, show=\"headings\", height=12, style=\"Custom.Treeview\")\n        for col, width in zip(cols, (220, 70, 90, 120, 280, 90)):\n            self.quick_recovery_tree.heading(col, text=col)\n            self.quick_recovery_tree.column(col, width=width, anchor=\"w\")\n        self.quick_recovery_tree.tag_configure(\"recovered\", foreground=C[\"success\"])\n        self.quick_recovery_tree.tag_configure(\"partial\", foreground=C[\"warning\"])\n        self.quick_recovery_tree.tag_configure(\"failed\", foreground=C[\"error\"])\n        self.quick_recovery_tree.pack(fill=\"both\", expand=True, padx=8, pady=8)\n        self.quick_recovery_tree.bind(\"&lt;&gt;\", self._on_quick_recovery_select)\n\n        self.quick_recovery_preview = scrolledtext.ScrolledText(body, height=6, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], wrap=\"word\", bd=0, relief=\"flat\")\n        self.quick_recovery_preview.pack(fill=\"x\", padx=14, pady=(0, 10))\n        self.quick_recovery_preview.config(state=\"disabled\")\n\n        return body\n\n    def _start_quick_recovery(self):\n        drive = self.quick_recovery_drive_var.get().strip()\n        if not drive or not os.path.exists(drive):\n            messagebox.showwarning(\"Drive Missing\", \"Valid drive select karo.\")\n            return\n        exts = [e.strip().lstrip(\".\").lower() for e in self.quick_recovery_types_var.get().split(\",\") if e.strip()]\n        dest = self.quick_recovery_dest_var.get().strip() or os.path.join(os.path.expanduser(\"~\"), \"Desktop\", \"Godawari_Quick_Recovery\")\n        try:\n            dest = get_recovery_safety(getattr(self, \"app_config\", None)).validate_output_dir(dest, drive)\n        except Exception as exc:\n            messagebox.showerror(\"Recovery Safety\", str(exc))\n            return\n        self.recovery_results.clear()\n        self._refresh_recovery_tree(self.quick_recovery_tree, category=\"Quick Recovery\")\n        self.recovery_manager.submit_task(\"Quick Recovery\", self._task_quick_recovery, drive, exts, dest)\n        self.quick_recovery_status.config(text=\"Queued quick recovery task...\", fg=C[\"accent4\"])\n\n    def _task_quick_recovery(self, task, drive, exts, dest):\n        found = 0\n        folders = 0\n        self._ui_queue.put((\"recovery_log\", f\"[Quick Recovery] Scanning {drive} for {', '.join(exts) or 'all file types'}\"))\n        for root, _, files in os.walk(drive):\n            folders += 1\n            task.wait_if_paused()\n            if task.is_cancelled():\n                raise InterruptedError(\"Quick recovery cancelled\")\n            for name in files:\n                task.wait_if_paused()\n                if task.is_cancelled():\n                    raise InterruptedError(\"Quick recovery cancelled\")\n                ext = os.path.splitext(name)[1].lstrip(\".\").lower()\n                if exts and ext not in exts:\n                    continue\n                path = os.path.join(root, name)\n                try:\n                    size = os.path.getsize(path)\n                except Exception:\n                    size = 0\n                score = 90 if size &gt; 0 else 20\n                item = RecoveryResultItem(\n                    item_id=f\"quick-{uuid.uuid4()}\",\n                    source=drive,\n                    category=\"Quick Recovery\",\n                    file_name=name,\n                    file_type=ext or \"unknown\",\n                    size_bytes=size,\n                    recoverability_score=score,\n                    status=\"found\",\n                    path=path,\n                    metadata={\"root\": root},\n                )\n                self.recovery_results.add(item)\n                found += 1\n                if found % 20 == 0:\n                    self._emit_recovery_scan_stats({\n                        \"tab\": \"quick\",\n                        \"pct\": min(95, found // 15),\n                        \"files_found\": found,\n                        \"folders_scanned\": folders,\n                        \"message\": f\"Scanning... {found:,} files in {folders:,} folders\",\n                    })\n                if score &gt;= 75 and dest:\n                    try:\n                        safe_dest = get_recovery_safety(getattr(self, \"app_config\", None)).validate_output_dir(dest, drive)\n                        rel = os.path.relpath(path, drive)\n                        out_path = os.path.join(safe_dest, rel)\n                        os.makedirs(os.path.dirname(out_path), exist_ok=True)\n                        if not os.path.exists(out_path):\n                            shutil.copy2(path, out_path)\n                            item.metadata[\"exported_to\"] = out_path\n                    except Exception:\n                        pass\n                if found % 25 == 0:\n                    self._ui_queue.put((\"recovery_queue\", None))\n                    self._ui_queue.put((\"recovery_log\", f\"[Quick Recovery] {found} items found\"))\n                if found &gt;= 1500:\n                    self._ui_queue.put((\"recovery_log\", \"[Quick Recovery] Limit reached (1500 items)\"))\n                    return\n        self._emit_recovery_scan_stats({\n            \"tab\": \"quick\", \"pct\": 100, \"files_found\": found, \"folders_scanned\": folders,\n            \"message\": f\"Complete \u2014 {found:,} files\",\n        })\n        self._ui_queue.put((\"recovery_queue\", None))\n        self._ui_queue.put((\"recovery_refresh\", None))\n        self._ui_queue.put((\"recovery_log\", f\"[Quick Recovery] Completed, {found} items found.\"))\n\n    def _on_quick_recovery_select(self, event=None):\n        sel = self.quick_recovery_tree.selection()\n        if not sel:\n            return\n        values = self.quick_recovery_tree.item(sel[0], \"values\")\n        if not values or len(values) &lt; 6:\n            return\n        path = values[4]\n        preview = [f\"Path: {path}\", f\"Type: {values[1]}\", f\"Size: {values[2]}\", f\"Status: {values[3]}\", f\"Integrity: {values[5]}\", \"\"]\n        try:\n            if os.path.exists(path) and os.path.isfile(path):\n                with open(path, \"rb\") as fh:\n                    data = fh.read(512)\n                preview.append(data[:512].hex(\" \"))\n        except Exception as exc:\n            preview.append(f\"Preview failed: {exc}\")\n        self.quick_recovery_preview.config(state=\"normal\")\n        self.quick_recovery_preview.delete(\"1.0\", \"end\")\n        self.quick_recovery_preview.insert(\"end\", \"\\n\".join(preview))\n        self.quick_recovery_preview.config(state=\"disabled\")\n\n    def _build_recovery_deep_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        self._build_recovery_progress_strip(body, \"deep\", \"Deep / Raw Scan \u2014 Live Progress\")\n        card = tk.LabelFrame(body, text=\"\ud83d\udd0e Deep / Raw Signature Scan\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        card.pack(fill=\"x\", padx=14, pady=10)\n\n        self.deep_recovery_source_var = tk.StringVar(value=DEFAULT_RAW_DISK)\n        self.deep_recovery_types_var = tk.StringVar(value=\"jpg,png,pdf,zip,exe\")\n        self.deep_recovery_scan_mb_var = tk.StringVar(value=\"0\")\n        self.deep_recovery_start_var = tk.StringVar(value=\"0\")\n\n        row = tk.Frame(card, bg=C[\"card\"])\n        row.pack(fill=\"x\", padx=10, pady=10)\n        tk.Label(row, text=\"Source:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=0, column=0, sticky=\"w\")\n        self.deep_recovery_source_combo = ttk.Combobox(row, textvariable=self.deep_recovery_source_var, values=self._get_recovery_disk_values(), width=34, state=\"readonly\")\n        self.deep_recovery_source_combo.grid(row=0, column=1, padx=4)\n        tk.Label(row, text=\"Types:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=1, column=0, sticky=\"w\", pady=(8,0))\n        tk.Entry(row, textvariable=self.deep_recovery_types_var, width=34, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).grid(row=1, column=1, padx=4, pady=(8,0))\n        tk.Label(row, text=\"Scan MB:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=0, column=2, padx=(18,4), sticky=\"w\")\n        tk.Entry(row, textvariable=self.deep_recovery_scan_mb_var, width=8, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).grid(row=0, column=3, padx=4)\n        tk.Label(row, text=\"Start Sector:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=1, column=2, padx=(18,4), sticky=\"w\", pady=(8,0))\n        tk.Entry(row, textvariable=self.deep_recovery_start_var, width=10, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).grid(row=1, column=3, padx=4, pady=(8,0))\n\n        action_row = tk.Frame(card, bg=C[\"card\"])\n        action_row.pack(fill=\"x\", padx=10, pady=(0, 8))\n        tk.Button(action_row, text=\"\u26a1 Scan Raw Source\", font=FONTS[\"small\"], bg=C[\"btn_warn\"], fg=C[\"text\"], bd=0, padx=14, pady=8, cursor=\"hand2\", command=self._start_deep_recovery).pack(side=\"left\")\n        tk.Button(action_row, text=\"\ud83e\uddf9 Clear\", font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text\"], bd=0, padx=14, pady=8, cursor=\"hand2\", command=lambda: (self.recovery_results.clear(), self._refresh_recovery_tree(self.deep_recovery_tree, category=\"Deep Recovery\"))).pack(side=\"left\", padx=8)\n\n        self.deep_recovery_status = tk.Label(card, text=\"Raw signature scan ready.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"])\n        self.deep_recovery_status.pack(fill=\"x\", padx=10, pady=(0, 6))\n\n        results_outer = tk.LabelFrame(body, text=\"\ud83d\udce6 Deep Recovery Results\", font=FONTS[\"subhead\"], fg=C[\"accent2\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        results_outer.pack(fill=\"both\", expand=True, padx=14, pady=(0, 14))\n        cols = (\"Signature\", \"Type\", \"Sector\", \"Confidence\", \"Source\", \"Path\")\n        self.deep_recovery_tree = ttk.Treeview(results_outer, columns=cols, show=\"headings\", height=12, style=\"Custom.Treeview\")\n        for col, width in zip(cols, (180, 80, 120, 90, 220, 200)):\n            self.deep_recovery_tree.heading(col, text=col)\n            self.deep_recovery_tree.column(col, width=width, anchor=\"w\")\n        self.deep_recovery_tree.tag_configure(\"recovered\", foreground=C[\"success\"])\n        self.deep_recovery_tree.tag_configure(\"partial\", foreground=C[\"warning\"])\n        self.deep_recovery_tree.tag_configure(\"failed\", foreground=C[\"error\"])\n        self.deep_recovery_tree.pack(fill=\"both\", expand=True, padx=8, pady=8)\n\n        self.deep_recovery_preview = scrolledtext.ScrolledText(body, height=6, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], wrap=\"word\", bd=0, relief=\"flat\")\n        self.deep_recovery_preview.pack(fill=\"x\", padx=14, pady=(0, 10))\n        self.deep_recovery_preview.config(state=\"disabled\")\n\n        return body\n\n    def _start_deep_recovery(self):\n        source = self._resolve_disk_path(self.deep_recovery_source_var.get().strip() or DEFAULT_RAW_DISK)\n        if not source:\n            messagebox.showwarning(\"Source Missing\", \"Raw source disk/image select karein.\")\n            return\n        file_types = [e.strip().lstrip(\".\").upper() for e in self.deep_recovery_types_var.get().split(\",\") if e.strip()]\n        max_mb = self.deep_recovery_scan_mb_var.get().strip()\n        start_sector = self.deep_recovery_start_var.get().strip()\n        try:\n            max_bytes = int(max_mb) * 1024 * 1024 if max_mb and int(max_mb) &gt; 0 else None\n        except Exception:\n            max_bytes = None\n        try:\n            start_offset = int(start_sector) * SECTOR_SIZE if start_sector and int(start_sector) &gt; 0 else 0\n        except Exception:\n            start_offset = 0\n        self.recovery_results.clear()\n        self._refresh_recovery_tree(self.deep_recovery_tree, category=\"Deep Recovery\")\n        self._reset_recovery_progress(\"deep\", \"Deep scan queue \u092e\u0947\u0902 \u0939\u0948...\")\n        self.recovery_manager.submit_task(\"Deep Recovery\", self._task_deep_recovery, source, file_types, max_bytes, start_offset)\n        self.deep_recovery_status.config(text=\"Queued raw recovery scan...\", fg=C[\"accent4\"])\n\n    def _task_deep_recovery(self, task, source, file_types, max_bytes, start_offset):\n        self._ui_queue.put((\"recovery_log\", f\"[Deep Recovery] Scanning {source} from offset {start_offset} for {', '.join(file_types)}\"))\n        if _is_raw_device_path(source) and not is_admin():\n            raise PermissionError(\"Administrator rights required for raw disk scan.\")\n        def stats_cb(st):\n            st[\"tab\"] = \"deep\"\n            self._emit_recovery_scan_stats(st)\n        prog = make_progress_callback(lambda s: self._emit_recovery_scan_stats({**s, \"tab\": \"deep\"}), \"deep\")\n        def find_callback(msg):\n            self._ui_queue.put((\"recovery_log\", f\"[Deep Recovery] {msg}\"))\n            prog(msg)\n        hits = scan_disk_for_files(\n            source, max_bytes=max_bytes, start_offset=start_offset, file_types=file_types,\n            progress_callback=find_callback, stats_callback=stats_cb,\n        )\n        live_count = 0\n        for hit in hits:\n            score = 80 if hit.get(\"confidence\") == \"high\" else 55\n            try:\n                sample = self._forensic_read_at(source, int(hit.get(\"offset\", 0)), 4096)\n                conf = validate_recovered_file(sample, hit.get(\"file_type\", \"\"))\n                score = conf.score\n            except Exception:\n                pass\n            item = RecoveryResultItem(\n                item_id=f\"deep-{uuid.uuid4()}\",\n                source=source,\n                category=\"Deep Recovery\",\n                file_name=f\"{hit.get('file_type','UNKNOWN')} @ {hit.get('offset',0)}\",\n                file_type=hit.get(\"file_type\", \"RAW\"),\n                size_bytes=0,\n                recoverability_score=score,\n                status=\"signature\",\n                path=f\"{hit.get('disk_path', source)}:{hit.get('offset', 0)}\",\n                metadata=hit,\n            )\n            self.recovery_results.add(item)\n            live_count += 1\n            if live_count % 10 == 0:\n                self._emit_recovery_scan_stats({\n                    \"tab\": \"deep\", \"pct\": 90, \"files_found\": live_count,\n                    \"message\": f\"Indexing results... {live_count}/{len(hits)}\",\n                })\n        self._emit_recovery_scan_stats({\n            \"tab\": \"deep\", \"pct\": 100, \"files_found\": len(hits),\n            \"message\": f\"Complete \u2014 {len(hits)} signatures\",\n        })\n        self._ui_queue.put((\"recovery_queue\", None))\n        self._ui_queue.put((\"recovery_refresh\", None))\n        self._ui_queue.put((\"recovery_log\", f\"[Deep Recovery] Completed, {len(hits)} signatures discovered.\"))\n\n    def _build_recovery_photorec_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        self._build_recovery_progress_strip(body, \"photorec\", \"PhotoRec Pro \u2014 Live Carving Progress\")\n        card = tk.LabelFrame(body, text=\"\ud83e\udde9 PhotoRec Pro (Multi-Pass Carving)\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        card.pack(fill=\"x\", padx=14, pady=10)\n\n        self.photorec_source_var = tk.StringVar(value=\"\")\n        self.photorec_output_var = tk.StringVar(value=os.path.join(os.path.expanduser(\"~\"), \"Desktop\", \"Godawari_PhotoRec\"))\n        row = tk.Frame(card, bg=C[\"card\"])\n        row.pack(fill=\"x\", padx=10, pady=10)\n        tk.Label(row, text=\"Source Disk:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=0, column=0, sticky=\"w\")\n        self.photorec_source_combo = ttk.Combobox(row, textvariable=self.photorec_source_var, width=40, state=\"readonly\")\n        self.photorec_source_combo.grid(row=0, column=1, padx=6)\n        tk.Label(row, text=\"Output:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=1, column=0, sticky=\"w\", pady=(8, 0))\n        tk.Entry(row, textvariable=self.photorec_output_var, width=50, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).grid(row=1, column=1, padx=6, pady=(8, 0), sticky=\"w\")\n        tk.Button(row, text=\"Browse\", font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text\"], bd=0, padx=8, pady=6, cursor=\"hand2\",\n                  command=lambda: self._browse_recovery_output(self.photorec_output_var)).grid(row=1, column=2, pady=(8, 0))\n\n        info = tk.Label(card,\n            text=\"PhotoRec \u091c\u0948\u0938\u093e workflow:\\n\"\n                 \"\u2460 Auto block size  \u2461 Pass 1 aligned carving  \u2462 Pass 2 unaligned  \u2463 Validation\\n\"\n                 \"Har recovered file live list \u092e\u0947\u0902 \u0926\u093f\u0916\u0947\u0917\u0940 \u2014 progress bar real-time update \u0939\u094b\u0917\u093e\u0964\",\n            font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\")\n        info.pack(fill=\"x\", padx=12, pady=(0, 8))\n\n        action = tk.Frame(card, bg=C[\"card\"])\n        action.pack(fill=\"x\", padx=10, pady=(0, 10))\n        tk.Button(action, text=\"\u25b6 Start PhotoRec Scan\", font=(\"Segoe UI\", 10, \"bold\"), bg=C[\"btn_hw\"], fg=C[\"text\"],\n                  bd=0, padx=16, pady=10, cursor=\"hand2\", command=self._start_photorec_tab_scan).pack(side=\"left\")\n        tk.Button(action, text=\"\u23f9 Stop\", font=FONTS[\"small\"], bg=C[\"btn_danger\"], fg=C[\"text\"], bd=0, padx=12, pady=8, cursor=\"hand2\",\n                  command=self._stop_file_recovery).pack(side=\"left\", padx=8)\n\n        self.photorec_status_label = tk.Label(card, text=\"PhotoRec Pro ready.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"])\n        self.photorec_status_label.pack(fill=\"x\", padx=10, pady=(0, 8))\n\n        results = tk.LabelFrame(body, text=\"\ud83d\udce6 Live Recovered Files (PhotoRec)\", font=FONTS[\"subhead\"], fg=C[\"accent2\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        results.pack(fill=\"both\", expand=True, padx=14, pady=(0, 14))\n        cols = (\"File\", \"Type\", \"Size\", \"Pass\", \"Offset\", \"Path\")\n        self.photorec_tree = ttk.Treeview(results, columns=cols, show=\"headings\", height=14, style=\"Custom.Treeview\")\n        for col, w in zip(cols, (220, 60, 80, 50, 120, 280)):\n            self.photorec_tree.heading(col, text=col)\n            self.photorec_tree.column(col, width=w, anchor=\"w\")\n        self.photorec_tree.pack(fill=\"both\", expand=True, padx=8, pady=8)\n        return body\n\n    def _start_photorec_tab_scan(self):\n        label = self.photorec_source_var.get().strip()\n        source = self._resolve_disk_path(getattr(self, \"_recovery_disk_map\", {}).get(label, label))\n        if not source:\n            messagebox.showwarning(\"Source\", \"Disk/image select karein.\")\n            return\n        if not self._ensure_admin_for_raw_recovery(source):\n            return\n        output_dir = self.photorec_output_var.get().strip() or filedialog.askdirectory(title=\"PhotoRec output\")\n        if not output_dir:\n            return\n        try:\n            output_dir = get_recovery_safety(getattr(self, \"app_config\", None)).validate_output_dir(output_dir, source)\n        except Exception as exc:\n            messagebox.showerror(\"Safety\", str(exc))\n            return\n        if not messagebox.askyesno(\"PhotoRec Pro\", f\"Source: {source}\\nOutput: {output_dir}\\n\\nMulti-pass carving start?\"):\n            return\n        self.photorec_tree.delete(*self.photorec_tree.get_children())\n        self._reset_recovery_progress(\"photorec\", \"PhotoRec Pass 1 \u0936\u0941\u0930\u0942...\")\n        self._set_recovery_scan_mode(\"Mode: PhotoRec Pro Multi-Pass\", C[\"warning\"])\n        self.recovery_manager.submit_task(\"PhotoRec Pro\", self._task_photorec_tab_scan, source, output_dir)\n\n    def _task_photorec_tab_scan(self, task, source, output_dir):\n        files_live = [0]\n\n        def on_progress(msg):\n            prog = make_progress_callback(lambda s: self._emit_recovery_scan_stats({**s, \"tab\": \"photorec\"}), \"photorec\")\n            prog(msg)\n            self._ui_queue.put((\"recovery_log\", f\"[PhotoRec] {msg}\"))\n            m = re.search(r\"Pass\\s+\\d+:\\s+recovered\\s+(.+)\", str(msg), re.I)\n            if m:\n                fn = m.group(1).strip()\n                files_live[0] += 1\n                self._emit_recovery_scan_stats({\n                    \"tab\": \"photorec\", \"files_found\": files_live[0], \"files_recovered\": files_live[0],\n                    \"message\": f\"Recovered: {fn}\",\n                })\n                row = (fn, os.path.splitext(fn)[1].lstrip(\".\").upper() or \"?\", \"\u2014\", \"\u2014\", \"\u2014\", fn)\n                self._ui_queue.put((\"photorec_tree_row\", row))\n\n        result = multi_pass_recovery(source, output_dir, progress_callback=on_progress)\n        for item in result.get(\"files\", []):\n            row = (\n                os.path.basename(item[\"path\"]),\n                item.get(\"file_type\", \"?\"),\n                self._fmt_size(item.get(\"bytes\", 0)),\n                str(item.get(\"pass\", \"?\")),\n                f\"0x{item.get('offset', 0):X}\",\n                item[\"path\"],\n            )\n            self._ui_queue.put((\"photorec_tree_row\", row))\n        self._emit_recovery_scan_stats({\n            \"tab\": \"photorec\", \"pct\": 100,\n            \"files_found\": len(result.get(\"files\", [])),\n            \"files_recovered\": len(result.get(\"files\", [])),\n            \"message\": f\"Done \u2014 {result.get('recup_dir', output_dir)}\",\n        })\n        self._ui_queue.put((\"recovery_log\", f\"[PhotoRec] Complete: {len(result.get('files', []))} files\"))\n\n    def _build_recovery_mft_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        self._build_recovery_progress_strip(body, \"mft\", \"MFT Deleted Recovery \u2014 Live Progress\")\n        card = tk.LabelFrame(body, text=\"\ud83d\uddc2\ufe0f NTFS MFT Deleted File Recovery\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        card.pack(fill=\"x\", padx=14, pady=10)\n\n        self.mft_source_var = tk.StringVar(value=\"\")\n        self.mft_output_var = tk.StringVar(value=os.path.join(os.path.expanduser(\"~\"), \"Desktop\", \"Godawari_MFT_Recovery\"))\n        self.mft_max_records_var = tk.StringVar(value=\"8192\")\n        row = tk.Frame(card, bg=C[\"card\"])\n        row.pack(fill=\"x\", padx=10, pady=10)\n        tk.Label(row, text=\"NTFS Volume:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=0, column=0, sticky=\"w\")\n        self.mft_source_combo = ttk.Combobox(row, textvariable=self.mft_source_var, width=40, state=\"readonly\")\n        self.mft_source_combo.grid(row=0, column=1, padx=6)\n        tk.Label(row, text=\"Output:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=1, column=0, sticky=\"w\", pady=(8, 0))\n        tk.Entry(row, textvariable=self.mft_output_var, width=50, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).grid(row=1, column=1, padx=6, pady=(8, 0), sticky=\"w\")\n        tk.Button(row, text=\"Browse\", font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text\"], bd=0, padx=8, pady=6, cursor=\"hand2\",\n                  command=lambda: self._browse_recovery_output(self.mft_output_var)).grid(row=1, column=2, pady=(8, 0))\n        tk.Label(row, text=\"Max MFT Records:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=2, column=0, sticky=\"w\", pady=(8, 0))\n        tk.Entry(row, textvariable=self.mft_max_records_var, width=10, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).grid(row=2, column=1, padx=6, pady=(8, 0), sticky=\"w\")\n\n        tk.Label(card,\n                 text=\"\u092f\u0939 tab $MFT \u0938\u0947 deleted files \u0915\u0940 actual bytes recover \u0915\u0930\u0924\u0940 \u0939\u0948 (DATA runs \u2192 clusters).\\n\"\n                      \"Sirf NTFS volume \u092a\u0930 \u0915\u093e\u092e \u0915\u0930\u0947\u0917\u093e \u2014 partition/image source select \u0915\u0930\u0947\u0902\u0964\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\").pack(fill=\"x\", padx=12, pady=(0, 8))\n\n        action = tk.Frame(card, bg=C[\"card\"])\n        action.pack(fill=\"x\", padx=10, pady=(0, 10))\n        tk.Button(action, text=\"\u25b6 Recover Deleted (MFT)\", font=(\"Segoe UI\", 10, \"bold\"), bg=C[\"btn_info\"], fg=C[\"text\"],\n                  bd=0, padx=16, pady=10, cursor=\"hand2\", command=self._start_mft_deleted_recovery).pack(side=\"left\")\n\n        self.mft_status_label = tk.Label(card, text=\"MFT recovery ready.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"])\n        self.mft_status_label.pack(fill=\"x\", padx=10, pady=(0, 8))\n\n        results = tk.LabelFrame(body, text=\"\ud83d\udcc1 Recovered Deleted Files\", font=FONTS[\"subhead\"], fg=C[\"accent2\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        results.pack(fill=\"both\", expand=True, padx=14, pady=(0, 14))\n        cols = (\"File\", \"Size\", \"Status\", \"Fragmented\", \"Path\")\n        self.mft_tree = ttk.Treeview(results, columns=cols, show=\"headings\", height=14, style=\"Custom.Treeview\")\n        for col, w in zip(cols, (220, 90, 100, 80, 340)):\n            self.mft_tree.heading(col, text=col)\n            self.mft_tree.column(col, width=w, anchor=\"w\")\n        self.mft_tree.pack(fill=\"both\", expand=True, padx=8, pady=8)\n        return body\n\n    def _start_mft_deleted_recovery(self):\n        label = self.mft_source_var.get().strip()\n        source = self._resolve_disk_path(getattr(self, \"_recovery_disk_map\", {}).get(label, label))\n        if not source:\n            messagebox.showwarning(\"Source\", \"NTFS volume select karein (C: \u092f\u093e partition image).\")\n            return\n        if not self._ensure_admin_for_raw_recovery(source):\n            return\n        output_dir = self.mft_output_var.get().strip()\n        if not output_dir:\n            messagebox.showwarning(\"Output\", \"Output folder set karein.\")\n            return\n        try:\n            output_dir = get_recovery_safety(getattr(self, \"app_config\", None)).validate_output_dir(output_dir, source)\n        except Exception as exc:\n            messagebox.showerror(\"Safety\", str(exc))\n            return\n        try:\n            max_records = max(512, int(self.mft_max_records_var.get().strip()))\n        except Exception:\n            max_records = 8192\n        if not messagebox.askyesno(\"MFT Recovery\", f\"Deleted files recover karein?\\n\\nSource: {source}\\nOutput: {output_dir}\\nRecords: {max_records}\"):\n            return\n        self.mft_tree.delete(*self.mft_tree.get_children())\n        self._reset_recovery_progress(\"mft\", \"MFT scan \u0936\u0941\u0930\u0942...\")\n        self.recovery_manager.submit_task(\"MFT Deleted Recovery\", self._task_mft_deleted_recovery, source, output_dir, max_records)\n\n    def _task_mft_deleted_recovery(self, task, source, output_dir, max_records):\n        partition_offset = 0\n        if hasattr(self, \"_parse_mbr_partitions\"):\n            try:\n                sector = self._forensic_read_at(source, 0, 512)\n                parts = self._parse_mbr_partitions(sector)\n                if parts:\n                    partition_offset = int(parts[0].get(\"start_lba\", 0)) * SECTOR_SIZE\n            except Exception:\n                pass\n\n        def read_fn(offset, length):\n            task.wait_if_paused()\n            if task.is_cancelled():\n                raise InterruptedError(\"MFT recovery cancelled\")\n            return self._forensic_read_at(source, offset, length)\n\n        boot = read_fn(partition_offset, 512)\n\n        def progress_cb(st):\n            st[\"tab\"] = \"mft\"\n            self._emit_recovery_scan_stats(st)\n\n        result = recover_deleted_mft_files(\n            read_fn, partition_offset, boot, output_dir,\n            max_records=max_records, max_recover=500,\n            progress_callback=progress_cb,\n            cancel_check=task.is_cancelled,\n        )\n        for item in result.get(\"results\", []):\n            if not item.ok:\n                continue\n            row = (\n                item.file_name,\n                self._fmt_size(item.size_bytes),\n                \"\u2705 Recovered\" if item.ok else \"Failed\",\n                \"Yes\" if item.fragmented else \"No\",\n                item.output_path,\n            )\n            self._ui_queue.put((\"mft_tree_row\", row))\n            rec_item = RecoveryResultItem(\n                item_id=f\"mft-{uuid.uuid4()}\",\n                source=source,\n                category=\"MFT Deleted\",\n                file_name=item.file_name,\n                file_type=os.path.splitext(item.file_name)[1].lstrip(\".\") or \"file\",\n                size_bytes=item.size_bytes,\n                recoverability_score=85 if item.ok else 20,\n                status=\"recovered\" if item.ok else \"failed\",\n                path=item.output_path,\n                metadata={\"deleted\": item.deleted, \"fragmented\": item.fragmented},\n            )\n            self.recovery_results.add(rec_item)\n        self._emit_recovery_scan_stats({\n            \"tab\": \"mft\", \"pct\": 100,\n            \"files_found\": result.get(\"deleted_candidates\", 0),\n            \"files_recovered\": result.get(\"recovered_count\", 0),\n            \"message\": f\"MFT done \u2014 {result.get('recovered_count', 0)} files saved\",\n        })\n        self._ui_queue.put((\"recovery_queue\", None))\n        self._ui_queue.put((\"recovery_refresh\", None))\n        self._ui_queue.put((\"recovery_log\",\n            f\"[MFT] Deleted candidates: {result.get('deleted_candidates', 0)}, \"\n            f\"Recovered: {result.get('recovered_count', 0)} \u2192 {output_dir}\"))\n\n    def _build_recovery_raw_carve_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        card = tk.LabelFrame(body, text=\"\ud83e\udde9 RAW Carving\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        card.pack(fill=\"x\", padx=14, pady=10)\n\n        self.raw_carve_source_var = tk.StringVar(value=DEFAULT_RAW_DISK)\n        self.raw_carve_offset_var = tk.StringVar(value=\"0\")\n        self.raw_carve_length_var = tk.StringVar(value=\"65536\")\n\n        row = tk.Frame(card, bg=C[\"card\"])\n        row.pack(fill=\"x\", padx=10, pady=10)\n        tk.Label(row, text=\"Source:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=0, column=0, sticky=\"w\")\n        self.raw_carve_source_combo = ttk.Combobox(row, textvariable=self.raw_carve_source_var, values=self._get_recovery_disk_values(), width=36, state=\"readonly\")\n        self.raw_carve_source_combo.grid(row=0, column=1, padx=4)\n        tk.Label(row, text=\"Offset:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=1, column=0, pady=(8,0), sticky=\"w\")\n        tk.Entry(row, textvariable=self.raw_carve_offset_var, width=16, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).grid(row=1, column=1, padx=4, pady=(8,0), sticky=\"w\")\n        tk.Label(row, text=\"Length:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=1, column=2, padx=(18,4), pady=(8,0), sticky=\"w\")\n        tk.Entry(row, textvariable=self.raw_carve_length_var, width=12, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).grid(row=1, column=3, padx=4, pady=(8,0), sticky=\"w\")\n\n        action_row = tk.Frame(card, bg=C[\"card\"])\n        action_row.pack(fill=\"x\", padx=10, pady=(0, 6))\n        tk.Button(action_row, text=\"\ud83e\uddea Analyze Range\", font=FONTS[\"small\"], bg=C[\"btn_chip\"], fg=C[\"text\"], bd=0, padx=14, pady=8, cursor=\"hand2\", command=self._run_raw_carve).pack(side=\"left\")\n        tk.Button(action_row, text=\"\ud83e\uddf9 Clear\", font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text\"], bd=0, padx=14, pady=8, cursor=\"hand2\", command=lambda: self.raw_carve_output.config(state=\"normal\") or self.raw_carve_output.delete(\"1.0\",\"end\") or self.raw_carve_output.config(state=\"disabled\")).pack(side=\"left\", padx=8)\n\n        self.raw_carve_output = scrolledtext.ScrolledText(body, height=12, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], wrap=\"word\", bd=0, relief=\"flat\")\n        self.raw_carve_output.pack(fill=\"both\", expand=True, padx=14, pady=(0, 14))\n        self.raw_carve_output.config(state=\"disabled\")\n        return body\n\n    def _run_raw_carve(self):\n        source = self._resolve_disk_path(self.raw_carve_source_var.get().strip() or DEFAULT_RAW_DISK)\n        try:\n            offset = int(self.raw_carve_offset_var.get().strip())\n            length = max(4096, int(self.raw_carve_length_var.get().strip()))\n        except Exception:\n            messagebox.showwarning(\"Invalid Range\", \"Offset aur length numeric hone chahiye.\")\n            return\n        try:\n            data = self._forensic_read_at(source, offset, length)\n            if not data:\n                raise IOError(\"No data read from raw source\")\n            analysis = [f\"Source: {source}\", f\"Offset: {offset}\", f\"Length: {len(data)} bytes\", \"\"]\n            patterns = {\n                \"JPEG\": b\"\\xff\\xd8\\xff\",\n                \"PNG\": b\"\\x89PNG\\r\\n\\x1a\\n\",\n                \"PDF\": b\"%PDF\",\n                \"PE\": b\"MZ\",\n                \"ZIP\": b\"PK\",\n            }\n            for name, sig in patterns.items():\n                idx = data.find(sig)\n                if idx &gt;= 0:\n                    analysis.append(f\"Found {name} signature at offset {offset + idx}\")\n            if len(analysis) == 4:\n                analysis.append(\"No known signatures found in the selected region.\")\n            analysis.append(\"\\nPreview (first 256 bytes):\")\n            analysis.append(data[:256].hex(\" \"))\n            self.raw_carve_output.config(state=\"normal\")\n            self.raw_carve_output.delete(\"1.0\", \"end\")\n            self.raw_carve_output.insert(\"end\", \"\\n\".join(analysis))\n            self.raw_carve_output.config(state=\"disabled\")\n            self._ui_queue.put((\"recovery_log\", f\"[RAW Carving] Analyzed {length} bytes from {source}@{offset}\"))\n        except Exception as exc:\n            messagebox.showerror(\"Raw Carve Error\", str(exc))\n            self._ui_queue.put((\"recovery_log\", f\"[RAW Carving] Error: {exc}\"))\n\n    def _build_recovery_partitions_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        card = tk.LabelFrame(body, text=\"\ud83e\udded Partition Recovery\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        card.pack(fill=\"x\", padx=14, pady=10)\n        self.partition_source_var = tk.StringVar(value=DEFAULT_RAW_DISK)\n\n        top_row = tk.Frame(card, bg=C[\"card\"])\n        top_row.pack(fill=\"x\", padx=4, pady=(6,4))\n\n        # Left: Detected disks list\n        left = tk.Frame(top_row, bg=C[\"card\"])\n        left.pack(side=\"left\", fill=\"y\", padx=(6,8))\n        tk.Label(left, text=\"Detected Disks:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\")\n        cols = (\"#\", \"Name\", \"Size\")\n        self.detected_disks_tree = ttk.Treeview(left, columns=cols, show=\"headings\", height=6, style=\"Custom.Treeview\")\n        for col, w in zip(cols, (40, 320, 120)):\n            self.detected_disks_tree.heading(col, text=col)\n            self.detected_disks_tree.column(col, width=w, anchor=\"w\")\n        self.detected_disks_tree.pack(fill=\"both\", expand=False)\n        self.detected_disks_tree.bind(\"&lt;&gt;\", lambda e: None)\n        tk.Button(left, text=\"\ud83d\udd04 Refresh\", font=FONTS[\"small\"], bg=C[\"btn\"], fg=C[\"text\"], bd=0, padx=8, pady=6, cursor=\"hand2\", command=lambda: self._launch_job(\"recovery_populate_disks\", self._populate_recovery_disks)).pack(pady=6)\n\n        # Middle: actions\n        mid = tk.Frame(top_row, bg=C[\"card\"])\n        mid.pack(side=\"left\", fill=\"y\", padx=(4,8))\n        tk.Label(mid, text=\"Actions:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\")\n        tk.Button(mid, text=\"\ud83e\udde0 Scan Selected Disk\", font=FONTS[\"small\"], bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=10, pady=8, cursor=\"hand2\", command=self._start_scan_partitions).pack(fill=\"x\", pady=4)\n        tk.Button(mid, text=\"\ud83d\uddc2 Recover Selected Partition\", font=FONTS[\"small\"], bg=C[\"btn_warn\"], fg=C[\"text\"], bd=0, padx=10, pady=8, cursor=\"hand2\", command=self._start_recover_partition).pack(fill=\"x\", pady=4)\n\n        # Right: progress + partition details\n        right = tk.Frame(top_row, bg=C[\"card\"])\n        right.pack(side=\"left\", fill=\"both\", expand=True, padx=(4,6))\n        self.partition_progress_var = tk.DoubleVar(value=0.0)\n        self.partition_progress_bar = ttk.Progressbar(right, variable=self.partition_progress_var, maximum=100.0, mode=\"determinate\")\n        self.partition_progress_bar.pack(fill=\"x\", pady=(4,6))\n        self.partition_status_label = tk.Label(right, text=\"Ready\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"])\n        self.partition_status_label.pack(anchor=\"w\")\n\n        self.partition_info_text = scrolledtext.ScrolledText(right, height=12, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], wrap=\"word\", bd=0, relief=\"flat\")\n        self.partition_info_text.pack(fill=\"both\", expand=True, padx=4, pady=(6,4))\n        self.partition_info_text.config(state=\"disabled\")\n\n        # Partition results tree (below)\n        results_frame = tk.LabelFrame(body, text=\"Partitions / Results\", font=FONTS[\"subhead\"], fg=C[\"accent2\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        results_frame.pack(fill=\"both\", expand=True, padx=14, pady=(6, 12))\n        pcols = (\"Index\", \"Type\", \"Start LBA\", \"Sectors\", \"Size\")\n        self.partition_tree = ttk.Treeview(results_frame, columns=pcols, show=\"headings\", height=8, style=\"Custom.Treeview\")\n        for col, w in zip(pcols, (60, 120, 120, 120, 120)):\n            self.partition_tree.heading(col, text=col)\n            self.partition_tree.column(col, width=w, anchor=\"w\")\n        self.partition_tree.pack(fill=\"both\", expand=True, padx=8, pady=8)\n\n        # Ensure disks enumerated at build time\n        try:\n            self._launch_job(\"populate_recovery_disks\", self._populate_recovery_disks)\n        except Exception:\n            pass\n\n        return body\n\n    def _refresh_recovery_partitions(self):\n        source = self._resolve_disk_path(self.partition_source_var.get().strip() or DEFAULT_RAW_DISK)\n        try:\n            sector = self._forensic_read_at(source, 0, 512)\n            parts = self._parse_mbr_partitions(sector)\n            gpt = self._parse_gpt_entries(source)\n            lines = [f\"Source: {source}\", f\"MBR partitions: {len(parts)}\"]\n            for part in parts:\n                lines.append(f\"  #{part['index']} type={part['type']} start={part['start_lba']} sectors={part['sectors']} size={self._fmt_size(part['size'])}\")\n            if gpt:\n                lines.append(f\"GPT entries: {len(gpt.get('partitions', []))}\")\n                for part in gpt.get('partitions', []):\n                    lines.append(f\"  #{part['index']} name={part['name']} first={part['first_lba']} last={part['last_lba']} size={self._fmt_size(part['size'])}\")\n            if not parts and not gpt:\n                lines.append(\"No valid MBR/GPT partition table detected.\")\n        except Exception as exc:\n            lines = [f\"Partition parse failed: {exc}\"]\n        self.partition_info_text.config(state=\"normal\")\n        self.partition_info_text.delete(\"1.0\", \"end\")\n        self.partition_info_text.insert(\"end\", \"\\n\".join(lines))\n        self.partition_info_text.config(state=\"disabled\")\n        self._ui_queue.put((\"recovery_log\", f\"[Partition Recovery] Parsed partitions for {source}\"))\n\n    def _start_scan_partitions(self):\n        try:\n            sel = self.detected_disks_tree.selection()\n            if not sel:\n                messagebox.showwarning(\"Select Disk\", \"Koi disk select nahi hua. Pehle disk select karo.\")\n                return\n            disk_path = sel[0]\n            self.partition_source_var.set(disk_path)\n            self.partition_status_label.config(text=f\"Queued scan for {disk_path}\")\n            self.recovery_manager.submit_task(\"Scan Partitions\", self._task_scan_partitions, disk_path)\n        except Exception as e:\n            self._ui_queue.put((\"recovery_log\", f\"[Partition Recovery] Scan start failed: {e}\"))\n\n    def _task_scan_partitions(self, task, source):\n        try:\n            self._ui_queue.put((\"recovery_log\", f\"[Partition Recovery] Scanning partitions on {source}\"))\n            self._ui_queue.put((\"clone_progress\", (0, f\"Scanning {source}\", \"partition\")))\n            # Read and parse\n            sector = self._forensic_read_at(source, 0, 512)\n            parts = self._parse_mbr_partitions(sector)\n            gpt = self._parse_gpt_entries(source)\n            # Update partition tree in UI thread\n            def _update_tree():\n                try:\n                    self.partition_tree.delete(*self.partition_tree.get_children())\n                except Exception:\n                    pass\n                try:\n                    for part in parts:\n                        self.partition_tree.insert(\"\", \"end\", values=(part.get('index'), part.get('type'), part.get('start_lba'), part.get('sectors'), self._fmt_size(part.get('size'))))\n                    if gpt:\n                        for part in gpt.get('partitions', []):\n                            self.partition_tree.insert(\"\", \"end\", values=(part.get('index'), part.get('type','GPT'), part.get('first_lba'), part.get('last_lba') - part.get('first_lba') + 1, self._fmt_size(part.get('size'))))\n                except Exception:\n                    pass\n            self.after(0, _update_tree)\n            self._ui_queue.put((\"recovery_log\", f\"[Partition Recovery] Scan complete: {len(parts) + (len(gpt.get('partitions', [])) if gpt else 0)} partitions found\"))\n            self._ui_queue.put((\"clone_progress\", (100, \"Partition scan complete\", \"partition\")))\n        except Exception as exc:\n            self._ui_queue.put((\"recovery_log\", f\"[Partition Recovery] Scan failed: {exc}\"))\n            self._ui_queue.put((\"clone_progress\", (0, f\"Scan failed: {exc}\", \"partition\")))\n            raise\n\n    def _start_recover_partition(self):\n        try:\n            sel = self.partition_tree.selection()\n            if not sel:\n                messagebox.showwarning(\"Select Partition\", \"Koi partition select nahi hua. Pehle partition select karo.\")\n                return\n            vals = self.partition_tree.item(sel[0], 'values')\n            if not vals or len(vals) &lt; 4:\n                messagebox.showwarning(\"Invalid\", \"Selected partition data invalid.\")\n                return\n            start_lba = int(vals[2])\n            sectors = int(vals[3])\n            source = self.partition_source_var.get().strip() or DEFAULT_RAW_DISK\n            target = filedialog.asksaveasfilename(title=\"Save partition image as\", defaultextension=\".img\", filetypes=[(\"IMG\", \"*.img *.dd *.raw\"),(\"All\",\"*.*\")])\n            if not target:\n                return\n            if not messagebox.askyesno(\"Recover Partition\", f\"Recover partition start={start_lba} sectors={sectors} to:\\n{target}?\\nProceed?\"):\n                return\n            try:\n                get_recovery_safety(getattr(self, \"app_config\", None)).validate_write_path(target, source)\n            except Exception as exc:\n                messagebox.showerror(\"Recovery Safety\", str(exc))\n                return\n            max_bytes = sectors * SECTOR_SIZE\n            start_offset = start_lba * SECTOR_SIZE\n            self.recovery_manager.submit_task(\"Recover Partition\", self._task_recover_partition, source, start_offset, max_bytes, target)\n            self._ui_queue.put((\"recovery_log\", f\"[Partition Recovery] Queued partition recovery: {source} @ {start_lba}\"))\n        except Exception as e:\n            self._ui_queue.put((\"recovery_log\", f\"[Partition Recovery] Recover start failed: {e}\"))\n\n    def _task_recover_partition(self, task, source, start_offset, max_bytes, target_path):\n        try:\n            self._ui_queue.put((\"recovery_log\", f\"[Partition Recovery] Recovering {source}@{start_offset} -&gt; {target_path}\"))\n            def progress_cb(msg):\n                try:\n                    text = str(msg or \"\")\n                    m = re.search(r\"(\\d{1,3})%\", text)\n                    pct = int(m.group(1)) if m else 0\n                    self._ui_queue.put((\"clone_progress\", (pct, text, \"partition\")))\n                    self._ui_queue.put((\"recovery_log\", f\"[Partition Recovery] {text}\"))\n                except Exception:\n                    pass\n            copy_disk_range_to_img(source, target_path, start_offset=start_offset, max_bytes=max_bytes, progress_callback=progress_cb)\n            self._ui_queue.put((\"clone_progress\", (100, f\"Recovered: {target_path}\", \"partition\")))\n            self._ui_queue.put((\"recovery_log\", f\"[Partition Recovery] Recovery complete: {target_path}\"))\n        except Exception as e:\n            self._ui_queue.put((\"recovery_log\", f\"[Partition Recovery] Recovery failed: {e}\"))\n            self._ui_queue.put((\"clone_progress\", (0, f\"Recover failed: {e}\", \"partition\")))\n            raise\n\n    def _clone_selected_disk(self):\n        try:\n            source = self._resolve_disk_path(self.partition_source_var.get().strip() or DEFAULT_RAW_DISK)\n            path = filedialog.asksaveasfilename(\n                title=\"Save disk image as\",\n                defaultextension=\".img\",\n                filetypes=[(\"Disk image\", \"*.img *.dd *.raw\"), (\"All files\", \"*.*\")],\n                initialfile=f\"disk_clone_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.img\",\n            )\n            if not path:\n                return\n            if not messagebox.askyesno(\"Clone Disk\", f\"Clone {source} to:\\n{path}?\\n\\nProceed?\"):\n                return\n            if hasattr(self, \"clone_status_label\"):\n                self.clone_status_label.config(text=f\"\ud83d\udd04 Cloning {os.path.basename(source)} \u2192 {os.path.basename(path)}...\")\n            if hasattr(self, \"clone_progress_var\"):\n                try:\n                    self.clone_progress_var.set(0.0)\n                except Exception:\n                    pass\n            self.recovery_manager.submit_task(\"Clone Disk\", self._task_clone_disk, source, path)\n            self._ui_queue.put((\"recovery_log\", f\"[Clone Disk] Queued clone: {source} -&gt; {path}\"))\n        except Exception as e:\n            self._ui_queue.put((\"recovery_log\", f\"[Clone Disk] Error queuing clone: {e}\"))\n\n    def _task_clone_disk(self, task, source, img_path):\n        try:\n            self._ui_queue.put((\"recovery_log\", f\"[Clone Disk] Starting clone {source} -&gt; {img_path}\"))\n            def progress_cb(msg):\n                try:\n                    text = str(msg or \"\")\n                    # Send log line\n                    self._ui_queue.put((\"recovery_log\", f\"[Clone Disk] {text}\"))\n                    # Extract percentage if present\n                    m = re.search(r\"(\\d{1,3})%\", text)\n                    if m:\n                        try:\n                            pct = int(m.group(1))\n                        except Exception:\n                            pct = 0\n                        self._ui_queue.put((\"clone_progress\", (pct, text, \"clone\")))\n                    else:\n                        # If no percent, send text-only update\n                        self._ui_queue.put((\"clone_progress\", (0, text, \"clone\")))\n                except Exception:\n                    pass\n            # Use existing create_disk_image helper\n            # Reset UI\n            self._ui_queue.put((\"clone_progress\", (0, \"Starting clone...\", \"clone\")))\n            create_disk_image(source, img_path, max_bytes=None, progress_callback=progress_cb)\n            self._ui_queue.put((\"clone_progress\", (100, f\"Completed: {img_path}\", \"clone\")))\n            self._ui_queue.put((\"recovery_log\", f\"[Clone Disk] Completed: {img_path}\"))\n            self._ui_queue.put((\"recovery_queue\", None))\n        except Exception as e:\n            self._ui_queue.put((\"recovery_log\", f\"[Clone Disk] Failed: {e}\"))\n            try:\n                self._ui_queue.put((\"clone_progress\", (0, f\"Failed: {e}\", \"clone\")))\n            except Exception:\n                pass\n            raise\n\n    def _build_recovery_nand_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        card = tk.LabelFrame(body, text=\"\u26a1 NAND / Flash Analysis\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        card.pack(fill=\"x\", padx=14, pady=10)\n\n        self.nand_source_var = tk.StringVar(value=DEFAULT_RAW_DISK)\n        self.nand_sample_var = tk.StringVar(value=\"16\")\n\n        row = tk.Frame(card, bg=C[\"card\"])\n        row.pack(fill=\"x\", padx=10, pady=10)\n        tk.Label(row, text=\"Source:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=0, column=0, sticky=\"w\")\n        self.nand_source_combo = ttk.Combobox(row, textvariable=self.nand_source_var, values=self._get_recovery_disk_values(), width=40, state=\"readonly\")\n        self.nand_source_combo.grid(row=0, column=1, padx=4)\n        tk.Label(row, text=\"Sample MB:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=0, column=2, padx=(14,4), sticky=\"w\")\n        tk.Entry(row, textvariable=self.nand_sample_var, width=6, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).grid(row=0, column=3, padx=4)\n        tk.Button(row, text=\"Analyze NAND\", font=FONTS[\"small\"], bg=C[\"btn_warn\"], fg=C[\"text\"], bd=0, padx=14, pady=8, cursor=\"hand2\", command=self._start_nand_analysis).grid(row=0, column=4, padx=(14,0))\n\n        self.nand_analysis_output = scrolledtext.ScrolledText(body, height=14, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], wrap=\"word\", bd=0, relief=\"flat\")\n        self.nand_analysis_output.pack(fill=\"both\", expand=True, padx=14, pady=(0, 14))\n        self.nand_analysis_output.config(state=\"disabled\")\n        return body\n\n    def _start_nand_analysis(self):\n        source = self._resolve_disk_path(self.nand_source_var.get().strip() or DEFAULT_RAW_DISK)\n        try:\n            sample_mb = max(1, int(self.nand_sample_var.get().strip()))\n        except Exception:\n            sample_mb = 16\n        self.recovery_manager.submit_task(\"NAND Analysis\", self._task_nand_analysis, source, sample_mb)\n        self._ui_queue.put((\"recovery_log\", f\"[NAND Analysis] Queued analysis for {source}\"))\n\n    def _task_nand_analysis(self, task, source, sample_mb):\n        self._ui_queue.put((\"recovery_log\", f\"[NAND Analysis] Sampling {sample_mb} MB from {source}\"))\n        try:\n            max_bytes = sample_mb * 1024 * 1024\n            sample_len = min(max_bytes, 4 * 1024 * 1024)\n            data = self._forensic_read_at(source, 0, sample_len)\n            if is_forensic_engine_available():\n                max_chunks = max(1, sample_mb // 4)\n                entropy_chunks = scan_disk_entropy(source, chunk_size=4 * 1024 * 1024, max_chunks=max_chunks)\n                erase_state = detect_nand_erase_state(data or b\"\")\n                headers = validate_media_headers(data or b\"\")\n                avg_entropy = (\n                    sum(e for _, e in entropy_chunks) / len(entropy_chunks) if entropy_chunks else 0.0\n                )\n                output = [\n                    f\"Source: {source}\",\n                    f\"Sample bytes: {len(data or b'')}\",\n                    f\"Avg entropy (chunks): {avg_entropy:.3f}\",\n                    f\"Entropy chunks: {len(entropy_chunks)}\",\n                    f\"Erase state: {erase_state}\",\n                    f\"Header validation: {headers}\",\n                ]\n            else:\n                entropy = self._shannon_entropy(data or b\"\")\n                erase_state = detect_nand_erase_state(data or b\"\")\n                output = [\n                    f\"Source: {source}\",\n                    f\"Forensic engine unavailable. Fallback entropy: {entropy:.2f}\",\n                    f\"Erase state: {erase_state}\",\n                ]\n            self.after(0, lambda out=\"\\n\".join(output): self._display_nand_output(out))\n            self._ui_queue.put((\"recovery_log\", f\"[NAND Analysis] Completed for {source}\"))\n        except Exception as exc:\n            self._ui_queue.put((\"recovery_log\", f\"[NAND Analysis] Error: {exc}\"))\n            raise\n\n    def _display_nand_output(self, text):\n        if not hasattr(self, \"nand_analysis_output\"):\n            return\n        self.nand_analysis_output.config(state=\"normal\")\n        self.nand_analysis_output.delete(\"1.0\", \"end\")\n        self.nand_analysis_output.insert(\"end\", text)\n        self.nand_analysis_output.config(state=\"disabled\")\n\n    def _build_recovery_queue_tab(self, parent):\n        body = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(body, \"\ud83d\udccc Recovery Queue\", \"Queued forensic and recovery tasks with cancel/pause control.\")\n        control_row = tk.Frame(body, bg=C[\"bg\"])\n        control_row.pack(fill=\"x\", padx=16, pady=(8, 2))\n        tk.Button(control_row, text=\"\u26d4 Cancel Selected\", font=FONTS[\"small\"], bg=C[\"btn_danger\"], fg=C[\"text\"], bd=0, padx=12, pady=6, cursor=\"hand2\", command=self._recovery_cancel_selected).pack(side=\"left\", padx=4)\n        tk.Button(control_row, text=\"\u23f8 Pause Selected\", font=FONTS[\"small\"], bg=C[\"btn_warn\"], fg=C[\"text\"], bd=0, padx=12, pady=6, cursor=\"hand2\", command=self._recovery_pause_selected).pack(side=\"left\", padx=4)\n        tk.Button(control_row, text=\"\u25b6 Resume Selected\", font=FONTS[\"small\"], bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=12, pady=6, cursor=\"hand2\", command=self._recovery_resume_selected).pack(side=\"left\", padx=4)\n\n        tree_frame = tk.Frame(body, bg=C[\"card\"])\n        tree_frame.pack(fill=\"both\", expand=True, padx=16, pady=10)\n        cols = (\"Task\", \"Status\", \"Progress\", \"Message\")\n        self.recovery_queue_tree = ttk.Treeview(tree_frame, columns=cols, show=\"headings\", style=\"Custom.Treeview\")\n        for col, width in zip(cols, (260, 120, 100, 420)):\n            self.recovery_queue_tree.heading(col, text=col)\n            self.recovery_queue_tree.column(col, width=width, anchor=\"w\")\n        self.recovery_queue_tree.pack(fill=\"both\", expand=True, side=\"left\")\n        yscroll = ttk.Scrollbar(tree_frame, orient=\"vertical\", command=self.recovery_queue_tree.yview)\n        yscroll.pack(side=\"right\", fill=\"y\")\n        self.recovery_queue_tree.configure(yscrollcommand=yscroll.set)\n        return body\n\n    def _recovery_cancel_selected(self):\n        sel = self.recovery_queue_tree.selection()\n        if not sel:\n            messagebox.showinfo(\"Select Task\", \"Ek task select karo.\")\n            return\n        for iid in sel:\n            self.recovery_manager.cancel_task(iid)\n        self._refresh_recovery_queue_tree()\n\n    def _recovery_pause_selected(self):\n        sel = self.recovery_queue_tree.selection()\n        if not sel:\n            messagebox.showinfo(\"Select Task\", \"Ek task select karo.\")\n            return\n        for iid in sel:\n            self.recovery_manager.pause_task(iid)\n        self._refresh_recovery_queue_tree()\n\n    def _recovery_resume_selected(self):\n        sel = self.recovery_queue_tree.selection()\n        if not sel:\n            messagebox.showinfo(\"Select Task\", \"Ek task select karo.\")\n            return\n        for iid in sel:\n            self.recovery_manager.resume_task(iid)\n        self._refresh_recovery_queue_tree()\n\n    def _build_recovery_logs_tab(self, parent):\n        body = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(body, \"\ud83d\udcda Recovery Logs\", \"Centralized log stream for recovery operations.\")\n        self.recovery_log_text = scrolledtext.ScrolledText(body, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], wrap=\"word\", bd=0, relief=\"flat\")\n        self.recovery_log_text.pack(fill=\"both\", expand=True, padx=16, pady=(10, 10))\n        self.recovery_log_text.config(state=\"disabled\")\n        btn_row = tk.Frame(body, bg=C[\"bg\"])\n        btn_row.pack(fill=\"x\", padx=16, pady=(0, 10))\n        tk.Button(btn_row, text=\"\ud83d\uddd1 Clear Log\", font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text\"], bd=0, padx=12, pady=6, cursor=\"hand2\", command=lambda: (self.recovery_log_text.config(state=\"normal\"), self.recovery_log_text.delete(\"1.0\",\"end\"), self.recovery_log_text.config(state=\"disabled\"))).pack(side=\"left\", padx=4)\n        tk.Button(btn_row, text=\"\ud83d\udcbe Save Log\", font=FONTS[\"small\"], bg=C[\"accent2\"], fg=\"#000\", bd=0, padx=12, pady=6, cursor=\"hand2\", command=self._save_recovery_log).pack(side=\"left\", padx=4)\n        return body\n\n    def _save_recovery_log(self):\n        try:\n            data = self.recovery_log_text.get(\"1.0\", \"end\").strip()\n            if not data:\n                messagebox.showinfo(\"No Log\", \"Recovery log empty hai.\")\n                return\n            path = os.path.join(os.path.expanduser(\"~\"), \"Desktop\", f\"Godawari_Recovery_Log_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.txt\")\n            with open(path, \"w\", encoding=\"utf-8\") as f:\n                f.write(data)\n            messagebox.showinfo(\"Saved\", f\"Log saved to Desktop:\\n{path}\")\n        except Exception as exc:\n            messagebox.showerror(\"Save Failed\", str(exc))\n\n    def _build_recovery_history_tab(self, parent):\n        body = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(body, \"\ud83d\uddc4\ufe0f Recovery History\", \"Session history and recovered object timeline.\")\n        btn_row = tk.Frame(body, bg=C[\"bg\"])\n        btn_row.pack(fill=\"x\", padx=16, pady=(8, 4))\n        tk.Button(btn_row, text=\"\ud83d\udd04 Refresh\", font=FONTS[\"small\"], bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=12, pady=6, cursor=\"hand2\", command=self._refresh_recovery_history).pack(side=\"left\")\n        self.recovery_history_tree = ttk.Treeview(body, columns=(\"Session\", \"Date\", \"Files\", \"Location\"), show=\"headings\", style=\"Custom.Treeview\")\n        for col, width in zip((\"Session\", \"Date\", \"Files\", \"Location\"), (220, 140, 90, 420)):\n            self.recovery_history_tree.heading(col, text=col)\n            self.recovery_history_tree.column(col, width=width, anchor=\"w\")\n        self.recovery_history_tree.pack(fill=\"both\", expand=True, padx=16, pady=(8, 12))\n        self._refresh_recovery_history()\n        return body\n\n    def _refresh_recovery_history(self):\n        tree = getattr(self, \"recovery_history_tree\", None)\n        if tree is None:\n            return\n        try:\n            for iid in tree.get_children():\n                tree.delete(iid)\n            base = getattr(self, \"recovery_sessions_dir\", os.path.join(os.path.expanduser(\"~\"), \"Desktop\"))\n            if not os.path.exists(base):\n                os.makedirs(base, exist_ok=True)\n            entries = []\n            for root, _, files in os.walk(base):\n                for fn in files:\n                    if fn.lower().endswith(\".json\") or fn.lower().endswith(\".log\"):\n                        path = os.path.join(root, fn)\n                        entries.append((fn, datetime.datetime.fromtimestamp(os.path.getmtime(path)).strftime(\"%Y-%m-%d %H:%M:%S\"), \"1\", root))\n            for row in sorted(entries, key=lambda x: x[1], reverse=True)[:80]:\n                tree.insert(\"\", \"end\", values=row)\n        except Exception:\n            pass\n\n    def _shannon_entropy(self, data: bytes) -&gt; float:\n        if not data:\n            return 0.0\n        freq = {}\n        for byte in data:\n            freq[byte] = freq.get(byte, 0) + 1\n        entropy = 0.0\n        length = len(data)\n        for count in freq.values():\n            p = count / length\n            entropy -= p * (0 if p &lt;= 0 else math.log2(p))\n        return entropy\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # ZONE C BACKEND \u2014 Batch Integrity Verifier\n    # Real SHA256 file hashing, fully threaded, queue-throttled UI updates\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _integ_log_write(self, msg):\n        \"\"\"Thread-safe write into Zone C log via after().\"\"\"\n        def _w():\n            try:\n                self._integ_log.config(state=\"normal\")\n                self._integ_log.insert(\"end\", msg + \"\\n\")\n                self._integ_log.see(\"end\")\n                self._integ_log.config(state=\"disabled\")\n            except Exception:\n                pass\n        self.after(0, _w)\n\n    def _integ_use_rec_dest(self):\n        \"\"\"Populate integrity folder from last known recovery destination.\"\"\"\n        d = getattr(self, \"_last_recovery_dest\", \"\")\n        if d and os.path.isdir(d):\n            self._integ_dir_var.set(d)\n        else:\n            messagebox.showinfo(\"No Dest\", \"Pehle Zone A/B se files recover karo, folder auto-fill ho jayega.\")\n\n    def _start_integrity_verifier(self):\n        \"\"\"Atomic-guarded launcher for Zone C background thread.\"\"\"\n        with self._rec_integrity_lock:\n            if self._recovery_is_processing:\n                messagebox.showwarning(\"Busy\", \"Ek operation pehle se chal raha hai. Wait karo.\")\n                return\n            folder = self._integ_dir_var.get().strip()\n            if not folder or not os.path.isdir(folder):\n                messagebox.showwarning(\"Folder\", \"Valid folder select karo.\")\n                return\n            self._recovery_is_processing = True\n            self._integ_run_btn.config(state=\"disabled\")\n\n        self._launch_job(\n            \"integrity_verify\",\n            self._do_integrity_verify,\n            folder,\n            self._integ_recurse_var.get(),\n            self._integ_export_var.get()\n        )\n\n    def _do_integrity_verify(self, folder, recurse, export_csv):\n        \"\"\"\n        Background worker \u2014 Zone C.\n        Walks folder, computes real SHA256 of every file, checks size / readability.\n        UI updates throttled to once per 120 ms via time.monotonic() guard.\n        No time.sleep() fakes. Every byte read is real OS I/O.\n        \"\"\"\n        results = []          # (path, size_bytes, sha256, status)\n        total_files  = 0\n        ok_files     = 0\n        corrupt_files = 0\n        zero_files   = 0\n        last_ui      = time.monotonic()\n\n        try:\n            # \u2500\u2500 collect files \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            all_files = []\n            if recurse:\n                for root_d, _, fnames in os.walk(folder):\n                    for fn in fnames:\n                        all_files.append(os.path.join(root_d, fn))\n            else:\n                for fn in os.listdir(folder):\n                    fp = os.path.join(folder, fn)\n                    if os.path.isfile(fp):\n                        all_files.append(fp)\n\n            total_files = len(all_files)\n            self._integ_log_write(f\"\u25b6 {total_files} files mili \u2014 SHA256 verification shuru\u2026\")\n\n            def _ui_update(idx, msg, pct):\n                now = time.monotonic()\n                if now - last_ui &gt;= 0.120:\n                    def _upd(m=msg, p=pct):\n                        try:\n                            self._integ_stat_lbl.config(text=m)\n                            self._integ_prog_var.set(p)\n                        except Exception:\n                            pass\n                    self.after(0, _upd)\n                    return now\n                return last_ui\n\n            for idx, fp in enumerate(all_files):\n                try:\n                    fsize = os.path.getsize(fp)\n                    if fsize == 0:\n                        status = \"ZERO_BYTE\"\n                        sha = \"\u2014\"\n                        zero_files += 1\n                    else:\n                        h = hashlib.sha256()\n                        try:\n                            with open(fp, \"rb\") as fh:\n                                for chunk in iter(lambda: fh.read(65536), b\"\"):\n                                    h.update(chunk)\n                            sha = h.hexdigest()\n                            status = \"OK\"\n                            ok_files += 1\n                        except (PermissionError, OSError) as read_err:\n                            sha = \"READ_ERROR\"\n                            status = f\"CORRUPT ({read_err.__class__.__name__})\"\n                            corrupt_files += 1\n                    results.append((fp, fsize, sha, status))\n                    pct = round((idx + 1) / max(total_files, 1) * 100, 1)\n                    msg_txt = (f\"\ud83d\udd10 Verifying {idx+1}/{total_files} | \u2705{ok_files} OK \"\n                               f\"| \u26a0{corrupt_files} Corrupt | 0\ufe0f\u20e3{zero_files} Zero\")\n                    last_ui = _ui_update(idx, msg_txt, pct)\n\n                    if status != \"OK\":\n                        self._integ_log_write(f\"  [{status}] {os.path.basename(fp)}\")\n\n                except Exception as file_err:\n                    results.append((fp, 0, \"ERROR\", str(file_err)))\n                    corrupt_files += 1\n                    self._integ_log_write(f\"  \u274c {os.path.basename(fp)}: {file_err}\")\n\n            # \u2500\u2500 final UI \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            final_msg = (f\"\u2705 Verification complete \u2014 {ok_files} OK | \"\n                         f\"{corrupt_files} Corrupt/Unreadable | {zero_files} Zero-byte\")\n            self.after(0, lambda: self._integ_stat_lbl.config(text=final_msg))\n            self.after(0, lambda: self._integ_prog_var.set(100))\n            self._integ_log_write(final_msg)\n\n            # \u2500\u2500 CSV export \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            if export_csv and results:\n                out_path = os.path.join(folder, f\"integrity_report_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.csv\")\n                try:\n                    with open(out_path, \"w\", newline=\"\", encoding=\"utf-8-sig\") as cf:\n                        w = csv.writer(cf)\n                        w.writerow([\"Path\", \"Size_Bytes\", \"SHA256\", \"Status\"])\n                        w.writerows(results)\n                    self._integ_log_write(f\"\ud83d\udce5 CSV saved: {out_path}\")\n                    self.after(0, lambda p=out_path: messagebox.showinfo(\n                        \"Report Saved\", f\"\u2705 Integrity CSV saved:\\n{p}\"))\n                except Exception as csv_err:\n                    self._integ_log_write(f\"\u274c CSV export failed: {csv_err}\")\n\n        except Exception as ex:\n            self._integ_log_write(f\"\u274c Fatal error: {ex}\")\n            self.after(0, lambda: self._integ_stat_lbl.config(text=f\"\u274c Error: {ex}\"))\n        finally:\n            # \u2500\u2500 strict resource cleanup \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            results.clear()\n            gc.collect()\n            with self._rec_integrity_lock:\n                self._recovery_is_processing = False\n            self.after(0, lambda: self._integ_run_btn.config(state=\"normal\"))\n\n    def _ensure_admin_for_raw_recovery(self, disk_path=None):\n        if disk_path and not _is_raw_device_path(disk_path):\n            return True\n        if is_admin():\n            return True\n        if messagebox.askyesno(\n            \"Admin Required\",\n            \"Raw disk recovery ke liye Administrator rights mandatory hain.\\n\\n\"\n            \"App ko admin mode me restart karein?\"\n        ):\n            run_as_admin()\n        return False\n\n    def _raw_disk_path(self):\n        return (self.raw_disk_var.get() if hasattr(self, \"raw_disk_var\") else DEFAULT_RAW_DISK).strip() or DEFAULT_RAW_DISK\n\n    def _forensic_read_at(self, source, offset, length):\n        if source and os.path.exists(source) and not _is_raw_device_path(source):\n            with open(source, \"rb\") as f:\n                f.seek(offset)\n                return f.read(length)\n        return _read_raw_at(source, offset, length)\n\n    def _parse_mbr_partitions(self, sector):\n        parts = []\n        if len(sector) &lt; 512 or sector[510:512] != b\"\\x55\\xAA\":\n            return parts\n        for idx in range(4):\n            off = 446 + idx * 16\n            ent = sector[off:off + 16]\n            if len(ent) &lt; 16:\n                continue\n            ptype = ent[4]\n            start = struct.unpack_from(\" 512:\n                    tail = self._forensic_read_at(source, max(0, size - 512), 512)\n            except Exception:\n                pass\n            if head.startswith(b\"vhdxfile\"):\n                return \"VHDX\"\n            if tail[0:8] == b\"conectix\":\n                return \"VHD\"\n            if head.startswith(b\"EVF\\x09\") or head.startswith(b\"LVF\\x09\"):\n                return \"E01\"\n            return ext.lstrip(\".\").upper() or \"RAW_FILE\"\n        except Exception:\n            return \"UNKNOWN\"\n\n    def _parse_gpt_entries(self, source):\n        try:\n            header = self._forensic_read_at(source, 512, 512)\n            if len(header) &lt; 92 or header[:8] != b\"EFI PART\":\n                return None\n            entry_lba = struct.unpack_from(\"= first_lba else 0,\n                    \"size\": ((last_lba - first_lba + 1) * SECTOR_SIZE) if last_lba &gt;= first_lba else 0,\n                    \"name\": name or \"(no name)\",\n                    \"attrs\": attrs,\n                    \"type_guid\": str(uuid.UUID(bytes_le=ent[:16])),\n                    \"part_guid\": str(uuid.UUID(bytes_le=ent[16:32])),\n                })\n            return {\n                \"disk_guid\": str(uuid.UUID(bytes_le=disk_guid_raw)),\n                \"entry_lba\": entry_lba,\n                \"entry_count\": entry_count,\n                \"entry_size\": entry_size,\n                \"partitions\": parts,\n            }\n        except Exception:\n            return None\n\n    def _parse_ntfs_runlist(self, data):\n        runs = []\n        i = 0\n        current_lcn = 0\n        while i &lt; len(data):\n            header = data[i]\n            i += 1\n            if header == 0:\n                break\n            len_size = header &amp; 0x0F\n            off_size = (header &gt;&gt; 4) &amp; 0x0F\n            if i + len_size + off_size &gt; len(data):\n                break\n            run_len = int.from_bytes(data[i:i + len_size], \"little\", signed=False)\n            i += len_size\n            run_off = int.from_bytes(data[i:i + off_size], \"little\", signed=True)\n            i += off_size\n            current_lcn += run_off\n            runs.append((current_lcn, run_len))\n        return runs\n\n    def _parse_ntfs_data_runs(self, rec):\n        if len(rec) &lt; 64 or rec[:4] != b\"FILE\":\n            return []\n        used = struct.unpack_from(\" len(rec):\n                break\n            nonresident = rec[pos + 8]\n            name_len = rec[pos + 9]\n            name_off = struct.unpack_from(\" len(rec):\n                    break\n                nonresident = rec[pos + 8]\n                if atype == 0x30 and not nonresident:\n                    vlen = struct.unpack_from(\"= 66:\n                        parent = struct.unpack_from(\" 1 else (\"contiguous\" if run_count == 1 else \"resident/unknown\")\n                lines.append(\n                    f\"- #{item.get('record')} [{state}/{kind}] {item.get('name')} | path={path_text} | \"\n                    f\"size={item.get('real_size','')} | modified={item.get('modified','')} | parent={item.get('parent_ref','')} | runs={run_count} {frag}\"\n                )\n            lines.append(\"\")\n            lines.append(\"Special NTFS metadata records:\")\n            for key in [\"$mft\", \"$mftmirr\", \"$bitmap\", \"$logfile\", \"$usnjrnl\"]:\n                if key in special:\n                    item = special[key]\n                    lines.append(f\"- {key}: record #{item.get('record')} path={self._reconstruct_ntfs_path(item, name_map)}\")\n                else:\n                    lines.append(f\"- {key}: sample range me not observed\")\n            lines.append(\"\")\n            lines.append(\"Professional note:\")\n            lines.append(\"- Ye sample parser original filename, deleted flag, timestamps, parent references aur best-effort path reconstruction prove karta hai.\")\n            lines.append(\"- Non-resident DATA runs parse kiye gaye hain; multiple runs fragmented file ka strong clue dete hain.\")\n            lines.append(\"- $Bitmap / $LogFile / $UsnJrnl presence recovery confidence aur filesystem timeline analysis me useful hoti hai.\")\n            report = \"\\n\".join(lines)\n            self._raw_recovery_progress(\"NTFS MFT sample complete.\")\n            self.after(0, lambda: self._open_raw_hex_window(0, report))\n        except Exception as e:\n            err = str(e)\n            self._raw_recovery_progress(f\"MFT sample failed: {err}\")\n            self.after(0, lambda err=err: messagebox.showerror(\"MFT Parser Error\", err))\n\n    def _shadow_copy_recovery_report(self):\n        self._reset_raw_progress(\"Shadow Copy enumeration...\")\n        self._launch_job(\"shadow_copy_report\", self._do_shadow_copy_recovery_report)\n\n    def _do_shadow_copy_recovery_report(self):\n        try:\n            out1, _ = self._run_cmd(\"vssadmin list shadows\", timeout=60)\n            out2, _ = self._run_cmd(\"wmic shadowcopy get ID,InstallDate,OriginatingMachine,VolumeName /format:list\", timeout=60)\n            report = (\n                \"Shadow Copy Recovery Report\\n\"\n                f\"Generated: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\\n\\n\"\n                \"Troubleshoot kya kiya:\\n\"\n                \"- vssadmin list shadows run kiya.\\n\"\n                \"- WMIC shadowcopy inventory collect ki.\\n\\n\"\n                \"Recovery guidance:\\n\"\n                \"- Shadow copy available ho to deleted files previous snapshot se copy kiye ja sakte hain.\\n\"\n                \"- Evidence-safe workflow: source snapshot read-only mount/copy, original disk par write mat karo.\\n\\n\"\n                f\"vssadmin output:\\n{out1 or 'No shadows or access denied.'}\\n\\n\"\n                f\"WMIC output:\\n{out2 or 'No WMIC shadow data.'}\\n\"\n            )\n            self._raw_recovery_progress(\"Shadow Copy report complete.\")\n            self.after(0, lambda: self._open_raw_hex_window(0, report))\n        except Exception as e:\n            err = str(e)\n            self._raw_recovery_progress(f\"Shadow Copy report failed: {err}\")\n\n    def _score_recovered_file(self, path):\n        try:\n            size = os.path.getsize(path)\n            with open(path, \"rb\") as f:\n                head = f.read(4096)\n                if size &gt; 4096:\n                    f.seek(max(0, size - 4096))\n                    tail = f.read(4096)\n                else:\n                    tail = head\n            ext = Path(path).suffix.lower().lstrip(\".\")\n            score = \"Partial (55)\"\n            reason = \"Header/footer unknown.\"\n            checks = {\n                \"jpg\": (head.startswith(b\"\\xff\\xd8\\xff\"), tail.rstrip().endswith(b\"\\xff\\xd9\")),\n                \"jpeg\": (head.startswith(b\"\\xff\\xd8\\xff\"), tail.rstrip().endswith(b\"\\xff\\xd9\")),\n                \"png\": (head.startswith(b\"\\x89PNG\\r\\n\\x1a\\n\"), b\"IEND\" in tail),\n                \"pdf\": (head.startswith(b\"%PDF\"), b\"%%EOF\" in tail),\n                \"zip\": (head.startswith(b\"PK\\x03\\x04\"), b\"PK\\x05\\x06\" in tail or b\"PK\\x06\\x06\" in tail),\n                \"docx\": (head.startswith(b\"PK\\x03\\x04\"), b\"PK\\x05\\x06\" in tail or b\"PK\\x06\\x06\" in tail),\n                \"xlsx\": (head.startswith(b\"PK\\x03\\x04\"), b\"PK\\x05\\x06\" in tail or b\"PK\\x06\\x06\" in tail),\n                \"pptx\": (head.startswith(b\"PK\\x03\\x04\"), b\"PK\\x05\\x06\" in tail or b\"PK\\x06\\x06\" in tail),\n            }\n            if ext in checks:\n                h_ok, f_ok = checks[ext]\n                if h_ok and f_ok:\n                    score, reason = \"Excellent (95)\", \"Header aur footer dono valid.\"\n                elif h_ok:\n                    score, reason = \"Partial (65)\", \"Header valid, footer missing/fragmented.\"\n                else:\n                    score, reason = \"Corrupted (20)\", \"Expected header missing.\"\n            if size == 0:\n                score, reason = \"Corrupted (0)\", \"Zero-byte recovered file.\"\n            return score, reason\n        except Exception as e:\n            return \"Unknown\", str(e)\n\n    def _forensic_hash_verify_dialog(self):\n        folder = filedialog.askdirectory(title=\"Recovered files folder select karo\")\n        if not folder:\n            return\n        self._reset_raw_progress(\"Hash + forensic verification running...\")\n        self._launch_job(\"forensic_hash_verify\", self._do_forensic_hash_verify, folder)\n\n    def _do_forensic_hash_verify(self, folder):\n        try:\n            rows = []\n            by_sha256 = {}\n            count = 0\n            for root, dirs, files in os.walk(folder):\n                for name in files:\n                    if getattr(self, \"_recovery_stop_flag\", False):\n                        break\n                    path = os.path.join(root, name)\n                    try:\n                        md5 = hashlib.md5()\n                        sha1 = hashlib.sha1()\n                        sha256 = hashlib.sha256()\n                        with open(path, \"rb\") as f:\n                            for chunk in iter(lambda: f.read(1024 * 1024), b\"\"):\n                                md5.update(chunk); sha1.update(chunk); sha256.update(chunk)\n                        score, reason = self._score_recovered_file(path)\n                        item = {\n                            \"path\": path,\n                            \"size\": os.path.getsize(path),\n                            \"md5\": md5.hexdigest(),\n                            \"sha1\": sha1.hexdigest(),\n                            \"sha256\": sha256.hexdigest(),\n                            \"score\": score,\n                            \"reason\": reason,\n                        }\n                        rows.append(item)\n                        by_sha256.setdefault(item[\"sha256\"], []).append(path)\n                        count += 1\n                        if count % 50 == 0:\n                            self._raw_recovery_progress(f\"Hashed {count} files...\")\n                    except Exception as e:\n                        rows.append({\"path\": path, \"error\": str(e)})\n            dups = {h: ps for h, ps in by_sha256.items() if len(ps) &gt; 1}\n            report_path = os.path.join(folder, \"Godawari_Forensic_Hash_Report.csv\")\n            with open(report_path, \"w\", newline=\"\", encoding=\"utf-8\") as f:\n                writer = csv.DictWriter(f, fieldnames=[\"path\", \"size\", \"md5\", \"sha1\", \"sha256\", \"score\", \"reason\", \"error\"])\n                writer.writeheader()\n                for row in rows:\n                    writer.writerow({k: row.get(k, \"\") for k in writer.fieldnames})\n            lines = [\n                \"Hash + Forensic Verification Report\",\n                f\"Folder: {folder}\",\n                f\"Files processed: {len(rows)}\",\n                f\"Duplicate SHA256 groups: {len(dups)}\",\n                f\"CSV report: {report_path}\",\n                \"\",\n                \"Recoverability scoring:\",\n                \"- Excellent: header/footer valid\",\n                \"- Partial: header valid but footer missing/fragmented\",\n                \"- Corrupted: expected header missing\",\n                \"\",\n                \"Duplicate groups:\",\n            ]\n            for h, ps in list(dups.items())[:20]:\n                lines.append(f\"- {h}: {len(ps)} files\")\n                lines.extend(f\"  {p}\" for p in ps[:5])\n            report = \"\\n\".join(lines)\n            self._raw_recovery_progress(\"Hash verification complete.\")\n            self.after(0, lambda: self._open_raw_hex_window(0, report))\n        except Exception as e:\n            err = str(e)\n            self._raw_recovery_progress(f\"Hash verification failed: {err}\")\n\n    def _recovery_session_db_path(self):\n        return os.path.join(getattr(self, \"backup_dir\", os.getcwd()), \"recovery_sessions.sqlite3\")\n\n    def _recovery_session_db_save(self):\n        try:\n            items = []\n            if hasattr(self, \"rec_tree\"):\n                for iid in self.rec_tree.get_children():\n                    vals = self.rec_tree.item(iid, \"values\")\n                    items.append(tuple(vals))\n            if not items and hasattr(self, \"rec_found_files\"):\n                for entry in self.rec_found_files.values():\n                    if isinstance(entry, str):\n                        p = entry\n                    elif isinstance(entry, dict):\n                        p = entry.get(\"path\") or \"\"\n                    else:\n                        continue\n                    if p:\n                        items.append((os.path.basename(str(p)), Path(str(p)).suffix.lstrip(\".\"), \"\", str(p)))\n            if not items:\n                messagebox.showinfo(\"No Session\", \"Recovery result list empty hai.\")\n                return\n            db_path = self._recovery_session_db_path()\n            os.makedirs(os.path.dirname(db_path), exist_ok=True)\n            con = sqlite3.connect(db_path)\n            try:\n                cur = con.cursor()\n                cur.execute(\"CREATE TABLE IF NOT EXISTS sessions(id INTEGER PRIMARY KEY, ts TEXT, source TEXT, note TEXT)\")\n                cur.execute(\"CREATE TABLE IF NOT EXISTS files(session_id INTEGER, filename TEXT, ext TEXT, size TEXT, path TEXT)\")\n                source = self._raw_disk_path() if hasattr(self, \"raw_disk_var\") else \"\"\n                cur.execute(\"INSERT INTO sessions(ts, source, note) VALUES(?,?,?)\", (datetime.datetime.now().isoformat(timespec=\"seconds\"), source, \"GUI recovery session\"))\n                sid = cur.lastrowid\n                cur.executemany(\"INSERT INTO files(session_id, filename, ext, size, path) VALUES(?,?,?,?,?)\", [(sid,) + tuple(x[:4]) for x in items])\n                con.commit()\n            finally:\n                con.close()\n            msg = f\"Recovery session saved: {db_path}\\nSession items: {len(items)}\"\n            self._raw_recovery_progress(msg)\n            messagebox.showinfo(\"Session Saved\", msg)\n        except Exception as e:\n            messagebox.showerror(\"Session DB Error\", str(e))\n\n    def _begin_recovery_operation(self, label):\n        if getattr(self, \"_recovery_active\", False):\n            raise RuntimeError(\"Ek recovery task already chal raha hai. Pehle usko complete/stop hone dein.\")\n        self._recovery_stop_flag = False\n        self._recovery_pause_flag = False\n        self._recovery_active = True\n        self._active_recovery_session_id = None\n        try:\n            mgr = getattr(self, \"recovery_session_manager\", None)\n            if mgr:\n                self._active_recovery_session_id = mgr.start(\n                    \"file_recovery\", {\"label\": str(label)})\n        except Exception:\n            pass\n        if hasattr(self, \"_rec_stop_btn\"):\n            self._rec_stop_btn.config(state=\"normal\")\n        if hasattr(self, \"_rec_pause_btn\"):\n            self._rec_pause_btn.config(state=\"normal\", text=\"\u23f8 Pause\")\n        self._set_status(label, C[\"warning\"])\n\n    def _finish_recovery_operation(self):\n        sid = getattr(self, \"_active_recovery_session_id\", None)\n        if sid:\n            try:\n                status = \"stopped\" if getattr(self, \"_recovery_stop_flag\", False) else \"completed\"\n                self.recovery_session_manager.complete(sid, status=status)\n            except Exception:\n                pass\n            self._active_recovery_session_id = None\n        self._recovery_active = False\n        self._recovery_pause_flag = False\n        if hasattr(self, \"_rec_stop_btn\"):\n            self._rec_stop_btn.config(state=\"disabled\")\n        if hasattr(self, \"_rec_pause_btn\"):\n            self._rec_pause_btn.config(state=\"disabled\", text=\"\u23f8 Pause\")\n\n    def _is_mobile_source(self, drive_text):\n        d = (drive_text or \"\").strip().lower()\n        return d in {\"mobile\", \"android\", \"phone\", \"mobile_deep\", \"android_deep\"} or d.startswith(\"android\")\n\n    def _android_media_preset(self, preset):\n        # Force Android mode + set exts presets; roots override used by mobile finder\n        try:\n            self.rec_drive.set(\"Android\")\n        except Exception:\n            pass\n        if preset == \"whatsapp\":\n            self.rec_ext.delete(0, \"end\")\n            self.rec_ext.insert(0, \"jpg,jpeg,png,mp4\")\n            self._mobile_roots_override = [\"/sdcard/WhatsApp/Media\", \"/sdcard/Android/media\"]\n        else:\n            self.rec_ext.delete(0, \"end\")\n            self.rec_ext.insert(0, \"jpg,jpeg,png,mp4\")\n            self._mobile_roots_override = [\"/sdcard/DCIM\", \"/sdcard/Pictures\", \"/sdcard/Movies\"]\n        self._start_file_recovery()\n\n    def _mobile_bridge_help(self):\n        cmd = os.environ.get(\"GODAWARI_MOBILE_BRIDGE_CMD\", \"\").strip()\n        messagebox.showinfo(\n            \"Mobile Bridge\",\n            \"Advanced mobile recovery ke liye optional bridge available hai.\\n\\n\"\n            \"Env var set karo:\\n\"\n            \"GODAWARI_MOBILE_BRIDGE_CMD = \\n\\n\"\n            \"Bridge command JSON list output kare:\\n\"\n            \"[\\\"/sdcard/path/file1.jpg\\\", \\\"...\\\" ]\\n\\n\"\n            f\"Current: {cmd if cmd else '(not set)'}\"\n        )\n\n    def _mobile_bridge_candidates(self, exts):\n        \"\"\"\n        Optional external bridge for advanced mobile recovery.\n        Set env var GODAWARI_MOBILE_BRIDGE_CMD to a command that outputs JSON list of paths.\n        \"\"\"\n        cmd = os.environ.get(\"GODAWARI_MOBILE_BRIDGE_CMD\", \"\").strip()\n        if not cmd:\n            return []\n        exts_arg = \",\".join(sorted({e.lower().strip(\".\") for e in exts if e.strip()}))\n        out, rc = self._run_cmd(f'{cmd} --ext \"{exts_arg}\"', timeout=180)\n        if rc != 0 or not out.strip():\n            return []\n        try:\n            data = json.loads(out)\n            if isinstance(data, list):\n                return [str(x) for x in data if str(x).strip()]\n        except Exception:\n            return []\n        return []\n\n    def _mobile_adb_available(self):\n        out, rc = self._run_cmd(self._adb_args(\"version\"), timeout=10)\n        return rc == 0 and \"android debug bridge\" in out.lower()\n\n    def _mobile_device_ready(self):\n        out, rc = self._run_cmd(self._adb_args(\"devices\"), timeout=10)\n        if rc != 0:\n            return False\n        for ln in out.splitlines()[1:]:\n            parts = ln.strip().split()\n            if len(parts) &gt;= 2 and parts[1].strip().lower() == \"device\":\n                return True\n        return False\n\n    def _find_adb_exe(self):\n        cached = getattr(self, \"_adb_exe_cache\", None)\n        if cached and os.path.isfile(cached):\n            return cached\n        candidates = []\n        env_direct = os.environ.get(\"ADB_PATH\", \"\").strip().strip('\"')\n        if env_direct:\n            candidates.append(env_direct)\n        for name in (\"adb.exe\", \"adb\"):\n            found = shutil.which(name)\n            if found:\n                candidates.append(found)\n        local_appdata = os.environ.get(\"LOCALAPPDATA\", \"\")\n        user_profile = os.environ.get(\"USERPROFILE\", \"\")\n        common_roots = [\n            os.getcwd(),\n            os.path.dirname(os.path.abspath(sys.argv[0])),\n            local_appdata,\n            user_profile,\n            os.path.join(local_appdata, \"Android\"),\n            os.path.join(local_appdata, \"Android\", \"Sdk\"),\n            os.path.join(user_profile, \"AppData\", \"Local\", \"Android\", \"Sdk\"),\n            os.path.join(user_profile, \"Downloads\"),\n            os.path.join(user_profile, \"Desktop\"),\n        ]\n        rels = [\n            \"platform-tools\\\\adb.exe\",\n            \"Android\\\\Sdk\\\\platform-tools\\\\adb.exe\",\n            \"sdk\\\\platform-tools\\\\adb.exe\",\n            \"tools\\\\platform-tools\\\\adb.exe\",\n        ]\n        for root in common_roots:\n            if not root:\n                continue\n            for rel in rels:\n                candidates.append(os.path.join(root, rel))\n        seen = set()\n        for path in candidates:\n            try:\n                norm = os.path.normcase(os.path.abspath(path))\n            except Exception:\n                norm = os.path.normcase(str(path))\n            if norm in seen:\n                continue\n            seen.add(norm)\n            if os.path.isfile(path):\n                self._adb_exe_cache = path\n                return path\n        return \"\"\n\n    def _adb_cmd(self, args):\n        adb_exe = self._find_adb_exe() or \"adb\"\n        return f'\"{adb_exe}\" {args}'.strip()\n\n    def _adb_args(self, *args):\n        adb_exe = self._find_adb_exe() or \"adb\"\n        return [adb_exe, *[str(a) for a in args]]\n\n    def _show_adb_help(self):\n        detected = self._find_adb_exe()\n        hint = detected if detected else \"Not detected\"\n        messagebox.showinfo(\n            \"ADB Required\",\n            \"Mobile recovery ke liye Android Platform Tools required hain.\\n\\n\"\n            f\"Detected ADB: {hint}\\n\\n\"\n            \"Setup:\\n\"\n            \"1. Android phone me USB debugging ON karo\\n\"\n            \"2. Platform Tools install/unzip karo\\n\"\n            \"3. adb.exe ko PATH me add karo ya ADB_PATH env var set karo\\n\"\n            \"4. Phone ko authorize karke retry karo\"\n        )\n\n    def _refresh_adb_status_label(self):\n        if not hasattr(self, \"adb_status_label\"):\n            return\n        adb_exe = self._find_adb_exe()\n        if not adb_exe:\n            text = \"ADB Status: Not Found\"\n            color = C[\"error\"]\n        elif self._mobile_device_ready():\n            text = \"ADB Status: Device Authorized\"\n            color = C[\"success\"]\n        else:\n            text = \"ADB Status: Found, device not authorized\"\n            color = C[\"warning\"]\n        self.adb_status_label.config(text=text, fg=color)\n\n    def _mobile_find_candidates(self, exts):\n        exts = [e.lower().strip(\".\") for e in exts if e.strip()]\n        roots = getattr(self, \"_mobile_roots_override\", None) or [\n            \"/sdcard/DCIM\", \"/sdcard/Download\", \"/sdcard/Pictures\", \"/sdcard/Movies\",\n            \"/sdcard/WhatsApp/Media\", \"/sdcard/Android/media\", \"/storage/emulated/0\",\n        ]\n        found = []\n        seen = set()\n        # Build a filtered find expression to reduce output volume\n        patterns = []\n        for ext in sorted({e for e in exts if e}):\n            # Use -iname for case-insensitive match\n            patterns.append(f\"-iname '*.{ext}'\")\n        expr = \"\"\n        if patterns:\n            expr = \"\\\\( \" + \" -o \".join(patterns[:20]) + \" \\\\)\"\n        for root in roots:\n            if getattr(self, \"_recovery_stop_flag\", False):\n                break\n            while getattr(self, \"_recovery_pause_flag\", False):\n                if getattr(self, \"_recovery_stop_flag\", False):\n                    break\n                time.sleep(0.2)\n            shell_script = \"if [ -d '\" + root + \"' ]; then find '\" + root + \"' -type f \"\n            if expr:\n                shell_script += expr + \" \"\n            shell_script += \"2&gt;/dev/null; fi\"\n            proc = subprocess.Popen(self._adb_args(\"shell\", shell_script), shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, encoding=\"utf-8\", errors=\"replace\")\n            try:\n                for line in proc.stdout:\n                    if getattr(self, \"_recovery_stop_flag\", False):\n                        proc.terminate()\n                        break\n                    while getattr(self, \"_recovery_pause_flag\", False):\n                        if getattr(self, \"_recovery_stop_flag\", False):\n                            proc.terminate()\n                            break\n                        time.sleep(0.2)\n                    p = line.strip()\n                    if not p:\n                        continue\n                    low = p.lower()\n                    if (not exts or any(low.endswith(\".\" + ext) for ext in exts)) and low not in seen:\n                        seen.add(low)\n                        found.append(p)\n                        if len(found) % 100 == 0:\n                            self._raw_recovery_progress(f\"MOBILE scan: {len(found)} files matched...\")\n            finally:\n                try:\n                    proc.wait(timeout=2)\n                except Exception:\n                    pass\n        # Extra recovery hint: media scanner cache can include recently indexed files.\n        try:\n            cmd = self._adb_args(\"shell\", \"find /sdcard -name .thumbnails -o -name LOST.DIR 2&gt;/dev/null\")\n            out, rc = self._run_cmd(cmd, timeout=25)\n            if rc == 0 and out.strip():\n                self._raw_recovery_progress(\"MOBILE hint: thumbnail/LOST.DIR folders bhi detect hui hain.\")\n        except Exception:\n            pass\n        bridge_items = self._mobile_bridge_candidates(exts)\n        if bridge_items:\n            for p in bridge_items:\n                low = p.lower()\n                if low not in seen:\n                    seen.add(low)\n                    found.append(p)\n            self._raw_recovery_progress(f\"MOBILE bridge added {len(bridge_items)} candidate(s)\")\n        return found\n\n    def _recovery_checkpoint_path(self, mode):\n        safe = re.sub(r\"[^a-zA-Z0-9_.-]+\", \"_\", str(mode or \"default\"))\n        return os.path.join(getattr(self, \"backup_dir\", os.getcwd()), f\"recovery_checkpoint_{safe}.json\")\n\n    def _save_recovery_checkpoint(self, mode, data):\n        try:\n            path = self._recovery_checkpoint_path(mode)\n            payload = {\n                \"ts\": datetime.datetime.now().isoformat(timespec=\"seconds\"),\n                \"mode\": mode,\n                \"data\": data,\n            }\n            with open(path, \"w\", encoding=\"utf-8\") as f:\n                json.dump(payload, f, ensure_ascii=False)\n        except Exception:\n            pass\n\n    def _load_recovery_checkpoint(self, mode):\n        try:\n            path = self._recovery_checkpoint_path(mode)\n            if not os.path.exists(path):\n                return None\n            with open(path, \"r\", encoding=\"utf-8\") as f:\n                payload = json.load(f)\n            if payload.get(\"mode\") != mode:\n                return None\n            return payload.get(\"data\")\n        except Exception:\n            return None\n\n    def _clear_recovery_checkpoint(self, mode):\n        try:\n            path = self._recovery_checkpoint_path(mode)\n            if os.path.exists(path):\n                os.remove(path)\n        except Exception:\n            pass\n\n    def _sha256_file(self, path):\n        h = hashlib.sha256()\n        with open(path, \"rb\") as f:\n            while True:\n                chunk = f.read(1024 * 1024)\n                if not chunk:\n                    break\n                h.update(chunk)\n        return h.hexdigest()\n\n    def _mobile_pull_with_retry(self, src, dst):\n        out = \"\"\n        for _ in range(3):\n            out, rc = self._run_cmd(self._adb_args(\"pull\", src, dst), timeout=300)\n            if rc == 0 and os.path.exists(dst):\n                return True, out\n            time.sleep(0.4)\n        return False, out\n\n    def _integrity_score(self, path, file_type_hint=\"\"):\n        try:\n            size = os.path.getsize(path)\n            if size &lt;= 0:\n                return 0, \"empty file\"\n            score = 40\n            reason = [\"file exists\"]\n            ext = (file_type_hint or os.path.splitext(path)[1].lstrip(\".\")).lower()\n            if size &gt; 1024:\n                score += 20\n                reason.append(\"size&gt;1KB\")\n            if size &gt; 1024 * 1024:\n                score += 10\n                reason.append(\"size&gt;1MB\")\n            if ext in (\"jpg\", \"jpeg\", \"png\", \"pdf\", \"zip\", \"mp4\", \"exe\"):\n                with open(path, \"rb\") as f:\n                    data = f.read(min(size, 8 * 1024 * 1024))\n                if ext in (\"jpg\", \"jpeg\") and data.startswith(b\"\\xFF\\xD8\"):\n                    score += 15\n                    reason.append(\"jpeg header ok\")\n                elif ext == \"png\" and data.startswith(b\"\\x89PNG\\r\\n\\x1A\\n\"):\n                    score += 15\n                    reason.append(\"png header ok\")\n                elif ext == \"pdf\" and data.startswith(b\"%PDF\"):\n                    score += 15\n                    reason.append(\"pdf header ok\")\n                elif ext == \"zip\" and data.startswith(b\"PK\\x03\\x04\"):\n                    score += 15\n                    reason.append(\"zip header ok\")\n                elif ext == \"mp4\" and b\"ftyp\" in data[:128]:\n                    score += 15\n                    reason.append(\"mp4 ftyp ok\")\n                elif ext == \"exe\" and data.startswith(b\"MZ\"):\n                    score += 15\n                    reason.append(\"mz header ok\")\n            return max(0, min(100, score)), \", \".join(reason)\n        except Exception as e:\n            return 20, f\"basic only ({e})\"\n\n    def _check_recovery_control(self):\n        if getattr(self, \"_recovery_stop_flag\", False):\n            raise InterruptedError(\"Recovery stopped by user.\")\n        paused_notice = False\n        while getattr(self, \"_recovery_pause_flag\", False):\n            if not paused_notice:\n                paused_notice = True\n                self.after(0, lambda: self._set_status(\"Recovery paused - Resume dabao\", C[\"warning\"]))\n            time.sleep(0.25)\n            if getattr(self, \"_recovery_stop_flag\", False):\n                raise InterruptedError(\"Recovery stopped by user.\")\n\n    def _update_raw_source_badge(self):\n        if not hasattr(self, \"raw_source_badge\"):\n            return\n        src = self._raw_disk_path()\n        if _is_raw_device_path(src):\n            self.raw_source_badge.config(text=\"RAW DEVICE - admin required\", fg=C[\"warning\"])\n        elif os.path.isfile(src):\n            self.raw_source_badge.config(text=\"IMG FILE - scan without admin\", fg=C[\"success\"])\n        else:\n            self.raw_source_badge.config(text=\"SOURCE NOT FOUND\", fg=C[\"error\"])\n\n    def _reset_raw_progress(self, message=\"Ready\"):\n        if hasattr(self, \"raw_progress_var\"):\n            self.raw_progress_var.set(0)\n        if hasattr(self, \"raw_progress_bar\"):\n            try:\n                self.raw_progress_bar.stop()\n            except Exception:\n                pass\n            self.raw_progress_bar.config(mode=\"determinate\")\n        if hasattr(self, \"raw_progress_label\"):\n            self.raw_progress_label.config(text=message)\n        if hasattr(self, \"raw_progress_log\"):\n            try:\n                self.raw_progress_log.config(state=\"normal\")\n                self.raw_progress_log.delete(\"1.0\", \"end\")\n                self.raw_progress_log.insert(\"end\", message + \"\\n\")\n                self.raw_progress_log.config(state=\"disabled\")\n            except Exception:\n                pass\n\n    def _append_log_line(self, text):\n        if hasattr(self, \"raw_progress_log\"):\n            try:\n                self.raw_progress_log.config(state=\"normal\")\n                self.raw_progress_log.insert(\"end\", text + \"\\n\")\n                self.raw_progress_log.see(\"end\")\n                self.raw_progress_log.config(state=\"disabled\")\n            except Exception:\n                pass\n\n    def _recovery_reset_ui_batch(self):\n        self._rec_pending_rows = []\n        self._rec_pending_progress = None\n        self._rec_pending_log = None\n        self._rec_flush_scheduled = False\n        if not hasattr(self, \"_rec_batch_lock\"):\n            self._rec_batch_lock = threading.Lock()\n\n    def _recovery_schedule_flush(self):\n        with self._rec_batch_lock:\n            if self._rec_flush_scheduled:\n                return\n            self._rec_flush_scheduled = True\n        self.after(80, self._recovery_flush_ui_batch)\n\n    def _recovery_queue_row(self, row, entry):\n        \"\"\"\n        Thread-safe row enqueue. Routes through _ui_queue so the main thread\n        can batch-insert rows without any direct widget access from threads.\n        \"\"\"\n        self._q_tree_row(row, entry)\n\n    def _recovery_set_drive_progress(self, scanned, file_count, dirpath):\n        \"\"\"\n        Thread-safe progress update. Enqueues label+log via _ui_queue.\n        Can be called from any thread.\n        \"\"\"\n        folder_tail = dirpath[-65:] if len(dirpath) &gt; 65 else dirpath\n        label_text = (\n            f\"\ud83d\udd0d Scanning...  {scanned:,} folders  |  {file_count:,} files mili  |  ...{folder_tail}\")\n        self._q(\"progress_label\", label_text)\n        self._q_log(dirpath)\n\n    def _recovery_flush_ui_batch(self):\n        \"\"\"\n        Drain any tree-row messages still sitting in the UI queue (main-thread only).\n        Called at the end of a scan to ensure no rows are left unrendered.\n        The heavy lifting is now done by _poll_ui_queue() every 50 ms.\n        \"\"\"\n        # Drain up to 500 pending tree_row messages from the queue\n        MAX_FLUSH = 500\n        processed = 0\n        try:\n            while processed &lt; MAX_FLUSH:\n                msg_type, payload = self._ui_queue.get_nowait()\n                processed += 1\n                if msg_type == \"tree_row\" and hasattr(self, \"rec_tree\"):\n                    row, entry = payload\n                    try:\n                        iid = self.rec_tree.insert(\"\", \"end\", values=row, tags=(\"found\",))\n                        if not isinstance(getattr(self, \"rec_found_files\", None), dict):\n                            self.rec_found_files = {}\n                        self.rec_found_files[iid] = entry\n                    except Exception:\n                        pass\n                elif msg_type == \"progress_label\" and hasattr(self, \"raw_progress_label\"):\n                    self.raw_progress_label.config(text=str(payload)[:200])\n                elif msg_type == \"log_line\":\n                    self._append_log_line(str(payload))\n        except _queue_module.Empty:\n            pass\n        self._on_rec_select()\n    def _prep_drive_scan_progress_ui(self):\n        self._recovery_reset_ui_batch()\n        if hasattr(self, \"raw_progress_bar\"):\n            try:\n                self.raw_progress_bar.stop()\n            except Exception:\n                pass\n            self.raw_progress_bar.config(mode=\"indeterminate\")\n            self.raw_progress_bar.start(10)\n        if hasattr(self, \"raw_progress_var\"):\n            self.raw_progress_var.set(0)\n\n    def _prep_raw_scan_progress_ui(self):\n        if hasattr(self, \"raw_progress_bar\"):\n            try:\n                self.raw_progress_bar.stop()\n            except Exception:\n                pass\n            self.raw_progress_bar.config(mode=\"indeterminate\")\n            try:\n                self.raw_progress_bar.start(5)\n            except Exception:\n                pass\n        if hasattr(self, \"raw_progress_var\"):\n            self.raw_progress_var.set(0)\n\n    def _on_rec_select(self, event=None):\n        total = len(self.rec_tree.get_children()) if hasattr(self, \"rec_tree\") else 0\n        sel = len(self.rec_tree.selection()) if hasattr(self, \"rec_tree\") else 0\n        if hasattr(self, \"rec_stats_label\"):\n            self.rec_stats_label.config(text=f\"{total:,} files | {sel} selected\")\n\n    def _make_recovery_progress_callback(self):\n        def cb(msg):\n            self._raw_recovery_progress(msg)\n            m = re.match(r\"Pass \\d+: recovered (.+)\", msg, re.I)\n            if m and hasattr(self, \"rec_tree\"):\n                filename = m.group(1).strip()\n                ext = os.path.splitext(filename)[1].lstrip(\".\").upper() or \"?\"\n                row = (filename, ext, \"\u2014\", \"Recovered \u2014 verifying...\", \"Raw Scan\", \"--\")\n\n                def _ins(r=row, fn=filename):\n                    iid = self.rec_tree.insert(\"\", \"end\", values=r, tags=(\"found\",))\n                    self.rec_found_files[iid] = {\"kind\": \"photorec_live\", \"path\": fn, \"filename\": fn}\n\n                self.after(0, _ins)\n        return cb\n\n    def _clear_recovery_progress_log(self):\n        if hasattr(self, \"raw_progress_log\"):\n            try:\n                self.raw_progress_log.config(state=\"normal\")\n                self.raw_progress_log.delete(\"1.0\", \"end\")\n                self.raw_progress_log.config(state=\"disabled\")\n            except Exception:\n                pass\n\n    def _set_recovery_scan_mode(self, text, fg=None):\n        if hasattr(self, \"scan_mode_label\"):\n            self.scan_mode_label.config(text=text, fg=fg or C[\"accent4\"])\n\n    def _update_rec_stats(self):\n        if not hasattr(self, \"rec_stats_label\"):\n            return\n        n = len(self.rec_tree.get_children()) if hasattr(self, \"rec_tree\") else 0\n        sel = len(self.rec_tree.selection()) if hasattr(self, \"rec_tree\") else 0\n        self.rec_stats_label.config(text=f\"{n:,} files | {sel:,} selected\")\n\n    def _clear_recovery_results(self):\n        if hasattr(self, \"rec_tree\"):\n            self.rec_tree.delete(*self.rec_tree.get_children())\n        self.rec_found_files = {}\n        if hasattr(self, \"raw_progress_var\"):\n            self.raw_progress_var.set(0)\n        if hasattr(self, \"raw_progress_label\"):\n            self.raw_progress_label.config(text=\"List saaf kar di gayi.\")\n        self._update_rec_stats()\n\n    def _raw_limit_bytes(self):\n        try:\n            raw_value = (self.raw_scan_mb.get() or \"\").strip()\n            if not raw_value:\n                return None\n            mb = int(raw_value)\n            if mb &lt;= 0:\n                return None\n            return mb * 1024 * 1024\n        except Exception:\n            return None\n\n    def _raw_file_types_from_entry(self):\n        mapping = {\n            \"JPG\": \"JPG\", \"JPEG\": \"JPG\",\n            \"PDF\": \"PDF\",\n            \"MP4\": \"MP4\", \"M4V\": \"MP4\", \"MOV\": \"MP4\",\n            \"ZIP\": \"ZIP\", \"DOCX\": \"ZIP\", \"XLSX\": \"ZIP\", \"PPTX\": \"ZIP\",\n            \"EXE\": \"EXE\",\n        }\n        types = []\n        for part in self.rec_ext.get().split(\",\"):\n            key = part.strip().strip(\".\").upper()\n            if key in mapping and mapping[key] not in types:\n                types.append(mapping[key])\n        return types or list(SIGNATURES.keys())\n\n    def _insert_raw_results(self, disk_path, results):\n        self.rec_tree.delete(*self.rec_tree.get_children())\n        self.rec_found_files = {}\n        for counter, item in enumerate(results, start=1):\n            file_type = item[\"file_type\"]\n            ext = item.get(\"extension\") or SIGNATURES.get(file_type, {}).get(\"ext\", \"\")\n            offset = item[\"offset\"]\n            display_name = f\"{file_type}_{counter:04d}{ext}\"\n            max_sz = SIGNATURES.get(file_type, {}).get(\"max_size\", 0)\n            est_size = f\"~{_human_size(max(max_sz // 8, SECTOR_SIZE))} est.\" if max_sz else \"\u2014\"\n            conf = str(item.get(\"confidence\", \"medium\"))\n            location = f\"Sector {item['sector']:,}  |  {conf.title()}\"\n            iid = self.rec_tree.insert(\"\", \"end\", values=(\n                display_name, file_type, est_size,\n                \"Found \u2014 Recover dabao \u25b6\", location, \"--\"), tags=(\"found\",))\n            self.rec_found_files[iid] = {\n                \"kind\": \"raw\",\n                \"disk_path\": disk_path,\n                \"offset\": offset,\n                \"file_type\": file_type,\n                \"display_name\": display_name,\n            }\n        self.after(0, self._on_rec_select)\n\n    def _raw_recovery_progress(self, msg):\n        self._check_recovery_control()\n        def _do(m=msg):\n            display = m if len(m) &lt;= 140 else (m[:137] + \"...\")\n            if hasattr(self, \"raw_progress_label\"):\n                self.raw_progress_label.config(text=display)\n            if hasattr(self, \"raw_progress_log\"):\n                try:\n                    self.raw_progress_log.config(state=\"normal\")\n                    self.raw_progress_log.insert(\"end\", self._fix_text(m) + \"\\n\")\n                    if float(self.raw_progress_log.index(\"end-1c\").split(\".\")[0]) &gt; 200:\n                        self.raw_progress_log.delete(\"1.0\", \"50.0\")\n                    self.raw_progress_log.see(\"end\")\n                    self.raw_progress_log.config(state=\"disabled\")\n                except Exception:\n                    pass\n            if hasattr(self, \"raw_progress_var\"):\n                pct = None\n                match = re.search(r\"Pass\\s+([12])\\s*:\\s*(\\d{1,3})%\", m, re.I)\n                if match:\n                    pass_num = int(match.group(1))\n                    pass_pct = max(0, min(100, int(match.group(2))))\n                    pct = (pass_pct * 0.45) if pass_num == 1 else 45 + (pass_pct * 0.45)\n                else:\n                    generic = re.search(r\"(\\d{1,3})%\\s*complete\", m, re.I)\n                    if generic:\n                        pct = max(0, min(100, int(generic.group(1))))\n                if pct is None:\n                    m2 = re.search(r\"(\\d{1,3})%\\s*complete\", m, re.I)\n                    if m2:\n                        pct = max(0, min(100, int(m2.group(1))))\n                if pct is None and \"AUTO 1/4\" in m:\n                    pct = 5\n                elif pct is None and \"AUTO 2/4\" in m:\n                    pct = 20\n                elif pct is None and \"AUTO 3/4\" in m:\n                    pct = max(float(self.raw_progress_var.get()), 25)\n                elif pct is None and \"AUTO 4/4\" in m:\n                    pct = 95\n                elif pct is None and (\"complete\" in m.lower() or \"done\" in m.lower()):\n                    pct = 100\n                elif pct is None and (\"start\" in m.lower() or \"start ho\" in m.lower()):\n                    pct = 1\n                if pct is not None and hasattr(self, \"raw_progress_bar\"):\n                    try:\n                        self.raw_progress_bar.stop()\n                    except Exception:\n                        pass\n                    self.raw_progress_bar.config(mode=\"determinate\")\n                    self.raw_progress_var.set(max(0, min(100, pct)))\n                elif hasattr(self, \"raw_progress_bar\"):\n                    try:\n                        self.raw_progress_bar.config(mode=\"indeterminate\")\n                        self.raw_progress_bar.start(5)\n                    except Exception:\n                        pass\n        self.after(0, _do)\n\n    def _start_raw_signature_scan(self):\n        disk_path = self._raw_disk_path()\n        self._update_raw_source_badge()\n        if not self._ensure_admin_for_raw_recovery(disk_path):\n            return\n        limit = self._raw_limit_bytes()\n        file_types = self._raw_file_types_from_entry()\n        limit_text = \"FULL DISK\" if limit is None else self._fmt_size(limit)\n        if not messagebox.askyesno(\n            \"Raw Signature Scan\",\n            f\"Raw disk scan start karein?\\n\\n\"\n            f\"Disk: {disk_path}\\n\"\n            f\"Limit: {limit_text}\\n\"\n            f\"Types: {', '.join(file_types)}\\n\\n\"\n            \"Yeh read-only scan hai, lekin time lag sakta hai.\"\n        ):\n            return\n        self.rec_tree.delete(*self.rec_tree.get_children())\n        self.rec_found_files = {}\n        self._set_recovery_scan_mode(\"Mode: Zone B \u2014 Raw Sector Recovery (Admin)\", C[\"warning\"])\n        self._clear_recovery_progress_log()\n        self._prep_raw_scan_progress_ui()\n        self._reset_raw_progress(\"Raw signature scan start ho raha hai...\")\n        try:\n            self._begin_recovery_operation(\"Raw signature scan start ho raha hai...\")\n        except Exception as e:\n            messagebox.showwarning(\"Recovery Busy\", str(e))\n            return\n        if not self._hdd_action_submit(\"raw_signature_scan\", self._do_raw_signature_scan, disk_path, limit, file_types):\n            self._set_status(\"Recovery action already running; wait for completion.\", C[\"warning\"])\n\n    def _do_raw_signature_scan(self, disk_path, limit, file_types):\n        try:\n            results = scan_disk_for_files(\n                disk_path,\n                max_bytes=limit,\n                file_types=file_types,\n                progress_callback=self._make_recovery_progress_callback(),\n            )\n\n            def _populate():\n                self._insert_raw_results(disk_path, results)\n                self._set_status(f\"Raw scan complete: {len(results)} signatures mile\", C[\"success\"])\n\n            self.after(0, _populate)\n        except InterruptedError as e:\n            msg = str(e)\n            self.after(0, lambda msg=msg: self._set_status(msg, C[\"warning\"]))\n        except Exception as e:\n            err = str(e)\n            self.after(0, lambda err=err: self._set_status(\"Raw scan failed: \" + err, C[\"error\"]))\n            self.after(0, lambda err=err: messagebox.showerror(\"Raw Scan Error\", err))\n        finally:\n            self.after(0, self._finish_recovery_operation)\n\n    def _create_img_dialog(self):\n        disk_path = self._raw_disk_path()\n        self._update_raw_source_badge()\n        if not self._ensure_admin_for_raw_recovery(disk_path):\n            return\n        limit = self._raw_limit_bytes()\n        img_path = filedialog.asksaveasfilename(\n            title=\"IMG file save location\",\n            defaultextension=\".img\",\n            filetypes=[(\"Disk image\", \"*.img\"), (\"All files\", \"*.*\")]\n        )\n        if not img_path:\n            return\n        limit_text = \"FULL DISK\" if limit is None else self._fmt_size(limit)\n        if not messagebox.askyesno(\n            \"Create Disk Image\",\n            f\"IMG backup banani hai?\\n\\nDisk: {disk_path}\\nOutput: {img_path}\\nSize: {limit_text}\\n\\n\"\n            \"Note: Full disk image bahut badi ho sakti hai.\"\n        ):\n            return\n        self._reset_raw_progress(\"IMG creation start ho rahi hai...\")\n        try:\n            self._begin_recovery_operation(\"IMG creation start ho rahi hai...\")\n        except Exception as e:\n            messagebox.showwarning(\"Recovery Busy\", str(e))\n            return\n        if not self._hdd_action_submit(\"raw_create_img\", self._do_create_img, disk_path, img_path, limit):\n            self._set_status(\"Recovery action already running; wait for completion.\", C[\"warning\"])\n\n    def _do_create_img(self, disk_path, img_path, limit):\n        try:\n            result = create_disk_image(disk_path, img_path, max_bytes=limit, progress_callback=self._raw_recovery_progress)\n            self.after(0, lambda: self._set_status(f\"IMG complete: {self._fmt_size(result['bytes'])}\", C[\"success\"]))\n            self.after(0, lambda: messagebox.showinfo(\"IMG Complete\", f\"IMG ban gayi:\\n{result['img_path']}\\n\\nSize: {self._fmt_size(result['bytes'])}\"))\n        except InterruptedError as e:\n            msg = str(e)\n            self.after(0, lambda msg=msg: self._set_status(msg, C[\"warning\"]))\n        except Exception as e:\n            err = str(e)\n            self.after(0, lambda err=err: self._set_status(\"IMG failed: \" + err, C[\"error\"]))\n            self.after(0, lambda err=err: messagebox.showerror(\"IMG Error\", err))\n        finally:\n            self.after(0, self._finish_recovery_operation)\n\n    def _start_auto_raw_recovery(self):\n        disk_path = self._raw_disk_path()\n        self._update_raw_source_badge()\n        if not self._ensure_admin_for_raw_recovery(disk_path):\n            return\n        limit = self._raw_limit_bytes()\n        file_types = self._raw_file_types_from_entry()\n        output_dir = filedialog.askdirectory(title=\"Recovered data save karne ke liye folder select karo\")\n        if not output_dir:\n            return\n        limit_text = \"FULL DISK\" if limit is None else self._fmt_size(limit)\n        if not messagebox.askyesno(\n            \"AUTO All Process\",\n            f\"Auto recovery workflow start karein?\\n\\n\"\n            f\"1. IMG backup banegi\\n\"\n            f\"2. Raw signature scan hoga\\n\"\n            f\"3. Found files auto extract hongi\\n\"\n            f\"4. Real hex preview show hoga\\n\\n\"\n            f\"Disk: {disk_path}\\n\"\n            f\"Scan/Image Size: {limit_text}\\n\"\n            f\"Types: {', '.join(file_types)}\\n\"\n            f\"Output: {output_dir}\\n\\n\"\n            \"Note: Large scan size se time aur storage dono lagenge.\"\n        ):\n            return\n        self.rec_tree.delete(*self.rec_tree.get_children())\n        self.rec_found_files = {}\n        self._set_recovery_scan_mode(\"Mode: Zone B \u2014 Raw Sector Recovery (Admin)\", C[\"warning\"])\n        self._clear_recovery_progress_log()\n        self._reset_raw_progress(\"AUTO recovery start ho rahi hai...\")\n        try:\n            self._begin_recovery_operation(\"AUTO recovery start ho rahi hai...\")\n        except Exception as e:\n            messagebox.showwarning(\"Recovery Busy\", str(e))\n            return\n        if not self._hdd_action_submit(\"auto_raw_recovery\", self._do_auto_raw_recovery, disk_path, limit, file_types, output_dir):\n            self._set_status(\"Recovery action already running; wait for completion.\", C[\"warning\"])\n\n    def _do_auto_raw_recovery(self, disk_path, limit, file_types, output_dir):\n        recovered = []\n        warnings = []\n        img_result = None\n        try:\n            stamp = datetime.datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n            img_path = os.path.join(output_dir, f\"raw_backup_{stamp}.img\")\n            self._raw_recovery_progress(\"AUTO 1/4: IMG backup ban rahi hai...\")\n            img_result = create_disk_image(disk_path, img_path, max_bytes=limit, progress_callback=self._raw_recovery_progress)\n\n            source_for_scan = img_result[\"img_path\"] if img_result and img_result.get(\"bytes\", 0) &gt; 0 else disk_path\n            self._raw_recovery_progress(\"AUTO 2/4: IMG import/source ready ho gaya...\")\n            self.after(0, lambda src=source_for_scan: self.raw_disk_var.set(src))\n\n            self._raw_recovery_progress(\"AUTO 3/4: PhotoRec multi-pass recovery chal rahi hai...\")\n            photo_result = multi_pass_recovery(\n                source_for_scan, output_dir,\n                progress_callback=self._make_recovery_progress_callback())\n            recovered = photo_result[\"files\"]\n\n            self._raw_recovery_progress(\"AUTO 4/4: Real hex preview read ho raha hai...\")\n            first_sector = recovered[0][\"offset\"] // SECTOR_SIZE if recovered else 0\n            hex_text = raw_hex_viewer(first_sector, disk_path=source_for_scan)\n\n            def _finish():\n                self._set_status(f\"AUTO complete: {len(recovered)} files recovered\", C[\"success\"])\n                file_map = {os.path.basename(f[\"path\"]): f for f in recovered}\n                seen_basenames = set()\n                for iid in list(self.rec_tree.get_children()):\n                    vals = list(self.rec_tree.item(iid, \"values\"))\n                    if not vals:\n                        continue\n                    bn = vals[0]\n                    seen_basenames.add(bn)\n                    if bn in file_map:\n                        item = file_map[bn]\n                        loc = item[\"path\"][-60:] if len(item[\"path\"]) &gt; 60 else item[\"path\"]\n                        self.rec_tree.item(iid, values=(\n                            bn, item[\"file_type\"], self._fmt_size(item[\"bytes\"]),\n                            \"\u2705 Recovered\", loc, \"--\"), tags=(\"recovered\",))\n                        self.rec_found_files[iid] = item[\"path\"]\n                for item in recovered:\n                    bn = os.path.basename(item[\"path\"])\n                    if bn in seen_basenames:\n                        continue\n                    loc = item[\"path\"][-60:] if len(item[\"path\"]) &gt; 60 else item[\"path\"]\n                    iid = self.rec_tree.insert(\"\", \"end\", values=(\n                        bn, item[\"file_type\"], self._fmt_size(item[\"bytes\"]),\n                        \"\u2705 Recovered\", loc, \"--\"), tags=(\"recovered\",))\n                    self.rec_found_files[iid] = item[\"path\"]\n                self._on_rec_select()\n                self._show_auto_recovery_result(output_dir, img_result, photo_result, recovered, warnings, hex_text)\n\n            self.after(0, _finish)\n        except InterruptedError as e:\n            msg = str(e)\n            self.after(0, lambda msg=msg: self._set_status(msg, C[\"warning\"]))\n        except Exception as e:\n            err = str(e)\n            self.after(0, lambda err=err: self._set_status(\"AUTO recovery failed: \" + err, C[\"error\"]))\n            self.after(0, lambda err=err: messagebox.showerror(\"AUTO Recovery Error\", err))\n        finally:\n            self.after(0, self._finish_recovery_operation)\n\n    def _show_auto_recovery_result(self, output_dir, img_result, results, recovered, warnings, hex_text):\n        win = tk.Toplevel(self)\n        win.title(\"AUTO Recovery Result\")\n        win.geometry(\"1100x720\")\n        win.configure(bg=C[\"bg\"])\n        if isinstance(results, dict):\n            found_count = len(results.get(\"files\", []))\n            recup_dir = results.get(\"recup_dir\", output_dir)\n            block_size = results.get(\"block_size\", \"N/A\")\n        else:\n            found_count = len(results)\n            recup_dir = output_dir\n            block_size = \"N/A\"\n        summary = (\n            f\"AUTO RECOVERY COMPLETE\\n\"\n            f\"Output Folder: {output_dir}\\n\"\n            f\"recup_dir: {recup_dir}\\n\"\n            f\"Block size: {block_size}\\n\"\n            f\"IMG: {(img_result or {}).get('img_path', 'N/A')}\\n\"\n            f\"IMG Size: {self._fmt_size((img_result or {}).get('bytes', 0))}\\n\"\n            f\"Signatures/Files Found: {found_count}\\n\"\n            f\"Files Recovered: {len(recovered)}\\n\"\n            f\"Warnings: {len(warnings)}\\n\"\n            f\"\\nRecovered Files:\\n\"\n        )\n        if recovered:\n            summary += \"\\n\".join(f\"- {item['path']} ({self._fmt_size(item['bytes'])})\" for item in recovered[:80])\n            if len(recovered) &gt; 80:\n                summary += f\"\\n... aur {len(recovered) - 80} files\"\n        else:\n            summary += \"Koi file extract nahi hui.\"\n        if warnings:\n            summary += \"\\n\\nWarnings:\\n\" + \"\\n\".join(warnings[:40])\n        summary += \"\\n\\nREAL HEX PREVIEW:\\n\" + hex_text\n        viewer = scrolledtext.ScrolledText(win, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], wrap=\"none\")\n        viewer.pack(fill=\"both\", expand=True, padx=10, pady=10)\n        viewer.insert(\"1.0\", summary)\n        viewer.config(state=\"disabled\")\n        messagebox.showinfo(\n            \"AUTO Recovery Complete\",\n            f\"{len(recovered)} files recover hui.\\n\\nOutput folder:\\n{output_dir}\\n\\nDetails result window me show ho rahe hain.\"\n        )\n\n    def _select_img_source(self):\n        img_path = filedialog.askopenfilename(\n            title=\"IMG/DD/raw disk image import karo\",\n            filetypes=[(\"Disk images\", \"*.img *.dd *.raw *.bin\"), (\"All files\", \"*.*\")]\n        )\n        if not img_path:\n            return\n        self.raw_disk_var.set(img_path)\n        try:\n            values = list(self.raw_disk_combo.cget(\"values\"))\n            if img_path not in values:\n                values.insert(0, img_path)\n                self.raw_disk_combo.configure(values=values)\n        except Exception:\n            pass\n        self._update_raw_source_badge()\n        self._set_status(f\"IMG source selected: {img_path}\", C[\"success\"])\n\n    def _export_hex_sector_img(self):\n        try:\n            sector = int((self.raw_sector_num.get() or \"0\").strip())\n            start_offset = sector * SECTOR_SIZE\n            limit = self._raw_limit_bytes()\n            disk_path = self._raw_disk_path()\n            self._update_raw_source_badge()\n            if not self._ensure_admin_for_raw_recovery(disk_path):\n                return\n        except Exception as e:\n            messagebox.showerror(\"Sector IMG Error\", str(e))\n            return\n        img_path = filedialog.asksaveasfilename(\n            title=\"Sector range ko IMG me save karo\",\n            defaultextension=\".img\",\n            filetypes=[(\"Disk image\", \"*.img\"), (\"All files\", \"*.*\")]\n        )\n        if not img_path:\n            return\n        size_text = \"source ke end tak\" if limit is None else self._fmt_size(limit)\n        if not messagebox.askyesno(\n            \"Sector to IMG\",\n            f\"Hex/Sector range ko IMG me export karein?\\n\\n\"\n            f\"Source: {disk_path}\\n\"\n            f\"Start sector: {sector}\\n\"\n            f\"Start offset: 0x{start_offset:X}\\n\"\n            f\"Size: {size_text}\\n\"\n            f\"Output: {img_path}\\n\\n\"\n            \"Is IMG ko Import IMG button se scan kar sakte hain.\"\n        ):\n            return\n        self._reset_raw_progress(\"Sector IMG export start ho raha hai...\")\n        try:\n            self._begin_recovery_operation(\"Sector IMG export start ho raha hai...\")\n        except Exception as e:\n            messagebox.showwarning(\"Recovery Busy\", str(e))\n            return\n        if not self._hdd_action_submit(\"sector_img_export\", self._do_export_hex_sector_img, disk_path, img_path, start_offset, limit):\n            self._set_status(\"Recovery action already running; wait for completion.\", C[\"warning\"])\n\n    def _do_export_hex_sector_img(self, disk_path, img_path, start_offset, limit):\n        try:\n            result = copy_disk_range_to_img(disk_path, img_path, start_offset=start_offset, max_bytes=limit, progress_callback=self._raw_recovery_progress)\n            def _finish():\n                self._set_status(f\"Sector IMG complete: {self._fmt_size(result['bytes'])}\", C[\"success\"])\n                self.raw_disk_var.set(result[\"img_path\"])\n                messagebox.showinfo(\n                    \"Sector IMG Complete\",\n                    f\"IMG ban gayi:\\n{result['img_path']}\\n\\n\"\n                    f\"Size: {self._fmt_size(result['bytes'])}\\n\\n\"\n                    \"Ab yahi IMG source select ho gayi hai; PhotoRec Deep Scan/AUTO se scan kar sakte hain.\"\n                )\n            self.after(0, _finish)\n        except InterruptedError as e:\n            msg = str(e)\n            self.after(0, lambda msg=msg: self._set_status(msg, C[\"warning\"]))\n        except Exception as e:\n            err = str(e)\n            self.after(0, lambda err=err: self._set_status(\"Sector IMG failed: \" + err, C[\"error\"]))\n            self.after(0, lambda err=err: messagebox.showerror(\"Sector IMG Error\", err))\n        finally:\n            self.after(0, self._finish_recovery_operation)\n\n    def _candidate_dmde_paths(self):\n        candidates = []\n        env_path = os.environ.get(\"GODAWARI_DMDE_PATH\", \"\").strip().strip('\"')\n        if env_path:\n            candidates.append(env_path)\n        for exe_name in (\"dmde.exe\", \"dmde64.exe\", \"dmde32.exe\"):\n            found = shutil.which(exe_name)\n            if found:\n                candidates.append(found)\n        base_dirs = [\n            os.getcwd(),\n            os.path.dirname(os.path.abspath(sys.argv[0])),\n            os.environ.get(\"ProgramFiles\", \"\"),\n            os.environ.get(\"ProgramFiles(x86)\", \"\"),\n            os.environ.get(\"LOCALAPPDATA\", \"\"),\n        ]\n        rels = [\n            \"DMDE\\\\dmde.exe\",\n            \"DMDE\\\\dmde64.exe\",\n            \"dmde\\\\dmde.exe\",\n            \"tools\\\\dmde\\\\dmde.exe\",\n            \"assets\\\\tools\\\\dmde\\\\dmde.exe\",\n        ]\n        for base in base_dirs:\n            if not base:\n                continue\n            for rel in rels:\n                candidates.append(os.path.join(base, rel))\n        seen = set()\n        result = []\n        for path in candidates:\n            norm = os.path.normcase(os.path.abspath(path))\n            if norm in seen:\n                continue\n            seen.add(norm)\n            if os.path.isfile(path):\n                result.append(path)\n        return result\n\n    def _find_dmde_exe(self):\n        candidates = self._candidate_dmde_paths()\n        if candidates:\n            return candidates[0]\n        return \"\"\n\n    def _ask_dmde_exe(self):\n        exe = filedialog.askopenfilename(\n            title=\"DMDE executable select karo (dmde.exe)\",\n            filetypes=[(\"DMDE executable\", \"dmde*.exe\"), (\"Executable\", \"*.exe\"), (\"All files\", \"*.*\")]\n        )\n        if exe and os.path.isfile(exe):\n            os.environ[\"GODAWARI_DMDE_PATH\"] = exe\n            return exe\n        return \"\"\n\n    def _start_dmde_recovery(self):\n        disk_path = self._raw_disk_path()\n        self._update_raw_source_badge()\n        if not self._ensure_admin_for_raw_recovery(disk_path):\n            return\n\n        dmde_exe = self._find_dmde_exe()\n        if not dmde_exe:\n            self._set_status(\"DMDE available nahi mila. Auto-detect only mode active hai.\", C[\"warning\"])\n            messagebox.showinfo(\n                \"DMDE Not Available\",\n                \"DMDE executable auto-detect nahi hua.\\n\\n\"\n                \"Ab yeh tool manual .exe browse nahi maangega.\\n\"\n                \"Agar DMDE use karna ho to usse standard location me install/put karo,\\n\"\n                \"ya GODAWARI_DMDE_PATH env var set karo.\"\n            )\n            return\n\n        source_kind = \"IMG/file source\" if os.path.isfile(disk_path) else \"raw disk/device\"\n        if not messagebox.askyesno(\n            \"DMDE Recovery\",\n            f\"DMDE recovery console launch karein?\\n\\n\"\n            f\"DMDE: {dmde_exe}\\n\"\n            f\"Source: {disk_path}\\n\"\n            f\"Type: {source_kind}\\n\\n\"\n            \"Forensic safety:\\n\"\n            \"- Source disk par kuch write mat karein.\\n\"\n            \"- Recovered data hamesha dusre drive/folder me save karein.\\n\"\n            \"- DMDE ke write/repair options sirf verified clone/IMG par use karein.\"\n        ):\n            return\n\n        self._reset_raw_progress(\"DMDE Recovery launch ho raha hai...\")\n        try:\n            self._begin_recovery_operation(\"DMDE Recovery launch ho raha hai...\")\n        except Exception as e:\n            messagebox.showwarning(\"Recovery Busy\", str(e))\n            return\n        if not self._hdd_action_submit(\"dmde_recovery\", self._do_dmde_recovery, dmde_exe, disk_path):\n            self._set_status(\"Recovery action already running; wait for completion.\", C[\"warning\"])\n\n    def _do_dmde_recovery(self, dmde_exe, disk_path):\n        proc = None\n        try:\n            report_dir = getattr(self, \"backup_dir\", os.getcwd())\n            os.makedirs(report_dir, exist_ok=True)\n            report_path = os.path.join(report_dir, \"dmde_recovery_launch.log\")\n            cmd = [dmde_exe, disk_path]\n            self._raw_recovery_progress(\"DMDE subprocess start: \" + subprocess.list2cmdline(cmd))\n            proc = subprocess.Popen(\n                cmd,\n                cwd=os.path.dirname(dmde_exe) or None,\n                stdout=subprocess.PIPE,\n                stderr=subprocess.STDOUT,\n                text=True,\n                encoding=\"utf-8\",\n                errors=\"replace\",\n            )\n            self._dmde_proc = proc\n            started = datetime.datetime.now().isoformat(timespec=\"seconds\")\n            with open(report_path, \"a\", encoding=\"utf-8\") as f:\n                f.write(f\"[{started}] DMDE launched\\n\")\n                f.write(\"Command: \" + subprocess.list2cmdline(cmd) + \"\\n\")\n                f.write(\"Source: \" + disk_path + \"\\n\")\n            self._audit_event(\"dmde_recovery_started\", {\n                \"dmde\": dmde_exe,\n                \"source\": disk_path,\n                \"pid\": proc.pid,\n                \"report\": report_path,\n            })\n            self.after(0, lambda: self._set_status(f\"DMDE running (PID {proc.pid})\", C[\"success\"]))\n\n            output_tail = []\n            if proc.stdout:\n                while proc.poll() is None:\n                    line = proc.stdout.readline()\n                    if line:\n                        clean = line.strip()\n                        if clean:\n                            output_tail.append(clean)\n                            output_tail = output_tail[-40:]\n                            self._raw_recovery_progress(\"DMDE: \" + clean[:180])\n                    else:\n                        time.sleep(0.25)\n                for line in proc.stdout.readlines():\n                    clean = line.strip()\n                    if clean:\n                        output_tail.append(clean)\n            rc = proc.wait(timeout=5)\n            ended = datetime.datetime.now().isoformat(timespec=\"seconds\")\n            with open(report_path, \"a\", encoding=\"utf-8\") as f:\n                f.write(f\"[{ended}] DMDE exited rc={rc}\\n\")\n                if output_tail:\n                    f.write(\"Output tail:\\n\" + \"\\n\".join(output_tail[-40:]) + \"\\n\")\n                f.write(\"\\n\")\n            self._audit_event(\"dmde_recovery_finished\", {\"rc\": rc, \"report\": report_path})\n            self.after(0, lambda rc=rc, report_path=report_path: self._set_status(f\"DMDE closed (rc={rc}) - log saved\", C[\"success\"] if rc == 0 else C[\"warning\"]))\n            self.after(0, lambda report_path=report_path: messagebox.showinfo(\"DMDE Recovery\", f\"DMDE session closed.\\n\\nLog:\\n{report_path}\"))\n        except FileNotFoundError:\n            self.after(0, lambda: messagebox.showerror(\"DMDE Missing\", \"DMDE executable nahi mila. dmde.exe path dobara select karein.\"))\n        except InterruptedError as e:\n            msg = str(e)\n            self.after(0, lambda msg=msg: self._set_status(msg, C[\"warning\"]))\n        except Exception as e:\n            err = str(e)\n            self.after(0, lambda err=err: self._set_status(\"DMDE launch failed: \" + err, C[\"error\"]))\n            self.after(0, lambda err=err: messagebox.showerror(\"DMDE Recovery Error\", err))\n        finally:\n            if getattr(self, \"_dmde_proc\", None) is proc:\n                self._dmde_proc = None\n            self.after(0, self._finish_recovery_operation)\n\n    def _start_photorec_deep_scan(self):\n        disk_path = self._raw_disk_path()\n        self._update_raw_source_badge()\n        if not self._ensure_admin_for_raw_recovery(disk_path):\n            return\n        output_dir = filedialog.askdirectory(title=\"PhotoRec recovered output folder select karo\")\n        if not output_dir:\n            return\n        if not messagebox.askyesno(\n            \"PhotoRec Deep Scan\",\n            f\"PhotoRec-style deep scan start karein?\\n\\n\"\n            f\"Source: {disk_path}\\n\"\n            f\"Output: {output_dir}\\\\recup_dir.N\\n\\n\"\n            \"Process:\\n\"\n            \"1. Auto block/cluster size detect\\n\"\n            \"2. Pass 1 block-aligned carving\\n\"\n            \"3. Pass 2 unaligned signature scan\\n\"\n            \"4. Validation + best-effort fragment reassembly\\n\\n\"\n            \"No size limit rakha gaya hai, isliye full disk scan bahut time le sakta hai.\"\n        ):\n            return\n        self.rec_tree.delete(*self.rec_tree.get_children())\n        self.rec_found_files = {}\n        self._set_recovery_scan_mode(\"Mode: Zone B \u2014 Raw Sector Recovery (Admin)\", C[\"warning\"])\n        self._clear_recovery_progress_log()\n        self._prep_raw_scan_progress_ui()\n        self._reset_raw_progress(\"PhotoRec Deep Scan start ho rahi hai...\")\n        try:\n            self._begin_recovery_operation(\"PhotoRec Deep Scan start ho rahi hai...\")\n        except Exception as e:\n            messagebox.showwarning(\"Recovery Busy\", str(e))\n            return\n        if not self._hdd_action_submit(\"photorec_deep_scan\", self._do_photorec_deep_scan, disk_path, output_dir):\n            self._set_status(\"Recovery action already running; wait for completion.\", C[\"warning\"])\n\n    def _do_photorec_deep_scan(self, disk_path, output_dir):\n        try:\n            result = multi_pass_recovery(\n                disk_path, output_dir,\n                progress_callback=self._make_recovery_progress_callback())\n            def _finish():\n                file_map = {os.path.basename(f[\"path\"]): f for f in result.get(\"files\", [])}\n                seen_basenames = set()\n                for iid in list(self.rec_tree.get_children()):\n                    vals = list(self.rec_tree.item(iid, \"values\"))\n                    if not vals:\n                        continue\n                    bn = vals[0]\n                    seen_basenames.add(bn)\n                    if bn in file_map:\n                        item = file_map[bn]\n                        loc = item[\"path\"][-60:] if len(item[\"path\"]) &gt; 60 else item[\"path\"]\n                        self.rec_tree.item(iid, values=(\n                            bn, item[\"file_type\"], self._fmt_size(item[\"bytes\"]),\n                            \"\u2705 Recovered\", loc, \"--\"), tags=(\"recovered\",))\n                        self.rec_found_files[iid] = item[\"path\"]\n                for item in result.get(\"files\", []):\n                    bn = os.path.basename(item[\"path\"])\n                    if bn in seen_basenames:\n                        continue\n                    loc = item[\"path\"][-60:] if len(item[\"path\"]) &gt; 60 else item[\"path\"]\n                    iid = self.rec_tree.insert(\"\", \"end\", values=(\n                        bn, item[\"file_type\"], self._fmt_size(item[\"bytes\"]),\n                        \"\u2705 Recovered\", loc, \"--\"), tags=(\"recovered\",))\n                    self.rec_found_files[iid] = item[\"path\"]\n                self._on_rec_select()\n                self._set_status(f\"PhotoRec scan complete: {len(result.get('files', []))} files\", C[\"success\"])\n                self._show_photorec_result(result)\n            self.after(0, _finish)\n        except InterruptedError as e:\n            msg = str(e)\n            self.after(0, lambda msg=msg: self._set_status(msg, C[\"warning\"]))\n        except Exception as e:\n            err = str(e)\n            self.after(0, lambda err=err: self._set_status(\"PhotoRec scan failed: \" + err, C[\"error\"]))\n            self.after(0, lambda err=err: messagebox.showerror(\"PhotoRec Deep Scan Error\", err))\n        finally:\n            self.after(0, self._finish_recovery_operation)\n\n    def _show_photorec_result(self, result):\n        win = tk.Toplevel(self)\n        win.title(\"PhotoRec Deep Scan Result\")\n        win.geometry(\"980x620\")\n        win.configure(bg=C[\"bg\"])\n        text = (\n            f\"PHOTOREC-STYLE DEEP SCAN COMPLETE\\n\"\n            f\"recup_dir: {result['recup_dir']}\\n\"\n            f\"Block size: {result['block_size']} bytes\\n\"\n            f\"Recovered files: {len(result['files'])}\\n\\n\"\n        )\n        for item in result[\"files\"][:300]:\n            text += f\"Pass {item['pass']} | 0x{item['offset']:X} | {item['file_type']} | {self._fmt_size(item['bytes'])} | {item['path']}\\n\"\n        if len(result[\"files\"]) &gt; 300:\n            text += f\"\\n... aur {len(result['files']) - 300} files tree me available hain.\"\n        viewer = scrolledtext.ScrolledText(win, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], wrap=\"none\")\n        viewer.pack(fill=\"both\", expand=True, padx=10, pady=10)\n        viewer.insert(\"1.0\", text)\n        viewer.config(state=\"disabled\")\n        messagebox.showinfo(\"PhotoRec Deep Scan\", f\"{len(result['files'])} files recover hui.\\n\\nFolder:\\n{result['recup_dir']}\")\n\n    def _show_raw_hex_dialog(self):\n        try:\n            sector = int((self.raw_sector_num.get() or \"0\").strip())\n            disk_path = self._raw_disk_path()\n            self._update_raw_source_badge()\n            if not self._ensure_admin_for_raw_recovery(disk_path):\n                return\n        except Exception as e:\n            messagebox.showerror(\"Hex Viewer Error\", str(e))\n            return\n        self._reset_raw_progress(f\"Hex viewer sector {sector} read ho raha hai...\")\n        try:\n            self._begin_recovery_operation(f\"Hex viewer sector {sector} read ho raha hai...\")\n        except Exception as e:\n            messagebox.showwarning(\"Recovery Busy\", str(e))\n            return\n        if not self._hdd_action_submit(\"raw_hex_view\", self._do_show_raw_hex_dialog, disk_path, sector):\n            self._set_status(\"Recovery action already running; wait for completion.\", C[\"warning\"])\n\n    def _do_show_raw_hex_dialog(self, disk_path, sector):\n        try:\n            self._raw_recovery_progress(f\"Hex viewer: reading {disk_path} sector {sector}\")\n            text = raw_hex_viewer(sector, disk_path=disk_path)\n            self.after(0, lambda: self._open_raw_hex_window(sector, text))\n            self.after(0, lambda: self._set_status(f\"Hex viewer ready: sector {sector}\", C[\"success\"]))\n        except InterruptedError as e:\n            msg = str(e)\n            self.after(0, lambda msg=msg: self._set_status(msg, C[\"warning\"]))\n        except Exception as e:\n            err = str(e)\n            self.after(0, lambda err=err: self._set_status(\"Hex viewer failed: \" + err, C[\"error\"]))\n            self.after(0, lambda err=err: messagebox.showerror(\"Hex Viewer Error\", err))\n        finally:\n            self.after(0, self._finish_recovery_operation)\n\n    def _open_raw_hex_window(self, sector, text):\n        win = tk.Toplevel(self)\n        win.title(f\"Raw Hex Viewer - Sector {sector}\")\n        win.geometry(\"980x620\")\n        win.configure(bg=C[\"bg\"])\n        viewer = scrolledtext.ScrolledText(win, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], wrap=\"none\")\n        viewer.pack(fill=\"both\", expand=True, padx=10, pady=10)\n        viewer.insert(\"1.0\", text)\n        viewer.config(state=\"disabled\")\n\n    def _start_file_recovery(self):\n        drive = self.rec_drive.get().replace(\"\\\\\", \"\").rstrip(\"\\\\\")\n        exts = [e.strip().lstrip(\".\") for e in self.rec_ext.get().split(\",\") if e.strip()]\n        if not drive or not exts:\n            messagebox.showwarning(\"Input\", \"Drive aur extensions fill karo.\")\n            return\n        if self._is_mobile_source(drive):\n            if not self._mobile_adb_available():\n                self._show_adb_help()\n                return\n            if not self._mobile_device_ready():\n                messagebox.showerror(\"Device Not Ready\", \"ADB mila, lekin phone connected/authorized nahi hai.\\nUSB debugging enable karke phone par Allow dabao, phir retry karo.\")\n                return\n        ext_str = \", \".join(exts)\n        if not messagebox.askyesno(\"File Search\",\n            f\"{'Mobile (ADB)' if self._is_mobile_source(drive) else f'Drive {drive}:'} pe yeh files dhundega:\\n{ext_str}\\n\\n\"\n            f\"Note: Yeh ZONE A scan hai \u2014 drive pe maujood accessible files dhundta hai.\\n\"\n            f\"Deleted files ke liye ZONE B \u2192 Raw Signature Scan use karo (Admin required).\\n\\nProceed?\"):\n            return\n        # Reset control flags\n        try:\n            self._begin_recovery_operation(f\"Searching {drive} for {ext_str}...\")\n        except Exception as e:\n            messagebox.showwarning(\"Recovery Busy\", str(e))\n            return\n        self._set_recovery_scan_mode(\"Mode: Zone A \u2014 File Search (Drive Scan)\", C[\"accent2\"])\n        self._clear_recovery_progress_log()\n        self._prep_drive_scan_progress_ui()\n        if hasattr(self, \"raw_progress_label\"):\n            self.raw_progress_label.config(text=f\"Searching {drive}: for {ext_str}...\")\n        if hasattr(self, \"raw_progress_var\"):\n            self.raw_progress_var.set(0)\n        # Update control buttons\n        if hasattr(self, \"_rec_stop_btn\"):\n            self._rec_stop_btn.config(state=\"normal\")\n        if hasattr(self, \"_rec_pause_btn\"):\n            self._rec_pause_btn.config(state=\"normal\", text=\"\u23f8 Pause\")\n        if not self._hdd_action_submit(\"file_search\", self._do_file_recovery, drive, exts):\n            self._set_status(\"Recovery action already running; wait for completion.\", C[\"warning\"])\n\n    def _stop_file_recovery(self):\n        # Set BOTH the legacy flag and the threading.Event so the background\n        # scan loop detects the stop signal at its very next check (&lt; 50 ms).\n        self._recovery_stop_flag = True\n        self._recovery_pause_flag = False\n        if hasattr(self, \"_scan_stop_event\"):\n            self._scan_stop_event.set()  # unblocks any time.sleep() pause too\n        self._set_status(\"\u23f9 Recovery roka ja raha hai...\", C[\"warning\"])\n        if hasattr(self, \"_rec_stop_btn\"):\n            self._rec_stop_btn.config(state=\"disabled\")\n        if hasattr(self, \"_rec_pause_btn\"):\n            self._rec_pause_btn.config(state=\"disabled\", text=\"\u23f8 Pause\")\n\n    def _pause_resume_file_recovery(self):\n        if not hasattr(self, \"_recovery_pause_flag\"):\n            return\n        self._recovery_pause_flag = not self._recovery_pause_flag\n        if self._recovery_pause_flag:\n            self._set_status(\"\u23f8 Recovery paused \u2014 Resume dabao jab taiyar ho\", C[\"warning\"])\n            if hasattr(self, \"_rec_pause_btn\"):\n                self._rec_pause_btn.config(text=\"\u25b6 Resume\")\n        else:\n            self._set_status(\"\u25b6 Recovery resume ho gayi...\", C[\"accent4\"])\n            if hasattr(self, \"_rec_pause_btn\"):\n                self._rec_pause_btn.config(text=\"\u23f8 Pause\")\n\n    def _do_file_recovery(self, drive, exts):\n        \"\"\"\n        Background thread worker for Zone-A file search.\n\n        ALL GUI updates go through self._ui_queue (via self._q*() helpers).\n        The main thread drains the queue every 50 ms in _poll_ui_queue().\n        This keeps the GUI fully responsive and the progress bar smooth.\n        \"\"\"\n        # \u2500\u2500 1. Reset UI on main thread \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        def _scan_start_ui():\n            try:\n                for i in self.rec_tree.get_children():\n                    self.rec_tree.delete(i)\n                self.rec_found_files = {}\n                self._recovery_reset_ui_batch()\n                self._on_rec_select()\n                if hasattr(self, \"raw_progress_log\"):\n                    self.raw_progress_log.config(state=\"normal\")\n                    self.raw_progress_log.delete(\"1.0\", \"end\")\n                    self.raw_progress_log.config(state=\"disabled\")\n                # Switch progress bar to indeterminate (animated bounce)\n                if hasattr(self, \"raw_progress_bar\"):\n                    try:\n                        self.raw_progress_bar.stop()\n                    except Exception:\n                        pass\n                    self.raw_progress_bar.config(mode=\"indeterminate\")\n                    self.raw_progress_bar.start(12)\n                if hasattr(self, \"raw_progress_label\"):\n                    self.raw_progress_label.config(text=f\"Scan shuru ho raha hai \u2014 {drive}:\\\\ ...\")\n            except Exception:\n                pass\n        self.after(0, _scan_start_ui)\n\n        # Clear the stop event so a previous stop does not block a fresh scan\n        self._scan_stop_event.clear()\n        self._recovery_stop_flag = False   # also reset the legacy flag\n        before_state = self._snapshot_resource_state() or {}\n\n        file_count   = 0\n        scanned      = 0\n        local_matches = []   # accumulate for checkpoint saves\n\n        try:\n            ext_set  = {(\".\" + e.lower().strip(\".\")) for e in exts if e.strip()}\n            mode_key = f\"search_{drive.lower()}\"\n\n            # \u2500\u2500 2. Resume checkpoint \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            cp = self._load_recovery_checkpoint(mode_key) or {}\n            cp_exts = set(cp.get(\"exts\", [])) if isinstance(cp, dict) else set()\n            resume_ok = (\n                bool(cp)\n                and cp.get(\"drive\", \"\").lower() == drive.lower()\n                and cp_exts == {e.lower().strip(\".\") for e in exts}\n            )\n            processed_dirs = set(cp.get(\"processed_dirs\", [])) if resume_ok else set()\n            saved_matches  = cp.get(\"matches\", []) if resume_ok else []\n\n            if resume_ok and saved_matches:\n                for p in saved_matches:\n                    if self._scan_stop_event.is_set():\n                        break\n                    try:\n                        nm  = os.path.basename(p)\n                        ex  = os.path.splitext(nm)[1].lstrip(\".\") or \"?\"\n                        sz  = self._fmt_size(os.path.getsize(p)) if os.path.exists(p) else \"?\"\n                        loc = p[-60:] if len(p) &gt; 60 else p\n                        row = (nm, ex, sz, \"Found \u2014 Recover dabao \u25b6\", loc, \"--\")\n                        # \u25b6 Queue the tree row \u2014 do NOT touch rec_tree from background thread\n                        self._q_tree_row(row, p)\n                        file_count += 1\n                        local_matches.append(p)\n                    except Exception:\n                        pass\n                self._q_log(f\"Resume checkpoint: {len(saved_matches)} previous matches loaded\")\n\n            # \u2500\u2500 3. Mobile or local drive scan \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            if self._is_mobile_source(drive):\n                mobile_paths = self._mobile_find_candidates(exts)\n                for p in mobile_paths:\n                    if self._scan_stop_event.is_set():\n                        break\n                    name = os.path.basename(p)\n                    ext  = os.path.splitext(name)[1].lstrip(\".\") or \"?\"\n                    loc  = p[-60:] if len(p) &gt; 60 else p\n                    row  = (name, ext, \"Mobile\", \"Found \u2014 Recover dabao \u25b6\", loc, \"--\")\n                    entry = {\"kind\": \"mobile\", \"path\": p}\n                    self._q_tree_row(row, entry)\n                    file_count += 1\n                    local_matches.append(p)\n\n                self._save_recovery_checkpoint(mode_key, {\n                    \"drive\": drive,\n                    \"exts\": [e.lower().strip(\".\") for e in exts],\n                    \"matches\": [m for m in local_matches][-3000:],\n                    \"processed_dirs\": [],\n                })\n\n            else:\n                # \u2500\u2500 Local drive walk \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n                root_path = drive + \":\\\\\"\n                _PROGRESS_INTERVAL   = 5    # update label every N dirs\n                _LOG_INTERVAL        = 25   # log path every N dirs\n                _CHECKPOINT_INTERVAL = 250  # save checkpoint every N dirs\n                last_progress_time = time.monotonic()\n\n                for dirpath, _, filenames in os.walk(root_path):\n                    # \u2500\u2500 Instant stop check \u2014 no Tk access, thread-safe \u2500\u2500\u2500\n                    if self._scan_stop_event.is_set() or getattr(self, \"_recovery_stop_flag\", False):\n                        self._scan_stop_event.set()\n                        break\n\n                    if dirpath in processed_dirs:\n                        continue\n\n                    # \u2500\u2500 Pause: tight sleep loop \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n                    while getattr(self, \"_recovery_pause_flag\", False):\n                        if self._scan_stop_event.is_set() or getattr(self, \"_recovery_stop_flag\", False):\n                            self._scan_stop_event.set()\n                            break\n                        time.sleep(0.15)\n\n                    # \u2500\u2500 Scan files in this directory \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n                    for fn in filenames:\n                        if self._scan_stop_event.is_set():\n                            break\n                        low_ext = os.path.splitext(fn)[1].lower()\n                        if low_ext not in ext_set:\n                            continue\n                        full = os.path.join(dirpath, fn)\n                        try:\n                            sz = self._fmt_size(os.path.getsize(full))\n                        except Exception:\n                            sz = \"?\"\n                        type_lbl = low_ext.lstrip(\".\") or \"?\"\n                        loc = dirpath[-60:] if len(dirpath) &gt; 60 else dirpath\n                        row = (fn, type_lbl, sz, \"Found \u2014 Recover dabao \u25b6\", loc, \"--\")\n                        # \u25b6 Thread-safe: put into queue, NOT self.after(0,...)\n                        self._q_tree_row(row, full)\n                        file_count += 1\n                        local_matches.append(full)\n\n                    scanned += 1\n                    processed_dirs.add(dirpath)\n\n                    # \u2500\u2500 Yield briefly so the UI thread can run often \u2500\u2500\u2500\u2500\u2500\n                    time.sleep(0.001)\n\n                    # \u2500\u2500 Real-time progress label update (via queue) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\n                    now = time.monotonic()\n                    if scanned == 1 or now - last_progress_time &gt;= 0.100:\n                        folder_tail = dirpath[-65:] if len(dirpath) &gt; 65 else dirpath\n                        label_text  = (\n                            f\"\ud83d\udd0d Scanning...  {scanned:,} folders scanned  |  \"\n                            f\"{file_count:,} files mili  |  ...{folder_tail}\"\n                        )\n                        self._q(\"progress_label\", label_text)\n                        self._hdd_recovery_emit_metrics({\n                            \"phase\": \"file_search\",\n                            \"status_text\": label_text,\n                            \"scan_mode\": \"Mode: Zone A \u2014 File Search (Drive Scan)\",\n                            \"progress_pct\": None,\n                            \"files_found\": file_count,\n                            \"scanned_dirs\": scanned,\n                            \"resource_before_mb\": before_state.get(\"available_mb\", 0),\n                            \"resource_after_mb\": int(psutil.virtual_memory().available / 1024**2) if psutil else 0,\n                            \"delta_mb\": int(psutil.virtual_memory().available / 1024**2) - int(before_state.get(\"available_mb\", 0)),\n                        })\n                        if scanned % _LOG_INTERVAL == 0 or file_count % 10 == 0:\n                            self._q_log(dirpath)\n                        last_progress_time = now\n\n                    # \u2500\u2500 Periodic checkpoint save \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n                    if scanned % _CHECKPOINT_INTERVAL == 0:\n                        self._save_recovery_checkpoint(mode_key, {\n                            \"drive\": drive,\n                            \"exts\": [e.lower().strip(\".\") for e in exts],\n                            \"matches\": local_matches[-3000:],\n                            \"processed_dirs\": list(processed_dirs)[-15000:],\n                        })\n\n            # \u2500\u2500 4. Scan done \u2014 final UI update via after() \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            stopped       = self._scan_stop_event.is_set() or getattr(self, \"_recovery_stop_flag\", False)\n            n             = file_count\n            folders_final = scanned\n\n            def _done():\n                \"\"\"Runs on main thread via self.after(0, ...).\"\"\"\n                # Stop indeterminate animation and switch to determinate\n                if hasattr(self, \"raw_progress_bar\"):\n                    try:\n                        self.raw_progress_bar.stop()\n                    except Exception:\n                        pass\n                    self.raw_progress_bar.config(mode=\"determinate\")\n\n                # Flush any leftover queued tree rows\n                self._recovery_flush_ui_batch()\n                self._on_rec_select()\n\n                color      = C[\"success\"] if n &gt; 0 else C[\"warning\"]\n                status_msg = f\"{'\u23f9 Stopped \u2014 ' if stopped else ''}Search complete: {n} files found on {drive}\"\n                self._set_status(status_msg, color)\n\n                if hasattr(self, \"raw_progress_var\"):\n                    self.raw_progress_var.set(100 if not stopped else 50)\n                if hasattr(self, \"raw_progress_label\"):\n                    if stopped:\n                        self.raw_progress_label.config(\n                            text=f\"\u23f9 Stopped | {n:,} files found | Drive {drive}\")\n                    else:\n                        self.raw_progress_label.config(\n                            text=(f\"\u2705 Scan complete \u2014 {n:,} files found on {drive}: | \"\n                                  f\"{folders_final:,} folders scanned\"))\n\n                if hasattr(self, \"_rec_stop_btn\"):\n                    self._rec_stop_btn.config(state=\"disabled\")\n                if hasattr(self, \"_rec_pause_btn\"):\n                    self._rec_pause_btn.config(state=\"disabled\", text=\"\u23f8 Pause\")\n                self._recovery_active = False\n\n                if not stopped:\n                    self._clear_recovery_checkpoint(mode_key)\n                if n == 0 and not stopped:\n                    messagebox.showinfo(\n                        \"No Files Found\",\n                        f\"Drive {drive}: pe koi file nahi mili.\\n\\n\"\n                        \"Deleted files ke liye Zone B \u2192 Raw Signature Scan use karo (admin required).\")\n                elif stopped and n &gt; 0:\n                    messagebox.showinfo(\n                        \"Search Stopped\",\n                        f\"\u23f9 Search rok di gayi.\\n{n} files abhi tak mili hain.\\n\\n\"\n                        \"In files ko select karke recover kar sakte ho.\")\n\n            self.after(0, _done)\n\n        except Exception as e:\n            err = str(e)\n            self.after(0, lambda err=err: self._set_status(\"Search failed: \" + err, C[\"error\"]))\n        finally:\n            self.after(0, self._finish_recovery_operation)\n\n    def _recover_selected_files(self):\n        dest = filedialog.askdirectory(title=\"Recovered files save karne ke liye folder choose karo\")\n        if not dest:\n            return\n        selected = self.rec_tree.selection()\n        if not selected:\n            messagebox.showwarning(\"Select Files\", \"Pehle list mein files select karo.\")\n            return\n        try:\n            self._begin_recovery_operation(\"Extracting selected files...\")\n        except Exception as e:\n            messagebox.showwarning(\"Busy\", str(e))\n            return\n        if hasattr(self, \"_rec_recover_btn\"):\n            self._rec_recover_btn.config(state=\"disabled\")\n        if not self._hdd_action_submit(\"recover_selected_files\", self._do_recover_selected_files, dest, list(selected)):\n            self._set_status(\"Recovery action already running; wait for completion.\", C[\"warning\"])\n\n    def _do_recover_selected_files(self, dest, selected_iids):\n        before_state = self._snapshot_resource_state() or {}\n        count = 0\n        errors = []\n        seen_hashes = set()\n        try:\n            for iid in selected_iids:\n                entry = self.rec_found_files.get(iid)\n                if entry is None:\n                    continue\n                if isinstance(entry, dict) and entry.get(\"kind\") == \"raw\":\n                    try:\n                        extract_limit = SIGNATURES[entry[\"file_type\"]][\"max_size\"]\n                        ui_limit = self._raw_limit_bytes()\n                        if ui_limit is not None and entry[\"offset\"] &lt; ui_limit:\n                            extract_limit = max(SECTOR_SIZE, min(extract_limit, ui_limit - entry[\"offset\"]))\n                        result = extract_file_at_offset(\n                            entry[\"disk_path\"],\n                            entry[\"offset\"],\n                            entry[\"file_type\"],\n                            output_dir=dest,\n                            max_bytes=extract_limit,\n                            progress_callback=self._raw_recovery_progress,\n                        )\n                        complete = result.get(\"complete_boundary\", True)\n                        if not complete:\n                            errors.append(f\"{os.path.basename(result['path'])}: boundary incomplete, file fragmented/truncated ho sakti hai\")\n                        try:\n                            h = self._sha256_file(result[\"path\"])\n                            if h in seen_hashes:\n                                os.remove(result[\"path\"])\n                                errors.append(f\"Duplicate removed: {os.path.basename(result['path'])}\")\n                            else:\n                                seen_hashes.add(h)\n                                score, _reason = self._integrity_score(result[\"path\"], entry.get(\"file_type\", \"\"))\n                                actual_size = self._fmt_size(result.get(\"bytes\") or os.path.getsize(result[\"path\"]))\n                                score_text = f\"{score}/100 {'\u2705' if score &gt;= 60 else '\u26a0 check'}\"\n                                status_txt = \"\u2705 Recovered\" if complete else \"\u26a0 May be corrupt\"\n                                tag = \"recovered\" if complete else \"partial\"\n                                def _upd_row(i=iid, s=actual_size, st=status_txt, sc=score_text, tg=tag):\n                                    vals = list(self.rec_tree.item(i, \"values\"))\n                                    if len(vals) &gt;= 6:\n                                        self.rec_tree.item(i, values=(vals[0], vals[1], s, st, vals[4], sc), tags=(tg,))\n                                    self._on_rec_select()\n                                self.after(0, _upd_row)\n                                count += 1\n                        except Exception as e:\n                            errors.append(f\"Hash/score failed: {e}\")\n                            count += 1\n                    except Exception as e:\n                        errors.append(str(e))\n                elif isinstance(entry, dict) and entry.get(\"kind\") == \"mobile\":\n                    try:\n                        src = entry.get(\"path\", \"\")\n                        if not src:\n                            continue\n                        dst = os.path.join(dest, os.path.basename(src))\n                        ok, out = self._mobile_pull_with_retry(src, dst)\n                        if ok:\n                            try:\n                                h = self._sha256_file(dst)\n                                if h in seen_hashes:\n                                    os.remove(dst)\n                                    errors.append(f\"Duplicate mobile file skipped: {os.path.basename(dst)}\")\n                                    continue\n                                seen_hashes.add(h)\n                                score, _reason = self._integrity_score(dst, os.path.splitext(dst)[1].lstrip(\".\"))\n                                actual_size = self._fmt_size(os.path.getsize(dst))\n                                score_text = f\"{score}/100 {'\u2705' if score &gt;= 60 else '\u26a0 check'}\"\n                                def _upd_mob(i=iid, s=actual_size, sc=score_text):\n                                    vals = list(self.rec_tree.item(i, \"values\"))\n                                    if len(vals) &gt;= 6:\n                                        self.rec_tree.item(i, values=(vals[0], vals[1], s, \"\u2705 Recovered\", vals[4], sc), tags=(\"recovered\",))\n                                    self._on_rec_select()\n                                self.after(0, _upd_mob)\n                            except Exception as e:\n                                errors.append(f\"Mobile hash/score failed: {e}\")\n                            count += 1\n                        else:\n                            errors.append(f\"Mobile pull failed: {src} | {out[:140]}\")\n                    except Exception as e:\n                        errors.append(str(e))\n                else:\n                    path = entry if isinstance(entry, str) else entry.get(\"path\", \"\")\n                    if path and os.path.exists(path):\n                        try:\n                            dst = os.path.join(dest, os.path.basename(path))\n                            shutil.copy2(path, dst)\n                            try:\n                                h = self._sha256_file(dst)\n                                if h in seen_hashes:\n                                    os.remove(dst)\n                                    errors.append(f\"Duplicate local file skipped: {os.path.basename(dst)}\")\n                                    continue\n                                seen_hashes.add(h)\n                                score, _reason = self._integrity_score(dst, os.path.splitext(dst)[1].lstrip(\".\"))\n                                actual_size = self._fmt_size(os.path.getsize(dst))\n                                score_text = f\"{score}/100 {'\u2705' if score &gt;= 60 else '\u26a0 check'}\"\n                                def _upd_loc(i=iid, s=actual_size, sc=score_text):\n                                    vals = list(self.rec_tree.item(i, \"values\"))\n                                    if len(vals) &gt;= 6:\n                                        self.rec_tree.item(i, values=(vals[0], vals[1], s, \"\u2705 Recovered\", vals[4], sc), tags=(\"recovered\",))\n                                    self._on_rec_select()\n                                self.after(0, _upd_loc)\n                            except Exception as e:\n                                errors.append(f\"Local hash/score failed: {e}\")\n                            count += 1\n                        except Exception as e:\n                            errors.append(str(e))\n        finally:\n            def _finish():\n                if hasattr(self, \"_rec_recover_btn\"):\n                    self._rec_recover_btn.config(state=\"normal\")\n                summary = f\"\u2705 {count} files recovered to {dest}\"\n                if errors:\n                    summary += f\" | \u26a0 {len(errors)} errors\"\n                self._set_status(summary, C[\"success\"] if not errors else C[\"warning\"])\n                after_state = self._snapshot_resource_state() or {}\n                self._hdd_recovery_emit_metrics({\n                    \"phase\": \"recovery_extract\",\n                    \"status_text\": summary,\n                    \"progress_pct\": 100.0,\n                    \"files_found\": count,\n                    \"resource_before_mb\": before_state.get(\"available_mb\", 0),\n                    \"resource_after_mb\": after_state.get(\"available_mb\", 0),\n                    \"delta_mb\": after_state.get(\"available_mb\", 0) - before_state.get(\"available_mb\", 0),\n                })\n            self.after(0, _finish)\n            self.after(0, self._finish_recovery_operation)\n            gc.collect()\n\n    # ---------- LIVE TEMPERATURE (unchanged) ----------\n    def _build_live_temps(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83c\udf21\ufe0f Live Temperature Monitor\", \"Real CPU/GPU thermal readings\", hw=True)\n        self._action_card_grid(frame, [\n            (\"\ud83c\udf21\", \"Refresh Temps\", \"CPU + GPU temperature readings\", C[\"btn_chip\"], self._scan_temps),\n        ], cols=1)\n        stats = tk.Frame(frame, bg=C[\"bg\"])\n        stats.pack(fill=\"x\", padx=16, pady=8)\n        self.temp_cards = {}\n        for i, (k, lbl, color) in enumerate([(\"cpu_t\",\"CPU Temp\",C[\"error\"]), (\"gpu_t\",\"GPU Temp\",C[\"accent4\"])]):\n            card = self._stat_card(stats, lbl, \"--\", color)\n            card.grid(row=0, column=i, padx=6, sticky=\"ew\")\n            stats.columnconfigure(i, weight=1)\n            self.temp_cards[k] = card\n        self.temp_log = self._scrolled_text(frame, 18)\n        return frame\n\n    def _scan_temps(self):\n        self._launch_job(\"scan_temps\", self._do_scan_temps)\n\n    def _do_scan_temps(self):\n        self._append_log(self.temp_log, \"Querying WMI thermal zones...\", C[\"text\"])\n        out, _ = self._run_powershell(\n            \"Get-WmiObject -Namespace root\\\\wmi \"\n            \"-Class MSAcpi_ThermalZoneTemperature | \"\n            \"Select-Object -ExpandProperty CurrentTemperature\", timeout=15)\n        temps = []\n        for line in out.splitlines():\n            stripped = line.strip()\n            if stripped.replace('.', '').isdigit():\n                try:\n                    temps.append(float(stripped))\n                except:\n                    pass\n        if temps:\n            cpu_c = (temps[0] / 10.0) - 273.15\n            self.temp_cards[\"cpu_t\"]._value_lbl.config(text=f\"{cpu_c:.1f} \u00b0C\")\n            self.temp_cards[\"cpu_t\"]._bar.config(value=min(cpu_c, 100))\n            self._append_log(self.temp_log, f\"CPU Temp: {cpu_c:.1f} \u00b0C\", C[\"success\"] if cpu_c &lt; 75 else C[\"error\"])\n            if len(temps) &gt; 1:\n                gpu_c = (temps[1] / 10.0) - 273.15\n                self.temp_cards[\"gpu_t\"]._value_lbl.config(text=f\"{gpu_c:.1f} \u00b0C\")\n                self.temp_cards[\"gpu_t\"]._bar.config(value=min(gpu_c, 100))\n                self._append_log(self.temp_log, f\"GPU Temp: {gpu_c:.1f} \u00b0C\", C[\"success\"] if gpu_c &lt; 85 else C[\"error\"])\n        else:\n            self._append_log(self.temp_log, \"\u26a0 Native WMI thermal probes not found on this hardware.\", C[\"warning\"])\n            self._append_log(self.temp_log, \"Note: Requires laptop sensors or specific desktop motherboards.\", C[\"text_dim\"])\n        self._append_log(self.temp_log, \"\u2705 Temp scan complete.\", C[\"success\"])\n        self._set_status(\"Temp scan complete\", C[\"success\"])\n\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  REVO-STYLE BATCH UNINSTALLER  v2.0  \u2014  Deep Forced Removal\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _build_uninstaller(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"Professional Uninstall Center\",\n                             \"Safe uninstall, force removal, leftover scan and audit-ready cleanup\")\n\n        guide = tk.Frame(frame, bg=C[\"card\"], highlightbackground=C[\"accent2\"], highlightthickness=1)\n        guide.pack(fill=\"x\", padx=16, pady=(8, 4))\n        tk.Label(guide, text=\"Beginner-safe workflow\", font=FONTS[\"subhead\"],\n                 fg=C[\"accent2\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=12, pady=(8, 2))\n        tk.Label(\n            guide,\n            text=\"1. Scan Programs.  2. Select an app.  3. Use Safe Uninstall first.  4. Scan Leftovers.  5. Clean only reviewed items. Force Uninstall is for broken uninstallers only.\",\n            font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], anchor=\"w\",\n            justify=\"left\", wraplength=self._dpi_px(1040)\n        ).pack(fill=\"x\", padx=12, pady=(0, 8))\n\n        uninst_actions = [\n            (\"Scan Programs\", C[\"btn_info\"], self._scan_installed),\n            (\"Safe Uninstall\", C[\"btn_warn\"], self._uninst_standard),\n            (\"Force Uninstall\", C[\"btn_danger\"], self._uninst_force),\n            (\"Deep Leftover Scan\", C[\"btn_info\"], self._scan_leftovers),\n            (\"Clean Reviewed\", C[\"btn_danger\"], self._clean_leftovers),\n            (\"Unlock Locked File\", C[\"btn_chip\"], self._unlock_file_dialog),\n            (\"Deep Folder Cleanup\", C[\"btn_danger\"], self._deep_cleanup_folder_dialog),\n        ]\n\n        sf = tk.Frame(frame, bg=C[\"bg\"])\n        sf.pack(fill=\"x\", padx=16, pady=(6,2))\n        tk.Label(sf, text=\"\ud83d\udd0d Search:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"]).pack(side=\"left\")\n        self.uninst_search = tk.Entry(sf, width=30, font=FONTS[\"body\"], bg=C[\"card\"],\n                                      fg=C[\"text\"], insertbackground=C[\"text\"], relief=\"flat\", bd=4)\n        self.uninst_search.pack(side=\"left\", padx=8)\n        self.uninst_search.bind(\"\", self._filter_uninst)\n        self.uninst_count_lbl = tk.Label(sf, text=\"\", font=FONTS[\"small\"], fg=C[\"accent\"], bg=C[\"bg\"])\n        self.uninst_count_lbl.pack(side=\"left\", padx=12)\n        self.uninst_pause_btn = self._btn(sf, \"Pause Scan\", C[\"btn_chip\"], self._pause_resume_uninst_scan)\n        self.uninst_pause_btn.pack(side=\"right\", padx=4)\n        self._btn(sf, \"Stop Scan\", C[\"btn_danger\"], self._stop_uninst_scan).pack(side=\"right\", padx=4)\n\n        self.uninst_progress_var = tk.DoubleVar(value=0)\n        ttk.Progressbar(frame, variable=self.uninst_progress_var, maximum=100, mode=\"determinate\").pack(\n            fill=\"x\", padx=16, pady=(2, 4)\n        )\n        self.uninst_timing_lbl = tk.Label(frame, text=\"Elapsed: 00:00 | Left: -- | Total: --\",\n                                          font=FONTS[\"small\"], fg=C[\"text_dim\"],\n                                          bg=C[\"bg\"], anchor=\"w\")\n        self.uninst_timing_lbl.pack(fill=\"x\", padx=16, pady=(0, 4))\n\n        summary = tk.Frame(frame, bg=C[\"bg\"])\n        summary.pack(fill=\"x\", padx=16, pady=(0, 4))\n        self.uninst_summary_vars = {}\n        for key, label, color in [\n            (\"programs\", \"Programs\", C[\"accent\"]),\n            (\"leftovers\", \"Leftovers\", C[\"warning\"]),\n            (\"risky\", \"Risky\", C[\"accent3\"]),\n            (\"safe\", \"Safe\", C[\"accent2\"]),\n        ]:\n            box = tk.Frame(summary, bg=C[\"card\"], highlightbackground=C[\"border\"], highlightthickness=1)\n            box.pack(side=\"left\", padx=(0, 6), fill=\"x\", expand=True)\n            tk.Label(box, text=label, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=8, pady=(5, 0))\n            var = tk.StringVar(value=\"0\")\n            self.uninst_summary_vars[key] = var\n            tk.Label(box, textvariable=var, font=FONTS[\"heading\"], fg=color, bg=C[\"card\"]).pack(anchor=\"w\", padx=8, pady=(0, 5))\n\n        # \u2500\u2500 Paned layout \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        paned = tk.Frame(frame, bg=C[\"bg\"])\n        paned.pack(fill=\"both\", expand=True, padx=16, pady=6)\n        paned.columnconfigure(0, weight=5)\n        paned.columnconfigure(1, weight=3)\n        paned.rowconfigure(0, weight=1)\n\n        # Left: program list\n        left = tk.Frame(paned, bg=C[\"card\"])\n        left.grid(row=0, column=0, sticky=\"nsew\", padx=(0,6))\n        left.rowconfigure(1, weight=1)\n        left.columnconfigure(0, weight=1)\n        tk.Label(left, text=\"  Installed Programs\", font=FONTS[\"subhead\"],\n                 fg=C[\"accent\"], bg=C[\"card\"]).grid(row=0, column=0, columnspan=3, sticky=\"w\", pady=(8,4), padx=8)\n        cols = (\"Software\",\"Version\",\"Size\",\"Date\",\"Publisher\")\n        self.uninst_tree = ttk.Treeview(left, columns=cols, show=\"headings\",\n                                        height=24, style=\"Custom.Treeview\")\n        for col, w in zip(cols, [260, 90, 80, 90, 170]):\n            self.uninst_tree.heading(col, text=col,\n                                     command=lambda c=col: self._sort_uninst(c))\n            self.uninst_tree.column(col, width=w, anchor=\"w\")\n        vsb = ttk.Scrollbar(left, orient=\"vertical\", command=self.uninst_tree.yview)\n        hsb = ttk.Scrollbar(left, orient=\"horizontal\", command=self.uninst_tree.xview)\n        self.uninst_tree.configure(yscrollcommand=vsb.set, xscrollcommand=hsb.set)\n        self.uninst_tree.grid(row=1, column=0, sticky=\"nsew\", padx=(8,0), pady=(0,0))\n        vsb.grid(row=1, column=1, sticky=\"ns\", pady=(0,0), padx=(0,8))\n        hsb.grid(row=2, column=0, sticky=\"ew\", padx=(8,0), pady=(0,8))\n        self._bind_tree_responsive_columns(self.uninst_tree, [\n            (\"Software\", 280, 5), (\"Version\", 90, 1), (\"Size\", 80, 1), (\"Date\", 90, 1), (\"Publisher\", 180, 3)\n        ])\n        self.uninst_tree.bind(\"&lt;&gt;\", self._on_uninst_select)\n\n        # Right: detail + leftover panel\n        right = tk.Frame(paned, bg=C[\"card\"])\n        right.grid(row=0, column=1, sticky=\"nsew\", padx=(6,0))\n        right.rowconfigure(3, weight=1)\n        right.rowconfigure(5, weight=2)\n        right.columnconfigure(0, weight=1)\n\n        tk.Label(right, text=\"  Actions\", font=FONTS[\"subhead\"],\n                 fg=C[\"accent\"], bg=C[\"card\"]).grid(row=0, column=0, columnspan=2,\n                 sticky=\"w\", padx=8, pady=(8,2))\n        action_box = tk.Frame(right, bg=C[\"card\"])\n        action_box.grid(row=1, column=0, columnspan=2, sticky=\"ew\", padx=4, pady=(0,4))\n        self._compact_action_grid(action_box, uninst_actions, cols=2)\n\n        tk.Label(right, text=\"  App Details\", font=FONTS[\"subhead\"],\n                 fg=C[\"accent\"], bg=C[\"card\"]).grid(row=2, column=0, columnspan=2,\n                 sticky=\"w\", padx=8, pady=(8,4))\n        self.uninst_detail = scrolledtext.ScrolledText(\n            right, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"],\n            height=5, bd=0, relief=\"flat\", state=\"disabled\", wrap=\"word\")\n        self.uninst_detail.grid(row=3, column=0, columnspan=2,\n                                sticky=\"nsew\", padx=8, pady=(0,4))\n\n        tk.Label(right, text=\"  Leftover Files / Registry / Folders\",\n                 font=FONTS[\"subhead\"], fg=C[\"warning\"], bg=C[\"card\"]).grid(\n                 row=4, column=0, sticky=\"w\", padx=8, pady=(4,4))\n        self.leftover_tree = ttk.Treeview(right, columns=(\"Type\",\"Risk\",\"Confidence\",\"Path\"),\n                                          show=\"headings\", height=10,\n                                          style=\"Custom.Treeview\")\n        self.leftover_tree.heading(\"Type\", text=\"Type\")\n        self.leftover_tree.column(\"Type\", width=80, anchor=\"center\")\n        self.leftover_tree.heading(\"Risk\", text=\"Risk\")\n        self.leftover_tree.column(\"Risk\", width=70, anchor=\"center\")\n        self.leftover_tree.heading(\"Confidence\", text=\"Score\")\n        self.leftover_tree.column(\"Confidence\", width=70, anchor=\"center\")\n        self.leftover_tree.heading(\"Path\", text=\"Path / Registry Key\")\n        self.leftover_tree.column(\"Path\", width=330, anchor=\"w\")\n        self.leftover_tree.tag_configure(\"file\", foreground=C[\"warning\"])\n        self.leftover_tree.tag_configure(\"reg\",  foreground=C[\"accent3\"])\n        self.leftover_tree.tag_configure(\"safe\", foreground=C[\"success\"])\n        self.leftover_tree.tag_configure(\"risky\", foreground=C[\"accent3\"])\n        lvsb = ttk.Scrollbar(right, orient=\"vertical\", command=self.leftover_tree.yview)\n        self.leftover_tree.configure(yscrollcommand=lvsb.set)\n        self.leftover_tree.grid(row=5, column=0, sticky=\"nsew\", padx=(8,0), pady=(0,8))\n        lvsb.grid(row=5, column=1, sticky=\"ns\", pady=(0,8), padx=(0,4))\n        self._bind_tree_responsive_columns(self.leftover_tree, [\n            (\"Type\", 80, 0), (\"Risk\", 70, 0), (\"Confidence\", 70, 0), (\"Path\", 330, 4)\n        ])\n\n        self.uninst_status = tk.Label(frame, text=\"  Ready \u2014 Scan programs to begin\",\n                                      font=FONTS[\"small\"], fg=C[\"accent2\"],\n                                      bg=C[\"bg\"], anchor=\"w\")\n        self.uninst_status.pack(fill=\"x\", padx=16, pady=(0,6))\n\n        # Internal state\n        self.uninst_data     = []\n        self.uninst_filtered = []\n        self.leftover_items  = []\n        self.uninst_sort_col = \"\"\n        self.uninst_sort_rev = False\n        self._uninst_cancel_flag = False\n        self._uninst_pause_flag = False\n        self._set_uninst_progress(0, \"Ready - Scan Programs to begin\", C[\"accent2\"])\n        return frame\n\n    def _build_event_viewer(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udcdc Event Viewer (Simple Explain)\",\n                             \"System/Application errors ka simple reason + solution\")\n\n        top = tk.Frame(frame, bg=C[\"panel\"])\n        top.pack(fill=\"x\", padx=16, pady=(8, 6))\n\n        tk.Label(top, text=\"Log:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"left\", padx=(8, 4))\n        self.ev_log_var = tk.StringVar(value=\"System\")\n        self.ev_log_combo = ttk.Combobox(top, textvariable=self.ev_log_var, values=[\"System\", \"Application\"], width=12, state=\"readonly\")\n        self.ev_log_combo.pack(side=\"left\", padx=4, pady=8)\n\n        tk.Label(top, text=\"Level:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"left\", padx=(10, 4))\n        self.ev_level_var = tk.StringVar(value=\"Error,Critical\")\n        self.ev_level_combo = ttk.Combobox(top, textvariable=self.ev_level_var, values=[\"Error,Critical\", \"Error\", \"Warning,Error,Critical\"], width=20, state=\"readonly\")\n        self.ev_level_combo.pack(side=\"left\", padx=4, pady=8)\n\n        tk.Label(top, text=\"Count:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"left\", padx=(10, 4))\n        self.ev_count_entry = tk.Entry(top, width=6, font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"])\n        self.ev_count_entry.insert(0, \"80\")\n        self.ev_count_entry.pack(side=\"left\", padx=4, pady=8)\n\n        self._btn(top, \"\ud83d\udd04 Fetch Events\", C[\"btn_info\"], self._eventviewer_fetch).pack(side=\"left\", padx=(12, 4), pady=8)\n        self._btn(top, \"\ud83e\udde0 Explain Selected\", C[\"btn_warn\"], self._eventviewer_explain_selected).pack(side=\"left\", padx=4, pady=8)\n\n        body = tk.Frame(frame, bg=C[\"bg\"])\n        body.pack(fill=\"both\", expand=True, padx=16, pady=(0, 8))\n        body.columnconfigure(0, weight=3)\n        body.columnconfigure(1, weight=2)\n        body.rowconfigure(0, weight=1)\n\n        left = tk.Frame(body, bg=C[\"card\"])\n        left.grid(row=0, column=0, sticky=\"nsew\", padx=(0, 6))\n        tk.Label(left, text=\"  Recent Windows Events\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8, 4), padx=8)\n\n        cols = (\"Time\", \"Source\", \"EventID\", \"Level\", \"Message\")\n        self.ev_tree = ttk.Treeview(left, columns=cols, show=\"headings\", height=18, style=\"Custom.Treeview\")\n        widths = [160, 180, 80, 90, 600]\n        for col, w in zip(cols, widths):\n            self.ev_tree.heading(col, text=col)\n            self.ev_tree.column(col, width=w, anchor=\"w\")\n        evsb = ttk.Scrollbar(left, orient=\"vertical\", command=self.ev_tree.yview)\n        self.ev_tree.configure(yscrollcommand=evsb.set)\n        self.ev_tree.pack(side=\"left\", fill=\"both\", expand=True, padx=(8, 0), pady=(0, 8))\n        evsb.pack(side=\"right\", fill=\"y\", pady=(0, 8), padx=(0, 4))\n        self.ev_tree.bind(\"&lt;&gt;\", self._eventviewer_explain_selected)\n\n        right = tk.Frame(body, bg=C[\"card\"])\n        right.grid(row=0, column=1, sticky=\"nsew\", padx=(6, 0))\n        tk.Label(right, text=\"  Simple Explanation\", font=FONTS[\"subhead\"], fg=C[\"warning\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8, 4), padx=8)\n        self.ev_explain = scrolledtext.ScrolledText(\n            right, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"],\n            height=22, bd=0, relief=\"flat\", state=\"disabled\", wrap=\"word\"\n        )\n        self.ev_explain.pack(fill=\"both\", expand=True, padx=8, pady=(0, 8))\n\n        self.ev_status = tk.Label(frame, text=\"  Ready - Fetch Events dabao\", font=FONTS[\"small\"],\n                                  fg=C[\"accent2\"], bg=C[\"bg\"], anchor=\"w\")\n        self.ev_status.pack(fill=\"x\", padx=16, pady=(0, 6))\n        self.ev_items = []\n        return frame\n\n    def _eventviewer_fetch(self):\n        log_name = (self.ev_log_var.get() if hasattr(self, \"ev_log_var\") else \"System\").strip() or \"System\"\n        level_csv = (self.ev_level_var.get() if hasattr(self, \"ev_level_var\") else \"Error,Critical\").strip()\n        count = 80\n        try:\n            count = max(10, min(300, int((self.ev_count_entry.get() or \"80\").strip())))\n        except Exception:\n            count = 80\n        self.ev_status.config(text=f\"  Fetching {log_name} events...\", fg=C[\"accent4\"])\n        self._launch_job(\"eventviewer_fetch\", self._do_eventviewer_fetch, log_name, level_csv, count)\n\n    def _do_eventviewer_fetch(self, log_name, level_csv, count):\n        levels = [x.strip().lower() for x in str(level_csv).split(\",\") if x.strip()]\n        level_map = {\"critical\": 1, \"error\": 2, \"warning\": 3, \"information\": 4, \"verbose\": 5}\n        lvl_ids = [str(level_map[x]) for x in levels if x in level_map]\n        if not lvl_ids:\n            lvl_ids = [\"1\", \"2\"]\n        level_expr = \",\".join(lvl_ids)\n\n        ps_script = (\n            f\"$f=@{{LogName='{log_name}'; Level={level_expr}}}; \"\n            f\"Get-WinEvent -FilterHashtable $f -MaxEvents {int(count)} -ErrorAction SilentlyContinue | \"\n            f\"Select-Object TimeCreated,ProviderName,Id,LevelDisplayName,Message | ConvertTo-Json -Depth 4\"\n        )\n        cmd = f'powershell -NoProfile -ExecutionPolicy Bypass -Command \"{ps_script}\"'\n        out, rc = self._run_cmd(cmd, timeout=60)\n        if rc != 0 or not out.strip():\n            self.after(0, lambda: self.ev_status.config(text=\"  Event fetch failed. Run as Admin and retry.\", fg=C[\"error\"]))\n            return\n        try:\n            data = json.loads(out)\n            if isinstance(data, dict):\n                data = [data]\n            if not isinstance(data, list):\n                data = []\n        except Exception:\n            data = []\n        self.ev_items = data\n        self.after(0, self._populate_eventviewer_tree)\n\n    def _populate_eventviewer_tree(self):\n        self.ev_tree.delete(*self.ev_tree.get_children())\n        for ev in self.ev_items:\n            try:\n                t = str(ev.get(\"TimeCreated\", \"\"))[:19].replace(\"T\", \" \")\n                src = str(ev.get(\"ProviderName\", \"\") or \"\")\n                eid = str(ev.get(\"Id\", \"\") or \"\")\n                lvl = str(ev.get(\"LevelDisplayName\", \"\") or \"\")\n                msg = \" \".join(str(ev.get(\"Message\", \"\") or \"\").split())\n                if len(msg) &gt; 220:\n                    msg = msg[:220] + \"...\"\n                self.ev_tree.insert(\"\", \"end\", values=(t, src, eid, lvl, msg))\n            except Exception:\n                pass\n        c = len(self.ev_items)\n        color = C[\"warning\"] if c else C[\"success\"]\n        self.ev_status.config(text=f\"  Loaded {c} event(s). Select one for simple explanation.\", fg=color)\n        if c:\n            first = self.ev_tree.get_children()\n            if first:\n                self.ev_tree.selection_set(first[0])\n                self._eventviewer_explain_selected()\n\n    def _eventviewer_explain_selected(self, event=None):\n        if not hasattr(self, \"ev_tree\"):\n            return\n        sel = self.ev_tree.selection()\n        if not sel:\n            return\n        idx = self.ev_tree.index(sel[0])\n        if idx &lt; 0 or idx &gt;= len(self.ev_items):\n            return\n        ev = self.ev_items[idx]\n        text = self._eventviewer_make_simple_explain(ev)\n        self.ev_explain.config(state=\"normal\")\n        self.ev_explain.delete(\"1.0\", \"end\")\n        self.ev_explain.insert(\"1.0\", text)\n        self.ev_explain.config(state=\"disabled\")\n\n    def _eventviewer_make_simple_explain(self, ev):\n        eid = str(ev.get(\"Id\", \"\") or \"\")\n        source = str(ev.get(\"ProviderName\", \"\") or \"Unknown\")\n        level = str(ev.get(\"LevelDisplayName\", \"\") or \"Unknown\")\n        t = str(ev.get(\"TimeCreated\", \"\") or \"\").replace(\"T\", \" \")\n        msg_full = str(ev.get(\"Message\", \"\") or \"\").strip()\n        msg_low = msg_full.lower()\n\n        reason = \"System me operation fail hua ya expected service response nahi mili.\"\n        solution = \"System restart karo, latest updates lagao, phir issue ko dubara reproduce karke check karo.\"\n\n        known = {\n            (\"Kernel-Power\", \"41\"): (\n                \"PC proper shutdown ke bina restart hua (power cut, crash, force restart).\",\n                \"Power cable/SMPS check karo, overheating test karo, RAM test chalao, aur sudden power loss avoid karo.\"\n            ),\n            (\"Microsoft-Windows-Kernel-Power\", \"41\"): (\n                \"PC proper shutdown ke bina restart hua. Ye BSOD, power cut, overheating ya force shutdown se aa sakta hai.\",\n                \"BugCheck/WHEA/Disk events ke saath compare karo. PSU, temperature, RAM, driver aur disk health check karo.\"\n            ),\n            (\"Microsoft-Windows-WER-SystemErrorReporting\", \"1001\"): (\n                \"Windows ne BugCheck/Blue Screen report log kiya.\",\n                \"Stop code note karo, C:\\\\Windows\\\\Minidump file analyze karo, phir culprit driver/hardware fix karo.\"\n            ),\n            (\"Microsoft-Windows-WHEA-Logger\", \"17\"): (\n                \"Corrected hardware error detect hua; system bach gaya par hardware path warning de raha hai.\",\n                \"BIOS/chipset update, overclock off, RAM/SSD/GPU/PCIe health aur temperature check karo.\"\n            ),\n            (\"Microsoft-Windows-WHEA-Logger\", \"18\"): (\n                \"Fatal hardware error detect hua; ye BSOD ka strong hardware clue hai.\",\n                \"RAM test, CPU/GPU temperature, PSU, SSD SMART, BIOS/chipset update aur overclock reset karo.\"\n            ),\n            (\"Microsoft-Windows-WHEA-Logger\", \"19\"): (\n                \"Corrected hardware error repeat ho sakta hai.\",\n                \"Event details me component dekho, phir related driver/firmware/hardware check karo.\"\n            ),\n            (\"volmgr\", \"161\"): (\n                \"Crash dump create nahi ho paya, isliye BSOD proof file missing ho sakti hai.\",\n                \"C: drive free space, pagefile aur CrashControl minidump settings enable karo.\"\n            ),\n            (\"Display\", \"4101\"): (\n                \"Display/GPU driver ne respond karna band kiya aur recover hua.\",\n                \"GPU driver clean reinstall/rollback, GPU temperature, power cable/PSU aur hardware acceleration test karo.\"\n            ),\n            (\"Application Error\", \"1000\"): (\n                \"Kisi application/module ne crash kiya.\",\n                \"Faulting application/module name dekho. Agar rundll32.exe hai to loaded DLL/app culprit hota hai; us app/driver ko repair karo.\"\n            ),\n            (\"SideBySide\", \"33\"): (\n                \"App runtime/VC++ dependency mismatch ya missing manifest issue.\",\n                \"Affected app reinstall/repair karo aur Microsoft Visual C++ Redistributables repair/install karo.\"\n            ),\n            (\"Service Control Manager\", \"7000\"): (\n                \"Koi service startup pe start nahi ho payi.\",\n                \"Services menu me jaake service dependencies check karo, startup type sahi set karo, phir reboot karo.\"\n            ),\n            (\"Service Control Manager\", \"7001\"): (\n                \"Service dependency chain me issue hai, required service pehle start nahi hui.\",\n                \"Related dependent services ko Automatic pe set karo aur start order verify karo.\"\n            ),\n            (\"Disk\", \"7\"): (\n                \"Disk read/write hardware level problem detect hui.\",\n                \"SMART scan chalao, cable/port check karo, data backup lo, aur disk health verify karo.\"\n            ),\n            (\"Ntfs\", \"55\"): (\n                \"File system me corruption detect hua.\",\n                \"Admin CMD me `chkdsk /f` run karo (boot drive ke liye restart required).\"\n            ),\n            (\"DistributedCOM\", \"10016\"): (\n                \"DCOM permission mismatch log hua; mostly harmless hota hai.\",\n                \"Agar app crash nahi ho rahi to ignore kar sakte ho; otherwise specific app permissions tune karo.\"\n            ),\n        }\n        if (source, eid) in known:\n            reason, solution = known[(source, eid)]\n        else:\n            if \"access is denied\" in msg_low or \"access denied\" in msg_low:\n                reason = \"Permission issue ki wajah se operation block hua.\"\n                solution = \"Tool/Admin rights ke saath run karo, folder/service permissions verify karo.\"\n            elif \"bugcheck\" in msg_low or \"blue screen\" in msg_low:\n                reason = \"Windows kernel crash/BSOD report log hua.\"\n                solution = \"BSoD Deep Diagnose run karo, stop code aur minidump check karo, phir driver/RAM/disk/GPU cause fix karo.\"\n            elif \"rundll32\" in msg_low or \"rundell32\" in msg_low:\n                reason = \"rundll32.exe se DLL load/crash issue lag raha hai. Real Windows file rundll32.exe hota hai, rundell32.dll nahi.\"\n                solution = \"Rundll32 Error Check run karo; startup/task me missing DLL entry disable karo, affected app reinstall/uninstall karo, SFC/DISM aur malware scan chalao.\"\n            elif \"specified module could not be found\" in msg_low or \"module could not be found\" in msg_low:\n                reason = \"Koi startup/app ek DLL load kar raha tha jo ab missing hai.\"\n                solution = \"Startup Apps, Task Scheduler aur registry Run entries me missing DLL reference dhoondh kar disable/remove karo ya related app reinstall karo.\"\n            elif \"side-by-side\" in msg_low or \"activation context\" in msg_low:\n                reason = \"App runtime/VC++ dependency mismatch detect hua.\"\n                solution = \"Affected app repair/reinstall karo aur Microsoft Visual C++ Redistributables repair/install karo.\"\n            elif \"whea\" in msg_low or \"hardware error\" in msg_low:\n                reason = \"Hardware layer se error signal mila.\"\n                solution = \"Temperature, RAM, SSD SMART, GPU/PCIe, PSU, BIOS/chipset driver aur overclock settings check karo.\"\n            elif \"timeout\" in msg_low or \"timed out\" in msg_low:\n                reason = \"Operation ko required response time me reply nahi mila.\"\n                solution = \"Heavy load kam karo, related service restart karo, network/disk responsiveness check karo.\"\n            elif \"driver\" in msg_low:\n                reason = \"Driver related compatibility ya corruption issue lag raha hai.\"\n                solution = \"Driver Checker se current driver version check karke stable version reinstall/update karo.\"\n            elif \"dns\" in msg_low or \"network\" in msg_low:\n                reason = \"Network stack ya DNS resolution me issue detect hua.\"\n                solution = \"Network Optimizer me DNS flush + TCP reset chalao, phir reconnect test karo.\"\n\n        if len(msg_full) &gt; 1200:\n            msg_full = msg_full[:1200] + \"\\n... (message truncated)\"\n\n        return (\n            f\"Event Time: {t}\\n\"\n            f\"Source: {source}\\n\"\n            f\"Error Code / Event ID: {eid}\\n\"\n            f\"Level: {level}\\n\\n\"\n            f\"1) Ye error code kya hai?\\n\"\n            f\"   Event ID {eid} ({source}) system ka diagnostic code hai jo issue category batata hai.\\n\\n\"\n            f\"2) Ye kyun aaya?\\n\"\n            f\"   {reason}\\n\\n\"\n            f\"3) Iska solution kya ho sakta hai?\\n\"\n            f\"   {solution}\\n\\n\"\n            f\"Original Windows Message:\\n{msg_full or 'N/A'}\\n\"\n        )\n\n    # \u2500\u2500 Scan all installed programs \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _threadsafe_confirm(self, title, message):\n        text = str(message)\n        if len(text) &gt; 5000:\n            text = text[:5000] + \"\\n\\n...list lambi hai, baaki items log me dekhein.\"\n        if threading.current_thread() is threading.main_thread():\n            return messagebox.askyesno(title, text)\n        done = threading.Event()\n        result = {\"yes\": False}\n\n        def _ask():\n            try:\n                result[\"yes\"] = messagebox.askyesno(title, text)\n            finally:\n                done.set()\n\n        self.after(0, _ask)\n        done.wait()\n        return result[\"yes\"]\n\n    def _tool_log(self, msg, level=\"INFO\"):\n        self.after(0, lambda: self._log(msg, level))\n\n    def _unlock_file_dialog(self):\n        path = filedialog.askopenfilename(title=\"Locked file select karo\")\n        if not path:\n            return\n        self.uninst_status.config(text=\"Locked file scan chal raha hai...\", fg=C[\"accent4\"])\n\n        def _run():\n            result = unlock_file_if_locked(\n                path,\n                confirm_callback=self._threadsafe_confirm,\n                log_callback=lambda msg: self._tool_log(msg, \"INFO\"),\n            )\n\n            def _finish():\n                color = C[\"success\"] if result.get(\"ok\") else C[\"warning\"]\n                self.uninst_status.config(text=result.get(\"message\", \"Unlock complete\"), fg=color)\n                details = result.get(\"message\", \"\")\n                if result.get(\"terminated\"):\n                    details += \"\\n\\nTerminated PID(s): \" + \", \".join(map(str, result[\"terminated\"]))\n                if result.get(\"errors\"):\n                    details += \"\\n\\nErrors:\\n\" + \"\\n\".join(result[\"errors\"])\n                if result.get(\"ok\"):\n                    messagebox.showinfo(\"Unlock Result\", details)\n                else:\n                    messagebox.showwarning(\"Unlock Result\", details)\n\n            self.after(0, _finish)\n\n        self._launch_job(\"unlock_app\", _run)\n\n    def _deep_cleanup_folder_dialog(self):\n        folder = filedialog.askdirectory(title=\"Program folder select karo\")\n        if not folder:\n            return\n        self.uninst_status.config(text=\"Deep cleanup scan chal raha hai...\", fg=C[\"accent4\"])\n\n        def _run():\n            result = deep_cleanup_program(\n                folder,\n                confirm_callback=self._threadsafe_confirm,\n                log_callback=lambda msg: self._tool_log(msg, \"INFO\"),\n            )\n\n            def _finish():\n                color = C[\"success\"] if result.get(\"ok\") else C[\"warning\"]\n                self.uninst_status.config(text=result.get(\"message\", \"Deep cleanup complete\"), fg=color)\n                details = result.get(\"message\", \"\")\n                if result.get(\"ok\"):\n                    details += (\n                        f\"\\n\\nFiles: {result.get('files', 0)}\"\n                        f\"\\nFolders: {result.get('dirs', 0)}\"\n                        f\"\\nRegistry clues listed: {len(result.get('registry_entries', []))}\"\n                    )\n                    messagebox.showinfo(\"Deep Cleanup Result\", details)\n                    self._scan_installed()\n                else:\n                    if result.get(\"errors\"):\n                        details += \"\\n\\nErrors:\\n\" + \"\\n\".join(result[\"errors\"])\n                    messagebox.showwarning(\"Deep Cleanup Result\", details)\n\n            self.after(0, _finish)\n\n        self._launch_job(\"deep_cleanup\", _run)\n\n    def _scan_installed(self):\n        self.uninst_tree.delete(*self.uninst_tree.get_children())\n        self.uninst_data = []\n        self.uninst_filtered = []\n        self._uninst_cancel_flag = False\n        self._uninst_pause_flag = False\n        if hasattr(self, \"uninst_pause_btn\"):\n            self.uninst_pause_btn.config(text=\"Pause Scan\")\n        self._set_uninst_progress(5, \"Scanning installed programs...\", C[\"accent4\"])\n        self._audit_event(\"uninstall_scan_started\", {\"scope\": \"installed_programs\"})\n        self._launch_job(\"scan_installed_programs\", self._do_scan_installed)\n\n    def _do_scan_installed(self):\n        regs = [\n            (winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\"),\n            (winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\"),\n            (winreg.HKEY_CURRENT_USER,  r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\"),\n        ]\n        found = []\n        try:\n            for reg_idx, (hive, path) in enumerate(regs, start=1):\n                self._check_uninst_control()\n                self._set_uninst_progress(10 + reg_idx * 18, f\"Reading uninstall registry hive {reg_idx}/{len(regs)}...\", C[\"accent4\"])\n                try:\n                    key = winreg.OpenKey(hive, path, 0, winreg.KEY_READ)\n                    i = 0\n                    while True:\n                        self._check_uninst_control()\n                        try:\n                            sub_name = winreg.EnumKey(key, i); i += 1\n                            subkey = winreg.OpenKey(key, sub_name, 0, winreg.KEY_READ)\n                            name      = self._reg_read_str(subkey, \"DisplayName\")\n                            version   = self._reg_read_str(subkey, \"DisplayVersion\")\n                            size_kb   = self._reg_read_str(subkey, \"EstimatedSize\")\n                            date      = self._reg_read_str(subkey, \"InstallDate\")\n                            uninst_s  = self._reg_read_str(subkey, \"UninstallString\")\n                            quiet_s   = self._reg_read_str(subkey, \"QuietUninstallString\")\n                            publisher = self._reg_read_str(subkey, \"Publisher\")\n                            inst_loc  = self._reg_read_str(subkey, \"InstallLocation\")\n                            winreg.CloseKey(subkey)\n                            if not name: continue\n                            skip_words = [\"KB\",\"Security Update\",\"Hotfix\",\"Service Pack\",\"Update for\"]\n                            if any(x in name for x in skip_words): continue\n                            try: sz = int(size_kb)*1024 if size_kb and size_kb.isdigit() else 0\n                            except: sz = 0\n                            found.append({\n                                \"name\": name, \"version\": version, \"size\": sz,\n                                \"date\": date[:8] if date and len(date) &gt;= 8 else \"--\",\n                                \"publisher\": publisher, \"uninst\": uninst_s,\n                                \"quiet\": quiet_s, \"install_loc\": inst_loc,\n                                \"has_uninstall\": bool(uninst_s or quiet_s),\n                                \"reg_key\": path + \"\\\\\" + sub_name,\n                                \"reg_hive\": \"HKLM\" if hive == winreg.HKEY_LOCAL_MACHINE else \"HKCU\",\n                            })\n                        except OSError: break\n                    winreg.CloseKey(key)\n                except Exception:\n                    pass\n        except InterruptedError:\n            self._audit_event(\"uninstall_scan_cancelled\", {\"scope\": \"installed_programs\", \"found\": len(found)})\n            self._set_uninst_progress(0, \"Installed-program scan cancelled.\", C[\"warning\"])\n            return\n        found.sort(key=lambda x: x[\"name\"].lower())\n        self.uninst_data     = found\n        self.uninst_filtered = found[:]\n        self.after(0, self._populate_uninst_tree)\n        self._set_uninst_progress(100, f\"Found {len(found)} programs\", C[\"success\"])\n        self._audit_event(\"uninstall_scan_finished\", {\"scope\": \"installed_programs\", \"count\": len(found)})\n        self.after(0, lambda: self._set_status(f\"Found {len(found)} installed programs\", C[\"success\"]))\n\n    def _populate_uninst_tree(self):\n        self.uninst_tree.delete(*self.uninst_tree.get_children())\n        for item in self.uninst_filtered:\n            self.uninst_tree.insert(\"\", \"end\", values=(\n                item[\"name\"], item[\"version\"],\n                self._fmt_size(item[\"size\"]), item[\"date\"], item[\"publisher\"]))\n        self.uninst_count_lbl.config(text=f\"{len(self.uninst_filtered)} programs\")\n        if hasattr(self, \"uninst_summary_vars\"):\n            self.uninst_summary_vars[\"programs\"].set(str(len(self.uninst_filtered)))\n\n    def _filter_uninst(self, event=None):\n        q = self.uninst_search.get().strip().lower()\n        self.uninst_filtered = (\n            self.uninst_data[:] if not q else\n            [x for x in self.uninst_data\n             if q in x[\"name\"].lower() or q in x[\"publisher\"].lower()])\n        self._populate_uninst_tree()\n\n    def _sort_uninst(self, col):\n        col_map = {\"Software\":\"name\",\"Version\":\"version\",\"Size\":\"size\",\"Date\":\"date\",\"Publisher\":\"publisher\"}\n        key = col_map.get(col, \"name\")\n        self.uninst_sort_rev = (not self.uninst_sort_rev) if self.uninst_sort_col == col else False\n        self.uninst_sort_col = col\n        self.uninst_filtered.sort(key=lambda x: str(x.get(key,\"\")), reverse=self.uninst_sort_rev)\n        self._populate_uninst_tree()\n\n    def _on_uninst_select(self, event=None):\n        sel = self.uninst_tree.selection()\n        if not sel: return\n        idx = self.uninst_tree.index(sel[0])\n        if idx &gt;= len(self.uninst_filtered): return\n        it = self.uninst_filtered[idx]\n        if not it.get(\"has_uninstall\"):\n            self.uninst_status.config(\n                text=\"Is program ka uninstall command nahi mila. \"\n                     \"Force Uninstall ya manual removal use karo.\",\n                fg=C[\"warning\"])\n        detail = (\n            f\"Name         : {it['name']}\\n\"\n            f\"Version      : {it['version'] or 'N/A'}\\n\"\n            f\"Publisher    : {it['publisher'] or 'N/A'}\\n\"\n            f\"Size         : {self._fmt_size(it['size'])}\\n\"\n            f\"Install Date : {it['date']}\\n\"\n            f\"Install Path : {it['install_loc'] or 'N/A'}\\n\"\n            f\"Registry Key : {it['reg_hive']}\\\\{it['reg_key']}\\n\"\n            f\"Has Uninstall: {'Yes' if it.get('has_uninstall') else 'No \u2014 use Force/manual'}\\n\"\n            f\"Uninstall    : {(it['uninst'] or 'N/A')[:100]}\\n\"\n            f\"Quiet Uninst : {(it['quiet'] or 'N/A')[:100]}\"\n        )\n        self.uninst_detail.config(state=\"normal\")\n        self.uninst_detail.delete(\"1.0\",\"end\")\n        self.uninst_detail.insert(\"1.0\", detail)\n        self.uninst_detail.config(state=\"disabled\")\n\n    def _get_sel_uninst(self):\n        items = []\n        for iid in self.uninst_tree.selection():\n            idx = self.uninst_tree.index(iid)\n            if idx &lt; len(self.uninst_filtered):\n                items.append(self.uninst_filtered[idx])\n        return items\n\n    def _uninst_is_protected(self, item):\n        \"\"\"\n        Publisher allowlist / protection guard.\n        Blocks uninstall for drivers/security/OS components by default.\n        \"\"\"\n        pub = (item.get(\"publisher\") or \"\").strip().lower()\n        name = (item.get(\"name\") or \"\").strip().lower()\n        protected_publishers = {\n            \"microsoft\", \"intel\", \"nvidia\", \"advanced micro devices\", \"amd\", \"realtek\",\n            \"qualcomm\", \"broadcom\", \"hewlett-packard\", \"hp\", \"dell\", \"lenovo\", \"asus\",\n            \"acer\", \"canon\", \"epson\", \"brother\", \"samsung\",\n        }\n        protected_keywords = {\n            \"driver\", \"chipset\", \"bluetooth\", \"wifi\", \"wireless\", \"lan\", \"ethernet\",\n            \"graphics\", \"display\", \"audio\", \"realtek\", \"nvidia\", \"intel\", \"amd\",\n            \"security update\", \"visual c++\", \"redistributable\", \"runtime\",\n        }\n        if any(p in pub for p in protected_publishers) or any(k in name for k in protected_keywords):\n            return True, f\"Protected publisher/app: {item.get('publisher') or 'N/A'}\"\n        return False, \"\"\n\n    def _uninst_verify_removed(self, item):\n        try:\n            hive = item.get(\"reg_hive\")\n            key_path = item.get(\"reg_key\")\n            if not hive or not key_path:\n                return True\n            # reg_hive stored as string in item; map it\n            hive_obj = winreg.HKEY_LOCAL_MACHINE if \"HKEY_LOCAL_MACHINE\" in hive or hive == \"HKLM\" else winreg.HKEY_CURRENT_USER\n            try:\n                k = winreg.OpenKey(hive_obj, key_path, 0, winreg.KEY_READ)\n                winreg.CloseKey(k)\n                return False\n            except Exception:\n                return True\n        except Exception:\n            return True\n\n    # \u2500\u2500 Standard Uninstall \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _uninst_standard(self):\n        items = self._get_sel_uninst()\n        if not items:\n            messagebox.showinfo(\"No Selection\",\"Select programs to uninstall.\"); return\n        no_cmd = [it for it in items if not it.get(\"has_uninstall\")]\n        if no_cmd:\n            self.uninst_status.config(\n                text=\"Is program ka uninstall command nahi mila. \"\n                     \"Force Uninstall ya manual removal use karo.\",\n                fg=C[\"warning\"])\n            messagebox.showwarning(\n                \"No Uninstall Command\",\n                \"In programs ke paas official uninstall command nahi hai:\\n\\n\"\n                + \"\\n\".join(x[\"name\"] for x in no_cmd[:12])\n                + (\"\\n...\" if len(no_cmd) &gt; 12 else \"\")\n                + \"\\n\\nSafe Uninstall skip hoga. Force Uninstall ya manual removal try karo.\")\n            items = [it for it in items if it.get(\"has_uninstall\")]\n            if not items:\n                return\n        protected = []\n        safe_items = []\n        for it in items:\n            ok, reason = self._uninst_is_protected(it)\n            if ok:\n                protected.append(f\"{it['name']} ({reason})\")\n            else:\n                safe_items.append(it)\n        if protected:\n            messagebox.showwarning(\"Protected Apps Skipped\",\n                                   \"Ye programs protected hain (drivers/system/security).\\n\"\n                                   \"Inko uninstall skip kiya ja raha hai:\\n\\n\" + \"\\n\".join(protected[:12]) +\n                                   (\"\\n...\" if len(protected) &gt; 12 else \"\"))\n        if not safe_items:\n            return\n        names = \"\\n\".join(it[\"name\"] for it in safe_items)\n        if not messagebox.askyesno(\"Safe Uninstall\",\n            f\"Run the official uninstaller for:\\n\\n{names}\\n\\n\"\n            \"A restore point is recommended. Silent mode is used only when the app provides it.\"): return\n        if not self._create_restore_point(\"Before Safe Uninstall\"):\n            return\n        self._audit_event(\"safe_uninstall_requested\", {\"items\": [x.get(\"name\") for x in safe_items]})\n        self._set_uninst_progress(10, f\"Safe uninstall queued for {len(safe_items)} program(s)\", C[\"accent4\"])\n        self._launch_job(\"safe_uninstall_batch\", self._run_uninst_batch_standard, safe_items)\n\n    def _run_uninst_batch_standard(self, items):\n        batch_leftovers = {}\n        total = len(items)\n        for idx, item in enumerate(items, start=1):\n            name = item[\"name\"]\n            self.after(0, lambda i=idx, t=total, n=name: self.uninst_status.config(\n                text=f\"[{i}/{t}] Uninstalling: {n}...\", fg=C[\"accent4\"]))\n            # Uninstall karo\n            cmd  = self._normalize_uninstall_command(item, quiet=True)\n            if cmd:\n                self._audit_event(\"safe_uninstall_command\", {\"name\": name, \"cmd\": cmd[:300]})\n                out, rc = self._run_cmd(cmd, timeout=300)\n                if rc == 0:\n                    self._log(f\"Uninstalled OK: {name}\", \"OK\")\n                else:\n                    self._log(f\"Uninstall issue: {name} (rc={rc})\", \"WARN\")\n            # \u2500\u2500 REVO STYLE: Uninstall ke turant baad leftover scan \u2500\u2500\u2500\u2500\u2500\n            self.after(0, lambda i=idx, t=total, n=name: self.uninst_status.config(\n                text=f\"[{i}/{t}] Scanning leftovers: {n}...\", fg=C[\"warning\"]))\n            try:\n                leftovers = self._scan_leftovers_for_item(item)\n            except InterruptedError:\n                self._set_uninst_progress(0, \"Safe uninstall leftover scan cancelled.\", C[\"warning\"])\n                self._audit_event(\"safe_uninstall_cancelled\", {\"completed\": idx - 1, \"total\": total})\n                break\n            batch_leftovers[name] = leftovers\n            # Leftover tree mein live update karo\n            if leftovers:\n                self.after(0, lambda n=name, lft=leftovers: self._append_batch_leftovers_to_tree(n, lft))\n            self.after(0, lambda i=idx, t=total, n=name, lc=len(leftovers): self.uninst_status.config(\n                text=f\"[{i}/{t}] Done: {n} | Leftovers: {lc}\",\n                fg=C[\"warning\"] if lc else C[\"success\"]))\n            self._set_uninst_progress(20 + (idx / max(total, 1)) * 75, f\"[{idx}/{total}] Safe uninstall scan complete: {name}\", C[\"warning\"] if leftovers else C[\"success\"])\n        self.after(500, self._scan_installed)\n        self.after(0, lambda: self._show_batch_leftover_preview(batch_leftovers))\n\n    def _append_batch_leftovers_to_tree(self, app_name, leftovers):\n        \"\"\"Batch uninstall ke baad leftovers turant right panel mein dikhao.\"\"\"\n        try:\n            # Section header\n            self.leftover_tree.insert(\"\", \"end\", values=(\"APP\", \"Info\", \"\", f\"--- {app_name} ---\"),\n                                      tags=(\"reg\",))\n            for item in leftovers:\n                ftype, path, risk, confidence, _meta = self._leftover_parts(item)\n                tag = \"risky\" if risk.lower() == \"risky\" else \"safe\"\n                self.leftover_tree.insert(\"\", \"end\", values=(ftype, risk, confidence, path), tags=(tag,))\n            # Auto-scroll\n            children = self.leftover_tree.get_children()\n            if children:\n                self.leftover_tree.see(children[-1])\n        except Exception:\n            pass\n\n    def _show_batch_leftover_preview(self, batch_leftovers):\n        apps_with_leftovers = {k: v for k, v in (batch_leftovers or {}).items() if v}\n        if not apps_with_leftovers:\n            self.uninst_status.config(text=\"Batch uninstall complete. No leftovers detected.\", fg=C[\"success\"])\n            messagebox.showinfo(\"Batch Uninstall Complete\",\n                                \"Selected programs uninstall ho gaye.\\n\\nNo obvious leftovers detected.\")\n            return\n\n        lines = []\n        for app_name, items in apps_with_leftovers.items():\n            risky = sum(1 for x in items if self._leftover_parts(x)[2].lower() == \"risky\")\n            lines.append(f\"* {app_name}  -&gt;  {len(items)} leftover(s), {risky} risky\")\n            for item in items[:8]:\n                ftype, path, risk, confidence, _meta = self._leftover_parts(item)\n                lines.append(f\"    [{ftype} | {risk} | {confidence}%] {path}\")\n            if len(items) &gt; 8:\n                lines.append(f\"    ... +{len(items)-8} more\")\n        preview = \"\\n\".join(lines)\n        if len(preview) &gt; 4500:\n            preview = preview[:4500] + \"\\n\\n...list truncated.\"\n\n        messagebox.showinfo(\n            \"Revo-style Leftovers Found\",\n            \"Uninstall ke baad ye leftovers detect hue:\\n\\n\"\n            f\"{preview}\\n\\n\"\n            \"Tip: Program select karke 'Scan Leftovers' aur phir 'Clean Leftovers' use karein.\"\n        )\n        self.uninst_status.config(\n            text=f\"Batch uninstall complete. Leftovers found in {len(apps_with_leftovers)} app(s).\",\n            fg=C[\"warning\"]\n        )\n\n    def _run_uninst_cmd(self, item, batch_leftovers=None):\n        name = item[\"name\"]\n        cmd  = self._normalize_uninstall_command(item, quiet=True)\n        if not cmd: return\n        self.after(0, lambda: self.uninst_status.config(\n            text=f\"Uninstalling: {name}...\", fg=C[\"accent4\"]))\n        self._log(f\"Uninstalling: {name}\", \"INFO\")\n        self._audit_event(\"safe_uninstall_command\", {\"name\": name, \"cmd\": cmd[:300]})\n        out, rc = self._run_cmd(cmd, timeout=300)\n        if rc == 0:\n            self._log(f\"Uninstalled OK: {name}\", \"OK\")\n            if not self._uninst_verify_removed(item):\n                self._log(f\"Verify WARN: {name} still present in registry list\", \"WARN\")\n            leftovers = self._scan_leftovers_for_item(item)\n            if batch_leftovers is not None:\n                batch_leftovers[name] = leftovers\n            self.after(0, lambda: self.uninst_status.config(\n                text=(f\"Uninstalled: {name} | Leftovers: {len(leftovers)}\"),\n                fg=(C[\"warning\"] if leftovers else C[\"success\"])))\n            if leftovers and batch_leftovers is None:\n                self.leftover_items = leftovers\n                self.after(0, self._populate_leftover_tree)\n                self.after(0, lambda: messagebox.showinfo(\n                    \"Leftovers Detected\",\n                    f\"{name} uninstall complete.\\n\\n\"\n                    f\"{len(leftovers)} leftover(s) detect hue.\\n\"\n                    \"Preview right panel me show ho raha hai.\"\n                ))\n            if batch_leftovers is None:\n                self.after(2000, self._scan_installed)\n        else:\n            self._log(f\"Uninstall issue: {name} (rc={rc})\", \"WARN\")\n            def ask_force():\n                if messagebox.askyesno(\"Uninstall Issue\",\n                    f\"Standard uninstall may have failed for:\\n{name}\\n\\n\"\n                    \"Run Force Remove to clean all leftovers?\"):\n                    self._launch_job(\"force_remove_item\", self._force_remove_item, item)\n            self.after(0, ask_force)\n\n    # \u2500\u2500 Force Remove (Revo-style deep clean) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _uninst_force(self):\n        items = self._get_sel_uninst()\n        if not items:\n            messagebox.showinfo(\"No Selection\",\"Select programs to force remove.\"); return\n        no_cmd = [it for it in items if not it.get(\"has_uninstall\")]\n        if no_cmd:\n            self.uninst_status.config(\n                text=\"Kuch programs mein uninstall command nahi \u2014 Force mode install path/registry se hataega.\",\n                fg=C[\"warning\"])\n            if not messagebox.askyesno(\n                \"No Uninstall Command\",\n                \"Ye programs mein official uninstall string nahi hai \u2014 Force mode registry/folders se hataega:\\n\\n\"\n                + \"\\n\".join(x[\"name\"] for x in no_cmd[:12])\n                + (\"\\n...\" if len(no_cmd) &gt; 12 else \"\")\n                + \"\\n\\nContinue with Force Uninstall?\"\n            ):\n                return\n        protected = []\n        safe_items = []\n        for it in items:\n            ok, reason = self._uninst_is_protected(it)\n            if ok:\n                protected.append(f\"{it['name']} ({reason})\")\n            else:\n                safe_items.append(it)\n        if protected:\n            messagebox.showwarning(\"Protected Apps Skipped\",\n                                   \"Force remove me bhi drivers/system apps skip kiye ja rahe hain:\\n\\n\" +\n                                   \"\\n\".join(protected[:12]) + (\"\\n...\" if len(protected) &gt; 12 else \"\"))\n        if not safe_items:\n            return\n        names = \"\\n\".join(it[\"name\"] for it in safe_items)\n        if not messagebox.askyesno(\"Force Uninstall\",\n            f\"Use Force Uninstall only for broken uninstallers or partially deleted apps.\\n\\n\"\n            f\"It will:\\n\"\n            f\" 1. Try the official uninstaller first\\n\"\n            f\" 2. Stop matching app processes\\n\"\n            f\" 3. Scan install folders, AppData, shortcuts, startup, services and registry\\n\"\n            f\" 4. Remove only matched leftovers after restore-point confirmation\\n\\n\"\n            f\"Programs:\\n{names}\\n\\nThis is permanent. Continue?\"\n        ): return\n        if not self._create_restore_point(f\"Force Remove: {safe_items[0]['name']}\"):\n            return\n        self._audit_event(\"force_uninstall_requested\", {\"items\": [x.get(\"name\") for x in safe_items]})\n        self._set_uninst_progress(5, f\"Force uninstall queued for {len(safe_items)} program(s)\", C[\"warning\"])\n        self._launch_job(\"force_uninstall\", self._run_force_remove_batch, safe_items)\n\n    def _run_force_remove_batch(self, items):\n        total = len(items)\n        try:\n            for idx, item in enumerate(items, start=1):\n                self._check_uninst_control()\n                self._set_uninst_progress(10 + ((idx - 1) / max(total, 1)) * 85, f\"[{idx}/{total}] Force uninstall: {item.get('name','')}\", C[\"warning\"])\n                self._force_remove_item(item, show_message=False)\n        except InterruptedError:\n            self._set_uninst_progress(0, \"Force uninstall cancelled at a safe checkpoint.\", C[\"warning\"])\n            self._audit_event(\"force_uninstall_cancelled\", {\"total\": total})\n            return\n        self._set_uninst_progress(100, \"Force uninstall batch complete. Restart is recommended.\", C[\"success\"])\n        self.after(0, lambda: messagebox.showinfo(\"Force Uninstall Complete\", \"Force uninstall batch complete.\\n\\nRestart is recommended to finish locked-file cleanup.\"))\n        self.after(2000, self._scan_installed)\n\n    def _app_keywords(self, name):\n        import re\n        words = re.split(r\"[ _\\-]+\", name.lower())\n        return [w for w in words if len(w) &gt; 3 and w not in\n                {\"microsoft\",\"windows\",\"update\",\"version\",\"setup\",\"install\",\n                 \"corp\",\"inc\",\"ltd\",\"llc\",\"software\",\"system\",\"service\"}]\n\n    def _force_remove_item(self, item, show_message=True):\n        name   = item[\"name\"]\n        words  = self._app_keywords(name)\n        removed = []\n        self.after(0, lambda: self.uninst_status.config(\n            text=f\"Force removing: {name}...\", fg=C[\"warning\"]))\n        self._log(f\"=== Force Remove START: {name} ===\", \"WARN\")\n\n        # 1. Run uninstaller silently\n        cmd = self._normalize_uninstall_command(item, quiet=True)\n        if cmd:\n            self._log(f\"[1] Uninstall cmd: {cmd[:100]}\", \"INFO\")\n            self._audit_event(\"force_uninstall_command\", {\"name\": name, \"cmd\": cmd[:300]})\n            self._run_cmd(cmd, timeout=180)\n            removed.append(\"Ran uninstaller\")\n        time.sleep(1)\n\n        # 2. Kill running processes\n        for proc in psutil.process_iter([\"pid\",\"name\",\"exe\"]):\n            try:\n                pname = (proc.info.get(\"name\") or \"\").lower()\n                pexe  = (proc.info.get(\"exe\")  or \"\").lower()\n                if any(w in pname or w in pexe for w in words):\n                    proc.kill()\n                    removed.append(f\"Killed process: {pname}\")\n                    self._log(f\"[2] Killed: {pname}\", \"OK\")\n            except: pass\n        time.sleep(1)\n\n        # 3. Delete install folder\n        inst_loc = item.get(\"install_loc\",\"\").strip()\n        candidate_dirs = []\n        if inst_loc and os.path.isdir(inst_loc):\n            candidate_dirs.append(inst_loc)\n        for base in [os.environ.get(\"ProgramFiles\",\"\"),\n                     os.environ.get(\"ProgramFiles(x86)\",\"\"),\n                     os.environ.get(\"LOCALAPPDATA\",\"\"),\n                     os.environ.get(\"APPDATA\",\"\")]:\n            if not base: continue\n            try:\n                for entry in Path(base).iterdir():\n                    if entry.is_dir() and any(w in entry.name.lower() for w in words):\n                        if str(entry) not in candidate_dirs:\n                            candidate_dirs.append(str(entry))\n            except: pass\n        for d in candidate_dirs:\n            try:\n                self._delete_leftover_path(d, \"FOLDER\")\n                removed.append(f\"Deleted folder: {d}\")\n                self._log(f\"[3] Deleted folder: {d}\", \"OK\")\n            except Exception as e:\n                self._log(f\"[3] Folder skipped: {d} ({e})\", \"WARN\")\n\n        # 4. Registry cleanup\n        reg_roots = [\n            (winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\"),\n            (winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\WOW6432Node\"),\n            (winreg.HKEY_CURRENT_USER,  r\"SOFTWARE\"),\n            (winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Services\"),\n            (winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\"),\n            (winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\"),\n            (winreg.HKEY_CURRENT_USER,  r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\"),\n        ]\n        for hive, root_path in reg_roots:\n            try:\n                root = winreg.OpenKey(hive, root_path, 0, winreg.KEY_READ)\n                to_del = []\n                i = 0\n                while True:\n                    try: sub = winreg.EnumKey(root, i); i += 1\n                    except OSError: break\n                    if any(w in sub.lower() for w in words):\n                        to_del.append(sub)\n                winreg.CloseKey(root)\n                for sub in to_del:\n                    full = root_path + \"\\\\\" + sub\n                    if root_path.lower().endswith(r\"currentcontrolset\\services\"):\n                        ok, err = self._native_delete_service(sub)\n                        if not ok:\n                            self._log(f\"[4] DeleteService fallback for {sub}: {err}\", \"WARN\")\n                            self._reg_delete_tree(hive, full)\n                    else:\n                        self._reg_delete_tree(hive, full)\n                    removed.append(f\"Reg: {full}\")\n                    self._log(f\"[4] Deleted reg: {full}\", \"OK\")\n            except: pass\n        # Also delete the specific stored key\n        try:\n            hive_map = {\"HKLM\": winreg.HKEY_LOCAL_MACHINE,\n                        \"HKCU\": winreg.HKEY_CURRENT_USER}\n            h = hive_map.get(item.get(\"reg_hive\",\"HKLM\"), winreg.HKEY_LOCAL_MACHINE)\n            self._reg_delete_tree(h, item.get(\"reg_key\",\"\"))\n        except: pass\n\n        # 5. AppData leftovers\n        for base in [os.environ.get(\"APPDATA\",\"\"), os.environ.get(\"LOCALAPPDATA\",\"\")]:\n            if not base: continue\n            try:\n                for entry in Path(base).iterdir():\n                    try:\n                        if any(w in entry.name.lower() for w in words):\n                            if entry.is_dir():\n                                self._delete_leftover_path(str(entry), \"FOLDER\")\n                            else:\n                                self._delete_leftover_path(str(entry), \"FILE\")\n                            removed.append(f\"AppData: {entry.name}\")\n                            self._log(f\"[5] AppData removed: {entry.name}\", \"OK\")\n                    except: pass\n            except: pass\n\n        # 6. Start Menu + Desktop shortcuts\n        for sm_base in [os.environ.get(\"APPDATA\",\"\"), os.environ.get(\"ProgramData\",\"\")]:\n            sm = Path(sm_base) / \"Microsoft\" / \"Windows\" / \"Start Menu\" / \"Programs\"\n            if sm.exists():\n                for entry in sm.rglob(\"*\"):\n                    try:\n                        if any(w in str(entry).lower() for w in words):\n                            if entry.is_file():\n                                self._delete_leftover_path(str(entry), \"SHORTCUT\")\n                            elif entry.is_dir():\n                                self._delete_leftover_path(str(entry), \"FOLDER\")\n                            removed.append(f\"StartMenu: {entry.name}\")\n                            self._log(f\"[6] StartMenu removed: {entry.name}\", \"OK\")\n                    except: pass\n        desktop = Path(os.path.expanduser(\"~\")) / \"Desktop\"\n        if desktop.exists():\n            for lnk in desktop.glob(\"*.lnk\"):\n                try:\n                    if any(w in lnk.stem.lower() for w in words):\n                        self._delete_leftover_path(str(lnk), \"SHORTCUT\")\n                        removed.append(f\"Desktop shortcut: {lnk.name}\")\n                        self._log(f\"[6] Desktop shortcut: {lnk.name}\", \"OK\")\n                except: pass\n\n        # 7. Temp folder\n        temp = os.environ.get(\"TEMP\",\"\")\n        if temp:\n            try:\n                for entry in Path(temp).iterdir():\n                    try:\n                        if any(w in str(entry).lower() for w in words):\n                            if entry.is_dir():\n                                self._delete_leftover_path(str(entry), \"FOLDER\")\n                            else:\n                                self._delete_leftover_path(str(entry), \"FILE\")\n                            removed.append(f\"Temp: {entry.name}\")\n                    except: pass\n            except: pass\n\n        # Done\n        summary = f\"Force remove complete: {name} \u2014 {len(removed)} items removed\"\n        self._log(f\"=== Force Remove DONE: {name} ({len(removed)} items) ===\", \"OK\")\n        self._audit_event(\"force_uninstall_finished\", {\"name\": name, \"removed_count\": len(removed)})\n        self.after(0, lambda: self.uninst_status.config(text=summary, fg=C[\"success\"]))\n        if show_message:\n            self.after(0, lambda: messagebox.showinfo(\n                \"Force Remove Complete\",\n                f\"Removed {len(removed)} items for:\\n{name}\\n\\n\"\n                \"Restart recommended to complete cleanup.\"))\n            self.after(2000, self._scan_installed)\n\n    def _reg_delete_tree(self, hive, path):\n        if not path: return\n        try:\n            key = winreg.OpenKey(hive, path, 0, winreg.KEY_READ)\n            subkeys = []\n            i = 0\n            while True:\n                try: subkeys.append(winreg.EnumKey(key, i)); i += 1\n                except OSError: break\n            winreg.CloseKey(key)\n            for sub in subkeys:\n                self._reg_delete_tree(hive, path + \"\\\\\" + sub)\n            winreg.DeleteKey(hive, path)\n        except: pass\n\n    # \u2500\u2500 Scan Leftovers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _scan_leftovers(self):\n        items = self._get_sel_uninst()\n        if not items:\n            messagebox.showinfo(\"No Selection\",\"Select a program to scan leftovers.\"); return\n        item = items[0]\n        self.leftover_tree.delete(*self.leftover_tree.get_children())\n        self.leftover_items = []\n        self._uninst_cancel_flag = False\n        self._uninst_pause_flag = False\n        if hasattr(self, \"uninst_pause_btn\"):\n            self.uninst_pause_btn.config(text=\"Pause Scan\")\n        self._set_uninst_progress(5, f\"Deep leftover scan for: {item['name']}...\", C[\"accent4\"])\n        self._audit_event(\"leftover_scan_started\", {\"name\": item.get(\"name\"), \"publisher\": item.get(\"publisher\")})\n        self._launch_job(\"scan_leftovers\", self._do_scan_leftovers, item)\n\n    def _do_scan_leftovers(self, item):\n        name = item[\"name\"]\n        try:\n            found = self._scan_leftovers_for_item(item, progress=True)\n        except InterruptedError:\n            self._audit_event(\"leftover_scan_cancelled\", {\"name\": name})\n            self._set_uninst_progress(0, f\"Leftover scan cancelled for: {name}\", C[\"warning\"])\n            return\n        self.leftover_items = found\n        self.after(0, self._populate_leftover_tree)\n        count = len(found)\n        risky = sum(1 for x in found if self._leftover_parts(x)[2].lower() == \"risky\")\n        safe = max(0, count - risky)\n        color = C[\"warning\"] if count else C[\"success\"]\n        self._set_uninst_progress(100, f\"{count} leftover(s) found for: {name}\", color)\n        if hasattr(self, \"uninst_summary_vars\"):\n            self.after(0, lambda: self.uninst_summary_vars[\"leftovers\"].set(str(count)))\n            self.after(0, lambda: self.uninst_summary_vars[\"risky\"].set(str(risky)))\n            self.after(0, lambda: self.uninst_summary_vars[\"safe\"].set(str(safe)))\n        self._audit_event(\"leftover_scan_finished\", {\"name\": name, \"count\": count, \"risky\": risky, \"safe\": safe})\n\n    def _scan_leftovers_for_item(self, item, progress=False):\n        name = item.get(\"name\", \"\")\n        words = self._app_keywords(name)\n        if not words:\n            fallback = re.sub(r\"[^a-z0-9]+\", \" \", name.lower()).strip().split()\n            words = [w for w in fallback if len(w) &gt;= 3][:3]\n        if not words:\n            return []\n\n        found = []\n        seen = set()\n\n        def add_item(ftype, path, confidence=70, risk=None, source=\"\", action=\"delete\", meta=None):\n            self._add_leftover_item(found, seen, ftype, path, confidence, risk, source, action, meta)\n\n        def word_hit(text):\n            low = str(text or \"\").lower()\n            return any(w in low for w in words)\n\n        def progress_step(pct, text):\n            if progress:\n                self._set_uninst_progress(pct, text, C[\"accent4\"])\n\n        install_loc = (item.get(\"install_loc\") or \"\").strip().strip('\"')\n        if install_loc and os.path.exists(install_loc):\n            add_item(\"FOLDER\", install_loc, 95, \"Risky\", \"InstallLocation\")\n\n        progress_step(12, \"Scanning registry residue...\")\n        reg_roots = [\n            (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\", 2),\n            (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\WOW6432Node\", 2),\n            (\"HKCU\", winreg.HKEY_CURRENT_USER,  r\"SOFTWARE\", 2),\n            (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Services\", 1),\n            (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\", 1),\n            (\"HKCU\", winreg.HKEY_CURRENT_USER,  r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\", 1),\n        ]\n        scanned = [0]\n        deadline = time.time() + 25\n\n        def scan_reg_level(hive_name, hive, root_path, depth):\n            self._check_uninst_control()\n            if scanned[0] &gt; 5000 or time.time() &gt; deadline:\n                return\n            try:\n                root = winreg.OpenKey(hive, root_path, 0, winreg.KEY_READ)\n            except Exception:\n                return\n            try:\n                try:\n                    value_text = _registry_value_text(root)\n                    if word_hit(root_path) or word_hit(value_text):\n                        add_item(\"REG\", f\"{hive_name}\\\\{root_path}\", 78, \"Risky\", \"Registry values\")\n                except Exception:\n                    pass\n                i = 0\n                while True:\n                    self._check_uninst_control()\n                    try:\n                        sub = winreg.EnumKey(root, i)\n                        i += 1\n                    except OSError:\n                        break\n                    scanned[0] += 1\n                    child_path = root_path + \"\\\\\" + sub\n                    if word_hit(sub):\n                        add_item(\"REG\", f\"{hive_name}\\\\{child_path}\", 88 if \"uninstall\" in root_path.lower() else 74, \"Risky\", \"Registry key\")\n                    if depth &gt; 0 and scanned[0] &lt; 5000 and time.time() &lt;= deadline:\n                        scan_reg_level(hive_name, hive, child_path, depth - 1)\n            finally:\n                try:\n                    winreg.CloseKey(root)\n                except Exception:\n                    pass\n\n        for hive_name, hive, root_path, depth in reg_roots:\n            scan_reg_level(hive_name, hive, root_path, depth)\n\n        progress_step(38, \"Scanning install folders, AppData and shortcuts...\")\n        search_bases = [\n            os.environ.get(\"ProgramFiles\",\"\"),\n            os.environ.get(\"ProgramFiles(x86)\",\"\"),\n            os.environ.get(\"ProgramData\",\"\"),\n            os.environ.get(\"APPDATA\",\"\"),\n            os.environ.get(\"LOCALAPPDATA\",\"\"),\n            os.environ.get(\"TEMP\",\"\"),\n            str(Path(os.path.expanduser(\"~\")) / \"Desktop\"),\n        ]\n        for base in search_bases:\n            self._check_uninst_control()\n            if not base:\n                continue\n            try:\n                for entry in Path(base).iterdir():\n                    self._check_uninst_control()\n                    try:\n                        if word_hit(entry.name):\n                            add_item(\"FOLDER\" if entry.is_dir() else \"FILE\", str(entry), 72, None, \"Filesystem\")\n                    except Exception:\n                        pass\n            except Exception:\n                pass\n\n        for sm_base in [os.environ.get(\"APPDATA\",\"\"), os.environ.get(\"ProgramData\",\"\")]:\n            self._check_uninst_control()\n            sm = Path(sm_base) / \"Microsoft\" / \"Windows\" / \"Start Menu\" / \"Programs\"\n            if sm.exists():\n                try:\n                    for idx, entry in enumerate(sm.rglob(\"*.lnk\")):\n                        if idx % 50 == 0:\n                            self._check_uninst_control()\n                        if word_hit(str(entry)):\n                            add_item(\"SHORTCUT\", str(entry), 68, \"Safe\", \"Start Menu shortcut\")\n                except Exception:\n                    pass\n\n        progress_step(58, \"Scanning startup entries...\")\n        run_roots = [\n            (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\"),\n            (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Run\"),\n            (\"HKCU\", winreg.HKEY_CURRENT_USER,  r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\"),\n            (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce\"),\n            (\"HKCU\", winreg.HKEY_CURRENT_USER,  r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce\"),\n        ]\n        for hive_name, hive, run_path in run_roots:\n            self._check_uninst_control()\n            try:\n                key = winreg.OpenKey(hive, run_path, 0, winreg.KEY_READ)\n                i = 0\n                while True:\n                    try:\n                        value_name, value, _vtype = winreg.EnumValue(key, i)\n                        i += 1\n                    except OSError:\n                        break\n                    if word_hit(value_name) or word_hit(value):\n                        display = f\"{hive_name}\\\\{run_path}\\\\{value_name}\"\n                        add_item(\"STARTUP\", display, 76, \"Risky\", \"Registry startup\",\n                                 meta={\"hive\": hive_name, \"path\": run_path, \"value\": value_name})\n                winreg.CloseKey(key)\n            except Exception:\n                pass\n\n        progress_step(70, \"Scanning Windows services...\")\n        try:\n            for svc in psutil.win_service_iter():\n                self._check_uninst_control()\n                try:\n                    info = svc.as_dict()\n                    svc_name = info.get(\"name\", \"\") or \"\"\n                    disp = info.get(\"display_name\", \"\") or \"\"\n                    bin_path = info.get(\"binpath\", \"\") or \"\"\n                    if word_hit(svc_name) or word_hit(disp) or word_hit(bin_path):\n                        add_item(\"SERVICE\", svc_name, 72, \"Risky\", \"Windows service\",\n                                 meta={\"service\": svc_name, \"display\": disp, \"binpath\": bin_path})\n                except Exception:\n                    pass\n        except Exception:\n            pass\n\n        progress_step(82, \"Scanning scheduled tasks...\")\n        try:\n            ps_terms = \"@(\" + \",\".join(_ps_single_quote(w) for w in words[:6]) + \")\"\n            script = f\"\"\"\n$terms = {ps_terms}\n$items = @()\ntry {{\n    $items = Get-ScheduledTask -ErrorAction SilentlyContinue | Where-Object {{\n        $txt = ($_.TaskName + ' ' + $_.TaskPath + ' ' + $_.URI).ToLower()\n        foreach($t in $terms) {{ if($txt.Contains($t.ToLower())) {{ return $true }} }}\n        return $false\n    }} | Select-Object -First 80 TaskName,TaskPath,State\n}} catch {{}}\n$items | ConvertTo-Json -Depth 3\n\"\"\"\n            out, _ = self._run_powershell(script, timeout=35)\n            for task in self._json_items_from_output(out):\n                self._check_uninst_control()\n                task_name = str(task.get(\"TaskName\", \"\") or \"\")\n                task_path = str(task.get(\"TaskPath\", \"\\\\\") or \"\\\\\")\n                full = (task_path.rstrip(\"\\\\\") + \"\\\\\" + task_name).replace(\"\\\\\\\\\", \"\\\\\")\n                add_item(\"TASK\", full, 66, \"Risky\", \"Scheduled Task\",\n                         meta={\"task\": full, \"state\": task.get(\"State\", \"\")})\n        except Exception:\n            pass\n\n        found.sort(key=lambda rec: (self._leftover_parts(rec)[0], -self._leftover_parts(rec)[3], self._leftover_parts(rec)[1].lower()))\n        return found[:2000]\n\n    def _populate_leftover_tree(self):\n        self.leftover_tree.delete(*self.leftover_tree.get_children())\n        risky = 0\n        safe = 0\n        for item in self.leftover_items:\n            ftype, path, risk, confidence, _meta = self._leftover_parts(item)\n            if risk.lower() == \"risky\":\n                risky += 1\n                tag = \"risky\"\n            else:\n                safe += 1\n                tag = \"safe\"\n            self.leftover_tree.insert(\"\", \"end\", tags=(tag,),\n                                      values=(ftype, risk, confidence, path))\n        if hasattr(self, \"uninst_summary_vars\"):\n            self.uninst_summary_vars[\"leftovers\"].set(str(len(self.leftover_items)))\n            self.uninst_summary_vars[\"risky\"].set(str(risky))\n            self.uninst_summary_vars[\"safe\"].set(str(safe))\n\n    # \u2500\u2500 Clean Leftovers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _clean_leftovers(self):\n        if not self.leftover_items:\n            messagebox.showinfo(\"Nothing\",\"Scan leftovers first.\"); return\n        n = len(self.leftover_items)\n        risky = sum(1 for x in self.leftover_items if self._leftover_parts(x)[2].lower() == \"risky\")\n        if not messagebox.askyesno(\"Clean Reviewed Leftovers\",\n            f\"Permanently clean {n} reviewed leftover item(s)?\\n\\n\"\n            f\"Risky items: {risky}\\n\"\n            \"This can remove files, folders, registry keys, services, startup entries and scheduled tasks.\\n\\n\"\n            \"Create/allow a restore point before continuing.\"): return\n        if not self._create_restore_point(\"Before Leftover Cleanup\"):\n            return\n        self._audit_event(\"leftover_cleanup_requested\", {\"count\": n, \"risky\": risky})\n        self._set_uninst_progress(5, f\"Cleaning {n} reviewed leftover item(s)...\", C[\"warning\"])\n        self._launch_job(\"clean_leftovers\", self._do_clean_leftovers)\n\n    def _do_clean_leftovers(self):\n        cleaned = 0; errors = 0\n        total = len(self.leftover_items)\n        for idx, item in enumerate(list(self.leftover_items), start=1):\n            ftype, path, _risk, _confidence, meta = self._leftover_parts(item)\n            try:\n                self._check_uninst_control()\n                if ftype == \"REG\":\n                    parts = path.split(\"\\\\\", 2)\n                    if len(parts) &lt; 3: continue\n                    hmap = {\"HKLM\": winreg.HKEY_LOCAL_MACHINE,\n                            \"HKCU\": winreg.HKEY_CURRENT_USER}\n                    h = hmap.get(parts[0])\n                    if not h: continue\n                    self._reg_delete_tree(h, parts[1] + \"\\\\\" + parts[2])\n                    cleaned += 1\n                elif ftype in (\"FOLDER\", \"FILE\", \"SHORTCUT\"):\n                    if os.path.exists(path):\n                        self._delete_leftover_path(path, ftype); cleaned += 1\n                elif ftype == \"SERVICE\":\n                    svc = meta.get(\"service\") or path\n                    ok, err = self._native_delete_service(svc)\n                    if not ok:\n                        raise RuntimeError(err or \"DeleteService failed\")\n                    cleaned += 1\n                elif ftype == \"STARTUP\":\n                    hive_name = meta.get(\"hive\", \"\")\n                    run_path = meta.get(\"path\", \"\")\n                    value_name = meta.get(\"value\", \"\")\n                    hmap = {\"HKLM\": winreg.HKEY_LOCAL_MACHINE,\n                            \"HKCU\": winreg.HKEY_CURRENT_USER}\n                    h = hmap.get(hive_name)\n                    if h and run_path and value_name:\n                        key = winreg.OpenKey(h, run_path, 0, winreg.KEY_SET_VALUE)\n                        try:\n                            winreg.DeleteValue(key, value_name)\n                        finally:\n                            winreg.CloseKey(key)\n                        cleaned += 1\n                elif ftype == \"TASK\":\n                    task_name = meta.get(\"task\") or path\n                    out, rc = self._run_cmd(f'schtasks /Delete /TN \"{task_name}\" /F', timeout=45)\n                    if rc != 0:\n                        raise RuntimeError(out[-300:] if out else \"schtasks delete failed\")\n                    cleaned += 1\n                self._set_uninst_progress(5 + (idx / max(total, 1)) * 90, f\"Cleaning leftovers [{idx}/{total}]...\", C[\"warning\"])\n            except InterruptedError:\n                self._set_uninst_progress(0, \"Leftover cleanup cancelled.\", C[\"warning\"])\n                self._audit_event(\"leftover_cleanup_cancelled\", {\"cleaned\": cleaned, \"errors\": errors})\n                return\n            except Exception as e:\n                errors += 1\n                self._audit_event(\"leftover_cleanup_error\", {\"type\": ftype, \"path\": path, \"error\": str(e)})\n        summary = f\"Cleaned {cleaned} leftover(s). Errors: {errors}\"\n        self._set_uninst_progress(100, summary, C[\"success\"] if errors == 0 else C[\"warning\"])\n        self._log(summary, \"OK\")\n        self._audit_event(\"leftover_cleanup_finished\", {\"cleaned\": cleaned, \"errors\": errors})\n        self.leftover_items = []\n        self.after(0, self._populate_leftover_tree)\n\n    def _reg_read_str(self, key, value_name):\n        try:\n            val, _ = winreg.QueryValueEx(key, value_name)\n            return str(val)\n        except:\n            return \"\"\n\n    def _uninstall_selected_with_confirm(self):\n        \"\"\"Legacy compatibility \u2014 calls standard uninstall\"\"\"\n        self._uninst_standard()\n\n\n        # ---------- HARDWARE, PRINTER, DRIVER, BACKUP, REPORT, LOG (unchanged, but confirm added where needed) ----------\n    def _build_hardware(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udda5\ufe0f Hardware Health\", \"Real stats\", hw=True)\n        self._action_card_grid(frame, [\n            (\"\ud83d\udd0d\", \"Scan Hardware\", \"CPU, GPU, RAM, Disk info scan karo\", C[\"btn_hw\"], self._scan_hw),\n        ], cols=1)\n        content = tk.Frame(frame, bg=C[\"card\"])\n        content.pack(fill=\"both\", expand=True, padx=16, pady=10)\n        self.hw_log = self._scrolled_text(content, height=22)\n        return frame\n\n    def _scan_hw(self):\n        self._launch_job(\"scan_hw\", self._do_scan_hw)\n\n    def _do_scan_hw(self):\n        self._append_log(self.hw_log, \"\u2550\"*50, C[\"border\"])\n        out, _ = self._run_cmd(\"wmic cpu get Name,LoadPercentage /format:list\")\n        self._append_log(self.hw_log, \"-- CPU --\", C[\"hw_accent\"])\n        for l in out.splitlines():\n            if \"=\" in l:\n                self._append_log(self.hw_log, l, C[\"text\"])\n        out, _ = self._run_cmd(\"wmic path win32_VideoController get Name,AdapterRAM,DriverVersion /format:list\")\n        self._append_log(self.hw_log, \"-- GPU --\", C[\"hw_accent\"])\n        for l in out.splitlines():\n            if \"=\" in l and l.split(\"=\")[1].strip():\n                if \"AdapterRAM\" in l:\n                    try:\n                        l = f\"VRAM={self._fmt_size(int(l.split('=')[1]))}\"\n                    except:\n                        pass\n                self._append_log(self.hw_log, l, C[\"text\"])\n        self._append_log(self.hw_log, \"\u2705 Hardware scan complete\", C[\"success\"])\n\n    def _build_printer(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udda8\ufe0f Advanced Printer Fixer\",\n                             \"Spooler reset, stuck jobs, driver repair, network printer \u2014 sab kuch\")\n\n        self._printer_action_buttons = []\n        printer_actions = [\n            (\"\ud83d\udd0d\", \"Detect Printers\",       \"System pe printers dhundho\",           C[\"btn_info\"],   self._printer_detect),\n            (\"\ud83d\udd01\", \"Reset Spooler\",         \"Print Spooler service restart karo\",   C[\"btn_warn\"],   self._printer_reset_spooler),\n            (\"\ud83d\uddd1\",  \"Clear Stuck Jobs\",     \"Atkaye hue print jobs saaf karo\",       C[\"btn_danger\"], self._printer_clear_jobs),\n            (\"\ud83d\udd27\", \"Full Auto-Repair\",      \"Spooler + jobs + driver full fix\",     C[\"btn_hw\"],     self._printer_full_repair),\n            (\"\ud83e\uddf9\", \"Driver Purge/Reinstall\",\"Printer driver saaf karo + reinstall\", C[\"btn_danger\"], self._printer_driver_purge_flow),\n            (\"\ud83d\udda5\",  \"Set as Default\",       \"Selected printer default set karo\",    C[\"btn_chip\"],   self._printer_set_default),\n            (\"\u274c\", \"Remove Printer\",        \"Selected printer hata do\",             C[\"btn_danger\"], self._printer_remove),\n            (\"\ud83c\udf10\", \"Network Printer Setup\", \"Network printer add karo\",             C[\"btn_info\"],   self._printer_network_setup),\n        ]\n        printer_toolbar = tk.Frame(frame, bg=C[\"bg\"])\n        printer_toolbar.pack(fill=\"x\", padx=12, pady=(4, 2))\n        for col in range(4):\n            printer_toolbar.columnconfigure(col, weight=1)\n        for idx, (_icon, title, _subtitle, color, cmd_func) in enumerate(printer_actions):\n            btn = tk.Button(printer_toolbar, text=title, font=FONTS[\"small\"],\n                            bg=color, fg=C[\"text\"], bd=0, padx=8, pady=4,\n                            cursor=\"hand2\", command=cmd_func)\n            btn.grid(row=idx // 4, column=idx % 4, sticky=\"ew\", padx=3, pady=2)\n            self._printer_action_buttons.append(btn)\n\n        # \u2500\u2500 Tab Notebook \u2014 Tab1: Printer Fixer, Tab2: Sharing Center \u2500\u2500\n        nb = ttk.Notebook(frame)\n        nb.pack(fill=\"both\", expand=True, padx=8, pady=(4,8))\n\n        # Tab 1 \u2014 Printer Fixer\n        tab1 = tk.Frame(nb, bg=C[\"bg\"])\n        nb.add(tab1, text=\"  \ud83d\udda8  Printer Fixer  \")\n\n        paned = tk.Frame(tab1, bg=C[\"bg\"])\n        paned.pack(fill=\"both\", expand=True, padx=8, pady=(4,8))\n        paned.columnconfigure(0, weight=2)\n        paned.columnconfigure(1, weight=3)\n        paned.rowconfigure(0, weight=1)\n\n        # Left \u2014 printer list + status cards\n        left = tk.Frame(paned, bg=C[\"card\"])\n        left.grid(row=0, column=0, sticky=\"nsew\", padx=(0,6))\n        left.rowconfigure(1, weight=1)\n\n        # Status cards\n        cards = tk.Frame(left, bg=C[\"card\"])\n        cards.pack(fill=\"x\", pady=(8,4), padx=8)\n        self.printer_stat_vars = {}\n        for i,(k,lbl,col) in enumerate([\n            (\"total\",   \"Total Printers\", C[\"accent\"]),\n            (\"online\",  \"Online\",         C[\"success\"]),\n            (\"offline\", \"Offline\",        C[\"error\"]),\n            (\"default\", \"Default\",        C[\"accent2\"]),\n        ]):\n            cards.columnconfigure(i, weight=1)\n            c = tk.Frame(cards, bg=C[\"bg\"], padx=8, pady=6)\n            c.grid(row=0, column=i, padx=3, sticky=\"ew\")\n            tk.Label(c, text=lbl, font=FONTS[\"small\"], fg=col, bg=C[\"bg\"]).pack(anchor=\"w\")\n            v = tk.StringVar(value=\"--\")\n            self.printer_stat_vars[k] = v\n            tk.Label(c, textvariable=v, font=(\"Segoe UI\",14,\"bold\"),\n                     fg=col, bg=C[\"bg\"]).pack(anchor=\"w\")\n\n        # Printer list\n        tk.Label(left, text=\"  Detected Printers\", font=FONTS[\"subhead\"],\n                 fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=8, pady=(4,2))\n        cols = (\"Name\",\"Status\",\"Default\",\"Jobs\")\n        self.printer_tree = ttk.Treeview(left, columns=cols, show=\"headings\",\n                                          height=12, style=\"Custom.Treeview\",\n                                          selectmode=\"browse\")\n        for col, w in zip(cols, [200,90,70,50]):\n            self.printer_tree.heading(col, text=col)\n            self.printer_tree.column(col, width=w, anchor=\"center\")\n        self.printer_tree.tag_configure(\"online\",  foreground=C[\"success\"])\n        self.printer_tree.tag_configure(\"offline\", foreground=C[\"error\"])\n        self.printer_tree.tag_configure(\"default\", foreground=C[\"warning\"])\n        psb = ttk.Scrollbar(left, orient=\"vertical\", command=self.printer_tree.yview)\n        self.printer_tree.configure(yscrollcommand=psb.set)\n        self.printer_tree.pack(side=\"left\", fill=\"both\", expand=True, padx=(8,0), pady=(0,8))\n        psb.pack(side=\"right\", fill=\"y\", pady=(0,8), padx=(0,4))\n        self.printer_tree.bind(\"&lt;&gt;\", self._on_printer_select)\n        self._printer_data = []\n\n        # Right \u2014 action log + diagnostics\n        right = tk.Frame(paned, bg=C[\"card\"])\n        right.grid(row=0, column=1, sticky=\"nsew\")\n        right.rowconfigure(1, weight=1)\n\n        # Quick action buttons\n        qa = tk.Frame(right, bg=C[\"card\"])\n        qa.pack(fill=\"x\", padx=8, pady=(8,4))\n        tk.Label(qa, text=\"Quick Fixes:\", font=FONTS[\"small\"],\n                 fg=C[\"text_dim\"], bg=C[\"card\"]).grid(row=0, column=0, sticky=\"w\", padx=(0,6), pady=(0,3))\n        quick_grid = tk.Frame(qa, bg=C[\"card\"])\n        quick_grid.grid(row=1, column=0, sticky=\"ew\")\n        qa.columnconfigure(0, weight=1)\n        for idx, (lbl, fn) in enumerate([\n            (\"Restart Spooler\",       self._printer_reset_spooler),\n            (\"SFC /scannow\",          self._printer_sfc),\n            (\"PrintNightmare Fix\",    self._printer_printnightmare),\n            (\"Run Troubleshooter\",    self._printer_troubleshooter),\n            (\"Open Print Queue\",      self._printer_open_queue),\n            (\"Driver Audit\",          self._printer_driver_signature_audit),\n            (\"Spooler Snapshot\",      self._printer_spooler_snapshot),\n        ]):\n            row, col = divmod(idx, 3)\n            quick_grid.columnconfigure(col, weight=1)\n            btn = tk.Button(quick_grid, text=lbl, font=FONTS[\"small\"],\n                            bg=C[\"btn_info\"], fg=\"white\", bd=0, padx=8, pady=3,\n                            cursor=\"hand2\", command=fn)\n            btn.grid(row=row, column=col, sticky=\"ew\", padx=3, pady=2)\n            self._printer_action_buttons.append(btn)\n\n        status_panel = tk.Frame(right, bg=C[\"card\"])\n        status_panel.pack(fill=\"x\", padx=8, pady=(0,4))\n        tk.Label(status_panel, text=\"Execution:\", font=FONTS[\"small\"],\n                 fg=C[\"text_dim\"], bg=C[\"card\"]).grid(row=0, column=0, sticky=\"w\", padx=(0,6))\n        self.printer_exec_status_lbl = tk.Label(status_panel, text=\"Ready\",\n                                                font=FONTS[\"small\"], fg=C[\"text_dim\"],\n                                                bg=C[\"card\"])\n        self.printer_exec_status_lbl.grid(row=0, column=1, sticky=\"w\")\n        self.printer_exec_time_lbl = tk.Label(status_panel, text=\"Elapsed: 00:00 | ETA: --\",\n                                              font=FONTS[\"small\"], fg=C[\"text_dim\"],\n                                              bg=C[\"card\"])\n        self.printer_exec_time_lbl.grid(row=1, column=0, columnspan=2, sticky=\"w\", pady=(2, 0))\n        status_panel.columnconfigure(1, weight=1)\n\n        tk.Label(right, text=\"  \ud83d\udcdd Repair Log\",\n                 font=FONTS[\"subhead\"], fg=C[\"accent2\"], bg=C[\"card\"]).pack(\n                 anchor=\"w\", padx=8, pady=(4,2))\n        self.printer_log = self._scrolled_text(right, height=12)\n        tk.Label(right, text=\"  \ud83d\udd0e Execution Trace\",\n                 font=FONTS[\"subhead\"], fg=C[\"accent2\"], bg=C[\"card\"]).pack(\n                 anchor=\"w\", padx=8, pady=(4,2))\n        self.printer_trace_log = self._scrolled_text(right, height=4)\n\n        # Spooler status indicator\n        bot = tk.Frame(right, bg=C[\"card\"])\n        bot.pack(fill=\"x\", padx=8, pady=(4,8))\n        tk.Label(bot, text=\"Spooler:\", font=FONTS[\"small\"],\n                 fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self.spooler_status_lbl = tk.Label(bot, text=\"Unknown\",\n                                            font=FONTS[\"small\"], fg=C[\"warning\"],\n                                            bg=C[\"card\"])\n        self.spooler_status_lbl.pack(side=\"left\", padx=6)\n        self._btn(bot, \"\u21bb Refresh Status\", C[\"btn_chip\"],\n                  self._refresh_spooler_status).pack(side=\"left\", padx=6)\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # \ud83d\udd17 TAB 2 \u2014 PRINTER SHARING CENTER\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        tab2 = tk.Frame(nb, bg=C[\"bg\"])\n        nb.add(tab2, text=\"  \ud83d\udd17  Sharing Center (Host &amp; Client)  \")\n\n        # Header inside tab2\n        share_hdr = tk.Frame(tab2, bg=C[\"panel\"])\n        share_hdr.pack(fill=\"x\")\n        tk.Label(share_hdr, text=\"  \ud83d\udd17 Printer Sharing Center\",\n                 font=FONTS[\"heading\"], fg=C[\"accent4\"], bg=C[\"panel\"]).pack(side=\"left\", pady=8, padx=8)\n        tk.Label(share_hdr,\n                 text=\"Har port, service, security alag-alag kholo \u2014 Host &amp; Client dono ke liye\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"left\", pady=8)\n        self._btn(share_hdr, \"\ud83d\udd0e Check Sharing Status\", C[\"btn_chip\"],\n                  self._check_sharing_status).pack(side=\"right\", padx=10, pady=6)\n\n        # Scrollable area inside tab2\n        sc_outer = tk.Frame(tab2, bg=C[\"bg\"])\n        sc_outer.pack(fill=\"both\", expand=True, padx=0, pady=0)\n        sc_canvas = tk.Canvas(sc_outer, bg=C[\"bg\"], highlightthickness=0)\n        sc_sb = ttk.Scrollbar(sc_outer, orient=\"vertical\", command=sc_canvas.yview)\n        sc_canvas.configure(yscrollcommand=sc_sb.set)\n        sc_sb.pack(side=\"right\", fill=\"y\")\n        sc_canvas.pack(side=\"left\", fill=\"both\", expand=True)\n        share_body = tk.Frame(sc_canvas, bg=C[\"bg\"])\n        sc_win = sc_canvas.create_window((0,0), window=share_body, anchor=\"nw\")\n        def _sc_resize(e):\n            sc_canvas.configure(scrollregion=sc_canvas.bbox(\"all\"))\n            sc_canvas.itemconfig(sc_win, width=sc_canvas.winfo_width())\n        share_body.bind(\"\", _sc_resize)\n        def _sc_canvas_configure(e):\n            sc_canvas.itemconfig(sc_win, width=e.width)\n            sc_canvas.configure(scrollregion=sc_canvas.bbox(\"all\"))\n        sc_canvas.bind(\"\", _sc_canvas_configure)\n        self._bind_scoped_mousewheel(share_body, sc_canvas)\n\n        share_body.columnconfigure(0, weight=1)\n        share_body.columnconfigure(1, weight=1)\n\n        def _section_card(parent, title, subtitle, bg_hdr, fg_title, col):\n            \"\"\"Card with header for HOST or CLIENT sections.\"\"\"\n            frm = tk.Frame(parent, bg=C[\"card\"], bd=0)\n            hdr = tk.Frame(frm, bg=bg_hdr)\n            hdr.pack(fill=\"x\")\n            tk.Label(hdr, text=title, font=FONTS[\"subhead\"], fg=fg_title, bg=bg_hdr).pack(anchor=\"w\", padx=10, pady=6)\n            tk.Label(hdr, text=subtitle, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=bg_hdr).pack(anchor=\"w\", padx=10, pady=(0,6))\n            return frm\n\n        def _grp_label(parent, text, bg=None):\n            bg = bg or C[\"card\"]\n            tk.Label(parent, text=text, font=FONTS[\"small\"],\n                     fg=C[\"accent4\"], bg=bg, anchor=\"w\").pack(fill=\"x\", padx=10, pady=(8,2))\n            tk.Frame(parent, bg=C[\"border\"], height=1).pack(fill=\"x\", padx=10)\n\n        def _ibtn(parent, text, color, cmd, desc=\"\"):\n            row = tk.Frame(parent, bg=C[\"card\"])\n            row.pack(fill=\"x\", padx=8, pady=2)\n            tk.Button(row, text=text, font=FONTS[\"body\"],\n                      bg=color, fg=C[\"bg\"] if color in (C[\"accent\"],C[\"success\"]) else C[\"text\"],\n                      bd=0, padx=10, pady=6, cursor=\"hand2\", anchor=\"w\",\n                      command=cmd).pack(side=\"left\", fill=\"x\", expand=True)\n            if desc:\n                tk.Label(row, text=desc, font=(\"Consolas\",8),\n                         fg=C[\"text_dim\"], bg=C[\"card\"], anchor=\"w\", wraplength=260).pack(side=\"left\", padx=(6,4))\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # \ud83d\udda5 HOST COMPUTER COLUMN\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        host_frame = _section_card(share_body,\n            \"\ud83d\udda5  HOST COMPUTER  \u2014  Jis PC pe printer laga hai\",\n            \"Yahan printer physically connected hai (USB/LPT)\",\n            \"#1A3A2A\", C[\"accent\"], 0)\n        host_frame.grid(row=0, column=0, sticky=\"nsew\", padx=(8,4), pady=6)\n\n        # \u2500\u2500 HOST: PORTS \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(host_frame, \"\ud83d\udd0c  PORTS \u2014 Firewall mein open karo (IN + OUT)\")\n        _ibtn(host_frame, \"\u25b6 Port 445 TCP+UDP  \u2014  SMB File &amp; Printer Sharing\",\n              C[\"btn_chip\"], lambda: self._open_single_port_host(445,\"TCP+UDP\",\"SMB-Printer-Sharing\"),\n              \"Printer sharing ka main port\")\n        _ibtn(host_frame, \"\u25b6 Port 139 TCP  \u2014  NetBIOS Session Service\",\n              C[\"btn_chip\"], lambda: self._open_single_port_host(139,\"TCP\",\"NetBIOS-Session\"),\n              \"Purane Windows me sharing ke liye\")\n        _ibtn(host_frame, \"\u25b6 Port 137 UDP  \u2014  NetBIOS Name Service\",\n              C[\"btn_chip\"], lambda: self._open_single_port_host(137,\"UDP\",\"NetBIOS-Name\"),\n              \"Network name resolution\")\n        _ibtn(host_frame, \"\u25b6 Port 138 UDP  \u2014  NetBIOS Datagram Service\",\n              C[\"btn_chip\"], lambda: self._open_single_port_host(138,\"UDP\",\"NetBIOS-Datagram\"),\n              \"NetBIOS broadcast messages\")\n        _ibtn(host_frame, \"\u25b6 Port 135 TCP  \u2014  RPC Endpoint Mapper\",\n              C[\"btn_chip\"], lambda: self._open_single_port_host(135,\"TCP\",\"RPC-Endpoint\"),\n              \"Windows Remote Procedure Call\")\n        _ibtn(host_frame, \"\u25b6 Port 9100 TCP  \u2014  RAW Print / JetDirect\",\n              C[\"btn_chip\"], lambda: self._open_single_port_host(9100,\"TCP\",\"RAW-Print-JetDirect\"),\n              \"Network printer direct print port\")\n        _ibtn(host_frame, \"\u25b6 Port 631 TCP  \u2014  IPP Internet Printing Protocol\",\n              C[\"btn_chip\"], lambda: self._open_single_port_host(631,\"TCP\",\"IPP-Printing\"),\n              \"Internet Printing Protocol (IPP)\")\n        _ibtn(host_frame, \"\u25b6 Port 515 TCP  \u2014  LPD/LPR Line Printer Daemon\",\n              C[\"btn_chip\"], lambda: self._open_single_port_host(515,\"TCP\",\"LPD-LPR-Printer\"),\n              \"Legacy Unix/Linux print protocol\")\n        _ibtn(host_frame, \"\u2705 Sabhi Printer Ports Ek Saath Kholo  (445+139+137+138+135+9100+631+515)\",\n              C[\"btn_warn\"], self._host_open_ports,\n              \"Saare ports ek click mein\")\n\n        # \u2500\u2500 HOST: SECURITY / FIREWALL \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(host_frame, \"\ud83d\udd12  SECURITY &amp; FIREWALL SETTINGS\")\n        _ibtn(host_frame, \"\u25b6 Network Discovery  \u2192  Enable (Private)\",\n              C[\"btn_info\"], lambda: self._host_single_security(\"network_discovery\"),\n              \"Doosre computers network mein dikh sakein\")\n        _ibtn(host_frame, \"\u25b6 File &amp; Printer Sharing Rules  \u2192  ON (All Profiles)\",\n              C[\"btn_info\"], lambda: self._host_single_security(\"fp_sharing_rules\"),\n              \"Windows Firewall built-in sharing rules\")\n        _ibtn(host_frame, \"\u25b6 Network Profile  \u2192  Private\",\n              C[\"btn_info\"], lambda: self._host_single_security(\"network_private\"),\n              \"Public profile pe sharing band hoti hai\")\n        _ibtn(host_frame, \"\u25b6 Password Protected Sharing  \u2192  OFF\",\n              C[\"btn_info\"], lambda: self._host_single_security(\"pwd_sharing_off\"),\n              \"Bina password ke client connect kar sake\")\n        _ibtn(host_frame, \"\u25b6 SMB Signing  \u2192  Optional (Not Required)\",\n              C[\"btn_info\"], lambda: self._host_single_security(\"smb_sign_optional\"),\n              \"HKLM/.../LanmanServer: RequireSecuritySignature=0\")\n        _ibtn(host_frame, \"\u25b6 Windows Defender Firewall  \u2192  Private Network OFF\",\n              C[\"btn_info\"], lambda: self._host_single_security(\"fw_private_off\"),\n              \"Private profile firewall band karo (trusted LAN)\")\n        _ibtn(host_frame, \"\u25b6 ICMPv4 Ping  \u2192  Allow (Firewall)\",\n              C[\"btn_info\"], lambda: self._host_single_security(\"allow_ping\"),\n              \"Client se ping ka jawab aaye\")\n        _ibtn(host_frame, \"\u2705 Saari Security Settings Ek Saath\",\n              C[\"btn_warn\"], self._host_security_fix,\n              \"Network Discovery + F&amp;P Rules + Private + SMB\")\n\n        # \u2500\u2500 HOST: REGISTRY \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(host_frame, \"\ud83d\udddd  REGISTRY CHANGES\")\n        _ibtn(host_frame, \"\u25b6 AutoShareServer = 1  (Admin shares C$, D$ enable)\",\n              C[\"btn_hw\"], lambda: self._host_single_reg(\"AutoShareServer\"),\n              \"HKLM/.../LanmanServer/Parameters\")\n        _ibtn(host_frame, \"\u25b6 AutoShareWks = 1  (Workstation shares enable)\",\n              C[\"btn_hw\"], lambda: self._host_single_reg(\"AutoShareWks\"),\n              \"HKLM/.../LanmanServer/Parameters\")\n        _ibtn(host_frame, \"\u25b6 IRPStackSize = 20  (Large network packets fix)\",\n              C[\"btn_hw\"], lambda: self._host_single_reg(\"IRPStackSize\"),\n              \"HKLM/.../LanmanServer/Parameters\")\n        _ibtn(host_frame, \"\u25b6 LimitBlankPasswordUse = 0  (Blank password allow)\",\n              C[\"btn_hw\"], lambda: self._host_single_reg(\"LimitBlankPasswordUse\"),\n              \"HKLM/.../Control/Lsa\")\n        _ibtn(host_frame, \"\u25b6 DisableWebPrinting = 0  (Web printing enable)\",\n              C[\"btn_hw\"], lambda: self._host_single_reg(\"DisableWebPrinting\"),\n              \"HKLM/.../Control/Print\")\n        _ibtn(host_frame, \"\u25b6 SMB1 Protocol  \u2192  Enable  (XP/Win7 clients ke liye)\",\n              C[\"btn_hw\"], lambda: self._host_single_reg(\"EnableSMB1\"),\n              \"\u26a0 Security risk \u2014 sirf trusted LAN pe karo\")\n        _ibtn(host_frame, \"\u2705 Saare Registry Changes Ek Saath\",\n              C[\"btn_warn\"], self._host_registry_fix,\n              \"AutoShare + IRPStack + LimitBlank + DisableWeb\")\n\n        # \u2500\u2500 HOST: SERVICES \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(host_frame, \"\u2699\ufe0f  SERVICES \u2014 Start/Enable karo\")\n        _ibtn(host_frame, \"\u25b6 Print Spooler  \u2192  Auto + Start\",\n              C[\"accent2\"], lambda: self._host_single_svc(\"Spooler\"),\n              \"Printer ka main service \u2014 shuruaat yahan se\")\n        _ibtn(host_frame, \"\u25b6 Server (LanmanServer)  \u2192  Auto + Start\",\n              C[\"accent2\"], lambda: self._host_single_svc(\"LanmanServer\"),\n              \"File &amp; Printer Sharing ka core service\")\n        _ibtn(host_frame, \"\u25b6 Workstation (LanmanWorkstation)  \u2192  Auto + Start\",\n              C[\"accent2\"], lambda: self._host_single_svc(\"LanmanWorkstation\"),\n              \"Network client redirector service\")\n        _ibtn(host_frame, \"\u25b6 TCP/IP NetBIOS Helper  \u2192  Auto + Start\",\n              C[\"accent2\"], lambda: self._host_single_svc(\"lmhosts\"),\n              \"NetBIOS over TCP/IP naam resolution\")\n        _ibtn(host_frame, \"\u25b6 Function Discovery Provider Host  \u2192  Auto + Start\",\n              C[\"accent2\"], lambda: self._host_single_svc(\"fdPHost\"),\n              \"Network discovery ke liye zaroori\")\n        _ibtn(host_frame, \"\u25b6 Function Discovery Resource Publication  \u2192  Auto + Start\",\n              C[\"accent2\"], lambda: self._host_single_svc(\"FDResPub\"),\n              \"Computer ko network mein publish karta hai\")\n        _ibtn(host_frame, \"\u25b6 SSDP Discovery  \u2192  Auto + Start\",\n              C[\"accent2\"], lambda: self._host_single_svc(\"SSDPSRV\"),\n              \"UPnP devices discovery\")\n        _ibtn(host_frame, \"\u2705 Saari Services Ek Saath Enable karo\",\n              C[\"btn_warn\"], self._host_enable_services,\n              \"Spooler + Server + Workstation + NetBIOS + FD\")\n\n        # \u2500\u2500 HOST: PRINTER SHARE \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(host_frame, \"\ud83d\udce4  PRINTER SHARE KARO\")\n        _ibtn(host_frame, \"\ud83d\udce4  Selected Printer Share Karo  (Auto Confirm)\",\n              C[\"accent\"], self._host_auto_share,\n              \"Upar list mein printer select karo, phir click\")\n\n        # \u2500\u2500 HOST: ERROR 0x0000709 FIX \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(host_frame, \"\ud83d\udd34  ERROR 0x0000709 \u2014 Default Printer Cannot Be Set\")\n        _ibtn(host_frame, \"\ud83d\udd27 Auto-Fix Error 0x0000709  (HOST \u2014 Ek Click Mein)\",\n              C[\"error\"], self._fix_error_709_host,\n              \"Default printer set nahi ho raha \u2014 registry + spooler + RPC fix\")\n\n        # \u2500\u2500 HOST: ERROR 0x0000011b FIX \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(host_frame, \"\ud83d\udd34  ERROR 0x0000011b \u2014 Network Printer Connect Fail\")\n        _ibtn(host_frame, \"\ud83d\udd27 Auto-Fix Error 0x0000011b  (HOST \u2014 Ek Click Mein)\",\n              C[\"error\"], self._fix_error_11b_host,\n              \"Windows Update KB5005565+ ke baad network printer connect nahi \u2014 CVE-2021-1678 patch rollback\")\n\n        # \u2500\u2500 HOST: ONE-CLICK MEGA FIX \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(host_frame, \"\u26a1  MEGA AUTO-FIX \u2014 HOST KI SAARI SETTINGS EK SAATH\")\n        _ibtn(host_frame, \"\ud83d\ude80  HOST: SABKUCH AUTO-FIX  (Ports + Security + Registry + Services + Share + 709 + 11b)\",\n              \"#FF6600\", self._host_mega_auto_fix,\n              \"Ek click mein HOST ka poora printer sharing setup complete \u2014 seedha ready to share\")\n        tk.Frame(host_frame, bg=C[\"bg\"], height=8).pack()\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # \ud83d\udcbb CLIENT COMPUTER COLUMN\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        client_frame = _section_card(share_body,\n            \"\ud83d\udcbb  CLIENT COMPUTER  \u2014  Jo shared printer use karega\",\n            \"Yahan printer nahi laga, network se use karna hai\",\n            \"#1A2A3A\", C[\"accent2\"], 1)\n        client_frame.grid(row=0, column=1, sticky=\"nsew\", padx=(4,8), pady=6)\n\n        # \u2500\u2500 CLIENT: PORTS \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(client_frame, \"\ud83d\udd0c  PORTS \u2014 Firewall mein open karo (IN + OUT)\")\n        _ibtn(client_frame, \"\u25b6 Port 445 TCP+UDP  \u2014  SMB Client Access\",\n              C[\"btn_chip\"], lambda: self._open_single_port_client(445,\"TCP+UDP\",\"SMB-Client-Access\"),\n              \"Host se SMB connection ke liye\")\n        _ibtn(client_frame, \"\u25b6 Port 139 TCP  \u2014  NetBIOS Session (Client)\",\n              C[\"btn_chip\"], lambda: self._open_single_port_client(139,\"TCP\",\"NetBIOS-Session-Client\"),\n              \"NetBIOS session connect karne ke liye\")\n        _ibtn(client_frame, \"\u25b6 Port 137 UDP  \u2014  NetBIOS Name (Client)\",\n              C[\"btn_chip\"], lambda: self._open_single_port_client(137,\"UDP\",\"NetBIOS-Name-Client\"),\n              \"Naam se IP resolve karne ke liye\")\n        _ibtn(client_frame, \"\u25b6 Port 138 UDP  \u2014  NetBIOS Datagram (Client)\",\n              C[\"btn_chip\"], lambda: self._open_single_port_client(138,\"UDP\",\"NetBIOS-Datagram-Client\"),\n              \"NetBIOS broadcast receive karne ke liye\")\n        _ibtn(client_frame, \"\u25b6 Port 135 TCP  \u2014  RPC Client\",\n              C[\"btn_chip\"], lambda: self._open_single_port_client(135,\"TCP\",\"RPC-Client\"),\n              \"Remote Procedure Call \u2014 Windows core\")\n        _ibtn(client_frame, \"\u25b6 Port 9100 TCP  \u2014  RAW Print (Client Side)\",\n              C[\"btn_chip\"], lambda: self._open_single_port_client(9100,\"TCP\",\"RAW-Print-Client\"),\n              \"Direct raw print access client pe\")\n        _ibtn(client_frame, \"\u25b6 Port 631 TCP  \u2014  IPP Client\",\n              C[\"btn_chip\"], lambda: self._open_single_port_client(631,\"TCP\",\"IPP-Client\"),\n              \"Internet Printing Protocol client\")\n        _ibtn(client_frame, \"\u25b6 Port 515 TCP  \u2014  LPD/LPR Client\",\n              C[\"btn_chip\"], lambda: self._open_single_port_client(515,\"TCP\",\"LPD-LPR-Client\"),\n              \"Legacy print protocol client\")\n        _ibtn(client_frame, \"\u2705 Sabhi Client Ports Ek Saath  (445+139+137+138+135+9100+631+515)\",\n              C[\"btn_warn\"], self._client_open_ports,\n              \"Saare ports ek click mein\")\n\n        # \u2500\u2500 CLIENT: SECURITY \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(client_frame, \"\ud83d\udd12  SECURITY &amp; FIREWALL SETTINGS\")\n        _ibtn(client_frame, \"\u25b6 Network Discovery  \u2192  Enable (Client)\",\n              C[\"btn_info\"], lambda: self._client_single_security(\"network_discovery\"),\n              \"Host PC ko network mein dhundh sake\")\n        _ibtn(client_frame, \"\u25b6 File &amp; Printer Sharing Rules  \u2192  ON (Client)\",\n              C[\"btn_info\"], lambda: self._client_single_security(\"fp_sharing_rules\"),\n              \"Windows Firewall F&amp;P rules enable\")\n        _ibtn(client_frame, \"\u25b6 Network Profile  \u2192  Private (Client)\",\n              C[\"btn_info\"], lambda: self._client_single_security(\"network_private\"),\n              \"Public profile pe sharing accessible nahi hoti\")\n        _ibtn(client_frame, \"\u25b6 SMB Client Signing  \u2192  Optional\",\n              C[\"btn_info\"], lambda: self._client_single_security(\"smb_sign_optional\"),\n              \"HKLM/.../LanmanWorkstation: RequireSecuritySignature=0\")\n        _ibtn(client_frame, \"\u25b6 Point &amp; Print  \u2192  No Warning / No Elevation\",\n              C[\"btn_info\"], lambda: self._client_single_security(\"point_print\"),\n              \"Driver install bina UAC prompt ke\")\n        _ibtn(client_frame, \"\u25b6 Windows Defender Firewall  \u2192  Private Network OFF\",\n              C[\"btn_info\"], lambda: self._client_single_security(\"fw_private_off\"),\n              \"Client pe private firewall temporarily off\")\n        _ibtn(client_frame, \"\u25b6 ICMPv4 Ping  \u2192  Allow (Client Firewall)\",\n              C[\"btn_info\"], lambda: self._client_single_security(\"allow_ping\"),\n              \"Host ko ping se dhundh sake\")\n        _ibtn(client_frame, \"\u2705 Saari Client Security Settings Ek Saath\",\n              C[\"btn_warn\"], self._client_security_fix,\n              \"Discovery + F&amp;P Rules + Private + SMB + PnP\")\n\n        # \u2500\u2500 CLIENT: REGISTRY \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(client_frame, \"\ud83d\udddd  REGISTRY CHANGES\")\n        _ibtn(client_frame, \"\u25b6 AllowInsecureGuestAuth = 1  (Guest share access)\",\n              C[\"btn_hw\"], lambda: self._client_single_reg(\"AllowInsecureGuestAuth\"),\n              \"HKLM/.../LanmanWorkstation/Parameters\")\n        _ibtn(client_frame, \"\u25b6 LimitBlankPasswordUse = 0  (Blank password connect)\",\n              C[\"btn_hw\"], lambda: self._client_single_reg(\"LimitBlankPasswordUse\"),\n              \"HKLM/.../Control/Lsa\")\n        _ibtn(client_frame, \"\u25b6 RequireSecuritySignature = 0  (SMB signing optional)\",\n              C[\"btn_hw\"], lambda: self._client_single_reg(\"RequireSecuritySignature\"),\n              \"HKLM/.../LanmanWorkstation/Parameters\")\n        _ibtn(client_frame, \"\u25b6 Point &amp; Print: NoWarningNoElevationOnInstall = 1\",\n              C[\"btn_hw\"], lambda: self._client_single_reg(\"PnP_NoWarning\"),\n              \"HKLM/SOFTWARE/Policies/.../PointAndPrint\")\n        _ibtn(client_frame, \"\u25b6 Point &amp; Print: UpdatePromptSettings = 2\",\n              C[\"btn_hw\"], lambda: self._client_single_reg(\"PnP_UpdatePrompt\"),\n              \"HKLM/SOFTWARE/Policies/.../PointAndPrint\")\n        _ibtn(client_frame, \"\u25b6 Point &amp; Print: RestrictDriverInstall = 0\",\n              C[\"btn_hw\"], lambda: self._client_single_reg(\"PnP_RestrictDriver\"),\n              \"HKLM/SOFTWARE/Policies/.../PointAndPrint\")\n        _ibtn(client_frame, \"\u2705 Saare Client Registry Changes Ek Saath\",\n              C[\"btn_warn\"], self._client_registry_fix,\n              \"GuestAuth + LimitBlank + SMB + Point&amp;Print\")\n\n        # \u2500\u2500 CLIENT: SERVICES \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(client_frame, \"\u2699\ufe0f  SERVICES \u2014 Start/Enable karo (Client)\")\n        _ibtn(client_frame, \"\u25b6 Print Spooler  \u2192  Auto + Start\",\n              C[\"accent2\"], lambda: self._host_single_svc(\"Spooler\"),\n              \"Client pe bhi spooler chahiye\")\n        _ibtn(client_frame, \"\u25b6 Workstation (LanmanWorkstation)  \u2192  Auto + Start\",\n              C[\"accent2\"], lambda: self._host_single_svc(\"LanmanWorkstation\"),\n              \"Network redirector \u2014 sharing ke liye zaroori\")\n        _ibtn(client_frame, \"\u25b6 TCP/IP NetBIOS Helper  \u2192  Auto + Start\",\n              C[\"accent2\"], lambda: self._host_single_svc(\"lmhosts\"),\n              \"NetBIOS naam resolution client side\")\n        _ibtn(client_frame, \"\u25b6 Function Discovery Provider Host  \u2192  Auto + Start\",\n              C[\"accent2\"], lambda: self._host_single_svc(\"fdPHost\"),\n              \"Network mein host PC dhundh sake\")\n        _ibtn(client_frame, \"\u25b6 SSDP Discovery  \u2192  Auto + Start\",\n              C[\"accent2\"], lambda: self._host_single_svc(\"SSDPSRV\"),\n              \"UPnP / network device discovery\")\n\n        # \u2500\u2500 CLIENT: CONNECT \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(client_frame, \"\ud83d\udda8  HOST SE CONNECT KARO\")\n        _ibtn(client_frame, \"\ud83d\udda8  Host ke Shared Printer se Connect Karo\",\n              C[\"accent\"], self._client_connect_printer,\n              \"Host IP + Share Name daal ke connect\")\n\n        # \u2500\u2500 CLIENT: ERROR 0x0000709 FIX \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(client_frame, \"\ud83d\udd34  ERROR 0x0000709 \u2014 Default Printer Cannot Be Set\")\n        _ibtn(client_frame, \"\ud83d\udd27 Auto-Fix Error 0x0000709  (CLIENT \u2014 Ek Click Mein)\",\n              C[\"error\"], self._fix_error_709_client,\n              \"Default printer set nahi ho raha \u2014 registry + spooler + UserSelectedDefault fix\")\n\n        # \u2500\u2500 CLIENT: ERROR 0x0000011b FIX \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(client_frame, \"\ud83d\udd34  ERROR 0x0000011b \u2014 Network Printer Connect Fail\")\n        _ibtn(client_frame, \"\ud83d\udd27 Auto-Fix Error 0x0000011b  (CLIENT \u2014 Ek Click Mein)\",\n              C[\"error\"], self._fix_error_11b_client,\n              \"Network printer connect nahi \u2014 RPC encryption + LanmanWorkstation fix\")\n\n        # \u2500\u2500 CLIENT: ONE-CLICK MEGA FIX \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(client_frame, \"\u26a1  MEGA AUTO-FIX \u2014 CLIENT KI SAARI SETTINGS EK SAATH\")\n        _ibtn(client_frame, \"\ud83d\ude80  CLIENT: SABKUCH AUTO-FIX  (Ports + Security + Registry + Services + 709 + 11b + Connect)\",\n              \"#FF6600\", self._client_mega_auto_fix,\n              \"Ek click mein CLIENT ka poora printer connect setup \u2014 seedha print karo\")\n        tk.Frame(client_frame, bg=C[\"bg\"], height=8).pack()\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # \ud83d\udcdd SHARING LOG \u2014 tab2 ke andar\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        share_log_outer = tk.Frame(tab2, bg=C[\"card\"])\n        share_log_outer.pack(fill=\"x\", padx=8, pady=(2,8))\n        tk.Label(share_log_outer, text=\"  \ud83d\udcdd Sharing Center Log\",\n                 font=FONTS[\"subhead\"], fg=C[\"accent4\"], bg=C[\"card\"]).pack(\n                 anchor=\"w\", padx=8, pady=(6,2))\n        self.sharing_log = self._scrolled_text(share_log_outer, height=6)\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # \ud83d\udd27 TAB 3 \u2014 ADVANCED ERROR FIX GUIDE (0x0000709 + 0x0000011b)\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        tab3 = tk.Frame(nb, bg=C[\"bg\"])\n        nb.add(tab3, text=\"  \ud83d\udd34  Error Fix Guide (709 &amp; 11b)  \")\n\n        # \u2500\u2500 Tab3 Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        t3_hdr = tk.Frame(tab3, bg=C[\"panel\"])\n        t3_hdr.pack(fill=\"x\")\n        tk.Label(t3_hdr, text=\"  \ud83d\udd34 Printer Error Fix Guide \u2014 0x0000709 &amp; 0x0000011b\",\n                 font=FONTS[\"heading\"], fg=C[\"error\"], bg=C[\"panel\"]).pack(side=\"left\", pady=8, padx=8)\n        tk.Label(t3_hdr,\n                 text=\"In-app auto-fix buttons + manual steps \u2014 dono tarike ek jagah\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"left\")\n\n        # \u2500\u2500 Tab3 Scrollable Canvas \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        t3_outer = tk.Frame(tab3, bg=C[\"bg\"])\n        t3_outer.pack(fill=\"both\", expand=True)\n        t3_canvas = tk.Canvas(t3_outer, bg=C[\"bg\"], highlightthickness=0)\n        t3_sb = ttk.Scrollbar(t3_outer, orient=\"vertical\", command=t3_canvas.yview)\n        t3_canvas.configure(yscrollcommand=t3_sb.set)\n        t3_sb.pack(side=\"right\", fill=\"y\")\n        t3_canvas.pack(side=\"left\", fill=\"both\", expand=True)\n        t3_body = tk.Frame(t3_canvas, bg=C[\"bg\"])\n        t3_win = t3_canvas.create_window((0,0), window=t3_body, anchor=\"nw\")\n        def _t3_resize(e):\n            t3_canvas.configure(scrollregion=t3_canvas.bbox(\"all\"))\n            t3_canvas.itemconfig(t3_win, width=t3_canvas.winfo_width())\n        t3_body.bind(\"\", _t3_resize)\n        def _t3_canvas_configure(e):\n            t3_canvas.itemconfig(t3_win, width=e.width)\n            t3_canvas.configure(scrollregion=t3_canvas.bbox(\"all\"))\n        t3_canvas.bind(\"\", _t3_canvas_configure)\n        self._bind_scoped_mousewheel(t3_body, t3_canvas)\n\n        # \u2500\u2500 Helper functions for Tab3 layout \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        def _t3_section(title, subtitle, color):\n            frm = tk.Frame(t3_body, bg=C[\"card\"], bd=0)\n            frm.pack(fill=\"x\", padx=12, pady=(8,0))\n            hdr = tk.Frame(frm, bg=color)\n            hdr.pack(fill=\"x\")\n            tk.Label(hdr, text=title, font=FONTS[\"subhead\"], fg=C[\"text\"],\n                     bg=color, anchor=\"w\").pack(anchor=\"w\", padx=12, pady=(8,2))\n            tk.Label(hdr, text=subtitle, font=FONTS[\"small\"], fg=C[\"text_dim\"],\n                     bg=color, anchor=\"w\").pack(anchor=\"w\", padx=12, pady=(0,6))\n            return frm\n\n        def _t3_step(parent, num, title, detail, cmd_text=\"\"):\n            \"\"\"Numbered step row with optional command display.\"\"\"\n            row = tk.Frame(parent, bg=C[\"card\"])\n            row.pack(fill=\"x\", padx=8, pady=3)\n            # Step number badge\n            badge = tk.Label(row, text=f\" {num} \", font=(\"Consolas\",10,\"bold\"),\n                             fg=C[\"bg\"], bg=C[\"accent4\"], padx=4, pady=2)\n            badge.pack(side=\"left\", padx=(6,8), pady=4, anchor=\"n\")\n            # Content\n            content = tk.Frame(row, bg=C[\"card\"])\n            content.pack(side=\"left\", fill=\"x\", expand=True, pady=4)\n            tk.Label(content, text=title, font=FONTS[\"body\"], fg=C[\"text\"],\n                     bg=C[\"card\"], anchor=\"w\").pack(anchor=\"w\")\n            if detail:\n                tk.Label(content, text=detail, font=FONTS[\"small\"], fg=C[\"text_dim\"],\n                         bg=C[\"card\"], anchor=\"w\", wraplength=700, justify=\"left\").pack(anchor=\"w\")\n            if cmd_text:\n                cmd_row = tk.Frame(content, bg=\"#0D0D1A\")\n                cmd_row.pack(fill=\"x\", pady=(3,0))\n                tk.Label(cmd_row, text=f\"  {cmd_text}\", font=(\"Consolas\",9),\n                         fg=C[\"accent2\"], bg=\"#0D0D1A\", anchor=\"w\").pack(side=\"left\", padx=4, pady=3)\n                def _copy(t=cmd_text):\n                    self.clipboard_clear()\n                    self.clipboard_append(t)\n                    messagebox.showinfo(\"Copied!\", f\"Copied:\\n{t}\", parent=self)\n                tk.Button(cmd_row, text=\"\ud83d\udccb Copy\", font=(\"Consolas\",8),\n                          bg=C[\"btn_chip\"], fg=C[\"text\"], bd=0, padx=6, pady=2,\n                          cursor=\"hand2\", command=_copy).pack(side=\"right\", padx=4)\n\n        def _t3_auto_btn(parent, text, color, cmd, note=\"\"):\n            row = tk.Frame(parent, bg=C[\"card\"])\n            row.pack(fill=\"x\", padx=8, pady=(4,2))\n            tk.Button(row, text=text, font=FONTS[\"body\"], bg=color, fg=C[\"text\"],\n                      bd=0, padx=14, pady=8, cursor=\"hand2\", anchor=\"w\",\n                      command=cmd).pack(side=\"left\")\n            if note:\n                tk.Label(row, text=note, font=FONTS[\"small\"], fg=C[\"text_dim\"],\n                         bg=C[\"card\"], anchor=\"w\").pack(side=\"left\", padx=10)\n\n        def _t3_divider(parent):\n            tk.Frame(parent, bg=C[\"border\"], height=1).pack(fill=\"x\", padx=12, pady=4)\n\n        def _t3_info_box(parent, text, bg=\"#1A1A2A\", fg=None):\n            fg = fg or C[\"accent4\"]\n            bx = tk.Frame(parent, bg=bg, bd=0)\n            bx.pack(fill=\"x\", padx=20, pady=(4,0))\n            tk.Label(bx, text=text, font=FONTS[\"small\"], fg=fg, bg=bg,\n                     anchor=\"w\", wraplength=820, justify=\"left\",\n                     padx=10, pady=8).pack(fill=\"x\")\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # SECTION 1 \u2014 QUICK DECISION (Kaunsa error hai?)\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        s0 = _t3_section(\"\ud83e\udd14  Pehle Pehchano \u2014 Kaunsa Error Hai?\",\n                         \"Error code dekho aur us section mein jaao\", \"#1A2A1A\")\n        _t3_info_box(s0,\n            \"0x0000709  \u2192  'Operation could not be completed. Cannot set default printer.'\\n\"\n            \"              Matlab: Windows ko default printer set karna nahi aa raha \u2014 mostly registry/spooler issue.\\n\\n\"\n            \"0x0000011b \u2192  'Windows cannot connect to the printer. Operation failed with error 0x0000011b.'\\n\"\n            \"              Matlab: Network/shared printer se connection nahi ho raha \u2014 mostly Windows Update (KB5005565) ne RPC strict kar diya.\",\n            bg=\"#0D1A0D\", fg=C[\"text\"])\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # SECTION 2 \u2014 ERROR 0x0000709 FULL GUIDE\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        s1 = _t3_section(\"\ud83d\udd34  Error 0x0000709 \u2014 Default Printer Cannot Be Set\",\n                         \"HOST aur CLIENT dono pe ye steps karo\", \"#2A1A1A\")\n\n        _t3_info_box(s1,\n            \"\u26a1 SABSE PEHLE \u2014 Neeche ka Auto-Fix button dabaao. Manually karne ki zaroorat nahi padegi.\",\n            bg=\"#1A0D0D\", fg=C[\"warning\"])\n\n        _t3_auto_btn(s1, \"\ud83d\udd27 AUTO-FIX 0x0000709 \u2014 HOST (Ek Click)\",  C[\"error\"],\n                     self._fix_error_709_host, \"\u2190 HOST PC pe run karo (jisme printer laga hai)\")\n        _t3_auto_btn(s1, \"\ud83d\udd27 AUTO-FIX 0x0000709 \u2014 CLIENT (Ek Click)\", C[\"error\"],\n                     self._fix_error_709_client, \"\u2190 CLIENT PC pe run karo (jo print karna chahta hai)\")\n\n        _t3_divider(s1)\n        tk.Label(s1, text=\"  \ud83d\udccb Manual Steps (agar auto-fix kaam na kare):\",\n                 font=FONTS[\"body\"], fg=C[\"accent4\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=10, pady=(6,2))\n\n        _t3_step(s1, \"1\", \"Group Policy se RPC Settings fix karo  (Windows Pro/Enterprise only)\",\n                 \"Windows Key + R \u2192 gpedit.msc \u2192 Computer Configuration \u2192 Administrative Templates \u2192 Printers\\n\"\n                 \"\u2192 'Configure RPC connection settings' \u2192 Enabled \u2192 Dropdown: 'RPC over named pipes' \u2192 Apply \u2192 OK\",\n                 \"gpedit.msc\")\n        _t3_auto_btn(s1,\n            \"\u2699 Auto-Fix: gpedit.msc Setting  \u2014 Configure RPC \u2192 Named Pipes (Windows Pro/Enterprise)\",\n            C[\"btn_hw\"], self._auto_gpedit_rpc_709,\n            \"\u2190 Ek click: Group Policy RPC setting auto set\")\n\n        _t3_step(s1, \"2\", \"Registry se RpcAuthnLevelPrivacyEnabled = 0 set karo  (Windows Home ke liye bhi kaam karta hai)\",\n                 \"Windows Key + R \u2192 regedit \u2192 HKEY_LOCAL_MACHINE\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\\n\"\n                 \"\u2192 Right-click \u2192 New \u2192 DWORD (32-bit) \u2192 Name: RpcAuthnLevelPrivacyEnabled \u2192 Value: 0\",\n                 r\"HKLM\\SYSTEM\\CurrentControlSet\\Control\\Print  \u2192  RpcAuthnLevelPrivacyEnabled = 0\")\n        _t3_auto_btn(s1,\n            \"\ud83d\udddd Auto-Fix: Registry Setting  \u2014 RpcAuthnLevelPrivacyEnabled = 0  (Home + Pro dono)\",\n            C[\"btn_hw\"], self._auto_reg_rpcauth_0,\n            \"\u2190 Ek click: Registry me value seedha set ho jaayegi\")\n\n        _t3_step(s1, \"3\", \"LegacyDefaultPrinterMode = 1 set karo  (Windows auto printer manage feature band karo)\",\n                 \"HKEY_CURRENT_USER\\\\SOFTWARE\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\Windows\\n\"\n                 \"\u2192 New DWORD \u2192 LegacyDefaultPrinterMode \u2192 Value: 1\",\n                 r\"HKCU\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows  \u2192  LegacyDefaultPrinterMode = 1\")\n        _t3_auto_btn(s1,\n            \"\ud83d\udddd Auto-Fix: Registry Setting  \u2014 LegacyDefaultPrinterMode = 1  (Windows auto-manage OFF)\",\n            C[\"btn_hw\"], self._auto_reg_legacy_default,\n            \"\u2190 Ek click: HKCU registry value auto set\")\n\n        _t3_step(s1, \"4\", \"Print Spooler Service Restart karo\",\n                 \"Windows Key + R \u2192 services.msc \u2192 Print Spooler \u2192 Right-click \u2192 Restart\",\n                 \"services.msc\")\n        _t3_auto_btn(s1,\n            \"\ud83d\udd01 Auto-Fix: Print Spooler Restart\",\n            C[\"btn_chip\"], self._printer_reset_spooler,\n            \"\u2190 Ek click: Spooler stop + start\")\n\n        _t3_step(s1, \"5\", \"UserSelectedDefault registry value delete karo  (stale default clear)\",\n                 \"HKEY_CURRENT_USER\\\\SOFTWARE\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\Windows\\n\"\n                 \"\u2192 'UserSelectedDefault' value ko delete karo (agar hai to)\", \"\")\n        _t3_auto_btn(s1,\n            \"\ud83d\udddd Auto-Fix: Registry Setting  \u2014 UserSelectedDefault Delete  (stale default clear)\",\n            C[\"btn_hw\"], self._auto_reg_delete_userselected,\n            \"\u2190 Ek click: Purana default printer entry hata do\")\n\n        _t3_step(s1, \"6\", \"Reboot karo\",\n                 \"Saari changes ke baad computer restart karo \u2014 registry changes tabhi full effect mein aati hain.\", \"\")\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # SECTION 3 \u2014 ERROR 0x0000011b FULL GUIDE\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        s2 = _t3_section(\"\ud83d\udd34  Error 0x0000011b \u2014 Network Printer Cannot Connect\",\n                         \"Ye error Windows Update KB5005565/KB5005566 ke baad aata hai \u2014 HOST + CLIENT dono fix karo\",\n                         \"#2A1A2A\")\n\n        _t3_info_box(s2,\n            \"Root Cause: Microsoft ne October 2021 update (KB5005565) mein RPC encryption strict kar di.\\n\"\n            \"Fix: RpcAuthnLevelPrivacyEnabled = 0 dono PCs pe \u2014 HOST aur CLIENT dono pe karna ZAROORI hai.\",\n            bg=\"#1A0D1A\", fg=C[\"warning\"])\n\n        _t3_auto_btn(s2, \"\ud83d\udd27 AUTO-FIX 0x0000011b \u2014 HOST (Ek Click)\",  C[\"error\"],\n                     self._fix_error_11b_host, \"\u2190 HOST PC pe pehle run karo\")\n        _t3_auto_btn(s2, \"\ud83d\udd27 AUTO-FIX 0x0000011b \u2014 CLIENT (Ek Click)\", C[\"error\"],\n                     self._fix_error_11b_client, \"\u2190 CLIENT PC pe run karo\")\n\n        _t3_divider(s2)\n        tk.Label(s2, text=\"  \ud83d\udccb Manual Steps (agar auto-fix kaam na kare):\",\n                 font=FONTS[\"body\"], fg=C[\"accent4\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=10, pady=(6,2))\n\n        _t3_step(s2, \"1\", \"Group Policy se RPC Settings fix karo \u2014 DONO PCs pe  (Windows Pro/Enterprise)\",\n                 \"Windows Key + R \u2192 gpedit.msc \u2192 Computer Configuration \u2192 Administrative Templates \u2192 Printers\\n\"\n                 \"\u2192 'Configure RPC connection settings' \u2192 Enabled \u2192 'RPC over named pipes' \u2192 Apply \u2192 OK\\n\"\n                 \"\u26a0 DONO COMPUTERS pe \u2014 HOST aur CLIENT dono pe ye setting karo\",\n                 \"gpedit.msc\")\n        _t3_auto_btn(s2,\n            \"\u2699 Auto-Fix: gpedit.msc Setting  \u2014 Configure RPC \u2192 Named Pipes  (Windows Pro/Enterprise)\",\n            C[\"btn_hw\"], self._auto_gpedit_rpc_11b,\n            \"\u2190 Ek click: Group Policy RPC + Printer settings auto set (dono computers pe alag-alag chalao)\")\n\n        _t3_step(s2, \"2\", \"Registry mein RpcAuthnLevelPrivacyEnabled = 0 set karo \u2014 DONO PCs pe\",\n                 \"Ye Windows Home ke liye bhi kaam karta hai (jahan gpedit nahi hota)\\n\"\n                 \"Path: HKEY_LOCAL_MACHINE\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\\n\"\n                 \"\u2192 New DWORD (32-bit) \u2192 Name: RpcAuthnLevelPrivacyEnabled \u2192 Value data: 0 \u2192 OK\",\n                 r\"reg add HKLM\\SYSTEM\\CurrentControlSet\\Control\\Print /v RpcAuthnLevelPrivacyEnabled /t REG_DWORD /d 0 /f\")\n        _t3_auto_btn(s2,\n            \"\ud83d\udddd Auto-Fix: Registry Setting  \u2014 RpcAuthnLevelPrivacyEnabled = 0  (Home + Pro dono)\",\n            C[\"btn_hw\"], self._auto_reg_rpcauth_0,\n            \"\u2190 Ek click: Registry me value seedha set \u2014 DONO PCs pe alag-alag chalao\")\n\n        _t3_step(s2, \"3\", \"Windows Credentials mein Password save karo  (Client PC pe)\",\n                 \"Client PC pe: Windows Search \u2192 Credential Manager \u2192 Windows Credentials\\n\"\n                 \"\u2192 'Add a Windows credential'\\n\"\n                 \"\u2192 Internet/network address: HOST PC ka naam ya IP (jaise: \\\\\\\\Main-PC ya 192.168.1.15)\\n\"\n                 \"\u2192 Username + Password: HOST PC ka login credentials \u2192 OK\",\n                 \"control /name Microsoft.CredentialManager\")\n        _t3_step(s2, \"4\", \"Print Spooler Restart karo \u2014 DONO PCs pe\",\n                 \"Windows Key + R \u2192 services.msc \u2192 Print Spooler \u2192 Right-click \u2192 Restart\\n\"\n                 \"Ya neeche ka button dabaao:\",\n                 \"net stop spooler &amp;&amp; net start spooler\")\n        _t3_auto_btn(s2,\n            \"\ud83d\udd01 Auto-Fix: Print Spooler Restart\",\n            C[\"btn_chip\"], self._printer_reset_spooler,\n            \"\u2190 Ek click: Spooler stop + start\")\n\n        _t3_step(s2, \"5\", \"DONO Computers Restart karo\",\n                 \"Registry changes full effect tab aati hain \u2014 restart zaroori hai.\", \"\")\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # SECTION 4 \u2014 CREDENTIAL MANAGER (Windows Credentials Save)\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        s3 = _t3_section(\"\ud83d\udd11  Windows Credentials Manager \u2014 Auto Save / Open\",\n                         \"PC-to-PC sharing mein authentication fail hoti hai \u2014 yahan credentials save karo\",\n                         \"#1A1A2A\")\n\n        _t3_info_box(s3,\n            \"Jab HOST PC password-protected ho aur CLIENT bina password ke connect karne ki koshish kare\\n\"\n            \"to error aata hai. Solution: CLIENT pe HOST ke credentials Credential Manager mein save karo.\",\n            bg=\"#0D0D1A\", fg=C[\"text_dim\"])\n\n        cred_frame = tk.Frame(s3, bg=C[\"card\"])\n        cred_frame.pack(fill=\"x\", padx=8, pady=8)\n        cred_cols = tk.Frame(cred_frame, bg=C[\"card\"])\n        cred_cols.pack(fill=\"x\", padx=4)\n\n        # Input fields for credential manager\n        tk.Label(cred_cols, text=\"  HOST PC ka IP / Name:\", font=FONTS[\"body\"],\n                 fg=C[\"text\"], bg=C[\"card\"]).grid(row=0, column=0, sticky=\"w\", padx=6, pady=4)\n        self._cred_host_var = tk.StringVar(value=\"192.168.1.x  ya  PC-Name\")\n        cred_host_e = tk.Entry(cred_cols, textvariable=self._cred_host_var,\n                               font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"],\n                               insertbackground=C[\"text\"], relief=\"flat\", bd=4, width=30)\n        cred_host_e.grid(row=0, column=1, padx=6, pady=4)\n        cred_host_e.bind(\"\",\n            lambda e: cred_host_e.delete(0,\"end\") if \"ya\" in cred_host_e.get() or \"x\" in cred_host_e.get() else None)\n\n        tk.Label(cred_cols, text=\"  Username:\", font=FONTS[\"body\"],\n                 fg=C[\"text\"], bg=C[\"card\"]).grid(row=1, column=0, sticky=\"w\", padx=6, pady=4)\n        self._cred_user_var = tk.StringVar(value=\"\")\n        tk.Entry(cred_cols, textvariable=self._cred_user_var, font=FONTS[\"body\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"],\n                 relief=\"flat\", bd=4, width=30).grid(row=1, column=1, padx=6, pady=4)\n\n        tk.Label(cred_cols, text=\"  Password:\", font=FONTS[\"body\"],\n                 fg=C[\"text\"], bg=C[\"card\"]).grid(row=2, column=0, sticky=\"w\", padx=6, pady=4)\n        self._cred_pwd_var = tk.StringVar(value=\"\")\n        tk.Entry(cred_cols, textvariable=self._cred_pwd_var, font=FONTS[\"body\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"],\n                 relief=\"flat\", bd=4, width=30, show=\"*\").grid(row=2, column=1, padx=6, pady=4)\n\n        cred_btn_row = tk.Frame(cred_frame, bg=C[\"card\"])\n        cred_btn_row.pack(fill=\"x\", padx=8, pady=(4,8))\n\n        def _auto_save_cred():\n            host = self._cred_host_var.get().strip()\n            user = self._cred_user_var.get().strip()\n            pwd  = self._cred_pwd_var.get().strip()\n            if not host or \"ya\" in host or \"x\" in host:\n                messagebox.showwarning(\"Host Missing\", \"HOST PC ka naam ya IP dalo.\")\n                return\n            if not user:\n                messagebox.showwarning(\"Username Missing\", \"Username dalo.\")\n                return\n            # Build cmdkey command\n            unc = host if host.startswith(\"\\\\\\\\\") else f\"\\\\\\\\{host}\"\n            cmd = f'cmdkey /add:{unc} /user:{user} /pass:{pwd if pwd else \"\"}'\n            out, rc = self._run_cmd(cmd, timeout=10)\n            if rc == 0:\n                self._sharing_log(f\"\u2705 Credential saved for {unc} (user: {user})\", C[\"success\"])\n                messagebox.showinfo(\"\u2705 Done!\", f\"Credential saved!\\nHost: {unc}\\nUser: {user}\\n\\nAb printer connect karo.\")\n            else:\n                self._sharing_log(f\"\u26a0 cmdkey failed rc={rc}: {out}\", C[\"warning\"])\n                messagebox.showerror(\"Error\", f\"Credential save nahi hua:\\n{out}\")\n\n        def _open_cred_manager():\n            self._run_cmd(\"control /name Microsoft.CredentialManager\")\n            self._sharing_log(\"\u2705 Credential Manager khola gaya.\", C[\"success\"])\n\n        def _list_creds():\n            out, _ = self._run_cmd(\"cmdkey /list\", timeout=10)\n            messagebox.showinfo(\"Saved Credentials\", out or \"Koi saved credential nahi mila.\")\n\n        def _delete_cred():\n            host = self._cred_host_var.get().strip()\n            if not host or \"ya\" in host:\n                messagebox.showwarning(\"\", \"Pehle HOST ka naam/IP dalo.\")\n                return\n            unc = host if host.startswith(\"\\\\\\\\\") else f\"\\\\\\\\{host}\"\n            out, rc = self._run_cmd(f'cmdkey /delete:{unc}', timeout=10)\n            msg = f\"\u2705 Credential deleted: {unc}\" if rc == 0 else f\"\u26a0 Delete failed: {out}\"\n            self._sharing_log(msg, C[\"success\"] if rc == 0 else C[\"warning\"])\n            messagebox.showinfo(\"Result\", msg)\n\n        tk.Button(cred_btn_row, text=\"\ud83d\udcbe Auto-Save Credential (cmdkey)\", font=FONTS[\"body\"],\n                  bg=C[\"accent\"], fg=C[\"bg\"], bd=0, padx=12, pady=7, cursor=\"hand2\",\n                  command=_auto_save_cred).pack(side=\"left\", padx=(0,6))\n        tk.Button(cred_btn_row, text=\"\ud83d\udcc2 Open Credential Manager\", font=FONTS[\"body\"],\n                  bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=10, pady=7, cursor=\"hand2\",\n                  command=_open_cred_manager).pack(side=\"left\", padx=(0,6))\n        tk.Button(cred_btn_row, text=\"\ud83d\udccb List Credentials\", font=FONTS[\"body\"],\n                  bg=C[\"btn_chip\"], fg=C[\"text\"], bd=0, padx=10, pady=7, cursor=\"hand2\",\n                  command=_list_creds).pack(side=\"left\", padx=(0,6))\n        tk.Button(cred_btn_row, text=\"\ud83d\uddd1 Delete Credential\", font=FONTS[\"body\"],\n                  bg=C[\"error\"], fg=C[\"text\"], bd=0, padx=10, pady=7, cursor=\"hand2\",\n                  command=_delete_cred).pack(side=\"left\")\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # SECTION 5 \u2014 QUICK ACTIONS (all-in-one shortcuts)\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        s4 = _t3_section(\"\u26a1  Quick Actions \u2014 Ek Click Tools\",\n                         \"Frequently needed tools seedha yahan se\",\n                         \"#1A2A2A\")\n\n        def _t3_quick(parent, label, cmd_str, note=\"\"):\n            row = tk.Frame(parent, bg=C[\"card\"])\n            row.pack(fill=\"x\", padx=8, pady=2)\n            def _run():\n                self._run_cmd(cmd_str, timeout=10)\n                self._sharing_log(f\"\u25b6 Ran: {cmd_str}\", C[\"text_dim\"])\n            tk.Button(row, text=label, font=FONTS[\"body\"],\n                      bg=C[\"btn_hw\"], fg=C[\"text\"], bd=0, padx=12, pady=6,\n                      cursor=\"hand2\", anchor=\"w\", command=_run).pack(side=\"left\", fill=\"x\", expand=True)\n            if note:\n                tk.Label(row, text=note, font=(\"Consolas\",8), fg=C[\"text_dim\"],\n                         bg=C[\"card\"]).pack(side=\"left\", padx=6)\n\n        _t3_quick(s4, \"\ud83d\udd01 Spooler Restart\",\n                  \"net stop spooler /y &amp; net start spooler\",\n                  \"Print queue hang fix\")\n        _t3_quick(s4, \"\ud83d\uddc2 Open Printers &amp; Scanners\",\n                  \"control printers\",\n                  \"Windows printers settings\")\n        _t3_quick(s4, \"\ud83d\udd11 Open Credential Manager\",\n                  \"control /name Microsoft.CredentialManager\",\n                  \"Saved network passwords\")\n        _t3_quick(s4, \"\u2699 Open Group Policy Editor\",\n                  \"gpedit.msc\",\n                  \"RPC settings (Pro/Enterprise only)\")\n        _t3_quick(s4, \"\ud83d\udcdd Open Registry Editor\",\n                  \"regedit\",\n                  \"Manual registry changes\")\n        _t3_quick(s4, \"\ud83d\udd27 Open Services\",\n                  \"services.msc\",\n                  \"Start/Stop/Restart services\")\n        _t3_quick(s4, \"\ud83c\udf10 Open Network &amp; Sharing Center\",\n                  \"control.exe /name Microsoft.NetworkAndSharingCenter\",\n                  \"Network profile + sharing settings\")\n        _t3_quick(s4, \"\ud83d\udda5 Open Computer Name / Workgroup Settings\",\n                  \"SystemPropertiesComputerName.exe\",\n                  \"Workgroup mismatch fix\")\n        _t3_quick(s4, \"\ud83d\udce1 IPConfig \u2014 IP Address Check\",\n                  \"cmd /k ipconfig /all\",\n                  \"Apna IP janno\")\n        _t3_quick(s4, \"\ud83d\udd0d SFC Scannow \u2014 System File Check\",\n                  \"cmd /k sfc /scannow\",\n                  \"Corrupted Windows files repair\")\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # SECTION 6 \u2014 DECISION TREE (Home vs Pro, IP vs Name)\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        s5 = _t3_section(\"\ud83d\uddfa  Windows Edition &amp; Connection Type \u2014 Kya Use Karo?\",\n                         \"Aapka Windows version aur connection method fix decide karta hai\",\n                         \"#1A2A3A\")\n\n        _t3_info_box(s5,\n            \"Windows HOME (jaise HP/Dell pe usually hota hai)\\n\"\n            \"  \u2192 gpedit.msc NAHI khulega\\n\"\n            \"  \u2192 Registry method use karo: RpcAuthnLevelPrivacyEnabled = 0\\n\"\n            \"  \u2192 Ya neeche Auto-Fix button seedha kaam karega\\n\\n\"\n            \"Windows PRO / ENTERPRISE (office machines usually)\\n\"\n            \"  \u2192 gpedit.msc bhi use kar sakte ho (Group Policy method)\\n\"\n            \"  \u2192 Registry method bhi kaam karta hai\\n\\n\"\n            \"IP Address se connect karna  (jaise \\\\\\\\192.168.1.15\\\\ShareName)\\n\"\n            \"  \u2192 Zyada reliable \u2014 naam resolution ki zaroorat nahi\\n\"\n            \"  \u2192 Credential Manager mein IP save karo\\n\\n\"\n            \"PC Name se connect karna  (jaise \\\\\\\\OFFICPC\\\\ShareName)\\n\"\n            \"  \u2192 NetBIOS naam resolution chahiye (lmhosts service)\\n\"\n            \"  \u2192 Agar naam se nahi ho raha to IP se try karo\",\n            bg=\"#0D1A2A\", fg=C[\"text\"])\n\n        # Windows Edition Check Button\n        def _check_win_edition():\n            out, _ = self._run_cmd(\n                'powershell -Command \"(Get-WmiObject -Class Win32_OperatingSystem).Caption\"',\n                timeout=10)\n            edition = out.strip() or \"Unknown\"\n            is_home = \"home\" in edition.lower()\n            msg = (\n                f\"Windows Edition: {edition}\\n\\n\"\n                + (\"\u26a0 HOME edition hai \u2014 gpedit.msc nahi khulega.\\n\"\n                   \"   Registry method ya Auto-Fix button use karo.\"\n                   if is_home else\n                   \"\u2705 Pro/Enterprise edition hai \u2014 gpedit.msc available hai.\\n\"\n                   \"   Group Policy ya Registry dono methods kaam karenge.\")\n            )\n            messagebox.showinfo(\"Windows Edition Check\", msg)\n            self._sharing_log(f\"\u2139 Windows: {edition}\", C[\"text_dim\"])\n\n        btn_row_s5 = tk.Frame(s5, bg=C[\"card\"])\n        btn_row_s5.pack(fill=\"x\", padx=8, pady=6)\n        tk.Button(btn_row_s5, text=\"\ud83d\udd0d Check Windows Edition\", font=FONTS[\"body\"],\n                  bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=14, pady=7, cursor=\"hand2\",\n                  command=_check_win_edition).pack(side=\"left\", padx=(0,8))\n        tk.Button(btn_row_s5, text=\"\ud83d\ude80 HOST Mega Auto-Fix\", font=FONTS[\"body\"],\n                  bg=\"#FF6600\", fg=C[\"text\"], bd=0, padx=14, pady=7, cursor=\"hand2\",\n                  command=self._host_mega_auto_fix).pack(side=\"left\", padx=(0,8))\n        tk.Button(btn_row_s5, text=\"\ud83d\ude80 CLIENT Mega Auto-Fix\", font=FONTS[\"body\"],\n                  bg=\"#FF6600\", fg=C[\"text\"], bd=0, padx=14, pady=7, cursor=\"hand2\",\n                  command=self._client_mega_auto_fix).pack(side=\"left\")\n\n        tk.Frame(t3_body, bg=C[\"bg\"], height=20).pack()  # bottom padding\n\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # \ud83d\udd34 TAB 4 \u2014 ENTERPRISE PRINTER RECOVERY CENTER\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        tab4 = tk.Frame(nb, bg=C[\"bg\"])\n        nb.add(tab4, text=\"  \ud83d\udd34  Network Printer Recovery  \")\n\n        # \u2500\u2500 Tab4 Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        t4_hdr = tk.Frame(tab4, bg=\"#1A0A0A\")\n        t4_hdr.pack(fill=\"x\")\n        tk.Label(t4_hdr, text=\"  \ud83d\udd34 Enterprise Network Printer Recovery Center\",\n                 font=FONTS[\"subhead\"], fg=\"#FF4444\", bg=\"#1A0A0A\").pack(side=\"left\", pady=4, padx=8)\n        tk.Label(t4_hdr,\n                 text=\"\\\"Windows Couldn't connect to the printer\\\" \u2014 Auto Diagnose &amp; Repair\",\n                 font=FONTS[\"xsmall\"], fg=C[\"text_dim\"], bg=\"#1A0A0A\").pack(side=\"left\", pady=4)\n\n        # \u2500\u2500 FULL AUTO FIX MEGA BUTTON \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        mega_frame = tk.Frame(tab4, bg=\"#2A0A0A\", pady=2)\n        mega_frame.pack(fill=\"x\", padx=8, pady=(3, 2))\n        tk.Label(mega_frame,\n                 text=\"  \u26a1 ONE-CLICK ENTERPRISE RECOVERY \u2014 Diagnose + Repair Everything Automatically\",\n                 font=FONTS[\"xsmall\"], fg=\"#FF9800\", bg=\"#2A0A0A\").pack(anchor=\"w\", padx=8, pady=(2,1))\n        self._epr_full_auto_btn = tk.Button(\n            mega_frame,\n            text=\"\ud83d\ude80  FULL AUTO FIX  \u2014  \\\"Windows Couldn't Connect to Printer\\\"  (All 18 Steps)\",\n            font=(\"Segoe UI\", 10, \"bold\"),\n            bg=\"#C62828\", fg=\"#FFFFFF\",\n            bd=0, padx=12, pady=6,\n            cursor=\"hand2\",\n            command=self._epr_full_auto_fix,\n            activebackground=\"#B71C1C\",\n            activeforeground=\"#FFFFFF\",\n            relief=\"flat\"\n        )\n        self._epr_full_auto_btn.pack(fill=\"x\", padx=8, pady=(1, 3))\n\n        # \u2500\u2500 Progress &amp; Status Bar \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        prog_frame = tk.Frame(tab4, bg=C[\"card\"])\n        prog_frame.pack(fill=\"x\", padx=8, pady=(0, 2))\n        prog_inner = tk.Frame(prog_frame, bg=C[\"card\"])\n        prog_inner.pack(fill=\"x\", padx=8, pady=2)\n        tk.Label(prog_inner, text=\"Status:\", font=FONTS[\"small\"],\n                 fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self.epr_status_lbl = tk.Label(prog_inner, text=\"Ready \u2014 Click FULL AUTO FIX to begin\",\n                                        font=FONTS[\"small\"], fg=C[\"accent4\"], bg=C[\"card\"])\n        self.epr_status_lbl.pack(side=\"left\", padx=6)\n        self.epr_progress = ttk.Progressbar(prog_frame, mode=\"indeterminate\", length=200)\n        self.epr_progress.pack(fill=\"x\", padx=8, pady=(0, 3))\n\n        # \u2500\u2500 Main body: 3-column layout \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        t4_body_outer = tk.Frame(tab4, bg=C[\"bg\"])\n        t4_body_outer.pack(fill=\"both\", expand=True, padx=8, pady=(0, 8))\n        t4_canvas = tk.Canvas(t4_body_outer, bg=C[\"bg\"], highlightthickness=0)\n        t4_vsb = ttk.Scrollbar(t4_body_outer, orient=\"vertical\", command=t4_canvas.yview)\n        t4_canvas.configure(yscrollcommand=t4_vsb.set)\n        t4_vsb.pack(side=\"right\", fill=\"y\")\n        t4_canvas.pack(side=\"left\", fill=\"both\", expand=True)\n        t4_body = tk.Frame(t4_canvas, bg=C[\"bg\"])\n        t4_win = t4_canvas.create_window((0, 0), window=t4_body, anchor=\"nw\")\n\n        def _t4_sc_resize(e):\n            t4_canvas.configure(scrollregion=t4_canvas.bbox(\"all\"))\n            t4_canvas.itemconfig(t4_win, width=t4_canvas.winfo_width())\n        t4_body.bind(\"\", _t4_sc_resize)\n        def _t4_canvas_configure(e):\n            t4_canvas.itemconfig(t4_win, width=e.width)\n            t4_canvas.configure(scrollregion=t4_canvas.bbox(\"all\"))\n        t4_canvas.bind(\"\", _t4_canvas_configure)\n        self._bind_scoped_mousewheel(t4_body, t4_canvas)\n\n        t4_body.columnconfigure(0, weight=1)\n        t4_body.columnconfigure(1, weight=1)\n        t4_body.columnconfigure(2, weight=1)\n\n        # \u2500\u2500 Helper functions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        def _t4_card(parent, title, color_hdr=\"#1A1A2E\"):\n            f = tk.Frame(parent, bg=C[\"card\"], bd=0)\n            h = tk.Frame(f, bg=color_hdr)\n            h.pack(fill=\"x\")\n            tk.Label(h, text=title, font=FONTS[\"subhead\"],\n                     fg=C[\"accent4\"], bg=color_hdr).pack(anchor=\"w\", padx=10, pady=6)\n            return f\n\n        def _t4_btn(parent, text, color, cmd, desc=\"\"):\n            row = tk.Frame(parent, bg=C[\"card\"])\n            row.pack(fill=\"x\", padx=6, pady=2)\n            tk.Button(row, text=text, font=FONTS[\"small\"],\n                      bg=color, fg=C[\"text\"], bd=0, padx=8, pady=5,\n                      cursor=\"hand2\", anchor=\"w\",\n                      command=cmd).pack(side=\"left\", fill=\"x\", expand=True)\n            if desc:\n                tk.Label(row, text=desc, font=(\"Consolas\", 8),\n                         fg=C[\"text_dim\"], bg=C[\"card\"],\n                         anchor=\"w\", wraplength=150).pack(side=\"left\", padx=(4, 2))\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # LEFT COLUMN \u2014 Connectivity &amp; Network\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        left_col = tk.Frame(t4_body, bg=C[\"bg\"])\n        left_col.grid(row=0, column=0, sticky=\"nsew\", padx=(0, 4), pady=4)\n\n        # \u2014 Tester / Validator Card \u2014\n        tester_card = _t4_card(left_col, \"\ud83d\udd0d  Printer Connection Tester\", \"#0D1B2A\")\n        tester_card.pack(fill=\"x\", pady=(0, 6))\n        tester_inner = tk.Frame(tester_card, bg=C[\"card\"])\n        tester_inner.pack(fill=\"x\", padx=8, pady=(4, 2))\n        tk.Label(tester_inner, text=\"Host IP / Name:\", font=FONTS[\"small\"],\n                 fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\")\n        self.epr_host_var = tk.StringVar(value=\"\")\n        tk.Entry(tester_inner, textvariable=self.epr_host_var,\n                 font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"],\n                 insertbackground=C[\"text\"], width=28).pack(fill=\"x\", pady=2)\n        tk.Label(tester_inner, text=\"Share Name:\", font=FONTS[\"small\"],\n                 fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(4, 0))\n        self.epr_share_var = tk.StringVar(value=\"\")\n        tk.Entry(tester_inner, textvariable=self.epr_share_var,\n                 font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"],\n                 insertbackground=C[\"text\"], width=28).pack(fill=\"x\", pady=2)\n        tk.Frame(tester_card, bg=C[\"border\"], height=1).pack(fill=\"x\", padx=8, pady=4)\n        _t4_btn(tester_card, \"\ud83d\udd0c  Ping Host PC\",           C[\"btn_chip\"], self._epr_ping_host,        \"ICMP ping test\")\n        _t4_btn(tester_card, \"\ud83d\uddc2  Test SMB Share Access\",  C[\"btn_chip\"], self._epr_test_smb,         \"\\\\\\\\host\\\\share reachability\")\n        _t4_btn(tester_card, \"\ud83d\udda8  Validate Printer Path\",  C[\"btn_chip\"], self._epr_validate_printer, \"UNC printer reachability\")\n        _t4_btn(tester_card, \"\ud83d\udd0c  Reconnect Shared Printer\", C[\"btn_info\"], self._epr_reconnect_shared, \"Auto reconnect + re-install\")\n        tk.Frame(tester_card, bg=C[\"bg\"], height=6).pack()\n\n        # \u2014 Network Share Validator \u2014\n        ns_card = _t4_card(left_col, \"\ud83c\udf10  Network Share Validator\", \"#0A1A1A\")\n        ns_card.pack(fill=\"x\", pady=(0, 6))\n        _t4_btn(ns_card, \"\ud83c\udf10  Network Share Validator\",    C[\"btn_info\"],  self._epr_net_share_validator, \"Validate share existence\")\n        _t4_btn(ns_card, \"\ud83d\udce1  Network Discovery Enable\",   C[\"btn_info\"],  self._epr_enable_netdiscovery, \"Private profile + FD services\")\n        _t4_btn(ns_card, \"\ud83d\udd25  Firewall Sharing Rules Fix\", C[\"btn_warn\"],  self._epr_firewall_fix,        \"F&amp;P sharing rules ON\")\n        tk.Frame(ns_card, bg=C[\"bg\"], height=6).pack()\n\n        # \u2014 Auto-Detection Status Area \u2014\n        det_card = _t4_card(left_col, \"\ud83d\udcca  Auto-Detection Status\", \"#1A2A0A\")\n        det_card.pack(fill=\"x\", pady=(0, 6))\n        self.epr_detect_log = self._scrolled_text(det_card, height=7)\n        _t4_btn(det_card, \"\ud83d\udd0d  Run Auto-Detection\",        C[\"btn_info\"],  self._epr_auto_detect, \"Diagnose root cause\")\n        tk.Frame(det_card, bg=C[\"bg\"], height=6).pack()\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # MIDDLE COLUMN \u2014 Repair Buttons\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        mid_col = tk.Frame(t4_body, bg=C[\"bg\"])\n        mid_col.grid(row=0, column=1, sticky=\"nsew\", padx=(4, 4), pady=4)\n\n        # \u2014 Spooler &amp; RPC \u2014\n        spool_card = _t4_card(mid_col, \"\u2699\ufe0f  Spooler &amp; RPC Repair\", \"#1A0A2E\")\n        spool_card.pack(fill=\"x\", pady=(0, 6))\n        _t4_btn(spool_card, \"\u26a1  Smart Spooler Recovery\",    C[\"btn_hw\"],    self._epr_smart_spooler,    \"Deep spooler + DLL repair\")\n        _t4_btn(spool_card, \"\ud83d\udd27  RPC + SMB Repair\",          C[\"btn_hw\"],    self._epr_rpc_smb_repair,   \"RpcAuthnLevel + SMB fix\")\n        _t4_btn(spool_card, \"\ud83d\uddd1  Printer Cache Cleaner\",      C[\"btn_danger\"], self._epr_cache_cleaner,   \"Corrupted mappings removal\")\n        _t4_btn(spool_card, \"\ud83d\udd04  Full Printer Reset\",         C[\"btn_danger\"], self._epr_full_reset,      \"Nuclear reset + reinstall\")\n        tk.Frame(spool_card, bg=C[\"bg\"], height=6).pack()\n\n        # \u2014 Permissions &amp; Drivers \u2014\n        perm_card = _t4_card(mid_col, \"\ud83d\udd11  Permissions &amp; Drivers\", \"#1A1A0A\")\n        perm_card.pack(fill=\"x\", pady=(0, 6))\n        _t4_btn(perm_card, \"\ud83d\udd11  Shared Printer Permission Repair\", C[\"btn_warn\"], self._epr_permission_repair, \"ACL + GPO permissions\")\n        _t4_btn(perm_card, \"\ud83d\udda8  Point &amp; Print Repair\",             C[\"btn_warn\"], self._epr_point_print_repair, \"NoWarning + restriction fix\")\n        _t4_btn(perm_card, \"\ud83d\udd27  Driver Compatibility Repair\",      C[\"btn_chip\"], self._epr_driver_compat,     \"x86/x64 mismatch fix\")\n        _t4_btn(perm_card, \"\ud83d\udce1  Canon Printer Compatibility Fix\",  C[\"btn_chip\"], self._epr_canon_fix,         \"CNUSB + Canon-specific fix\")\n        tk.Frame(perm_card, bg=C[\"bg\"], height=6).pack()\n\n        # \u2014 Error-Specific Fixes \u2014\n        err_card = _t4_card(mid_col, \"\ud83d\udd34  Error-Specific Repairs\", \"#2A0A0A\")\n        err_card.pack(fill=\"x\", pady=(0, 6))\n        for err_code, err_desc, err_fn in [\n            (\"0x0000011b\", \"RPC Encryption / KB5005565\",   self._epr_fix_11b),\n            (\"0x0000007c\", \"Printer Driver Corrupt\",        self._epr_fix_7c),\n            (\"0x00000709\", \"Default Printer Cannot Set\",    self._epr_fix_709),\n            (\"Access Denied\", \"Printer ACL / Auth Fail\",   self._epr_fix_access_denied),\n            (\"RPC Unavailable\", \"RPC Server Unavailable\",  self._epr_fix_rpc_unavail),\n            (\"Driver Missing\", \"Driver Not Found / Bad\",   self._epr_fix_driver_missing),\n            (\"Path Not Found\", \"Network Path Not Found\",   self._epr_fix_path_not_found),\n        ]:\n            row = tk.Frame(err_card, bg=C[\"card\"])\n            row.pack(fill=\"x\", padx=6, pady=2)\n            tk.Label(row, text=err_code, font=(\"Consolas\", 9, \"bold\"),\n                     fg=C[\"error\"], bg=C[\"card\"], width=14, anchor=\"w\").pack(side=\"left\", padx=(4, 0))\n            tk.Label(row, text=err_desc, font=FONTS[\"small\"],\n                     fg=C[\"text_dim\"], bg=C[\"card\"], anchor=\"w\").pack(side=\"left\", padx=(4, 4))\n            tk.Button(row, text=\"Fix\", font=FONTS[\"small\"],\n                      bg=C[\"btn_danger\"], fg=C[\"text\"], bd=0, padx=10, pady=3,\n                      cursor=\"hand2\", command=err_fn).pack(side=\"right\", padx=4)\n        tk.Frame(err_card, bg=C[\"bg\"], height=6).pack()\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # RIGHT COLUMN \u2014 Live Diagnostics + Repair Log + Summary\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        right_col = tk.Frame(t4_body, bg=C[\"bg\"])\n        right_col.grid(row=0, column=2, sticky=\"nsew\", padx=(4, 0), pady=4)\n\n        # \u2014 Live Diagnostics Panel \u2014\n        diag_card = _t4_card(right_col, \"\ud83d\udce1  Live Diagnostics Panel\", \"#0D2A1A\")\n        diag_card.pack(fill=\"x\", pady=(0, 4))\n        self.epr_diag_log = self._scrolled_text(diag_card, height=8)\n\n        # \u2014 Repair Log Viewer \u2014\n        replog_card = _t4_card(right_col, \"\ud83d\udcdd  Repair Log\", \"#2A1A0A\")\n        replog_card.pack(fill=\"x\", pady=(0, 4))\n        self.epr_repair_log = self._scrolled_text(replog_card, height=6)\n\n        # \u2014 Recovery Summary Viewer \u2014\n        summ_card = _t4_card(right_col, \"\ud83d\udccb  Recovery Summary\", \"#0A1A2A\")\n        summ_card.pack(fill=\"x\", pady=(0, 4))\n        self.epr_summary_log = self._scrolled_text(summ_card, height=4)\n\n        # \u2014 RPC Smart Switcher Panel \u2014\n        rpc_panel = tk.Frame(right_col, bg=\"#1E1A00\")\n        rpc_panel.pack(fill=\"x\", padx=0, pady=(0, 4))\n        hdr_rpc = tk.Frame(rpc_panel, bg=\"#2A2200\")\n        hdr_rpc.pack(fill=\"x\")\n        tk.Label(hdr_rpc, text=\"  \u26a1 Smart RPC Privacy Switcher\",\n                 font=FONTS[\"subhead\"], fg=\"#FFCC00\", bg=\"#2A2200\").pack(side=\"left\", padx=8, pady=6)\n        rpc_info = tk.Frame(rpc_panel, bg=\"#1E1A00\")\n        rpc_info.pack(fill=\"x\", padx=8, pady=4)\n        self.epr_rpc_status_lbl = tk.Label(rpc_info,\n            text=\"RpcAuthnLevelPrivacyEnabled: Checking...\",\n            font=FONTS[\"small\"], fg=C[\"warning\"], bg=\"#1E1A00\")\n        self.epr_rpc_status_lbl.pack(anchor=\"w\")\n        btn_rpc_row = tk.Frame(rpc_panel, bg=\"#1E1A00\")\n        btn_rpc_row.pack(fill=\"x\", padx=8, pady=(0, 6))\n        tk.Button(btn_rpc_row, text=\"\ud83d\udd0d Check RPC Setting\",\n                  font=FONTS[\"small\"], bg=C[\"btn_chip\"], fg=C[\"text\"],\n                  bd=0, padx=10, pady=5, cursor=\"hand2\",\n                  command=self._epr_check_rpc_setting).pack(side=\"left\", padx=(0, 6))\n        tk.Button(btn_rpc_row, text=\"\ud83d\udd27 Smart RPC Fix (Auto Validate + Rollback)\",\n                  font=FONTS[\"small\"], bg=C[\"btn_warn\"], fg=C[\"text\"],\n                  bd=0, padx=10, pady=5, cursor=\"hand2\",\n                  command=self._epr_smart_rpc_fix).pack(side=\"left\")\n        tk.Frame(right_col, bg=C[\"bg\"], height=90).pack(fill=\"x\")\n        self.after(250, lambda c=t4_canvas: c.configure(scrollregion=c.bbox(\"all\")))\n\n\n        return frame\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \u2699 AUTO-FIX: gpedit.msc RPC Setting \u2014 Error 709\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _auto_gpedit_rpc_709(self):\n        \"\"\"Group Policy: Configure RPC \u2192 Named Pipes (for 709 fix).\"\"\"\n        if not messagebox.askyesno(\"\u2699 Auto-Fix: gpedit RPC Setting (Error 709)\",\n                \"Ye setting Group Policy mein auto set hogi:\\n\\n\"\n                \"Path: Computer Config \u2192 Admin Templates \u2192 Printers\\n\"\n                \"Setting: Configure RPC connection settings\\n\"\n                \"Value: Enabled, Protocol: RPC over named pipes\\n\\n\"\n                \"\u26a0 Windows Pro/Enterprise pe hi kaam karta hai.\\n\"\n                \"Windows Home me bhi try karega \u2014 Registry fallback bhi chalega.\\n\\n\"\n                \"Continue karein?\"):\n            return\n        self._sharing_log(\"\u2699 [gpedit] RPC setting fix chal raha hai (Error 709)...\", C[\"accent4\"])\n        self._launch_job(\"gpedit_rpc_fix\", self._do_auto_gpedit_rpc)\n\n    def _auto_gpedit_rpc_11b(self):\n        \"\"\"Group Policy: Configure RPC \u2192 Named Pipes (for 11b fix).\"\"\"\n        if not messagebox.askyesno(\"\u2699 Auto-Fix: gpedit RPC Setting (Error 0x0000011b)\",\n                \"Ye setting Group Policy mein auto set hogi:\\n\\n\"\n                \"Path: Computer Config \u2192 Admin Templates \u2192 Printers\\n\"\n                \"Setting: Configure RPC connection settings\\n\"\n                \"Value: Enabled, Protocol: RPC over named pipes\\n\\n\"\n                \"\u26a0 DONO PCs pe alag-alag run karo \u2014 HOST aur CLIENT dono pe!\\n\"\n                \"Windows Home me bhi try karega \u2014 Registry fallback bhi chalega.\\n\\n\"\n                \"Continue karein?\"):\n            return\n        self._sharing_log(\"\u2699 [gpedit] RPC setting fix chal raha hai (Error 11b)...\", C[\"accent4\"])\n        self._launch_job(\"gpedit_rpc_fix\", self._do_auto_gpedit_rpc)\n\n    def _do_auto_gpedit_rpc(self):\n        \"\"\"\n        Internally Group Policy ki 'Configure RPC connection settings' wali setting\n        Registry ke through set karta hai \u2014 gpedit.msc open kiye bina.\n        HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Printers\\\\RPC\n        RpcUseNamedPipeProtocol = 1  (Named Pipes force karo)\n        ForceKerberosForRpc     = 0  (Kerberos RPC strict band)\n        RpcTcpPort              = 0  (TCP port: 0 = any)\n        AllowEncryptedPrinterRPC= 0  (Encrypted RPC: off)\n        \"\"\"\n        log = self._sharing_log\n        L = C\n        reg_path = r\"SOFTWARE\\Policies\\Microsoft\\Windows NT\\Printers\\RPC\"\n\n        log(\"  [gpedit-auto 1/4] RpcUseNamedPipeProtocol = 1 (Named Pipes)...\", L[\"accent4\"])\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE, reg_path,\n                          \"RpcUseNamedPipeProtocol\", 1, winreg.REG_DWORD)\n            log(\"  \u2705 RpcUseNamedPipeProtocol = 1\", L[\"success\"])\n        except Exception as e:\n            self._run_cmd(f'reg add \"HKLM\\\\{reg_path}\" /v RpcUseNamedPipeProtocol /t REG_DWORD /d 1 /f')\n            log(f\"  \u2705 RpcUseNamedPipeProtocol = 1 (reg cmd, {e})\", L[\"success\"])\n\n        log(\"  [gpedit-auto 2/4] ForceKerberosForRpc = 0 (Kerberos strict band)...\", L[\"accent4\"])\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE, reg_path,\n                          \"ForceKerberosForRpc\", 0, winreg.REG_DWORD)\n            log(\"  \u2705 ForceKerberosForRpc = 0\", L[\"success\"])\n        except Exception as e:\n            self._run_cmd(f'reg add \"HKLM\\\\{reg_path}\" /v ForceKerberosForRpc /t REG_DWORD /d 0 /f')\n            log(f\"  \u2705 ForceKerberosForRpc = 0 (reg cmd)\", L[\"success\"])\n\n        log(\"  [gpedit-auto 3/4] AllowEncryptedPrinterRPC = 0 (Encrypted RPC off)...\", L[\"accent4\"])\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE, reg_path,\n                          \"AllowEncryptedPrinterRPC\", 0, winreg.REG_DWORD)\n            log(\"  \u2705 AllowEncryptedPrinterRPC = 0\", L[\"success\"])\n        except Exception as e:\n            self._run_cmd(f'reg add \"HKLM\\\\{reg_path}\" /v AllowEncryptedPrinterRPC /t REG_DWORD /d 0 /f')\n            log(f\"  \u2705 AllowEncryptedPrinterRPC = 0 (reg cmd)\", L[\"success\"])\n\n        log(\"  [gpedit-auto 4/4] RpcAuthnLevelPrivacyEnabled = 0 (main fix)...\", L[\"accent4\"])\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                          r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                          \"RpcAuthnLevelPrivacyEnabled\", 0, winreg.REG_DWORD)\n            log(\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0\", L[\"success\"])\n        except Exception as e:\n            self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\" /v RpcAuthnLevelPrivacyEnabled /t REG_DWORD /d 0 /f')\n            log(f\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0 (reg cmd)\", L[\"success\"])\n\n        log(\"\u2705 gpedit RPC settings \u2014 auto apply ho gayi!\", L[\"success\"])\n        log(\"   \u25ba Computer restart karo for Group Policy to take full effect.\", L[\"text_dim\"])\n        self.after(0, lambda: messagebox.showinfo(\n            \"\u2705 gpedit Auto-Fix Done!\",\n            \"Group Policy RPC settings apply ho gayi:\\n\\n\"\n            \"  \u2705 RpcUseNamedPipeProtocol = 1  (Named Pipes)\\n\"\n            \"  \u2705 ForceKerberosForRpc     = 0\\n\"\n            \"  \u2705 AllowEncryptedPrinterRPC = 0\\n\"\n            \"  \u2705 RpcAuthnLevelPrivacyEnabled = 0\\n\\n\"\n            \"\u26a0 Agar dono PCs hain to DONO pe run karo.\\n\"\n            \"Computer restart karo for full effect.\"))\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \ud83d\udddd AUTO-FIX: Registry \u2014 RpcAuthnLevelPrivacyEnabled = 0\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _auto_reg_rpcauth_0(self):\n        \"\"\"Registry: HKLM\\\\...\\\\Control\\\\Print \u2192 RpcAuthnLevelPrivacyEnabled = 0\"\"\"\n        self._sharing_log(\"\ud83d\udddd [Registry] RpcAuthnLevelPrivacyEnabled = 0 set kar raha hoon...\", C[\"accent4\"])\n        def _r():\n            try:\n                self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                              r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                              \"RpcAuthnLevelPrivacyEnabled\", 0, winreg.REG_DWORD)\n                self._sharing_log(\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0  \u2190 DONE\", C[\"success\"])\n                self.after(0, lambda: messagebox.showinfo(\n                    \"\u2705 Registry Fix Done!\",\n                    \"Registry set ho gayi:\\n\\n\"\n                    \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\\n\"\n                    \"  RpcAuthnLevelPrivacyEnabled = 0\\n\\n\"\n                    \"\u26a0 DONO PCs pe alag-alag run karo (HOST + CLIENT).\\n\"\n                    \"Phir Spooler restart karo \u2014 button neeche hai.\"))\n            except Exception as e:\n                # cmd fallback\n                out, rc = self._run_cmd(\n                    'reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\" '\n                    '/v RpcAuthnLevelPrivacyEnabled /t REG_DWORD /d 0 /f')\n                if rc == 0:\n                    self._sharing_log(\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0 (reg cmd fallback)\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"\u2705 Done!\", \"Registry fix ho gayi!\\nSpooler restart karo.\"))\n                else:\n                    self._sharing_log(f\"  \u274c Registry set failed: {e} | rc={rc}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", f\"Registry set nahi hua:\\n{e}\\n\\nAdmin mode mein run karo.\"))\n        self._launch_job(\"auto_reg_rpcauth\", _r)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \ud83d\udddd AUTO-FIX: Registry \u2014 LegacyDefaultPrinterMode = 1\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _auto_reg_legacy_default(self):\n        \"\"\"Registry: HKCU\\\\...\\\\Windows \u2192 LegacyDefaultPrinterMode = 1\"\"\"\n        self._sharing_log(\"\ud83d\udddd [Registry] LegacyDefaultPrinterMode = 1 set kar raha hoon...\", C[\"accent4\"])\n        def _r():\n            try:\n                key = winreg.OpenKey(\n                    winreg.HKEY_CURRENT_USER,\n                    r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows\",\n                    0, winreg.KEY_SET_VALUE)\n                winreg.SetValueEx(key, \"LegacyDefaultPrinterMode\", 0, winreg.REG_DWORD, 1)\n                winreg.CloseKey(key)\n                self._sharing_log(\"  \u2705 LegacyDefaultPrinterMode = 1  \u2190 DONE\", C[\"success\"])\n                self.after(0, lambda: messagebox.showinfo(\n                    \"\u2705 Registry Fix Done!\",\n                    \"Registry set ho gayi:\\n\\n\"\n                    \"HKCU\\\\SOFTWARE\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\Windows\\n\"\n                    \"  LegacyDefaultPrinterMode = 1\\n\\n\"\n                    \"Windows ab printer default automatically change nahi karega.\\n\"\n                    \"Spooler restart karo \u2014 button neeche hai.\"))\n            except Exception as e:\n                out, rc = self._run_cmd(\n                    'reg add \"HKCU\\\\SOFTWARE\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\Windows\" '\n                    '/v LegacyDefaultPrinterMode /t REG_DWORD /d 1 /f')\n                if rc == 0:\n                    self._sharing_log(\"  \u2705 LegacyDefaultPrinterMode = 1 (reg cmd fallback)\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"\u2705 Done!\", \"Registry fix ho gayi!\"))\n                else:\n                    self._sharing_log(f\"  \u274c Failed: {e}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", f\"Registry set nahi hua:\\n{e}\"))\n        self._launch_job(\"auto_reg_legacy_default\", _r)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \ud83d\udddd AUTO-FIX: Registry \u2014 UserSelectedDefault DELETE\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _auto_reg_delete_userselected(self):\n        \"\"\"Registry: HKCU\\\\...\\\\Windows \u2192 Delete UserSelectedDefault\"\"\"\n        self._sharing_log(\"\ud83d\udddd [Registry] UserSelectedDefault delete kar raha hoon...\", C[\"accent4\"])\n        def _r():\n            try:\n                key = winreg.OpenKey(\n                    winreg.HKEY_CURRENT_USER,\n                    r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows\",\n                    0, winreg.KEY_SET_VALUE | winreg.KEY_READ)\n                try:\n                    winreg.DeleteValue(key, \"UserSelectedDefault\")\n                    self._sharing_log(\"  \u2705 UserSelectedDefault deleted \u2014 Windows fresh default set karega\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\n                        \"\u2705 Done!\",\n                        \"UserSelectedDefault registry value delete ho gayi!\\n\\n\"\n                        \"Windows ab apne aap fresh default printer set karega.\\n\"\n                        \"Spooler restart karo ya reboot karo.\"))\n                except FileNotFoundError:\n                    self._sharing_log(\"  \u2139 UserSelectedDefault nahi mili \u2014 already clean hai\", C[\"text_dim\"])\n                    self.after(0, lambda: messagebox.showinfo(\"\u2139 Info\",\n                        \"UserSelectedDefault value nahi mili.\\n\"\n                        \"Already clean hai \u2014 koi action zaruri nahi.\"))\n                winreg.CloseKey(key)\n            except Exception as e:\n                self._sharing_log(f\"  \u274c Delete failed: {e}\", C[\"error\"])\n                self.after(0, lambda: messagebox.showerror(\"Error\", f\"Delete nahi hua:\\n{e}\"))\n        self._launch_job(\"auto_reg_delete_userselected\", _r)\n\n    def _printer_detect(self):\n        self._set_status(\"Detecting printers...\", C[\"accent4\"])\n        self._printer_action_submit(\"printer_detect\", self._do_printer_detect)\n\n    def _do_printer_detect(self):\n        out, _ = self._run_cmd(\n            'powershell -Command \"Get-Printer | Select-Object Name,PrinterStatus,Default,JobCount | ConvertTo-Csv -NoTypeInformation\"',\n            timeout=15)\n        rows = []\n        counts = {\"total\":0,\"online\":0,\"offline\":0,\"default\":\"\u2014\"}\n        for line in out.splitlines()[1:]:\n            line = line.strip().replace('\"','')\n            parts = line.split(',')\n            if len(parts) &lt; 4:\n                continue\n            name    = parts[0].strip()\n            status  = parts[1].strip()\n            default = parts[2].strip()\n            jobs    = parts[3].strip()\n            if not name:\n                continue\n            is_online  = status.lower() in (\"normal\",\"0\",\"idle\")\n            is_default = default.lower() == \"true\"\n            status_txt = \"\ud83d\udfe2 Online\" if is_online else \"\ud83d\udd34 Offline\"\n            def_txt    = \"\u2705 Yes\" if is_default else \"\"\n            tag = \"default\" if is_default else (\"online\" if is_online else \"offline\")\n            rows.append(((name, status_txt, def_txt, jobs or \"0\"), tag,\n                         {\"name\":name,\"online\":is_online,\"default\":is_default}))\n            counts[\"total\"] += 1\n            if is_online:\n                counts[\"online\"] += 1\n            else:\n                counts[\"offline\"] += 1\n            if is_default:\n                counts[\"default\"] = name[:18]\n\n        self._printer_data = rows\n\n        def insert():\n            for i in self.printer_tree.get_children():\n                self.printer_tree.delete(i)\n            for row, tag, _ in rows:\n                self.printer_tree.insert(\"\",\"end\", values=row, tags=(tag,))\n            for k,v in counts.items():\n                if k in self.printer_stat_vars:\n                    self.printer_stat_vars[k].set(str(v))\n            self._set_status(f\"Found {counts['total']} printers \u2014 {counts['online']} online, {counts['offline']} offline\", C[\"success\"])\n            self._refresh_spooler_status()\n            self._append_log(self.printer_log, f\"\u2705 Scan complete \u2014 {counts['total']} printers detected\", C[\"success\"])\n        self.after(0, insert)\n\n    def _on_printer_select(self, event=None):\n        sel = self.printer_tree.selection()\n        if not sel or not self._printer_data:\n            return\n        idx = self.printer_tree.index(sel[0])\n        if idx &gt;= len(self._printer_data):\n            return\n        meta = self._printer_data[idx][2]\n        self._append_log(self.printer_log,\n            f\"\u2139 Selected: {meta['name']} \u2014 {'Online' if meta['online'] else 'OFFLINE'}{'  [DEFAULT]' if meta['default'] else ''}\",\n            C[\"accent2\"])\n\n    def _refresh_spooler_status(self):\n        out, _ = self._run_cmd('sc query Spooler', timeout=5)\n        if \"RUNNING\" in out:\n            self.spooler_status_lbl.config(text=\"\u2705 Running\", fg=C[\"success\"])\n        elif \"STOPPED\" in out:\n            self.spooler_status_lbl.config(text=\"\u274c STOPPED\", fg=C[\"error\"])\n        else:\n            self.spooler_status_lbl.config(text=\"\u26a0 Unknown\", fg=C[\"warning\"])\n\n    def _printer_reset_spooler(self):\n        self._printer_action_submit(\"printer_reset_spooler\", self._do_reset_spooler)\n\n    def _do_reset_spooler(self):\n        self._printer_log(\"\u2501\"*50, C[\"border\"])\n        self._printer_log(\"\ud83d\udd01 Spooler restart ho raha hai...\", C[\"accent4\"])\n        # Stop spooler\n        self._run_cmd('net stop spooler /y')\n        self._printer_log(\"  \u23f9 Spooler stopped\", C[\"warning\"])\n        # Also stop dependent services\n        self._run_cmd('net stop \"Print Spooler\" /y')\n        time.sleep(1)\n        # Start spooler\n        self._run_cmd('net start spooler')\n        self._printer_log(\"  \u25b6 Spooler started\", C[\"success\"])\n        # Verify\n        out, _ = self._run_cmd('sc query Spooler')\n        if \"RUNNING\" in out:\n            self._printer_log(\"\u2705 Spooler successfully restarted!\", C[\"success\"])\n        else:\n            self._printer_log(\"\u274c Spooler start nahi hua \u2014 Full Repair try karo.\", C[\"error\"])\n        self.after(0, self._refresh_spooler_status)\n\n    def _printer_clear_jobs(self):\n        if not messagebox.askyesno(\"Clear Print Jobs\",\n                \"Saare stuck print jobs delete ho jaayenge.\\n\"\n                \"Spooler restart hoga.\\nAage badhein?\"):\n            return\n        self._printer_action_submit(\"printer_clear_jobs\", self._do_clear_jobs)\n\n    def _do_clear_jobs(self):\n        self._printer_log(\"\u2501\"*50, C[\"border\"])\n        self._printer_log(\"\ud83d\uddd1 Print jobs clear ho rahe hain...\", C[\"accent4\"])\n        # Stop spooler\n        self._run_cmd('net stop spooler /y')\n        self._printer_log(\"  \u23f9 Spooler stopped\", C[\"warning\"])\n        time.sleep(1)\n        # Delete spool files\n        spool_dir = os.path.join(os.environ.get(\"SYSTEMROOT\",\"C:\\\\Windows\"),\n                                  \"System32\",\"spool\",\"PRINTERS\")\n        deleted = 0\n        if os.path.exists(spool_dir):\n            for f in Path(spool_dir).glob(\"*\"):\n                try:\n                    f.unlink()\n                    deleted += 1\n                except: pass\n        self._printer_log(f\"  \ud83d\uddd1 {deleted} spool files deleted from {spool_dir}\", C[\"warning\"])\n        # Restart spooler\n        self._run_cmd('net start spooler')\n        self._printer_log(\"  \u25b6 Spooler restarted\", C[\"success\"])\n        self._printer_log(\"\u2705 Print queue cleared! Ab print karo.\", C[\"success\"])\n        self.after(0, self._refresh_spooler_status)\n\n    def _printer_full_repair(self):\n        if not messagebox.askyesno(\"\ud83d\udd27 Full Printer Auto-Repair\",\n                \"Ye steps perform hoge:\\n\"\n                \"1. Spooler stop + restart\\n\"\n                \"2. Stuck jobs delete\\n\"\n                \"3. Spooler DLL re-register\\n\"\n                \"4. Firewall rules check\\n\"\n                \"5. Registry default path verify\\n\"\n                \"6. Spooler auto startup set\\n\\n\"\n                \"Aage badhein?\"):\n            return\n        self._printer_action_submit(\"printer_full_repair\", self._do_full_repair)\n\n    def _printer_driver_purge_flow(self):\n        sel = self.printer_tree.selection()\n        if not sel or not self._printer_data:\n            messagebox.showinfo(\"Select Printer\", \"Pehle printer select karo.\")\n            return\n        idx = self.printer_tree.index(sel[0])\n        if idx &gt;= len(self._printer_data):\n            return\n        name = self._printer_data[idx][2][\"name\"]\n        if not messagebox.askyesno(\"Driver Purge/Reinstall\",\n                                   f\"Selected printer:\\n{name}\\n\\n\"\n                                   \"Steps:\\n\"\n                                   \"1) Remove printer\\n\"\n                                   \"2) Remove printer driver\\n\"\n                                   \"3) pnputil cleanup (best-effort)\\n\\n\"\n                                   \"Proceed? (Admin recommended)\"):\n            return\n        self._printer_action_submit(\"printer_driver_purge\", self._do_printer_driver_purge, name)\n\n    def _do_printer_driver_purge(self, printer_name):\n        self._printer_log(\"\u2550\"*52, C[\"border\"])\n        self._printer_log(f\"\ud83e\uddf9 Driver purge starting for: {printer_name}\", C[\"accent4\"])\n        # Detect driver name\n        drv = \"\"\n        out, rc = self._run_cmd(\n            f'powershell -Command \"(Get-Printer -Name \\'{printer_name}\\' -ErrorAction SilentlyContinue).DriverName\"',\n            timeout=15\n        )\n        if rc == 0:\n            drv = (out or \"\").strip().splitlines()[-1].strip()\n        self._printer_log(f\"Driver detected: {drv if drv else 'Unknown'}\", C[\"text_dim\"])\n        # Remove printer\n        out2, rc2 = self._run_cmd(\n            f'powershell -Command \"Remove-Printer -Name \\'{printer_name}\\' -ErrorAction SilentlyContinue\"',\n            timeout=20\n        )\n        self._printer_log(\"\u2705 Printer removed\" if rc2 == 0 else f\"\u26a0 Remove printer rc={rc2}: {out2[:200]}\", C[\"success\"] if rc2 == 0 else C[\"warning\"])\n        # Remove driver\n        if drv:\n            out3, rc3 = self._run_cmd(\n                f'powershell -Command \"Remove-PrinterDriver -Name \\'{drv}\\' -ErrorAction SilentlyContinue\"',\n                timeout=25\n            )\n            self._printer_log(\"\u2705 Driver removed\" if rc3 == 0 else f\"\u26a0 Remove driver rc={rc3}: {out3[:200]}\", C[\"success\"] if rc3 == 0 else C[\"warning\"])\n        # pnputil cleanup (best-effort)\n        out4, rc4 = self._run_cmd('pnputil /enum-drivers', timeout=25)\n        if rc4 == 0 and drv:\n            self._printer_log(\"\u2139 pnputil listed drivers (manual cleanup if needed).\", C[\"text_dim\"])\n        self._printer_log(\"\u2705 Driver purge flow complete. Now reinstall printer driver and add printer again.\", C[\"success\"])\n        self.after(0, self._printer_detect)\n\n    def _do_full_repair(self):\n        self._printer_log(\"\u2550\"*52, C[\"border\"])\n        self._printer_log(\"  \ud83d\udd27 FULL PRINTER AUTO-REPAIR STARTING\", C[\"hw_accent\"])\n        self._printer_log(\"\u2550\"*52, C[\"border\"])\n\n        # Step 1 \u2014 Stop spooler\n        self._printer_log(\"\\n[1/6] Spooler band kar raha hoon...\", C[\"accent4\"])\n        try:\n            self._service_config_checked(\"Spooler\", \"auto\", \"Spooler startup=auto\", self.printer_log)\n        except Exception:\n            pass\n        try:\n            self._service_stop_checked(\"Spooler\", \"Print Spooler\", self.printer_log)\n        except Exception:\n            self._run_cmd('net stop spooler /y')\n        self._printer_log(\"  \u2705 Spooler stopped, startup=auto set\", C[\"success\"])\n\n        # Step 2 \u2014 Clear spool folder\n        self._printer_log(\"\\n[2/6] Stuck print jobs delete kar raha hoon...\", C[\"accent4\"])\n        spool_dir = os.path.join(os.environ.get(\"SYSTEMROOT\",\"C:\\\\Windows\"),\n                                  \"System32\",\"spool\",\"PRINTERS\")\n        deleted = 0\n        for f in Path(spool_dir).glob(\"*\"):\n            try: f.unlink(); deleted += 1\n            except: pass\n        self._printer_log(f\"  \u2705 {deleted} stuck jobs deleted\", C[\"success\"])\n\n        # Step 3 \u2014 Re-register spooler DLLs\n        self._printer_log(\"\\n[3/6] Spooler DLLs re-register kar raha hoon...\", C[\"accent4\"])\n        sys32 = os.path.join(os.environ.get(\"SYSTEMROOT\",\"C:\\\\Windows\"), \"System32\")\n        for dll in [\"spoolsv.exe\",\"localspl.dll\",\"spoolss.dll\",\"win32spl.dll\"]:\n            path = os.path.join(sys32, dll)\n            if os.path.exists(path) and dll.endswith(\".dll\"):\n                self._run_cmd(f'regsvr32 /s \"{path}\"')\n                self._printer_log(f\"  \u2705 Registered: {dll}\", C[\"success\"])\n            elif os.path.exists(path):\n                self._printer_log(f\"  \u2705 Found: {dll}\", C[\"success\"])\n            else:\n                self._printer_log(f\"  \u274c Missing: {dll} \u2014 SFC /scannow try karo\", C[\"error\"])\n\n        # Step 4 \u2014 Firewall rules for printing\n        self._printer_log(\"\\n[4/6] Printer firewall rules check kar raha hoon...\", C[\"accent4\"])\n        for port, proto, name in [\n            (135,\"TCP\",\"RPC\"),\n            (445,\"TCP\",\"SMB\"),\n            (9100,\"TCP\",\"RAW Print\"),\n            (631,\"TCP\",\"IPP Print\"),\n        ]:\n            self._run_cmd(f'netsh advfirewall firewall add rule name=\"GodawariPrint_{name}\" '\n                          f'dir=in action=allow protocol={proto} localport={port} '\n                          f'profile=private,domain')\n            self._printer_log(f\"  \u2705 Port {port}/{proto} ({name}) open\", C[\"success\"])\n\n        # Step 5 \u2014 Registry spool path verify\n        self._printer_log(\"\\n[5/6] Registry spool path verify kar raha hoon...\", C[\"accent4\"])\n        default_spool = spool_dir\n        try:\n            key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,\n                                  r\"SYSTEM\\CurrentControlSet\\Control\\Print\\Printers\",\n                                  0, winreg.KEY_SET_VALUE | winreg.KEY_READ)\n            try:\n                current, _ = winreg.QueryValueEx(key, \"DefaultSpoolDirectory\")\n                if not os.path.exists(current):\n                    winreg.SetValueEx(key, \"DefaultSpoolDirectory\", 0,\n                                      winreg.REG_SZ, default_spool)\n                    self._printer_log(f\"  \u2705 Spool path fixed: {default_spool}\", C[\"success\"])\n                else:\n                    self._printer_log(f\"  \u2705 Spool path OK: {current}\", C[\"success\"])\n            except:\n                self._printer_log(\"  \u2139 Spool path entry not found \u2014 using default\", C[\"text_dim\"])\n            winreg.CloseKey(key)\n        except Exception as e:\n            self._printer_log(f\"  \u26a0 Registry check failed: {e}\", C[\"warning\"])\n\n        # Step 6 \u2014 PrintNightmare mitigation\n        self._printer_log(\"\\n[6/6] PrintNightmare security fix kar raha hoon...\", C[\"accent4\"])\n        self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                      r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                      \"RpcAuthnLevelPrivacyEnabled\", 1, winreg.REG_DWORD)\n        self._printer_log(\"  \u2705 RPC auth level hardened\", C[\"success\"])\n\n        # Start spooler\n        try:\n            self._service_start_checked(\"Spooler\", \"Print Spooler\", self.printer_log)\n        except Exception:\n            self._run_cmd('net start spooler')\n        self._printer_log(\"\\n\u2550\"*52, C[\"border\"])\n        self._printer_log(\"\u2705 FULL REPAIR COMPLETE! Ab printer test karo.\", C[\"success\"])\n        self._printer_log(\"   Agar abhi bhi problem hai \u2014 Driver reinstall karo.\", C[\"text_dim\"])\n        self.after(0, self._refresh_spooler_status)\n\n    def _printer_sfc(self):\n        if not messagebox.askyesno(\"SFC Scan\",\n                \"System File Checker chalega \u2014 Windows files repair karega.\\n\"\n                \"10-15 minute lag sakte hain.\\nAage badhein?\"):\n            return\n        self._printer_log(\"\ud83d\udd0d SFC /scannow chal raha hai...\", C[\"accent4\"])\n        self._printer_action_submit(\"printer_sfc\", self._do_printer_sfc)\n\n    def _do_printer_sfc(self):\n        out, _ = self._run_cmd('sfc /scannow', timeout=900)\n        self._printer_log(out[-300:] if isinstance(out, str) else \"SFC completed.\", C[\"text\"])\n        self._printer_log(\"\u2705 SFC complete\", C[\"success\"])\n\n    def _printer_printnightmare(self):\n        if not messagebox.askyesno(\"PrintNightmare Fix\",\n                \"PrintNightmare vulnerability fix karega:\\n\"\n                \"\u2022 Remote access restrict karega\\n\"\n                \"\u2022 Point and Print disable karega\\n\"\n                \"\u2022 RPC auth harden karega\\nAage badhein?\"):\n            return\n        self._printer_action_submit(\"printer_printnightmare\", self._do_printer_printnightmare)\n\n    def _do_printer_printnightmare(self):\n        self._printer_log(\"\ud83d\udd12 Applying PrintNightmare mitigations...\", C[\"accent4\"])\n        self._run_cmd('reg add \"HKLM/SOFTWARE/Policies/Microsoft/Windows NT/Printers/PointAndPrint\" /v RestrictDriverInstallationToAdministrators /t REG_DWORD /d 1 /f')\n        self._run_cmd('reg add \"HKLM/SOFTWARE/Policies/Microsoft/Windows NT/Printers/PointAndPrint\" /v NoWarningNoElevationOnInstall /t REG_DWORD /d 0 /f')\n        self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                      r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                      \"RpcAuthnLevelPrivacyEnabled\", 1, winreg.REG_DWORD)\n        self._printer_log(\"\u2705 PrintNightmare vulnerability patched!\", C[\"success\"])\n\n    def _printer_troubleshooter(self):\n        self._printer_log(\"\ud83d\udd0d Windows Printer Troubleshooter chal raha hai...\", C[\"accent4\"])\n        self._printer_action_submit(\"printer_troubleshooter\", self._do_printer_troubleshooter)\n\n    def _do_printer_troubleshooter(self):\n        self._run_cmd('msdt.exe /id PrinterDiagnostic')\n        self._printer_log(\"\u2139 Troubleshooter window open hua.\", C[\"text_dim\"])\n\n    def _printer_open_queue(self):\n        sel = self.printer_tree.selection()\n        if sel and self._printer_data:\n            idx = self.printer_tree.index(sel[0])\n            if idx &lt; len(self._printer_data):\n                name = self._printer_data[idx][2][\"name\"]\n                self._run_cmd(f'rundll32 printui.dll,PrintUIEntry /o /n \"{name}\"')\n                return\n        # Open printers &amp; scanners settings\n        self._run_cmd('control printers')\n\n    def _printer_set_default(self):\n        sel = self.printer_tree.selection()\n        if not sel or not self._printer_data:\n            messagebox.showinfo(\"Select Printer\",\"Pehle printer select karo.\")\n            return\n        idx = self.printer_tree.index(sel[0])\n        if idx &gt;= len(self._printer_data):\n            return\n        name = self._printer_data[idx][2][\"name\"]\n        self._printer_action_submit(\"printer_set_default\", self._do_printer_set_default, printer_name=name)\n\n    def _do_printer_set_default(self, printer_name):\n        out, rc = self._run_cmd(\n            f'powershell -Command \"Set-Printer -Name \\'{printer_name}\\' -IsDefault $true\"',\n            timeout=10)\n        if rc == 0:\n            self._printer_log(f\"\u2705 '{printer_name}' default printer set ho gaya!\", C[\"success\"])\n        else:\n            self._run_cmd(f'rundll32 printui.dll,PrintUIEntry /y /n \"{printer_name}\"')\n            self._printer_log(f\"\u2705 '{printer_name}' default set (legacy method)\", C[\"success\"])\n        self._printer_detect()\n\n    def _printer_remove(self):\n        sel = self.printer_tree.selection()\n        if not sel or not self._printer_data:\n            messagebox.showinfo(\"Select Printer\",\"Pehle printer select karo.\")\n            return\n        idx = self.printer_tree.index(sel[0])\n        if idx &gt;= len(self._printer_data):\n            return\n        name = self._printer_data[idx][2][\"name\"]\n        if not messagebox.askyesno(\"Remove Printer\",\n                f\"'{name}' printer remove ho jaayega.\\nAage badhein?\"):\n            return\n        self._printer_action_submit(\"printer_remove\", self._do_printer_remove, printer_name=name)\n\n    def _do_printer_remove(self, printer_name):\n        out, rc = self._run_cmd(\n            f'powershell -Command \"Remove-Printer -Name \\'{printer_name}\\'\"', timeout=10)\n        if rc == 0:\n            self._printer_log(f\"\u2705 '{printer_name}' removed!\", C[\"success\"])\n        else:\n            self._run_cmd(f'rundll32 printui.dll,PrintUIEntry /dl /n \"{printer_name}\"')\n            self._printer_log(f\"\u2705 '{printer_name}' removed (legacy method)\", C[\"success\"])\n        self._printer_detect()\n\n    def _printer_driver_signature_audit(self):\n        self._printer_action_submit(\"printer_driver_signature_audit\", self._do_printer_driver_signature_audit)\n\n    def _do_printer_driver_signature_audit(self):\n        self._printer_log(\"\ud83d\udd0d Collecting printer driver metadata...\", C[\"accent4\"])\n        output, rc = self._run_cmd(\n            'powershell -Command \"Get-PrinterDriver | Select-Object Name,Manufacturer,InfName,Version | ConvertTo-Csv -NoTypeInformation\"',\n            timeout=12)\n        if rc != 0 or not output:\n            self._printer_log(\"\u26a0 Driver audit failed or returned no data.\", C[\"warning\"])\n            return\n        lines = [line.strip() for line in output.splitlines() if line.strip()]\n        self._printer_log(f\"\u2705 {len(lines)-1} driver entries found\", C[\"success\"]) if len(lines) &gt; 1 else self._printer_log(\"\u26a0 No drivers discovered.\", C[\"warning\"])\n        for row in lines[:12]:\n            self._printer_trace(row, C[\"text_dim\"])\n        if len(lines) &gt; 12:\n            self._printer_trace(f\"... and {len(lines)-1-11} more driver records\", C[\"text_dim\"])\n\n    def _printer_spooler_snapshot(self):\n        self._printer_action_submit(\"printer_spooler_snapshot\", self._do_printer_spooler_snapshot)\n\n    def _do_printer_spooler_snapshot(self):\n        self._printer_log(\"\ud83d\udcf8 Capturing spooler and driver snapshot...\", C[\"accent4\"])\n        cfg, rc1 = self._run_cmd('sc qc spooler', timeout=10)\n        self._printer_trace(cfg or \"Unable to read spooler service config.\", C[\"text\"]) \n        driver_info, rc2 = self._run_cmd('pnputil /enum-drivers', timeout=20)\n        drivers = [line for line in (driver_info or \"\").splitlines() if line.strip()]\n        self._printer_log(f\"\u2705 Spooler snapshot captured \u2014 {len(drivers)} driver lines\", C[\"success\"])\n        for line in drivers[:8]:\n            self._printer_trace(line, C[\"text_dim\"])\n        if len(drivers) &gt; 8:\n            self._printer_trace(f\"... and {len(drivers)-8} more lines\", C[\"text_dim\"])\n\n    def _printer_network_setup(self):\n        dlg = tk.Toplevel(self)\n        dlg.title(\"Network Printer Setup\")\n        dlg.geometry(\"480x340\")\n        dlg.configure(bg=C[\"bg\"])\n        dlg.grab_set()\n\n        tk.Label(dlg, text=\"\ud83c\udf10 Network / Shared Printer Setup\",\n                 font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"bg\"]).pack(pady=(16,4))\n\n        info = tk.Frame(dlg, bg=C[\"card\"])\n        info.pack(fill=\"x\", padx=20, pady=6)\n\n        fields = {}\n        for lbl, key, placeholder in [\n            (\"Printer IP / Hostname:\", \"ip\",   \"e.g. 192.168.1.100\"),\n            (\"Share Name (optional):\", \"share\",\"e.g. HP_LaserJet\"),\n            (\"Port Name:\",             \"port\", \"e.g. IP_192.168.1.100\"),\n        ]:\n            row = tk.Frame(info, bg=C[\"card\"])\n            row.pack(fill=\"x\", pady=4)\n            tk.Label(row, text=lbl, font=FONTS[\"body\"], fg=C[\"text\"],\n                     bg=C[\"card\"], width=22, anchor=\"w\").pack(side=\"left\")\n            e = tk.Entry(row, font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"],\n                         insertbackground=C[\"text\"], relief=\"flat\", bd=4, width=24)\n            e.insert(0, placeholder)\n            e.bind(\"\",  lambda ev,p=placeholder,en=e: en.delete(0,\"end\") if en.get()==p else None)\n            e.bind(\"\", lambda ev,p=placeholder,en=e: en.insert(0,p) if not en.get() else None)\n            e.pack(side=\"left\", padx=4)\n            fields[key] = e\n\n        log = scrolledtext.ScrolledText(dlg, height=6, font=FONTS[\"mono\"],\n                                         bg=C[\"bg\"], fg=C[\"text\"], bd=0, state=\"disabled\")\n        log.pack(fill=\"both\", expand=True, padx=20, pady=4)\n\n        def _do_add():\n            ip    = fields[\"ip\"].get().strip()\n            share = fields[\"share\"].get().strip()\n            port  = fields[\"port\"].get().strip() or f\"IP_{ip}\"\n            if not ip or ip.startswith(\"e.g\"):\n                messagebox.showwarning(\"IP Missing\",\"Printer IP enter karo.\", parent=dlg)\n                return\n\n            def _run():\n                def _log(msg, col=C[\"text\"]):\n                    log.config(state=\"normal\")\n                    log.insert(\"end\", msg+\"\\n\")\n                    log.see(\"end\")\n                    log.config(state=\"disabled\")\n\n                _log(f\"Connecting to {ip}...\")\n                # Add TCP/IP port\n                self._run_cmd(\n                    f'powershell -Command \"Add-PrinterPort -Name \\'{port}\\' -PrinterHostAddress \\'{ip}\\'\"',\n                    timeout=10)\n                _log(f\"\u2705 Port {port} added\")\n                # Add printer\n                if share:\n                    cmd = (f'powershell -Command \"Add-Printer -Name \\'Network_{ip}\\' '\n                           f'-DriverName \\'Microsoft Print To PDF\\' -PortName \\'{port}\\'\"')\n                else:\n                    cmd = (f'net use LPT1: \\\\\\\\{ip}\\\\{share} /persistent:yes')\n                out, rc = self._run_cmd(cmd, timeout=15)\n                if rc == 0:\n                    _log(f\"\u2705 Printer added! IP: {ip}\")\n                else:\n                    _log(f\"\u26a0 Auto-add failed. Manually karo:\\n  Control Panel \u2192 Devices \u2192 Add Printer \u2192 Manual \u2192 TCP/IP \u2192 {ip}\")\n                _log(\"Done!\")\n                self.after(0, self._printer_detect)\n\n            self._launch_job(\"printer_add\", _run)\n\n        btn_frame = tk.Frame(dlg, bg=C[\"bg\"])\n        btn_frame.pack(pady=8)\n        self._btn(btn_frame, \"\ud83c\udf10 Add Network Printer\", C[\"btn_info\"], _do_add).pack(side=\"left\", padx=6)\n        self._btn(btn_frame, \"\ud83d\udd0d Ping Printer IP\",     C[\"btn_chip\"],\n                  lambda ip=fields[\"ip\"].get(): self._launch_job(\"printer_ping\", lambda: self._append_log(log, self._run_cmd(f'ping -n 2 {ip}')[0], C[\"text\"])) ).pack(side=\"left\", padx=6)\n        self._btn(btn_frame, \"Close\", C[\"btn_warn\"], dlg.destroy).pack(side=\"left\", padx=6)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \ud83d\udd17 PRINTER SHARING CENTER \u2014 HELPER &amp; STATUS\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _get_hostname(self):\n        try:\n            return platform.node()\n        except:\n            return \"YourHostPC\"\n\n    def _sharing_log(self, msg, col=None):\n        \"\"\"Safe append to sharing_log widget.\"\"\"\n        if col is None:\n            col = C[\"text\"]\n        try:\n            self._append_log(self.sharing_log, msg, col)\n        except Exception:\n            pass\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # INDIVIDUAL PORT OPENERS \u2014 HOST\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _open_single_port_host(self, port, proto_str, name):\n        \"\"\"Open a single port on HOST firewall (IN + OUT).\"\"\"\n        self._sharing_log(f\"\ud83d\udd0c [HOST] Port {port}/{proto_str} ({name}) khol raha hoon...\", C[\"accent4\"])\n        def _r():\n            protos = [\"TCP\",\"UDP\"] if proto_str == \"TCP+UDP\" else [proto_str]\n            for proto in protos:\n                for dirn in [\"in\",\"out\"]:\n                    rule = f\"GodawariHost_{name}_{dirn.upper()}\"\n                    cmd = (f'netsh advfirewall firewall add rule '\n                           f'name=\"{rule}\" dir={dirn} action=allow '\n                           f'protocol={proto} localport={port} profile=any')\n                    _, rc = self._run_cmd(cmd)\n                    self._sharing_log(\n                        f\"  {'\u2705' if rc==0 else '\u26a0'} {port}/{proto} {dirn.upper()} \u2192 {'OK' if rc==0 else 'Already exists / Error'}\",\n                        C[\"success\"] if rc==0 else C[\"warning\"])\n            self._sharing_log(f\"\u2705 Port {port}/{proto_str} ({name}) \u2192 Done!\", C[\"success\"])\n        self._launch_job(f\"open_port_host_{port}_{name}\", _r)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # INDIVIDUAL PORT OPENERS \u2014 CLIENT\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _open_single_port_client(self, port, proto_str, name):\n        \"\"\"Open a single port on CLIENT firewall (IN + OUT).\"\"\"\n        self._sharing_log(f\"\ud83d\udd0c [CLIENT] Port {port}/{proto_str} ({name}) khol raha hoon...\", C[\"accent2\"])\n        def _r():\n            protos = [\"TCP\",\"UDP\"] if proto_str == \"TCP+UDP\" else [proto_str]\n            for proto in protos:\n                for dirn in [\"in\",\"out\"]:\n                    rule = f\"GodawariClient_{name}_{dirn.upper()}\"\n                    cmd = (f'netsh advfirewall firewall add rule '\n                           f'name=\"{rule}\" dir={dirn} action=allow '\n                           f'protocol={proto} localport={port} profile=any')\n                    _, rc = self._run_cmd(cmd)\n                    self._sharing_log(\n                        f\"  {'\u2705' if rc==0 else '\u26a0'} {port}/{proto} {dirn.upper()} \u2192 {'OK' if rc==0 else 'Already exists / Error'}\",\n                        C[\"success\"] if rc==0 else C[\"warning\"])\n            self._sharing_log(f\"\u2705 Port {port}/{proto_str} ({name}) \u2192 Done!\", C[\"success\"])\n        self._launch_job(f\"open_port_client_{port}_{name}\", _r)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # INDIVIDUAL SECURITY ACTIONS \u2014 HOST\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _host_single_security(self, key):\n        \"\"\"Apply one specific HOST security setting.\"\"\"\n        self._sharing_log(f\"\ud83d\udd12 [HOST] Security setting apply kar raha hoon: {key}\", C[\"accent4\"])\n        def _r():\n            if key == \"network_discovery\":\n                self._run_cmd('netsh advfirewall firewall set rule group=\"Network Discovery\" new enable=Yes profile=private')\n                self._sharing_log(\"  \u2705 Network Discovery \u2192 ON (Private profile)\", C[\"success\"])\n            elif key == \"fp_sharing_rules\":\n                self._run_cmd('netsh advfirewall firewall set rule group=\"File and Printer Sharing\" new enable=Yes profile=any')\n                self._sharing_log(\"  \u2705 File &amp; Printer Sharing Rules \u2192 ON (All profiles)\", C[\"success\"])\n            elif key == \"network_private\":\n                self._run_cmd('powershell -Command \"Set-NetConnectionProfile -NetworkCategory Private\"')\n                self._sharing_log(\"  \u2705 Network Profile \u2192 Private\", C[\"success\"])\n            elif key == \"pwd_sharing_off\":\n                self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Lsa\" /v LimitBlankPasswordUse /t REG_DWORD /d 0 /f')\n                self._sharing_log(\"  \u2705 Password Protected Sharing \u2192 OFF (LimitBlankPasswordUse=0)\", C[\"success\"])\n            elif key == \"smb_sign_optional\":\n                self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanServer\\\\Parameters\" /v RequireSecuritySignature /t REG_DWORD /d 0 /f')\n                self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanServer\\\\Parameters\" /v EnableSecuritySignature /t REG_DWORD /d 1 /f')\n                self._sharing_log(\"  \u2705 SMB Server Signing \u2192 Optional (RequireSecuritySignature=0, Enable=1)\", C[\"success\"])\n            elif key == \"fw_private_off\":\n                self._run_cmd('netsh advfirewall set privateprofile state off')\n                self._sharing_log(\"  \u2705 Windows Defender Firewall \u2192 Private profile OFF\", C[\"success\"])\n                self._sharing_log(\"  \u26a0 Sirf trusted/local LAN pe karo!\", C[\"warning\"])\n            elif key == \"allow_ping\":\n                self._run_cmd('netsh advfirewall firewall add rule name=\"GodawariAllowPing_IN\" protocol=ICMPv4 dir=in action=allow')\n                self._run_cmd('netsh advfirewall firewall add rule name=\"GodawariAllowPing_OUT\" protocol=ICMPv4 dir=out action=allow')\n                self._sharing_log(\"  \u2705 ICMPv4 Ping \u2192 Allowed (IN + OUT)\", C[\"success\"])\n            self._sharing_log(f\"\u2705 [HOST] {key} \u2192 Complete!\", C[\"success\"])\n        self._launch_job(f\"host_security_{key}\", _r)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # INDIVIDUAL SECURITY ACTIONS \u2014 CLIENT\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _client_single_security(self, key):\n        \"\"\"Apply one specific CLIENT security setting.\"\"\"\n        self._sharing_log(f\"\ud83d\udd12 [CLIENT] Security setting: {key}\", C[\"accent2\"])\n        def _r():\n            if key == \"network_discovery\":\n                self._run_cmd('netsh advfirewall firewall set rule group=\"Network Discovery\" new enable=Yes profile=private')\n                self._sharing_log(\"  \u2705 Network Discovery \u2192 ON (Private profile)\", C[\"success\"])\n            elif key == \"fp_sharing_rules\":\n                self._run_cmd('netsh advfirewall firewall set rule group=\"File and Printer Sharing\" new enable=Yes profile=any')\n                self._sharing_log(\"  \u2705 File &amp; Printer Sharing Rules \u2192 ON (All profiles)\", C[\"success\"])\n            elif key == \"network_private\":\n                self._run_cmd('powershell -Command \"Set-NetConnectionProfile -NetworkCategory Private\"')\n                self._sharing_log(\"  \u2705 Network Profile \u2192 Private\", C[\"success\"])\n            elif key == \"smb_sign_optional\":\n                self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanWorkstation\\\\Parameters\" /v RequireSecuritySignature /t REG_DWORD /d 0 /f')\n                self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanWorkstation\\\\Parameters\" /v EnableSecuritySignature /t REG_DWORD /d 1 /f')\n                self._sharing_log(\"  \u2705 SMB Client Signing \u2192 Optional (RequireSecuritySignature=0)\", C[\"success\"])\n            elif key == \"point_print\":\n                self._run_cmd('reg add \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Printers\\\\PointAndPrint\" /v NoWarningNoElevationOnInstall /t REG_DWORD /d 1 /f')\n                self._run_cmd('reg add \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Printers\\\\PointAndPrint\" /v UpdatePromptSettings /t REG_DWORD /d 2 /f')\n                self._sharing_log(\"  \u2705 Point &amp; Print \u2192 No Warning, No Elevation on Install\", C[\"success\"])\n            elif key == \"fw_private_off\":\n                self._run_cmd('netsh advfirewall set privateprofile state off')\n                self._sharing_log(\"  \u2705 Windows Defender Firewall \u2192 Private profile OFF (Client)\", C[\"success\"])\n                self._sharing_log(\"  \u26a0 Sirf trusted/local LAN pe karo!\", C[\"warning\"])\n            elif key == \"allow_ping\":\n                self._run_cmd('netsh advfirewall firewall add rule name=\"GodawariClientPing_IN\" protocol=ICMPv4 dir=in action=allow')\n                self._run_cmd('netsh advfirewall firewall add rule name=\"GodawariClientPing_OUT\" protocol=ICMPv4 dir=out action=allow')\n                self._sharing_log(\"  \u2705 ICMPv4 Ping \u2192 Allowed on Client (IN + OUT)\", C[\"success\"])\n            self._sharing_log(f\"\u2705 [CLIENT] {key} \u2192 Complete!\", C[\"success\"])\n        self._launch_job(f\"client_single_reg_{key}\", _r)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # INDIVIDUAL REGISTRY CHANGES \u2014 HOST\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _host_single_reg(self, key):\n        \"\"\"Apply one specific HOST registry change.\"\"\"\n        self._sharing_log(f\"\ud83d\udddd [HOST] Registry: {key}\", C[\"accent4\"])\n        def _r():\n            try:\n                if key == \"AutoShareServer\":\n                    self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                        r\"SYSTEM\\CurrentControlSet\\Services\\LanmanServer\\Parameters\",\n                        \"AutoShareServer\", 1, winreg.REG_DWORD)\n                    self._sharing_log(\"  \u2705 AutoShareServer = 1  (Admin C$,D$ shares ON)\", C[\"success\"])\n                elif key == \"AutoShareWks\":\n                    self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                        r\"SYSTEM\\CurrentControlSet\\Services\\LanmanServer\\Parameters\",\n                        \"AutoShareWks\", 1, winreg.REG_DWORD)\n                    self._sharing_log(\"  \u2705 AutoShareWks = 1  (Workstation shares ON)\", C[\"success\"])\n                elif key == \"IRPStackSize\":\n                    self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                        r\"SYSTEM\\CurrentControlSet\\Services\\LanmanServer\\Parameters\",\n                        \"IRPStackSize\", 20, winreg.REG_DWORD)\n                    self._sharing_log(\"  \u2705 IRPStackSize = 20  (Large network packets fix)\", C[\"success\"])\n                elif key == \"LimitBlankPasswordUse\":\n                    self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                        r\"SYSTEM\\CurrentControlSet\\Control\\Lsa\",\n                        \"LimitBlankPasswordUse\", 0, winreg.REG_DWORD)\n                    self._sharing_log(\"  \u2705 LimitBlankPasswordUse = 0  (Blank password allowed)\", C[\"success\"])\n                elif key == \"DisableWebPrinting\":\n                    self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                        r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                        \"DisableWebPrinting\", 0, winreg.REG_DWORD)\n                    self._sharing_log(\"  \u2705 DisableWebPrinting = 0  (Web printing enabled)\", C[\"success\"])\n                elif key == \"EnableSMB1\":\n                    if messagebox.askyesno(\"SMB1 Enable\",\n                            \"SMB1 enable karna chahte hain?\\n\\n\"\n                            \"\u26a0 Security risk \u2014 sirf XP/Win7 clients ke liye!\\nContinue?\"):\n                        self._run_cmd('powershell -Command \"Set-SmbServerConfiguration -EnableSMB1Protocol $true -Force\"')\n                        self._sharing_log(\"  \u2705 SMB1 Protocol \u2192 Enabled\", C[\"warning\"])\n                self._sharing_log(f\"\u2705 [HOST] {key} \u2192 Done!\", C[\"success\"])\n            except Exception as ex:\n                self._sharing_log(f\"  \u274c {key}: {ex}\", C[\"error\"])\n        self._launch_job(f\"host_single_reg_{key}\", _r)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # INDIVIDUAL REGISTRY CHANGES \u2014 CLIENT\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _client_single_reg(self, key):\n        \"\"\"Apply one specific CLIENT registry change.\"\"\"\n        self._sharing_log(f\"\ud83d\udddd [CLIENT] Registry: {key}\", C[\"accent2\"])\n        def _r():\n            try:\n                if key == \"AllowInsecureGuestAuth\":\n                    self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                        r\"SYSTEM\\CurrentControlSet\\Services\\LanmanWorkstation\\Parameters\",\n                        \"AllowInsecureGuestAuth\", 1, winreg.REG_DWORD)\n                    self._sharing_log(\"  \u2705 AllowInsecureGuestAuth = 1  (Guest share access)\", C[\"success\"])\n                elif key == \"LimitBlankPasswordUse\":\n                    self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                        r\"SYSTEM\\CurrentControlSet\\Control\\Lsa\",\n                        \"LimitBlankPasswordUse\", 0, winreg.REG_DWORD)\n                    self._sharing_log(\"  \u2705 LimitBlankPasswordUse = 0  (Blank password connect)\", C[\"success\"])\n                elif key == \"RequireSecuritySignature\":\n                    self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                        r\"SYSTEM\\CurrentControlSet\\Services\\LanmanWorkstation\\Parameters\",\n                        \"RequireSecuritySignature\", 0, winreg.REG_DWORD)\n                    self._sharing_log(\"  \u2705 RequireSecuritySignature = 0  (SMB signing optional)\", C[\"success\"])\n                elif key == \"PnP_NoWarning\":\n                    self._run_cmd('reg add \"HKLM/SOFTWARE/Policies/Microsoft/Windows NT/Printers/PointAndPrint\" /v NoWarningNoElevationOnInstall /t REG_DWORD /d 1 /f')\n                    self._sharing_log(\"  \u2705 PnP NoWarningNoElevationOnInstall = 1\", C[\"success\"])\n                elif key == \"PnP_UpdatePrompt\":\n                    self._run_cmd('reg add \"HKLM/SOFTWARE/Policies/Microsoft/Windows NT/Printers/PointAndPrint\" /v UpdatePromptSettings /t REG_DWORD /d 2 /f')\n                    self._sharing_log(\"  \u2705 PnP UpdatePromptSettings = 2\", C[\"success\"])\n                elif key == \"PnP_RestrictDriver\":\n                    self._run_cmd('reg add \"HKLM/SOFTWARE/Policies/Microsoft/Windows NT/Printers/PointAndPrint\" /v RestrictDriverInstallationToAdministrators /t REG_DWORD /d 0 /f')\n                    self._sharing_log(\"  \u2705 PnP RestrictDriverInstallationToAdministrators = 0\", C[\"success\"])\n                self._sharing_log(f\"\u2705 [CLIENT] {key} \u2192 Done!\", C[\"success\"])\n            except Exception as ex:\n                self._sharing_log(f\"  \u274c {key}: {ex}\", C[\"error\"])\n        self._launch_job(\"apply_sharing_client_changes\", _r)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # INDIVIDUAL SERVICE STARTER \u2014 HOST/CLIENT SHARED\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _host_single_svc(self, svc_name):\n        \"\"\"Start and set a single service to Auto.\"\"\"\n        svc_display = {\n            \"Spooler\": \"Print Spooler\",\n            \"LanmanServer\": \"Server (File &amp; Printer Sharing)\",\n            \"LanmanWorkstation\": \"Workstation (Network Redirector)\",\n            \"lmhosts\": \"TCP/IP NetBIOS Helper\",\n            \"fdPHost\": \"Function Discovery Provider Host\",\n            \"FDResPub\": \"Function Discovery Resource Publication\",\n            \"SSDPSRV\": \"SSDP Discovery\",\n        }.get(svc_name, svc_name)\n        self._sharing_log(f\"\u2699\ufe0f Service: {svc_display} \u2192 Auto + Start\", C[\"accent4\"])\n        def _r():\n            _, r1 = self._run_cmd(f'sc config \"{svc_name}\" start= auto')\n            _, r2 = self._run_cmd(f'sc start \"{svc_name}\"')\n            ok = r1 == 0 or r2 == 0\n            self._sharing_log(\n                f\"  {'\u2705' if ok else '\u26a0'} {svc_display} \u2192 {'Auto+Started' if ok else 'Check manually'}\",\n                C[\"success\"] if ok else C[\"warning\"])\n        threading.Thread(target=_r, daemon=True).start()\n\n    def _check_sharing_status(self):\n        \"\"\"Quick check: Network Discovery, File Sharing, Spooler, Workgroup.\"\"\"\n        self._sharing_log(\"\u2550\"*56, C[\"border\"])\n        self._sharing_log(\"\ud83d\udd0e Sharing Status Check chal raha hai...\", C[\"accent4\"])\n        self._launch_job(\"check_sharing_status\", self._do_check_sharing_status)\n\n    def _do_check_sharing_status(self):\n        # Spooler\n        out, _ = self._run_cmd('sc query spooler')\n        running = \"running\" in out.lower()\n        self._sharing_log(f\"  {'\u2705' if running else '\u274c'} Print Spooler: {'Running' if running else 'Stopped'}\",\n                          C[\"success\"] if running else C[\"error\"])\n\n        # Server / LanmanServer\n        out2, _ = self._run_cmd('sc query lanmanserver')\n        srv = \"running\" in out2.lower()\n        self._sharing_log(f\"  {'\u2705' if srv else '\u274c'} LanmanServer (File Sharing): {'Running' if srv else 'Stopped'}\",\n                          C[\"success\"] if srv else C[\"error\"])\n\n        # Workgroup\n        out3, _ = self._run_cmd('wmic computersystem get Workgroup /value')\n        wg = out3.strip().replace(\"Workgroup=\",\"\").strip()\n        self._sharing_log(f\"  \u2139 Workgroup: {wg if wg else 'Unknown'}\", C[\"text_dim\"])\n\n        # Computer Name + IP\n        out4, _ = self._run_cmd('ipconfig')\n        for line in out4.splitlines():\n            if \"IPv4\" in line and \"169.\" not in line:\n                self._sharing_log(f\"  \u2139 {line.strip()}\", C[\"text_dim\"])\n                break\n\n        # Firewall File &amp; Printer Sharing state\n        out5, _ = self._run_cmd('netsh advfirewall firewall show rule name=\"File and Printer Sharing (SMB-In)\"')\n        enabled_fw = \"enabled\" in out5.lower()\n        self._sharing_log(\n            f\"  {'\u2705' if enabled_fw else '\u26a0'} Firewall F&amp;P Rule: {'Enabled' if enabled_fw else 'Disabled/Missing'}\",\n            C[\"success\"] if enabled_fw else C[\"warning\"])\n\n        # Printer sharing via PowerShell\n        out6, _ = self._run_cmd(\n            'powershell -Command \"Get-Printer | Select-Object Name,Shared,ShareName | ConvertTo-Csv -NoTypeInformation\"',\n            timeout=10)\n        any_shared = False\n        for line in out6.splitlines()[1:]:\n            parts = line.strip().replace('\"','').split(',')\n            if len(parts) &gt;= 2 and parts[1].strip().lower() == \"true\":\n                any_shared = True\n                self._sharing_log(\n                    f\"  \u2705 Shared Printer: {parts[0].strip()}  \u2192  ShareName: {parts[2].strip() if len(parts)&gt;2 else '\u2014'}\",\n                    C[\"success\"])\n        if not any_shared:\n            self._sharing_log(\"  \u26a0 Koi printer shared nahi hai! Host pe Auto-Share button chalao.\", C[\"warning\"])\n\n        self._sharing_log(\"\u2705 Status check complete!\", C[\"success\"])\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \ud83d\udda5 HOST COMPUTER \u2014 PRINTER SHARING METHODS\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _host_open_ports(self):\n        if not messagebox.askyesno(\"Host: Port Fix\",\n                \"HOST computer pe ye ports open honge:\\n\\n\"\n                \"\u2022 445 TCP/UDP  \u2014 SMB File &amp; Printer Sharing\\n\"\n                \"\u2022 139 TCP      \u2014 NetBIOS Session Service\\n\"\n                \"\u2022 137 UDP      \u2014 NetBIOS Name Service\\n\"\n                \"\u2022 138 UDP      \u2014 NetBIOS Datagram Service\\n\"\n                \"\u2022 135 TCP      \u2014 RPC Endpoint Mapper\\n\"\n                \"\u2022 9100 TCP     \u2014 RAW Print Port\\n\"\n                \"\u2022 631  TCP     \u2014 IPP Print\\n\\n\"\n                \"\u26a0 Sirf private/trusted network pe karo!\\nContinue karein?\"):\n            return\n        self._sharing_log(\"\u2550\"*56, C[\"border\"])\n        self._sharing_log(\"\ud83d\udd0c [HOST] Printer ports khol raha hoon...\", C[\"accent4\"])\n        self._launch_job(\"host_open_ports\", self._do_host_open_ports)\n\n    def _do_host_open_ports(self):\n        ports = [\n            (445,  \"TCP\", \"SMB-Print-TCP\"),\n            (445,  \"UDP\", \"SMB-Print-UDP\"),\n            (139,  \"TCP\", \"NetBIOS-Session\"),\n            (137,  \"UDP\", \"NetBIOS-Name\"),\n            (138,  \"UDP\", \"NetBIOS-Datagram\"),\n            (135,  \"TCP\", \"RPC-Endpoint\"),\n            (9100, \"TCP\", \"RAW-Print\"),\n            (631,  \"TCP\", \"IPP-Print\"),\n        ]\n        for port, proto, name in ports:\n            cmd_in = (f'netsh advfirewall firewall add rule '\n                      f'name=\"GodawariShare_{name}_IN\" '\n                      f'dir=in action=allow protocol={proto} '\n                      f'localport={port} profile=any')\n            _, rc = self._run_cmd(cmd_in)\n            cmd_out = (f'netsh advfirewall firewall add rule '\n                       f'name=\"GodawariShare_{name}_OUT\" '\n                       f'dir=out action=allow protocol={proto} '\n                       f'localport={port} profile=any')\n            self._run_cmd(cmd_out)\n            sym = \"\u2705\" if rc == 0 else \"\u26a0\"\n            self._sharing_log(\n                f\"  {sym} Port {port}/{proto} ({name}) \u2192 IN+OUT opened\",\n                C[\"success\"] if rc == 0 else C[\"warning\"])\n\n        # Enable predefined Windows rule group\n        self._run_cmd(\n            'netsh advfirewall firewall set rule '\n            'group=\"File and Printer Sharing\" new enable=Yes profile=any')\n        self._sharing_log(\"  \u2705 Windows 'File and Printer Sharing' rule group \u2192 ON\", C[\"success\"])\n        self._sharing_log(\"\u2705 [HOST] All printer sharing ports opened!\", C[\"success\"])\n\n    def _host_security_fix(self):\n        if not messagebox.askyesno(\"Host: Security &amp; Firewall Fix\",\n                \"HOST security changes honge:\\n\\n\"\n                \"\u2022 Network Discovery \u2192 Enable (Private profile)\\n\"\n                \"\u2022 File &amp; Printer Sharing firewall rules \u2192 ON\\n\"\n                \"\u2022 Network profile \u2192 Private\\n\"\n                \"\u2022 SMB security signature \u2192 Optional\\n\"\n                \"\u2022 Password Protected Sharing \u2192 aapki choice\\n\\n\"\n                \"Continue karein?\"):\n            return\n        pwd_off = messagebox.askyesno(\"Password Protected Sharing\",\n            \"Password Protected Sharing BAND karna chahte hain?\\n\\n\"\n            \"\u2705 YES = Band karo (Client bina password connect kar sake)\\n\"\n            \"\u274c NO  = On rehne do (Zyada secure)\")\n        self._sharing_log(\"\u2550\"*56, C[\"border\"])\n        self._sharing_log(\"\ud83d\udd12 [HOST] Security &amp; Firewall fix chal raha hai...\", C[\"accent4\"])\n        self._launch_job(\"host_security_fix\", lambda: self._do_host_security_fix(pwd_off))\n\n    def _do_host_security_fix(self, disable_pwd_sharing):\n        # Network Discovery \u2014 private\n        self._run_cmd('netsh advfirewall firewall set rule group=\"Network Discovery\" new enable=Yes profile=private')\n        self._sharing_log(\"  \u2705 Network Discovery \u2192 ON (Private)\", C[\"success\"])\n\n        # File &amp; Printer Sharing \u2014 all profiles\n        self._run_cmd('netsh advfirewall firewall set rule group=\"File and Printer Sharing\" new enable=Yes profile=any')\n        self._sharing_log(\"  \u2705 File &amp; Printer Sharing rules \u2192 ON (All profiles)\", C[\"success\"])\n\n        # Network profile \u2192 Private\n        self._run_cmd('powershell -Command \"Set-NetConnectionProfile -NetworkCategory Private\"')\n        self._sharing_log(\"  \u2705 Network profile \u2192 Private\", C[\"success\"])\n\n        # Password protected sharing\n        val = 0 if disable_pwd_sharing else 1\n        self._run_cmd(\n            f'reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Lsa\" '\n            f'/v LimitBlankPasswordUse /t REG_DWORD /d {val} /f')\n        self._sharing_log(\n            f\"  \u2705 Password Protected Sharing \u2192 {'OFF' if disable_pwd_sharing else 'ON (unchanged)'}\",\n            C[\"success\"])\n\n        # SMB server signature \u2014 optional (not required)\n        self._run_cmd(\n            'reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanServer\\\\Parameters\" '\n            '/v RequireSecuritySignature /t REG_DWORD /d 0 /f')\n        self._run_cmd(\n            'reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanServer\\\\Parameters\" '\n            '/v EnableSecuritySignature /t REG_DWORD /d 1 /f')\n        self._sharing_log(\"  \u2705 SMB signature \u2192 Optional (not required)\", C[\"success\"])\n\n        self._sharing_log(\"\u2705 [HOST] Security fix complete!\", C[\"success\"])\n\n    def _host_registry_fix(self):\n        if not messagebox.askyesno(\"Host: Registry Changes\",\n                \"HOST ke liye ye registry changes honge:\\n\\n\"\n                \"\u2022 AutoShareServer = 1 (admin shares enable)\\n\"\n                \"\u2022 AutoShareWks   = 1 (workstation shares)\\n\"\n                \"\u2022 IRPStackSize   = 20 (large network packets)\\n\"\n                \"\u2022 LimitBlankPasswordUse = 0\\n\"\n                \"\u2022 DisableWebPrinting    = 0\\n\"\n                \"\u2022 SMB1 status check (aapki marzi)\\n\\n\"\n                \"\u26a0 Registry badlega \u2014 seedha asar padega!\\nContinue karein?\"):\n            return\n        self._sharing_log(\"\u2550\"*56, C[\"border\"])\n        self._sharing_log(\"\ud83d\udddd [HOST] Registry changes apply kar raha hoon...\", C[\"accent4\"])\n        self._launch_job(\"host_registry_fix\", self._do_host_registry_fix)\n\n    def _do_host_registry_fix(self):\n        changes = [\n            (winreg.HKEY_LOCAL_MACHINE,\n             r\"SYSTEM\\CurrentControlSet\\Services\\LanmanServer\\Parameters\",\n             \"AutoShareServer\", 1, winreg.REG_DWORD),\n            (winreg.HKEY_LOCAL_MACHINE,\n             r\"SYSTEM\\CurrentControlSet\\Services\\LanmanServer\\Parameters\",\n             \"AutoShareWks\", 1, winreg.REG_DWORD),\n            (winreg.HKEY_LOCAL_MACHINE,\n             r\"SYSTEM\\CurrentControlSet\\Services\\LanmanServer\\Parameters\",\n             \"IRPStackSize\", 20, winreg.REG_DWORD),\n            (winreg.HKEY_LOCAL_MACHINE,\n             r\"SYSTEM\\CurrentControlSet\\Control\\Lsa\",\n             \"LimitBlankPasswordUse\", 0, winreg.REG_DWORD),\n            (winreg.HKEY_LOCAL_MACHINE,\n             r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n             \"DisableWebPrinting\", 0, winreg.REG_DWORD),\n        ]\n        for hive, path, name, val, typ in changes:\n            try:\n                self._reg_set(hive, path, name, val, typ)\n                self._sharing_log(f\"  \u2705 {name} = {val}\", C[\"success\"])\n            except Exception as e:\n                self._sharing_log(f\"  \u26a0 {name}: {e}\", C[\"warning\"])\n\n        # SMB1 check\n        out, _ = self._run_cmd(\n            'powershell -Command \"(Get-SmbServerConfiguration).EnableSMB1Protocol\"',\n            timeout=10)\n        smb1_on = out.strip().lower() == \"true\"\n        self._sharing_log(\n            f\"  \u2139 SMB1 currently: {'Enabled' if smb1_on else 'Disabled'}\",\n            C[\"text_dim\"])\n        if not smb1_on:\n            def ask_smb1():\n                if messagebox.askyesno(\"SMB1 Protocol\",\n                        \"SMB1 abhi BAND hai.\\n\\n\"\n                        \"Purane clients (Windows XP/7) ke liye SMB1 chahiye.\\n\"\n                        \"Enable karein?\\n\\n\"\n                        \"\u26a0 Security risk \u2014 sirf trusted/local network pe karo!\"):\n                    self._run_cmd(\n                        'powershell -Command \"Set-SmbServerConfiguration -EnableSMB1Protocol $true -Force\"')\n                    self._sharing_log(\"  \u2705 SMB1 \u2192 Enabled\", C[\"success\"])\n                else:\n                    self._sharing_log(\"  \u2139 SMB1 \u2192 Unchanged (Disabled)\", C[\"text_dim\"])\n            self.after(0, ask_smb1)\n\n        self._sharing_log(\"\u2705 [HOST] Registry changes complete!\", C[\"success\"])\n        self._sharing_log(\"   \u26a0 Restart karna recommended hai.\", C[\"warning\"])\n\n    def _host_enable_services(self):\n        if not messagebox.askyesno(\"Host: Enable Sharing Services\",\n                \"Ye services start + Auto hogi HOST pe:\\n\\n\"\n                \"\u2022 Spooler          \u2014 Print queue manager\\n\"\n                \"\u2022 LanmanServer     \u2014 Network shares provide karta hai\\n\"\n                \"\u2022 LanmanWorkstation \u2014 SMB client\\n\"\n                \"\u2022 lmhosts          \u2014 TCP/IP NetBIOS Helper\\n\"\n                \"\u2022 fdPHost          \u2014 Function Discovery Host\\n\"\n                \"\u2022 FDResPub         \u2014 Network resource publishing\\n\"\n                \"\u2022 SSDPSRV          \u2014 SSDP Discovery\\n\"\n                \"\u2022 upnphost         \u2014 UPnP\\n\"\n                \"\u2022 Dnscache         \u2014 DNS Client\\n\\n\"\n                \"Continue karein?\"):\n            return\n        self._sharing_log(\"\u2550\"*56, C[\"border\"])\n        self._sharing_log(\"\ud83c\udfe0 [HOST] Sharing services enable kar raha hoon...\", C[\"accent4\"])\n        self._launch_job(\"host_enable_services\", self._do_host_enable_services)\n\n    def _do_host_enable_services(self):\n        services = [\n            (\"Spooler\",            \"Print Spooler\"),\n            (\"LanmanServer\",       \"Server (File Sharing)\"),\n            (\"LanmanWorkstation\",  \"Workstation\"),\n            (\"lmhosts\",            \"TCP/IP NetBIOS Helper\"),\n            (\"fdPHost\",            \"Function Discovery Host\"),\n            (\"FDResPub\",           \"Function Discovery Resource Publication\"),\n            (\"SSDPSRV\",            \"SSDP Discovery\"),\n            (\"upnphost\",           \"UPnP Device Host\"),\n            (\"Dnscache\",           \"DNS Client\"),\n        ]\n        for svc, display in services:\n            self._run_cmd(f'sc config {svc} start= auto')\n            out, rc = self._run_cmd(f'net start {svc}')\n            ok = rc == 0 or \"already\" in out.lower() or \"started\" in out.lower()\n            self._sharing_log(\n                f\"  {'\u2705' if ok else '\u26a0'} {display} ({svc}) \u2192 Auto + Started\",\n                C[\"success\"] if ok else C[\"warning\"])\n        self._sharing_log(\"\u2705 [HOST] All sharing services enabled!\", C[\"success\"])\n\n    def _host_auto_share(self):\n        \"\"\"Auto-share selected printer from HOST + open Windows confirmation.\"\"\"\n        sel = self.printer_tree.selection()\n        if not sel or not self._printer_data:\n            messagebox.showinfo(\"Printer Select Karo\",\n                \"Pehle printer list mein se printer click karke select karo,\\n\"\n                \"phir 'Auto-Share' button dabao.\")\n            return\n        idx = self.printer_tree.index(sel[0])\n        if idx &gt;= len(self._printer_data):\n            return\n        printer_name = self._printer_data[idx][2][\"name\"]\n        share_name   = printer_name.replace(\" \", \"_\")[:20]\n\n        if not messagebox.askyesno(\"Host: Auto-Share Printer\",\n                f\"Printer:    {printer_name}\\n\"\n                f\"Share Name: {share_name}\\n\\n\"\n                \"Ye automatically share ho jaayega.\\n\"\n                \"Firewall rules bhi enable honge.\\n\"\n                \"Sharing hone ke baad Windows confirmation window\\n\"\n                \"aur Printer Properties khud khul jaayengi.\\n\\n\"\n                \"Continue karein?\"):\n            return\n        self._sharing_log(\"\u2550\"*56, C[\"border\"])\n        self._sharing_log(\n            f\"\ud83d\udce4 [HOST] '{printer_name}' ko share kar raha hoon \u2192 ShareName: '{share_name}'\",\n            C[\"accent4\"])\n        self._launch_job(\"host_auto_share\", lambda: self._do_host_auto_share(printer_name, share_name))\n\n    def _do_host_auto_share(self, printer_name, share_name):\n        # 1) Ensure spooler running\n        self._run_cmd('net start spooler')\n        self._sharing_log(\"  \u2705 Spooler started\", C[\"success\"])\n\n        # 2) Enable firewall rules\n        self._run_cmd(\n            'netsh advfirewall firewall set rule '\n            'group=\"File and Printer Sharing\" new enable=Yes profile=any')\n        self._sharing_log(\"  \u2705 File &amp; Printer Sharing firewall \u2192 ON\", C[\"success\"])\n\n        # 3) Share via PowerShell (primary)\n        out, rc = self._run_cmd(\n            f'powershell -Command \"Set-Printer -Name \\'{printer_name}\\' '\n            f'-Shared $true -ShareName \\'{share_name}\\'\"',\n            timeout=15)\n        if rc == 0:\n            self._sharing_log(\n                f\"  \u2705 '{printer_name}' shared as '{share_name}' (PowerShell)\", C[\"success\"])\n        else:\n            # Fallback: rundll32\n            self._run_cmd(\n                f'rundll32 printui.dll,PrintUIEntry /Xs /n \"{printer_name}\" '\n                f'attributes +shared sharename \"{share_name}\"',\n                timeout=10)\n            self._sharing_log(\n                f\"  \u2705 Shared via legacy method (rundll32)\", C[\"success\"])\n\n        # 4) Restart spooler to apply\n        self._run_cmd('net stop spooler /y')\n        time.sleep(1)\n        self._run_cmd('net start spooler')\n        self._sharing_log(\"  \u2705 Spooler restarted \u2014 sharing active\", C[\"success\"])\n\n        # 5) Open Windows confirmation automatically\n        hostname = self._get_hostname()\n        unc_path = f\"\\\\\\\\{hostname}\\\\{share_name}\"\n\n        def _open_confirmation():\n            # Open Printers &amp; Scanners control panel\n            subprocess.Popen([\"control.exe\", \"printers\"], shell=False)\n            time.sleep(1)\n            # Open Printer Properties (sharing tab visible)\n            try:\n                subprocess.Popen(\n                    [\"rundll32.exe\", \"printui.dll,PrintUIEntry\", \"/p\", \"/n\", printer_name],\n                    shell=False)\n            except Exception:\n                pass\n            # Final confirmation dialog\n            messagebox.showinfo(\n                \"\ud83c\udf89 Printer Sharing Complete!\",\n                f\"\u2705 Printer successfully shared!\\n\\n\"\n                f\"Printer Name : {printer_name}\\n\"\n                f\"Share Name   : {share_name}\\n\"\n                f\"UNC Path     : {unc_path}\\n\"\n                f\"Host PC      : {hostname}\\n\\n\"\n                f\"Client computers isko iss address se connect kar sakte hain:\\n\"\n                f\"  {unc_path}\\n\\n\"\n                \"Printers window aur Printer Properties\\n\"\n                \"ab khul gaye hain \u2014 Sharing tab check karo. \u2705\")\n            self._sharing_log(\n                f\"\u2705 [HOST] SHARING CONFIRMED!  UNC: {unc_path}\", C[\"success\"])\n\n        self.after(0, _open_confirmation)\n        self.after(500, self._printer_detect)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \ud83d\udd34 ERROR 0x0000709 \u2014 AUTO-FIX  (HOST)\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _fix_error_709_host(self):\n        \"\"\"Error 0x0000709 fix: HOST side \u2014 default printer registry + spooler + RPC.\"\"\"\n        if not messagebox.askyesno(\"Fix Error 0x0000709 \u2014 HOST\",\n                \"Error 0x0000709 matlab:\\n\"\n                \"  'Operation could not be completed \u2014 default printer cannot be set'\\n\\n\"\n                \"HOST pe ye fixes honge:\\n\"\n                \"  1. Spooler stop \u2192 spool folder clean \u2192 restart\\n\"\n                \"  2. UserSelectedDefault registry fix\\n\"\n                \"  3. DefaultSpoolDirectory path verify\\n\"\n                \"  4. Spooler DLLs re-register (localspl, spoolss, win32spl)\\n\"\n                \"  5. RPC service verify\\n\"\n                \"  6. Windows 'Manage my default printer' feature disable\\n\"\n                \"  7. Spooler startup = Auto forced\\n\\n\"\n                \"Continue karein?\"):\n            return\n        self._sharing_log(\"\u2550\"*56, C[\"border\"])\n        self._sharing_log(\"\ud83d\udd34 [HOST] Error 0x0000709 fix chal raha hai...\", C[\"error\"])\n        self._launch_job(\"fix_error_709_host\", self._do_fix_error_709_host)\n\n    def _do_fix_error_709_host(self):\n        log = self._sharing_log\n        L = C\n\n        # Step 1 \u2014 Spooler stop + spool clean + restart\n        log(\"  [1/7] Spooler stop + spool clean...\", L[\"accent4\"])\n        self._run_cmd('net stop spooler /y')\n        time.sleep(1)\n        spool_dir = os.path.join(os.environ.get(\"SYSTEMROOT\",\"C:\\\\Windows\"),\n                                  \"System32\",\"spool\",\"PRINTERS\")\n        deleted = 0\n        for f in Path(spool_dir).glob(\"*\"):\n            try: f.unlink(); deleted += 1\n            except: pass\n        log(f\"  \u2705 {deleted} spool files deleted\", L[\"success\"])\n\n        # Step 2 \u2014 UserSelectedDefault registry\n        log(\"  [2/7] UserSelectedDefault registry fix...\", L[\"accent4\"])\n        try:\n            key = winreg.OpenKey(\n                winreg.HKEY_CURRENT_USER,\n                r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows\",\n                0, winreg.KEY_SET_VALUE | winreg.KEY_READ)\n            try:\n                winreg.DeleteValue(key, \"UserSelectedDefault\")\n                log(\"  \u2705 UserSelectedDefault removed (will auto-rebuild)\", L[\"success\"])\n            except FileNotFoundError:\n                log(\"  \u2139 UserSelectedDefault not found \u2014 OK\", L[\"text_dim\"])\n            winreg.CloseKey(key)\n        except Exception as e:\n            log(f\"  \u26a0 UserSelectedDefault: {e}\", L[\"warning\"])\n\n        # Also clear Device registry stale default\n        try:\n            key2 = winreg.OpenKey(\n                winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\\Printers\",\n                0, winreg.KEY_SET_VALUE | winreg.KEY_READ)\n            try:\n                winreg.DeleteValue(key2, \"DefaultSpoolDirectory\")\n            except: pass\n            winreg.CloseKey(key2)\n        except: pass\n\n        # Step 3 \u2014 DefaultSpoolDirectory path set correct\n        log(\"  [3/7] DefaultSpoolDirectory path verify + fix...\", L[\"accent4\"])\n        try:\n            key3 = winreg.OpenKey(\n                winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\\Printers\",\n                0, winreg.KEY_SET_VALUE)\n            winreg.SetValueEx(key3, \"DefaultSpoolDirectory\", 0,\n                              winreg.REG_SZ, spool_dir)\n            winreg.CloseKey(key3)\n            log(f\"  \u2705 DefaultSpoolDirectory = {spool_dir}\", L[\"success\"])\n        except Exception as e:\n            log(f\"  \u26a0 Spool dir registry: {e}\", L[\"warning\"])\n\n        # Step 4 \u2014 Re-register spooler DLLs\n        log(\"  [4/7] Spooler DLLs re-register...\", L[\"accent4\"])\n        sys32 = os.path.join(os.environ.get(\"SYSTEMROOT\",\"C:\\\\Windows\"), \"System32\")\n        for dll in [\"localspl.dll\",\"spoolss.dll\",\"win32spl.dll\",\"inetpp.dll\"]:\n            path = os.path.join(sys32, dll)\n            if os.path.exists(path):\n                self._run_cmd(f'regsvr32 /s \"{path}\"')\n                log(f\"  \u2705 Registered: {dll}\", L[\"success\"])\n\n        # Step 5 \u2014 RPC service running\n        log(\"  [5/7] RPC service verify...\", L[\"accent4\"])\n        self._run_cmd('sc config RpcSs start= auto')\n        self._run_cmd('sc start RpcSs')\n        out, _ = self._run_cmd('sc query RpcSs')\n        log(\"  \u2705 RPC: Running\" if \"RUNNING\" in out else \"  \u26a0 RPC: Check manually\", L[\"success\"] if \"RUNNING\" in out else L[\"warning\"])\n\n        # Step 6 \u2014 \"Let Windows manage my default printer\" OFF\n        log(\"  [6/7] Windows auto-default printer feature \u2192 OFF...\", L[\"accent4\"])\n        try:\n            key4 = winreg.OpenKey(\n                winreg.HKEY_CURRENT_USER,\n                r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows\",\n                0, winreg.KEY_SET_VALUE)\n            winreg.SetValueEx(key4, \"LegacyDefaultPrinterMode\", 0, winreg.REG_DWORD, 1)\n            winreg.CloseKey(key4)\n            log(\"  \u2705 LegacyDefaultPrinterMode = 1 (Windows auto-manage OFF)\", L[\"success\"])\n        except Exception as e:\n            log(f\"  \u26a0 LegacyDefaultPrinterMode: {e}\", L[\"warning\"])\n\n        # Step 7 \u2014 Spooler auto + restart\n        log(\"  [7/7] Spooler startup = Auto + Start...\", L[\"accent4\"])\n        self._run_cmd('sc config Spooler start= auto')\n        self._run_cmd('net start spooler')\n        time.sleep(1)\n        out2, _ = self._run_cmd('sc query Spooler')\n        if \"RUNNING\" in out2:\n            log(\"  \u2705 Spooler: Running!\", L[\"success\"])\n        else:\n            log(\"  \u26a0 Spooler start nahi hua \u2014 Full Repair try karo\", L[\"warning\"])\n\n        log(\"\", L[\"text\"])\n        log(\"\u2705 [HOST] Error 0x0000709 FIX COMPLETE!\", L[\"success\"])\n        log(\"   \u25ba Ab printer detect karo aur default set karo.\", L[\"text_dim\"])\n        self.after(0, self._refresh_spooler_status)\n        self.after(500, self._printer_detect)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \ud83d\udd34 ERROR 0x0000011b \u2014 AUTO-FIX  (HOST)\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _fix_error_11b_host(self):\n        \"\"\"Error 0x0000011b fix: HOST side \u2014 RpcAuthnLevelPrivacyEnabled rollback + SMB.\"\"\"\n        if not messagebox.askyesno(\"Fix Error 0x0000011b \u2014 HOST\",\n                \"Error 0x0000011b matlab:\\n\"\n                \"'Windows cannot connect to the printer \u2014 Operation failed with error 0x0000011b'\\n\\n\"\n                \"Ye Microsoft ke Windows Update (KB5005565/KB5005566) ke baad\\n\"\n                \"aata hai \u2014 RPC encryption policy strict ho gayi hai.\\n\\n\"\n                \"HOST pe ye fixes honge:\\n\"\n                \"  1. RpcAuthnLevelPrivacyEnabled = 0  (KB5005565 rollback)\\n\"\n                \"  2. RestrictRemoteClients = 0  (RPC remote access allow)\\n\"\n                \"  3. EnableAuthEpResolution = 1\\n\"\n                \"  4. LanmanServer security relax\\n\"\n                \"  5. Spooler restart\\n\"\n                \"  6. Firewall rules verify\\n\\n\"\n                \"\u26a0 Sirf trusted/private LAN pe karo!\\nContinue karein?\"):\n            return\n        self._sharing_log(\"\u2550\"*56, C[\"border\"])\n        self._sharing_log(\"\ud83d\udd34 [HOST] Error 0x0000011b fix chal raha hai...\", C[\"error\"])\n        self._launch_job(\"fix_error_11b_host\", self._do_fix_error_11b_host)\n\n    def _do_fix_error_11b_host(self):\n        log = self._sharing_log\n        L = C\n\n        # Step 1 \u2014 RpcAuthnLevelPrivacyEnabled = 0 (THE main fix for 11b)\n        log(\"  [1/6] RpcAuthnLevelPrivacyEnabled = 0 (KB5005565 fix)...\", L[\"accent4\"])\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                \"RpcAuthnLevelPrivacyEnabled\", 0, winreg.REG_DWORD)\n            log(\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0  (HOST \u2014 RPC encryption relaxed)\", L[\"success\"])\n        except Exception as e:\n            # Fallback via reg command\n            self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\" /v RpcAuthnLevelPrivacyEnabled /t REG_DWORD /d 0 /f')\n            log(f\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0 (via reg cmd, {e})\", L[\"success\"])\n\n        # Step 2 \u2014 RestrictRemoteClients = 0\n        log(\"  [2/6] RPC RestrictRemoteClients = 0...\", L[\"accent4\"])\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SOFTWARE\\Policies\\Microsoft\\Windows NT\\Rpc\",\n                \"RestrictRemoteClients\", 0, winreg.REG_DWORD)\n            log(\"  \u2705 RestrictRemoteClients = 0\", L[\"success\"])\n        except Exception as e:\n            self._run_cmd('reg add \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Rpc\" /v RestrictRemoteClients /t REG_DWORD /d 0 /f')\n            log(f\"  \u2705 RestrictRemoteClients = 0 (reg cmd)\", L[\"success\"])\n\n        # Step 3 \u2014 EnableAuthEpResolution = 1\n        log(\"  [3/6] EnableAuthEpResolution = 1...\", L[\"accent4\"])\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SOFTWARE\\Policies\\Microsoft\\Windows NT\\Rpc\",\n                \"EnableAuthEpResolution\", 1, winreg.REG_DWORD)\n            log(\"  \u2705 EnableAuthEpResolution = 1\", L[\"success\"])\n        except Exception as e:\n            self._run_cmd('reg add \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Rpc\" /v EnableAuthEpResolution /t REG_DWORD /d 1 /f')\n            log(f\"  \u2705 EnableAuthEpResolution = 1 (reg cmd)\", L[\"success\"])\n\n        # Step 4 \u2014 LanmanServer security relax\n        log(\"  [4/6] LanmanServer security relax...\", L[\"accent4\"])\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanServer\\\\Parameters\" /v RequireSecuritySignature /t REG_DWORD /d 0 /f')\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanServer\\\\Parameters\" /v EnableSecuritySignature /t REG_DWORD /d 1 /f')\n        log(\"  \u2705 LanmanServer SMB signing: optional\", L[\"success\"])\n\n        # Step 5 \u2014 Spooler restart\n        log(\"  [5/6] Spooler restart...\", L[\"accent4\"])\n        self._run_cmd('net stop spooler /y')\n        time.sleep(1)\n        self._run_cmd('net start spooler')\n        out, _ = self._run_cmd('sc query Spooler')\n        log(\"  \u2705 Spooler: Running\" if \"RUNNING\" in out else \"  \u26a0 Spooler check karo\", L[\"success\"] if \"RUNNING\" in out else L[\"warning\"])\n\n        # Step 6 \u2014 Firewall printer rules\n        log(\"  [6/6] Firewall rules verify...\", L[\"accent4\"])\n        self._run_cmd('netsh advfirewall firewall set rule group=\"File and Printer Sharing\" new enable=Yes profile=any')\n        for port, proto, name in [(445,\"TCP\",\"SMB\"),(135,\"TCP\",\"RPC\"),(9100,\"TCP\",\"RAW\")]:\n            self._run_cmd(f'netsh advfirewall firewall add rule name=\"Godawari11b_{name}\" dir=in action=allow protocol={proto} localport={port} profile=any')\n        log(\"  \u2705 Firewall rules: set\", L[\"success\"])\n\n        log(\"\", L[\"text\"])\n        log(\"\u2705 [HOST] Error 0x0000011b FIX COMPLETE!\", L[\"success\"])\n        log(\"   \u25ba IMPORTANT: HOST + CLIENT dono pe ye fix karo!\", L[\"warning\"])\n        log(\"   \u25ba Phir HOST restart karo for registry to take effect.\", L[\"text_dim\"])\n        self.after(0, self._refresh_spooler_status)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \ud83d\udd34 ERROR 0x0000709 \u2014 AUTO-FIX  (CLIENT)\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _fix_error_709_client(self):\n        if not messagebox.askyesno(\"Fix Error 0x0000709 \u2014 CLIENT\",\n                \"CLIENT pe Error 0x0000709 fix:\\n\\n\"\n                \"  1. Spooler stop + clean + restart\\n\"\n                \"  2. UserSelectedDefault registry clear\\n\"\n                \"  3. LegacyDefaultPrinterMode = 1\\n\"\n                \"  4. AllowInsecureGuestAuth = 1\\n\"\n                \"  5. LimitBlankPasswordUse = 0\\n\"\n                \"  6. Spooler DLLs re-register\\n\"\n                \"  7. Spooler Auto + Start\\n\\n\"\n                \"Continue karein?\"):\n            return\n        self._sharing_log(\"\u2550\"*56, C[\"border\"])\n        self._sharing_log(\"\ud83d\udd34 [CLIENT] Error 0x0000709 fix chal raha hai...\", C[\"error\"])\n        self._launch_job(\"fix_error_709_client\", self._do_fix_error_709_client)\n\n    def _do_fix_error_709_client(self):\n        log = self._sharing_log\n        L = C\n\n        log(\"  [1/7] Spooler stop + spool clean...\", L[\"accent4\"])\n        self._run_cmd('net stop spooler /y')\n        time.sleep(1)\n        spool_dir = os.path.join(os.environ.get(\"SYSTEMROOT\",\"C:\\\\Windows\"),\"System32\",\"spool\",\"PRINTERS\")\n        deleted = 0\n        for f in Path(spool_dir).glob(\"*\"):\n            try: f.unlink(); deleted += 1\n            except: pass\n        log(f\"  \u2705 {deleted} spool files deleted\", L[\"success\"])\n\n        log(\"  [2/7] UserSelectedDefault registry clear...\", L[\"accent4\"])\n        try:\n            key = winreg.OpenKey(winreg.HKEY_CURRENT_USER,\n                r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows\",\n                0, winreg.KEY_SET_VALUE | winreg.KEY_READ)\n            try:\n                winreg.DeleteValue(key, \"UserSelectedDefault\")\n                log(\"  \u2705 UserSelectedDefault removed\", L[\"success\"])\n            except FileNotFoundError:\n                log(\"  \u2139 UserSelectedDefault not found \u2014 OK\", L[\"text_dim\"])\n            winreg.CloseKey(key)\n        except Exception as e:\n            log(f\"  \u26a0 {e}\", L[\"warning\"])\n\n        log(\"  [3/7] LegacyDefaultPrinterMode = 1 (Windows auto-manage OFF)...\", L[\"accent4\"])\n        try:\n            key2 = winreg.OpenKey(winreg.HKEY_CURRENT_USER,\n                r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows\",\n                0, winreg.KEY_SET_VALUE)\n            winreg.SetValueEx(key2, \"LegacyDefaultPrinterMode\", 0, winreg.REG_DWORD, 1)\n            winreg.CloseKey(key2)\n            log(\"  \u2705 LegacyDefaultPrinterMode = 1\", L[\"success\"])\n        except Exception as e:\n            log(f\"  \u26a0 {e}\", L[\"warning\"])\n\n        log(\"  [4/7] AllowInsecureGuestAuth = 1...\", L[\"accent4\"])\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Services\\LanmanWorkstation\\Parameters\",\n                \"AllowInsecureGuestAuth\", 1, winreg.REG_DWORD)\n            log(\"  \u2705 AllowInsecureGuestAuth = 1\", L[\"success\"])\n        except Exception as e:\n            log(f\"  \u26a0 {e}\", L[\"warning\"])\n\n        log(\"  [5/7] LimitBlankPasswordUse = 0...\", L[\"accent4\"])\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Lsa\" /v LimitBlankPasswordUse /t REG_DWORD /d 0 /f')\n        log(\"  \u2705 LimitBlankPasswordUse = 0\", L[\"success\"])\n\n        log(\"  [6/7] Spooler DLLs re-register...\", L[\"accent4\"])\n        sys32 = os.path.join(os.environ.get(\"SYSTEMROOT\",\"C:\\\\Windows\"), \"System32\")\n        for dll in [\"localspl.dll\",\"spoolss.dll\",\"win32spl.dll\"]:\n            path = os.path.join(sys32, dll)\n            if os.path.exists(path):\n                self._run_cmd(f'regsvr32 /s \"{path}\"')\n                log(f\"  \u2705 Registered: {dll}\", L[\"success\"])\n\n        log(\"  [7/7] Spooler Auto + Start...\", L[\"accent4\"])\n        self._run_cmd('sc config Spooler start= auto')\n        self._run_cmd('net start spooler')\n        time.sleep(1)\n        out, _ = self._run_cmd('sc query Spooler')\n        log(\"  \u2705 Spooler: Running!\" if \"RUNNING\" in out else \"  \u26a0 Spooler check karo\", L[\"success\"] if \"RUNNING\" in out else L[\"warning\"])\n\n        log(\"\", L[\"text\"])\n        log(\"\u2705 [CLIENT] Error 0x0000709 FIX COMPLETE!\", L[\"success\"])\n        log(\"   \u25ba Ab 'Detect Printers' karo aur default printer set karo.\", L[\"text_dim\"])\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \ud83d\udd34 ERROR 0x0000011b \u2014 AUTO-FIX  (CLIENT)\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _fix_error_11b_client(self):\n        if not messagebox.askyesno(\"Fix Error 0x0000011b \u2014 CLIENT\",\n                \"CLIENT pe Error 0x0000011b fix:\\n\\n\"\n                \"'Windows cannot connect to the printer \u2014 0x0000011b'\\n\"\n                \"Ye Windows Update KB5005565 ke baad aata hai.\\n\\n\"\n                \"  1. RpcAuthnLevelPrivacyEnabled = 0  \u2190 MAIN FIX\\n\"\n                \"  2. RestrictRemoteClients = 0\\n\"\n                \"  3. EnableAuthEpResolution = 1\\n\"\n                \"  4. LanmanWorkstation SMB signing relax\\n\"\n                \"  5. AllowInsecureGuestAuth = 1\\n\"\n                \"  6. Point &amp; Print restrictions relax\\n\"\n                \"  7. Firewall rules + Spooler restart\\n\\n\"\n                \"\u26a0 Sirf trusted LAN pe karo!\\nContinue karein?\"):\n            return\n        self._sharing_log(\"\u2550\"*56, C[\"border\"])\n        self._sharing_log(\"\ud83d\udd34 [CLIENT] Error 0x0000011b fix chal raha hai...\", C[\"error\"])\n        self._launch_job(\"fix_error_11b_client\", self._do_fix_error_11b_client)\n\n    def _do_fix_error_11b_client(self):\n        log = self._sharing_log\n        L = C\n\n        # Step 1 \u2014 THE main fix\n        log(\"  [1/7] RpcAuthnLevelPrivacyEnabled = 0  \u2190 MAIN FIX...\", L[\"accent4\"])\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                \"RpcAuthnLevelPrivacyEnabled\", 0, winreg.REG_DWORD)\n            log(\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0  (CLIENT)\", L[\"success\"])\n        except Exception as e:\n            self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\" /v RpcAuthnLevelPrivacyEnabled /t REG_DWORD /d 0 /f')\n            log(f\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0 (reg cmd, {e})\", L[\"success\"])\n\n        # Step 2 \u2014 RestrictRemoteClients\n        log(\"  [2/7] RestrictRemoteClients = 0...\", L[\"accent4\"])\n        self._run_cmd('reg add \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Rpc\" /v RestrictRemoteClients /t REG_DWORD /d 0 /f')\n        log(\"  \u2705 RestrictRemoteClients = 0\", L[\"success\"])\n\n        # Step 3 \u2014 EnableAuthEpResolution\n        log(\"  [3/7] EnableAuthEpResolution = 1...\", L[\"accent4\"])\n        self._run_cmd('reg add \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Rpc\" /v EnableAuthEpResolution /t REG_DWORD /d 1 /f')\n        log(\"  \u2705 EnableAuthEpResolution = 1\", L[\"success\"])\n\n        # Step 4 \u2014 LanmanWorkstation signing relax\n        log(\"  [4/7] LanmanWorkstation SMB signing relax...\", L[\"accent4\"])\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanWorkstation\\\\Parameters\" /v RequireSecuritySignature /t REG_DWORD /d 0 /f')\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanWorkstation\\\\Parameters\" /v EnableSecuritySignature /t REG_DWORD /d 1 /f')\n        log(\"  \u2705 LanmanWorkstation SMB signing: optional\", L[\"success\"])\n\n        # Step 5 \u2014 AllowInsecureGuestAuth\n        log(\"  [5/7] AllowInsecureGuestAuth = 1...\", L[\"accent4\"])\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Services\\LanmanWorkstation\\Parameters\",\n                \"AllowInsecureGuestAuth\", 1, winreg.REG_DWORD)\n            log(\"  \u2705 AllowInsecureGuestAuth = 1\", L[\"success\"])\n        except Exception as e:\n            log(f\"  \u26a0 {e}\", L[\"warning\"])\n\n        # Step 6 \u2014 Point &amp; Print relax\n        log(\"  [6/7] Point &amp; Print restrictions relax...\", L[\"accent4\"])\n        for cmd in [\n            'reg add \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Printers\\\\PointAndPrint\" /v NoWarningNoElevationOnInstall /t REG_DWORD /d 1 /f',\n            'reg add \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Printers\\\\PointAndPrint\" /v UpdatePromptSettings /t REG_DWORD /d 2 /f',\n            'reg add \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Printers\\\\PointAndPrint\" /v RestrictDriverInstallationToAdministrators /t REG_DWORD /d 0 /f',\n        ]:\n            self._run_cmd(cmd)\n        log(\"  \u2705 Point &amp; Print: relaxed\", L[\"success\"])\n\n        # Step 7 \u2014 Firewall + Spooler\n        log(\"  [7/7] Firewall + Spooler restart...\", L[\"accent4\"])\n        self._run_cmd('netsh advfirewall firewall set rule group=\"File and Printer Sharing\" new enable=Yes profile=any')\n        self._run_cmd('net stop spooler /y')\n        time.sleep(1)\n        self._run_cmd('net start spooler')\n        out, _ = self._run_cmd('sc query Spooler')\n        log(\"  \u2705 Spooler: Running\" if \"RUNNING\" in out else \"  \u26a0 Spooler check karo\", L[\"success\"] if \"RUNNING\" in out else L[\"warning\"])\n\n        log(\"\", L[\"text\"])\n        log(\"\u2705 [CLIENT] Error 0x0000011b FIX COMPLETE!\", L[\"success\"])\n        log(\"   \u25ba HOST pe bhi yahi fix karo!\", L[\"warning\"])\n        log(\"   \u25ba Phir computer restart karo \u2014 printer connect hoga.\", L[\"text_dim\"])\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \ud83d\ude80 MEGA AUTO-FIX \u2014 HOST (Sabkuch ek saath)\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \ud83d\udd34 ENTERPRISE PRINTER RECOVERY CENTER \u2014 Backend Methods\n    #  Tab 4: Network Printer Recovery \u2014 All repair logic\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    # \u2500\u2500 Internal logging helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_log(self, msg, color=None):\n        \"\"\"Log to repair log panel.\"\"\"\n        color = color or C[\"text\"]\n        self._append_log(getattr(self, \"epr_repair_log\", None) or\n                         getattr(self, \"printer_log\", None), msg, color)\n\n    def _epr_diag(self, msg, color=None):\n        \"\"\"Log to live diagnostics panel.\"\"\"\n        color = color or C[\"text\"]\n        self._append_log(getattr(self, \"epr_diag_log\", None) or\n                         getattr(self, \"printer_log\", None), msg, color)\n\n    def _epr_summary(self, msg, color=None):\n        \"\"\"Log to recovery summary panel.\"\"\"\n        color = color or C[\"text\"]\n        self._append_log(getattr(self, \"epr_summary_log\", None) or\n                         getattr(self, \"printer_log\", None), msg, color)\n\n    def _epr_detect_log(self, msg, color=None):\n        \"\"\"Log to auto-detection panel.\"\"\"\n        color = color or C[\"text\"]\n        self._append_log(getattr(self, \"epr_detect_log\", None) or\n                         getattr(self, \"printer_log\", None), msg, color)\n\n    def _epr_set_status(self, msg, color=None):\n        \"\"\"Update status label on the EPR tab.\"\"\"\n        color = color or C[\"accent4\"]\n        def _do():\n            try:\n                lbl = getattr(self, \"epr_status_lbl\", None)\n                if lbl:\n                    lbl.config(text=msg, fg=color)\n            except Exception:\n                pass\n        self.after(0, _do)\n\n    def _epr_progress_start(self):\n        def _do():\n            try:\n                p = getattr(self, \"epr_progress\", None)\n                if p:\n                    p.start(12)\n            except Exception:\n                pass\n        self.after(0, _do)\n\n    def _epr_progress_stop(self):\n        def _do():\n            try:\n                p = getattr(self, \"epr_progress\", None)\n                if p:\n                    p.stop()\n            except Exception:\n                pass\n        self.after(0, _do)\n\n    def _epr_submit(self, name, fn, *args, **kwargs):\n        \"\"\"Submit an EPR task to worker manager.\"\"\"\n        mgr = getattr(self, \"worker_manager\", None)\n        if mgr:\n            try:\n                mgr.submit(name, fn, *args, **kwargs)\n                return\n            except Exception:\n                pass\n        self._launch_job(\"bg_task\", fn, *args, **kwargs)\n\n    def _epr_reg_backup(self, hive, path, backup_name):\n        \"\"\"Backup a registry key before modifying it.\"\"\"\n        try:\n            backup_dir = Path(os.environ.get(\"TEMP\", \"C:\\\\Temp\")) / \"GodawariEPR_Backup\"\n            backup_dir.mkdir(parents=True, exist_ok=True)\n            ts = datetime.datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n            backup_file = str(backup_dir / f\"{backup_name}_{ts}.reg\")\n            hive_str = {\n                winreg.HKEY_LOCAL_MACHINE:  \"HKLM\",\n                winreg.HKEY_CURRENT_USER:   \"HKCU\",\n                winreg.HKEY_USERS:          \"HKU\",\n            }.get(hive, \"HKLM\")\n            self._run_cmd(f'reg export \"{hive_str}\\\\{path}\" \"{backup_file}\" /y', timeout=10)\n            return backup_file\n        except Exception:\n            return None\n\n    # \u2500\u2500 Auto Detection \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_auto_detect(self):\n        self._epr_submit(\"epr_auto_detect\", self._do_epr_auto_detect)\n\n    def _do_epr_auto_detect(self):\n        log = self._epr_detect_log\n        self._epr_progress_start()\n        self._epr_set_status(\"Running auto-detection...\", C[\"accent4\"])\n        log(\"\u2550\" * 54, C[\"border\"])\n        log(\"\ud83d\udd0d AUTO-DETECTION STARTING...\", C[\"accent\"])\n        issues = []\n\n        # 1. Spooler check\n        log(\"  [1/8] Checking Print Spooler...\", C[\"text_dim\"])\n        out, _ = self._run_cmd(\"sc query Spooler\", timeout=8)\n        if \"RUNNING\" not in out:\n            log(\"  \u274c Spooler NOT running\", C[\"error\"])\n            issues.append(\"Spooler stopped\")\n        else:\n            log(\"  \u2705 Spooler: Running\", C[\"success\"])\n\n        # 2. RPC setting check\n        log(\"  [2/8] Checking RpcAuthnLevelPrivacyEnabled...\", C[\"text_dim\"])\n        try:\n            key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                0, winreg.KEY_READ)\n            val, _ = winreg.QueryValueEx(key, \"RpcAuthnLevelPrivacyEnabled\")\n            winreg.CloseKey(key)\n            if val == 1:\n                log(\"  \u26a0 RpcAuthnLevelPrivacyEnabled = 1 (may block printer sharing)\", C[\"warning\"])\n                issues.append(\"RPC Privacy = 1 (error 0x0000011b risk)\")\n            else:\n                log(\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0 (OK)\", C[\"success\"])\n        except FileNotFoundError:\n            log(\"  \u2139 RpcAuthnLevelPrivacyEnabled not set (default=1 on patched Win11)\", C[\"warning\"])\n            issues.append(\"RPC Privacy key missing \u2014 may default to 1\")\n        except Exception as e:\n            log(f\"  \u26a0 RPC check failed: {e}\", C[\"warning\"])\n\n        # 3. Firewall check\n        log(\"  [3/8] Checking Firewall sharing rules...\", C[\"text_dim\"])\n        out2, _ = self._run_cmd(\n            'netsh advfirewall firewall show rule name=\"File and Printer Sharing (SMB-In)\" verbose',\n            timeout=10)\n        if \"Enabled\" not in out2 and \"Yes\" not in out2:\n            log(\"  \u274c File &amp; Printer Sharing firewall rules may be OFF\", C[\"error\"])\n            issues.append(\"Firewall sharing rules disabled\")\n        else:\n            log(\"  \u2705 Firewall: F&amp;P Sharing rules OK\", C[\"success\"])\n\n        # 4. Network discovery\n        log(\"  [4/8] Checking Network Discovery...\", C[\"text_dim\"])\n        out3, _ = self._run_cmd(\n            \"netsh advfirewall firewall show rule name=\\\"Network Discovery (NB-Datagram-In)\\\" verbose\",\n            timeout=10)\n        if \"Enabled\" not in out3 and \"Yes\" not in out3:\n            log(\"  \u26a0 Network Discovery may be disabled\", C[\"warning\"])\n            issues.append(\"Network Discovery disabled\")\n        else:\n            log(\"  \u2705 Network Discovery: OK\", C[\"success\"])\n\n        # 5. SMB1 check\n        log(\"  [5/8] Checking SMB services...\", C[\"text_dim\"])\n        out4, _ = self._run_cmd(\"sc query LanmanServer\", timeout=8)\n        if \"RUNNING\" not in out4:\n            log(\"  \u274c LanmanServer (Server service) NOT running\", C[\"error\"])\n            issues.append(\"LanmanServer stopped\")\n        else:\n            log(\"  \u2705 LanmanServer: Running\", C[\"success\"])\n\n        # 6. Point &amp; Print check\n        log(\"  [6/8] Checking Point &amp; Print restrictions...\", C[\"text_dim\"])\n        try:\n            key2 = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,\n                r\"SOFTWARE\\Policies\\Microsoft\\Windows NT\\Printers\\PointAndPrint\",\n                0, winreg.KEY_READ)\n            try:\n                restrict, _ = winreg.QueryValueEx(key2, \"Restricted\")\n                if restrict == 1:\n                    log(\"  \u26a0 Point &amp; Print Restricted = 1 (may block driver install)\", C[\"warning\"])\n                    issues.append(\"Point &amp; Print restriction active\")\n                else:\n                    log(\"  \u2705 Point &amp; Print: Not restricted\", C[\"success\"])\n            except FileNotFoundError:\n                log(\"  \u2705 Point &amp; Print: Default (OK)\", C[\"success\"])\n            winreg.CloseKey(key2)\n        except Exception:\n            log(\"  \u2139 Point &amp; Print GPO key not found (OK)\", C[\"text_dim\"])\n\n        # 7. Printer port reachability (if host/share entered)\n        host = getattr(self, \"epr_host_var\", tk.StringVar()).get().strip()\n        if host:\n            log(f\"  [7/8] Pinging host: {host}...\", C[\"text_dim\"])\n            out5, rc5 = self._run_cmd(f\"ping -n 2 -w 1000 {host}\", timeout=10)\n            if rc5 == 0 and \"TTL=\" in out5:\n                log(f\"  \u2705 Host reachable: {host}\", C[\"success\"])\n            else:\n                log(f\"  \u274c Host NOT reachable: {host}\", C[\"error\"])\n                issues.append(f\"Host unreachable: {host}\")\n        else:\n            log(\"  [7/8] Host not entered \u2014 skip ping\", C[\"text_dim\"])\n\n        # 8. Spool directory check\n        log(\"  [8/8] Checking spool directory...\", C[\"text_dim\"])\n        spool_dir = os.path.join(os.environ.get(\"SYSTEMROOT\", \"C:\\\\Windows\"),\n                                  \"System32\", \"spool\", \"PRINTERS\")\n        try:\n            stuck = list(Path(spool_dir).glob(\"*.SPL\")) + list(Path(spool_dir).glob(\"*.SHD\"))\n            if stuck:\n                log(f\"  \u26a0 {len(stuck)} stuck spool files found\", C[\"warning\"])\n                issues.append(f\"{len(stuck)} stuck spool files\")\n            else:\n                log(\"  \u2705 Spool directory: Clean\", C[\"success\"])\n        except Exception:\n            log(\"  \u2139 Spool check skipped (access issue)\", C[\"text_dim\"])\n\n        # Summary\n        log(\"\", C[\"text\"])\n        if issues:\n            log(f\"\u26a0 ISSUES DETECTED ({len(issues)}):\", C[\"warning\"])\n            for iss in issues:\n                log(f\"  \u2022 {iss}\", C[\"error\"])\n            log(\"\", C[\"text\"])\n            log(\"\u2192 Click FULL AUTO FIX to repair all detected issues.\", C[\"accent4\"])\n        else:\n            log(\"\u2705 No major issues detected! Network printer should work.\", C[\"success\"])\n\n        self._epr_progress_stop()\n        self._epr_set_status(\n            f\"Detection complete \u2014 {len(issues)} issue(s) found\",\n            C[\"error\"] if issues else C[\"success\"])\n\n    # \u2500\u2500 Full Auto Fix \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_full_auto_fix(self):\n        if not messagebox.askyesno(\n            \"\ud83d\ude80 FULL AUTO FIX \u2014 Enterprise Printer Recovery\",\n            \"This will automatically perform 18 repair steps:\\n\\n\"\n            \"  1.  Diagnose printer sharing problems\\n\"\n            \"  2.  Detect root cause\\n\"\n            \"  3.  Repair Print Spooler\\n\"\n            \"  4.  Repair RPC + SMB issues\\n\"\n            \"  5.  Repair Point &amp; Print restrictions\\n\"\n            \"  6.  Repair firewall sharing rules\\n\"\n            \"  7.  Repair network discovery\\n\"\n            \"  8.  Repair printer sharing settings\\n\"\n            \"  9.  Repair broken printer cache\\n\"\n            \" 10. Remove corrupted printer mappings\\n\"\n            \" 11. Repair Canon printer compatibility\\n\"\n            \" 12. Detect x86/x64 driver mismatch\\n\"\n            \" 13. Repair driver installation issues\\n\"\n            \" 14. Validate printer reachability\\n\"\n            \" 15. Reconnect shared printer\\n\"\n            \" 16. Validate successful printer installation\\n\"\n            \" 17. Generate repair summary\\n\"\n            \" 18. Log all actions safely\\n\\n\"\n            \"\u26a0 Run as Administrator for full effect.\\n\"\n            \"Continue?\"):\n            return\n        self._epr_submit(\"epr_full_auto_fix\", self._do_epr_full_auto_fix)\n\n    def _do_epr_full_auto_fix(self):\n        log  = self._epr_log\n        diag = self._epr_diag\n        summ = self._epr_summary\n        self._epr_progress_start()\n        results = []\n\n        def step(n, total, msg):\n            self._epr_set_status(f\"[{n}/{total}] {msg}\", C[\"accent4\"])\n            log(f\"\\n[{n:02d}/{total}] {msg}\", C[\"accent4\"])\n            diag(f\"  \u25ba {msg}\", C[\"text_dim\"])\n\n        log(\"\u2550\" * 56, C[\"border\"])\n        log(\"\ud83d\ude80 FULL AUTO FIX \u2014 Enterprise Network Printer Recovery\", C[\"error\"])\n        log(\"\u2550\" * 56, C[\"border\"])\n\n        TOTAL = 18\n\n        # \u2500\u2500 Step 1: Diagnose \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(1, TOTAL, \"Diagnosing printer sharing problems\")\n        self._do_epr_auto_detect()\n        results.append(\"\u2705 Diagnosis complete\")\n\n        # \u2500\u2500 Step 2: Detect root cause \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(2, TOTAL, \"Detecting root cause (RPC, spooler, firewall)\")\n        rpc_broken = False\n        spooler_broken = False\n        try:\n            key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\", 0, winreg.KEY_READ)\n            try:\n                val, _ = winreg.QueryValueEx(key, \"RpcAuthnLevelPrivacyEnabled\")\n                rpc_broken = (val == 1)\n            except FileNotFoundError:\n                rpc_broken = True   # missing = system default may be 1 on patched Win11\n            winreg.CloseKey(key)\n        except Exception:\n            rpc_broken = True\n\n        out_sp, _ = self._run_cmd(\"sc query Spooler\", timeout=8)\n        spooler_broken = \"RUNNING\" not in out_sp\n        log(f\"  RPC broken: {rpc_broken}  |  Spooler broken: {spooler_broken}\", C[\"text_dim\"])\n        results.append(f\"\u2705 Root cause: RPC={rpc_broken}, Spooler={spooler_broken}\")\n\n        # \u2500\u2500 Step 3: Repair Spooler \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(3, TOTAL, \"Repairing Print Spooler\")\n        self._run_cmd(\"net stop spooler /y\", timeout=8)\n        time.sleep(1)\n        spool_dir = os.path.join(os.environ.get(\"SYSTEMROOT\", \"C:\\\\Windows\"),\n                                  \"System32\", \"spool\", \"PRINTERS\")\n        cleared = 0\n        try:\n            for f in Path(spool_dir).glob(\"*\"):\n                try:\n                    f.unlink(); cleared += 1\n                except Exception:\n                    pass\n        except Exception:\n            pass\n        self._run_cmd(\"sc config Spooler start= auto\")\n        self._run_cmd(\"net start spooler\", timeout=8)\n        time.sleep(1)\n        out_sp2, _ = self._run_cmd(\"sc query Spooler\", timeout=8)\n        ok = \"RUNNING\" in out_sp2\n        log(f\"  {'\u2705' if ok else '\u274c'} Spooler: {'Running' if ok else 'FAILED'} | {cleared} spool files cleared\",\n            C[\"success\"] if ok else C[\"error\"])\n        results.append(f\"{'\u2705' if ok else '\u274c'} Spooler repair\")\n\n        # \u2500\u2500 Step 4: RPC + SMB repair \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(4, TOTAL, \"Repairing RPC + SMB issues\")\n        self._epr_reg_backup(winreg.HKEY_LOCAL_MACHINE,\n            r\"SYSTEM\\CurrentControlSet\\Control\\Print\", \"RpcPrint_backup\")\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                \"RpcAuthnLevelPrivacyEnabled\", 0, winreg.REG_DWORD)\n            log(\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0\", C[\"success\"])\n        except Exception:\n            self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\" /v RpcAuthnLevelPrivacyEnabled /t REG_DWORD /d 0 /f')\n            log(\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0 (via reg cmd)\", C[\"success\"])\n\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SOFTWARE\\Policies\\Microsoft\\Windows NT\\Rpc\",\n                \"RestrictRemoteClients\", 0, winreg.REG_DWORD)\n            log(\"  \u2705 RestrictRemoteClients = 0\", C[\"success\"])\n        except Exception:\n            self._run_cmd('reg add \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Rpc\" /v RestrictRemoteClients /t REG_DWORD /d 0 /f')\n\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanServer\\\\Parameters\" /v RequireSecuritySignature /t REG_DWORD /d 0 /f')\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanWorkstation\\\\Parameters\" /v RequireSecuritySignature /t REG_DWORD /d 0 /f')\n        log(\"  \u2705 SMB signing: optional on both sides\", C[\"success\"])\n        results.append(\"\u2705 RPC + SMB repaired\")\n\n        # \u2500\u2500 Step 5: Point &amp; Print \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(5, TOTAL, \"Repairing Point &amp; Print restrictions\")\n        self._do_epr_point_print_repair_silent()\n        results.append(\"\u2705 Point &amp; Print repaired\")\n\n        # \u2500\u2500 Step 6: Firewall \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(6, TOTAL, \"Repairing firewall sharing rules\")\n        self._do_epr_firewall_fix_silent()\n        results.append(\"\u2705 Firewall rules applied\")\n\n        # \u2500\u2500 Step 7: Network discovery \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(7, TOTAL, \"Repairing network discovery\")\n        self._do_epr_enable_netdiscovery_silent()\n        results.append(\"\u2705 Network discovery enabled\")\n\n        # \u2500\u2500 Step 8: Printer sharing settings \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(8, TOTAL, \"Repairing printer sharing settings\")\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanServer\\\\Parameters\" /v AutoShareServer /t REG_DWORD /d 1 /f')\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanServer\\\\Parameters\" /v AutoShareWks /t REG_DWORD /d 1 /f')\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Lsa\" /v LimitBlankPasswordUse /t REG_DWORD /d 0 /f')\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanWorkstation\\\\Parameters\" /v AllowInsecureGuestAuth /t REG_DWORD /d 1 /f')\n        log(\"  \u2705 Sharing settings: AutoShare + LimitBlank + GuestAuth\", C[\"success\"])\n        results.append(\"\u2705 Sharing settings repaired\")\n\n        # \u2500\u2500 Step 9: Printer cache \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(9, TOTAL, \"Repairing broken printer cache\")\n        self._do_epr_cache_cleaner_silent()\n        results.append(\"\u2705 Printer cache cleaned\")\n\n        # \u2500\u2500 Step 10: Remove corrupted mappings \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(10, TOTAL, \"Removing corrupted printer mappings\")\n        removed = 0\n        try:\n            ps_script = (\n                \"$printers = Get-Printer -ErrorAction SilentlyContinue | \"\n                \"Where-Object {$_.PrinterStatus -eq 'Error' -or $_.PrinterStatus -eq 'Offline'};\"\n                \"foreach ($p in $printers) { Remove-Printer -Name $p.Name -ErrorAction SilentlyContinue; \"\n                \"Write-Output \\\"REMOVED:$($p.Name)\\\" }\"\n            )\n            out_rm = self._run_cmd(\n                f'powershell -NoProfile -Command \"{ps_script}\"', timeout=30)\n            out_str = out_rm[0] if isinstance(out_rm, tuple) else str(out_rm)\n            removed = out_str.count(\"REMOVED:\")\n            log(f\"  \u2705 {removed} corrupted printer mapping(s) removed\", C[\"success\"])\n        except Exception as e:\n            log(f\"  \u26a0 Mapping removal: {e}\", C[\"warning\"])\n        results.append(f\"\u2705 Removed {removed} corrupted mapping(s)\")\n\n        # \u2500\u2500 Step 11: Canon compatibility \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(11, TOTAL, \"Repairing Canon printer compatibility\")\n        self._do_epr_canon_fix_silent()\n        results.append(\"\u2705 Canon compatibility applied\")\n\n        # \u2500\u2500 Step 12: Driver mismatch detection \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(12, TOTAL, \"Detecting x86/x64 driver mismatch\")\n        arch_ok = self._do_epr_check_driver_arch()\n        results.append(f\"{'\u2705' if arch_ok else '\u26a0'} Driver arch: {'OK' if arch_ok else 'Mismatch detected'}\")\n\n        # \u2500\u2500 Step 13: Driver repair \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(13, TOTAL, \"Repairing driver installation issues\")\n        sys32 = os.path.join(os.environ.get(\"SYSTEMROOT\", \"C:\\\\Windows\"), \"System32\")\n        for dll in [\"localspl.dll\", \"spoolss.dll\", \"win32spl.dll\", \"winspool.drv\"]:\n            path = os.path.join(sys32, dll)\n            if os.path.exists(path):\n                self._run_cmd(f'regsvr32 /s \"{path}\"')\n        log(\"  \u2705 Spooler DLLs re-registered\", C[\"success\"])\n        results.append(\"\u2705 Driver DLLs re-registered\")\n\n        # \u2500\u2500 Step 14: Validate reachability \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(14, TOTAL, \"Validating printer reachability\")\n        host = getattr(self, \"epr_host_var\", tk.StringVar()).get().strip()\n        if host:\n            safe_host = re.sub(r\"[^A-Za-z0-9_.:-]\", \"\", host)\n            out_ping, rc_ping = self._run_cmd(f\"ping -n 1 -w 1000 {safe_host}\", timeout=5)\n            reachable = rc_ping == 0 and \"TTL=\" in out_ping.upper()\n            log(f\"  {'\u2705' if reachable else '\u274c'} Host {host}: {'reachable' if reachable else 'unreachable'}\", C[\"success\"] if reachable else C[\"error\"])\n            results.append(f\"{'\u2705' if reachable else '\u274c'} Host reachability: {host}\")\n        else:\n            log(\"  \u2139 Host not specified \u2014 skip ping test\", C[\"text_dim\"])\n            results.append(\"\u2139 Host reachability: skipped (no host entered)\")\n\n        # \u2500\u2500 Step 15: Reconnect shared printer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(15, TOTAL, \"Reconnecting shared printer\")\n        share = getattr(self, \"epr_share_var\", tk.StringVar()).get().strip()\n        if host and share:\n            safe_host = re.sub(r\"[^A-Za-z0-9_.:-]\", \"\", host)\n            safe_share = re.sub(r\"[^A-Za-z0-9_.$ -]\", \"\", share).strip()\n            unc = f\"\\\\\\\\{safe_host}\\\\{safe_share}\"\n            out_nu, rc_nu = self._run_cmd(f'net use \"{unc}\" /persistent:yes', timeout=8)\n            if rc_nu == 0 or \"completed\" in out_nu.lower():\n                log(f\"  \u2705 Connected to: {unc}\", C[\"success\"])\n                results.append(f\"\u2705 Reconnected: {unc}\")\n            else:\n                log(f\"  \u26a0 net use result: {out_nu[:100]}\", C[\"warning\"])\n                results.append(f\"\u26a0 Reconnect attempted: {unc}\")\n        else:\n            log(\"  \u2139 Host/Share not specified \u2014 skip reconnect\", C[\"text_dim\"])\n            results.append(\"\u2139 Reconnect: skipped (enter Host IP and Share Name above)\")\n\n        # \u2500\u2500 Step 16: Validate installation \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(16, TOTAL, \"Validating successful printer installation\")\n        out_list, _ = self._run_cmd(\n            'powershell -NoProfile -Command \"Get-Printer | Select-Object Name,PrinterStatus | ConvertTo-Csv -NoTypeInformation\"',\n            timeout=12)\n        printer_count = max(0, out_list.count(\"\\n\") - 1)\n        log(f\"  \u2705 {printer_count} printer(s) found after repair\", C[\"success\"])\n        results.append(f\"\u2705 Validation: {printer_count} printer(s) visible\")\n\n        # \u2500\u2500 Step 17: Spooler final restart \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(17, TOTAL, \"Final spooler restart + service validation\")\n        self._run_cmd(\"net stop spooler /y\", timeout=8)\n        time.sleep(1)\n        self._run_cmd(\"net start spooler\", timeout=8)\n        out_final, _ = self._run_cmd(\"sc query Spooler\", timeout=8)\n        spooler_ok = \"RUNNING\" in out_final\n        log(f\"  {'\u2705' if spooler_ok else '\u274c'} Final spooler state: {'Running' if spooler_ok else 'STOPPED'}\", C[\"success\"] if spooler_ok else C[\"error\"])\n        self.after(0, self._refresh_spooler_status)\n\n        # \u2500\u2500 Step 18: Generate summary \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(18, TOTAL, \"Generating repair summary + logging\")\n        ts = datetime.datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\")\n        summ(\"\u2550\" * 50, C[\"border\"])\n        summ(f\"\ud83d\udd34 ENTERPRISE PRINTER RECOVERY \u2014 SUMMARY\", C[\"accent\"])\n        summ(f\"   Completed at: {ts}\", C[\"text_dim\"])\n        summ(\"\", C[\"text\"])\n        for r in results:\n            color = C[\"success\"] if r.startswith(\"\u2705\") else (C[\"error\"] if r.startswith(\"\u274c\") else C[\"warning\"])\n            summ(f\"  {r}\", color)\n        summ(\"\", C[\"text\"])\n        passed = sum(1 for r in results if r.startswith(\"\u2705\"))\n        failed = sum(1 for r in results if r.startswith(\"\u274c\"))\n        summ(f\"  Total: {passed} passed / {failed} failed / {len(results)} steps\", C[\"accent4\"])\n        if failed == 0:\n            summ(\"  \u25ba REPAIR SUCCESSFUL \u2014 Try your printer now!\", C[\"success\"])\n            summ(\"  \u25ba Restart this PC if printer still not working.\", C[\"text_dim\"])\n        else:\n            summ(\"  \u25ba Some steps had issues \u2014 check Repair Log for details.\", C[\"warning\"])\n            summ(\"  \u25ba Try individual repair buttons for failed steps.\", C[\"text_dim\"])\n        summ(\"\u2550\" * 50, C[\"border\"])\n\n        self._epr_progress_stop()\n        self._epr_set_status(\n            f\"COMPLETE \u2014 {passed}/{len(results)} steps passed\",\n            C[\"success\"] if failed == 0 else C[\"warning\"])\n\n        # Structured log\n        try:\n            lg = getattr(self, \"structured_logger\", None)\n            if lg:\n                lg.log(\"epr_full_auto_fix\", \"Full Auto Fix completed\", {\n                    \"passed\": passed, \"failed\": failed, \"steps\": len(results)})\n        except Exception:\n            pass\n\n    # \u2500\u2500 Connection Tester Methods \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_ping_host(self):\n        host = getattr(self, \"epr_host_var\", tk.StringVar()).get().strip()\n        if not host:\n            messagebox.showinfo(\"Host IP\", \"Host IP ya naam enter karo upar.\")\n            return\n        self._epr_submit(\"epr_ping\", self._do_epr_ping, host)\n\n    def _do_epr_ping(self, host):\n        self._epr_set_status(f\"Pinging {host}...\")\n        self._epr_diag(f\"\ud83d\udd0c Pinging {host}...\", C[\"text_dim\"])\n        out, rc = self._run_cmd(f\"ping -n 4 -w 1000 {host}\", timeout=12)\n        if rc == 0 and \"TTL=\" in out:\n            self._epr_diag(f\"  \u2705 Host reachable: {host}\", C[\"success\"])\n            self._epr_set_status(f\"\u2705 {host} is reachable\", C[\"success\"])\n        else:\n            self._epr_diag(f\"  \u274c Host NOT reachable: {host}\", C[\"error\"])\n            self._epr_set_status(f\"\u274c {host} unreachable \u2014 check IP/network\", C[\"error\"])\n\n    def _epr_test_smb(self):\n        host  = getattr(self, \"epr_host_var\",  tk.StringVar()).get().strip()\n        share = getattr(self, \"epr_share_var\", tk.StringVar()).get().strip()\n        if not host:\n            messagebox.showinfo(\"Host\", \"Host IP enter karo.\")\n            return\n        self._epr_submit(\"epr_smb_test\", self._do_epr_test_smb, host, share)\n\n    def _do_epr_test_smb(self, host, share):\n        self._epr_set_status(f\"Testing SMB: \\\\\\\\{host}...\")\n        self._epr_diag(f\"\ud83d\uddc2 Testing SMB share: \\\\\\\\{host}\\\\{share or '*'}\", C[\"text_dim\"])\n        unc = f\"\\\\\\\\{host}\" if not share else f\"\\\\\\\\{host}\\\\{share}\"\n        out, rc = self._run_cmd(f'net use \"{unc}\" /persistent:no', timeout=12)\n        if rc == 0 or \"completed\" in out.lower():\n            self._epr_diag(f\"  \u2705 SMB accessible: {unc}\", C[\"success\"])\n            self._epr_set_status(f\"\u2705 SMB OK: {unc}\", C[\"success\"])\n        else:\n            # Try listing\n            out2, rc2 = self._run_cmd(f'dir \"{unc}\"', timeout=8)\n            if rc2 == 0:\n                self._epr_diag(f\"  \u2705 SMB share visible: {unc}\", C[\"success\"])\n                self._epr_set_status(f\"\u2705 SMB OK\", C[\"success\"])\n            else:\n                self._epr_diag(f\"  \u274c SMB not accessible: {unc}\", C[\"error\"])\n                self._epr_diag(f\"     Result: {out[:120]}\", C[\"text_dim\"])\n                self._epr_set_status(f\"\u274c SMB failed \u2014 check sharing settings\", C[\"error\"])\n\n    def _epr_validate_printer(self):\n        host  = getattr(self, \"epr_host_var\",  tk.StringVar()).get().strip()\n        share = getattr(self, \"epr_share_var\", tk.StringVar()).get().strip()\n        if not host or not share:\n            messagebox.showinfo(\"Input\", \"Host IP aur Share Name dono enter karo.\")\n            return\n        self._epr_submit(\"epr_validate\", self._do_epr_validate_printer, host, share)\n\n    def _do_epr_validate_printer(self, host, share):\n        unc = f\"\\\\\\\\{host}\\\\{share}\"\n        self._epr_set_status(f\"Validating: {unc}...\")\n        self._epr_diag(f\"\ud83d\udda8 Validating printer path: {unc}\", C[\"text_dim\"])\n        out, rc = self._run_cmd(f'rundll32 printui.dll,PrintUIEntry /ga /n\"{unc}\"', timeout=15)\n        if rc == 0:\n            self._epr_diag(f\"  \u2705 Printer connection validated: {unc}\", C[\"success\"])\n            self._epr_set_status(f\"\u2705 Printer reachable: {unc}\", C[\"success\"])\n        else:\n            # Fallback: add printer via PowerShell\n            ps = f'Add-Printer -ConnectionName \"{unc}\" -ErrorAction SilentlyContinue; if ($?) {{ \"OK\" }} else {{ \"FAIL\" }}'\n            out2, _ = self._run_cmd(f'powershell -NoProfile -Command \"{ps}\"', timeout=20)\n            if \"OK\" in out2:\n                self._epr_diag(f\"  \u2705 Printer added via PowerShell: {unc}\", C[\"success\"])\n                self._epr_set_status(f\"\u2705 Printer added\", C[\"success\"])\n            else:\n                self._epr_diag(f\"  \u274c Could not connect to printer: {unc}\", C[\"error\"])\n                self._epr_set_status(f\"\u274c Printer not reachable \u2014 run FULL AUTO FIX\", C[\"error\"])\n\n    def _epr_reconnect_shared(self):\n        host  = getattr(self, \"epr_host_var\",  tk.StringVar()).get().strip()\n        share = getattr(self, \"epr_share_var\", tk.StringVar()).get().strip()\n        if not host or not share:\n            messagebox.showinfo(\"Input\", \"Host IP aur Share Name dono enter karo.\")\n            return\n        if not messagebox.askyesno(\"Reconnect Shared Printer\",\n                f\"Printer reconnect hoga:\\n\\\\\\\\{host}\\\\{share}\\n\\nContinue?\"):\n            return\n        self._epr_submit(\"epr_reconnect\", self._do_epr_reconnect_shared, host, share)\n\n    def _do_epr_reconnect_shared(self, host, share):\n        log = self._epr_log\n        unc = f\"\\\\\\\\{host}\\\\{share}\"\n        self._epr_set_status(f\"Reconnecting: {unc}...\")\n        log(f\"\ud83d\udd17 Reconnecting shared printer: {unc}\", C[\"accent4\"])\n\n        # Remove old connection\n        self._run_cmd(f'net use \"{unc}\" /delete /y', timeout=10)\n        log(\"  \u2139 Old connection removed\", C[\"text_dim\"])\n\n        # Firewall\n        self._run_cmd('netsh advfirewall firewall set rule group=\"File and Printer Sharing\" new enable=Yes profile=any')\n        log(\"  \u2705 Firewall rules: ON\", C[\"success\"])\n\n        # RPC fix\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                \"RpcAuthnLevelPrivacyEnabled\", 0, winreg.REG_DWORD)\n        except Exception:\n            self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\" /v RpcAuthnLevelPrivacyEnabled /t REG_DWORD /d 0 /f')\n        log(\"  \u2705 RPC setting: OK\", C[\"success\"])\n\n        # Reconnect\n        out, rc = self._run_cmd(f'net use \"{unc}\" /persistent:yes', timeout=15)\n        if rc == 0 or \"completed\" in out.lower():\n            log(f\"  \u2705 Connected: {unc}\", C[\"success\"])\n        else:\n            log(f\"  \u26a0 net use: {out[:120]}\", C[\"warning\"])\n\n        # Add as printer\n        ps = f'Add-Printer -ConnectionName \"{unc}\" -ErrorAction SilentlyContinue'\n        self._run_cmd(f'powershell -NoProfile -Command \"{ps}\"', timeout=20)\n        log(f\"  \u2705 Printer install attempted: {unc}\", C[\"success\"])\n\n        # Spooler restart\n        self._run_cmd(\"net stop spooler /y\"); time.sleep(1)\n        self._run_cmd(\"net start spooler\")\n        log(\"  \u2705 Spooler restarted\", C[\"success\"])\n        log(\"\u2705 Shared printer reconnect complete!\", C[\"success\"])\n        self._epr_set_status(\"\u2705 Reconnect complete\", C[\"success\"])\n\n    # \u2500\u2500 Firewall &amp; Network Discovery \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_firewall_fix(self):\n        self._epr_submit(\"epr_fw_fix\", self._do_epr_firewall_fix_silent)\n\n    def _do_epr_firewall_fix_silent(self):\n        self._epr_set_status(\"Applying firewall rules...\")\n        cmds = [\n            'netsh advfirewall firewall set rule group=\"File and Printer Sharing\" new enable=Yes profile=any',\n            'netsh advfirewall firewall set rule group=\"Network Discovery\" new enable=Yes profile=Private',\n            'netsh advfirewall firewall add rule name=\"EPR_SMB_In\" dir=in action=allow protocol=TCP localport=445 profile=any',\n            'netsh advfirewall firewall add rule name=\"EPR_SMB_Out\" dir=out action=allow protocol=TCP localport=445 profile=any',\n            'netsh advfirewall firewall add rule name=\"EPR_RPC_In\" dir=in action=allow protocol=TCP localport=135 profile=any',\n            'netsh advfirewall firewall add rule name=\"EPR_RAW_In\" dir=in action=allow protocol=TCP localport=9100 profile=any',\n            'netsh advfirewall firewall add rule name=\"EPR_NetBIOS_In\" dir=in action=allow protocol=TCP localport=139 profile=any',\n        ]\n        for cmd in cmds:\n            self._run_cmd(cmd, timeout=10)\n        self._epr_log(\"  \u2705 Firewall sharing rules applied\", C[\"success\"])\n        self._epr_set_status(\"\u2705 Firewall rules applied\", C[\"success\"])\n\n    def _epr_enable_netdiscovery(self):\n        self._epr_submit(\"epr_netdisc\", self._do_epr_enable_netdiscovery_silent)\n\n    def _do_epr_enable_netdiscovery_silent(self):\n        self._epr_set_status(\"Enabling network discovery...\")\n        self._run_cmd('netsh advfirewall firewall set rule group=\"Network Discovery\" new enable=Yes profile=Private')\n        # FD services\n        for svc in [\"FDResPub\", \"fdPHost\", \"SSDPSRV\", \"upnphost\"]:\n            self._run_cmd(f\"sc config {svc} start= auto\")\n            self._run_cmd(f\"net start {svc}\")\n        self._epr_log(\"  \u2705 Network discovery enabled + FD services started\", C[\"success\"])\n        self._epr_set_status(\"\u2705 Network discovery: ON\", C[\"success\"])\n\n    # \u2500\u2500 Network Share Validator \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_net_share_validator(self):\n        host  = getattr(self, \"epr_host_var\",  tk.StringVar()).get().strip()\n        share = getattr(self, \"epr_share_var\", tk.StringVar()).get().strip()\n        if not host:\n            messagebox.showinfo(\"Host\", \"Host IP enter karo.\")\n            return\n        self._epr_submit(\"epr_nsv\", self._do_epr_net_share_validator, host, share)\n\n    def _do_epr_net_share_validator(self, host, share):\n        log = self._epr_diag\n        self._epr_set_status(f\"Validating share: \\\\\\\\{host}...\")\n        log(f\"\ud83c\udf10 Network Share Validator: \\\\\\\\{host}\\\\{share or ''}\", C[\"accent4\"])\n\n        # Ping\n        out, rc = self._run_cmd(f\"ping -n 2 -w 1000 {host}\", timeout=8)\n        log(f\"  Ping: {'\u2705 OK' if (rc==0 and 'TTL=' in out) else '\u274c FAIL'}\", C[\"success\"] if (rc==0 and \"TTL=\" in out) else C[\"error\"])\n\n        # Port 445\n        ps445 = f\"Test-NetConnection -ComputerName {host} -Port 445 -InformationLevel Quiet 2&gt;$null\"\n        out445, _ = self._run_cmd(f'powershell -NoProfile -Command \"{ps445}\"', timeout=10)\n        log(f\"  Port 445: {'\u2705 Open' if 'True' in out445 else '\u274c Closed/Filtered'}\", C[\"success\"] if \"True\" in out445 else C[\"error\"])\n\n        # Port 139\n        ps139 = f\"Test-NetConnection -ComputerName {host} -Port 139 -InformationLevel Quiet 2&gt;$null\"\n        out139, _ = self._run_cmd(f'powershell -NoProfile -Command \"{ps139}\"', timeout=10)\n        log(f\"  Port 139: {'\u2705 Open' if 'True' in out139 else '\u26a0 Closed'}\", C[\"success\"] if \"True\" in out139 else C[\"warning\"])\n\n        # Share list\n        if share:\n            out_nu, rc_nu = self._run_cmd(f'net use \"\\\\\\\\{host}\\\\{share}\" /persistent:no', timeout=12)\n            log(f\"  Share: {'\u2705 Accessible' if (rc_nu==0 or 'completed' in out_nu.lower()) else '\u274c Not accessible'}\", C[\"success\"] if (rc_nu==0) else C[\"error\"])\n\n        self._epr_set_status(\"\u2705 Share validation done\", C[\"success\"])\n\n    # \u2500\u2500 Smart Spooler Recovery \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_smart_spooler(self):\n        if not messagebox.askyesno(\"Smart Spooler Recovery\",\n                \"Deep spooler repair:\\n\"\n                \"1. Stop spooler + dependents\\n\"\n                \"2. Clear spool directory\\n\"\n                \"3. Re-register spooler DLLs\\n\"\n                \"4. Repair spooler registry\\n\"\n                \"5. Restart spooler\\n\\nContinue?\"):\n            return\n        self._epr_submit(\"epr_smart_spooler\", self._do_epr_smart_spooler)\n\n    def _do_epr_smart_spooler(self):\n        log = self._epr_log\n        self._epr_set_status(\"Smart Spooler Recovery running...\")\n        log(\"\u2550\" * 48, C[\"border\"])\n        log(\"\u26a1 Smart Spooler Recovery\", C[\"accent4\"])\n\n        # Stop dependent services\n        for svc in [\"RpcSs\", \"SENS\"]:\n            pass   # don't stop critical services\n        self._run_cmd(\"net stop spooler /y\"); time.sleep(1)\n        log(\"  \u2705 Spooler stopped\", C[\"success\"])\n\n        # Clear spool directory\n        spool = Path(os.environ.get(\"SYSTEMROOT\", \"C:\\\\Windows\")) / \"System32\" / \"spool\" / \"PRINTERS\"\n        n = 0\n        for f in spool.glob(\"*\"):\n            try: f.unlink(); n += 1\n            except Exception: pass\n        log(f\"  \u2705 {n} spool files cleared\", C[\"success\"])\n\n        # Re-register DLLs\n        sys32 = os.path.join(os.environ.get(\"SYSTEMROOT\", \"C:\\\\Windows\"), \"System32\")\n        for dll in [\"localspl.dll\", \"spoolss.dll\", \"win32spl.dll\", \"winspool.drv\", \"ntprint.dll\"]:\n            p = os.path.join(sys32, dll)\n            if os.path.exists(p):\n                self._run_cmd(f'regsvr32 /s \"{p}\"')\n        log(\"  \u2705 Spooler DLLs re-registered\", C[\"success\"])\n\n        # Registry repair\n        self._run_cmd('sc config Spooler start= auto')\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\Spooler\" /v Start /t REG_DWORD /d 2 /f')\n\n        # Start spooler\n        self._run_cmd(\"net start spooler\"); time.sleep(2)\n        out, _ = self._run_cmd(\"sc query Spooler\", timeout=8)\n        ok = \"RUNNING\" in out\n        log(f\"  {'\u2705 Spooler: Running!' if ok else '\u274c Spooler failed to start'}\", C[\"success\"] if ok else C[\"error\"])\n        self.after(0, self._refresh_spooler_status)\n        self._epr_set_status(\"\u2705 Smart Spooler Recovery complete\" if ok else \"\u274c Spooler still failing\", C[\"success\"] if ok else C[\"error\"])\n\n    # \u2500\u2500 RPC + SMB Repair \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_rpc_smb_repair(self):\n        if not messagebox.askyesno(\"RPC + SMB Repair\",\n                \"This will:\\n\"\n                \"1. Set RpcAuthnLevelPrivacyEnabled = 0\\n\"\n                \"2. Set RestrictRemoteClients = 0\\n\"\n                \"3. Enable SMB signing optional\\n\"\n                \"4. Enable AllowInsecureGuestAuth\\n\"\n                \"5. Restart spooler\\n\\nContinue?\"):\n            return\n        self._epr_submit(\"epr_rpc_smb\", self._do_epr_rpc_smb)\n\n    def _do_epr_rpc_smb(self):\n        log = self._epr_log\n        self._epr_set_status(\"RPC + SMB Repair running...\")\n        log(\"\u2550\" * 48, C[\"border\"])\n        log(\"\ud83d\udd27 RPC + SMB Repair\", C[\"accent4\"])\n\n        self._epr_reg_backup(winreg.HKEY_LOCAL_MACHINE,\n            r\"SYSTEM\\CurrentControlSet\\Control\\Print\", \"RPC_backup\")\n\n        # RpcAuthnLevelPrivacyEnabled\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                \"RpcAuthnLevelPrivacyEnabled\", 0, winreg.REG_DWORD)\n        except Exception:\n            self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\" /v RpcAuthnLevelPrivacyEnabled /t REG_DWORD /d 0 /f')\n        log(\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0\", C[\"success\"])\n\n        # RestrictRemoteClients\n        self._run_cmd('reg add \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Rpc\" /v RestrictRemoteClients /t REG_DWORD /d 0 /f')\n        log(\"  \u2705 RestrictRemoteClients = 0\", C[\"success\"])\n\n        # SMB signing optional\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanServer\\\\Parameters\" /v RequireSecuritySignature /t REG_DWORD /d 0 /f')\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanWorkstation\\\\Parameters\" /v RequireSecuritySignature /t REG_DWORD /d 0 /f')\n        log(\"  \u2705 SMB signing: optional\", C[\"success\"])\n\n        # GuestAuth\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanWorkstation\\\\Parameters\" /v AllowInsecureGuestAuth /t REG_DWORD /d 1 /f')\n        log(\"  \u2705 AllowInsecureGuestAuth = 1\", C[\"success\"])\n\n        # Spooler restart\n        self._run_cmd(\"net stop spooler /y\"); time.sleep(1)\n        self._run_cmd(\"net start spooler\")\n        log(\"  \u2705 Spooler restarted\", C[\"success\"])\n        log(\"\u2705 RPC + SMB Repair complete!\", C[\"success\"])\n        self.after(0, self._refresh_spooler_status)\n        self._epr_set_status(\"\u2705 RPC + SMB Repair complete\", C[\"success\"])\n\n    # \u2500\u2500 Printer Cache Cleaner \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_cache_cleaner(self):\n        if not messagebox.askyesno(\"Printer Cache Cleaner\",\n                \"Remove corrupted printer cache:\\n\"\n                \"1. Stop spooler\\n\"\n                \"2. Clear PRINTERS spool folder\\n\"\n                \"3. Clear print driver cache\\n\"\n                \"4. Restart spooler\\n\\nContinue?\"):\n            return\n        self._epr_submit(\"epr_cache\", self._do_epr_cache_cleaner_silent)\n\n    def _do_epr_cache_cleaner_silent(self):\n        log = self._epr_log\n        self._epr_set_status(\"Cleaning printer cache...\")\n        log(\"\ud83d\uddd1 Printer Cache Cleaner running...\", C[\"accent4\"])\n\n        self._run_cmd(\"net stop spooler /y\"); time.sleep(1)\n\n        # Spool printers dir\n        spool = Path(os.environ.get(\"SYSTEMROOT\", \"C:\\\\Windows\")) / \"System32\" / \"spool\" / \"PRINTERS\"\n        n_spool = 0\n        for f in spool.glob(\"*\"):\n            try: f.unlink(); n_spool += 1\n            except Exception: pass\n        log(f\"  \u2705 Spool PRINTERS: {n_spool} files cleared\", C[\"success\"])\n\n        # Driver cache dir\n        driver_cache = Path(os.environ.get(\"SYSTEMROOT\", \"C:\\\\Windows\")) / \"System32\" / \"spool\" / \"drivers\"\n        n_cache = 0\n        for sub in [\"w32x86\", \"x64\", \"3\"]:\n            cache_dir = driver_cache / sub\n            if cache_dir.exists():\n                for f in cache_dir.glob(\"*.gpd\"):\n                    try: f.unlink(); n_cache += 1\n                    except Exception: pass\n\n        log(f\"  \u2705 Driver cache cleaned: {n_cache} files\", C[\"success\"])\n\n        self._run_cmd(\"net start spooler\"); time.sleep(1)\n        log(\"  \u2705 Spooler restarted\", C[\"success\"])\n        log(\"\u2705 Printer cache clean complete!\", C[\"success\"])\n        self.after(0, self._refresh_spooler_status)\n        self._epr_set_status(\"\u2705 Cache clean complete\", C[\"success\"])\n\n    # \u2500\u2500 Driver Compatibility Repair \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_driver_compat(self):\n        if not messagebox.askyesno(\"Driver Compatibility Repair\",\n                \"Fix x86/x64 driver mismatch:\\n\"\n                \"1. Detect OS architecture\\n\"\n                \"2. Check driver architecture\\n\"\n                \"3. Re-register driver DLLs\\n\"\n                \"4. Clear incompatible driver cache\\n\\nContinue?\"):\n            return\n        self._epr_submit(\"epr_driver_compat\", self._do_epr_driver_compat)\n\n    def _do_epr_driver_compat(self):\n        log = self._epr_log\n        self._epr_set_status(\"Driver Compatibility Repair...\")\n        log(\"\ud83d\udd27 Driver Compatibility Repair\", C[\"accent4\"])\n        arch_ok = self._do_epr_check_driver_arch()\n        # Re-register DLLs regardless\n        sys32 = os.path.join(os.environ.get(\"SYSTEMROOT\", \"C:\\\\Windows\"), \"System32\")\n        for dll in [\"localspl.dll\", \"spoolss.dll\", \"win32spl.dll\", \"ntprint.dll\"]:\n            p = os.path.join(sys32, dll)\n            if os.path.exists(p):\n                self._run_cmd(f'regsvr32 /s \"{p}\"')\n        log(\"  \u2705 DLLs re-registered\", C[\"success\"])\n        self._epr_set_status(\"\u2705 Driver compatibility repair done\", C[\"success\"])\n\n    def _do_epr_check_driver_arch(self):\n        \"\"\"Detect x86/x64 mismatch. Returns True if OK.\"\"\"\n        log = self._epr_log\n        try:\n            import platform as _platform\n            is_64 = _platform.architecture()[0] == \"64bit\"\n            log(f\"  \u2139 OS Architecture: {'x64' if is_64 else 'x86'}\", C[\"text_dim\"])\n\n            out, _ = self._run_cmd(\n                'powershell -NoProfile -Command \"Get-PrinterDriver | Select-Object Name,PrinterEnvironment | Format-Table -AutoSize\"',\n                timeout=20)\n            if out:\n                log(f\"  Driver list:\\n{out[:400]}\", C[\"text_dim\"])\n                if is_64 and \"Windows x86\" in out:\n                    log(\"  \u26a0 x86 driver on x64 OS \u2014 mismatch detected!\", C[\"warning\"])\n                    return False\n                else:\n                    log(\"  \u2705 Driver architecture: OK\", C[\"success\"])\n            return True\n        except Exception as e:\n            log(f\"  \u26a0 Arch check failed: {e}\", C[\"warning\"])\n            return True\n\n    # \u2500\u2500 Canon Compatibility Fix \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_canon_fix(self):\n        if not messagebox.askyesno(\"Canon Printer Compatibility Fix\",\n                \"Apply Canon-specific fixes:\\n\"\n                \"1. Canon CNUSB registry fix\\n\"\n                \"2. LimitBlankPasswordUse = 0\\n\"\n                \"3. Canon port registry\\n\"\n                \"4. Spooler restart\\n\\nContinue?\"):\n            return\n        self._epr_submit(\"epr_canon\", self._do_epr_canon_fix_silent)\n\n    def _do_epr_canon_fix_silent(self):\n        log = self._epr_log\n        self._epr_set_status(\"Canon Compatibility Fix...\")\n        log(\"\ud83d\udce1 Canon Printer Compatibility Fix\", C[\"accent4\"])\n\n        # Canon registry fixes\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                \"RpcAuthnLevelPrivacyEnabled\", 0, winreg.REG_DWORD)\n        except Exception:\n            self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\" /v RpcAuthnLevelPrivacyEnabled /t REG_DWORD /d 0 /f')\n\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Lsa\" /v LimitBlankPasswordUse /t REG_DWORD /d 0 /f')\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanWorkstation\\\\Parameters\" /v AllowInsecureGuestAuth /t REG_DWORD /d 1 /f')\n\n        # Canon-specific: disable WSD port issues\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                \"SNMPEnabled\", 0, winreg.REG_DWORD)\n        except Exception:\n            pass\n        log(\"  \u2705 Canon registry fixes applied\", C[\"success\"])\n\n        # Firewall for Canon WSD\n        self._run_cmd('netsh advfirewall firewall add rule name=\"Canon_WSD_In\" dir=in action=allow protocol=TCP localport=5357 profile=any')\n\n        # Spooler restart\n        self._run_cmd(\"net stop spooler /y\"); time.sleep(1)\n        self._run_cmd(\"net start spooler\")\n        log(\"  \u2705 Spooler restarted\", C[\"success\"])\n        log(\"\u2705 Canon compatibility fix complete!\", C[\"success\"])\n        self.after(0, self._refresh_spooler_status)\n        self._epr_set_status(\"\u2705 Canon fix applied\", C[\"success\"])\n\n    # \u2500\u2500 Point &amp; Print Repair \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_point_print_repair(self):\n        if not messagebox.askyesno(\"Point &amp; Print Repair\",\n                \"Fix Point &amp; Print restrictions:\\n\"\n                \"1. NoWarningNoElevationOnInstall = 1\\n\"\n                \"2. UpdatePromptSettings = 2\\n\"\n                \"3. RestrictDriverInstallationToAdministrators = 0\\n\"\n                \"4. Restricted = 0\\n\\nContinue?\"):\n            return\n        self._epr_submit(\"epr_pnp\", self._do_epr_point_print_repair_silent)\n\n    def _do_epr_point_print_repair_silent(self):\n        log = self._epr_log\n        self._epr_set_status(\"Point &amp; Print Repair...\")\n        log(\"\ud83d\udd11 Point &amp; Print Repair\", C[\"accent4\"])\n        pnp_path = r\"SOFTWARE\\Policies\\Microsoft\\Windows NT\\Printers\\PointAndPrint\"\n        self._epr_reg_backup(winreg.HKEY_LOCAL_MACHINE, pnp_path, \"PointAndPrint_backup\")\n\n        cmds = [\n            f'reg add \"HKLM\\\\{pnp_path}\" /v NoWarningNoElevationOnInstall /t REG_DWORD /d 1 /f',\n            f'reg add \"HKLM\\\\{pnp_path}\" /v UpdatePromptSettings /t REG_DWORD /d 2 /f',\n            f'reg add \"HKLM\\\\{pnp_path}\" /v RestrictDriverInstallationToAdministrators /t REG_DWORD /d 0 /f',\n            f'reg add \"HKLM\\\\{pnp_path}\" /v Restricted /t REG_DWORD /d 0 /f',\n            'reg add \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Printers\\\\PointAndPrint\" /v TrustedServers /t REG_DWORD /d 0 /f',\n        ]\n        for cmd in cmds:\n            self._run_cmd(cmd, timeout=8)\n        log(\"  \u2705 Point &amp; Print restrictions relaxed\", C[\"success\"])\n        self._epr_set_status(\"\u2705 Point &amp; Print repaired\", C[\"success\"])\n\n    # \u2500\u2500 Shared Printer Permission Repair \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_permission_repair(self):\n        if not messagebox.askyesno(\"Shared Printer Permission Repair\",\n                \"Repair shared printer permissions:\\n\"\n                \"1. LimitBlankPasswordUse = 0\\n\"\n                \"2. AllowInsecureGuestAuth = 1\\n\"\n                \"3. Enable Everyone print permission\\n\"\n                \"4. Repair ACL via PrintUI\\n\\nContinue?\"):\n            return\n        self._epr_submit(\"epr_perm\", self._do_epr_permission_repair)\n\n    def _do_epr_permission_repair(self):\n        log = self._epr_log\n        self._epr_set_status(\"Permission Repair running...\")\n        log(\"\ud83d\udd11 Shared Printer Permission Repair\", C[\"accent4\"])\n\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Lsa\" /v LimitBlankPasswordUse /t REG_DWORD /d 0 /f')\n        log(\"  \u2705 LimitBlankPasswordUse = 0\", C[\"success\"])\n\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanWorkstation\\\\Parameters\" /v AllowInsecureGuestAuth /t REG_DWORD /d 1 /f')\n        log(\"  \u2705 AllowInsecureGuestAuth = 1\", C[\"success\"])\n\n        # Grant Everyone print rights on all printers\n        ps = (\n            \"Get-Printer | ForEach-Object { \"\n            \"  $pName = $_.Name; \"\n            \"  try { \"\n            \"    $sd = Get-PrinterPermission -PrinterName $pName -ErrorAction SilentlyContinue; \"\n            \"    Write-Output \\\"OK:$pName\\\" \"\n            \"  } catch { Write-Output \\\"SKIP:$pName\\\" } \"\n            \"}\"\n        )\n        out, _ = self._run_cmd(f'powershell -NoProfile -Command \"{ps}\"', timeout=20)\n        log(f\"  Permissions checked: {out[:200]}\", C[\"text_dim\"])\n        log(\"  \u2705 Permissions reviewed (manual ACL may be needed for domain)\", C[\"success\"])\n        log(\"\u2705 Permission repair complete!\", C[\"success\"])\n        self._epr_set_status(\"\u2705 Permission repair done\", C[\"success\"])\n\n    # \u2500\u2500 Full Printer Reset \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_full_reset(self):\n        if not messagebox.askyesno(\"\u26a0 Full Printer Reset\",\n                \"NUCLEAR RESET \u2014 Removes all printers and drivers:\\n\\n\"\n                \"1. Remove ALL printers\\n\"\n                \"2. Remove ALL printer drivers\\n\"\n                \"3. Clear ALL spool data\\n\"\n                \"4. Reset spooler\\n\"\n                \"5. Re-enable default Windows printers\\n\\n\"\n                \"\u26a0 Use as LAST RESORT. You will need to reinstall printers.\\n\"\n                \"Continue?\"):\n            return\n        self._epr_submit(\"epr_full_reset\", self._do_epr_full_reset)\n\n    def _do_epr_full_reset(self):\n        log = self._epr_log\n        self._epr_set_status(\"Full Printer Reset \u2014 WARNING: removing all printers...\")\n        log(\"\u2501\" * 48, C[\"border\"])\n        log(\"\u26a0 FULL PRINTER RESET\", C[\"error\"])\n\n        # Remove all printers\n        ps_remove = (\n            \"Get-Printer | ForEach-Object { \"\n            \"  Remove-Printer -Name $_.Name -ErrorAction SilentlyContinue; \"\n            \"  Write-Output \\\"REMOVED:$($_.Name)\\\" \"\n            \"}\"\n        )\n        out_rem, _ = self._run_cmd(f'powershell -NoProfile -Command \"{ps_remove}\"', timeout=30)\n        n_removed = out_rem.count(\"REMOVED:\")\n        log(f\"  \u2705 {n_removed} printer(s) removed\", C[\"success\"])\n\n        # Stop spooler\n        self._run_cmd(\"net stop spooler /y\"); time.sleep(1)\n\n        # Clear spool\n        spool = Path(os.environ.get(\"SYSTEMROOT\", \"C:\\\\Windows\")) / \"System32\" / \"spool\" / \"PRINTERS\"\n        n_spool = 0\n        for f in spool.glob(\"*\"):\n            try: f.unlink(); n_spool += 1\n            except Exception: pass\n        log(f\"  \u2705 {n_spool} spool files cleared\", C[\"success\"])\n\n        # Remove printer registry entries\n        try:\n            key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\\Printers\",\n                0, winreg.KEY_ALL_ACCESS)\n            printers_to_del = []\n            i = 0\n            while True:\n                try:\n                    printers_to_del.append(winreg.EnumKey(key, i))\n                    i += 1\n                except OSError:\n                    break\n            for p in printers_to_del:\n                try:\n                    winreg.DeleteKey(key, p)\n                except Exception:\n                    pass\n            winreg.CloseKey(key)\n            log(f\"  \u2705 Registry printer entries removed: {len(printers_to_del)}\", C[\"success\"])\n        except Exception as e:\n            log(f\"  \u26a0 Registry cleanup: {e}\", C[\"warning\"])\n\n        # Restart spooler\n        self._run_cmd(\"sc config Spooler start= auto\")\n        self._run_cmd(\"net start spooler\"); time.sleep(1)\n        out_sp, _ = self._run_cmd(\"sc query Spooler\", timeout=8)\n        log(f\"  {'\u2705 Spooler: Running' if 'RUNNING' in out_sp else '\u274c Spooler stopped'}\", C[\"success\"] if \"RUNNING\" in out_sp else C[\"error\"])\n        log(\"\u2705 Full Printer Reset complete! Reinstall your printers.\", C[\"warning\"])\n        self.after(0, self._refresh_spooler_status)\n        self._epr_set_status(\"\u2705 Full reset done \u2014 reinstall printers now\", C[\"warning\"])\n\n    # \u2500\u2500 Error-Specific Fixes \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_fix_11b(self):\n        \"\"\"Quick error 0x0000011b fix \u2014 delegates to existing host fix.\"\"\"\n        if messagebox.askyesno(\"Fix 0x0000011b\",\n                \"Apply 0x0000011b fix (RpcAuthnLevelPrivacyEnabled = 0)?\\n\"\n                \"Registry backup will be made first.\\nContinue?\"):\n            self._epr_submit(\"epr_fix_11b\", self._do_epr_fix_11b)\n\n    def _do_epr_fix_11b(self):\n        log = self._epr_log\n        self._epr_set_status(\"Fixing 0x0000011b...\")\n        self._epr_reg_backup(winreg.HKEY_LOCAL_MACHINE,\n            r\"SYSTEM\\CurrentControlSet\\Control\\Print\", \"11b_backup\")\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                \"RpcAuthnLevelPrivacyEnabled\", 0, winreg.REG_DWORD)\n        except Exception:\n            self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\" /v RpcAuthnLevelPrivacyEnabled /t REG_DWORD /d 0 /f')\n\n        self._run_cmd('reg add \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Rpc\" /v RestrictRemoteClients /t REG_DWORD /d 0 /f')\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanServer\\\\Parameters\" /v RequireSecuritySignature /t REG_DWORD /d 0 /f')\n        self._run_cmd(\"net stop spooler /y\"); time.sleep(1)\n        self._run_cmd(\"net start spooler\")\n        log(\"\u2705 0x0000011b fix applied! (Restart PC for full effect)\", C[\"success\"])\n        self._epr_set_status(\"\u2705 0x0000011b fixed\", C[\"success\"])\n\n    def _epr_fix_7c(self):\n        \"\"\"Fix 0x0000007c \u2014 driver corruption.\"\"\"\n        if messagebox.askyesno(\"Fix 0x0000007c\",\n                \"Fix 0x0000007c (corrupt driver/spoolsv):\\n\"\n                \"1. Re-register spooler DLLs\\n\"\n                \"2. Run SFC /scannow\\n\"\n                \"3. Restart spooler\\n\\nContinue?\"):\n            self._epr_submit(\"epr_fix_7c\", self._do_epr_fix_7c)\n\n    def _do_epr_fix_7c(self):\n        log = self._epr_log\n        self._epr_set_status(\"Fixing 0x0000007c...\")\n        self._run_cmd(\"net stop spooler /y\"); time.sleep(1)\n        sys32 = os.path.join(os.environ.get(\"SYSTEMROOT\", \"C:\\\\Windows\"), \"System32\")\n        for dll in [\"localspl.dll\", \"spoolss.dll\", \"win32spl.dll\", \"ntprint.dll\", \"prnntfy.dll\"]:\n            p = os.path.join(sys32, dll)\n            if os.path.exists(p):\n                self._run_cmd(f'regsvr32 /s \"{p}\"')\n        log(\"  \u2705 Spooler DLLs re-registered\", C[\"success\"])\n        # SFC async - don't block\n        self._launch_job(\"sfc_scannow\", lambda: self._run_cmd(\"sfc /scannow\", timeout=300))\n        log(\"  \u2139 SFC /scannow running in background...\", C[\"text_dim\"])\n        self._run_cmd(\"net start spooler\"); time.sleep(1)\n        log(\"\u2705 0x0000007c fix applied!\", C[\"success\"])\n        self._epr_set_status(\"\u2705 0x0000007c fixed\", C[\"success\"])\n\n    def _epr_fix_709(self):\n        \"\"\"Quick 0x00000709 fix \u2014 delegates.\"\"\"\n        if messagebox.askyesno(\"Fix 0x00000709\",\n                \"Apply 0x00000709 fix (default printer set error)?\\n\"\n                \"Spooler + registry fix will run.\\nContinue?\"):\n            self._epr_submit(\"epr_fix_709\", self._do_fix_error_709_client)\n\n    def _epr_fix_access_denied(self):\n        \"\"\"Fix Access Denied printer errors.\"\"\"\n        if messagebox.askyesno(\"Fix Access Denied\",\n                \"Fix printer access denied:\\n\"\n                \"1. LimitBlankPasswordUse = 0\\n\"\n                \"2. AllowInsecureGuestAuth = 1\\n\"\n                \"3. Point &amp; Print relax\\n\\nContinue?\"):\n            self._epr_submit(\"epr_fix_access\", self._do_epr_fix_access_denied)\n\n    def _do_epr_fix_access_denied(self):\n        log = self._epr_log\n        self._epr_set_status(\"Fixing Access Denied...\")\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Lsa\" /v LimitBlankPasswordUse /t REG_DWORD /d 0 /f')\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanWorkstation\\\\Parameters\" /v AllowInsecureGuestAuth /t REG_DWORD /d 1 /f')\n        self._do_epr_point_print_repair_silent()\n        log(\"\u2705 Access denied fix applied!\", C[\"success\"])\n        self._epr_set_status(\"\u2705 Access denied fix done\", C[\"success\"])\n\n    def _epr_fix_rpc_unavail(self):\n        \"\"\"Fix RPC server unavailable.\"\"\"\n        if messagebox.askyesno(\"Fix RPC Unavailable\",\n                \"Fix 'RPC server unavailable':\\n\"\n                \"1. Start RpcSs, RpcEptMapper\\n\"\n                \"2. RpcAuthnLevelPrivacyEnabled = 0\\n\"\n                \"3. Restart spooler\\n\\nContinue?\"):\n            self._epr_submit(\"epr_fix_rpc\", self._do_epr_fix_rpc_unavail)\n\n    def _do_epr_fix_rpc_unavail(self):\n        log = self._epr_log\n        self._epr_set_status(\"Fixing RPC Unavailable...\")\n        for svc in [\"RpcSs\", \"RpcEptMapper\", \"DcomLaunch\"]:\n            self._run_cmd(f\"sc start {svc}\")\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                \"RpcAuthnLevelPrivacyEnabled\", 0, winreg.REG_DWORD)\n        except Exception:\n            self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\" /v RpcAuthnLevelPrivacyEnabled /t REG_DWORD /d 0 /f')\n        self._run_cmd(\"net stop spooler /y\"); time.sleep(1)\n        self._run_cmd(\"net start spooler\")\n        log(\"\u2705 RPC Unavailable fix applied!\", C[\"success\"])\n        self._epr_set_status(\"\u2705 RPC fix done\", C[\"success\"])\n\n    def _epr_fix_driver_missing(self):\n        \"\"\"Fix Driver unavailable/missing.\"\"\"\n        if messagebox.askyesno(\"Fix Driver Missing\",\n                \"Fix 'Driver unavailable':\\n\"\n                \"1. Re-register driver DLLs\\n\"\n                \"2. Re-register ntprint.dll\\n\"\n                \"3. Trigger driver store cleanup\\n\\nContinue?\"):\n            self._epr_submit(\"epr_fix_driver\", self._do_epr_fix_driver_missing)\n\n    def _do_epr_fix_driver_missing(self):\n        log = self._epr_log\n        self._epr_set_status(\"Fixing Driver Missing...\")\n        self._run_cmd(\"net stop spooler /y\"); time.sleep(1)\n        sys32 = os.path.join(os.environ.get(\"SYSTEMROOT\", \"C:\\\\Windows\"), \"System32\")\n        for dll in [\"ntprint.dll\", \"localspl.dll\", \"spoolss.dll\", \"win32spl.dll\"]:\n            p = os.path.join(sys32, dll)\n            if os.path.exists(p):\n                self._run_cmd(f'regsvr32 /s \"{p}\"')\n        # Trigger PnPUtil cleanup\n        self._run_cmd(\"pnputil /scan-devices\", timeout=30)\n        self._run_cmd(\"net start spooler\")\n        log(\"\u2705 Driver missing fix applied!\", C[\"success\"])\n        self._epr_set_status(\"\u2705 Driver fix done\", C[\"success\"])\n\n    def _epr_fix_path_not_found(self):\n        \"\"\"Fix Network path not found.\"\"\"\n        if messagebox.askyesno(\"Fix Path Not Found\",\n                \"Fix 'Network path not found':\\n\"\n                \"1. Enable NetBIOS over TCP/IP\\n\"\n                \"2. Enable lmhosts service\\n\"\n                \"3. Flush DNS\\n\"\n                \"4. Fix routing\\n\\nContinue?\"):\n            self._epr_submit(\"epr_fix_path\", self._do_epr_fix_path_not_found)\n\n    def _do_epr_fix_path_not_found(self):\n        log = self._epr_log\n        self._epr_set_status(\"Fixing Path Not Found...\")\n        # Enable lmhosts\n        self._run_cmd(\"sc config lmhosts start= auto\")\n        self._run_cmd(\"net start lmhosts\")\n        # Flush DNS\n        self._run_cmd(\"ipconfig /flushdns\")\n        self._run_cmd(\"ipconfig /registerdns\")\n        # NetBIOS over TCP/IP via registry\n        try:\n            key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Services\\NetBT\\Parameters\\Interfaces\",\n                0, winreg.KEY_READ)\n            i = 0\n            while True:\n                try:\n                    sub = winreg.EnumKey(key, i)\n                    i += 1\n                    try:\n                        sub_key = winreg.OpenKey(key, sub, 0, winreg.KEY_SET_VALUE)\n                        winreg.SetValueEx(sub_key, \"NetbiosOptions\", 0, winreg.REG_DWORD, 0)\n                        winreg.CloseKey(sub_key)\n                    except Exception:\n                        pass\n                except OSError:\n                    break\n            winreg.CloseKey(key)\n        except Exception:\n            pass\n        log(\"  \u2705 NetBIOS over TCP/IP enabled\", C[\"success\"])\n        log(\"  \u2705 DNS flushed + registered\", C[\"success\"])\n        log(\"\u2705 Path not found fix applied!\", C[\"success\"])\n        self._epr_set_status(\"\u2705 Path fix done\", C[\"success\"])\n\n    # \u2500\u2500 Smart RPC Switcher \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_check_rpc_setting(self):\n        self._epr_submit(\"epr_check_rpc\", self._do_epr_check_rpc_setting)\n\n    def _do_epr_check_rpc_setting(self):\n        try:\n            key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\", 0, winreg.KEY_READ)\n            try:\n                val, _ = winreg.QueryValueEx(key, \"RpcAuthnLevelPrivacyEnabled\")\n                status = f\"RpcAuthnLevelPrivacyEnabled = {val} ({'SAFE for sharing' if val == 0 else 'MAY BREAK printer sharing (error 0x0000011b)'})\"\n                color = C[\"success\"] if val == 0 else C[\"warning\"]\n            except FileNotFoundError:\n                status = \"RpcAuthnLevelPrivacyEnabled not set (system default \u2014 may be 1 on patched Win11)\"\n                color = C[\"warning\"]\n            winreg.CloseKey(key)\n        except Exception as e:\n            status = f\"Cannot read RPC setting: {e}\"\n            color = C[\"error\"]\n\n        def _update(s=status, c=color):\n            lbl = getattr(self, \"epr_rpc_status_lbl\", None)\n            if lbl:\n                lbl.config(text=s, fg=c)\n        self.after(0, _update)\n        self._epr_diag(f\"RPC check: {status}\", color)\n\n    def _epr_smart_rpc_fix(self):\n        \"\"\"Smart RPC fix: try setting = 0, validate, rollback if broken.\"\"\"\n        if not messagebox.askyesno(\"Smart RPC Fix\",\n                \"Smart RPC Privacy Switcher:\\n\\n\"\n                \"1. Backup current RPC setting\\n\"\n                \"2. Set RpcAuthnLevelPrivacyEnabled = 0\\n\"\n                \"3. Restart spooler\\n\"\n                \"4. Validate printer connectivity\\n\"\n                \"5. Auto-rollback if validation fails\\n\\n\"\n                \"This is the safest way to fix error 0x0000011b.\\n\"\n                \"Continue?\"):\n            return\n        self._epr_submit(\"epr_smart_rpc\", self._do_epr_smart_rpc_fix)\n\n    def _do_epr_smart_rpc_fix(self):\n        log = self._epr_log\n        self._epr_set_status(\"Smart RPC Fix \u2014 backing up...\")\n        log(\"\u2550\" * 48, C[\"border\"])\n        log(\"\u26a1 Smart RPC Privacy Switcher\", C[\"accent4\"])\n\n        # Step 1: Read current value\n        current_val = 1  # assume restricted\n        try:\n            key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\", 0, winreg.KEY_READ)\n            try:\n                current_val, _ = winreg.QueryValueEx(key, \"RpcAuthnLevelPrivacyEnabled\")\n            except FileNotFoundError:\n                current_val = 1  # not set = default 1\n            winreg.CloseKey(key)\n        except Exception:\n            pass\n        log(f\"  Current value: RpcAuthnLevelPrivacyEnabled = {current_val}\", C[\"text_dim\"])\n\n        # Step 2: Backup\n        backup_file = self._epr_reg_backup(winreg.HKEY_LOCAL_MACHINE,\n            r\"SYSTEM\\CurrentControlSet\\Control\\Print\", \"SmartRPC_backup\")\n        log(f\"  \u2705 Backed up: {backup_file}\", C[\"text_dim\"])\n\n        # Step 3: Set = 0\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                \"RpcAuthnLevelPrivacyEnabled\", 0, winreg.REG_DWORD)\n            log(\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0 (set)\", C[\"success\"])\n        except Exception:\n            self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\" /v RpcAuthnLevelPrivacyEnabled /t REG_DWORD /d 0 /f')\n            log(\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0 (via reg cmd)\", C[\"success\"])\n\n        # Step 4: Restart spooler\n        self._run_cmd(\"net stop spooler /y\"); time.sleep(1)\n        self._run_cmd(\"net start spooler\"); time.sleep(1)\n        out_sp, _ = self._run_cmd(\"sc query Spooler\", timeout=8)\n        spooler_ok = \"RUNNING\" in out_sp\n        log(f\"  {'\u2705 Spooler: Running' if spooler_ok else '\u274c Spooler failed'}\", C[\"success\"] if spooler_ok else C[\"error\"])\n\n        # Step 5: Validate\n        host = getattr(self, \"epr_host_var\", tk.StringVar()).get().strip()\n        validated = False\n        if host and spooler_ok:\n            out_ping, rc_ping = self._run_cmd(f\"ping -n 2 -w 1000 {host}\", timeout=8)\n            validated = rc_ping == 0 and \"TTL=\" in out_ping\n            log(f\"  {'\u2705 Host reachable: ' + host if validated else '\u26a0 Host not reachable (or not set)'}\", C[\"success\"] if validated else C[\"warning\"])\n\n        if spooler_ok:\n            log(\"\u2705 Smart RPC fix applied successfully!\", C[\"success\"])\n            log(\"   \u25ba Try your printer now. Restart PC if still failing.\", C[\"text_dim\"])\n            self._epr_set_status(\"\u2705 Smart RPC fix done \u2014 test printer now\", C[\"success\"])\n        else:\n            # Rollback\n            log(\"\u26a0 Spooler failed \u2014 rolling back RPC setting...\", C[\"warning\"])\n            try:\n                self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                    r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                    \"RpcAuthnLevelPrivacyEnabled\", current_val, winreg.REG_DWORD)\n                log(f\"  \u2705 Rollback: RpcAuthnLevelPrivacyEnabled = {current_val}\", C[\"warning\"])\n            except Exception:\n                if backup_file:\n                    self._run_cmd(f'reg import \"{backup_file}\"', timeout=10)\n                    log(\"  \u2705 Registry restored from backup\", C[\"warning\"])\n            self._run_cmd(\"net start spooler\")\n            log(\"\u2705 Rollback complete.\", C[\"warning\"])\n            self._epr_set_status(\"\u26a0 Rolled back \u2014 spooler issue detected\", C[\"warning\"])\n\n        self.after(0, self._do_epr_check_rpc_setting)\n        self.after(0, self._refresh_spooler_status)\n\n\n    def _host_mega_auto_fix(self):\n        sel = self.printer_tree.selection()\n        printer_name = \"\"\n        if sel and self._printer_data:\n            idx = self.printer_tree.index(sel[0])\n            if idx &lt; len(self._printer_data):\n                printer_name = self._printer_data[idx][2][\"name\"]\n\n        confirm_msg = (\n            \"\ud83d\ude80 HOST MEGA AUTO-FIX\\n\\n\"\n            \"Ye saari settings ek saath apply hongi HOST pe:\\n\\n\"\n            \"  \u2705 Ports open: 445/139/137/138/135/9100/631/515\\n\"\n            \"  \u2705 Security: Network Discovery + F&amp;P Rules + Private\\n\"\n            \"  \u2705 Password Protected Sharing \u2192 OFF\\n\"\n            \"  \u2705 SMB signing \u2192 Optional\\n\"\n            \"  \u2705 Registry: AutoShare + IRPStack + LimitBlank + DisableWeb\\n\"\n            \"  \u2705 Services: Spooler + LanmanServer + Workstation + NetBIOS + FD\\n\"\n            \"  \u2705 Error 0x0000709 Fix\\n\"\n            \"  \u2705 Error 0x0000011b Fix\\n\"\n        )\n        if printer_name:\n            confirm_msg += f\"\\n  \u2705 Printer '{printer_name}' share karega\\n\"\n        confirm_msg += \"\\n\u26a0 Sirf trusted private LAN pe karo!\\nContinue karein?\"\n\n        if not messagebox.askyesno(\"\ud83d\ude80 HOST Mega Auto-Fix\", confirm_msg):\n            return\n\n        self._sharing_log(\"\u2550\"*60, C[\"border\"])\n        self._sharing_log(\"\ud83d\ude80 [HOST] MEGA AUTO-FIX STARTING \u2014 SABKUCH EK SAATH\", C[\"error\"])\n        self._sharing_log(\"\u2550\"*60, C[\"border\"])\n\n        def _mega():\n            # 1. Ports\n            self._sharing_log(\"\\n\ud83d\udccc PORTS open kar raha hoon...\", C[\"accent4\"])\n            self._do_host_open_ports()\n\n            # 2. Security\n            self._sharing_log(\"\\n\ud83d\udccc Security fix...\", C[\"accent4\"])\n            self._do_host_security_fix(disable_pwd_sharing=True)\n\n            # 3. Registry\n            self._sharing_log(\"\\n\ud83d\udccc Registry changes...\", C[\"accent4\"])\n            self._do_host_registry_fix()\n\n            # 4. Services\n            self._sharing_log(\"\\n\ud83d\udccc Services enable...\", C[\"accent4\"])\n            self._do_host_enable_services()\n\n            # 5. Error 709 fix\n            self._sharing_log(\"\\n\ud83d\udccc Error 0x0000709 fix...\", C[\"accent4\"])\n            self._do_fix_error_709_host()\n\n            # 6. Error 11b fix\n            self._sharing_log(\"\\n\ud83d\udccc Error 0x0000011b fix...\", C[\"accent4\"])\n            self._do_fix_error_11b_host()\n\n            # 7. Share selected printer if any\n            if printer_name:\n                share_name = printer_name.replace(\" \", \"_\")[:20]\n                self._sharing_log(f\"\\n\ud83d\udccc Printer '{printer_name}' share kar raha hoon...\", C[\"accent4\"])\n                self._do_host_auto_share(printer_name, share_name)\n\n            self._sharing_log(\"\\n\" + \"\u2550\"*60, C[\"border\"])\n            self._sharing_log(\"\ud83c\udf89 HOST MEGA AUTO-FIX COMPLETE!\", C[\"success\"])\n            self._sharing_log(\"   \u25ba CLIENT pe bhi Mega Fix run karo!\", C[\"warning\"])\n            self._sharing_log(\"   \u25ba Phir HOST restart karo for all changes to take effect.\", C[\"text_dim\"])\n            self.after(0, lambda: messagebox.showinfo(\n                \"\ud83c\udf89 HOST Mega Fix Complete!\",\n                \"\u2705 HOST ki saari printer sharing settings apply ho gayi!\\n\\n\"\n                \"Ab CLIENT computer pe jaao aur:\\n\"\n                \"  \u2192 Sharing Center \u2192 CLIENT tab\\n\"\n                \"  \u2192 '\ud83d\ude80 CLIENT: SABKUCH AUTO-FIX' button dabao\\n\\n\"\n                \"Phir dono machines restart karo.\"))\n\n        self._launch_job(\"mega_task\", _mega)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \ud83d\ude80 MEGA AUTO-FIX \u2014 CLIENT (Sabkuch ek saath)\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _client_mega_auto_fix(self):\n        if not messagebox.askyesno(\"\ud83d\ude80 CLIENT Mega Auto-Fix\",\n                \"\ud83d\ude80 CLIENT MEGA AUTO-FIX\\n\\n\"\n                \"Ye saari settings ek saath apply hongi CLIENT pe:\\n\\n\"\n                \"  \u2705 Ports open: 445/139/137/138/135/9100/631/515\\n\"\n                \"  \u2705 Security: Network Discovery + F&amp;P Rules + Private\\n\"\n                \"  \u2705 SMB client signing \u2192 Optional\\n\"\n                \"  \u2705 Registry: GuestAuth + LimitBlank + SMB + Point&amp;Print\\n\"\n                \"  \u2705 Services: Spooler + Workstation + NetBIOS + FD + SSDP\\n\"\n                \"  \u2705 Error 0x0000709 Fix\\n\"\n                \"  \u2705 Error 0x0000011b Fix\\n\\n\"\n                \"\u26a0 Sirf trusted private LAN pe karo!\\nContinue karein?\"):\n            return\n\n        self._sharing_log(\"\u2550\"*60, C[\"border\"])\n        self._sharing_log(\"\ud83d\ude80 [CLIENT] MEGA AUTO-FIX STARTING \u2014 SABKUCH EK SAATH\", C[\"error\"])\n        self._sharing_log(\"\u2550\"*60, C[\"border\"])\n\n        def _mega():\n            # 1. Ports\n            self._sharing_log(\"\\n\ud83d\udccc PORTS open kar raha hoon...\", C[\"accent4\"])\n            self._do_client_open_ports()\n\n            # 2. Security\n            self._sharing_log(\"\\n\ud83d\udccc Security fix...\", C[\"accent4\"])\n            self._do_client_security_fix()\n\n            # 3. Registry\n            self._sharing_log(\"\\n\ud83d\udccc Registry changes...\", C[\"accent4\"])\n            self._do_client_registry_fix()\n\n            # 4. Services\n            self._sharing_log(\"\\n\ud83d\udccc Services enable...\", C[\"accent4\"])\n            services = [\n                (\"Spooler\",          \"Print Spooler\"),\n                (\"LanmanWorkstation\",\"Workstation (Network Redirector)\"),\n                (\"lmhosts\",          \"TCP/IP NetBIOS Helper\"),\n                (\"fdPHost\",          \"Function Discovery Provider Host\"),\n                (\"SSDPSRV\",          \"SSDP Discovery\"),\n            ]\n            for svc, display in services:\n                self._run_cmd(f'sc config \"{svc}\" start= auto')\n                self._run_cmd(f'sc start \"{svc}\"')\n                self._sharing_log(f\"  \u2705 {display} \u2192 Auto+Started\", C[\"success\"])\n\n            # 5. Error 709 fix\n            self._sharing_log(\"\\n\ud83d\udccc Error 0x0000709 fix...\", C[\"accent4\"])\n            self._do_fix_error_709_client()\n\n            # 6. Error 11b fix\n            self._sharing_log(\"\\n\ud83d\udccc Error 0x0000011b fix...\", C[\"accent4\"])\n            self._do_fix_error_11b_client()\n\n            self._sharing_log(\"\\n\" + \"\u2550\"*60, C[\"border\"])\n            self._sharing_log(\"\ud83c\udf89 CLIENT MEGA AUTO-FIX COMPLETE!\", C[\"success\"])\n            self._sharing_log(\"   \u25ba Ab 'Host se Printer Connect Karo' button se printer add karo.\", C[\"text_dim\"])\n            self.after(0, lambda: messagebox.showinfo(\n                \"\ud83c\udf89 CLIENT Mega Fix Complete!\",\n                \"\u2705 CLIENT ki saari printer sharing settings apply ho gayi!\\n\\n\"\n                \"Ab printer connect karne ke liye:\\n\"\n                \"  \u2192 'Host ke Shared Printer se Connect Karo' button dabao\\n\"\n                \"  \u2192 Host IP aur Share Name dalo\\n\\n\"\n                \"Agar abhi bhi error aaye \u2014 dono machines restart karo.\"))\n\n        self._launch_job(\"mega_task\", _mega)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \ud83d\udcbb CLIENT COMPUTER \u2014 PRINTER SHARING METHODS\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _client_open_ports(self):\n        if not messagebox.askyesno(\"Client: Port Fix\",\n                \"CLIENT computer pe ye ports open honge:\\n\\n\"\n                \"\u2022 445 TCP/UDP  \u2014 SMB access\\n\"\n                \"\u2022 139 TCP      \u2014 NetBIOS Session\\n\"\n                \"\u2022 137 UDP      \u2014 NetBIOS Name\\n\"\n                \"\u2022 138 UDP      \u2014 NetBIOS Datagram\\n\"\n                \"\u2022 135 TCP      \u2014 RPC\\n\\n\"\n                \"\u26a0 Private/trusted network pe karo!\\nContinue karein?\"):\n            return\n        self._sharing_log(\"\u2550\"*56, C[\"border\"])\n        self._sharing_log(\"\ud83d\udd0c [CLIENT] Ports khol raha hoon...\", C[\"accent2\"])\n        self._launch_job(\"client_open_ports\", self._do_client_open_ports)\n\n    def _do_client_open_ports(self):\n        ports = [\n            (445,  \"TCP\", \"SmbClient-TCP\"),\n            (445,  \"UDP\", \"SmbClient-UDP\"),\n            (139,  \"TCP\", \"NetBIOS-Sess-Client\"),\n            (137,  \"UDP\", \"NetBIOS-Name-Client\"),\n            (138,  \"UDP\", \"NetBIOS-Dgm-Client\"),\n            (135,  \"TCP\", \"RPC-Client\"),\n        ]\n        for port, proto, name in ports:\n            cmd = (f'netsh advfirewall firewall add rule '\n                   f'name=\"GodawariClient_{name}\" '\n                   f'dir=in action=allow protocol={proto} '\n                   f'localport={port} profile=any')\n            _, rc = self._run_cmd(cmd)\n            self._sharing_log(\n                f\"  {'\u2705' if rc==0 else '\u26a0'} Port {port}/{proto} ({name})\",\n                C[\"success\"] if rc == 0 else C[\"warning\"])\n        self._run_cmd(\n            'netsh advfirewall firewall set rule '\n            'group=\"File and Printer Sharing\" new enable=Yes profile=any')\n        self._sharing_log(\"  \u2705 File &amp; Printer Sharing rules (Client) \u2192 ON\", C[\"success\"])\n        self._sharing_log(\"\u2705 [CLIENT] Port fix complete!\", C[\"success\"])\n\n    def _client_security_fix(self):\n        if not messagebox.askyesno(\"Client: Security &amp; Firewall Fix\",\n                \"CLIENT security changes:\\n\\n\"\n                \"\u2022 Network Discovery \u2192 Enable\\n\"\n                \"\u2022 File &amp; Printer Sharing rules \u2192 ON\\n\"\n                \"\u2022 Network profile \u2192 Private\\n\"\n                \"\u2022 SMB client signing \u2192 Optional\\n\"\n                \"\u2022 Point &amp; Print driver settings\\n\\n\"\n                \"Continue karein?\"):\n            return\n        self._sharing_log(\"\u2550\"*56, C[\"border\"])\n        self._sharing_log(\"\ud83d\udd12 [CLIENT] Security fix chal raha hai...\", C[\"accent2\"])\n        self._launch_job(\"client_security_fix\", self._do_client_security_fix)\n\n    def _do_client_security_fix(self):\n        # Network Discovery\n        self._run_cmd(\n            'netsh advfirewall firewall set rule group=\"Network Discovery\" '\n            'new enable=Yes profile=private')\n        self._sharing_log(\"  \u2705 Network Discovery \u2192 ON\", C[\"success\"])\n\n        # F&amp;P Sharing rules\n        self._run_cmd(\n            'netsh advfirewall firewall set rule '\n            'group=\"File and Printer Sharing\" new enable=Yes profile=any')\n        self._sharing_log(\"  \u2705 F&amp;P Sharing rules \u2192 ON\", C[\"success\"])\n\n        # Private profile\n        self._run_cmd('powershell -Command \"Set-NetConnectionProfile -NetworkCategory Private\"')\n        self._sharing_log(\"  \u2705 Network profile \u2192 Private\", C[\"success\"])\n\n        # SMB client signing \u2014 optional\n        self._run_cmd(\n            'reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanWorkstation\\\\Parameters\" '\n            '/v RequireSecuritySignature /t REG_DWORD /d 0 /f')\n        self._run_cmd(\n            'reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanWorkstation\\\\Parameters\" '\n            '/v EnableSecuritySignature /t REG_DWORD /d 1 /f')\n        self._sharing_log(\"  \u2705 SMB client signature \u2192 Optional\", C[\"success\"])\n\n        # Point &amp; Print \u2014 relax for easier driver install\n        self._run_cmd(\n            'reg add \"HKLM/SOFTWARE/Policies/Microsoft/Windows NT/Printers/PointAndPrint\" '\n            '/v NoWarningNoElevationOnInstall /t REG_DWORD /d 1 /f')\n        self._run_cmd(\n            'reg add \"HKLM/SOFTWARE/Policies/Microsoft/Windows NT/Printers/PointAndPrint\" '\n            '/v UpdatePromptSettings /t REG_DWORD /d 2 /f')\n        self._sharing_log(\"  \u2705 Point &amp; Print settings configured\", C[\"success\"])\n        self._sharing_log(\"\u2705 [CLIENT] Security fix complete!\", C[\"success\"])\n\n    def _client_registry_fix(self):\n        if not messagebox.askyesno(\"Client: Registry Changes\",\n                \"CLIENT registry changes:\\n\\n\"\n                \"\u2022 AllowInsecureGuestAuth = 1\\n\"\n                \"  (Guest/no-password shares access)\\n\"\n                \"\u2022 LimitBlankPasswordUse  = 0\\n\"\n                \"  (Blank password se connect)\\n\"\n                \"\u2022 RequireSecuritySignature = 0\\n\"\n                \"  (SMB signing optional on client)\\n\"\n                \"\u2022 Point &amp; Print restrictions relax\\n\\n\"\n                \"\u26a0 Sirf trusted network pe karo!\\nContinue karein?\"):\n            return\n        self._sharing_log(\"\u2550\"*56, C[\"border\"])\n        self._sharing_log(\"\ud83d\udddd [CLIENT] Registry changes apply kar raha hoon...\", C[\"accent2\"])\n        self._launch_job(\"client_registry_fix\", self._do_client_registry_fix)\n\n    def _do_client_registry_fix(self):\n        changes = [\n            (winreg.HKEY_LOCAL_MACHINE,\n             r\"SYSTEM\\CurrentControlSet\\Services\\LanmanWorkstation\\Parameters\",\n             \"AllowInsecureGuestAuth\", 1, winreg.REG_DWORD),\n            (winreg.HKEY_LOCAL_MACHINE,\n             r\"SYSTEM\\CurrentControlSet\\Control\\Lsa\",\n             \"LimitBlankPasswordUse\", 0, winreg.REG_DWORD),\n            (winreg.HKEY_LOCAL_MACHINE,\n             r\"SYSTEM\\CurrentControlSet\\Services\\LanmanWorkstation\\Parameters\",\n             \"RequireSecuritySignature\", 0, winreg.REG_DWORD),\n        ]\n        for hive, path, name, val, typ in changes:\n            try:\n                self._reg_set(hive, path, name, val, typ)\n                self._sharing_log(f\"  \u2705 {name} = {val}\", C[\"success\"])\n            except Exception as e:\n                self._sharing_log(f\"  \u26a0 {name}: {e}\", C[\"warning\"])\n\n        # Point &amp; Print via reg commands\n        for cmd in [\n            'reg add \"HKLM/SOFTWARE/Policies/Microsoft/Windows NT/Printers/PointAndPrint\" '\n            '/v RestrictDriverInstallationToAdministrators /t REG_DWORD /d 0 /f',\n            'reg add \"HKLM/SOFTWARE/Policies/Microsoft/Windows NT/Printers/PointAndPrint\" '\n            '/v NoWarningNoElevationOnInstall /t REG_DWORD /d 1 /f',\n            'reg add \"HKLM/SOFTWARE/Policies/Microsoft/Windows NT/Printers/PointAndPrint\" '\n            '/v UpdatePromptSettings /t REG_DWORD /d 2 /f',\n        ]:\n            self._run_cmd(cmd)\n        self._sharing_log(\"  \u2705 Point &amp; Print registry \u2192 configured\", C[\"success\"])\n        self._sharing_log(\"\u2705 [CLIENT] Registry changes complete!\", C[\"success\"])\n        self._sharing_log(\"   \u26a0 Restart recommended.\", C[\"warning\"])\n\n    def _client_connect_printer(self):\n        \"\"\"CLIENT: Dialog to connect to HOST's shared printer.\"\"\"\n        dlg = tk.Toplevel(self)\n        dlg.title(\"\ud83d\udda8 Client \u2014 Host se Shared Printer Connect Karo\")\n        dlg.geometry(\"540x470\")\n        dlg.configure(bg=C[\"bg\"])\n        dlg.grab_set()\n\n        tk.Label(dlg, text=\"\ud83d\udda8  Client: Host se Printer Connect Karo\",\n                 font=FONTS[\"subhead\"], fg=C[\"accent2\"], bg=C[\"bg\"]).pack(\n                 pady=(16,4), padx=20)\n        tk.Label(dlg,\n                 text=\"Host PC ka naam/IP aur Printer Share Name daalein\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"]).pack(padx=20)\n\n        info = tk.Frame(dlg, bg=C[\"card\"])\n        info.pack(fill=\"x\", padx=20, pady=8)\n\n        fields = {}\n        field_defs = [\n            (\"Host PC Name / IP:\",   \"host\",  \"e.g. 192.168.1.5  ya  OFFICPC\",  False),\n            (\"Printer Share Name:\",  \"share\", \"e.g. HP_LaserJet\",                False),\n            (\"Username (optional):\", \"user\",  \"khali chhod sakte hain\",           False),\n            (\"Password (optional):\", \"pwd\",   \"khali chhod sakte hain\",           True),\n        ]\n        for lbl, key, placeholder, secret in field_defs:\n            row = tk.Frame(info, bg=C[\"card\"])\n            row.pack(fill=\"x\", pady=4, padx=8)\n            tk.Label(row, text=lbl, font=FONTS[\"body\"], fg=C[\"text\"],\n                     bg=C[\"card\"], width=22, anchor=\"w\").pack(side=\"left\")\n            e = tk.Entry(row, font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"],\n                         insertbackground=C[\"text\"], relief=\"flat\", bd=4,\n                         width=24, show=\"*\" if secret else \"\")\n            e.insert(0, placeholder)\n            e.bind(\"\",\n                   lambda ev, p=placeholder, en=e: en.delete(0, \"end\") if en.get() == p else None)\n            e.bind(\"\",\n                   lambda ev, p=placeholder, en=e: en.insert(0, p) if not en.get() else None)\n            e.pack(side=\"left\", padx=4)\n            fields[key] = e\n\n        log = scrolledtext.ScrolledText(\n            dlg, height=9, font=FONTS[\"mono\"],\n            bg=C[\"bg\"], fg=C[\"text\"], bd=0, state=\"disabled\")\n        log.pack(fill=\"both\", expand=True, padx=20, pady=4)\n\n        def _log(msg, col=C[\"text\"]):\n            log.config(state=\"normal\")\n            log.insert(\"end\", msg + \"\\n\")\n            log.see(\"end\")\n            log.config(state=\"disabled\")\n\n        def _do_connect():\n            host  = fields[\"host\"].get().strip()\n            share = fields[\"share\"].get().strip()\n            user  = fields[\"user\"].get().strip()\n            pwd   = fields[\"pwd\"].get().strip()\n            if not host or \"e.g\" in host:\n                messagebox.showwarning(\"Host Missing\",\n                    \"Host PC ka naam ya IP enter karo.\", parent=dlg)\n                return\n            if not share or \"e.g\" in share:\n                messagebox.showwarning(\"Share Missing\",\n                    \"Printer share name enter karo.\", parent=dlg)\n                return\n            unc = f\"\\\\\\\\{host}\\\\{share}\"\n\n            def _run():\n                _log(f\"\ud83d\udd17 Connecting to: {unc}\")\n\n                # Step 1: Client firewall\n                self._run_cmd(\n                    'netsh advfirewall firewall set rule '\n                    'group=\"File and Printer Sharing\" new enable=Yes profile=any')\n                _log(\"  \u2705 Client firewall rules \u2192 ON\")\n\n                # Step 2: net use (authentication)\n                has_user = user and \"khali\" not in user\n                has_pwd  = pwd  and \"khali\" not in pwd\n                if has_user and has_pwd:\n                    net_cmd = f'net use \"{unc}\" /user:{user} {pwd} /persistent:yes'\n                elif has_user:\n                    net_cmd = f'net use \"{unc}\" /user:{user} /persistent:yes'\n                else:\n                    net_cmd = f'net use \"{unc}\" /persistent:yes'\n\n                out, rc = self._run_cmd(net_cmd, timeout=15)\n                if rc == 0 or \"completed\" in out.lower():\n                    _log(f\"  \u2705 Network path accessible: {unc}\")\n                else:\n                    _log(f\"  \u26a0 net use: {out[:120]}\")\n                    _log(\"  \u2139 Phir bhi printer add karne ki koshish kar raha hoon...\")\n\n                # Step 3: Add printer \u2014 PowerShell\n                out2, rc2 = self._run_cmd(\n                    f'powershell -Command \"Add-Printer -ConnectionName \\'{unc}\\'\"',\n                    timeout=20)\n                if rc2 == 0:\n                    _log(f\"  \u2705 Printer added from {unc}!\")\n                else:\n                    # Fallback 1: rundll32\n                    self._run_cmd(\n                        f'rundll32 printui.dll,PrintUIEntry /in /n \"{unc}\"')\n                    _log(\"  \u2705 Printer add attempt via legacy method (rundll32)\")\n                    _log(f\"  \u2139 Agar nahi hua: Control Panel \u2192 Printers \u2192 \"\n                         f\"Add Printer \u2192 Network \u2192 {unc}\")\n\n                # Step 4: Auto-open confirmation\n                def _confirm():\n                    subprocess.Popen([\"control.exe\", \"printers\"], shell=False)\n                    time.sleep(1)\n                    self._printer_detect()\n                    messagebox.showinfo(\n                        \"\ud83d\udda8 Connection Result\",\n                        f\"Connection attempt complete!\\n\\n\"\n                        f\"Host  : {host}\\n\"\n                        f\"Share : {share}\\n\"\n                        f\"Path  : {unc}\\n\\n\"\n                        \"\u2705 Printers window khul gaya hai.\\n\"\n                        \"Wahan shared printer check karo.\\n\\n\"\n                        \"Agar nahi dikh raha:\\n\"\n                        \"1. Host pe 'Auto-Share' dobara chalao\\n\"\n                        \"2. Host pe 'Port Fix' chalao\\n\"\n                        \"3. Dono PC ek hi workgroup mein hain? Check karo.\",\n                        parent=dlg)\n                self.after(0, _confirm)\n                self._sharing_log(\n                    f\"[CLIENT] Printer connect attempt \u2192 {unc}\", C[\"accent2\"])\n\n            self._launch_job(\"open_network_explorer\", _run)\n\n        def _do_ping():\n            host = fields[\"host\"].get().strip()\n            if not host or \"e.g\" in host:\n                messagebox.showwarning(\"Host Missing\",\n                    \"Host ka IP ya naam pehle enter karo.\", parent=dlg)\n                return\n            threading.Thread(\n                target=lambda: _log(self._run_cmd(f'ping -n 3 {host}')[0]),\n                daemon=True).start()\n\n        def _browse():\n            subprocess.Popen([\"explorer.exe\", \"Network\"], shell=False)\n\n        btn_f = tk.Frame(dlg, bg=C[\"bg\"])\n        btn_f.pack(pady=8)\n        self._btn(btn_f, \"\ud83d\udda8 Connect Printer\",  C[\"btn_warn\"],   _do_connect).pack(side=\"left\", padx=4)\n        self._btn(btn_f, \"\ud83c\udfd3 Ping Host\",        C[\"btn_chip\"],   _do_ping).pack(side=\"left\", padx=4)\n        self._btn(btn_f, \"\ud83c\udf10 Browse Network\",   C[\"btn_info\"],   _browse).pack(side=\"left\", padx=4)\n        self._btn(btn_f, \"\u274c Close\",             C[\"btn_danger\"], dlg.destroy).pack(side=\"left\", padx=4)\n\n    def _build_driver(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udce6 Driver Checker\",\n                             \"Third-party drivers \u2014 outdated ya problem wale dhundho, update karo\")\n\n        # \u2500\u2500 Guide Banner \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        guide = tk.Frame(frame, bg=\"#0D1F0D\", highlightbackground=C[\"accent2\"], highlightthickness=1)\n        guide.pack(fill=\"x\", padx=16, pady=(4, 6))\n        tk.Label(guide, text=\"\ud83d\udcd6  Kaise use karein?\", font=FONTS[\"subhead\"], fg=C[\"accent2\"], bg=\"#0D1F0D\").pack(anchor=\"w\", padx=12, pady=(8,2))\n        for s in [\n            \"\u2460 'Scan Drivers' dabao \u2014 third-party drivers ki list aayegi\",\n            \"\u2461 List mein driver select karo \u2192 'Open in Device Manager' se update/uninstall karo\",\n            \"\u2462 'Open Driver Folder' se driver file directly dekh sakte ho\",\n            \"\u2463 'Export CSV' se list save karo \u2014 customer ko dene ke liye useful\",\n            \"\u26a0  Old 'Link Date' wale drivers update karne chahiye \u2014 yellow mein highlight honge\",\n        ]:\n            tk.Label(guide, text=s, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=\"#0D1F0D\", anchor=\"w\").pack(anchor=\"w\", padx=20, pady=1)\n        tk.Label(guide, text=\"\", bg=\"#0D1F0D\").pack(pady=3)\n\n        # \u2500\u2500 Action Buttons \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        self._action_card_grid(frame, [\n            (\"\ud83d\udd0d\", \"Scan Drivers\",         \"Third-party drivers scan karo\",          C[\"btn_info\"],   self._scan_drivers),\n            (\"\ud83d\udda5\",  \"Open Device Manager\",  \"Windows Device Manager mein update karo\",C[\"btn_warn\"],   self._driver_open_devmgr),\n            (\"\ud83d\udcc2\", \"Open Driver Folder\",   \"Selected driver ki file location kholo\", C[\"btn_chip\"],   self._driver_open_folder),\n            (\"\ud83d\udce5\", \"Export CSV\",           \"Driver list CSV mein save karo\",         C[\"accent2\"],    self._driver_export_csv),\n        ], cols=4)\n\n        # \u2500\u2500 Treeview for driver list \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        tv_frame = tk.Frame(frame, bg=C[\"bg\"])\n        tv_frame.pack(fill=\"both\", expand=True, padx=16, pady=(4, 4))\n\n        cols = (\"Display Name\", \"Module\", \"Type\", \"Link Date\", \"Path\")\n        self.driver_tree = ttk.Treeview(tv_frame, columns=cols, show=\"headings\",\n                                         height=18, style=\"Custom.Treeview\",\n                                         selectmode=\"browse\")\n        for col, w in zip(cols, [200, 130, 80, 110, 380]):\n            self.driver_tree.heading(col, text=col)\n            self.driver_tree.column(col, width=w, anchor=\"w\")\n        self.driver_tree.tag_configure(\"old\",  foreground=C[\"warning\"])\n        self.driver_tree.tag_configure(\"ok\",   foreground=C[\"success\"])\n        dsb = ttk.Scrollbar(tv_frame, orient=\"vertical\", command=self.driver_tree.yview)\n        self.driver_tree.configure(yscrollcommand=dsb.set)\n        self.driver_tree.pack(side=\"left\", fill=\"both\", expand=True)\n        dsb.pack(side=\"right\", fill=\"y\")\n\n        # Status bar\n        self.driver_status_lbl = tk.Label(frame, text=\"  Scan karo \u2014 drivers list yahan aayegi\",\n                                           font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"], anchor=\"w\")\n        self.driver_status_lbl.pack(fill=\"x\", padx=16, pady=(2, 4))\n\n        # Fallback log (error/warnings ke liye)\n        self.driver_log = self._scrolled_text(frame, height=4)\n        self._driver_rows = []   # store parsed data\n        return frame\n\n    def _scan_drivers(self):\n        self._launch_job(\"scan_drivers\", self._do_scan_drivers)\n\n    def _do_scan_drivers(self):\n        import datetime as _dt\n        self.after(0, lambda: self.driver_tree.delete(*self.driver_tree.get_children()))\n        self.after(0, lambda: self.driver_status_lbl.config(text=\"  \u23f3 Scanning drivers...\", fg=C[\"accent4\"]))\n        self._append_log(self.driver_log, \"\ud83d\udd0d driverquery chal raha hai...\", C[\"accent4\"])\n        out, rc = self._run_cmd('driverquery /FO CSV /V', timeout=30)\n        if rc != 0 or not out.strip():\n            self._append_log(self.driver_log, \"\u274c driverquery failed. Admin mode mein run karo.\", C[\"error\"])\n            self.after(0, lambda: self.driver_status_lbl.config(text=\"  \u274c Scan failed \u2014 Admin mode use karo\", fg=C[\"error\"]))\n            return\n        try:\n            reader = csv.DictReader(io.StringIO(out))\n            self._driver_rows = []\n            cutoff_year = _dt.datetime.now().year - 3   # 3 saal purana = old\n\n            for r in reader:\n                mod  = (r.get(\"Module Name\") or r.get(\"ModuleName\") or \"\").strip()\n                disp = (r.get(\"Display Name\") or r.get(\"DisplayName\") or \"\").strip()\n                dtype= (r.get(\"Driver Type\")  or r.get(\"DriverType\")  or \"\").strip()\n                link = (r.get(\"Link Date\")    or r.get(\"LinkDate\")    or \"\").strip()\n                path = (r.get(\"Path\") or \"\").strip()\n                if not mod and not disp:\n                    continue\n                if \"microsoft\" in (disp.lower() + \" \" + path.lower()):\n                    continue\n                self._driver_rows.append((disp or mod, mod, dtype, link, path))\n\n            # Sort: purane pehle (link date ascending)\n            self._driver_rows.sort(key=lambda x: (x[3] or \"0000\", x[0].lower()))\n\n            def populate():\n                for name, mod, dtype, link, path in self._driver_rows:\n                    # Tag: old if link year &lt; cutoff\n                    tag = \"ok\"\n                    try:\n                        yr = int(link.split(\"/\")[-1]) if \"/\" in link else int(link[-4:]) if len(link) &gt;= 4 else 9999\n                        if yr &lt; cutoff_year:\n                            tag = \"old\"\n                    except:\n                        pass\n                    self.driver_tree.insert(\"\", \"end\", values=(name, mod, dtype, link, path), tags=(tag,))\n\n                total = len(self._driver_rows)\n                self.driver_status_lbl.config(\n                    text=f\"  \u2705 {total} third-party drivers found  |  \ud83d\udfe1 Yellow = 3+ saal purane (update recommended)\",\n                    fg=C[\"success\"])\n                self._append_log(self.driver_log, f\"\u2705 {total} drivers found.\", C[\"success\"])\n            self.after(0, populate)\n\n        except Exception as e:\n            self._append_log(self.driver_log, f\"\u26a0 Parse error: {e}\", C[\"warning\"])\n            self.after(0, lambda: self.driver_status_lbl.config(text=f\"  \u26a0 Error: {e}\", fg=C[\"warning\"]))\n\n    def _driver_open_devmgr(self):\n        \"\"\"Windows Device Manager open karo \u2014 wahan driver update/uninstall possible hai.\"\"\"\n        self._run_cmd(\"devmgmt.msc\", timeout=5)\n        self._append_log(self.driver_log, \"\u2705 Device Manager khola gaya. Driver select karo \u2192 Right-click \u2192 Update Driver.\", C[\"success\"])\n\n    def _driver_open_folder(self):\n        \"\"\"Selected driver ki folder location Explorer mein open karo.\"\"\"\n        sel = self.driver_tree.selection()\n        if not sel:\n            messagebox.showinfo(\"Select Driver\", \"Pehle list mein ek driver select karo.\")\n            return\n        path = self.driver_tree.item(sel[0])[\"values\"][4]\n        if not path or not os.path.exists(path):\n            messagebox.showwarning(\"Not Found\", f\"Driver file nahi mili:\\n{path}\")\n            return\n        folder = os.path.dirname(path)\n        try:\n            os.startfile(folder)\n            self._append_log(self.driver_log, f\"\ud83d\udcc2 Folder khola: {folder}\", C[\"success\"])\n        except Exception as e:\n            messagebox.showerror(\"Error\", str(e))\n\n    # ---------- DUPLICATE FINDER ----------\n    def _build_dupfinder(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83e\uddec Duplicate Finder\", \"Find &amp; remove duplicate files (size + hash)\")\n\n        top = tk.Frame(frame, bg=C[\"card\"])\n        top.pack(fill=\"x\", padx=16, pady=8)\n\n        tk.Label(top, text=\"Folder:\", font=FONTS[\"body\"], fg=C[\"text\"], bg=C[\"card\"]).pack(side=\"left\", padx=6)\n        self.dup_folder_var = tk.StringVar(value=os.path.join(os.path.expanduser(\"~\"), \"Downloads\"))\n        self.dup_folder_entry = tk.Entry(top, textvariable=self.dup_folder_var, width=46, font=FONTS[\"body\"])\n        self.dup_folder_entry.pack(side=\"left\", padx=6)\n        self._btn(top, \"\ud83d\udcc1 Browse\", C[\"btn_info\"], self._dup_pick_folder).pack(side=\"left\", padx=4)\n\n        tk.Label(top, text=\"Mode:\", font=FONTS[\"body\"], fg=C[\"text\"], bg=C[\"card\"]).pack(side=\"left\", padx=(12, 4))\n        self.dup_mode_var = tk.StringVar(value=\"fast\")\n        ttk.Combobox(top, values=[\"fast\", \"accurate\"], textvariable=self.dup_mode_var,\n                     width=10, font=FONTS[\"body\"], state=\"readonly\").pack(side=\"left\", padx=4)\n\n        tk.Label(top, text=\"Min MB:\", font=FONTS[\"body\"], fg=C[\"text\"], bg=C[\"card\"]).pack(side=\"left\", padx=(12, 4))\n        self.dup_min_mb = tk.Entry(top, width=6, font=FONTS[\"body\"])\n        self.dup_min_mb.insert(0, \"1\")\n        self.dup_min_mb.pack(side=\"left\", padx=4)\n\n        self._action_card_grid(frame, [\n            (\"\ud83d\udd0d\", \"Scan Duplicates\",          \"Folder mein duplicate files dhundho\", C[\"btn_danger\"], self._dup_start_scan),\n            (\"\ud83d\udce6\", \"Move to Quarantine\",        \"Selected files quarantine mein bhejo\",C[\"btn_warn\"],   self._dup_quarantine_selected),\n            (\"\ud83d\uddd1\",  \"Delete Selected\",          \"Selected files permanently delete karo\",C[\"btn_danger\"],self._dup_delete_selected),\n            (\"\ud83d\udcc2\", \"Open Selected Folder\",     \"File ki location folder open karo\",   C[\"btn_chip\"],   self._dup_open_selected_folder),\n        ], cols=4)\n\n        prog = tk.Frame(frame, bg=C[\"card\"])\n        prog.pack(fill=\"x\", padx=16, pady=(0, 6))\n        self.dup_status_lbl = tk.Label(prog, text=\"Ready\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], anchor=\"w\")\n        self.dup_status_lbl.pack(fill=\"x\", padx=8, pady=(6, 2))\n        self.dup_progress = tk.DoubleVar(value=0)\n        ttk.Progressbar(prog, variable=self.dup_progress, maximum=100, mode=\"determinate\").pack(fill=\"x\", padx=8, pady=(0, 8))\n\n        cols = (\"Group\", \"Filename\", \"Size\", \"Path\")\n        self.dup_tree = ttk.Treeview(frame, columns=cols, show=\"headings\", height=20, style=\"Custom.Treeview\", selectmode=\"extended\")\n        for col, w in zip(cols, [80, 260, 90, 520]):\n            self.dup_tree.heading(col, text=col)\n            self.dup_tree.column(col, width=w, anchor=\"w\")\n        vsb = ttk.Scrollbar(frame, orient=\"vertical\", command=self.dup_tree.yview)\n        self.dup_tree.configure(yscrollcommand=vsb.set)\n        self.dup_tree.pack(side=\"left\", fill=\"both\", expand=True, padx=16, pady=8)\n        vsb.pack(side=\"right\", fill=\"y\", pady=8, padx=(0, 8))\n\n        self.dup_log = self._scrolled_text(frame, height=8)\n        self._dup_results = []  # list of meta dicts aligned with displayed rows\n        return frame\n\n    def _dup_pick_folder(self):\n        path = filedialog.askdirectory(title=\"Select Folder to Scan\")\n        if path:\n            self.dup_folder_var.set(path)\n\n    def _dup_start_scan(self):\n        folder = (self.dup_folder_var.get() or \"\").strip()\n        if not folder or not os.path.isdir(folder):\n            messagebox.showwarning(\"Input\", \"Valid folder select karo.\")\n            return\n        mode = (self.dup_mode_var.get() or \"fast\").strip().lower()\n        try:\n            min_mb = float((self.dup_min_mb.get() or \"0\").strip())\n        except Exception:\n            min_mb = 0\n        min_bytes = int(max(0, min_mb) * 1024 * 1024)\n        if not messagebox.askyesno(\"Duplicate Scan\",\n                                   f\"Folder: {folder}\\nMode: {mode}\\nMin size: {min_mb} MB\\n\\nScan start karein?\"):\n            return\n        self.dup_tree.delete(*self.dup_tree.get_children())\n        self._dup_results = []\n        self.dup_progress.set(0)\n        self.dup_status_lbl.config(text=\"Scanning...\", fg=C[\"accent4\"])\n        self._launch_job(\"duplicate_scan\", self._dup_do_scan, folder, mode, min_bytes)\n\n    def _dup_hash_fast(self, path, size):\n        h = hashlib.sha256()\n        with open(path, \"rb\") as f:\n            head = f.read(min(size, 1024 * 1024))\n            h.update(head)\n            if size &gt; 2 * 1024 * 1024:\n                try:\n                    f.seek(max(0, size - 1024 * 1024))\n                    tail = f.read(1024 * 1024)\n                    h.update(tail)\n                except Exception:\n                    pass\n        return h.hexdigest()\n\n    def _dup_hash_full(self, path):\n        h = hashlib.sha256()\n        with open(path, \"rb\") as f:\n            while True:\n                chunk = f.read(1024 * 1024)\n                if not chunk:\n                    break\n                h.update(chunk)\n        return h.hexdigest()\n\n    def _dup_do_scan(self, folder, mode, min_bytes):\n        try:\n            self._append_log(self.dup_log, f\"\ud83d\udd0d Scanning: {folder}\", C[\"accent\"])\n            files = []\n            scanned = 0\n            for dirpath, _, filenames in os.walk(folder):\n                for fn in filenames:\n                    full = os.path.join(dirpath, fn)\n                    try:\n                        st = os.stat(full)\n                        if st.st_size &lt; min_bytes:\n                            continue\n                        files.append((full, int(st.st_size)))\n                    except Exception:\n                        continue\n                scanned += 1\n                if scanned % 200 == 0:\n                    self.after(0, lambda s=scanned: self.dup_status_lbl.config(text=f\"Scanning... {s} folders\", fg=C[\"accent4\"]))\n\n            by_size = {}\n            for p, sz in files:\n                by_size.setdefault(sz, []).append(p)\n            candidates = [(sz, ps) for sz, ps in by_size.items() if len(ps) &gt; 1]\n            if not candidates:\n                self.after(0, lambda: self.dup_status_lbl.config(text=\"No duplicates candidates found.\", fg=C[\"warning\"]))\n                self.after(0, lambda: self.dup_progress.set(100))\n                self._append_log(self.dup_log, \"\u2705 No duplicate candidates (by size).\", C[\"success\"])\n                return\n\n            total = sum(len(ps) for _, ps in candidates)\n            done = 0\n            groups = []\n            for sz, paths in candidates:\n                hash_map = {}\n                for p in paths:\n                    try:\n                        if mode == \"accurate\":\n                            hx = self._dup_hash_full(p)\n                        else:\n                            hx = self._dup_hash_fast(p, sz)\n                        hash_map.setdefault(hx, []).append(p)\n                    except Exception:\n                        continue\n                    done += 1\n                    if done % 25 == 0:\n                        pct = int((done / max(1, total)) * 100)\n                        self.after(0, lambda pct=pct: self.dup_progress.set(pct))\n                        self.after(0, lambda d=done, t=total: self.dup_status_lbl.config(text=f\"Hashing... {d}/{t}\", fg=C[\"accent4\"]))\n                for hx, ps in hash_map.items():\n                    if len(ps) &gt; 1:\n                        groups.append({\"size\": sz, \"hash\": hx, \"paths\": ps})\n\n            def render():\n                self.dup_tree.delete(*self.dup_tree.get_children())\n                self._dup_results = []\n                gid = 0\n                dup_files = 0\n                dup_bytes = 0\n                for g in groups:\n                    gid += 1\n                    group_label = f\"G{gid}\"\n                    for p in g[\"paths\"]:\n                        name = os.path.basename(p)\n                        self.dup_tree.insert(\"\", \"end\",\n                                             values=(group_label, name, self._fmt_size(g[\"size\"]), p))\n                        self._dup_results.append({\"path\": p, \"group\": group_label, \"size\": g[\"size\"], \"hash\": g[\"hash\"]})\n                        dup_files += 1\n                    # duplicates count excludes one \"original\"\n                    if len(g[\"paths\"]) &gt; 1:\n                        dup_bytes += (len(g[\"paths\"]) - 1) * g[\"size\"]\n                self.dup_progress.set(100)\n                if groups:\n                    self.dup_status_lbl.config(\n                        text=f\"\u2705 {len(groups)} duplicate group(s) found | extra space: {self._fmt_size(dup_bytes)}\",\n                        fg=C[\"success\"])\n                    self._append_log(self.dup_log, f\"\u2705 Groups: {len(groups)} | Extra space: {self._fmt_size(dup_bytes)}\", C[\"success\"])\n                else:\n                    self.dup_status_lbl.config(text=\"No duplicates found (hash matched none).\", fg=C[\"warning\"])\n                    self._append_log(self.dup_log, \"\u2705 No duplicates after hashing.\", C[\"success\"])\n\n            self.after(0, render)\n        except Exception as e:\n            self.after(0, lambda: self.dup_status_lbl.config(text=f\"Scan failed: {e}\", fg=C[\"error\"]))\n\n    def _dup_selected_entries(self):\n        items = []\n        for iid in self.dup_tree.selection():\n            idx = self.dup_tree.index(iid)\n            if 0 &lt;= idx &lt; len(self._dup_results):\n                items.append(self._dup_results[idx])\n        return items\n\n    def _dup_quarantine_selected(self):\n        sel = self._dup_selected_entries()\n        if not sel:\n            messagebox.showinfo(\"No Selection\", \"Pehle duplicate files select karo.\")\n            return\n        base = (self.dup_folder_var.get() or \"\").strip()\n        quarantine = os.path.join(base, \"_Duplicate_Quarantine\")\n        if not messagebox.askyesno(\"Quarantine\",\n                                   f\"Selected {len(sel)} file(s) quarantine folder me move honge:\\n{quarantine}\\n\\nProceed?\"):\n            return\n        os.makedirs(quarantine, exist_ok=True)\n        moved = 0\n        for it in sel:\n            src = it.get(\"path\", \"\")\n            if not src or not os.path.exists(src):\n                continue\n            dst = os.path.join(quarantine, os.path.basename(src))\n            # avoid overwrite\n            if os.path.exists(dst):\n                root, ext = os.path.splitext(dst)\n                dst = f\"{root}_{int(time.time())}{ext}\"\n            try:\n                shutil.move(src, dst)\n                moved += 1\n            except Exception as e:\n                self._append_log(self.dup_log, f\"\u274c Move failed: {src} ({e})\", C[\"error\"])\n        self._append_log(self.dup_log, f\"\u2705 Moved to quarantine: {moved}\", C[\"success\"])\n        self._dup_start_scan()\n\n    def _dup_delete_selected(self):\n        sel = self._dup_selected_entries()\n        if not sel:\n            messagebox.showinfo(\"No Selection\", \"Pehle duplicate files select karo.\")\n            return\n        if not messagebox.askyesno(\"Permanent Delete\",\n                                   f\"\u26a0\ufe0f Selected {len(sel)} file(s) PERMANENT delete honge.\\nUndo possible nahi.\\n\\nProceed?\"):\n            return\n        deleted = 0\n        for it in sel:\n            src = it.get(\"path\", \"\")\n            if not src or not os.path.exists(src):\n                continue\n            try:\n                os.remove(src)\n                deleted += 1\n            except Exception as e:\n                self._append_log(self.dup_log, f\"\u274c Delete failed: {src} ({e})\", C[\"error\"])\n        self._append_log(self.dup_log, f\"\ud83d\uddd1 Deleted: {deleted}\", C[\"warning\"])\n        self._dup_start_scan()\n\n    def _dup_open_selected_folder(self):\n        sel = self._dup_selected_entries()\n        if not sel:\n            messagebox.showinfo(\"No Selection\", \"Pehle ek file select karo.\")\n            return\n        p = sel[0].get(\"path\", \"\")\n        if not p:\n            return\n        folder = os.path.dirname(p)\n        try:\n            os.startfile(folder)\n        except Exception:\n            pass\n\n    def _build_backup(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udcbe Backup/Restore\", \"Profiles\")\n        self._action_card_grid(frame, [\n            (\"\ud83d\udcc0\", \"Backup Settings\",  \"Current settings JSON mein save karo\", C[\"btn_info\"], self._backup_settings),\n            (\"\ud83d\udd04\", \"Restore Settings\", \"Pehle saved settings wapas lao\",       C[\"btn_warn\"], self._restore_settings),\n        ], cols=2)\n        self.backup_log = self._scrolled_text(frame, height=18)\n        return frame\n\n    def _backup_settings(self):\n        data = {\"reg\": {k: v.get() for k, v in self.reg_vars.items()}, \"gp\": {k: v.get() for k, v in self.gp_vars.items()}}\n        fpath = filedialog.asksaveasfilename(defaultextension=\".json\", filetypes=[(\"JSON\",\"*.json\")])\n        if fpath:\n            with open(fpath, \"w\") as f:\n                json.dump(data, f, indent=2)\n            self._append_log(self.backup_log, \"\u2705 Saved\", C[\"success\"])\n\n    def _restore_settings(self):\n        fpath = filedialog.askopenfilename(filetypes=[(\"JSON\",\"*.json\")])\n        if fpath:\n            with open(fpath, \"r\") as f:\n                data = json.load(f)\n            if \"reg\" in data:\n                for k, val in data[\"reg\"].items():\n                    if k in self.reg_vars:\n                        self.reg_vars[k].set(bool(val))\n            self._append_log(self.backup_log, \"\u2705 Restored\", C[\"success\"])\n\n    def _build_report(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udcca HTML Report\", \"Export system report\")\n        self._action_card_grid(frame, [\n            (\"\ud83d\udcd1\", \"Generate Report\", \"System ka HTML report export karo\", C[\"btn_info\"], self._export_report),\n        ], cols=1)\n        self.report_log = self._scrolled_text(frame, height=18)\n        return frame\n\n    def _export_report(self):\n        fpath = filedialog.asksaveasfilename(defaultextension=\".html\", filetypes=[(\"HTML\",\"*.html\")])\n        if fpath:\n            vm = psutil.virtual_memory()\n            du = psutil.disk_usage(\"/\")\n            html = f\"\nGodawari Report\nCPU: {psutil.cpu_percent()}% | RAM: {vm.percent}% | Disk: {du.percent}%\"\n            with open(fpath, \"w\") as f:\n                f.write(html)\n            self._append_log(self.report_log, \"\u2705 Saved\", C[\"success\"])\n            os.startfile(fpath)\n\n    def _build_log(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udcdd Activity Log\", \"History\")\n        self._action_card_grid(frame, [\n            (\"\ud83d\udcbe\", \"Save Log\",   \"Log file Desktop pe save karo\",C[\"btn_info\"],   self._save_log),\n            (\"\ud83d\uddd1\", \"Clear Log\",  \"Log screen saaf karo\",          C[\"btn_danger\"], self._clear_log),\n        ], cols=2)\n        log_frame = tk.Frame(frame, bg=C[\"card\"])\n        log_frame.pack(fill=\"both\", expand=True, padx=16, pady=8)\n        self.log_text = scrolledtext.ScrolledText(log_frame, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"], height=28, bd=0, wrap=\"word\", relief=\"flat\", state=\"disabled\")\n        self.log_text.pack(fill=\"both\", expand=True, padx=8, pady=(0,8))\n        for line, color in self.log_lines:\n            self.log_text.config(state=\"normal\")\n            self.log_text.insert(\"end\", line + \"\\n\", f\"c{color.replace('#','')}\")\n            self.log_text.tag_config(f\"c{color.replace('#','')}\", foreground=color)\n            self.log_text.config(state=\"disabled\")\n        return frame\n\n    def _save_log(self):\n        path = os.path.join(os.path.expanduser(\"~\"), \"Desktop\", f\"Godawari_Log_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.txt\")\n        self.log_text.config(state=\"normal\")\n        with open(path, \"w\", encoding=\"utf-8\") as f:\n            f.write(self.log_text.get(\"1.0\", \"end\"))\n        self.log_text.config(state=\"disabled\")\n        messagebox.showinfo(\"Saved\", f\"Log saved to Desktop\")\n\n    def _clear_log(self):\n        self.log_lines.clear()\n        self.log_text.config(state=\"normal\")\n        self.log_text.delete(\"1.0\", \"end\")\n        self.log_text.config(state=\"disabled\")\n\n    # ---------- REMAINING HARDWARE SECTIONS (unchanged) ----------\n    def _build_motherboard(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udda5\ufe0f Motherboard Info\", \"Board &amp; BIOS\", hw=True)\n        self._action_card_grid(frame, [\n            (\"\ud83d\udda5\", \"Scan Motherboard\", \"Board maker, model, BIOS version\", C[\"btn_hw\"], self._scan_mb),\n        ], cols=1)\n        self.mb_log = self._scrolled_text(frame, 20)\n        return frame\n\n    def _scan_mb(self):\n        self.mb_log.config(state=\"normal\")\n        self.mb_log.delete(\"1.0\", \"end\")\n        self.mb_log.config(state=\"disabled\")\n        self._launch_job(\"scan_mb\", self._do_scan_mb)\n\n    def _do_scan_mb(self):\n        out, _ = self._run_cmd(\"wmic baseboard get Manufacturer,Product,Version,SerialNumber /format:list\")\n        self._append_log(self.mb_log, \"\u2550\"*50, C[\"border\"])\n        self._append_log(self.mb_log, \"  MOTHERBOARD INFORMATION\", C[\"hw_accent\"])\n        for line in out.splitlines():\n            if \"=\" in line:\n                self._append_log(self.mb_log, f\"  {line}\", C[\"text\"])\n        self._set_status(\"Motherboard scan complete\", C[\"success\"])\n\n    def _build_chip_diag(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udd2c CPU Diagnostics\", \"Architecture &amp; Cache\", hw=True)\n        self._action_card_grid(frame, [\n            (\"\ud83d\udd2c\", \"Full CPU Analysis\", \"CPU cores, cache, speed details\", C[\"btn_chip\"], self._scan_cpu),\n        ], cols=1)\n        self.chip_log = self._scrolled_text(frame, 20)\n        return frame\n\n    def _scan_cpu(self):\n        self.chip_log.config(state=\"normal\")\n        self.chip_log.delete(\"1.0\", \"end\")\n        self.chip_log.config(state=\"disabled\")\n        self._launch_job(\"scan_cpu\", self._do_scan_cpu)\n\n    def _do_scan_cpu(self):\n        out, _ = self._run_cmd(\"wmic cpu get Name,MaxClockSpeed,NumberOfCores,L2CacheSize,L3CacheSize /format:list\")\n        self._append_log(self.chip_log, \"\u2550\"*50, C[\"border\"])\n        self._append_log(self.chip_log, \"  CPU ARCHITECTURE &amp; CACHE\", C[\"hw_accent\"])\n        for line in out.splitlines():\n            if \"=\" in line:\n                self._append_log(self.chip_log, f\"  {line}\", C[\"text\"])\n\n    def _build_voltage_monitor(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\u26a1 Voltage Monitor\", \"PSU Rails Reference\", hw=True)\n        self._action_card_grid(frame, [\n            (\"\u26a1\", \"Scan Voltages\", \"PSU rails reference chart dekhao\", C[\"btn_chip\"], self._scan_volts),\n        ], cols=1)\n        self.volt_log = self._scrolled_text(frame, 20)\n        return frame\n\n    def _scan_volts(self):\n        self.volt_log.config(state=\"normal\")\n        self.volt_log.delete(\"1.0\", \"end\")\n        self.volt_log.config(state=\"disabled\")\n        self._launch_job(\"scan_volts\", self._do_scan_volts)\n\n    def _do_scan_volts(self):\n        self._append_log(self.volt_log, \"  PSU Rails (ATX Standard Reference):\", C[\"hw_accent\"])\n        for rail, spec in [(\"3.3V Rail\", \"3.135-3.465V\"), (\"5V Rail\", \"4.750-5.250V\"), (\"12V Rail\", \"11.400-12.600V\")]:\n            self._append_log(self.volt_log, f\"  {rail:&lt;15}: {spec}\", C[\"text\"])\n\n    def _build_gpu_diag_fixed(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83c\udfae GPU Diagnostics\", \"Real GPU Stats\", hw=True)\n        self._action_card_grid(frame, [\n            (\"\ud83c\udfae\", \"Scan GPU\", \"Graphics card details scan karo\", C[\"btn_chip\"], self._scan_gpu),\n        ], cols=1)\n        self.gpu_log = self._scrolled_text(frame, 20)\n        return frame\n\n    def _scan_gpu(self):\n        self.gpu_log.config(state=\"normal\")\n        self.gpu_log.delete(\"1.0\", \"end\")\n        self.gpu_log.config(state=\"disabled\")\n        self._launch_job(\"scan_gpu\", self._do_scan_gpu)\n\n    def _do_scan_gpu(self):\n        out, _ = self._run_cmd(\"wmic path win32_VideoController get Name,AdapterRAM,DriverVersion,VideoProcessor /format:list\")\n        self._append_log(self.gpu_log, \"\u2550\"*50, C[\"border\"])\n        self._append_log(self.gpu_log, \"  GPU INFORMATION\", C[\"hw_accent\"])\n        for line in out.splitlines():\n            if \"=\" in line and line.split(\"=\")[1].strip():\n                if \"AdapterRAM\" in line:\n                    try:\n                        line = f\"VRAM={self._fmt_size(int(line.split('=')[1]))}\"\n                    except:\n                        pass\n                self._append_log(self.gpu_log, line, C[\"text\"])\n\n    def _build_ram_slots(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83c\udccf RAM Slots\", \"DIMM Info\", hw=True)\n        self._action_card_grid(frame, [\n            (\"\ud83c\udccf\", \"Scan RAM Slots\", \"DIMM slot info \u2014 size, speed, brand\", C[\"btn_chip\"], self._scan_dimms),\n        ], cols=1)\n        self.ramslot_log = self._scrolled_text(frame, 20)\n        return frame\n\n    def _scan_dimms(self):\n        self.ramslot_log.config(state=\"normal\")\n        self.ramslot_log.delete(\"1.0\", \"end\")\n        self.ramslot_log.config(state=\"disabled\")\n        self._launch_job(\"scan_dimms\", self._do_scan_dimms)\n\n    def _do_scan_dimms(self):\n        out, _ = self._run_cmd(\"wmic memorychip get BankLabel,Capacity,Speed,Manufacturer /format:list\")\n        self._append_log(self.ramslot_log, \"\u2550\"*50, C[\"border\"])\n        self._append_log(self.ramslot_log, \"  RAM SLOT INFORMATION\", C[\"hw_accent\"])\n        for line in out.splitlines():\n            if \"=\" in line:\n                self._append_log(self.ramslot_log, f\"  {line}\", C[\"text\"])\n\n    def _build_post_codes(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udcdf POST Codes\", \"Reference\", hw=True)\n        self.post_tree = ttk.Treeview(frame, columns=(\"BIOS\", \"Code\", \"Meaning\", \"Fix\"), show=\"headings\", height=24, style=\"Custom.Treeview\")\n        for col, w in zip((\"BIOS\", \"Code\", \"Meaning\", \"Fix\"), [100,100,300,400]):\n            self.post_tree.heading(col, text=col)\n            self.post_tree.column(col, width=w, anchor=\"w\")\n        for row in [(\"AMI\",\"1 Beep\",\"DRAM Refresh\",\"Reseat RAM\"),\n                    (\"AMI\",\"5 Beeps\",\"CPU Error\",\"Reseat CPU\"),\n                    (\"Award\",\"1 Long\",\"DRAM Error\",\"Check RAM\"),\n                    (\"Phoenix\",\"1-1-2\",\"CPU Fail\",\"Check CPU Socket\")]:\n            self.post_tree.insert(\"\", \"end\", values=row)\n        self.post_tree.pack(fill=\"both\", expand=True, padx=16, pady=8)\n        return frame\n\n    def _build_cap_check(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udd0d Capacitor Guide\", \"Visual Inspection\", hw=True)\n        self.cap_guide = self._scrolled_text(frame, 25)\n        self._append_log(self.cap_guide, \"\u274c BAD: Bulging top, leaked crust.\\n\u2705 GOOD: Flat top, clean base.\\nMOSFET BAD: Cracked, burnt legs.\", C[\"error\"])\n        return frame\n\n    # ---------- POWER BOOST SECTION (clean grid layout) ----------\n    def _build_boost_section(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\u26a1 Ultimate Power Boost\", \"PC ki speed badhaane ke liye professional tweaks \u2014 ek click mein\")\n\n        # \u2500\u2500 Top: One-Click master button \u2500\u2500\n        master_row = tk.Frame(frame, bg=C[\"card\"])\n        master_row.pack(fill=\"x\", padx=16, pady=(10, 4))\n        tk.Label(master_row, text=\"\ud83d\udd25  Sabse pehle yahi chalao:\",\n                 font=FONTS[\"subhead\"], fg=C[\"accent4\"], bg=C[\"card\"]).pack(side=\"left\", padx=14, pady=10)\n        def one_click_all_boosts():\n            if self._create_restore_point(\"Ultimate Power Boost\"):\n                self._launch_job(\"run_all_boosts\", self._run_all_boosts)\n        tk.Button(master_row, text=\"\u26a1 ONE-CLICK: Saare Boosts Apply Karo\",\n                  font=(\"Segoe UI\", 11, \"bold\"), bg=C[\"accent4\"], fg=C[\"bg\"],\n                  bd=0, padx=20, pady=10, cursor=\"hand2\",\n                  command=one_click_all_boosts).pack(side=\"left\", padx=10, pady=8)\n\n        # \u2500\u2500 Grid: individual tweak cards \u2500\u2500\n        grid_lbl = tk.Frame(frame, bg=C[\"bg\"])\n        grid_lbl.pack(fill=\"x\", padx=16, pady=(8, 2))\n        tk.Label(grid_lbl, text=\"Ya alag alag apply karo:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"]).pack(side=\"left\")\n\n        grid = tk.Frame(frame, bg=C[\"bg\"])\n        grid.pack(fill=\"x\", padx=16, pady=4)\n\n        boost_items = [\n            (\"\u26a1\", \"CPU Cores Unpark\",   \"Sabhi cores active karo\\n(latency kum hoti hai)\",       C[\"btn_hw\"],     lambda: self._confirm_and_run(\"Unpark CPU Cores\", \"Sabhi CPU cores hamesha active rahenge, latency kum hogi.\", lambda: f\"CPU cores: {psutil.cpu_count()}\", self._unpark_cpu_cores, None)),\n            (\"\ud83c\udfaf\", \"App Priority Fix\",   \"Foreground app ko\\nzyada CPU do\",                        C[\"btn_info\"],   lambda: self._confirm_and_run(\"Priority Optimizer\", \"Foreground apps ko zyada CPU priority milegi.\", lambda: \"Default Windows settings.\", self._auto_priority_optimizer, None)),\n            (\"\ud83d\udcc0\", \"Pagefile Optimize\",  \"RAM ke hisaab se\\nPagefile set karo (1.5x)\",             C[\"btn_warn\"],   lambda: self._confirm_and_run(\"Optimal Pagefile\", \"Pagefile 1.5x RAM size pe set hoga.\", lambda: \"Current pagefile badle ga.\", self._optimal_pagefile, None)),\n            (\"\ud83e\udde0\", \"RAM Compression Off\",\"Memory compression band\\n(CPU load ghatega)\",            C[\"btn_chip\"],   lambda: self._confirm_and_run(\"Disable Memory Compression\", \"Memory compression disable hoga, CPU load kum hoga.\", lambda: \"Currently on.\", self._disable_memory_compression, None)),\n            (\"\ud83c\udfae\", \"Game Mode ON\",       \"Game Mode + GPU\\nScheduling enable karo\",                C[\"btn_info\"],   lambda: self._confirm_and_run(\"Game Mode\", \"Game Mode aur GPU hardware scheduling enable hoga.\", lambda: \"Current: unknown.\", self._enable_game_mode, None)),\n            (\"\u2601\ufe0f\", \"OneDrive Hatao\",     \"OneDrive uninstall karo\\n(Explorer fast hoga)\",          C[\"btn_danger\"], lambda: self._confirm_and_run(\"Remove OneDrive\", \"OneDrive poori tarah uninstall hoga.\", lambda: \"OneDrive installed hai.\", self._remove_onedrive, None)),\n        ]\n\n        for i, (emoji, title, desc, color, cmd) in enumerate(boost_items):\n            col = i % 3\n            row_n = i // 3\n            card = tk.Frame(grid, bg=C[\"card\"], highlightbackground=color, highlightthickness=1)\n            card.grid(row=row_n, column=col, padx=6, pady=6, sticky=\"nsew\")\n            grid.columnconfigure(col, weight=1)\n            tk.Label(card, text=emoji, font=(\"Segoe UI\", 18), fg=color, bg=C[\"card\"]).pack(pady=(10, 2))\n            tk.Label(card, text=title, font=FONTS[\"subhead\"], fg=C[\"text\"], bg=C[\"card\"]).pack()\n            tk.Label(card, text=desc, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"],\n                     justify=\"center\", wraplength=180).pack(padx=8, pady=4)\n            tk.Button(card, text=\"\u25b6 Apply\", font=FONTS[\"small\"],\n                      bg=color, fg=C[\"bg\"] if color in [C[\"accent\"], C[\"accent2\"], C[\"accent4\"]] else C[\"text\"],\n                      bd=0, padx=14, pady=5, cursor=\"hand2\",\n                      command=cmd).pack(pady=(0, 10))\n\n        # \u2500\u2500 Log area \u2500\u2500\n        tk.Label(frame, text=\"  Result Log:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"]).pack(anchor=\"w\", padx=16, pady=(8, 2))\n        self.boost_log = self._scrolled_text(frame, height=10)\n        return frame\n\n    def _run_all_boosts(self):\n        self._append_log(self.boost_log, \"Starting Deep Scan + Ultimate Power Boost...\", C[\"accent4\"])\n        self._deep_boost_scan()\n        self._unpark_cpu_cores(quiet=True)\n        self._auto_priority_optimizer(quiet=True)\n        self._optimal_pagefile(quiet=True)\n        self._disable_memory_compression(quiet=True)\n        self._enable_game_mode(quiet=True)\n        self._remove_onedrive(quiet=True)\n        self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Multimedia\\SystemProfile\", \"NetworkThrottlingIndex\", 0xffffffff, winreg.REG_DWORD, \"Network throttling disabled\", self.boost_log)\n        self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\DeliveryOptimization\\Config\", \"DODownloadMode\", 0, winreg.REG_DWORD, \"Delivery Optimization P2P off\", self.boost_log)\n        self._service_stop_checked(\"DoSvc\", \"Delivery Optimization service\", self.boost_log)\n        self._service_config_checked(\"DoSvc\", \"disabled\", \"Delivery Optimization service\", self.boost_log)\n        self._run_cmd('powercfg -h off')\n        self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Power\", \"HiberbootEnabled\", 0, winreg.REG_DWORD, \"Fast Startup disabled\", self.boost_log)\n        self._append_log(self.boost_log, \"\ud83c\udf89 All boosts applied! Restart recommended.\", C[\"success\"])\n        self._set_status(\"Ultimate Power Boost Complete\", C[\"success\"])\n\n    def _deep_boost_scan(self):\n        try:\n            vm = psutil.virtual_memory()\n            self._append_log(self.boost_log, f\"Deep scan: RAM used {vm.percent:.1f}% | available {self._fmt_size(vm.available)}\", C[\"text\"])\n            heavy = []\n            for proc in psutil.process_iter(['pid', 'name', 'memory_info']):\n                try:\n                    mem = proc.info.get('memory_info')\n                    rss = mem.rss if mem else 0\n                    if rss:\n                        heavy.append((rss, proc.info.get('pid'), proc.info.get('name') or 'unknown'))\n                except Exception:\n                    pass\n            for rss, pid, name in sorted(heavy, reverse=True)[:5]:\n                self._append_log(self.boost_log, f\"Deep scan process: PID {pid} {name} {self._fmt_size(rss)}\", C[\"text_dim\"])\n            junk_total = 0\n            for path in [os.environ.get(\"TEMP\", \"\"), r\"C:\\Windows\\Temp\", os.path.join(os.environ.get(\"LOCALAPPDATA\", \"\"), r\"Microsoft\\Windows\\Explorer\")]:\n                if path and os.path.exists(path):\n                    junk_total += self._folder_size(path)\n            self._append_log(self.boost_log, f\"Deep scan cache estimate: {self._fmt_size(junk_total)}\", C[\"accent\"])\n        except Exception as e:\n            self._append_log(self.boost_log, f\"Deep scan skipped: {e}\", C[\"warning\"])\n\n    def _unpark_cpu_cores(self, quiet=False):\n        try:\n            self._run_cmd('powercfg -setacvalueindex scheme_current sub_processor 0cc5b647-c1df-4637-891a-dec35c318583 0')\n            self._run_cmd('powercfg -setactive scheme_current')\n            msg = \"\u2705 CPU Cores Unparked (All cores active)\"\n            if not quiet:\n                self._append_log(self.boost_log, msg, C[\"success\"])\n            else:\n                self._log(msg, \"OK\")\n        except:\n            pass\n\n    def _auto_priority_optimizer(self, quiet=False):\n        self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Multimedia\\SystemProfile\", \"SystemResponsiveness\", 0, winreg.REG_DWORD)\n        self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Multimedia\\SystemProfile\", \"EnablePriorityBoost\", 1, winreg.REG_DWORD)\n        self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Multimedia\\SystemProfile\\Tasks\\Games\", \"GPU Priority\", 8, winreg.REG_DWORD)\n        self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Multimedia\\SystemProfile\\Tasks\\Games\", \"Priority\", 6, winreg.REG_DWORD)\n        msg = \"\u2705 Foreground app priority boosted, background lowered\"\n        if not quiet:\n            self._append_log(self.boost_log, msg, C[\"success\"])\n        else:\n            self._log(msg, \"OK\")\n\n    def _optimal_pagefile(self, quiet=False):\n        try:\n            total_ram_gb = psutil.virtual_memory().total // (1024**3)\n            recommended_mb = max(1024, total_ram_gb * 1024)  # min 1GB\n            self._run_cmd(f'wmic pagefileset where name=\"C:\\\\\\\\pagefile.sys\" set InitialSize={recommended_mb},MaximumSize={recommended_mb}')\n            msg = f\"\u2705 Pagefile set to {recommended_mb}MB (1x RAM)\"\n            if not quiet:\n                self._append_log(self.boost_log, msg, C[\"success\"])\n        except Exception as e:\n            self._append_log(self.boost_log, f\"Pagefile error: {e}\", C[\"error\"])\n\n    def _disable_memory_compression(self, quiet=False):\n        self._run_cmd('powershell \"Disable-MMAgent -MemoryCompression\"')\n        msg = \"\u2705 Memory Compression Disabled (CPU load reduced)\"\n        if not quiet:\n            self._append_log(self.boost_log, msg, C[\"success\"])\n        else:\n            self._log(msg, \"OK\")\n\n    def _enable_game_mode(self, quiet=False):\n        self._reg_set(winreg.HKEY_CURRENT_USER, r\"Software\\Microsoft\\Windows\\CurrentVersion\\GameDVR\", \"AppCaptureEnabled\", 0, winreg.REG_DWORD)\n        self._reg_set(winreg.HKEY_CURRENT_USER, r\"Software\\Microsoft\\Windows\\CurrentVersion\\GameDVR\", \"GameDVR_Enabled\", 0, winreg.REG_DWORD)\n        self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\PolicyManager\\default\\ApplicationManagement\\AllowGameDVR\", \"value\", 0, winreg.REG_DWORD)\n        self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Multimedia\\SystemProfile\", \"SystemResponsiveness\", 0, winreg.REG_DWORD)\n        self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Multimedia\\SystemProfile\\Tasks\\Games\", \"GPU Priority\", 8, winreg.REG_DWORD)\n        self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Multimedia\\SystemProfile\\Tasks\\Games\", \"Priority\", 6, winreg.REG_DWORD)\n        msg = \"\u2705 Game Mode + GPU Scheduling Enabled\"\n        if not quiet:\n            self._append_log(self.boost_log, msg, C[\"success\"])\n        else:\n            self._log(msg, \"OK\")\n\n    def _remove_onedrive(self, quiet=False):\n        try:\n            self._run_cmd('taskkill /f /im OneDrive.exe')\n            self._run_cmd('%SystemRoot%\\\\SysWOW64\\\\OneDriveSetup.exe /uninstall')\n            self._run_cmd('%SystemRoot%\\\\System32\\\\OneDriveSetup.exe /uninstall')\n            self._run_cmd('rd \"%UserProfile%\\\\OneDrive\" /s /q')\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Policies\\Microsoft\\Windows\\OneDrive\", \"DisableFileSyncNGSC\", 1, winreg.REG_DWORD)\n            msg = \"\u2705 OneDrive completely removed (Explorer will be faster)\"\n            if not quiet:\n                self._append_log(self.boost_log, msg, C[\"success\"])\n            else:\n                self._log(msg, \"OK\")\n        except Exception as e:\n            self._append_log(self.boost_log, f\"OneDrive removal error: {e}\", C[\"error\"])\n\n    # ---------- QUICK ACTIONS ----------\n    def _quick_clean_and_ram(self):\n        \"\"\"Clean Temp + RAM Optimize \u2014 ek saath dono kaam\"\"\"\n        self._quick_clean_temp()\n        self.after(500, self._quick_optimize_ram)\n\n    def _quick_services_and_registry(self):\n        \"\"\"Services disable + Registry tweaks \u2014 ek saath dono kaam\"\"\"\n        self._quick_services()\n        self.after(500, self._quick_registry)\n\n    def _quick_clean_temp(self):\n        self._show_section(\"cleaner\")\n        self._professional_scan()\n\n    def _quick_optimize_ram(self):\n        self._show_section(\"memory\")\n        self._ram_empty_with_confirm()\n\n    def _quick_services(self):\n        self._show_section(\"services\")\n        self._scan_impacting_services()\n\n    def _quick_registry(self):\n        self._show_section(\"registry\")\n        self._apply_registry()\n\n    def _full_scan(self):\n        def before():\n            return \"Starting full system scan (cleaner + services).\"\n        def action():\n            self._do_full_scan()\n        self._confirm_and_run(\"Full System Scan\", \"This will scan for junk files and heavy services. No changes will be applied automatically.\", before, action, None)\n\n    def _do_full_scan(self):\n        self._do_clean_scan()\n        self._do_scan_services()\n        self._log(\"Full scan complete\", \"OK\")\n\n    def _one_click_health_scan(self):\n        self._set_status(\"Health scan...\", C[\"accent4\"])\n        self._launch_job(\"health_scan\", self._do_health_scan)\n\n    def _do_health_scan(self):\n        try:\n            report = self.health_engine.analyze()\n            self._last_health_report = report\n            self.after(0, lambda: self._apply_health_report_ui(report))\n            lines = [f\"Health Score: {report['score']}/100 ({report['grade']})\"]\n            for c in report.get(\"checks\", [])[:12]:\n                lines.append(f\"  \u2022 {c['name']}: {c['detail']}\")\n            if report.get(\"recommendations\"):\n                lines.append(\"\\nRecommendations:\")\n                for r in report[\"recommendations\"]:\n                    lines.append(f\"  \u2192 {r}\")\n            msg = \"\\n\".join(lines)\n            self.after(0, lambda: messagebox.showinfo(\"System Health Scan\", msg))\n            self.after(0, lambda: self._set_status(f\"Health score: {report['score']}/100\", C[\"success\"]))\n        except Exception as e:\n            self.after(0, lambda: messagebox.showerror(\"Health Scan\", str(e)))\n\n    def _apply_health_report_ui(self, report):\n        if not report or \"health\" not in getattr(self, \"dash_cards\", {}):\n            return\n        try:\n            score = int(report.get(\"score\", 0))\n            grade = report.get(\"grade\", \"\")\n            color = C.get(report.get(\"color\", \"accent\"), C[\"accent\"])\n            self.dash_cards[\"health\"]._value_lbl.config(text=f\"{score}\")\n            self.dash_cards[\"health\"]._bar.config(value=score)\n            if hasattr(self, \"safety_health_lbl\"):\n                self.safety_health_lbl.config(\n                    text=f\"{score}/100 \u2014 {grade}\", fg=color)\n            if hasattr(self, \"dashboard_recommendation_tree\"):\n                self._refresh_intelligent_recommendations()\n            if hasattr(self, \"safety_recommendations\"):\n                self.safety_recommendations.config(text=self._recommendations_as_text(limit=6), fg=C[\"text\"])\n        except Exception:\n            pass\n\n    def _refresh_health_score_card(self):\n        def task():\n            try:\n                report = self.health_engine.analyze()\n                self._last_health_report = report\n                self.after(0, lambda r=report: self._apply_health_report_ui(r))\n            except Exception:\n                pass\n        self._launch_job(\"health_score_refresh\", task)\n\n    def _one_click_all_boosts(self):\n        if self._create_restore_point(\"One Click All Boosts\"):\n            self._launch_job(\"run_all_boosts\", self._run_all_boosts)\n\n    # ---------- ADVANCED TOOLS ----------\n    def _adv_tree(self, parent, columns, height=12):\n        wrap = tk.Frame(parent, bg=C[\"card\"])\n        tree = ttk.Treeview(wrap, columns=columns, show=\"headings\", height=height, style=\"Custom.Treeview\")\n        vsb = ttk.Scrollbar(wrap, orient=\"vertical\", command=tree.yview)\n        hsb = ttk.Scrollbar(wrap, orient=\"horizontal\", command=tree.xview)\n        tree.configure(yscrollcommand=vsb.set, xscrollcommand=hsb.set)\n        tree.grid(row=0, column=0, sticky=\"nsew\")\n        vsb.grid(row=0, column=1, sticky=\"ns\")\n        hsb.grid(row=1, column=0, sticky=\"ew\")\n        wrap.rowconfigure(0, weight=1)\n        wrap.columnconfigure(0, weight=1)\n        for col in columns:\n            tree.heading(col, text=col)\n            tree.column(col, width=130, anchor=\"w\", stretch=True)\n        return wrap, tree\n\n    def _adv_card(self, parent, title):\n        frame = tk.LabelFrame(parent, text=title, font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"], bd=1, relief=\"flat\", labelanchor=\"nw\")\n        return frame\n\n    def _build_driver_manager(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"Driver Manager\", \"Driver scan, purane driver aur unsigned risk check\")\n        content = self._scrollable_section_body(frame)\n        self._action_card_grid(content, [\n            (\"\ud83d\udd0d\", \"Driver Scan\", \"Saare drivers scan karo\", C[\"btn_info\"], self._driver_scan_all),\n            (\"\ud83d\udccb\", \"Purane Only\", \"Purane drivers filter karo\", C[\"btn_chip\"], self._driver_filter_old),\n            (\"\ud83d\udd04\", \"Unsigned Only\", \"Unsigned drivers filter karo\", C[\"btn_warn\"], self._driver_filter_unsigned),\n            (\"\ud83d\udcbe\", \"CSV Backup\", \"Driver list CSV mein save karo\", C[\"btn\"], self._driver_export_csv),\n            (\"\ud83c\udf10\", \"Device Manager\", \"Device Manager kholo\", C[\"accent2\"], lambda: self._run_cmd(\"devmgmt.msc\")),\n            (\"\u2699\", \"Driver Update via WU\", \"Windows Update se driver updates dhundo\", C[\"btn_chip\"], self._easydriver_update_via_windows_update),\n        ], cols=6)\n        body = tk.Frame(content, bg=C[\"bg\"])\n        body.pack(fill=\"both\", expand=True, padx=14, pady=8)\n        left = tk.Frame(body, bg=C[\"card\"])\n        left.pack(side=\"left\", fill=\"both\", expand=True, padx=(0,8))\n        right = tk.Frame(body, bg=C[\"card\"], width=380)\n        right.pack(side=\"right\", fill=\"both\", padx=(8,0))\n        right.pack_propagate(False)\n        cols = [\"Device Name\", \"Driver Version\", \"Driver Date\", \"Status\", \"Age\"]\n        wrap, self.driver_tree = self._adv_tree(left, cols, height=18)\n        wrap.pack(fill=\"both\", expand=True, padx=8, pady=8)\n        self.driver_tree.tag_configure(\"old\", foreground=C[\"warning\"])\n        self.driver_tree.tag_configure(\"very_old\", foreground=C[\"error\"])\n        self.driver_tree.tag_configure(\"unsigned\", foreground=C[\"error\"])\n        self.driver_tree.tag_configure(\"ok\", foreground=C[\"success\"])\n        self.driver_tree.bind(\"&lt;&gt;\", self._driver_on_select)\n        self.driver_detail = tk.Frame(right, bg=C[\"card\"])\n        self.driver_detail.pack(fill=\"both\", expand=True, padx=10, pady=10)\n        tk.Label(self.driver_detail, text=\"Driver select karo\", font=FONTS[\"subhead\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\")\n        self.driver_log = self._scrolled_text(content, height=7)\n        self.driver_all_rows = []\n        return frame\n\n    def _build_easy_driver_clone(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udda5 Easy Driver\",\n                             \"Missing/Outdated driver scan, Windows Update driver install, backup &amp; restore \u2014 DriverEasy style\")\n        content = self._scrollable_section_body(frame)\n\n        # \u2500\u2500 Fixed top area: info banner + action buttons \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        top = tk.Frame(content, bg=C[\"bg\"])\n        top.pack(fill=\"x\")\n\n        info = tk.Frame(top, bg=\"#0D1A0D\", highlightbackground=C[\"accent2\"], highlightthickness=1)\n        info.pack(fill=\"x\", padx=16, pady=(4, 6))\n        for txt in [\n            \"\ud83c\udf10 Internet required for Windows Update driver downloads.\",\n            \"\ud83d\udcbe Driver backup uses built-in pnputil export/restore.\",\n            \"\u26a0 Only signed drivers install successfully \u2014 unsigned drivers are skipped.\",\n            \"\u2705 Missing driver scan uses real PnP device status and WMI fallback.\",\n        ]:\n            tk.Label(info, text=txt, font=FONTS[\"small\"], fg=C[\"text_dim\"],\n                     bg=\"#0D1A0D\", anchor=\"w\").pack(anchor=\"w\", padx=12, pady=1)\n        tk.Label(info, text=\"\", bg=\"#0D1A0D\").pack(pady=2)\n\n        self._action_card_grid(top, [\n            (\"\ud83d\udd0d\", \"Scan Missing\",  \"Error/missing drivers dhundo\", C[\"error\"],   self._easydriver_scan_and_show),\n            (\"\ud83d\udccb\", \"Scan Outdated\", \"Purane drivers list karo\",       C[\"btn_warn\"], self._easydriver_show_outdated),\n            (\"\ud83c\udf10\", \"Update via WU\",  \"Windows Update se install karo\", C[\"btn_chip\"], self._easydriver_update_via_windows_update),\n            (\"\ud83d\udcbe\", \"Backup All\",    \"Saare installed drivers export karo\", C[\"accent2\"], self._easydriver_backup_all),\n            (\"\ud83d\udce5\", \"Restore Backup\", \"Backup folder se restore karo\",   C[\"btn_chip\"], self._easydriver_restore_from_backup),\n            (\"\ud83d\udda5\", \"Device Manager\", \"Windows Device Manager kholo\",   C[\"btn\"],     lambda: self._run_cmd(\"devmgmt.msc\", timeout=5)),\n        ], cols=3)\n\n        # \u2500\u2500 Progress bar (always visible, fixed below buttons) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        clone_prog_frame = tk.Frame(content, bg=C[\"card\"], relief=\"flat\", bd=0)\n        clone_prog_frame.pack(fill=\"x\", padx=16, pady=(4, 2))\n        self.clone_status_label = tk.Label(\n            clone_prog_frame,\n            text=\"Ready\",\n            font=FONTS[\"small\"],\n            fg=C[\"text_dim\"],\n            bg=C[\"card\"],\n            anchor=\"w\"\n        )\n        self.clone_status_label.pack(fill=\"x\", padx=6, pady=(4, 2))\n        self.clone_progress_var = tk.DoubleVar(value=0.0)\n        self.clone_progress_bar = ttk.Progressbar(\n            clone_prog_frame,\n            variable=self.clone_progress_var,\n            maximum=100.0,\n            mode=\"determinate\"\n        )\n        self.clone_progress_bar.pack(fill=\"x\", padx=6, pady=(0, 6))\n\n        # \u2500\u2500 Scrollable body: tree + log \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        body_outer = tk.Frame(content, bg=C[\"bg\"])\n        body_outer.pack(fill=\"both\", expand=True, padx=16, pady=(4, 6))\n\n        cols = (\"Device Name\", \"Status\", \"Class\", \"Severity\", \"Action\")\n        self.driver_easy_tree = ttk.Treeview(body_outer, columns=cols, show=\"headings\",\n                                              height=12, style=\"Custom.Treeview\",\n                                              selectmode=\"browse\")\n        for col, w in zip(cols, [300, 90, 120, 90, 150]):\n            self.driver_easy_tree.heading(col, text=col)\n            self.driver_easy_tree.column(col, width=w, anchor=\"w\")\n        self.driver_easy_tree.tag_configure(\"critical\", foreground=C[\"error\"])\n        self.driver_easy_tree.tag_configure(\"warning\", foreground=C[\"warning\"])\n        self.driver_easy_tree.tag_configure(\"ok\", foreground=C[\"success\"])\n\n        vsb = ttk.Scrollbar(body_outer, orient=\"vertical\", command=self.driver_easy_tree.yview)\n        self.driver_easy_tree.configure(yscrollcommand=vsb.set)\n        self.driver_easy_tree.pack(side=\"left\", fill=\"both\", expand=True)\n        vsb.pack(side=\"right\", fill=\"y\")\n\n        self.driver_easy_log = self._scrolled_text(content, height=6)\n        self.driver_easy_rows = []\n        return frame\n\n    def _easydriver_set_progress(self, pct, text=None, mode=\"determinate\"):\n        def _update():\n            try:\n                pct_float = max(0.0, min(100.0, float(pct)))\n            except Exception:\n                pct_float = 0.0\n            if hasattr(self, \"clone_progress_bar\"):\n                try:\n                    self.clone_progress_bar.stop()\n                    self.clone_progress_bar.config(mode=mode)\n                    if mode == \"indeterminate\":\n                        self.clone_progress_bar.start(10)\n                except Exception:\n                    pass\n            if hasattr(self, \"clone_progress_var\"):\n                try:\n                    self.clone_progress_var.set(pct_float)\n                except Exception:\n                    pass\n            if hasattr(self, \"clone_status_label\") and text is not None:\n                self.clone_status_label.config(text=f\"{int(pct_float)}% - {str(text)[:180]}\")\n        self.after(0, _update)\n\n    def _easydriver_scan_and_show(self):\n        self._append_log(self.driver_easy_log, \"\ud83d\udd0d Easy Driver scan starting...\", C[\"accent\"])\n        self._easydriver_set_progress(0, \"Scanning missing/error drivers...\")\n        self._launch_job(\"easy_driver_scan\", self._do_easydriver_scan)\n\n    def _easydriver_show_outdated(self):\n        self._append_log(self.driver_easy_log, \"\ud83d\udd0d Easy Driver outdated scan starting...\", C[\"accent\"])\n        self._easydriver_set_progress(0, \"Scanning outdated drivers...\")\n        self._launch_job(\"easy_driver_outdated\", self._do_easydriver_show_outdated)\n\n    def _easydriver_check_internet(self):\n        import urllib.request\n        import urllib.error\n\n        for url in [\n            \"https://www.microsoft.com\",\n            \"https://www.google.com\",\n            \"https://1.1.1.1\",\n        ]:\n            try:\n                urllib.request.urlopen(url, timeout=5)\n                return True\n            except Exception:\n                continue\n\n        messagebox.showerror(\n            \"Internet Connection Nahi Mili\",\n            \"Driver auto-download ke liye internet zaroori hai.\\n\\n\"\n            \"Kya check karo:\\n\"\n            \"  1\ufe0f\u20e3  Wi-Fi ya LAN cable connected hai?\\n\"\n            \"  2\ufe0f\u20e3  Antivirus/Firewall block to nahi kar raha?\\n\"\n            \"  3\ufe0f\u20e3  Browser mein koi website khulti hai?\\n\\n\"\n            \"Offline kya kar sakte hain:\\n\"\n            \"  \u2705 Driver Scan \u2014 chalegi\\n\"\n            \"  \u2705 Driver Backup \u2014 chalegi (pnputil)\\n\"\n            \"  \u2705 Driver Restore \u2014 chalegi (agar backup hai)\\n\"\n            \"  \u274c Auto Download \u2014 nahi chalegi\"\n        )\n        return False\n\n    def _easydriver_update_via_windows_update(self):\n        if not hasattr(self, \"driver_easy_log\") and hasattr(self, \"driver_log\"):\n            self.driver_easy_log = self.driver_log\n        if not self._easydriver_check_internet():\n            return\n\n        if not messagebox.askyesno(\n            \"Windows Update Driver\",\n            \"Windows Update se drivers download aur install honge.\\n\\n\"\n            \"\u26a0 Kuch drivers ke liye reboot required hoga.\\n\"\n            \"\u26a0 Installation mein 5-15 minute lag sakta hai.\\n\\n\"\n            \"Pehle system restore point create kiya jaayega.\\n\\n\"\n            \"Continue karein?\"\n        ):\n            return\n\n        self._easydriver_set_progress(5, \"Creating restore point...\")\n        self._append_log(self.driver_easy_log, \"System Restore Point bana raha hoon...\", C[\"accent4\"])\n        rp = safe_powershell(\n            'Checkpoint-Computer -Description \"GodawariDriverUpdate\" '\n            '-RestorePointType DEVICE_DRIVER_INSTALL', timeout=120)\n        if rp.returncode == 0:\n            self._append_log(self.driver_easy_log, \"\u2705 Restore point created\", C[\"success\"])\n\n        wu_script = r\"\"\"\n        try {\n            $UpdateSession = New-Object -ComObject Microsoft.Update.Session\n            $Searcher = $UpdateSession.CreateUpdateSearcher()\n            $SearchResult = $Searcher.Search(\"IsInstalled=0 and Type='Driver'\")\n\n            $Updates = $SearchResult.Updates\n            $Count = $Updates.Count\n\n            if ($Count -eq 0) {\n                Write-Output \"NO_UPDATES\"\n                exit 0\n            }\n\n            Write-Output \"FOUND:$Count\"\n\n            $ToInstall = New-Object -ComObject Microsoft.Update.UpdateColl\n            for ($i=0; $i -lt $Updates.Count; $i++) {\n                $update = $Updates.Item($i)\n                Write-Output \"DRIVER:$($update.Title)\"\n                $ToInstall.Add($update) | Out-Null\n            }\n\n            $Downloader = $UpdateSession.CreateUpdateDownloader()\n            $Downloader.Updates = $ToInstall\n            Write-Output \"DOWNLOADING...\"\n            $DownloadResult = $Downloader.Download()\n            Write-Output \"DOWNLOAD_RC:$($DownloadResult.ResultCode)\"\n\n            $Installer = $UpdateSession.CreateUpdateInstaller()\n            $Installer.Updates = $ToInstall\n            Write-Output \"INSTALLING...\"\n            $InstallResult = $Installer.Install()\n            Write-Output \"INSTALL_RC:$($InstallResult.ResultCode)\"\n            Write-Output \"REBOOT_REQUIRED:$($InstallResult.RebootRequired)\"\n\n        } catch {\n            Write-Output \"ERROR:$($_.Exception.Message)\"\n        }\n        \"\"\"\n\n        def run_wu():\n            self._easydriver_set_progress(15, \"Searching Windows Update drivers...\")\n            result = safe_powershell(wu_script, timeout=600)\n            for line in result.output.splitlines():\n                line = line.strip()\n                if not line:\n                    continue\n                if line == \"NO_UPDATES\":\n                    self._easydriver_set_progress(100, \"No driver updates found.\")\n                    self.after(0, lambda: self._append_log(self.driver_easy_log, \"\u2705 Saare drivers up-to-date hain!\", C[\"success\"]))\n                elif line.startswith(\"FOUND:\"):\n                    count = line.split(\":\", 1)[1]\n                    self._easydriver_set_progress(30, f\"{count} driver update(s) found.\")\n                    self.after(0, lambda c=count: self._append_log(self.driver_easy_log, f\"\ud83d\udd0d {c} driver update(s) mila!\", C[\"accent4\"]))\n                elif line.startswith(\"DRIVER:\"):\n                    name = line.split(\":\", 1)[1]\n                    self.after(0, lambda n=name: self._append_log(self.driver_easy_log, f\"  \ud83d\udce6 {n}\", C[\"text\"]))\n                elif line.startswith(\"DOWNLOADING\"):\n                    self._easydriver_set_progress(45, \"Downloading driver updates...\", \"indeterminate\")\n                elif line.startswith(\"DOWNLOAD_RC:\"):\n                    self._easydriver_set_progress(65, f\"Download finished rc={line.split(':', 1)[1]}\")\n                elif line.startswith(\"INSTALLING\"):\n                    self._easydriver_set_progress(75, \"Installing driver updates...\", \"indeterminate\")\n                elif line.startswith(\"INSTALL_RC:\"):\n                    rc = line.split(\":\", 1)[1]\n                    status = \"\u2705 Install successful\" if rc in (\"2\", \"3\") else f\"\u26a0 Install rc={rc}\"\n                    color = C[\"success\"] if rc in (\"2\", \"3\") else C[\"warning\"]\n                    self._easydriver_set_progress(100 if rc in (\"2\", \"3\") else 90, status)\n                    self.after(0, lambda s=status, c=color: self._append_log(self.driver_easy_log, s, c))\n                elif line.startswith(\"REBOOT_REQUIRED:True\"):\n                    self.after(0, lambda: messagebox.showinfo(\n                        \"Reboot Required\",\n                        \"Driver install complete!\\n\\nSystem restart zaroori hai.\\nAbhi restart karein?\"\n                    ))\n                elif line.startswith(\"ERROR:\"):\n                    err = line.split(\":\", 1)[1]\n                    self._easydriver_set_progress(0, f\"Windows Update failed: {err}\")\n                    self.after(0, lambda e=err: self._append_log(self.driver_easy_log, f\"\u274c Error: {e}\", C[\"error\"]))\n\n        self._launch_job(\"easy_driver_update\", run_wu)\n\n    def _easydriver_backup_all(self):\n        backup_dir = filedialog.askdirectory(\n            title=\"Driver Backup Folder Select Karo (naya ya khali folder choose karo)\")\n        if not backup_dir:\n            return\n\n        if not messagebox.askyesno(\n            \"Driver Backup Confirm\",\n            f\"Saare installed drivers yahan export honge:\\n{backup_dir}\\n\\n\" \\\n            \"Isme kuch minute lag sakte hain.\\nContinue?\"):\n            return\n\n        self._append_log(self.driver_easy_log, f\"Driver backup shuru: {backup_dir}\", C[\"accent4\"])\n        self._easydriver_set_progress(0, \"Driver backup starting...\")\n\n        def run_backup():\n            self._easydriver_set_progress(10, \"Exporting installed drivers...\", \"indeterminate\")\n            result = safe_run([\"pnputil\", \"/export-driver\", \"*\", backup_dir], timeout=300)\n            out = (result.output or \"\").strip()\n            rc = result.returncode\n            inf_count = 0\n            try:\n                for root, _, files in os.walk(backup_dir):\n                    for f in files:\n                        if f.lower().endswith(\".inf\"):\n                            inf_count += 1\n            except Exception:\n                pass\n            if rc == 0:\n                self._easydriver_set_progress(100, f\"Backup complete: {inf_count} drivers exported.\")\n                self.after(0, lambda: self._append_log(\n                    self.driver_easy_log,\n                    f\"\u2705 Backup complete! {inf_count} drivers exported to:\\n{backup_dir}\",\n                    C[\"success\"]))\n                self.after(0, lambda: messagebox.showinfo(\n                    \"Backup Complete\",\n                    f\"\u2705 {inf_count} driver files backup ho gaye!\\n\\nLocation:\\n{backup_dir}\\n\\n\"\n                    \"Restore ke liye: 'Restore From Backup' button dabao.\"))\n            else:\n                self._easydriver_set_progress(0, f\"Backup failed rc={rc}\")\n                self.after(0, lambda: self._append_log(\n                    self.driver_easy_log,\n                    f\"\u274c Backup failed (rc={rc})\\n{out[:300]}\",\n                    C[\"error\"]))\n\n        self._launch_job(\"easy_driver_backup\", run_backup)\n\n    def _easydriver_restore_from_backup(self):\n        backup_dir = filedialog.askdirectory(\n            title=\"Driver Backup Folder Select Karo (jahan .inf files hain)\")\n        if not backup_dir:\n            return\n\n        inf_files = [f for f in os.listdir(backup_dir) if f.lower().endswith(\".inf\")]\n        if not inf_files:\n            messagebox.showerror(\"INF Files Nahi Mili\",\n                                 f\"Selected folder mein koi .inf file nahi mili:\\n{backup_dir}\\n\\n\"\n                                 \"Sahi backup folder select karo.\")\n            return\n\n        if not messagebox.askyesno(\n            \"Driver Restore Confirm\",\n            f\"Folder: {backup_dir}\\n\"\n            f\"INF files found: {len(inf_files)}\\n\\n\"\n            \"\u26a0 Yeh sab drivers install karne ki koshish karega.\\n\"\n            \"\u26a0 Kuch drivers ke liye reboot required ho sakta hai.\\n\"\n            \"\u26a0 Sirf digitally signed drivers install honge.\\n\\n\"\n            \"Continue?\"):\n            return\n\n        self._append_log(self.driver_easy_log,\n                         f\"Driver restore shuru: {backup_dir} ({len(inf_files)} INF files)\",\n                         C[\"accent4\"])\n        self._easydriver_set_progress(0, f\"Restoring {len(inf_files)} driver INF files...\")\n\n        def run_restore():\n            self._easydriver_set_progress(15, \"Installing drivers from backup...\", \"indeterminate\")\n            backup_dir_abs = os.path.abspath(backup_dir)\n            cmd = [\n                \"pnputil\",\n                \"/add-driver\",\n                backup_dir_abs,\n                \"/subdirs\",\n                \"/install\",\n            ]\n            result = safe_run(cmd, timeout=600)\n            out = (result.output or \"\").strip()\n            rc = result.returncode\n            installed = sum(1 for line in out.splitlines() if \"published name\" in line.lower())\n            failed = sum(1 for line in out.splitlines() if \"failed\" in line.lower())\n            status = \"OK\" if rc == 0 else \"PARTIAL\"\n            color = C[\"success\"] if status == \"OK\" else C[\"warning\"]\n            self._easydriver_set_progress(100 if rc == 0 else 90, f\"Restore {status}: {installed} installed, {failed} failed\")\n            self.after(0, lambda: self._append_log(\n                self.driver_easy_log,\n                f\"{'\u2705' if status=='OK' else '\u26a0'} Restore complete: \"\n                f\"{installed} drivers installed, {failed} failed\\n\"\n                f\"Return code: {rc}\",\n                color))\n            if rc == 0:\n                self.after(0, lambda: messagebox.showinfo(\n                    \"Restore Complete\",\n                    f\"\u2705 Driver restore complete!\\n\\n\"\n                    f\"Installed: {installed}\\n\"\n                    f\"Failed: {failed}\\n\\n\"\n                    \"System restart recommended.\"))\n\n        self._launch_job(\"easy_driver_restore\", run_restore)\n\n    def _easydriver_fill_tree(self, rows):\n        self.driver_easy_tree.delete(*self.driver_easy_tree.get_children())\n        for row in rows:\n            self.driver_easy_tree.insert(\"\", \"end\",\n                values=(row[\"name\"], row[\"status\"], row[\"class\"], row[\"severity\"], row[\"action\"]),\n                tags=(row[\"severity\"],))\n\n    def _easydriver_scan_missing(self):\n        script = \"\"\"\n        $devices = Get-PnpDevice -PresentOnly |\n            Where-Object { $_.Status -ne 'OK' } |\n            Select-Object Status, Class, FriendlyName, InstanceId,\n                          @{N='HardwareID';E={($_.HardwareID -join ';')}} |\n            ConvertTo-Json -Depth 2\n        \"\"\"\n        result = safe_powershell(script, timeout=60)\n        if result.returncode != 0 or not result.output.strip():\n            return self._easydriver_scan_missing_wmi()\n        try:\n            data = json.loads(result.output)\n            if isinstance(data, dict):\n                data = [data]\n        except json.JSONDecodeError:\n            return self._easydriver_scan_missing_wmi()\n        missing = []\n        for device in data:\n            name = device.get(\"FriendlyName\") or device.get(\"InstanceId\") or \"Unknown Device\"\n            status = device.get(\"Status\") or \"Unknown\"\n            missing.append({\n                \"name\": name,\n                \"status\": status,\n                \"class\": device.get(\"Class\") or \"Unknown\",\n                \"severity\": \"critical\" if status.lower() in (\"error\",\"unknown\") else \"warning\",\n                \"action\": \"Install Driver\" if status.lower() == \"unknown\" else \"Update Driver\",\n            })\n        return missing\n\n    def _easydriver_scan_missing_wmi(self):\n        script = \"\"\"\n        Get-WmiObject Win32_PnPEntity |\n        Where-Object { $_.ConfigManagerErrorCode -ne 0 } |\n        Select-Object Name, ConfigManagerErrorCode, DeviceID,\n                      @{N='HardwareID';E={($_.HardwareID -join ';')}} |\n        ConvertTo-Json\n        \"\"\"\n        result = safe_powershell(script, timeout=60)\n        try:\n            data = json.loads(result.output)\n            if isinstance(data, dict):\n                data = [data]\n            return [{\n                \"name\": d.get(\"Name\", \"Unknown\"),\n                \"status\": f\"Error Code {d.get('ConfigManagerErrorCode')}\",\n                \"class\": \"Unknown\",\n                \"severity\": \"warning\",\n                \"action\": \"Update Driver\",\n            } for d in data if d.get(\"Name\")]\n        except Exception:\n            return []\n\n    def _do_easydriver_scan(self):\n        try:\n            self._easydriver_set_progress(20, \"Querying PnP devices...\")\n            self.after(0, lambda: self._append_log(self.driver_easy_log, \"\ud83d\udd0d WMI aur PnP device query chal rahi hai...\", C[\"text_dim\"]))\n            rows = self._easydriver_scan_missing()\n            self._easydriver_set_progress(70, \"Preparing scan results...\")\n            if not rows:\n                self._easydriver_set_progress(100, \"No missing/error drivers detected.\")\n                self.after(0, lambda: self._append_log(self.driver_easy_log, \"\u2705 No missing or error drivers detected.\", C[\"success\"]))\n                self.after(0, lambda: self._easydriver_fill_tree([]))\n                return\n            for device in rows:\n                name = device.get(\"name\", \"Unknown\")\n                self.after(0, lambda n=name: self._append_log(self.driver_easy_log, f\"  \u2022 Checking: {n}\", C[\"text_dim\"]))\n            self.after(0, lambda: self._easydriver_fill_tree(rows))\n            self._easydriver_set_progress(100, f\"{len(rows)} problem device(s) detected.\")\n            self.after(0, lambda: self._append_log(self.driver_easy_log, f\"\u2705 {len(rows)} problem device(s) detected.\", C[\"warning\"]))\n        except Exception as e:\n            self._easydriver_set_progress(0, f\"Driver scan failed: {e}\")\n            self.after(0, lambda: self._append_log(self.driver_easy_log, f\"\u26a0 Driver scan failed: {e}\", C[\"error\"]))\n\n    def _do_easydriver_show_outdated(self):\n        try:\n            self._easydriver_set_progress(20, \"Reading signed driver inventory...\")\n            script = \"\"\"\n            Get-WmiObject Win32_PnPSignedDriver |\n            Select-Object DeviceName,DriverVersion,DriverDate,IsSigned,InfName |\n            ConvertTo-Json -Depth 2\n            \"\"\"\n            result = safe_powershell(script, timeout=120)\n            if result.returncode != 0 or not result.output.strip():\n                raise RuntimeError(\"Driver WMI query failed\")\n            data = json.loads(result.output)\n            if isinstance(data, dict):\n                data = [data]\n            rows = []\n            now = datetime.datetime.now()\n            total = max(1, len(data))\n            for d in data:\n                dt = self._driver_parse_date(d.get(\"DriverDate\"))\n                days = (now - dt).days if dt else None\n                signed = bool(d.get(\"IsSigned\"))\n                if days is None or days &lt; 365:\n                    continue\n                rows.append({\n                    \"name\": d.get(\"DeviceName\") or \"Unknown\",\n                    \"status\": \"Signed\" if signed else \"Unsigned\",\n                    \"class\": d.get(\"InfName\") or \"Driver Package\",\n                    \"severity\": \"critical\" if not signed else \"warning\",\n                    \"action\": f\"{days} days old\",\n                })\n                if len(rows) % 20 == 0:\n                    self._easydriver_set_progress(min(85, 20 + int((len(rows) / total) * 60)), \"Analyzing driver ages...\")\n            if not rows:\n                self._easydriver_set_progress(100, \"No outdated drivers older than 365 days found.\")\n                self.after(0, lambda: self._append_log(self.driver_easy_log, \"\u2705 No outdated drivers older than 365 days found.\", C[\"success\"]))\n                self.after(0, lambda: self._easydriver_fill_tree([]))\n                return\n            self.after(0, lambda: self._easydriver_fill_tree(rows))\n            self._easydriver_set_progress(100, f\"{len(rows)} outdated drivers detected.\")\n            self.after(0, lambda: self._append_log(self.driver_easy_log, f\"\u2705 {len(rows)} outdated drivers detected.\", C[\"warning\"]))\n        except Exception as e:\n            self._easydriver_set_progress(0, f\"Outdated scan failed: {e}\")\n            self.after(0, lambda: self._append_log(self.driver_easy_log, f\"\u26a0 Outdated scan failed: {e}\", C[\"error\"]))\n\n    def _build_partition_manager(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udcbd Partition Manager\",\n                             \"Partition operations with safe merge, shrink, extend, format, clone, and restore support.\")\n        content = self._scrollable_section_body(frame)\n\n        # \u2500\u2500 Fixed top: action buttons \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        top = tk.Frame(content, bg=C[\"bg\"])\n        top.pack(fill=\"x\")\n\n        self._action_card_grid(top, [\n            (\"\ud83d\udd04\", \"Refresh\", \"Partition map refresh karo\", C[\"accent\"], self._partition_refresh_tree),\n            (\"\ud83d\udd17\", \"Merge\", \"Do partitions merge karo\", C[\"accent2\"], self._partition_merge_prompt),\n            (\"\u2194\ufe0f\", \"Split\", \"Partition split karo\", C[\"btn_warn\"], self._partition_split_prompt),\n            (\"\u2b06\ufe0f\", \"Extend\", \"Partition expand karo\", C[\"btn_chip\"], self._partition_extend_prompt),\n            (\"\u2b07\ufe0f\", \"Shrink\", \"Partition shrink karo\", C[\"warning\"], self._partition_shrink_prompt),\n            (\"\ud83c\udf00\", \"Clone\", \"Partition contents clone karo\", C[\"btn\"], self._partition_clone_prompt),\n            (\"\u2699\ufe0f\", \"Format\", \"Partition NTFS format karo\", C[\"error\"], self._partition_format_prompt),\n            (\"\ud83d\udd20\", \"Change Letter\", \"Drive letter change karo\", C[\"btn\"], self._partition_change_letter_prompt),\n            (\"\u26d4\", \"Cancel\", \"Running partition op cancel karo\", C[\"warning\"], self._partition_cancel_operation),\n            (\"\ud83d\udcbe\", \"Backup Table\", \"Partition table ka backup banao\", C[\"accent4\"], self._partition_backup_table),\n        ], cols=3)\n\n        # \u2500\u2500 Progress bars (FIXED \u2014 always visible, below buttons) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        prog_container = tk.Frame(content, bg=C[\"bg\"])\n        prog_container.pack(fill=\"x\", padx=16, pady=(6, 2))\n\n        # Operation progress bar\n        progress_label_frame = tk.Frame(prog_container, bg=C[\"bg\"])\n        progress_label_frame.pack(fill=\"x\")\n        self.partition_op_status = tk.Label(\n            progress_label_frame,\n            text=\"Ready for partition operations.\",\n            font=FONTS[\"small\"],\n            fg=C[\"text_dim\"],\n            bg=C[\"bg\"],\n            anchor=\"w\",\n        )\n        self.partition_op_status.pack(side=\"left\", fill=\"x\", expand=True)\n        self.partition_op_pct_label = tk.Label(\n            progress_label_frame,\n            text=\"0%\",\n            font=FONTS[\"small\"],\n            fg=C[\"text_dim\"],\n            bg=C[\"bg\"],\n            anchor=\"e\",\n            width=6,\n        )\n        self.partition_op_pct_label.pack(side=\"right\")\n        self.partition_op_progress_var = tk.DoubleVar(value=0.0)\n        self.partition_op_progress_bar = ttk.Progressbar(\n            prog_container,\n            variable=self.partition_op_progress_var,\n            maximum=100.0,\n            mode=\"determinate\",\n        )\n        self.partition_op_progress_bar.pack(fill=\"x\", pady=(2, 6))\n\n        # Merge-specific progress bar\n        self.partition_merge_status_label = tk.Label(\n            prog_container,\n            text=\"Ready for partition merge operations.\",\n            font=FONTS[\"small\"],\n            fg=C[\"text_dim\"],\n            bg=C[\"bg\"],\n            anchor=\"w\",\n        )\n        self.partition_merge_status_label.pack(fill=\"x\")\n        self.partition_merge_progress_var = tk.DoubleVar(value=0.0)\n        self.partition_merge_progress = ttk.Progressbar(\n            prog_container,\n            variable=self.partition_merge_progress_var,\n            maximum=100.0,\n            mode=\"determinate\"\n        )\n        self.partition_merge_progress.pack(fill=\"x\", pady=(2, 4))\n\n        # \u2500\u2500 Disk bar canvas (responsive width &amp; redraw on resize) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        self.partition_canvas = tk.Canvas(content, height=self._dpi_px(80), bg=C[\"card\"], bd=0, highlightthickness=0)\n        self.partition_canvas.pack(fill=\"x\", padx=16, pady=(4, 4))\n        self.partition_canvas.bind(\"\", lambda event: self._partition_redraw_disk_bar())\n\n        # \u2500\u2500 Detail label \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        self.partition_detail = tk.Label(content, text=\"Select partition for details.\", font=FONTS[\"small\"],\n                                         fg=C[\"text_dim\"], bg=C[\"bg\"], anchor=\"w\")\n        self.partition_detail.pack(fill=\"x\", padx=16, pady=(0, 2))\n\n        # \u2500\u2500 Tree + log in scrollable body (expands to fill remaining space) \u2500\n        body = tk.Frame(content, bg=C[\"bg\"])\n        body.pack(fill=\"both\", expand=True, padx=16, pady=(0, 4))\n\n        cols = (\"Disk\", \"Partition\", \"Letter\", \"Type\", \"SizeGB\", \"FS\", \"Health\")\n        self.partition_tree = ttk.Treeview(body, columns=cols, show=\"headings\",\n                                           height=14, style=\"Custom.Treeview\",\n                                           selectmode=\"extended\")\n        for col, width in zip(cols, [60, 70, 70, 140, 90, 110, 110]):\n            self.partition_tree.heading(col, text=col)\n            self.partition_tree.column(col, width=width, anchor=\"w\")\n        self.partition_tree.tag_configure(\"warning\", foreground=C[\"warning\"])\n        self.partition_tree.tag_configure(\"error\", foreground=C[\"error\"])\n        self.partition_tree.pack(side=\"left\", fill=\"both\", expand=True)\n\n        vsb = ttk.Scrollbar(body, orient=\"vertical\", command=self.partition_tree.yview)\n        self.partition_tree.configure(yscrollcommand=vsb.set)\n        vsb.pack(side=\"right\", fill=\"y\")\n\n        self.partition_tree.bind(\"&lt;&gt;\", self._partition_on_tree_select)\n\n        self.partition_log = self._scrolled_text(content, height=5)\n        self.partition_data = {}\n        self._partition_refresh_tree()\n        return frame\n\n    def _partition_refresh_tree(self):\n        self._append_log(self.partition_log, \"\ud83d\udd04 Refreshing partition map...\", C[\"accent\"])\n        self._launch_job(\"partition_refresh\", self._partition_refresh_worker)\n\n    def _partition_refresh_worker(self):\n        try:\n            self._partition_update_progress(10, \"Querying disk and partition metadata...\")\n            data = self._partition_fetch_all_disks()\n            if not data or not data.get(\"Partitions\"):\n                self._partition_update_progress(0, \"Partition refresh failed: no data returned.\")\n                self.after(0, lambda: self._append_log(self.partition_log, \"\u274c Partition refresh failed.\", C[\"error\"]))\n                return\n            self.partition_data = data\n            self.after(0, lambda: self._partition_render_tree(data))\n            self._partition_update_progress(100, \"Partition map refreshed.\")\n            self.after(0, lambda: self._append_log(self.partition_log, \"\u2705 Partition map refreshed.\", C[\"success\"]))\n        except Exception as e:\n            self._partition_update_progress(0, f\"Partition refresh failed: {e}\")\n            self.after(0, lambda: self._append_log(self.partition_log, f\"\u274c Partition refresh failed: {e}\", C[\"error\"]))\n        finally:\n            self._partition_reset_progress_delayed(1500)\n\n    def _partition_update_progress(self, pct, status_text):\n        def _update():\n            try:\n                pct_float = max(0.0, min(100.0, float(pct)))\n            except Exception:\n                pct_float = 0.0\n            if hasattr(self, \"partition_op_progress_var\"):\n                self.partition_op_progress_var.set(pct_float)\n            if hasattr(self, \"partition_op_status\"):\n                self.partition_op_status.config(text=str(status_text)[:200])\n            if hasattr(self, \"partition_op_pct_label\"):\n                self.partition_op_pct_label.config(text=f\"{int(pct_float)}%\")\n            if hasattr(self, \"partition_merge_status_label\"):\n                self.partition_merge_status_label.config(text=str(status_text)[:200])\n            if hasattr(self, \"partition_merge_progress_var\"):\n                self.partition_merge_progress_var.set(pct_float)\n        self.after(0, _update)\n\n    def _partition_reset_progress_delayed(self, delay_ms=3000, session_id=None):\n        def _reset():\n            with self._partition_op_lock:\n                if session_id and self._partition_operation_session != session_id:\n                    return\n            self._partition_update_progress(0, \"Ready for partition operations.\")\n        self.after(delay_ms, _reset)\n\n    def _partition_start_operation(self, name):\n        with self._partition_op_lock:\n            if self._partition_operation_active:\n                return False, \"Another partition operation is already running.\"\n            self._partition_operation_active = True\n            self._partition_operation_session = f\"partition-{int(time.time() * 1000)}\"\n            self._partition_cancel_event.clear()\n            self._partition_operation_log = []\n            self._partition_operation_start_time = time.time()\n        self._partition_update_progress(0, f\"{name} initializing...\")\n        self._audit_event(\"partition_operation_start\", {\n            \"session\": self._partition_operation_session,\n            \"name\": name,\n        })\n        return True, self._partition_operation_session\n\n    def _partition_end_operation(self, session_id, success, message, color=C[\"success\"]):\n        with self._partition_op_lock:\n            if self._partition_operation_session != session_id:\n                return\n            elapsed = time.time() - (self._partition_operation_start_time or time.time())\n            self._partition_operation_active = False\n            self._partition_operation_session = None\n            self._partition_operation_start_time = None\n        self._audit_event(\"partition_operation_end\", {\n            \"session\": session_id,\n            \"success\": success,\n            \"message\": message,\n            \"elapsed_seconds\": round(elapsed, 2),\n        })\n        self._partition_update_progress(100 if success else 0, message)\n        self._partition_reset_progress_delayed(3000, session_id)\n\n    def _partition_cancel_operation(self):\n        if not self._partition_operation_active:\n            self._append_log(self.partition_log, \"\u26a0 Koi active partition operation nahi hai.\", C[\"warning\"])\n            return\n        self._partition_cancel_event.set()\n        self._partition_update_progress(0, \"Cancellation requested... Please wait.\")\n        self._append_log(self.partition_log, \"\u23f9 Partition operation cancellation requested.\", C[\"warning\"])\n        self._audit_event(\"partition_operation_cancel_requested\", {\"session\": self._partition_operation_session})\n\n    def _partition_operation_is_cancelled(self):\n        return self._partition_cancel_event.is_set()\n\n    def _partition_log_diagnostic(self, level, message, extra=None):\n        entry = {\n            \"ts\": datetime.datetime.now().isoformat(timespec=\"seconds\"),\n            \"level\": level,\n            \"message\": message,\n        }\n        if extra:\n            entry.update(extra)\n        self._partition_operation_log.append(entry)\n        self._audit_event(\"partition_operation_log\", entry)\n        color = C[\"success\"] if level == \"OK\" else C[\"warning\"] if level in (\"WARN\", \"INFO\") else C[\"error\"]\n        self._append_log(self.partition_log, message, color)\n\n    def _partition_run_powershell_cancelable(self, script, timeout=60):\n        Result = collections.namedtuple(\"Result\", [\"returncode\", \"output\"])\n        proc = subprocess.Popen(\n            [\"powershell\", \"-NoProfile\", \"-NonInteractive\", \"-Command\", script],\n            stdout=subprocess.PIPE,\n            stderr=subprocess.PIPE,\n            text=True,\n            creationflags=subprocess.CREATE_NO_WINDOW,\n        )\n        deadline = time.time() + timeout\n        while proc.poll() is None and time.time() &lt; deadline:\n            if self._partition_operation_is_cancelled():\n                proc.terminate()\n                try:\n                    proc.wait(10)\n                except Exception:\n                    proc.kill()\n                return Result(1, \"Operation cancelled\")\n            time.sleep(0.5)\n        if proc.poll() is None:\n            proc.kill()\n            return Result(1, \"Timeout waiting for PowerShell\")\n        out, err = proc.communicate()\n        return Result(proc.returncode, (out or \"\") + (err or \"\"))\n\n    def _partition_run_cmd_cancelable(self, cmd, timeout=3600):\n        start = time.time()\n        proc = subprocess.Popen(\n            cmd,\n            stdout=subprocess.PIPE,\n            stderr=subprocess.PIPE,\n            text=True,\n            creationflags=subprocess.CREATE_NO_WINDOW,\n        )\n        while proc.poll() is None:\n            if self._partition_operation_is_cancelled():\n                proc.terminate()\n                try:\n                    proc.wait(10)\n                except Exception:\n                    proc.kill()\n                return SafeRunResult(\"Operation cancelled\", 1, args=list(cmd), elapsed_ms=int((time.time() - start) * 1000))\n            if time.time() - start &gt; timeout:\n                proc.kill()\n                return SafeRunResult(\"Timeout waiting for command\", -1, args=list(cmd), elapsed_ms=int((time.time() - start) * 1000), timed_out=True)\n            time.sleep(0.5)\n        out, err = proc.communicate()\n        elapsed = int((time.time() - start) * 1000)\n        return SafeRunResult((out or \"\") + (err or \"\"), proc.returncode, args=list(cmd), elapsed_ms=elapsed)\n\n    def _partition_query_disk_info(self, disk_number):\n        script = f\"$d = Get-Disk -Number {disk_number} -ErrorAction Stop; $dyn = $d | Select-Object -ExpandProperty IsDynamic -ErrorAction SilentlyContinue; [pscustomobject]@{{Number=$d.Number;PartitionStyle=$d.PartitionStyle;IsSystem=$d.IsSystem;IsBoot=$d.IsBoot;IsOffline=$d.IsOffline;IsReadOnly=$d.IsReadOnly;IsDynamic=$dyn}} | ConvertTo-Json -Depth 2\"\n        result = safe_powershell(script, timeout=15)\n        if result.returncode != 0 or not result.output.strip():\n            return {}\n        try:\n            return json.loads(result.output)\n        except Exception:\n            return {}\n\n    def _partition_query_partition_info(self, part):\n        if not part or 'DiskNumber' not in part or 'PartitionNumber' not in part:\n            return {}\n        script = f\"Get-Partition -DiskNumber {part['DiskNumber']} -PartitionNumber {part['PartitionNumber']} | Select-Object DriveLetter,Type,IsBoot,IsOffline,AccessPaths,Size,SizeRemaining,IsHidden | ConvertTo-Json -Depth 2\"\n        result = safe_powershell(script, timeout=15)\n        if result.returncode != 0 or not result.output.strip():\n            return {}\n        try:\n            info = json.loads(result.output)\n            if isinstance(info, dict):\n                return info\n            return info[0] if isinstance(info, list) and info else info\n        except Exception:\n            return {}\n\n    def _partition_query_supported_size(self, disk_number, partition_number):\n        script = f\"Get-PartitionSupportedSize -DiskNumber {disk_number} -PartitionNumber {partition_number} | ConvertTo-Json -Depth 2\"\n        result = safe_powershell(script, timeout=15)\n        if result.returncode != 0 or not result.output.strip():\n            return {}\n        try:\n            return json.loads(result.output)\n        except Exception:\n            return {}\n\n    def _partition_query_volume_info(self, drive_letter):\n        if not drive_letter:\n            return {}\n        script = f\"Get-Volume -DriveLetter {drive_letter} | Select-Object DriveLetter,FileSystem,HealthStatus,Size,SizeRemaining,DriveType | ConvertTo-Json -Depth 2\"\n        result = safe_powershell(script, timeout=15)\n        if result.returncode != 0 or not result.output.strip():\n            return {}\n        try:\n            info = json.loads(result.output)\n            if isinstance(info, dict):\n                return info\n            return info[0] if isinstance(info, list) and info else info\n        except Exception:\n            return {}\n\n    def _partition_detect_bitlocker(self, letter):\n        if not letter:\n            return False, \"\"\n        script = f\"try {{ Get-BitLockerVolume -MountPoint '{letter}:' | Select-Object ProtectionStatus,VolumeStatus | ConvertTo-Json -Depth 2 }} catch {{ Write-Output '' }}\"\n        result = safe_powershell(script, timeout=15)\n        if result.returncode != 0 or not result.output.strip():\n            return False, \"\"\n        try:\n            info = json.loads(result.output)\n            protection = info.get('ProtectionStatus') if isinstance(info, dict) else None\n            status = info.get('VolumeStatus') if isinstance(info, dict) else None\n            enabled = protection not in (0, None) or (status and status.lower() != 'fullydecrypted')\n            return bool(enabled), f\"BitLocker status={status}, protection={protection}\"\n        except Exception:\n            return False, \"\"\n\n    def _partition_folder_size(self, path):\n        total = 0\n        try:\n            for root, _, files in os.walk(path):\n                for f in files:\n                    try:\n                        total += os.path.getsize(os.path.join(root, f))\n                    except Exception:\n                        pass\n        except Exception:\n            pass\n        return total\n\n    def _partition_confirm_action(self, title, message, warnings=None):\n        body = message\n        if warnings:\n            body += \"\\n\\nWarnings:\\n\" + \"\\n\".join([f\"- {w}\" for w in warnings])\n        body += \"\\n\\nBackup recommend kiya jata hai. Continue?\"\n        return messagebox.askyesno(title, body)\n\n    def _partition_preflight_checks(self, action, part=None, dest_part=None, new_size=None):\n        result = {\"ok\": True, \"errors\": [], \"warnings\": [], \"details\": {}}\n        if not is_admin():\n            result[\"ok\"] = False\n            result[\"errors\"].append(\"Administrator privileges required for partition operations.\")\n            return result\n        if action in (\"extend\", \"shrink\", \"split\", \"format\", \"change_letter\", \"merge\", \"clone\"):\n            if part is None:\n                result[\"ok\"] = False\n                result[\"errors\"].append(\"Partition metadata missing.\")\n                return result\n            if part.get(\"DriveLetter\", \"\").upper() == \"C\":\n                result[\"errors\"].append(\"System volume C: pe direct operation unsafe hai.\")\n            if part.get(\"Type\") in {\"System\", \"Reserved\", \"Recovery\", \"EFI\", \"Unknown\"}:\n                result[\"warnings\"].append(\"Selected partition type is special or protected.\")\n            disk_info = self._partition_query_disk_info(part[\"DiskNumber\"])\n            if disk_info.get(\"IsOffline\"):\n                result[\"errors\"].append(\"Target disk is offline.\")\n            if disk_info.get(\"IsReadOnly\"):\n                result[\"errors\"].append(\"Target disk is read-only.\")\n            if disk_info.get(\"IsDynamic\"):\n                result[\"warnings\"].append(\"Dynamic disk detected \u2014 partition operations may not be fully supported.\")\n            if disk_info.get(\"PartitionStyle\") not in (\"MBR\", \"GPT\"):\n                result[\"warnings\"].append(\"Unknown or unsupported partition style.\")\n            if action in (\"extend\", \"shrink\", \"split\") and new_size is not None:\n                supported = self._partition_query_supported_size(part[\"DiskNumber\"], part[\"PartitionNumber\"])\n                if supported:\n                    min_size = supported.get(\"SizeMin\") or 0\n                    max_size = supported.get(\"SizeMax\") or 0\n                    requested = int(new_size * 1024 ** 3)\n                    if action == \"shrink\" and requested &lt; min_size:\n                        result[\"errors\"].append(\"Requested shrink size below supported minimum.\")\n                    if action == \"extend\" and requested &gt; max_size:\n                        result[\"errors\"].append(\"Requested extend size exceeds supported maximum.\")\n                    if action == \"split\" and requested &gt;= (part.get(\"Size\") or 0):\n                        result[\"errors\"].append(\"Split size must be smaller than current partition size.\")\n        if action == \"clone\":\n            src_letter = part.get(\"DriveLetter\")\n            dst_letter = dest_part.get(\"DriveLetter\") if dest_part else None\n            if not src_letter or not dst_letter:\n                result[\"errors\"].append(\"Clone ke liye dono source aur destination drive letters chahiye.\")\n            else:\n                source_bytes = self._partition_folder_size(f\"{src_letter}:\\\\\")\n                try:\n                    usage = shutil.disk_usage(f\"{dst_letter}:\\\\\")\n                    if usage.free &lt; source_bytes:\n                        result[\"errors\"].append(\"Destination volume par kaafi free space nahi hai.\")\n                except Exception:\n                    result[\"warnings\"].append(\"Destination free space check failed; manual verify karo.\")\n                if source_bytes == 0:\n                    result[\"warnings\"].append(\"Source folder size calculation zero ya failed. Progress estimate may be inaccurate.\")\n        if action == \"format\":\n            if part.get(\"DriveLetter\", \"\").upper() == \"C\":\n                result[\"errors\"].append(\"System volume C: ko format nahi kiya ja sakta.\")\n            bitlocker_enabled, bitlocker_info = self._partition_detect_bitlocker(part.get(\"DriveLetter\"))\n            if bitlocker_enabled:\n                result[\"errors\"].append(f\"BitLocker enabled on {part.get('DriveLetter', '')}: \u2014 disable before formatting. {bitlocker_info}\")\n        if action == \"change_letter\":\n            new_letter = dest_part if isinstance(dest_part, str) else None\n            if new_letter and new_letter.upper() == \"C\":\n                result[\"errors\"].append(\"Drive letter C: reserved hai \u2014 choose another letter.\")\n        if action == \"merge\":\n            if dest_part and part and part.get(\"DiskNumber\") != dest_part.get(\"DiskNumber\"):\n                result[\"errors\"].append(\"Merge ke liye same disk par partitions hone chahiye.\")\n            if dest_part and abs(int(part.get(\"PartitionNumber\", 0)) - int(dest_part.get(\"PartitionNumber\", 0))) != 1:\n                result[\"errors\"].append(\"Merge ke liye partitions adjacent hone chahiye.\")\n        if result[\"errors\"]:\n            result[\"ok\"] = False\n        return result\n\n    def _partition_verify_post_operation(self, action, part=None, expected=None):\n        if not part or not part.get(\"DiskNumber\"):\n            return False, \"Post-operation verification failed: partition metadata missing.\"\n        if action in (\"extend\", \"shrink\", \"split\"):\n            info = self._partition_query_partition_info(part)\n            if not info:\n                return False, \"Unable to verify partition after resize/split.\"\n            if expected is not None and isinstance(expected, (int, float)):\n                actual_gb = round((info.get(\"Size\") or 0) / (1024 ** 3), 2)\n                if abs(actual_gb - expected) &gt; 0.5:\n                    return False, f\"Expected size {expected} GB, actual {actual_gb} GB.\"\n        if action == \"change_letter\":\n            info = self._partition_query_partition_info(part)\n            if info and str(info.get(\"DriveLetter\", \"\")).upper() != str(expected).upper():\n                return False, f\"Drive letter change verification failed - expected {expected}:.\"\n        if action == \"format\":\n            vol = self._partition_query_volume_info(part.get(\"DriveLetter\"))\n            if not vol or vol.get(\"FileSystem\") != \"NTFS\":\n                return False, f\"Format verification failed \u2014 expected NTFS on {part.get('DriveLetter','')}:\"\n            if vol.get(\"HealthStatus\", \"\").lower() not in (\"healthy\", \"healthy\"):\n                return False, f\"Volume health warning: {vol.get('HealthStatus')}\"\n        return True, \"Verification passed\"\n\n    def _partition_render_tree(self, data):\n        self.partition_tree.delete(*self.partition_tree.get_children())\n        partitions = data.get(\"Partitions\") or []\n        volumes = data.get(\"Volumes\") or []\n        if isinstance(partitions, dict):\n            partitions = [partitions]\n        if isinstance(volumes, dict):\n            volumes = [volumes]\n\n        for part in partitions:\n            disk = part.get(\"DiskNumber\")\n            pno = part.get(\"PartitionNumber\")\n            letter = part.get(\"DriveLetter\") or \"\"\n            ptype = part.get(\"Type\") or \"\"\n            sizegb = part.get(\"SizeGB\") or round((part.get(\"Size\") or 0) / (1024**3), 2)\n            fs = \"\"\n            health = \"\"\n            if letter:\n                vol = next((v for v in volumes if v.get(\"DriveLetter\") == letter), None)\n                if vol:\n                    fs = vol.get(\"FileSystem\") or \"\"\n                    health = vol.get(\"HealthStatus\") or \"\"\n            self.partition_tree.insert(\"\", \"end\", iid=f\"{disk}-{pno}\", values=(disk, pno, letter, ptype, sizegb, fs, health))\n\n        if data.get(\"Disks\"):\n            disk = data.get(\"Disks\")[0]\n            self._partition_selected_disk = str(disk.get(\"Number\"))\n            parts = [p for p in partitions if str(p.get(\"DiskNumber\")) == str(disk.get(\"Number\"))]\n            self._partition_draw_disk_bar(self.partition_canvas, disk, parts)\n\n    def _partition_redraw_disk_bar(self):\n        if not getattr(self, \"partition_data\", None):\n            return\n        selected_disk = getattr(self, \"_partition_selected_disk\", None)\n        disks = self.partition_data.get(\"Disks\") or []\n        disk = None\n        if selected_disk is not None:\n            disk = next((d for d in disks if str(d.get(\"Number\")) == str(selected_disk)), None)\n        if not disk and disks:\n            disk = disks[0]\n            self._partition_selected_disk = str(disk.get(\"Number\"))\n        if not disk:\n            return\n        parts = [p for p in (self.partition_data.get(\"Partitions\") or []) if str(p.get(\"DiskNumber\")) == str(disk.get(\"Number\"))]\n        self._partition_draw_disk_bar(self.partition_canvas, disk, parts)\n\n    def _partition_on_tree_select(self, event=None):\n        sel = self.partition_tree.selection()\n        if not sel:\n            return\n        values = self.partition_tree.item(sel[0])[\"values\"]\n        if len(values) &lt; 2:\n            return\n        disk, pno = values[0], values[1]\n        self._partition_selected_disk = str(disk)\n        part = self._partition_find_data(disk, pno)\n        if not part:\n            return\n        details = [\n            f\"Disk: {disk}\",\n            f\"Partition: {pno}\",\n            f\"Type: {part.get('Type','Unknown')}\",\n            f\"Letter: {part.get('DriveLetter','')}\",\n            f\"Size: {part.get('SizeGB') or round((part.get('Size') or 0)/(1024**3),2)} GB\",\n        ]\n        self.partition_detail.config(text=\" | \".join(details))\n        disk_data = next((d for d in (self.partition_data.get('Disks') or []) if str(d.get('Number')) == str(disk)), None)\n        if disk_data:\n            parts = [p for p in (self.partition_data.get('Partitions') or []) if str(p.get('DiskNumber')) == str(disk)]\n            self._partition_draw_disk_bar(self.partition_canvas, disk_data, parts)\n\n    def _partition_find_data(self, disk, partition_number):\n        for part in (self.partition_data.get(\"Partitions\") or []):\n            if str(part.get(\"DiskNumber\")) == str(disk) and str(part.get(\"PartitionNumber\")) == str(partition_number):\n                return part\n        return None\n\n    def _partition_fetch_all_disks(self):\n        script = \"\"\"\n        $disks = Get-Disk | Select-Object Number,Size,FriendlyName,PartitionStyle,OperationalStatus,@{N='SizeGB';E={[math]::Round($_.Size/1GB,2)}}\n        $parts = Get-Partition | Select-Object DiskNumber,PartitionNumber,DriveLetter,Size,Type,IsActive,IsHidden,@{N='SizeGB';E={[math]::Round($_.Size/1GB,2)}},@{N='AccessPaths';E={$_.AccessPaths -join ';'}}\n        $vols  = Get-Volume | Select-Object DriveLetter,FileSystem,SizeRemaining,Size,HealthStatus,@{N='FreeGB';E={[math]::Round($_.SizeRemaining/1GB,2)}},@{N='TotalGB';E={[math]::Round($_.Size/1GB,2)}}\n        @{Disks=$disks; Partitions=$parts; Volumes=$vols} | ConvertTo-Json -Depth 4\n        \"\"\"\n        result = safe_powershell(script, timeout=30)\n        if result.returncode != 0 or not result.output.strip():\n            return self._partition_fetch_via_wmic()\n        try:\n            return json.loads(result.output)\n        except json.JSONDecodeError:\n            return self._partition_fetch_via_wmic()\n\n    def _partition_fetch_via_wmic(self):\n        script = \"\"\"\n        Get-WmiObject Win32_DiskPartition |\n        Select-Object DiskIndex,Index,Name,Size,Type,Bootable |\n        ConvertTo-Json\n        \"\"\"\n        result = safe_powershell(script, timeout=20)\n        try:\n            data = json.loads(result.output)\n            if isinstance(data, dict):\n                data = [data]\n            return {\"Disks\": [], \"Partitions\": data, \"Volumes\": []}\n        except Exception:\n            return {\"Disks\": [], \"Partitions\": [], \"Volumes\": []}\n\n    def _partition_draw_disk_bar(self, canvas, disk_data, partitions):\n        canvas.delete(\"all\")\n        W = canvas.winfo_width() or 900\n        H = max(self._dpi_px(60), canvas.winfo_height() or self._dpi_px(60))\n        colors = {\n            \"System\": \"#FF6B6B\",\n            \"Primary\": \"#4DABF7\",\n            \"Recovery\": \"#FFD43B\",\n            \"Unknown\": \"#868E96\",\n            \"Unallocated\": \"#2D3436\",\n        }\n        total_bytes = sum(p.get(\"Size\", 0) for p in partitions)\n        if total_bytes == 0:\n            return\n        x = 0\n        for p in partitions:\n            w = int((p.get(\"Size\", 0) / total_bytes) * W)\n            if w &lt; 2:\n                w = 2\n            ptype = p.get(\"Type\", \"Primary\")\n            color = colors.get(ptype, \"#4DABF7\")\n            letter = p.get(\"DriveLetter\") or \"?\"\n            size_gb = round((p.get(\"Size\") or 0) / (1024**3), 1)\n            canvas.create_rectangle(x, 5, x + w - 2, H - 5,\n                                    fill=color, outline=\"#1A1A2A\", width=1)\n            if w &gt; 40:\n                canvas.create_text(x + w//2, H//2,\n                                   text=f\"{letter}:\\n{size_gb}GB\",\n                                   font=(\"Segoe UI\", 8, \"bold\"),\n                                   fill=\"white\", anchor=\"center\")\n            x += w\n        disk_total = disk_data.get(\"Size\", 0)\n        unalloc = disk_total - total_bytes\n        if unalloc &gt; 100 * 1024 * 1024:\n            w = int((unalloc / disk_total) * W)\n            canvas.create_rectangle(x, 5, x + w - 2, H - 5,\n                                    fill=\"#2D3436\", outline=\"#555\", width=1,\n                                    dash=(4, 2))\n            if w &gt; 60:\n                canvas.create_text(x + w//2, H//2,\n                                   text=f\"Free\\n{round(unalloc/(1024**3),1)}GB\",\n                                   font=(\"Segoe UI\", 8), fill=\"#AAA\", anchor=\"center\")\n\n    def _partition_merge_prompt(self):\n        sel = self.partition_tree.selection()\n        if len(sel) != 2:\n            messagebox.showinfo(\"Select Two Partitions\", \"Pehle 2 adjacent partitions select karo \u2014 source aur destination.\")\n            return\n        src_data = self._partition_find_data(*self.partition_tree.item(sel[0])[\"values\"][:2])\n        dst_data = self._partition_find_data(*self.partition_tree.item(sel[1])[\"values\"][:2])\n        if not src_data or not dst_data:\n            return\n        if src_data.get(\"SizeGB\", 0) &gt; dst_data.get(\"SizeGB\", 0):\n            source, dest = dst_data, src_data\n        else:\n            source, dest = src_data, dst_data\n        if not messagebox.askyesno(\"Merge Partitions\",\n                                  f\"Source: {source.get('DriveLetter','')} ({source.get('SizeGB')} GB)\\n\"\n                                  f\"Destination: {dest.get('DriveLetter','')} ({dest.get('SizeGB')} GB)\\n\\n\"\n                                  \"Data source ko destination par copy karke merge kiya jayega. Continue?\" ):\n            return\n        self._launch_job(\"partition_merge\", self._partition_merge_worker, source, dest)\n\n    def _partition_merge_worker(self, source, dest):\n        started, session_id = self._partition_start_operation(\"Merge Partitions\")\n        if not started:\n            self._append_log(self.partition_log, \"\u26a0 Another partition operation is already running.\", C[\"warning\"])\n            return\n        success = False\n        message = \"Partition merge failed\"\n        try:\n            self._partition_update_progress(0, \"Partition merge started...\")\n            success, message = self._partition_merge(source, dest)\n            color = C[\"success\"] if success else C[\"error\"]\n            self.after(0, lambda: self._append_log(self.partition_log, message, color))\n            if success:\n                self._partition_update_progress(100, \"Partition merge completed.\")\n                self.after(0, self._partition_refresh_tree)\n            else:\n                self._partition_update_progress(0, \"Partition merge failed.\")\n        except Exception as e:\n            message = f\"Partition merge failed: {e}\"\n            self._partition_log_diagnostic(\"ERROR\", message)\n            self._partition_update_progress(0, message)\n        finally:\n            self._partition_end_operation(session_id, success, message, C[\"success\"] if success else C[\"error\"])\n\n    def _partition_merge(self, source_part, dest_part):\n        journal = []\n        def update_merge_progress(percent, text=None):\n            self._partition_update_progress(percent, text or \"Merging...\")\n            if text is not None and hasattr(self, \"partition_merge_status_label\"):\n                self.after(0, lambda: self.partition_merge_status_label.config(text=text))\n            if hasattr(self, \"partition_merge_progress_var\"):\n                self.after(0, lambda: self.partition_merge_progress_var.set(max(0.0, min(100.0, float(percent)))))\n\n        def jlog(msg, level=\"INFO\", pct=None):\n            journal.append({\"ts\": datetime.datetime.now().isoformat(), \"level\": level, \"msg\": msg})\n            self._append_log(self.partition_log, msg, C[\"success\"] if level == \"OK\" else C[\"warning\"] if level == \"WARN\" else C[\"error\"])\n            if pct is not None:\n                update_merge_progress(pct, msg)\n\n        if not is_admin():\n            jlog(\"Admin rights nahi hain. Run as Administrator karo.\", \"ERROR\")\n            return False, \"Admin required\"\n\n        if source_part.get(\"DiskNumber\") != dest_part.get(\"DiskNumber\"):\n            jlog(\"Partitions alag disk par hain \u2014 merge supported nahi. Use same disk.\", \"ERROR\")\n            return False, \"Different disks\"\n\n        if abs(int(source_part.get(\"PartitionNumber\", 0)) - int(dest_part.get(\"PartitionNumber\", 0))) != 1:\n            jlog(\"Partitions adjacent nahi hain. Merge ke liye adjacent partitions chahiye.\", \"ERROR\")\n            return False, \"Partitions not adjacent\"\n\n        protected_types = {\"System\", \"Reserved\", \"Recovery\", \"EFI\", \"Unknown\"}\n        if source_part.get(\"Type\") in protected_types or dest_part.get(\"Type\") in protected_types:\n            jlog(\"System/Recovery partition pe merge block hai.\", \"ERROR\")\n            return False, \"Protected partition\"\n\n        jlog(\"SMART check chal raha hai...\", \"INFO\")\n        smart_script = \"\"\"\n        Get-WmiObject -Namespace root/wmi -Class MSStorageDriver_FailurePredictStatus |\n            Select-Object PredictFailure,Reason | ConvertTo-Json\n        \"\"\"\n        smart_result = safe_powershell(smart_script, timeout=15)\n        try:\n            smart_data = json.loads(smart_result.output)\n            if isinstance(smart_data, dict):\n                smart_data = [smart_data]\n            for s in smart_data:\n                if s.get(\"PredictFailure\"):\n                    jlog(\"SMART: Disk failure predicted! Merge BLOCKED. Pehle data backup karo.\", \"ERROR\")\n                    return False, \"SMART failure predicted\"\n        except Exception:\n            jlog(\"SMART check available nahi \u2014 proceeding with caution.\", \"WARN\")\n\n        src_letter = source_part.get(\"DriveLetter\") or self._partition_assign_temp_letter(source_part)\n        dst_letter = dest_part.get(\"DriveLetter\") or self._partition_assign_temp_letter(dest_part)\n        backup_dir = os.path.join(os.environ.get(\"APPDATA\", \"\"), \"GodawariOptimizer\", \"partition_backups\")\n        os.makedirs(backup_dir, exist_ok=True)\n        if src_letter and dst_letter:\n            self._record_rollback_point(\n                \"partition_merge\",\n                details={\n                    \"source_letter\": src_letter,\n                    \"dest_letter\": dst_letter,\n                    \"src_disk\": source_part.get(\"DiskNumber\"),\n                    \"src_partition\": source_part.get(\"PartitionNumber\"),\n                    \"dest_disk\": dest_part.get(\"DiskNumber\"),\n                    \"dest_partition\": dest_part.get(\"PartitionNumber\"),\n                    \"backup_dir\": backup_dir,\n                },\n                snapshot_path=backup_dir)\n        if not src_letter or not dst_letter:\n            jlog(\"Drive letter missing \u2014 merge ke liye drive letters chahiye.\", \"ERROR\")\n            return False, \"Drive letter required\"\n\n        jlog(f\"Data copy shuru kar raha hoon: {src_letter}: \u2192 {dst_letter}: ...\", \"INFO\")\n        ts = datetime.datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n        copy_log = os.path.join(backup_dir, f\"robocopy_{ts}.log\")\n        robocopy_cmd = [\n            \"robocopy\",\n            f\"{src_letter}:\\\\\",\n            f\"{dst_letter}:\\\\GodawariMerge_{ts}\",\n            \"/MIR\", \"/COPYALL\", \"/R:3\", \"/W:5\",\n            \"/NFL\", f\"/LOG:{copy_log}\", \"/TEE\"\n        ]\n        copy_result = safe_run(robocopy_cmd, timeout=7200)\n        if copy_result.returncode &gt;= 8:\n            jlog(f\"Data copy FAILED (rc={copy_result.returncode}). Merge aborted.\", \"ERROR\", pct=20)\n            return False, f\"Robocopy failed: rc={copy_result.returncode}\"\n\n        src_count = self._partition_count_files(f\"{src_letter}:\\\\\")\n        dst_count = self._partition_count_files(f\"{dst_letter}:\\\\GodawariMerge_{ts}\")\n        if src_count &gt; 0 and dst_count &lt; int(src_count * 0.95):\n            jlog(f\"Verification FAILED: src={src_count} files, dst={dst_count} files\", \"ERROR\", pct=40)\n            return False, \"File count mismatch after copy\"\n        jlog(f\"Verification OK: {src_count} \u2192 {dst_count} files\", \"OK\", pct=45)\n\n        diskpart_script = f\"\"\"select disk {source_part['DiskNumber']}\\nselect partition {source_part['PartitionNumber']}\\ndelete partition override\\n\"\"\"\n        diskpart_file = os.path.join(backup_dir, f\"diskpart_delete_{ts}.txt\")\n        with open(diskpart_file, \"w\", encoding=\"utf-8\") as f:\n            f.write(diskpart_script)\n        delete_result = safe_run([\"diskpart\", \"/s\", diskpart_file], timeout=60)\n        if delete_result.returncode != 0:\n            jlog(f\"Partition delete failed: {delete_result.output[:200]}\", \"ERROR\", pct=55)\n            return False, \"Delete failed\"\n        jlog(\"Source partition deleted.\", \"OK\", pct=60)\n\n        extend_script = f\"\"\"select disk {dest_part['DiskNumber']}\\nselect partition {dest_part['PartitionNumber']}\\nextend\\n\"\"\"\n        extend_file = os.path.join(backup_dir, f\"diskpart_extend_{ts}.txt\")\n        with open(extend_file, \"w\", encoding=\"utf-8\") as f:\n            f.write(extend_script)\n        extend_result = safe_run([\"diskpart\", \"/s\", extend_file], timeout=60)\n        if extend_result.returncode != 0:\n            ps_extend = f\"\"\"\n            $maxSize = (Get-PartitionSupportedSize -DiskNumber {dest_part['DiskNumber']} -PartitionNumber {dest_part['PartitionNumber']}).SizeMax\n            Resize-Partition -DiskNumber {dest_part['DiskNumber']} -PartitionNumber {dest_part['PartitionNumber']} -Size $maxSize\n            \"\"\"\n            ps_result = safe_powershell(ps_extend, timeout=60)\n            if ps_result.returncode != 0:\n                jlog(\"Extend FAILED \u2014 manual extend required via Disk Management\", \"ERROR\", pct=70)\n                return False, \"Extend failed\"\n        jlog(\"Partition extended!\", \"OK\", pct=75)\n\n        verify_script = f\"\"\"\n        Get-Partition -DiskNumber {dest_part['DiskNumber']} -PartitionNumber {dest_part['PartitionNumber']} |\n            Select-Object @{{N='SizeGB';E={{[math]::Round($_.Size/1GB,2)}}}} |\n            ConvertTo-Json\n        \"\"\"\n        verify_result = safe_powershell(verify_script, timeout=15)\n        try:\n            new_size = json.loads(verify_result.output).get(\"SizeGB\", 0)\n            expected = round((source_part.get(\"SizeGB\", 0) + dest_part.get(\"SizeGB\", 0)) * 0.98, 1)\n            if new_size &gt;= expected:\n                jlog(f\"VERIFY OK: New size = {new_size} GB\", \"OK\", pct=90)\n            else:\n                jlog(f\"Size verify: {new_size} GB (expected ~{expected} GB) \u2014 check manually\", \"WARN\", pct=85)\n        except Exception:\n            jlog(\"Size verify parse failed \u2014 visually confirm\", \"WARN\", pct=85)\n\n        journal_file = os.path.join(backup_dir, f\"partition_merge_journal_{ts}.json\")\n        with open(journal_file, \"w\", encoding=\"utf-8\") as f:\n            json.dump(journal, f, indent=2, ensure_ascii=False)\n        jlog(f\"Merge complete! Journal saved: {journal_file}\", \"OK\")\n        return True, \"Merge successful\"\n\n    def _partition_count_files(self, path):\n        count = 0\n        try:\n            for root, _, files in os.walk(path):\n                count += len(files)\n        except Exception:\n            pass\n        return count\n\n    def _partition_assign_temp_letter(self, part):\n        if part.get(\"DriveLetter\"):\n            return part[\"DriveLetter\"]\n        existing = [v for v in \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"]\n        script = 'Get-Volume | Select-Object -ExpandProperty DriveLetter | ConvertTo-Json'\n        result = safe_powershell(script, timeout=15)\n        used = set()\n        try:\n            letters = json.loads(result.output)\n            if isinstance(letters, list):\n                used.update([str(x) for x in letters if x])\n            elif isinstance(letters, str):\n                used.add(letters)\n        except Exception:\n            pass\n        for letter in \"RSTUVWXYZ\":\n            if letter in used:\n                continue\n            assign_script = f\"$p = Get-Partition -DiskNumber {part['DiskNumber']} -PartitionNumber {part['PartitionNumber']}; Add-PartitionAccessPath -InputObject $p -AssignDriveLetter -DriveLetter {letter} -ErrorAction SilentlyContinue\"\n            assign_res = safe_powershell(assign_script, timeout=20)\n            if assign_res.returncode == 0:\n                return letter\n        return None\n\n    def _partition_extend_prompt(self):\n        sel = self.partition_tree.selection()\n        if len(sel) != 1:\n            messagebox.showinfo(\"Select Partition\", \"Pehle ek partition select karo.\")\n            return\n        values = self.partition_tree.item(sel[0])[\"values\"]\n        part = self._partition_find_data(*values[:2])\n        if not part:\n            return\n        import tkinter.simpledialog as simpledialog\n        current = part.get(\"SizeGB\") or round((part.get(\"Size\") or 0)/(1024**3),2)\n        new_size = simpledialog.askfloat(\"Extend Partition\", f\"Naya size (GB) enter karo (current {current}):\", initialvalue=current + 10, minvalue=current + 1)\n        if not new_size:\n            return\n        if not messagebox.askyesno(\"Extend Partition\", f\"Partition {part.get('DriveLetter','')} ko {new_size} GB tak extend karna hai?\\nContinue?\"):\n            return\n        preflight = self._partition_preflight_checks(\"extend\", part, new_size=new_size)\n        if not preflight[\"ok\"]:\n            messagebox.showerror(\"Preflight Failed\", \"\\n\".join(preflight[\"errors\"]))\n            return\n        if preflight[\"warnings\"] and not self._partition_confirm_action(\"Extend Partition\", f\"Extending partition {part.get('DriveLetter','')} to {new_size} GB.\", preflight[\"warnings\"]):\n            return\n        dry_run = messagebox.askyesno(\"Dry-Run Recommended\", \"Dry-run preview recommended for partition extend. Yes = preview only, No = run actual operation now.\")\n        self._launch_job(\"partition_extend\", self._partition_extend_worker, part, new_size, dry_run)\n\n    def _partition_extend_worker(self, part, new_size, dry_run=False):\n        started, session_id = self._partition_start_operation(\"Extend Partition\")\n        if not started:\n            self._append_log(self.partition_log, \"\u26a0 Another partition operation is already running.\", C[\"warning\"])\n            return\n        self._partition_log_diagnostic(\"INFO\", f\"Starting partition extend: {part.get('DriveLetter','')} to {new_size} GB\", {\"dry_run\": dry_run})\n        command = f\"Resize-Partition -DiskNumber {part['DiskNumber']} -PartitionNumber {part['PartitionNumber']} -Size ({new_size}GB)\"\n        if dry_run:\n            command += \" -WhatIf\"\n        self._partition_update_progress(15, \"Preparing extend command...\")\n        self._partition_log_diagnostic(\"INFO\", \"Executing Resize-Partition (or dry-run).\")\n        self._partition_update_progress(35, \"Executing PowerShell command...\")\n        result = self._partition_run_powershell_cancelable(command, timeout=90)\n        if self._partition_operation_is_cancelled():\n            self._partition_log_diagnostic(\"WARN\", \"Extend operation cancelled.\")\n            self._partition_end_operation(session_id, False, \"Extend cancelled\", C[\"warning\"])\n            return\n        self._partition_update_progress(70, \"Verifying result...\")\n        if result.returncode == 0:\n            if dry_run:\n                self._partition_log_diagnostic(\"OK\", \"Dry-run complete: extend command validated.\")\n                self._partition_end_operation(session_id, True, \"Dry-run complete\", C[\"success\"])\n                return\n            verify_ok, verify_msg = self._partition_verify_post_operation(\"extend\", part, expected=new_size)\n            if verify_ok:\n                self._partition_log_diagnostic(\"OK\", f\"Extended to {new_size} GB successfully.\")\n                self.after(0, self._partition_refresh_tree)\n                self._partition_end_operation(session_id, True, f\"\u2705 Extended to {new_size} GB successfully!\", C[\"success\"])\n            else:\n                self._partition_log_diagnostic(\"ERROR\", verify_msg)\n                self._partition_end_operation(session_id, False, f\"\u274c Extend verify failed: {verify_msg}\", C[\"error\"])\n        else:\n            self._partition_log_diagnostic(\"ERROR\", f\"Extend failed: {result.output[:200]}\")\n            self._partition_end_operation(session_id, False, \"\u274c Extend failed\", C[\"error\"])\n\n    def _partition_shrink_prompt(self):\n        sel = self.partition_tree.selection()\n        if len(sel) != 1:\n            messagebox.showinfo(\"Select Partition\", \"Pehle ek partition select karo.\")\n            return\n        values = self.partition_tree.item(sel[0])[\"values\"]\n        part = self._partition_find_data(*values[:2])\n        if not part:\n            return\n        import tkinter.simpledialog as simpledialog\n        current = part.get(\"SizeGB\") or round((part.get(\"Size\") or 0)/(1024**3),2)\n        new_size = simpledialog.askfloat(\"Shrink Partition\", f\"Naya size (GB) enter karo (current {current}):\", initialvalue=max(current - 10, 1), minvalue=1, maxvalue=current - 1)\n        if not new_size:\n            return\n        if not messagebox.askyesno(\"Shrink Partition\", f\"Partition {part.get('DriveLetter','')} ko {new_size} GB tak shrink karna hai?\\nContinue?\"):\n            return\n        preflight = self._partition_preflight_checks(\"shrink\", part, new_size=new_size)\n        if not preflight[\"ok\"]:\n            messagebox.showerror(\"Preflight Failed\", \"\\n\".join(preflight[\"errors\"]))\n            return\n        if preflight[\"warnings\"] and not self._partition_confirm_action(\"Shrink Partition\", f\"Shrinking partition {part.get('DriveLetter','')} to {new_size} GB.\", preflight[\"warnings\"]):\n            return\n        dry_run = messagebox.askyesno(\"Dry-Run Recommended\", \"Dry-run preview recommended for partition shrink. Yes = preview only, No = run actual operation now.\")\n        self._launch_job(\"partition_shrink\", self._partition_shrink_worker, part, new_size, dry_run)\n\n    def _partition_shrink_worker(self, part, new_size, dry_run=False):\n        started, session_id = self._partition_start_operation(\"Shrink Partition\")\n        if not started:\n            self._append_log(self.partition_log, \"\u26a0 Another partition operation is already running.\", C[\"warning\"])\n            return\n        self._partition_log_diagnostic(\"INFO\", f\"Starting partition shrink: {part.get('DriveLetter','')} to {new_size} GB\", {\"dry_run\": dry_run})\n        command = f\"Resize-Partition -DiskNumber {part['DiskNumber']} -PartitionNumber {part['PartitionNumber']} -Size ({new_size}GB)\"\n        if dry_run:\n            command += \" -WhatIf\"\n        self._partition_update_progress(15, \"Preparing shrink command...\")\n        self._partition_update_progress(35, \"Executing PowerShell command...\")\n        result = self._partition_run_powershell_cancelable(command, timeout=90)\n        if self._partition_operation_is_cancelled():\n            self._partition_log_diagnostic(\"WARN\", \"Shrink operation cancelled.\")\n            self._partition_end_operation(session_id, False, \"Shrink cancelled\", C[\"warning\"])\n            return\n        self._partition_update_progress(70, \"Verifying shrink result...\")\n        if result.returncode == 0:\n            if dry_run:\n                self._partition_log_diagnostic(\"OK\", \"Dry-run complete: shrink command validated.\")\n                self._partition_end_operation(session_id, True, \"Dry-run complete\", C[\"success\"])\n                return\n            verify_ok, verify_msg = self._partition_verify_post_operation(\"shrink\", part, expected=new_size)\n            if verify_ok:\n                self._partition_log_diagnostic(\"OK\", f\"Shrunk to {new_size} GB successfully.\")\n                self.after(0, self._partition_refresh_tree)\n                self._partition_end_operation(session_id, True, f\"\u2705 Shrunk to {new_size} GB successfully!\", C[\"success\"])\n            else:\n                self._partition_log_diagnostic(\"ERROR\", verify_msg)\n                self._partition_end_operation(session_id, False, f\"\u274c Shrink verify failed: {verify_msg}\", C[\"error\"])\n        else:\n            self._partition_log_diagnostic(\"ERROR\", f\"Shrink failed: {result.output[:200]}\")\n            self._partition_end_operation(session_id, False, \"\u274c Shrink failed\", C[\"error\"])\n\n    def _partition_format_prompt(self):\n        sel = self.partition_tree.selection()\n        if len(sel) != 1:\n            messagebox.showinfo(\"Select Partition\", \"Pehle ek partition select karo.\")\n            return\n        values = self.partition_tree.item(sel[0])[\"values\"]\n        part = self._partition_find_data(*values[:2])\n        if not part:\n            messagebox.showinfo(\"Format Partition\", \"Partition metadata nahi mila.\")\n            return\n        if not messagebox.askyesno(\n            \"Format Partition\",\n            f\"Partition {part.get('DriveLetter','(no letter)')} ko NTFS se format karne se saari files permanently delete ho jayengi.\\n\\n\"\n            \"Yeh operation irreversible hai.\\n\\nContinue?\"\n        ):\n            return\n        preflight = self._partition_preflight_checks(\"format\", part)\n        if not preflight[\"ok\"]:\n            messagebox.showerror(\"Preflight Failed\", \"\\n\".join(preflight[\"errors\"]))\n            return\n        if preflight[\"warnings\"] and not self._partition_confirm_action(\n            \"Format Partition\",\n            f\"Formatting partition {part.get('DriveLetter','')} to NTFS.\",\n            preflight[\"warnings\"]\n        ):\n            return\n        dry_run = messagebox.askyesno(\n            \"Dry-Run Recommended\",\n            \"Dry-run preview recommended for format. Yes = preview only, No = run actual operation now.\"\n        )\n        self._launch_job(\"partition_format\", self._partition_format_worker, part, dry_run)\n\n    def _partition_format_worker(self, part, dry_run=False):\n        started, session_id = self._partition_start_operation(\"Format Partition\")\n        if not started:\n            self._append_log(self.partition_log, \"\u26a0 Another partition operation is already running.\", C[\"warning\"])\n            return\n        self._partition_log_diagnostic(\"INFO\", f\"Starting format on partition {part.get('DriveLetter','')} ({part.get('DiskNumber')}/{part.get('PartitionNumber')})\", {\"dry_run\": dry_run})\n        label = f\"Godawari_{datetime.datetime.now().strftime('%Y%m%d')}\"\n        self._partition_update_progress(10, \"Preparing format command...\")\n        if part.get(\"DriveLetter\"):\n            command = f\"Format-Volume -DriveLetter {part['DriveLetter']} -FileSystem NTFS -NewFileSystemLabel '{label}' -Confirm:$false\"\n        else:\n            command = f\"$part = Get-Partition -DiskNumber {part['DiskNumber']} -PartitionNumber {part['PartitionNumber']}; Format-Volume -Partition $part -FileSystem NTFS -NewFileSystemLabel '{label}' -Confirm:$false\"\n        if dry_run:\n            command += \" -WhatIf\"\n        self._partition_update_progress(35, \"Executing format command...\")\n        result = self._partition_run_powershell_cancelable(command, timeout=120)\n        if self._partition_operation_is_cancelled():\n            self._partition_log_diagnostic(\"WARN\", \"Format operation cancelled.\")\n            self._partition_end_operation(session_id, False, \"Format cancelled\", C[\"warning\"])\n            return\n        if result.returncode == 0:\n            if dry_run:\n                self._partition_log_diagnostic(\"OK\", \"Dry-run complete: format command validated.\")\n                self._partition_end_operation(session_id, True, \"Dry-run complete\", C[\"success\"])\n                return\n            self._partition_update_progress(65, \"Verifying format result...\")\n            verify_ok, verify_msg = self._partition_verify_post_operation(\"format\", part)\n            if verify_ok:\n                self._partition_log_diagnostic(\"OK\", f\"Partition formatted to NTFS successfully.\")\n                self.after(0, self._partition_refresh_tree)\n                self._partition_end_operation(session_id, True, \"\u2705 Partition formatted successfully\", C[\"success\"])\n            else:\n                self._partition_log_diagnostic(\"ERROR\", verify_msg)\n                self._partition_end_operation(session_id, False, f\"\u274c Format verify failed: {verify_msg}\", C[\"error\"])\n        else:\n            self._partition_log_diagnostic(\"ERROR\", f\"Format failed: {result.output[:200]}\")\n            self._partition_end_operation(session_id, False, \"\u274c Format failed\", C[\"error\"])\n\n    def _partition_change_letter_prompt(self):\n        sel = self.partition_tree.selection()\n        if len(sel) != 1:\n            messagebox.showinfo(\"Select Partition\", \"Pehle ek partition select karo.\")\n            return\n        values = self.partition_tree.item(sel[0])[\"values\"]\n        part = self._partition_find_data(*values[:2])\n        if not part:\n            return\n        import tkinter.simpledialog as simpledialog\n        new_letter = simpledialog.askstring(\"Change Drive Letter\", \"Naya drive letter enter karo:\", initialvalue=part.get(\"DriveLetter\") or \"G\")\n        if not new_letter:\n            return\n        letter = new_letter.strip().upper()[:1]\n        if not letter.isalpha():\n            messagebox.showerror(\"Invalid Letter\", \"Sirf A-Z drive letter use karo.\")\n            return\n        if not messagebox.askyesno(\"Change Drive Letter\", f\"{part.get('DriveLetter','')} ko {letter}: pe change karna hai?\\nContinue?\"):\n            return\n        preflight = self._partition_preflight_checks(\"change_letter\", part, dest_part=letter)\n        if not preflight[\"ok\"]:\n            messagebox.showerror(\"Preflight Failed\", \"\\n\".join(preflight[\"errors\"]))\n            return\n        if preflight[\"warnings\"] and not self._partition_confirm_action(\"Change Drive Letter\", f\"Changing drive letter for {part.get('DriveLetter','')} to {letter}:\", preflight[\"warnings\"]):\n            return\n        dry_run = messagebox.askyesno(\"Dry-Run Recommended\", \"Dry-run preview recommended for drive letter change. Yes = preview only, No = run actual operation now.\")\n        self._launch_job(\"partition_change_letter\", self._partition_change_letter_worker, part, letter, dry_run)\n\n    def _partition_change_letter_worker(self, part, letter, dry_run=False):\n        started, session_id = self._partition_start_operation(\"Change Drive Letter\")\n        if not started:\n            self._append_log(self.partition_log, \"\u26a0 Another partition operation is already running.\", C[\"warning\"])\n            return\n        self._partition_log_diagnostic(\"INFO\", f\"Starting drive letter change: {part.get('DriveLetter','')} \u2192 {letter}\", {\"dry_run\": dry_run})\n        command = f\"Set-Partition -DiskNumber {part['DiskNumber']} -PartitionNumber {part['PartitionNumber']} -NewDriveLetter {letter}\"\n        if dry_run:\n            command += \" -WhatIf\"\n        self._partition_update_progress(15, \"Preparing change letter command...\")\n        self._partition_update_progress(50, \"Executing PowerShell Set-Partition...\")\n        result = self._partition_run_powershell_cancelable(command, timeout=45)\n        if self._partition_operation_is_cancelled():\n            self._partition_log_diagnostic(\"WARN\", \"Drive letter change cancelled.\")\n            self._partition_end_operation(session_id, False, \"Change letter cancelled\", C[\"warning\"])\n            return\n        if result.returncode == 0:\n            if dry_run:\n                self._partition_log_diagnostic(\"OK\", \"Dry-run complete: drive letter change command validated.\")\n                self._partition_end_operation(session_id, True, \"Dry-run complete\", C[\"success\"])\n                return\n            verify_ok, verify_msg = self._partition_verify_post_operation(\"change_letter\", part, expected=letter)\n            if verify_ok:\n                self._partition_log_diagnostic(\"OK\", f\"Drive letter changed to {letter} successfully.\")\n                self.after(0, self._partition_refresh_tree)\n                self._partition_end_operation(session_id, True, f\"\u2705 Drive letter changed to {letter}:\", C[\"success\"])\n            else:\n                self._partition_log_diagnostic(\"ERROR\", verify_msg)\n                self._partition_end_operation(session_id, False, f\"\u274c Change letter verify failed: {verify_msg}\", C[\"error\"])\n        else:\n            self._partition_log_diagnostic(\"ERROR\", f\"Change letter failed: {result.output[:200]}\")\n            self._partition_end_operation(session_id, False, \"\u274c Change letter failed\", C[\"error\"])\n\n    def _partition_split_prompt(self):\n        sel = self.partition_tree.selection()\n        if len(sel) != 1:\n            messagebox.showinfo(\"Select Partition\", \"Pehle ek partition select karo.\")\n            return\n        values = self.partition_tree.item(sel[0])[\"values\"]\n        part = self._partition_find_data(*values[:2])\n        if not part:\n            return\n        import tkinter.simpledialog as simpledialog\n        current = part.get(\"SizeGB\") or round((part.get(\"Size\") or 0)/(1024**3),2)\n        new_size = simpledialog.askfloat(\"Split Partition\", f\"Nayi sub-partition ka size (GB) enter karo, current {current}:\", initialvalue=max(current / 2, 1), minvalue=1, maxvalue=current - 1)\n        if not new_size:\n            return\n        if not messagebox.askyesno(\"Split Partition\", f\"Partition {current} GB se {new_size} GB ka new partition banega. Continue?\"):\n            return\n        preflight = self._partition_preflight_checks(\"split\", part, new_size=new_size)\n        if not preflight[\"ok\"]:\n            messagebox.showerror(\"Preflight Failed\", \"\\n\".join(preflight[\"errors\"]))\n            return\n        if preflight[\"warnings\"] and not self._partition_confirm_action(\"Split Partition\", f\"Split partition {part.get('DriveLetter','')} into new {new_size} GB volume.\", preflight[\"warnings\"]):\n            return\n        dry_run = messagebox.askyesno(\"Dry-Run Recommended\", \"Dry-run preview recommended for partition split. Yes = preview only, No = run actual operation now.\")\n        self._launch_job(\"partition_split\", self._partition_split_worker, part, new_size, dry_run)\n\n    def _partition_split_worker(self, part, new_size, dry_run=False):\n        started, session_id = self._partition_start_operation(\"Split Partition\")\n        if not started:\n            self._append_log(self.partition_log, \"\u26a0 Another partition operation is already running.\", C[\"warning\"])\n            return\n        if not is_admin():\n            self._partition_log_diagnostic(\"ERROR\", \"Admin rights required for split.\")\n            self._partition_end_operation(session_id, False, \"Admin required\", C[\"error\"])\n            return\n        self._partition_log_diagnostic(\"INFO\", f\"Starting partition split: {part.get('DriveLetter','')} -&gt; {new_size} GB\", {\"dry_run\": dry_run})\n        self._partition_update_progress(25, \"Preparing split plan...\")\n        command = f\"$diskNum = {part['DiskNumber']}; $partNum = {part['PartitionNumber']}; $newSize = {new_size}GB; $currentPart = Get-Partition -DiskNumber $diskNum -PartitionNumber $partNum; $targetSize = $currentPart.Size - $newSize - 1MB; Resize-Partition -DiskNumber $diskNum -PartitionNumber $partNum -Size $targetSize\"\n        if not dry_run:\n            command += \"; $newPart = New-Partition -DiskNumber $diskNum -Size $newSize -AssignDriveLetter; Format-Volume -DriveLetter $newPart.DriveLetter -FileSystem NTFS -NewFileSystemLabel 'GodawariSplit' -Confirm:$false\"\n        else:\n            command += \" -WhatIf\"\n        self._partition_update_progress(40, \"Executing split command...\")\n        result = self._partition_run_powershell_cancelable(command, timeout=240)\n        if self._partition_operation_is_cancelled():\n            self._partition_log_diagnostic(\"WARN\", \"Split operation cancelled.\")\n            self._partition_end_operation(session_id, False, \"Split cancelled\", C[\"warning\"])\n            return\n        if result.returncode == 0:\n            if dry_run:\n                self._partition_log_diagnostic(\"OK\", \"Dry-run complete: split command validated.\")\n                self._partition_end_operation(session_id, True, \"Dry-run complete\", C[\"success\"])\n                return\n            self._partition_update_progress(85, \"Verifying split result...\")\n            verify_ok, verify_msg = self._partition_verify_post_operation(\"split\", part, expected=new_size)\n            if verify_ok:\n                self._partition_log_diagnostic(\"OK\", f\"Split created with {new_size} GB successfully.\")\n                self.after(0, self._partition_refresh_tree)\n                self._partition_end_operation(session_id, True, f\"\u2705 Split created with {new_size} GB.\", C[\"success\"])\n            else:\n                self._partition_log_diagnostic(\"ERROR\", verify_msg)\n                self._partition_end_operation(session_id, False, f\"\u274c Split verify failed: {verify_msg}\", C[\"error\"])\n        else:\n            self._partition_log_diagnostic(\"ERROR\", f\"Split failed: {result.output[:200]}\")\n            self._partition_end_operation(session_id, False, \"\u274c Split failed\", C[\"error\"])\n\n    def _partition_clone_prompt(self):\n        sel = self.partition_tree.selection()\n        if len(sel) != 1:\n            messagebox.showinfo(\"Select Partition\", \"Pehle ek source partition select karo.\")\n            return\n        src = self._partition_find_data(*self.partition_tree.item(sel[0])[\"values\"][:2])\n        if not src or not src.get(\"DriveLetter\"):\n            messagebox.showinfo(\"Clone Partition\", \"Source partition ko drive letter chahiye.\")\n            return\n        candidates = [p for p in (self.partition_data.get(\"Partitions\") or []) if p.get(\"DriveLetter\") and p.get(\"DriveLetter\") != src.get(\"DriveLetter\")]\n        if not candidates:\n            messagebox.showinfo(\"Clone Partition\", \"Kam se kam ek destination partition drive letter ke saath chahiye.\")\n            return\n        options = [f\"{p.get('DriveLetter')}: {p.get('SizeGB')}GB {p.get('Type')}\" for p in candidates]\n        import tkinter.simpledialog as simpledialog\n        choice = simpledialog.askstring(\"Clone Target\", \"Destination partition choose karo:\\n\" + \"\\n\".join(options), initialvalue=options[0])\n        if not choice:\n            return\n        selected = None\n        for p, label in zip(candidates, options):\n            if choice.strip() == label:\n                selected = p\n                break\n        if not selected:\n            messagebox.showerror(\"Invalid Selection\", \"Valid destination select karo.\")\n            return\n        if not messagebox.askyesno(\"Clone Partition\", f\"Source {src.get('DriveLetter')}: ko {selected.get('DriveLetter')}: par clone karna hai?\\nContinue?\"):\n            return\n        preflight = self._partition_preflight_checks(\"clone\", src, dest_part=selected)\n        if not preflight[\"ok\"]:\n            messagebox.showerror(\"Preflight Failed\", \"\\n\".join(preflight[\"errors\"]))\n            return\n        if preflight[\"warnings\"] and not self._partition_confirm_action(\"Clone Partition\", f\"Clone {src.get('DriveLetter','')} to {selected.get('DriveLetter','')}.\", preflight[\"warnings\"]):\n            return\n        dry_run = messagebox.askyesno(\"Dry-Run Recommended\", \"Dry-run preview recommended for partition clone. Yes = preview only, No = run actual operation now.\")\n        self._launch_job(\"partition_clone\", self._partition_clone_worker, src, selected, dry_run)\n\n    def _partition_clone_worker(self, source_part, dest_part, dry_run=False):\n        started, session_id = self._partition_start_operation(\"Clone Partition\")\n        if not started:\n            self._append_log(self.partition_log, \"\u26a0 Another partition operation is already running.\", C[\"warning\"])\n            return\n        src_letter = source_part.get(\"DriveLetter\")\n        dst_letter = dest_part.get(\"DriveLetter\")\n        if not src_letter or not dst_letter:\n            self._partition_log_diagnostic(\"ERROR\", \"Clone failed: drive letters required.\")\n            self._partition_end_operation(session_id, False, \"Clone failed\", C[\"error\"])\n            return\n        self._partition_log_diagnostic(\"INFO\", f\"Starting clone: {src_letter}: \u2192 {dst_letter}:\", {\"dry_run\": dry_run})\n        ts = datetime.datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n        dst_folder = f\"{dst_letter}:\\\\GodawariClone_{ts}\"\n        copy_log = os.path.join(os.environ.get(\"APPDATA\", \"\"), \"GodawariOptimizer\", \"partition_backups\", f\"clone_{ts}.log\")\n        os.makedirs(os.path.dirname(copy_log), exist_ok=True)\n        self._partition_update_progress(10, \"Calculating source size...\")\n        total_bytes = self._partition_folder_size(f\"{src_letter}:\\\\\")\n        self._partition_log_diagnostic(\"INFO\", f\"Source size: {total_bytes} bytes\")\n        if not dry_run:\n            try:\n                usage = shutil.disk_usage(f\"{dst_letter}:\\\\\")\n                if usage.free &lt; total_bytes:\n                    self._partition_log_diagnostic(\"ERROR\", \"Destination volume does not have enough free space.\")\n                    self._partition_end_operation(session_id, False, \"Clone failed: insufficient free space\", C[\"error\"])\n                    return\n            except Exception:\n                self._partition_log_diagnostic(\"WARN\", \"Unable to verify destination free space.\")\n        self._partition_update_progress(20, f\"Starting robocopy (source size: {round(total_bytes/1024**3,1)} GB)...\")\n        cmd = [\"robocopy\", f\"{src_letter}:\\\\\", dst_folder, \"/MIR\", \"/COPYALL\", \"/R:3\", \"/W:5\", f\"/LOG:{copy_log}\", \"/TEE\"]\n        if dry_run:\n            cmd.append(\"/L\")\n        result = self._partition_run_cmd_cancelable(cmd, timeout=7200)\n        if self._partition_operation_is_cancelled():\n            self._partition_log_diagnostic(\"WARN\", \"Clone operation cancelled.\")\n            self._partition_end_operation(session_id, False, \"Clone cancelled\", C[\"warning\"])\n            return\n        self._partition_update_progress(90, \"Verifying copied files...\")\n        if dry_run:\n            self._partition_log_diagnostic(\"OK\", \"Dry-run complete: clone plan validated.\")\n            self._partition_end_operation(session_id, True, \"Dry-run complete\", C[\"success\"])\n            return\n        if result.returncode &gt;= 8:\n            self._partition_log_diagnostic(\"ERROR\", f\"Clone failed: rc={result.returncode}\")\n            self._partition_end_operation(session_id, False, \"\u274c Clone failed\", C[\"error\"])\n        else:\n            self._partition_log_diagnostic(\"OK\", f\"Clone complete: {dst_folder}\")\n            self.after(0, self._partition_refresh_tree)\n            self._partition_end_operation(session_id, True, f\"\u2705 Clone complete: {dst_folder}\", C[\"success\"])\n\n    def _partition_backup_table(self):\n        self._launch_job(\"partition_backup\", self._partition_backup_table_worker)\n\n    def _partition_backup_table_worker(self):\n        backup_dir = os.path.join(os.environ.get(\"APPDATA\", \"\"), \"GodawariOptimizer\", \"partition_backups\")\n        os.makedirs(backup_dir, exist_ok=True)\n        ts = datetime.datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n        backup_file = os.path.join(backup_dir, f\"partition_backup_{ts}.json\")\n        backup_script = \"\"\"\n        $data = @{\n            Disks = (Get-Disk | ConvertTo-Json -Depth 3)\n            Partitions = (Get-Partition | ConvertTo-Json -Depth 3)\n        }\n        $data | ConvertTo-Json -Depth 4\n        \"\"\"\n        self._partition_update_progress(20, \"Reading partition table...\")\n        self._partition_update_progress(50, \"PowerShell query running...\")\n        result = safe_powershell(backup_script, timeout=20)\n        if result.returncode == 0 and result.output.strip():\n            with open(backup_file, \"w\", encoding=\"utf-8\") as f:\n                f.write(result.output)\n            self._partition_update_progress(100, \"\u2705 Partition table backup saved!\")\n            self.after(0, lambda: self._append_log(self.partition_log, f\"\u2705 Partition table backup saved: {backup_file}\", C[\"success\"]))\n        else:\n            self._partition_update_progress(0, \"\u274c Backup failed\")\n            self.after(0, lambda: self._append_log(self.partition_log, f\"\u274c Partition backup failed: {getattr(result, 'output', '')[:200]}\", C[\"error\"]))\n        self._partition_reset_progress_delayed(3000)\n\n    def _partition_get_selected_partitions(self):\n        return [self._partition_find_data(*self.partition_tree.item(iid)[\"values\"][:2]) for iid in self.partition_tree.selection() if self._partition_find_data(*self.partition_tree.item(iid)[\"values\"][:2])]\n\n    def _driver_scan_all(self):\n        self._append_log(self.driver_log, \"Driver scan shuru ho raha hai...\", C[\"accent\"])\n        self._launch_job(\"driver_scan_all\", self._do_driver_scan)\n\n    def _driver_age_text(self, days):\n        if days is None:\n            return \"Nahi pata\"\n        if days &gt;= 365:\n            return f\"{days//365} saal {(days%365)//30} mahine\"\n        return f\"{days} din\"\n\n    def _driver_parse_date(self, raw):\n        try:\n            if not raw:\n                return None\n            text = str(raw)\n            if re.match(r\"^\\d{14}\", text):\n                return datetime.datetime.strptime(text[:14], \"%Y%m%d%H%M%S\")\n            m = re.search(r\"/Date\\((\\d+)\", text)\n            if m:\n                return datetime.datetime.fromtimestamp(int(m.group(1)) / 1000)\n            for fmt in (\"%Y-%m-%dT%H:%M:%S\", \"%m/%d/%Y %H:%M:%S\", \"%Y-%m-%d\"):\n                try:\n                    return datetime.datetime.strptime(text[:19], fmt)\n                except Exception:\n                    pass\n        except Exception:\n            return None\n        return None\n\n    def _do_driver_scan(self):\n        try:\n            cmd = 'powershell -NoProfile -Command \"Get-WmiObject Win32_PnPSignedDriver | Select-Object DeviceName,DriverVersion,DriverDate,IsSigned,InfName | ConvertTo-Json\"'\n            out, rc = self._run_cmd(cmd, timeout=180)\n            if rc != 0:\n                self._append_log(self.driver_log, f\"Error aaya: {out[:300]}\", C[\"error\"])\n                return\n            data = json.loads(out) if out.strip() else []\n            if isinstance(data, dict):\n                data = [data]\n            rows = []\n            now = datetime.datetime.now()\n            for d in data:\n                dt = self._driver_parse_date(d.get(\"DriverDate\"))\n                days = (now - dt).days if dt else None\n                signed = bool(d.get(\"IsSigned\"))\n                tag = \"ok\"\n                if not signed:\n                    tag = \"unsigned\"\n                elif days is not None and days &gt; 730:\n                    tag = \"very_old\"\n                elif days is not None and days &gt; 365:\n                    tag = \"old\"\n                rows.append({\n                    \"device\": d.get(\"DeviceName\") or \"Naam nahi mila\",\n                    \"version\": d.get(\"DriverVersion\") or \"Nahi pata\",\n                    \"date\": dt.strftime(\"%Y-%m-%d\") if dt else \"Nahi pata\",\n                    \"signed\": signed,\n                    \"inf\": d.get(\"InfName\") or \"Nahi pata\",\n                    \"days\": days,\n                    \"age\": self._driver_age_text(days),\n                    \"tag\": tag,\n                })\n            self.after(0, lambda: self._driver_fill_rows(rows))\n        except Exception as e:\n            self._append_log(self.driver_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _driver_fill_rows(self, rows):\n        try:\n            self.driver_all_rows = rows\n            self.driver_tree.delete(*self.driver_tree.get_children())\n            for idx, r in enumerate(rows):\n                status = \"Signed\" if r[\"signed\"] else \"Unsigned\"\n                self.driver_tree.insert(\"\", \"end\", iid=str(idx), values=(r[\"device\"], r[\"version\"], r[\"date\"], status, r[\"age\"]), tags=(r[\"tag\"],))\n            self._append_log(self.driver_log, f\"\u2705 Kaam ho gaya: {len(rows)} drivers load ho gaye\", C[\"success\"])\n        except Exception as e:\n            self._append_log(self.driver_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _driver_filter_old(self):\n        try:\n            rows = [r for r in getattr(self, \"driver_all_rows\", []) if (r.get(\"days\") or 0) &gt;= 365]\n            self._driver_fill_rows(rows)\n            self._append_log(self.driver_log, \"Purane drivers filter ho gaye\", C[\"warning\"])\n        except Exception as e:\n            self._append_log(self.driver_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _driver_filter_unsigned(self):\n        try:\n            rows = [r for r in getattr(self, \"driver_all_rows\", []) if not r.get(\"signed\")]\n            self._driver_fill_rows(rows)\n            self._append_log(self.driver_log, \"Unsigned drivers filter ho gaye\", C[\"warning\"])\n        except Exception as e:\n            self._append_log(self.driver_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _driver_on_select(self, event):\n        try:\n            sel = self.driver_tree.selection()\n            if not sel:\n                return\n            vals = self.driver_tree.item(sel[0], \"values\")\n            device = vals[0]\n            row = next((r for r in getattr(self, \"driver_all_rows\", []) if r.get(\"device\") == device), None)\n            if not row:\n                return\n            for w in self.driver_detail.winfo_children():\n                w.destroy()\n            tk.Label(self.driver_detail, text=row[\"device\"], font=(\"Segoe UI\", 13, \"bold\"), fg=C[\"accent\"], bg=C[\"card\"], wraplength=330, justify=\"left\").pack(anchor=\"w\", pady=(0,8))\n            info = [\n                f\"Version: {row['version']}\",\n                f\"Date: {row['date']}\",\n                f\"Signed: {'Haan' if row['signed'] else 'Nahi'}\",\n                f\"INF file: {row['inf']}\",\n            ]\n            for line in info:\n                tk.Label(self.driver_detail, text=line, font=FONTS[\"body\"], fg=C[\"text\"], bg=C[\"card\"], wraplength=330, justify=\"left\").pack(anchor=\"w\", pady=2)\n            if not row[\"signed\"]:\n                rec, color = \"\u26a0 Unsigned driver - security risk\", C[\"error\"]\n            elif (row.get(\"days\") or 0) &gt; 730:\n                rec, color = \"\u26a0 Bahut purana driver - update recommended\", C[\"warning\"]\n            elif row.get(\"days\") is not None and row[\"days\"] &lt; 180:\n                rec, color = \"\u2705 Recent driver - action ki zaroorat nahi\", C[\"success\"]\n            else:\n                rec, color = \"Info: Driver theek lag raha hai\", C[\"text_dim\"]\n            tk.Label(self.driver_detail, text=rec, font=FONTS[\"subhead\"], fg=color, bg=C[\"card\"], wraplength=330, justify=\"left\").pack(anchor=\"w\", pady=12)\n        except Exception as e:\n            self._append_log(self.driver_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _driver_export_csv(self):\n        try:\n            rows = getattr(self, \"driver_all_rows\", [])\n            if not rows:\n                messagebox.showwarning(\"Data nahi mila\", \"Pehle driver scan karo\")\n                return\n            csv_mod = __import__(\"csv\")\n            desktop = os.path.join(os.environ.get(\"USERPROFILE\", \"\"), \"Desktop\")\n            path = os.path.join(desktop, f\"Godawari_Driver_Report_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.csv\")\n            with open(path, \"w\", newline=\"\", encoding=\"utf-8-sig\") as f:\n                writer = csv_mod.writer(f)\n                writer.writerow([\"DeviceName\", \"DriverVersion\", \"DriverDate\", \"Signed\", \"Age\"])\n                for r in rows:\n                    writer.writerow([r[\"device\"], r[\"version\"], r[\"date\"], \"Haan\" if r[\"signed\"] else \"Nahi\", r[\"age\"]])\n            self._append_log(self.driver_log, f\"\u2705 Kaam ho gaya: CSV save hua - {path}\", C[\"success\"])\n            messagebox.showinfo(\"Kaam ho gaya\", f\"Driver CSV save ho gaya:\\n{path}\")\n        except Exception as e:\n            self._append_log(self.driver_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _build_svc_presets(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"Services Preset Manager\", \"Gaming, office, safe aur repair presets\")\n        content = self._scrollable_section_body(frame)\n        self.svc_presets_data = {\n            \"Gaming\": {\"description\": \"Maximum performance - gaming ke liye\", \"icon\": \"\ud83c\udfae\", \"color\": C[\"btn_danger\"], \"disable\": [\"SysMain\",\"DiagTrack\",\"WSearch\",\"TabletInputService\",\"Fax\",\"PrintNotify\",\"WerSvc\",\"XblAuthManager\",\"XblGameSave\",\"XboxNetApiSvc\"], \"manual\": [\"wuauserv\"], \"keep_running\": [\"AudioSrv\",\"AudioEndpointBuilder\",\"Themes\"]},\n            \"Office/Work\": {\"description\": \"Stable aur fast - office work ke liye\", \"icon\": \"\ud83d\udcbc\", \"color\": C[\"btn_info\"], \"disable\": [\"XblAuthManager\",\"XblGameSave\",\"XboxNetApiSvc\",\"Fax\",\"RetailDemo\",\"DiagTrack\"], \"manual\": [\"SysMain\",\"WSearch\"], \"keep_running\": [\"wuauserv\",\"AudioSrv\",\"Themes\"]},\n            \"Minimal/Safe\": {\"description\": \"Sirf zaroori services - slow PC ke liye\", \"icon\": \"\ud83d\udee1\", \"color\": C[\"btn_chip\"], \"disable\": [\"SysMain\",\"DiagTrack\",\"WSearch\",\"TabletInputService\",\"Fax\",\"PrintNotify\",\"WerSvc\",\"XblAuthManager\",\"XblGameSave\",\"XboxNetApiSvc\",\"RetailDemo\",\"MapsBroker\",\"lfsvc\",\"SharedAccess\"], \"manual\": [\"wuauserv\",\"BITS\"], \"keep_running\": [\"AudioSrv\",\"Themes\",\"LanmanWorkstation\"]},\n            \"Repair Shop\": {\"description\": \"Troubleshooting ke liye - diagnostics on\", \"icon\": \"\ud83d\udd27\", \"color\": C[\"hw_accent\"], \"disable\": [\"XblAuthManager\",\"XblGameSave\",\"Fax\",\"RetailDemo\"], \"manual\": [\"DiagTrack\",\"WerSvc\"], \"keep_running\": [\"WSearch\",\"wuauserv\",\"SysMain\",\"AudioSrv\"]},\n        }\n        self.svc_selected_preset = tk.StringVar(value=\"Gaming\")\n        self.svc_preset_snapshot = {}\n        self.svc_preset_cards = {}\n        cards = tk.Frame(content, bg=C[\"bg\"])\n        cards.pack(fill=\"x\", padx=14, pady=8)\n        for i, (name, data) in enumerate(self.svc_presets_data.items()):\n            card = tk.Frame(cards, bg=C[\"card\"], highlightbackground=data[\"color\"], highlightthickness=1, cursor=\"hand2\")\n            card.grid(row=0, column=i, sticky=\"nsew\", padx=5)\n            cards.columnconfigure(i, weight=1)\n            tk.Label(card, text=data[\"icon\"], font=(\"Segoe UI\", 22), fg=data[\"color\"], bg=C[\"card\"]).pack(pady=(8,0))\n            tk.Label(card, text=name, font=FONTS[\"subhead\"], fg=C[\"text\"], bg=C[\"card\"]).pack()\n            tk.Label(card, text=data[\"description\"], font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=220).pack(padx=8, pady=(0,8))\n            card.bind(\"\", lambda e, n=name: self._svc_preset_select(n))\n            for child in card.winfo_children():\n                child.bind(\"\", lambda e, n=name: self._svc_preset_select(n))\n            self.svc_preset_cards[name] = card\n        body = tk.Frame(content, bg=C[\"bg\"])\n        body.pack(fill=\"both\", expand=True, padx=14)\n        left = tk.Frame(body, bg=C[\"card\"])\n        left.pack(side=\"left\", fill=\"both\", expand=True, padx=(0,8))\n        right = tk.Frame(body, bg=C[\"card\"], width=360)\n        right.pack(side=\"right\", fill=\"both\", padx=(8,0))\n        right.pack_propagate(False)\n        wrap, self.svc_tree = self._adv_tree(left, [\"Service Naam\", \"Display Naam\", \"Action\", \"Current Status\"], height=16)\n        wrap.pack(fill=\"both\", expand=True, padx=8, pady=8)\n        self.svc_tree.tag_configure(\"risk\", foreground=C[\"error\"])\n        self.svc_status_text = self._scrolled_text(right, height=15)\n        btns = tk.Frame(content, bg=C[\"bg\"])\n        btns.pack(fill=\"x\", padx=14, pady=6)\n        for label, color, cmd in [\n            (\"Status Check\", C[\"btn_info\"], self._svc_preset_check_status),\n            (\"Preset Apply\", C[\"btn_danger\"], lambda: self._svc_preset_apply(self.svc_selected_preset.get())),\n            (\"Custom Save\", C[\"btn\"], self._svc_preset_save_custom),\n            (\"Custom Load\", C[\"btn_chip\"], self._svc_preset_load_custom),\n            (\"Previous Restore\", C[\"btn_warn\"], self._svc_preset_restore),\n        ]:\n            self._btn(btns, label, color, cmd).pack(side=\"left\", padx=4)\n        self.svc_log = self._scrolled_text(content, height=6)\n        self._svc_preset_select(\"Gaming\")\n        return frame\n\n    def _svc_preset_select(self, preset_name):\n        try:\n            self.svc_selected_preset.set(preset_name)\n            for name, card in self.svc_preset_cards.items():\n                card.configure(bg=C[\"panel\"] if name == preset_name else C[\"card\"])\n                for child in card.winfo_children():\n                    child.configure(bg=card[\"bg\"])\n            data = self.svc_presets_data[preset_name]\n            self.svc_tree.delete(*self.svc_tree.get_children())\n            for svc in data.get(\"disable\", []):\n                self.svc_tree.insert(\"\", \"end\", values=(svc, svc, \"Disable\", \"Check pending\"))\n            for svc in data.get(\"manual\", []):\n                self.svc_tree.insert(\"\", \"end\", values=(svc, svc, \"Manual\", \"Check pending\"))\n            for svc in data.get(\"keep_running\", []):\n                self.svc_tree.insert(\"\", \"end\", values=(svc, svc, \"Keep\", \"Check pending\"))\n            self._append_log(self.svc_log, f\"{preset_name} preset select ho gaya\", C[\"accent\"])\n        except Exception as e:\n            self._append_log(self.svc_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _svc_preset_check_status(self):\n        try:\n            services = []\n            for iid in self.svc_tree.get_children():\n                vals = self.svc_tree.item(iid, \"values\")\n                if len(vals) &gt;= 3:\n                    services.append((iid, vals[0], vals[2]))\n            self._launch_job(\"svc_preset_check\", self._do_svc_preset_check, services)\n        except Exception as e:\n            self._append_log(self.svc_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _do_svc_preset_check(self, services=None):\n        try:\n            updates = []\n            for iid, svc, action in (services or []):\n                status = self._svc_get_status(svc)\n                updates.append((iid, status, action))\n            def apply():\n                for iid, status, action in updates:\n                    vals = list(self.svc_tree.item(iid, \"values\"))\n                    vals[3] = status\n                    tags = (\"risk\",) if status == \"Running\" and vals[2] == \"Disable\" else ()\n                    self.svc_tree.item(iid, values=vals, tags=tags)\n                self._append_log(self.svc_log, \"\u2705 Kaam ho gaya: Service status update ho gaya\", C[\"success\"])\n            self.after(0, apply)\n        except Exception as e:\n            self._append_log(self.svc_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _svc_preset_apply(self, preset_name):\n        try:\n            data = self.svc_presets_data.get(preset_name)\n            if not data:\n                messagebox.showwarning(\"Preset nahi mila\", \"Pehle preset select karo\")\n                return\n            count = len(data.get(\"disable\", [])) + len(data.get(\"manual\", []))\n            if not messagebox.askyesno(\"Confirm karo\", f\"{preset_name} preset apply karna hai?\\n{count} services change hongi.\"):\n                return\n            self._launch_job(\"svc_preset_apply\", self._do_svc_preset_apply, preset_name, data)\n        except Exception as e:\n            self._append_log(self.svc_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _do_svc_preset_apply(self, preset_name, preset_data):\n        try:\n            affected = set(preset_data.get(\"disable\", []) + preset_data.get(\"manual\", []) + preset_data.get(\"keep_running\", []))\n            self.svc_preset_snapshot = {svc: self._svc_get_start_type(svc) for svc in affected}\n            for svc in preset_data.get(\"disable\", []):\n                out, rc = self._run_cmd(f\"sc config {svc} start= disabled\", timeout=40)\n                self._append_log(self.svc_log, f\"{svc}: disabled set - rc {rc}\", C[\"warning\"] if rc else C[\"success\"])\n                self._run_cmd(f\"sc stop {svc}\", timeout=25)\n            for svc in preset_data.get(\"manual\", []):\n                out, rc = self._run_cmd(f\"sc config {svc} start= demand\", timeout=40)\n                self._append_log(self.svc_log, f\"{svc}: manual set - rc {rc}\", C[\"success\"] if rc == 0 else C[\"warning\"])\n            self._append_log(self.svc_log, f\"\u2705 Kaam ho gaya: {preset_name} preset apply ho gaya\", C[\"success\"])\n            self._svc_preset_check_status()\n        except Exception as e:\n            self._append_log(self.svc_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _svc_preset_save_custom(self):\n        self._launch_job(\"svc_custom_save\", self._svc_preset_save_custom_worker)\n\n    def _svc_preset_save_custom_worker(self):\n        try:\n            all_svcs = set()\n            for data in self.svc_presets_data.values():\n                all_svcs.update(data.get(\"disable\", []) + data.get(\"manual\", []) + data.get(\"keep_running\", []))\n            custom = {\"description\": \"Saved custom service state\", \"icon\": \"\ud83d\udcbe\", \"color\": C[\"btn\"], \"disable\": [], \"manual\": [], \"keep_running\": []}\n            for svc in all_svcs:\n                st = self._svc_get_start_type(svc)\n                if st == \"disabled\":\n                    custom[\"disable\"].append(svc)\n                elif st == \"demand\":\n                    custom[\"manual\"].append(svc)\n                elif st == \"auto\":\n                    custom[\"keep_running\"].append(svc)\n            path = os.path.join(os.environ.get(\"APPDATA\", \"\"), \"GodawariOptimizer\", \"svc_custom.json\")\n            os.makedirs(os.path.dirname(path), exist_ok=True)\n            with open(path, \"w\", encoding=\"utf-8\") as f:\n                json.dump(custom, f, indent=2)\n            self.svc_presets_data[\"Custom\"] = custom\n            self._append_log(self.svc_log, f\"\u2705 Kaam ho gaya: Custom preset save hua - {path}\", C[\"success\"])\n        except Exception as e:\n            self._append_log(self.svc_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _svc_preset_load_custom(self):\n        try:\n            path = os.path.join(os.environ.get(\"APPDATA\", \"\"), \"GodawariOptimizer\", \"svc_custom.json\")\n            if not os.path.exists(path):\n                messagebox.showwarning(\"Custom nahi mila\", \"Custom preset abhi save nahi hai\")\n                return\n            with open(path, \"r\", encoding=\"utf-8\") as f:\n                self.svc_presets_data[\"Custom\"] = json.load(f)\n            self._svc_preset_select(\"Custom\")\n            self._append_log(self.svc_log, \"\u2705 Kaam ho gaya: Custom preset load ho gaya\", C[\"success\"])\n        except Exception as e:\n            self._append_log(self.svc_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _svc_preset_restore(self):\n        try:\n            if not getattr(self, \"svc_preset_snapshot\", {}):\n                messagebox.showwarning(\"Snapshot nahi mila\", \"Restore ke liye pehle preset apply hona chahiye\")\n                return\n            if not messagebox.askyesno(\"Confirm karo\", \"Previous service state restore karna hai?\"):\n                return\n            self._launch_job(\"svc_restore\", self._svc_preset_restore_worker)\n        except Exception as e:\n            self._append_log(self.svc_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _svc_preset_restore_worker(self):\n        try:\n            for svc, st in self.svc_preset_snapshot.items():\n                if st in (\"auto\", \"demand\", \"disabled\"):\n                    out, rc = self._run_cmd(f\"sc config {svc} start= {st}\", timeout=40)\n                    self._append_log(self.svc_log, f\"{svc}: {st} restore - rc {rc}\", C[\"success\"] if rc == 0 else C[\"warning\"])\n            self._append_log(self.svc_log, \"\u2705 Kaam ho gaya: Previous state restore ho gayi\", C[\"success\"])\n        except Exception as e:\n            self._append_log(self.svc_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _svc_get_start_type(self, service_name):\n        try:\n            out, rc = self._run_cmd(f\"sc qc {service_name}\", timeout=20)\n            m = re.search(r\"START_TYPE\\s+:\\s+\\d+\\s+(\\w+)\", out)\n            text = (m.group(1).lower() if m else \"\")\n            if \"auto\" in text:\n                return \"auto\"\n            if \"demand\" in text:\n                return \"demand\"\n            if \"disabled\" in text:\n                return \"disabled\"\n        except Exception:\n            pass\n        return \"unknown\"\n\n    def _svc_get_status(self, service_name):\n        try:\n            out, rc = self._run_cmd(f\"sc query {service_name}\", timeout=20)\n            m = re.search(r\"STATE\\s+:\\s+\\d+\\s+(\\w+)\", out)\n            if m:\n                return \"Running\" if m.group(1).upper() == \"RUNNING\" else \"Stopped\"\n        except Exception:\n            pass\n        return \"Unknown\"\n\n    # Remaining advanced menus are implemented as operational compact panels.\n    def _build_disk_analyzer(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"Disk Space Analyzer\", \"Drive/folder size aur Windows bloat check\")\n        content = self._scrollable_section_body(frame)\n        top = tk.Frame(content, bg=C[\"bg\"])\n        top.pack(fill=\"x\", padx=14, pady=8)\n        string_mod = __import__(\"string\")\n        drives = [f\"{d}:\\\\\" for d in string_mod.ascii_uppercase if os.path.exists(f\"{d}:\\\\\")]\n        self.disk_drive_var = tk.StringVar(value=drives[0] if drives else \"C:\\\\\")\n        self.disk_depth_var = tk.IntVar(value=2)\n        ttk.Combobox(top, textvariable=self.disk_drive_var, values=drives + [\"Custom folder browse karo\"], width=28, state=\"readonly\").pack(side=\"left\", padx=4)\n        tk.Spinbox(top, from_=1, to=5, textvariable=self.disk_depth_var, width=5, bg=C[\"card\"], fg=C[\"text\"]).pack(side=\"left\", padx=4)\n        self._btn(top, \"Scan Drive\", C[\"btn_info\"], self._disk_start_scan).pack(side=\"left\", padx=4)\n        status = tk.Frame(content, bg=C[\"bg\"])\n        status.pack(fill=\"x\", padx=14, pady=(0, 6))\n        self.disk_scan_status = tk.Label(status, text=\"Ready to scan.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"], anchor=\"w\")\n        self.disk_scan_status.pack(side=\"left\", fill=\"x\", expand=True)\n        self.disk_scan_progress_var = tk.DoubleVar(value=0.0)\n        self.disk_scan_progress = ttk.Progressbar(status, variable=self.disk_scan_progress_var, maximum=100.0, mode=\"determinate\")\n        self.disk_scan_progress.pack(side=\"right\", fill=\"x\", expand=False, ipadx=90, padx=(8, 0))\n        body = tk.Frame(content, bg=C[\"bg\"])\n        body.pack(fill=\"both\", expand=True, padx=14)\n        left = tk.Frame(body, bg=C[\"card\"])\n        left.pack(side=\"left\", fill=\"both\", expand=True, padx=(0,8))\n        right = tk.Frame(body, bg=C[\"card\"], width=360)\n        right.pack(side=\"right\", fill=\"both\", padx=(8,0))\n        right.pack_propagate(False)\n        wrap, self.disk_tree = self._adv_tree(left, [\"Folder\", \"Size\", \"Files Count\", \"% Parent\"], height=18)\n        wrap.pack(fill=\"both\", expand=True, padx=8, pady=8)\n        self.disk_summary = self._scrolled_text(right, height=18)\n        self._action_card_grid(content, [\n            (\"\ud83d\udd0d\", \"Scan Drive\", \"Selected drive scan karo\", C[\"btn_info\"], self._disk_start_scan),\n            (\"\ud83d\udcc2\", \"Folder Kholo\", \"Selected folder Explorer mein kholo\", C[\"btn_chip\"], self._disk_open_selected),\n            (\"\ud83e\uddf9\", \"Temp Clean\", \"Temp folders directly clean karo\", C[\"btn_warn\"], self._disk_clean_temp),\n            (\"\ud83d\udcbe\", \"Report Export\", \"Results CSV mein save karo\", C[\"btn\"], self._disk_export_report),\n            (\"\ud83d\udd04\", \"Refresh\", \"Dobara scan karo\", C[\"accent2\"], self._disk_start_scan),\n        ], cols=5)\n        self.disk_log = self._scrolled_text(content, height=5)\n        self.disk_results = []\n        return frame\n\n    def _disk_start_scan(self):\n        try:\n            root = self.disk_drive_var.get()\n            if root == \"Custom folder browse karo\":\n                root = filedialog.askdirectory()\n                if not root:\n                    return\n                self.disk_drive_var.set(root)\n            self._append_log(self.disk_log, f\"Scan shuru: {root}\", C[\"accent\"])\n            self._disk_update_scan_progress(0, f\"Scanning {root}...\")\n            self._launch_job(\"disk_scan\", self._do_disk_scan, root, int(self.disk_depth_var.get()))\n        except Exception as e:\n            self._append_log(self.disk_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _disk_update_scan_progress(self, pct, text=None):\n        def _update():\n            try:\n                pct_float = max(0.0, min(100.0, float(pct)))\n            except Exception:\n                pct_float = 0.0\n            if hasattr(self, \"disk_scan_progress_var\"):\n                self.disk_scan_progress_var.set(pct_float)\n            if hasattr(self, \"disk_scan_status\") and text is not None:\n                self.disk_scan_status.config(text=f\"{int(pct_float)}% - {str(text)[:160]}\")\n        self.after(0, _update)\n\n    def _do_disk_scan(self, root_path, max_depth):\n        try:\n            root_path = os.path.abspath(root_path)\n            base_depth = root_path.rstrip(\"\\\\/\").count(os.sep)\n            results = []\n            scanned_dirs = 0\n            for cur, dirs, files in os.walk(root_path):\n                depth = cur.rstrip(\"\\\\/\").count(os.sep) - base_depth\n                if depth &gt; max_depth:\n                    dirs[:] = []\n                    continue\n                dirs[:] = [d for d in dirs if not d.startswith(\"$\")]\n                size, count = self._disk_get_folder_size(cur)\n                results.append((cur, size, count, 0))\n                scanned_dirs += 1\n                if scanned_dirs % 8 == 0:\n                    self._disk_update_scan_progress(min(95, 5 + scanned_dirs), f\"{scanned_dirs} folders scanned...\")\n                if len(results) &gt; 250:\n                    break\n            results.sort(key=lambda x: x[1], reverse=True)\n            top = results[:50]\n            bloat = self._disk_check_windows_bloat()\n            self._disk_update_scan_progress(100, f\"{len(top)} folders ready.\")\n            self.after(0, lambda: (self._disk_populate_treeview(top), self._disk_generate_recommendations(bloat)))\n        except Exception as e:\n            self._disk_update_scan_progress(0, f\"Scan failed: {e}\")\n            self._append_log(self.disk_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _disk_get_folder_size(self, path):\n        total = 0\n        count = 0\n        try:\n            for root, dirs, files in os.walk(path):\n                dirs[:] = [d for d in dirs if not d.startswith(\"$\")]\n                for fn in files:\n                    try:\n                        fp = os.path.join(root, fn)\n                        total += os.path.getsize(fp)\n                        count += 1\n                        if count &gt;= 3000:\n                            return total, count\n                    except Exception:\n                        continue\n        except Exception:\n            return total, count\n        return total, count\n\n    def _disk_populate_treeview(self, results):\n        try:\n            self.disk_results = results\n            self.disk_tree.delete(*self.disk_tree.get_children())\n            parent_size = results[0][1] if results else 1\n            for path, size, count, _pct in results:\n                pct = (size / parent_size * 100) if parent_size else 0\n                self.disk_tree.insert(\"\", \"end\", values=(path, self._fmt_size_disk(size), count, f\"{pct:.1f}%\"))\n            self._append_log(self.disk_log, f\"\u2705 Kaam ho gaya: {len(results)} folders show ho rahe hain\", C[\"success\"])\n        except Exception as e:\n            self._append_log(self.disk_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _disk_check_windows_bloat(self):\n        data = {}\n        try:\n            user = os.environ.get(\"USERNAME\", \"\")\n            paths = {\n                \"Windows Temp\": r\"C:\\Windows\\Temp\",\n                \"User Temp\": os.path.join(os.environ.get(\"USERPROFILE\", \"\"), \"AppData\", \"Local\", \"Temp\"),\n                \"Windows Update Cache\": r\"C:\\Windows\\SoftwareDistribution\\Download\",\n                \"Windows Installer\": r\"C:\\Windows\\Installer\",\n                \"Recycle Bin\": r\"C:\\$Recycle.Bin\",\n                \"hiberfil.sys\": r\"C:\\hiberfil.sys\",\n                \"pagefile.sys\": r\"C:\\pagefile.sys\",\n            }\n            for name, path in paths.items():\n                if os.path.isfile(path):\n                    data[name] = os.path.getsize(path)\n                elif os.path.isdir(path):\n                    data[name] = self._disk_get_folder_size(path)[0]\n                else:\n                    data[name] = 0\n        except Exception as e:\n            self._append_log(self.disk_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n        return data\n\n    def _disk_generate_recommendations(self, bloat_data):\n        try:\n            self.disk_summary.config(state=\"normal\")\n            self.disk_summary.delete(\"1.0\", \"end\")\n            self.disk_summary.insert(\"end\", \"Windows Bloat Summary\\n\\n\")\n            recs = []\n            for name, size in bloat_data.items():\n                self.disk_summary.insert(\"end\", f\"{name}: {self._fmt_size_disk(size)}\\n\")\n            if bloat_data.get(\"Windows Temp\", 0) + bloat_data.get(\"User Temp\", 0) &gt; 500*1024*1024:\n                recs.append(\"\ud83d\udfe1 Temp files cleanup recommended - Junk Cleaner use karo\")\n            if bloat_data.get(\"Windows Update Cache\", 0) &gt; 1024*1024*1024:\n                recs.append(\"\ud83d\udfe1 Windows Update cache bada hai - safe clear ho sakta hai\")\n            if bloat_data.get(\"Recycle Bin\", 0) &gt; 100*1024*1024:\n                recs.append(\"\ud83d\udfe1 Recycle Bin empty karo\")\n            if bloat_data.get(\"hiberfil.sys\", 0) &gt; 2*1024*1024*1024:\n                recs.append(\"\ud83d\udfe1 Hibernation disable karo agar laptop nahi hai: powercfg /h off\")\n            if bloat_data.get(\"Windows Installer\", 0) &gt; 2*1024*1024*1024:\n                recs.append(\"\u26a0 Windows Installer folder bada hai - careful cleanup needed\")\n            self.disk_summary.insert(\"end\", \"\\nRecommendations\\n\\n\" + (\"\\n\".join(recs) if recs else \"\u2705 Koi badi cleanup warning nahi mili\"))\n            self.disk_summary.config(state=\"disabled\")\n        except Exception as e:\n            self._append_log(self.disk_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _disk_open_selected(self):\n        try:\n            sel = self.disk_tree.selection()\n            if not sel:\n                messagebox.showwarning(\"Select karo\", \"Pehle folder select karo\")\n                return\n            path = self.disk_tree.item(sel[0], \"values\")[0]\n            if os.path.exists(path):\n                os.startfile(path)\n        except Exception as e:\n            self._append_log(self.disk_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _disk_clean_temp(self):\n        if messagebox.askyesno(\"Confirm karo\", \"Temp files delete karne hain?\"):\n            self._launch_job(\"disk_clean_temp\", self._disk_clean_temp_worker)\n\n    def _disk_clean_temp_worker(self):\n        try:\n            for folder in [r\"C:\\Windows\\Temp\", os.path.join(os.environ.get(\"USERPROFILE\", \"\"), \"AppData\", \"Local\", \"Temp\")]:\n                if os.path.isdir(folder):\n                    for name in os.listdir(folder):\n                        p = os.path.join(folder, name)\n                        try:\n                            shutil.rmtree(p) if os.path.isdir(p) else os.remove(p)\n                        except Exception:\n                            pass\n            self._append_log(self.disk_log, \"\u2705 Kaam ho gaya: Temp clean ho gaya\", C[\"success\"])\n        except Exception as e:\n            self._append_log(self.disk_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _disk_export_report(self):\n        try:\n            if not getattr(self, \"disk_results\", []):\n                messagebox.showwarning(\"Data nahi mila\", \"Pehle disk scan karo\")\n                return\n            csv_mod = __import__(\"csv\")\n            path = os.path.join(os.environ.get(\"USERPROFILE\", \"\"), \"Desktop\", f\"Godawari_Disk_Report_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.csv\")\n            with open(path, \"w\", newline=\"\", encoding=\"utf-8-sig\") as f:\n                writer = csv_mod.writer(f)\n                writer.writerow([\"Folder\", \"SizeBytes\", \"FilesCount\"])\n                for r in self.disk_results:\n                    writer.writerow([r[0], r[1], r[2]])\n            messagebox.showinfo(\"Kaam ho gaya\", f\"Report save ho gayi:\\n{path}\")\n        except Exception as e:\n            self._append_log(self.disk_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _fmt_size_disk(self, bytes):\n        try:\n            val = float(bytes)\n            for unit in [\"B\", \"KB\", \"MB\", \"GB\", \"TB\"]:\n                if val &lt; 1024:\n                    return f\"{val:.1f} {unit}\"\n                val /= 1024\n            return f\"{val:.1f} PB\"\n        except Exception:\n            return \"0 B\"\n\n    def _build_bsod_history(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"BSOD History\", \"Crash events, stop code aur minidump report\")\n        content = self._scrollable_section_body(frame)\n        self._action_card_grid(content, [\n            (\"\ud83d\udd0d\", \"BSOD Scan\", \"Event log se BSOD history nikalo\", C[\"btn_info\"], self._bsod_scan),\n            (\"\ud83d\udcc2\", \"Dump Folder\", \"Minidump folder kholo\", C[\"btn_chip\"], self._bsod_open_dumps),\n            (\"\ud83d\udccb\", \"Dump Copy\", \"Dumps Desktop pe copy karo\", C[\"btn_warn\"], self._bsod_copy_dumps),\n            (\"\ud83d\udcbe\", \"Report Export\", \"BSOD report save karo\", C[\"btn\"], self._bsod_export_report),\n            (\"\ud83e\uddf9\", \"Events Clear\", \"BSOD events clean karo\", C[\"btn_danger\"], self._bsod_clear_events),\n        ], cols=5)\n        body = tk.Frame(content, bg=C[\"bg\"])\n        body.pack(fill=\"both\", expand=True, padx=14, pady=8)\n        left = tk.Frame(body, bg=C[\"card\"])\n        left.pack(side=\"left\", fill=\"both\", expand=True, padx=(0,8))\n        right = tk.Frame(body, bg=C[\"card\"], width=390)\n        right.pack(side=\"right\", fill=\"both\", padx=(8,0))\n        right.pack_propagate(False)\n        wrap, self.bsod_tree = self._adv_tree(left, [\"Date Time\", \"Event ID\", \"Stop Code\", \"Description\"], height=14)\n        wrap.pack(fill=\"both\", expand=True, padx=8, pady=8)\n        self.bsod_tree.bind(\"&lt;&gt;\", self._bsod_on_select)\n        self.bsod_detail = self._scrolled_text(right, height=16)\n        dump_frame = tk.Frame(content, bg=C[\"card\"])\n        dump_frame.pack(fill=\"x\", padx=14, pady=(0,8))\n        wrap2, self.bsod_dump_tree = self._adv_tree(dump_frame, [\"File Naam\", \"Date\", \"Size\"], height=5)\n        wrap2.pack(fill=\"x\", padx=8, pady=8)\n        self.bsod_log = self._scrolled_text(content, height=5)\n        self.bsod_rows = []\n        return frame\n\n    def _bsod_scan(self):\n        self._append_log(self.bsod_log, \"BSOD scan shuru ho raha hai...\", C[\"accent\"])\n        self._launch_job(\"bsod_scan\", self._do_bsod_scan)\n\n    def _do_bsod_scan(self):\n        try:\n            cmd = '''powershell -NoProfile -Command \"Get-WinEvent -FilterHashtable @{LogName='System'; Id=41,1001,6008} -MaxEvents 50 -ErrorAction SilentlyContinue | Select-Object TimeCreated, Id, Message | ConvertTo-Json\"'''\n            out, rc = self._run_cmd(cmd, timeout=120)\n            data = json.loads(out) if out.strip() else []\n            if isinstance(data, dict):\n                data = [data]\n            rows = []\n            for ev in data:\n                msg = ev.get(\"Message\", \"\") or \"\"\n                code = self._bsod_parse_stop_code(msg)\n                desc = \"BugCheck crash\" if str(ev.get(\"Id\")) == \"1001\" else (\"Unexpected shutdown\" if str(ev.get(\"Id\")) == \"6008\" else \"Kernel Power restart\")\n                rows.append({\"time\": str(ev.get(\"TimeCreated\", \"\"))[:19], \"id\": str(ev.get(\"Id\", \"\")), \"code\": code, \"desc\": desc, \"msg\": msg})\n            dumps = []\n            dump_dir = r\"C:\\Windows\\Minidump\"\n            if os.path.isdir(dump_dir):\n                for fn in os.listdir(dump_dir):\n                    if fn.lower().endswith(\".dmp\"):\n                        p = os.path.join(dump_dir, fn)\n                        try:\n                            dumps.append((fn, datetime.datetime.fromtimestamp(os.path.getmtime(p)).strftime(\"%Y-%m-%d %H:%M\"), self._fmt_size_disk(os.path.getsize(p))))\n                        except Exception:\n                            pass\n            self.after(0, lambda: self._bsod_fill(rows, dumps))\n        except Exception as e:\n            self._append_log(self.bsod_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _bsod_fill(self, rows, dumps):\n        self.bsod_rows = rows\n        self.bsod_tree.delete(*self.bsod_tree.get_children())\n        for i, r in enumerate(rows):\n            self.bsod_tree.insert(\"\", \"end\", iid=str(i), values=(r[\"time\"], r[\"id\"], r[\"code\"], r[\"desc\"]))\n        self.bsod_dump_tree.delete(*self.bsod_dump_tree.get_children())\n        for d in dumps:\n            self.bsod_dump_tree.insert(\"\", \"end\", values=d)\n        self._append_log(self.bsod_log, f\"\u2705 Kaam ho gaya: {len(rows)} events aur {len(dumps)} dumps mile\", C[\"success\"])\n\n    def _bsod_parse_stop_code(self, message):\n        try:\n            m = re.search(r\"0x[0-9A-Fa-f]{8}\", message or \"\")\n            return m.group(0).upper() if m else \"Nahi mila\"\n        except Exception:\n            return \"Nahi mila\"\n\n    def _bsod_stop_db(self):\n        return {\n            \"0X0000001A\": (\"MEMORY_MANAGEMENT\", \"RAM faulty hai ya driver memory corrupt kar raha hai\", \"RAM test karo - MemTest86 chalao\"),\n            \"0X0000003B\": (\"SYSTEM_SERVICE_EXCEPTION\", \"Driver ya system service mein error\", \"Recent driver uninstall karo\"),\n            \"0X0000007E\": (\"SYSTEM_THREAD_EXCEPTION\", \"Driver crash - usually graphics ya chipset driver\", \"GPU driver reinstall karo\"),\n            \"0X0000007F\": (\"UNEXPECTED_KERNEL_MODE_TRAP\", \"CPU hardware error ya overclocking\", \"Overclock remove karo, RAM check karo\"),\n            \"0X00000050\": (\"PAGE_FAULT_IN_NONPAGED_AREA\", \"RAM ya driver ne invalid memory access kiya\", \"RAM slots change karo, driver update karo\"),\n            \"0X0000009F\": (\"DRIVER_POWER_STATE_FAILURE\", \"Sleep/hibernate se wake pe driver fail\", \"Power management driver update karo\"),\n            \"0X000000D1\": (\"DRIVER_IRQL_NOT_LESS_OR_EQUAL\", \"Driver ne wrong memory access kiya - faulty driver\", \"Recent installed driver remove karo\"),\n            \"0X000000EF\": (\"CRITICAL_PROCESS_DIED\", \"Windows ka critical process crash ho gaya\", \"SFC /scannow chalao\"),\n            \"0X0000000A\": (\"IRQL_NOT_LESS_OR_EQUAL\", \"Driver IRQ level problem - usually RAM ya driver\", \"RAM test + driver check\"),\n            \"0X00000024\": (\"NTFS_FILE_SYSTEM\", \"NTFS disk corruption - HDD/SSD issue\", \"chkdsk /f /r chalao\"),\n            \"0X0000002E\": (\"DATA_BUS_ERROR\", \"RAM ya motherboard hardware fault\", \"RAM replace karo\"),\n            \"0X00000074\": (\"BAD_SYSTEM_CONFIG_INFO\", \"Registry corrupt hai\", \"Registry repair ya Windows repair chalao\"),\n            \"0X000000C4\": (\"DRIVER_VERIFIER_DETECTED_VIOLATION\", \"Driver Verifier ne faulty driver pakda\", \"Driver Verifier disable karo: verifier /reset\"),\n            \"0XC0000005\": (\"ACCESS_VIOLATION\", \"Program ne invalid memory access kiya\", \"Application reinstall karo\"),\n        }\n\n    def _bsod_on_select(self, event):\n        try:\n            sel = self.bsod_tree.selection()\n            if not sel:\n                return\n            r = self.bsod_rows[int(sel[0])]\n            name, explain, fix = self._bsod_stop_db().get(r[\"code\"].upper(), (\"Unknown Stop Code\", f\"Stop code database mein nahi - online search karo: {r['code']}\", \"Microsoft support aur driver history check karo\"))\n            text = f\"Date/Time: {r['time']}\\nEvent ID: {r['id']}\\nStop Code: {r['code']}\\nNaam: {name}\\n\\nSamjhaav: {explain}\\n\\nFix Steps:\\n1. {fix}\\n2. Recent driver/update check karo\\n3. RAM aur disk health test karo\\n\\nFull Message:\\n{r['msg'][:1200]}\"\n            self.bsod_detail.config(state=\"normal\")\n            self.bsod_detail.delete(\"1.0\", \"end\")\n            self.bsod_detail.insert(\"end\", text)\n            self.bsod_detail.config(state=\"disabled\")\n        except Exception as e:\n            self._append_log(self.bsod_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _bsod_open_dumps(self):\n        try:\n            os.startfile(r\"C:\\Windows\\Minidump\")\n        except Exception as e:\n            self._append_log(self.bsod_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _bsod_copy_dumps(self):\n        self._launch_job(\"bsod_copy_dumps\", self._bsod_copy_dumps_worker)\n\n    def _bsod_copy_dumps_worker(self):\n        try:\n            src = r\"C:\\Windows\\Minidump\"\n            dst = os.path.join(os.environ.get(\"USERPROFILE\", \"\"), \"Desktop\", \"Minidumps\")\n            os.makedirs(dst, exist_ok=True)\n            count = 0\n            if os.path.isdir(src):\n                for fn in os.listdir(src):\n                    if fn.lower().endswith(\".dmp\"):\n                        shutil.copy2(os.path.join(src, fn), os.path.join(dst, fn))\n                        count += 1\n            self._append_log(self.bsod_log, f\"\u2705 Kaam ho gaya: {count} dump files copy ho gaye\", C[\"success\"])\n        except Exception as e:\n            self._append_log(self.bsod_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _bsod_export_report(self):\n        try:\n            path = os.path.join(os.environ.get(\"USERPROFILE\", \"\"), \"Desktop\", f\"Godawari_BSOD_Report_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.txt\")\n            with open(path, \"w\", encoding=\"utf-8\") as f:\n                for r in getattr(self, \"bsod_rows\", []):\n                    f.write(f\"{r['time']} | {r['id']} | {r['code']} | {r['desc']}\\n{r['msg']}\\n\\n\")\n            messagebox.showinfo(\"Kaam ho gaya\", f\"BSOD report save ho gayi:\\n{path}\")\n        except Exception as e:\n            self._append_log(self.bsod_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _bsod_clear_events(self):\n        if messagebox.askyesno(\"Confirm karo\", \"System event log clear karna destructive action hai. Kya continue karna hai?\"):\n            self._launch_job(\"bsod_clear_events\", lambda: self._append_log(self.bsod_log, f\"Result: {self._run_cmd('wevtutil cl System', timeout=60)[0]}\", C[\"warning\"]))\n\n    def _bsod_search_online(self, stop_code):\n        try:\n            os.startfile(f\"https://www.google.com/search?q=BSOD+{stop_code}+fix\")\n        except Exception as e:\n            self._append_log(self.bsod_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _build_corrupt_wizard(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"Corrupt Windows Repair Wizard\", \"Step-by-step SFC, DISM aur CBS analysis\")\n        content = self._scrollable_section_body(frame)\n        self.corrupt_results = {}\n        self.corrupt_indicator = tk.Frame(content, bg=C[\"bg\"])\n        self.corrupt_indicator.pack(fill=\"x\", padx=14, pady=8)\n        self.corrupt_content = tk.Frame(content, bg=C[\"card\"])\n        self.corrupt_content.pack(fill=\"both\", expand=True, padx=14, pady=8)\n        self.corrupt_log = self._scrolled_text(content, height=8)\n        nav = tk.Frame(content, bg=C[\"bg\"])\n        nav.pack(fill=\"x\", padx=14, pady=6)\n        self._btn(nav, \"\u21a9 Back\", C[\"btn_chip\"], self._corrupt_wizard_back).pack(side=\"left\", padx=4)\n        self._btn(nav, \"\u25b6 Next Step\", C[\"btn_info\"], self._corrupt_wizard_next).pack(side=\"left\", padx=4)\n        self._btn(nav, \"\u23ed Skip Step\", C[\"btn_warn\"], self._corrupt_wizard_skip).pack(side=\"left\", padx=4)\n        self._btn(nav, \"\u23f9 Stop\", C[\"btn_danger\"], self._corrupt_wizard_stop).pack(side=\"left\", padx=4)\n        self._corrupt_wizard_show_step(1)\n        return frame\n\n    def _corrupt_wizard_build_step_indicator(self, parent):\n        for w in parent.winfo_children():\n            w.destroy()\n        for i in range(1, 7):\n            color = C[\"accent\"] if i == self._corrupt_wizard_step else (C[\"success\"] if i &lt; self._corrupt_wizard_step else C[\"border\"])\n            tk.Label(parent, text=f\"  {i}  \", font=FONTS[\"subhead\"], fg=C[\"text\"], bg=color).pack(side=\"left\", padx=6, pady=4)\n        tk.Label(parent, text=f\"Step {self._corrupt_wizard_step} of 6\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"bg\"]).pack(side=\"left\", padx=14)\n\n    def _corrupt_wizard_show_step(self, step_num):\n        self._corrupt_wizard_step = max(1, min(6, int(step_num)))\n        self._corrupt_wizard_build_step_indicator(self.corrupt_indicator)\n        for w in self.corrupt_content.winfo_children():\n            w.destroy()\n        getattr(self, f\"_corrupt_wizard_build_step{self._corrupt_wizard_step}\")(self.corrupt_content)\n\n    def _corrupt_step_label(self, parent, title, body):\n        tk.Label(parent, text=title, font=(\"Segoe UI\", 16, \"bold\"), fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=14, pady=(14,4))\n        tk.Label(parent, text=body, font=FONTS[\"body\"], fg=C[\"text\"], bg=C[\"card\"], wraplength=900, justify=\"left\").pack(anchor=\"w\", padx=14, pady=(0,10))\n\n    def _corrupt_wizard_build_step1(self, parent):\n        self._corrupt_step_label(parent, \"Pre-Check &amp; Restore Point\", \"Repair shuru karne se pehle admin, free space aur Windows version check hota hai.\")\n        self._btn(parent, \"Pre-check chalao\", C[\"btn_info\"], lambda: self._launch_job(\"corrupt_precheck\", self._corrupt_check_prerequisites)).pack(anchor=\"w\", padx=14)\n        self._btn(parent, \"Restore Point banao\", C[\"btn_warn\"], lambda: self._launch_job(\"corrupt_restore_point\", lambda: self._append_log(self.corrupt_log, self._run_cmd('wmic.exe /Namespace:\\\\\\\\root\\\\default Path SystemRestore Call CreateRestorePoint \"Before Corrupt Windows Repair\", 100, 7', timeout=120)[0], C[\"warning\"]))).pack(anchor=\"w\", padx=14, pady=6)\n\n    def _corrupt_wizard_build_step2(self, parent):\n        self._corrupt_step_label(parent, \"SFC Scan\", \"Windows system files check karta hai aur corrupt files repair karne ki koshish karta hai.\")\n        self._btn(parent, \"Run SFC\", C[\"btn_info\"], lambda: self._launch_job(\"corrupt_sfc_1\", self._do_corrupt_sfc_scan, 2)).pack(anchor=\"w\", padx=14)\n\n    def _corrupt_wizard_build_step3(self, parent):\n        self._corrupt_step_label(parent, \"DISM RestoreHealth\", \"Windows image repair karta hai. Internet connection helpful hota hai.\")\n        self._btn(parent, \"Run DISM\", C[\"btn_danger\"], lambda: self._launch_job(\"corrupt_dism\", self._do_corrupt_dism)).pack(anchor=\"w\", padx=14)\n\n    def _corrupt_wizard_build_step4(self, parent):\n        self._corrupt_step_label(parent, \"SFC Re-scan\", \"DISM ke baad SFC dobara chalao taaki files final verify ho sakein.\")\n        self._btn(parent, \"Run SFC Dobara\", C[\"btn_info\"], lambda: self._launch_job(\"corrupt_sfc_2\", self._do_corrupt_sfc_scan, 4)).pack(anchor=\"w\", padx=14)\n\n    def _corrupt_wizard_build_step5(self, parent):\n        self._corrupt_step_label(parent, \"CBS Log Analysis\", \"CBS.log se exact corrupt file names nikaale jaate hain.\")\n        self._btn(parent, \"Analyze CBS Log\", C[\"btn_chip\"], lambda: self._launch_job(\"corrupt_cbs\", self._do_corrupt_cbs_analysis)).pack(anchor=\"w\", padx=14)\n        wrap, self.corrupt_cbs_tree = self._adv_tree(parent, [\"File Naam\", \"Path\", \"Status\"], height=8)\n        wrap.pack(fill=\"both\", expand=True, padx=14, pady=10)\n\n    def _corrupt_wizard_build_step6(self, parent):\n        self._corrupt_step_label(parent, \"Result &amp; Next Steps\", \"Repair run ka summary aur advanced recovery options.\")\n        for label, cmd in [(\"Open WinRE\", \"reagentc /boottore\"), (\"Safe Mode Enable\", \"bcdedit /set {current} safeboot minimal\"), (\"chkdsk Schedule\", \"chkdsk C: /f /r /x\"), (\"System Reset Option\", \"ms-settings:recovery\")]:\n            self._btn(parent, label, C[\"btn_warn\"], lambda c=cmd: self._run_cmd(c, timeout=120)).pack(side=\"left\", padx=8, pady=12)\n        self._btn(parent, \"Repair Report Save\", C[\"btn\"], self._corrupt_save_report).pack(side=\"left\", padx=8, pady=12)\n\n    def _corrupt_wizard_next(self):\n        self._corrupt_wizard_show_step(self._corrupt_wizard_step + 1)\n\n    def _corrupt_wizard_back(self):\n        self._corrupt_wizard_show_step(self._corrupt_wizard_step - 1)\n\n    def _corrupt_wizard_skip(self):\n        self._append_log(self.corrupt_log, f\"Step {self._corrupt_wizard_step} skip ho gaya\", C[\"warning\"])\n        self._corrupt_wizard_next()\n\n    def _corrupt_wizard_stop(self):\n        self._corrupt_wizard_running = False\n        self._append_log(self.corrupt_log, \"Stop request set ho gaya. Running command khatam hone par rukega.\", C[\"warning\"])\n\n    def _do_corrupt_sfc_scan(self, step):\n        try:\n            self._corrupt_wizard_running = True\n            out, rc = self._run_cmd(\"sfc /scannow\", timeout=3600)\n            result, color = self._corrupt_parse_sfc_result(out)\n            self.corrupt_results[f\"sfc_{step}\"] = result\n            self._append_log(self.corrupt_log, out[-3000:], color)\n            self._append_log(self.corrupt_log, result, color)\n        except Exception as e:\n            self._append_log(self.corrupt_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n        finally:\n            self._corrupt_wizard_running = False\n\n    def _do_corrupt_dism(self):\n        try:\n            out, rc = self._run_cmd(\"DISM /Online /Cleanup-Image /RestoreHealth /NoRestart\", timeout=3600)\n            ok = \"restore operation completed successfully\" in out.lower()\n            self.corrupt_results[\"dism\"] = \"DISM success\" if ok else \"DISM warning\"\n            self._append_log(self.corrupt_log, out[-3000:], C[\"success\"] if ok else C[\"warning\"])\n        except Exception as e:\n            self._append_log(self.corrupt_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _do_corrupt_cbs_analysis(self):\n        try:\n            rows = self._corrupt_parse_cbs_log()\n            def fill():\n                if hasattr(self, \"corrupt_cbs_tree\"):\n                    self.corrupt_cbs_tree.delete(*self.corrupt_cbs_tree.get_children())\n                    for r in rows:\n                        self.corrupt_cbs_tree.insert(\"\", \"end\", values=r)\n                self._append_log(self.corrupt_log, f\"\u2705 Kaam ho gaya: {len(rows)} CBS entries mile\", C[\"success\"] if not rows else C[\"warning\"])\n            self.after(0, fill)\n        except Exception as e:\n            self._append_log(self.corrupt_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _corrupt_parse_sfc_result(self, output):\n        low = (output or \"\").lower()\n        if \"did not find any integrity violations\" in low:\n            return \"\u2705 Corruption nahi mila\", C[\"success\"]\n        if \"found corrupt files and successfully repaired\" in low or \"repaired them\" in low:\n            return \"\u2705 Files automatically fix ho gayi\", C[\"success\"]\n        if \"unable to fix\" in low or \"unable to repair\" in low:\n            return \"\u26a0 Repair needed - Step 3 DISM chalao\", C[\"error\"]\n        if \"could not perform\" in low:\n            return \"\u26a0 Admin mode required ho sakta hai\", C[\"warning\"]\n        return \"SFC result clear nahi hai - log check karo\", C[\"warning\"]\n\n    def _corrupt_parse_cbs_log(self):\n        rows = []\n        path = r\"C:\\Windows\\Logs\\CBS\\CBS.log\"\n        if not os.path.exists(path):\n            return rows\n        with open(path, \"r\", encoding=\"utf-8\", errors=\"ignore\") as f:\n            for line in f:\n                if \"[SR]\" not in line:\n                    continue\n                name = None\n                for pat in [r\"\\[SR\\].*?Cannot repair member file \\[l:.*?\\](.+?),\", r\"\\[SR\\] Repairing (.+?) \\.\", r\"Cannot repair member file.*?\\\\(.+?)$\"]:\n                    m = re.search(pat, line)\n                    if m:\n                        name = m.group(1).strip().strip('\"')\n                        break\n                if name:\n                    rows.append((os.path.basename(name), name, \"CBS mein mention\"))\n                if len(rows) &gt;= 200:\n                    break\n        return rows\n\n    def _corrupt_check_prerequisites(self):\n        try:\n            admin = bool(ctypes.windll.shell32.IsUserAnAdmin())\n            free = shutil.disk_usage(\"C:\\\\\").free\n            ver = platform.platform()\n            self._append_log(self.corrupt_log, f\"Admin: {'Haan' if admin else 'Nahi'}\", C[\"success\"] if admin else C[\"error\"])\n            self._append_log(self.corrupt_log, f\"C free space: {self._fmt_size_disk(free)}\", C[\"success\"] if free &gt; 2*1024*1024*1024 else C[\"error\"])\n            self._append_log(self.corrupt_log, f\"Windows: {ver}\", C[\"accent\"])\n        except Exception as e:\n            self._append_log(self.corrupt_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _corrupt_save_report(self):\n        try:\n            path = os.path.join(os.environ.get(\"USERPROFILE\", \"\"), \"Desktop\", f\"Godawari_Repair_Report_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.txt\")\n            text = self.corrupt_log.get(\"1.0\", \"end\")\n            with open(path, \"w\", encoding=\"utf-8\") as f:\n                f.write(text)\n            messagebox.showinfo(\"Kaam ho gaya\", f\"Repair report save ho gayi:\\n{path}\")\n        except Exception as e:\n            self._append_log(self.corrupt_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _build_password_audit(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"Password &amp; Security Audit\", \"Accounts, firewall, BitLocker aur failed login check\")\n        content = self._scrollable_section_body(frame)\n        self._action_card_grid(content, [\n            (\"\ud83d\udd0d\", \"Full Scan\", \"Poora security audit chalao\", C[\"btn_info\"], self._sec_full_scan),\n            (\"\ud83d\udd12\", \"Firewall On\", \"Saare firewall profiles on karo\", C[\"btn_danger\"], self._sec_enable_firewall),\n            (\"\ud83d\udc65\", \"Guest Fix\", \"Guest account disable karo\", C[\"btn_warn\"], self._sec_fix_guest),\n            (\"\ud83d\udcbe\", \"Report Export\", \"Security report save karo\", C[\"btn\"], self._sec_export_report),\n            (\"\ud83d\udd11\", \"Password Reset\", \"Selected account ka password reset karo\", C[\"btn_chip\"], self._sec_reset_selected_password),\n        ], cols=5)\n        self.sec_summary = tk.Frame(content, bg=C[\"bg\"])\n        self.sec_summary.pack(fill=\"x\", padx=14)\n        self.sec_summary_labels = []\n        for title in [\"Local Accounts\", \"Security Issues\", \"Firewall\", \"BitLocker\"]:\n            card = self._stat_card(self.sec_summary, title, \"Scan pending\", C[\"accent\"])\n            card.pack(side=\"left\", fill=\"x\", expand=True, padx=5, pady=6)\n            self.sec_summary_labels.append(card._value_lbl)\n        nb = ttk.Notebook(content)\n        nb.pack(fill=\"both\", expand=True, padx=14, pady=8)\n        self.sec_trees = {}\n        for tab, cols in {\n            \"Accounts\": [\"Username\", \"Account Type\", \"Status\", \"Password Required\", \"Last Logon\", \"Risk\"],\n            \"Firewall\": [\"Profile\", \"State\", \"Inbound\", \"Outbound\", \"Note\"],\n            \"BitLocker\": [\"Drive\", \"Status\", \"Protection\", \"Encryption\", \"Recovery Key\"],\n            \"Login Events\": [\"Time\", \"Username\", \"Logon Type\", \"Source IP\", \"Reason\"],\n        }.items():\n            pane = tk.Frame(nb, bg=C[\"card\"])\n            nb.add(pane, text=tab)\n            wrap, tree = self._adv_tree(pane, cols, height=10)\n            wrap.pack(fill=\"both\", expand=True, padx=8, pady=8)\n            self.sec_trees[tab] = tree\n        self.sec_reco = self._scrolled_text(content, height=5)\n        self.sec_log = self._scrolled_text(content, height=5)\n        self.sec_data = {}\n        return frame\n\n    def _sec_full_scan(self):\n        self._launch_job(\"security_full_scan\", self._do_sec_full_scan)\n\n    def _do_sec_full_scan(self):\n        try:\n            data = {\"accounts\": self._sec_scan_accounts(), \"firewall\": self._sec_scan_firewall(), \"bitlocker\": self._sec_scan_bitlocker(), \"login\": self._sec_scan_login_events()}\n            self.sec_data = data\n            self.after(0, lambda: (self._sec_populate_accounts_tab(data[\"accounts\"]), self._sec_populate_firewall_tab(data[\"firewall\"]), self._sec_populate_bitlocker_tab(data[\"bitlocker\"]), self._sec_populate_login_tab(data[\"login\"]), self._sec_generate_recommendations(data)))\n        except Exception as e:\n            self._append_log(self.sec_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _sec_scan_accounts(self):\n        out, rc = self._run_cmd('powershell -NoProfile -Command \"Get-LocalUser | Select-Object Name,Enabled,PasswordRequired,LastLogon | ConvertTo-Json\"', timeout=80)\n        users = json.loads(out) if out.strip().startswith((\"{\", \"[\")) else []\n        if isinstance(users, dict):\n            users = [users]\n        admins_out, _ = self._run_cmd(\"net localgroup Administrators\", timeout=40)\n        return {\"users\": users, \"admins_text\": admins_out}\n\n    def _sec_scan_firewall(self):\n        out, rc = self._run_cmd(\"netsh advfirewall show allprofiles\", timeout=60)\n        return out\n\n    def _sec_scan_bitlocker(self):\n        rows = []\n        string_mod = __import__(\"string\")\n        for d in string_mod.ascii_uppercase:\n            drive = f\"{d}:\"\n            if os.path.exists(drive + \"\\\\\"):\n                out, rc = self._run_cmd(f\"manage-bde -status {drive}\", timeout=45)\n                rows.append((drive, out))\n        return rows\n\n    def _sec_scan_login_events(self):\n        out, rc = self._run_cmd(\"powershell -NoProfile -Command \\\"Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4625} -MaxEvents 30 -ErrorAction SilentlyContinue | Select-Object TimeCreated, Message | ConvertTo-Json\\\"\", timeout=90)\n        try:\n            data = json.loads(out) if out.strip() else []\n            return [data] if isinstance(data, dict) else data\n        except Exception:\n            return []\n\n    def _sec_populate_accounts_tab(self, data):\n        tree = self.sec_trees[\"Accounts\"]\n        tree.delete(*tree.get_children())\n        admins = data.get(\"admins_text\", \"\")\n        risks = 0\n        for u in data.get(\"users\", []):\n            name = u.get(\"Name\", \"\")\n            is_admin = name and name.lower() in admins.lower()\n            enabled = bool(u.get(\"Enabled\"))\n            pwd = bool(u.get(\"PasswordRequired\"))\n            risk = \"OK\"\n            if name.lower() == \"guest\" and enabled:\n                risk = \"HIGH\"\n            elif not pwd:\n                risk = \"MEDIUM\"\n            if risk != \"OK\":\n                risks += 1\n            tree.insert(\"\", \"end\", values=(name, \"Admin\" if is_admin else \"User\", \"Enabled\" if enabled else \"Disabled\", \"Haan\" if pwd else \"Nahi\", str(u.get(\"LastLogon\", \"\"))[:19], risk))\n        self.sec_summary_labels[0].config(text=f\"{len(data.get('users', []))} users\")\n        self.sec_summary_labels[1].config(text=f\"{risks} issues\")\n\n    def _sec_populate_firewall_tab(self, data):\n        tree = self.sec_trees[\"Firewall\"]\n        tree.delete(*tree.get_children())\n        on_count = len(re.findall(r\"State\\s+ON\", data, re.I))\n        for profile in [\"Domain\", \"Private\", \"Public\"]:\n            m = re.search(profile + r\".*?State\\s+(\\w+).*?Firewall Policy\\s+([^\\r\\n]+)\", data, re.I | re.S)\n            state = m.group(1) if m else \"Unknown\"\n            policy = m.group(2) if m else \"Nahi mila\"\n            tree.insert(\"\", \"end\", values=(profile, state, policy, policy, \"Firewall profile\"))\n        self.sec_summary_labels[2].config(text=\"All ON\" if on_count &gt;= 3 else \"Partially OFF\")\n\n    def _sec_populate_bitlocker_tab(self, data):\n        tree = self.sec_trees[\"BitLocker\"]\n        tree.delete(*tree.get_children())\n        protected = 0\n        for drive, out in data:\n            conv = re.search(r\"Conversion Status:\\s+(.+)\", out)\n            prot = re.search(r\"Protection Status:\\s+(.+)\", out)\n            enc = re.search(r\"Encryption Method:\\s+(.+)\", out)\n            ptxt = prot.group(1).strip() if prot else \"Unknown\"\n            if \"On\" in ptxt:\n                protected += 1\n            tree.insert(\"\", \"end\", values=(drive, conv.group(1).strip() if conv else \"Unknown\", ptxt, enc.group(1).strip() if enc else \"Unknown\", \"Check needed\"))\n        self.sec_summary_labels[3].config(text=f\"{protected}/{len(data)} protected\")\n\n    def _sec_populate_login_tab(self, data):\n        tree = self.sec_trees[\"Login Events\"]\n        tree.delete(*tree.get_children())\n        for ev in data:\n            msg = ev.get(\"Message\", \"\") or \"\"\n            user = re.search(r\"Account Name:\\s+([^\\r\\n]+)\", msg)\n            typ = re.search(r\"Logon Type:\\s+(\\d+)\", msg)\n            ip = re.search(r\"Source Network Address:\\s+([^\\r\\n]+)\", msg)\n            reason = re.search(r\"Failure Reason:\\s+([^\\r\\n]+)\", msg)\n            tree.insert(\"\", \"end\", values=(str(ev.get(\"TimeCreated\", \"\"))[:19], user.group(1).strip() if user else \"Nahi mila\", typ.group(1) if typ else \"Nahi\", ip.group(1).strip() if ip else \"-\", reason.group(1).strip() if reason else \"-\"))\n\n    def _sec_generate_recommendations(self, all_data):\n        recs = []\n        users = all_data.get(\"accounts\", {}).get(\"users\", [])\n        guest = [u for u in users if str(u.get(\"Name\", \"\")).lower() == \"guest\" and u.get(\"Enabled\")]\n        no_pwd = [u.get(\"Name\") for u in users if not u.get(\"PasswordRequired\")]\n        if guest:\n            recs.append(\"\u274c Guest account immediately disable karo\")\n        if no_pwd:\n            recs.append(\"\u274c In accounts ko password lagao: \" + \", \".join(map(str, no_pwd)))\n        if \"State                                 OFF\" in all_data.get(\"firewall\", \"\"):\n            recs.append(\"\u274c Windows Firewall enable karo\")\n        if not recs:\n            recs.append(\"\u2705 Major security issue nahi mila\")\n        self.sec_reco.config(state=\"normal\")\n        self.sec_reco.delete(\"1.0\", \"end\")\n        self.sec_reco.insert(\"end\", \"\\n\".join(recs))\n        self.sec_reco.config(state=\"disabled\")\n        self._append_log(self.sec_log, \"\u2705 Kaam ho gaya: Security audit complete\", C[\"success\"])\n\n    def _sec_enable_firewall(self):\n        if messagebox.askyesno(\"Confirm karo\", \"Saare firewall profiles ON karne hain?\"):\n            self._launch_job(\"sec_firewall_on\", lambda: self._append_log(self.sec_log, self._run_cmd(\"netsh advfirewall set allprofiles state on\", timeout=60)[0], C[\"success\"]))\n\n    def _sec_fix_guest(self):\n        if messagebox.askyesno(\"Confirm karo\", \"Guest account disable karna hai?\"):\n            self._launch_job(\"sec_guest_fix\", lambda: self._append_log(self.sec_log, self._run_cmd(\"net user Guest /active:no\", timeout=60)[0], C[\"success\"]))\n\n    def _sec_export_report(self):\n        try:\n            path = os.path.join(os.environ.get(\"USERPROFILE\", \"\"), \"Desktop\", f\"Godawari_Security_Report_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.json\")\n            with open(path, \"w\", encoding=\"utf-8\") as f:\n                json.dump(getattr(self, \"sec_data\", {}), f, indent=2, ensure_ascii=False, default=str)\n            messagebox.showinfo(\"Kaam ho gaya\", f\"Security report save ho gayi:\\n{path}\")\n        except Exception as e:\n            self._append_log(self.sec_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _sec_account_action(self, action, username):\n        cmds = {\"enable\": f\"net user {username} /active:yes\", \"disable\": f\"net user {username} /active:no\", \"require_password\": f\"net user {username} /passwordreq:yes\", \"remove_admin\": f\"net localgroup Administrators {username} /delete\"}\n        if action in cmds and messagebox.askyesno(\"Confirm karo\", f\"{username} par action apply karna hai?\"):\n            self._launch_job(\"sec_account_action\", lambda: self._append_log(self.sec_log, self._run_cmd(cmds[action], timeout=60)[0], C[\"warning\"]))\n\n    def _sec_reset_selected_password(self):\n        \"\"\"Reset password for selected account. PASSWORD FIELD IS OPTIONAL.\n        \n        ENGINEERING FIX #2: Allow empty password input to be treated as 'skip' or 'no-password mode'.\n        Empty input no longer triggers a validation error - user can choose to skip password reset.\n        \"\"\"\n        try:\n            tree = self.sec_trees.get(\"Accounts\") if hasattr(self, \"sec_trees\") else None\n            if tree is None:\n                messagebox.showwarning(\"Account select karo\", \"Pehle Security Scan chalao aur account select karo\")\n                return\n            sel = tree.selection()\n            if not sel:\n                messagebox.showwarning(\"Account select karo\", \"Pehle Accounts tab mein user select karo\")\n                return\n            username = tree.item(sel[0], \"values\")[0]\n            if not username:\n                messagebox.showwarning(\"User nahi mila\", \"Selected account ka username nahi mila\")\n                return\n            \n            simpledialog = __import__(\"tkinter.simpledialog\", fromlist=[\"askstring\"])\n            \n            # FIX: Password is now OPTIONAL - user can enter empty password to skip\n            new_password = simpledialog.askstring(\n                \"Naya password\",\n                f\"{username} ke liye naya password daalo:\\n\\n(Khali chhod ke OK karo to skip ho jayega)\",\n                show=\"*\"\n            )\n            if new_password is None:\n                # User clicked Cancel - operation aborted\n                return\n            \n            # FIX: Empty password is now ACCEPTED as 'skip' or 'no-password' mode\n            if not new_password:\n                # User entered empty password - ask if they want to skip OR set no password\n                choice = messagebox.askyesnocancel(\n                    \"Password Reset - Confirmation\",\n                    f\"Blank password entry for {username}:\\n\\n\"\n                    \"Yes = Set empty password (no-password mode)\\n\"\n                    \"No = Skip this account\\n\"\n                    \"Cancel = Go back and enter password\"\n                )\n                if choice is None:\n                    # User clicked Cancel - go back to ask for password again\n                    self._sec_reset_selected_password()\n                    return\n                elif choice is False:\n                    # User clicked No - skip this account\n                    messagebox.showinfo(\"Skipped\", f\"Password reset skipped for {username}\")\n                    return\n                # choice is True - proceed with empty password (no-password mode)\n            else:\n                # User entered a password - confirm it\n                confirm_password = simpledialog.askstring(\n                    \"Password confirm\",\n                    \"Naya password dobara daalo:\",\n                    show=\"*\"\n                )\n                if confirm_password is None:\n                    return\n                if new_password != confirm_password:\n                    messagebox.showerror(\"Password match nahi\", \"Dono password same nahi hain\")\n                    return\n                if len(new_password) &lt; 6:\n                    if not messagebox.askyesno(\"Password weak hai\", \"Password 6 characters se chhota hai. Kya phir bhi set karna hai?\"):\n                        return\n            \n            # Final confirmation before executing password reset\n            mode_text = \"no-password mode\" if not new_password else \"set karna\"\n            if not messagebox.askyesno(\"Kya aap sure hain?\", f\"{username} ka password {mode_text} hai? Confirm karo?\"):\n                return\n            \n            self._launch_job(\"sec_password_reset\", self._do_sec_reset_password, username, new_password)\n        except Exception as e:\n            self._append_log(self.sec_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _do_sec_reset_password(self, username, new_password):\n        \"\"\"Execute password reset for the user account.\n        \n        ENGINEERING FIX #3: Handles both regular passwords AND empty passwords (no-password mode).\n        Empty password is accepted and processed without error.\n        \"\"\"\n        try:\n            # FIX: Support empty password for no-password mode\n            if new_password == \"\":\n                # No-password mode: set empty password using PowerShell\n                cmd = (\n                    f\"powershell -NoProfile -Command \"\n                    f'\"$user = [ADSI](\\'WinNT://./\\' + \\'{username}\\'); '\n                    f'$user.SetPassword(\\'\\'); $user.CommitChanges()\"'\n                )\n                out, rc = self._run_cmd(cmd, timeout=60)\n                success_msg = f\"\u2705 No-password mode set for {username}\"\n                user_msg = f\"No-password mode activated for {username}\"\n            else:\n                # Regular password reset using net user command\n                out, rc = self._run_cmd([\"net\", \"user\", username, new_password], timeout=60)\n                success_msg = f\"\u2705 Kaam ho gaya: {username} ka password reset ho gaya\"\n                user_msg = f\"{username} ka password reset ho gaya\"\n            \n            if rc == 0:\n                self._append_log(self.sec_log, success_msg, C[\"success\"])\n                self.after(0, lambda m=user_msg: messagebox.showinfo(\"Kaam ho gaya\", m))\n                self.after(500, self._sec_full_scan)\n            else:\n                error_text = out[:300] if out else \"Unknown error\"\n                self._append_log(self.sec_log, f\"Password reset nahi hua: {error_text}\", C[\"error\"])\n                self.after(0, lambda: messagebox.showerror(\n                    \"Password reset nahi hua\",\n                    f\"{username} ka password reset nahi hua.\\n{error_text}\"\n                ))\n        except Exception as e:\n            self._append_log(self.sec_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _build_auto_backup(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"Auto Backup\", \"Sources, destination, schedule aur registry backup\")\n        content = self._scrollable_section_body(frame)\n        top = tk.Frame(content, bg=C[\"bg\"])\n        top.pack(fill=\"x\", padx=14, pady=8)\n        src = self._adv_card(top, \"Backup Sources\")\n        src.pack(side=\"left\", fill=\"both\", expand=True, padx=(0,8))\n        self.backup_source_list = tk.Listbox(src, bg=C[\"card\"], fg=C[\"text\"], selectbackground=C[\"accent\"], height=8)\n        self.backup_source_list.pack(fill=\"both\", expand=True, padx=8, pady=8)\n        user = os.environ.get(\"USERPROFILE\", \"\")\n        if not self.backup_sources:\n            self.backup_sources = [os.path.join(user, x) for x in [\"Desktop\", \"Documents\", \"Downloads\", \"Pictures\"] if os.path.exists(os.path.join(user, x))]\n        for p in self.backup_sources:\n            self.backup_source_list.insert(\"end\", p)\n        self._btn(src, \"Custom Folder Add\", C[\"btn_chip\"], lambda: self._backup_add_source()).pack(side=\"left\", padx=8, pady=4)\n        self._btn(src, \"Selected Remove\", C[\"btn_warn\"], lambda: self._backup_remove_source()).pack(side=\"left\", padx=8, pady=4)\n        dst = self._adv_card(top, \"Destination &amp; Schedule\")\n        dst.pack(side=\"right\", fill=\"both\", expand=True, padx=(8,0))\n        tk.Entry(dst, textvariable=self.backup_dest_var, bg=C[\"panel\"], fg=C[\"text\"]).pack(fill=\"x\", padx=8, pady=4)\n        self._btn(dst, \"Browse\", C[\"btn_chip\"], lambda: self.backup_dest_var.set(filedialog.askdirectory() or self.backup_dest_var.get())).pack(anchor=\"w\", padx=8)\n        ttk.Combobox(dst, textvariable=self.backup_schedule_var, values=[\"Manual Only\", \"Daily\", \"Weekly\", \"Monthly\"], state=\"readonly\").pack(fill=\"x\", padx=8, pady=4)\n        tk.Entry(dst, textvariable=self.backup_time_var, bg=C[\"panel\"], fg=C[\"text\"]).pack(fill=\"x\", padx=8, pady=4)\n        modes = self._adv_card(content, \"\ud83d\udcc1 Overwrite Mode - Backup Size Control\")\n        modes.pack(fill=\"x\", padx=14, pady=6)\n        for val, txt in [(\"mirror\", \"\u267b Overwrite Previous (Mirror) - size same rahega\"), (\"versioned\", \"\ud83d\udcc5 Keep Last N Versions - purane auto delete\"), (\"incremental\", \"\u26a1 Incremental - sirf changed files\")]:\n            tk.Radiobutton(modes, text=txt, variable=self.backup_overwrite_mode, value=val, bg=C[\"card\"], fg=C[\"text\"], selectcolor=C[\"panel\"], activebackground=C[\"card\"]).pack(anchor=\"w\", padx=8)\n        tk.Spinbox(modes, from_=1, to=10, textvariable=self.backup_keep_n, width=5, bg=C[\"panel\"], fg=C[\"text\"]).pack(anchor=\"w\", padx=28, pady=2)\n        reg = self._adv_card(content, \"\ud83d\uddc2 Registry Auto-Backup (RegBack)\")\n        reg.pack(fill=\"x\", padx=14, pady=6)\n        tk.Checkbutton(reg, text=\"RegBack enable rakho\", variable=self.regback_enabled, bg=C[\"card\"], fg=C[\"text\"], selectcolor=C[\"panel\"]).pack(anchor=\"w\", padx=8)\n        tk.Label(reg, text=\"Windows crash ho jaaye to restore ke liye SYSTEM, SOFTWARE, SAM, SECURITY, DEFAULT hives backup honge\", fg=C[\"warning\"], bg=C[\"card\"], font=FONTS[\"small\"], wraplength=1050, justify=\"left\").pack(anchor=\"w\", padx=8)\n        self._action_card_grid(content, [\n            (\"\u25b6\", \"Backup Now\", \"Abhi backup chalao\", C[\"btn_info\"], self._backup_run_now),\n            (\"\ud83d\udcc5\", \"Schedule Enable\", \"Task Scheduler mein add karo\", C[\"btn_chip\"], self._backup_schedule_enable),\n            (\"\u274c\", \"Schedule Remove\", \"Scheduled task hatao\", C[\"btn_warn\"], self._backup_schedule_remove),\n            (\"\ud83d\udcc2\", \"Folder Kholo\", \"Backup folder kholo\", C[\"accent2\"], self._backup_open_folder),\n            (\"\ud83d\udcbe\", \"Config Save\", \"Settings save karo\", C[\"btn\"], self._backup_save_config),\n            (\"\ud83d\udcc2\", \"Config Load\", \"Settings load karo\", C[\"btn_chip\"], self._backup_load_config),\n        ], cols=6)\n        # \u2500\u2500 Progress bar \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        prog_card = self._adv_card(content, \"\ud83d\udcca Backup Progress\")\n        prog_card.pack(fill=\"x\", padx=14, pady=4)\n        self.backup_progress_var = tk.DoubleVar(value=0.0)\n        self.backup_progress_bar = ttk.Progressbar(\n            prog_card, variable=self.backup_progress_var,\n            maximum=100, mode=\"determinate\")\n        self.backup_progress_bar.pack(fill=\"x\", padx=12, pady=(4, 2))\n        self.backup_status_lbl = tk.Label(\n            prog_card, text=\"Ready \u2014 'Backup Now' press karo\",\n            font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"])\n        self.backup_status_lbl.pack(anchor=\"w\", padx=12, pady=(0, 6))\n        # \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        wrap, self.backup_history_tree = self._adv_tree(content, [\"#\", \"Date Time\", \"Mode\", \"Sources\", \"Destination\", \"Total Size\", \"Status\", \"Duration\"], height=6)\n        wrap.pack(fill=\"x\", padx=14, pady=6)\n        self.backup_log = self._scrolled_text(content, height=6)\n        self._backup_load_config(silent=True)\n        self._backup_refresh_history()\n        return frame\n\n    def _backup_add_source(self):\n        p = filedialog.askdirectory()\n        if p:\n            self.backup_sources.append(p)\n            self.backup_source_list.insert(\"end\", p)\n\n    def _backup_remove_source(self):\n        try:\n            idx = self.backup_source_list.curselection()\n            if idx:\n                self.backup_sources.pop(idx[0])\n                self.backup_source_list.delete(idx[0])\n        except Exception as e:\n            self._append_log(self.backup_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _backup_run_now(self):\n        try:\n            dest = self.backup_dest_var.get().strip()\n            sources = self._backup_get_selected_sources()\n            mode = self.backup_overwrite_mode.get()\n            keep_n = int(self.backup_keep_n.get())\n            regback = bool(self.regback_enabled.get())\n            self._launch_job(\"auto_backup_now\", self._do_run_backup, dest, sources, mode, keep_n, regback)\n        except Exception as e:\n            self._append_log(self.backup_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _do_run_backup(self, dest=None, sources=None, mode=None, keep_n=None, regback_enabled=None):\n        def _set_status(msg, pct=None, color=None):\n            try:\n                self.after(0, lambda m=msg, c=color or C[\"text_dim\"]:\n                           self.backup_status_lbl.config(text=m, fg=c)\n                           if False else None)\n                self.after(0, lambda m=msg, c=color or C[\"text_dim\"]:\n                           self.backup_status_lbl.config(text=m, fg=c))\n                if pct is not None:\n                    self.after(0, lambda p=float(pct): self.backup_progress_var.set(p))\n            except Exception:\n                pass\n\n        def _set_indeterminate(on=True):\n            try:\n                if on:\n                    self.after(0, lambda: self.backup_progress_bar.config(mode=\"indeterminate\"))\n                    self.after(50, lambda: self.backup_progress_bar.start(12))\n                else:\n                    self.after(0, lambda: self.backup_progress_bar.stop())\n                    self.after(0, lambda: self.backup_progress_bar.config(mode=\"determinate\"))\n            except Exception:\n                pass\n\n        try:\n            dest = (dest or \"\").strip()\n            sources = list(sources or [])\n            if not dest or not os.path.isdir(dest):\n                self._append_log(self.backup_log, \"Pehle valid destination folder select karo\", C[\"error\"])\n                _set_status(\"\u274c Destination folder invalid hai\", color=C[\"error\"])\n                return\n            if not sources:\n                self._append_log(self.backup_log, \"Pehle backup source select karo\", C[\"error\"])\n                _set_status(\"\u274c Koi source select nahi kiya\", color=C[\"error\"])\n                return\n\n            start = time.time()\n            timestamp = datetime.datetime.now().strftime(\"%Y-%m-%d_%H-%M\")\n            mode = mode or \"mirror\"\n            base_dest = dest\n            if mode == \"versioned\":\n                base_dest = os.path.join(dest, f\"Backup_{timestamp}\")\n                os.makedirs(base_dest, exist_ok=True)\n\n            total_sources = len([s for s in sources if os.path.isdir(s)])\n            done_sources = 0\n\n            for source in sources:\n                if not os.path.isdir(source):\n                    self._append_log(self.backup_log, f\"\u26a0\ufe0f Skipped (not found): {source}\", C[\"warning\"])\n                    continue\n\n                src_name = os.path.basename(source.rstrip(\"\\\\/\")) or source\n                dest_sub = os.path.join(base_dest, src_name)\n\n                # Pre-count files for determinate progress\n                try:\n                    file_count = sum(len(files) for _, _, files in os.walk(source))\n                except Exception:\n                    file_count = 0\n\n                _set_status(f\"\ud83d\udcc2 Copying: {src_name}  ({done_sources+1}/{total_sources})  [{file_count} files]\",\n                            pct=(done_sources / max(1, total_sources)) * 85, color=C[\"accent4\"])\n                self._append_log(self.backup_log,\n                                 f\"\u25b6 Source: {source}  \u2192  {dest_sub}  ({file_count} files)\",\n                                 C[\"accent4\"])\n\n                flag = \"/MIR\" if mode == \"mirror\" else (\"/XO /E\" if mode == \"incremental\" else \"/E\")\n\n                # Stream robocopy output line by line for live feedback\n                try:\n                    startupinfo = subprocess.STARTUPINFO()\n                    startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW\n                    proc = subprocess.Popen(\n                        f'robocopy \"{source}\" \"{dest_sub}\" {flag} /R:2 /W:5 /NP /TEE',\n                        shell=True,\n                        stdout=subprocess.PIPE,\n                        stderr=subprocess.STDOUT,\n                        text=True,\n                        startupinfo=startupinfo,\n                    )\n                    copied = 0\n                    for line in proc.stdout:\n                        line = line.strip()\n                        if not line:\n                            continue\n                        # robocopy progress lines contain file names\n                        if any(x in line.lower() for x in [\"new file\", \"newer\", \"extra\", \"copying\"]):\n                            copied += 1\n                            if copied % 5 == 0 or file_count &lt;= 20:\n                                _set_status(\n                                    f\"\ud83d\udcc2 {src_name}: {copied} files copied\u2026\",\n                                    pct=min(85, (done_sources / max(1, total_sources)) * 85 +\n                                            min(15, (copied / max(1, file_count)) * 15)),\n                                    color=C[\"accent4\"]\n                                )\n                        # Log important lines only\n                        if any(x in line for x in [\"ERROR\", \"WARN\", \"Access is denied\", \"Failed\"]):\n                            self._append_log(self.backup_log, f\"  \u26a0\ufe0f {line}\", C[\"warning\"])\n                    rc = proc.wait()\n                except Exception as pex:\n                    rc = -1\n                    self._append_log(self.backup_log, f\"\u26a0\ufe0f robocopy error: {pex}\", C[\"warning\"])\n\n                color = C[\"success\"] if rc &lt; 8 else C[\"warning\"]\n                self._append_log(self.backup_log,\n                                 f\"  \u2705 {src_name}: robocopy exit code {rc}  ({copied if 'copied' in dir() else '?'} files copied)\",\n                                 color)\n                done_sources += 1\n\n            # Versioned: cleanup old backups\n            if mode == \"versioned\":\n                glob_mod = __import__(\"glob\")\n                versions = sorted(glob_mod.glob(os.path.join(dest, \"Backup_*\")))\n                while len(versions) &gt; int(keep_n or 3):\n                    shutil.rmtree(versions.pop(0), ignore_errors=True)\n\n            # Registry backup\n            _set_status(\"\ud83d\uddc2 Registry backup chal raha hai\u2026\", pct=88, color=C[\"accent4\"])\n            reg_backup_path = \"\"\n            if bool(regback_enabled):\n                reg_backup_path = self._do_regback_backup(base_dest) or \"\"\n\n            # Final size\n            _set_status(\"\ud83d\udcca Size calculate ho raha hai\u2026\", pct=95, color=C[\"text_dim\"])\n            total = self._backup_calculate_size(base_dest)\n            dur = time.time() - start\n            status = \"Files + Registry\" if reg_backup_path else \"Files only\"\n\n            self._backup_add_history({\n                \"dt\": datetime.datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\"),\n                \"mode\": mode,\n                \"sources\": len(sources),\n                \"dest\": base_dest,\n                \"size\": f\"{total:.1f} MB\",\n                \"status\": status,\n                \"duration\": f\"{dur:.1f}s\"\n            })\n\n            _set_status(f\"\u2705 Backup complete! {total:.1f} MB  \u2022  {dur:.1f}s\", pct=100, color=C[\"success\"])\n            self._append_log(self.backup_log, f\"\u2705 Kaam ho gaya: Backup complete  [{total:.1f} MB, {dur:.1f}s]\", C[\"success\"])\n            if reg_backup_path:\n                self._append_log(self.backup_log, f\"Registry recovery backup: {reg_backup_path}\", C[\"success\"])\n            self.after(0, lambda: messagebox.showinfo(\"Kaam ho gaya\", f\"\u2705 Backup complete!\\n\\nSize: {total:.1f} MB\\nTime: {dur:.1f}s\\nDest: {base_dest}\"))\n\n        except Exception as e:\n            _set_indeterminate(False)\n            _set_status(f\"\u274c Error: {e}\", pct=0, color=C[\"error\"])\n            self._append_log(self.backup_log, f\"\u274c Error aaya: {str(e)}\", C[\"error\"])\n\n    def _do_regback_backup(self, dest_folder):\n        try:\n            stamp = datetime.datetime.now().strftime(\"%Y-%m-%d_%H-%M-%S\")\n            reg_dest = os.path.join(dest_folder, f\"Registry_Recovery_{stamp}\")\n            os.makedirs(reg_dest, exist_ok=True)\n            regback = r\"C:\\Windows\\System32\\config\\RegBack\"\n            names = [\"DEFAULT\", \"SAM\", \"SECURITY\", \"SOFTWARE\", \"SYSTEM\"]\n            manifest = {\n                \"created_at\": datetime.datetime.now().isoformat(timespec=\"seconds\"),\n                \"machine\": platform.node(),\n                \"windows\": platform.platform(),\n                \"method\": \"\",\n                \"files\": [],\n                \"restore_note\": \"WinRE Command Prompt se restore karne ke liye RESTORE_GUIDE_HINGLISH.txt padho.\",\n            }\n            if os.path.exists(os.path.join(regback, \"SYSTEM\")) and os.path.getsize(os.path.join(regback, \"SYSTEM\")) &gt; 0:\n                manifest[\"method\"] = \"RegBack folder copy\"\n                for n in names:\n                    src = os.path.join(regback, n)\n                    if os.path.exists(src):\n                        dst = os.path.join(reg_dest, f\"{n}.hiv\")\n                        shutil.copy2(src, dst)\n                        manifest[\"files\"].append(self._backup_registry_file_info(dst, n))\n                        self._append_log(self.backup_log, f\"{n} hive backup ho gaya\", C[\"success\"])\n            else:\n                manifest[\"method\"] = \"Live reg save\"\n                hive_cmds = [\n                    (\"SYSTEM\", \"HKLM\\\\SYSTEM\"),\n                    (\"SOFTWARE\", \"HKLM\\\\SOFTWARE\"),\n                    (\"SAM\", \"HKLM\\\\SAM\"),\n                    (\"SECURITY\", \"HKLM\\\\SECURITY\"),\n                    (\"DEFAULT\", \"HKU\\\\.DEFAULT\"),\n                ]\n                for hive_name, hive_key in hive_cmds:\n                    dst = os.path.join(reg_dest, f\"{hive_name}.hiv\")\n                    out, rc = self._run_cmd(f'reg save \"{hive_key}\" \"{dst}\" /y', timeout=180)\n                    if rc == 0 and os.path.exists(dst):\n                        manifest[\"files\"].append(self._backup_registry_file_info(dst, hive_name))\n                        self._append_log(self.backup_log, f\"{hive_name} hive backup ho gaya\", C[\"success\"])\n                    else:\n                        self._append_log(self.backup_log, f\"{hive_name} hive backup nahi hua: {out[:200]}\", C[\"warning\"])\n            self._backup_write_registry_restore_guide(reg_dest, manifest)\n            with open(os.path.join(reg_dest, \"registry_manifest.json\"), \"w\", encoding=\"utf-8\") as f:\n                json.dump(manifest, f, indent=2, ensure_ascii=False)\n            self._append_log(self.backup_log, \"Registry crash-recovery backup complete ho gaya\", C[\"success\"])\n            return reg_dest\n        except Exception as e:\n            self._append_log(self.backup_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n            return \"\"\n\n    def _backup_registry_file_info(self, path, hive_name):\n        try:\n            h = hashlib.sha256()\n            with open(path, \"rb\") as f:\n                for chunk in iter(lambda: f.read(1024 * 1024), b\"\"):\n                    h.update(chunk)\n            return {\n                \"hive\": hive_name,\n                \"file\": os.path.basename(path),\n                \"size_bytes\": os.path.getsize(path),\n                \"sha256\": h.hexdigest(),\n            }\n        except Exception as e:\n            return {\n                \"hive\": hive_name,\n                \"file\": os.path.basename(path),\n                \"size_bytes\": 0,\n                \"error\": str(e),\n            }\n\n    def _backup_write_registry_restore_guide(self, reg_dest, manifest):\n        try:\n            guide = os.path.join(reg_dest, \"RESTORE_GUIDE_HINGLISH.txt\")\n            lines = [\n                \"Godawari Computers - Registry Crash Recovery Guide\",\n                \"\",\n                \"Kab use kare:\",\n                \"- Windows boot nahi ho raha ho aur registry corrupt ka doubt ho.\",\n                \"- Pehle customer ka data backup verify karo.\",\n                \"- Ye advanced recovery hai. Galat hive restore karne se Windows aur kharab ho sakta hai.\",\n                \"\",\n                \"WinRE se restore ka tarika:\",\n                \"1. Windows Recovery Environment open karo.\",\n                \"2. Troubleshoot &gt; Advanced options &gt; Command Prompt kholo.\",\n                \"3. Windows drive letter confirm karo. WinRE mein C: kabhi-kabhi D: hota hai.\",\n                \"   Command: bcdedit | find \\\"osdevice\\\"\",\n                \"4. Existing registry hives ka backup banao:\",\n                \"   mkdir C:\\\\Windows\\\\System32\\\\config\\\\Godawari_BadRegistry_Backup\",\n                \"   copy C:\\\\Windows\\\\System32\\\\config\\\\SYSTEM C:\\\\Windows\\\\System32\\\\config\\\\Godawari_BadRegistry_Backup\\\\SYSTEM.bad\",\n                \"   copy C:\\\\Windows\\\\System32\\\\config\\\\SOFTWARE C:\\\\Windows\\\\System32\\\\config\\\\Godawari_BadRegistry_Backup\\\\SOFTWARE.bad\",\n                \"   copy C:\\\\Windows\\\\System32\\\\config\\\\SAM C:\\\\Windows\\\\System32\\\\config\\\\Godawari_BadRegistry_Backup\\\\SAM.bad\",\n                \"   copy C:\\\\Windows\\\\System32\\\\config\\\\SECURITY C:\\\\Windows\\\\System32\\\\config\\\\Godawari_BadRegistry_Backup\\\\SECURITY.bad\",\n                \"   copy C:\\\\Windows\\\\System32\\\\config\\\\DEFAULT C:\\\\Windows\\\\System32\\\\config\\\\Godawari_BadRegistry_Backup\\\\DEFAULT.bad\",\n                \"\",\n                \"5. Is backup folder se hives restore karo. BACKUP_PATH ko actual path se replace karo:\",\n                \"   copy /y BACKUP_PATH\\\\SYSTEM.hiv C:\\\\Windows\\\\System32\\\\config\\\\SYSTEM\",\n                \"   copy /y BACKUP_PATH\\\\SOFTWARE.hiv C:\\\\Windows\\\\System32\\\\config\\\\SOFTWARE\",\n                \"   copy /y BACKUP_PATH\\\\SAM.hiv C:\\\\Windows\\\\System32\\\\config\\\\SAM\",\n                \"   copy /y BACKUP_PATH\\\\SECURITY.hiv C:\\\\Windows\\\\System32\\\\config\\\\SECURITY\",\n                \"   copy /y BACKUP_PATH\\\\DEFAULT.hiv C:\\\\Windows\\\\System32\\\\config\\\\DEFAULT\",\n                \"\",\n                \"6. Restart karo:\",\n                \"   wpeutil reboot\",\n                \"\",\n                \"Important:\",\n                \"- Agar backup external drive par hai to pehle drive letter check karo: diskpart &gt; list volume\",\n                \"- SYSTEM aur SOFTWARE hives same backup set se restore karo.\",\n                \"- BitLocker enabled ho to recovery key ki zaroorat pad sakti hai.\",\n                \"\",\n                f\"Backup created at: {manifest.get('created_at', '')}\",\n                f\"Machine: {manifest.get('machine', '')}\",\n                f\"Windows: {manifest.get('windows', '')}\",\n                f\"Backup method: {manifest.get('method', '')}\",\n                \"\",\n                \"Files:\",\n            ]\n            for item in manifest.get(\"files\", []):\n                lines.append(f\"- {item.get('hive')}: {item.get('file')} | {item.get('size_bytes')} bytes | sha256 {item.get('sha256', '')}\")\n            with open(guide, \"w\", encoding=\"utf-8\") as f:\n                f.write(\"\\n\".join(lines))\n        except Exception as e:\n            self._append_log(self.backup_log, f\"Restore guide banane mein error aaya: {str(e)}\", C[\"warning\"])\n\n    def _backup_config_data(self):\n        return {\"sources\": self.backup_sources, \"dest\": self.backup_dest_var.get(), \"schedule\": self.backup_schedule_var.get(), \"time\": self.backup_time_var.get(), \"mode\": self.backup_overwrite_mode.get(), \"keep_n\": self.backup_keep_n.get(), \"regback\": self.regback_enabled.get(), \"history\": getattr(self, \"backup_history\", [])}\n\n    def _backup_save_config(self):\n        try:\n            os.makedirs(os.path.dirname(self.backup_config_file), exist_ok=True)\n            with open(self.backup_config_file, \"w\", encoding=\"utf-8\") as f:\n                json.dump(self._backup_config_data(), f, indent=2, ensure_ascii=False)\n            self._append_log(self.backup_log, \"\u2705 Kaam ho gaya: Config save ho gaya\", C[\"success\"])\n        except Exception as e:\n            self._append_log(self.backup_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _backup_load_config(self, silent=False):\n        try:\n            if os.path.exists(self.backup_config_file):\n                with open(self.backup_config_file, \"r\", encoding=\"utf-8\") as f:\n                    data = json.load(f)\n                self.backup_sources = data.get(\"sources\", self.backup_sources)\n                self.backup_dest_var.set(data.get(\"dest\", \"\"))\n                self.backup_schedule_var.set(data.get(\"schedule\", \"Manual Only\"))\n                self.backup_time_var.set(data.get(\"time\", \"02:00\"))\n                self.backup_overwrite_mode.set(data.get(\"mode\", \"mirror\"))\n                self.backup_keep_n.set(int(data.get(\"keep_n\", 3)))\n                self.regback_enabled.set(bool(data.get(\"regback\", True)))\n                self.backup_history = data.get(\"history\", [])\n                if hasattr(self, \"backup_source_list\"):\n                    self.backup_source_list.delete(0, \"end\")\n                    for p in self.backup_sources:\n                        self.backup_source_list.insert(\"end\", p)\n            if not silent:\n                self._append_log(self.backup_log, \"\u2705 Kaam ho gaya: Config load ho gaya\", C[\"success\"])\n        except Exception as e:\n            if not silent:\n                self._append_log(self.backup_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _backup_schedule_enable(self):\n        try:\n            sched = self.backup_schedule_var.get()\n            if sched == \"Manual Only\":\n                messagebox.showwarning(\"Schedule nahi hai\", \"Daily, Weekly ya Monthly select karo\")\n                return\n            script_path = sys.argv[0]\n            time_txt = self.backup_time_var.get()\n            sc = \"daily\" if sched == \"Daily\" else (\"weekly /d MON\" if sched == \"Weekly\" else \"monthly /d 1\")\n            cmd = f'schtasks /create /tn \"GodawariAutoBackup\" /tr \"pythonw \\\\\"{script_path}\\\\\" --backup\" /sc {sc} /st {time_txt} /f'\n            self._launch_job(\"backup_schedule_enable\", lambda: self._append_log(self.backup_log, self._run_cmd(cmd, timeout=90)[0], C[\"success\"]))\n        except Exception as e:\n            self._append_log(self.backup_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _backup_schedule_remove(self):\n        if messagebox.askyesno(\"Confirm karo\", \"GodawariAutoBackup scheduled task remove karna hai?\"):\n            self._launch_job(\"backup_schedule_remove\", lambda: self._append_log(self.backup_log, self._run_cmd('schtasks /delete /tn \"GodawariAutoBackup\" /f', timeout=60)[0], C[\"warning\"]))\n\n    def _backup_add_history(self, entry):\n        self.backup_history = getattr(self, \"backup_history\", [])\n        self.backup_history.insert(0, entry)\n        self.backup_history = self.backup_history[:50]\n        self.after(0, self._backup_save_config)\n        self.after(0, self._backup_refresh_history)\n\n    def _backup_refresh_history(self):\n        try:\n            if not hasattr(self, \"backup_history\"):\n                self.backup_history = []\n            if hasattr(self, \"backup_history_tree\"):\n                self.backup_history_tree.delete(*self.backup_history_tree.get_children())\n                for i, h in enumerate(self.backup_history[:50], 1):\n                    self.backup_history_tree.insert(\"\", \"end\", values=(i, h.get(\"dt\", \"\"), h.get(\"mode\", \"\"), h.get(\"sources\", \"\"), h.get(\"dest\", \"\"), h.get(\"size\", \"\"), h.get(\"status\", \"\"), h.get(\"duration\", \"\")))\n        except Exception as e:\n            self._append_log(self.backup_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _backup_calculate_size(self, folder):\n        total = 0\n        try:\n            for root, dirs, files in os.walk(folder):\n                for fn in files:\n                    try:\n                        total += os.path.getsize(os.path.join(root, fn))\n                    except Exception:\n                        pass\n        except Exception:\n            pass\n        return total / (1024 * 1024)\n\n    def _backup_open_folder(self):\n        try:\n            dest = self.backup_dest_var.get().strip()\n            if dest and os.path.isdir(dest):\n                os.startfile(dest)\n            else:\n                messagebox.showwarning(\"Folder nahi mila\", \"Pehle valid backup folder select karo\")\n        except Exception as e:\n            self._append_log(self.backup_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _backup_get_selected_sources(self):\n        try:\n            if hasattr(self, \"backup_source_list\") and self.backup_source_list.curselection():\n                return [self.backup_source_list.get(i) for i in self.backup_source_list.curselection()]\n            return list(self.backup_sources)\n        except Exception:\n            return list(self.backup_sources)\n\n    # ---------- UTILITIES ----------\n    def _toggle_theme(self):\n        self.current_theme = \"light\" if self.current_theme == \"dark\" else \"dark\"\n        self.theme_btn.config(text=\"\u2600\ufe0f\" if self.current_theme == \"light\" else \"\ud83c\udf19\")\n\n    def _save_settings(self):\n        try:\n            with open(self.settings_file, \"w\") as f:\n                json.dump({\"theme\": self.current_theme}, f)\n        except:\n            pass\n\n    def _load_settings(self):\n        if os.path.exists(self.settings_file):\n            try:\n                with open(self.settings_file, \"r\") as f:\n                    data = json.load(f)\n                    self.current_theme = data.get(\"theme\", \"dark\")\n            except:\n                pass\n\n    def _fmt_size(self, size):\n        for unit in [\"B\",\"KB\",\"MB\",\"GB\"]:\n            if size &lt; 1024:\n                return f\"{size:.1f} {unit}\"\n            size /= 1024\n        return f\"{size:.1f} TB\"\n\n    def _format_seconds(self, seconds):\n        try:\n            seconds = max(0, int(float(seconds)))\n        except Exception:\n            seconds = 0\n        h, rem = divmod(seconds, 3600)\n        m, s = divmod(rem, 60)\n        if h:\n            return f\"{h:02d}:{m:02d}:{s:02d}\"\n        return f\"{m:02d}:{s:02d}\"\n\n    def _section_header(self, parent, title, subtitle=\"\", hw=False):\n        hdr = tk.Frame(parent, bg=C[\"panel\"] if not hw else \"#1A0A2E\")\n        hdr.pack(fill=\"x\")\n        fg = C[\"hw_accent\"] if hw else C[\"accent\"]\n        tk.Label(hdr, text=f\"  {title}\", font=FONTS[\"heading\"], fg=fg, bg=hdr[\"bg\"]).pack(side=\"left\", pady=10, padx=8)\n        if subtitle:\n            tk.Label(hdr, text=f\"\u2014  {subtitle}\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=hdr[\"bg\"]).pack(side=\"left\", pady=10)\n\n    def _btn(self, parent, text, color, cmd):\n        return tk.Button(parent, text=self._fix_text(text), font=FONTS[\"small\"], bg=color, fg=C[\"text\"], bd=0, padx=12, pady=6, cursor=\"hand2\", command=cmd)\n\n    def _action_card_grid(self, parent, actions, cols=4, button_refs=None):\n        \"\"\"\n        HDD/SSD repair jaisa card-grid banata hai.\n        actions = list of (emoji, title, subtitle, color, cmd_func)\n        cols = columns per row (default 4)\n        button_refs = optional list to collect created button widgets.\n        \"\"\"\n        grid_frame = tk.Frame(parent, bg=C[\"bg\"])\n        grid_frame.pack(fill=\"x\", padx=14, pady=4)\n        cols = max(1, min(int(cols or 1), 4))\n        for i in range(cols):\n            grid_frame.columnconfigure(i, weight=1)\n        for idx, (emoji, title, subtitle, color, cmd_func) in enumerate(actions):\n            col = idx % cols\n            row_n = idx // cols\n            card = tk.Frame(grid_frame, bg=C[\"card\"], bd=1, relief=\"flat\",\n                            highlightbackground=color, highlightthickness=1)\n            card.grid(row=row_n, column=col, padx=5, pady=5, sticky=\"nsew\")\n            tk.Label(card, text=emoji, font=(\"Segoe UI\", 18),\n                     fg=color, bg=C[\"card\"]).pack(pady=(8, 2))\n            tk.Label(card, text=title, font=FONTS[\"subhead\"],\n                     fg=C[\"text\"], bg=C[\"card\"]).pack()\n            tk.Label(card, text=subtitle, font=FONTS[\"small\"],\n                     fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=160, justify=\"center\").pack(padx=6)\n            btn = tk.Button(card, text=\"\u25b6  Run\", font=FONTS[\"small\"],\n                      bg=color, fg=\"#000\" if color in (C.get(\"accent\",\"\"), C.get(\"accent2\",\"\")) else C[\"text\"],\n                      bd=0, padx=12, pady=5, cursor=\"hand2\",\n                      command=cmd_func)\n            btn.pack(pady=(6, 10))\n            if isinstance(button_refs, list):\n                button_refs.append(btn)\n        return grid_frame\n\n    def _compact_action_grid(self, parent, actions, cols=2):\n        grid = tk.Frame(parent, bg=C[\"card\"])\n        grid.pack(fill=\"x\", padx=8, pady=(0, 6))\n        cols = max(1, int(cols or 1))\n        for i in range(cols):\n            grid.columnconfigure(i, weight=1)\n        for idx, (label, color, cmd_func) in enumerate(actions):\n            row = idx // cols\n            col = idx % cols\n            btn = tk.Button(\n                grid, text=self._fix_text(label), font=FONTS[\"small\"],\n                bg=color, fg=C[\"text\"], bd=0, padx=8, pady=5,\n                cursor=\"hand2\", command=cmd_func\n            )\n            btn.grid(row=row, column=col, sticky=\"ew\", padx=3, pady=3)\n        return grid\n\n    def _bind_tree_responsive_columns(self, tree, specs):\n        \"\"\"\n        specs: [(column_name, base_width, grow_weight), ...]\n        Keeps tree columns readable while allowing wide screens to use extra room.\n        \"\"\"\n        safe_specs = []\n        for col, base, weight in specs:\n            try:\n                safe_specs.append((col, max(40, int(base)), max(0, int(weight))))\n            except Exception:\n                pass\n        if not safe_specs:\n            return\n\n        def _resize(_event=None):\n            try:\n                base_total = sum(base for _col, base, _weight in safe_specs)\n                available = max(tree.winfo_width() - 28, base_total)\n                extra = max(0, available - base_total)\n                weight_total = sum(weight for _col, _base, weight in safe_specs) or 1\n                for col, base, weight in safe_specs:\n                    width = base + int(extra * (weight / weight_total))\n                    tree.column(col, width=width, stretch=True)\n            except Exception:\n                pass\n\n        tree.bind(\"\", _resize, add=\"+\")\n        try:\n            tree.after(80, _resize)\n        except Exception:\n            pass\n\n    def _scrolled_text(self, parent, height=12):\n        st = scrolledtext.ScrolledText(parent, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], height=height, bd=0, wrap=\"word\", relief=\"flat\", state=\"disabled\")\n        st.pack(fill=\"both\", expand=True, padx=8, pady=(0,8))\n        return st\n\n    def _stat_card(self, parent, title, value, color):\n        card = tk.Frame(parent, bg=C[\"card\"], pady=14, padx=14)\n        tk.Label(card, text=title, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\")\n        lbl = tk.Label(card, text=value, font=(\"Segoe UI\", 22, \"bold\"), fg=color, bg=C[\"card\"])\n        lbl.pack(anchor=\"w\", pady=(4,0))\n        bar = ttk.Progressbar(card, length=140, mode=\"determinate\")\n        bar.pack(fill=\"x\", pady=(6,0))\n        card._value_lbl = lbl\n        card._bar = bar\n        return card\n\n    def _append_log(self, widget, msg, color=None):\n        def _do():\n            try:\n                widget.config(state=\"normal\")\n                start = widget.index(\"end-1c\")\n                widget.insert(\"end\", self._fix_text(msg) + \"\\n\")\n                if color:\n                    end = widget.index(\"end-1c\")\n                    tag = f\"c{color.replace('#','')}\"\n                    widget.tag_config(tag, foreground=color)\n                    widget.tag_add(tag, start, end)\n                widget.see(\"end\")\n                widget.config(state=\"disabled\")\n            except Exception:\n                pass\n        self.after(0, _do)\n\n    def _reg_set(self, hive, path, name, value, vtype):\n        try:\n            key = winreg.OpenKey(hive, path, 0, winreg.KEY_ALL_ACCESS)\n        except:\n            key = winreg.CreateKey(hive, path)\n        winreg.SetValueEx(key, name, 0, vtype, value)\n        winreg.CloseKey(key)\n\n    def _reg_get(self, hive, path, name):\n        try:\n            key = winreg.OpenKey(hive, path, 0, winreg.KEY_READ)\n            try:\n                value, vtype = winreg.QueryValueEx(key, name)\n                return True, value, vtype\n            finally:\n                winreg.CloseKey(key)\n        except FileNotFoundError:\n            return False, None, None\n        except OSError:\n            return False, None, None\n\n    def _same_reg_value(self, current, desired, vtype):\n        if vtype == winreg.REG_DWORD:\n            try:\n                return int(current) == int(desired)\n            except Exception:\n                return False\n        if vtype == winreg.REG_BINARY:\n            return bytes(current or b\"\") == bytes(desired or b\"\")\n        return str(current) == str(desired)\n\n    def _action_summary(self, title, results):\n        changed = sum(1 for r in results if r.get(\"state\") == \"changed\")\n        already = sum(1 for r in results if r.get(\"state\") == \"already\")\n        failed = [r for r in results if r.get(\"state\") == \"failed\"]\n        lines = [f\"{title} summary:\"]\n        lines.append(f\"Applied now: {changed}\")\n        lines.append(f\"Already done: {already}\")\n        if failed:\n            lines.append(f\"Failed: {len(failed)}\")\n            lines.extend(f\"- {r.get('label', 'item')}: {r.get('error', '')}\" for r in failed[:8])\n        elif changed == 0 and already &gt; 0:\n            lines.append(\"No new change needed.\")\n        return {\n            \"changed\": changed,\n            \"already\": already,\n            \"failed\": len(failed),\n            \"already_done\": changed == 0 and already &gt; 0 and not failed,\n            \"message\": \"\\n\".join(lines),\n        }\n\n    def _reg_set_checked(self, hive, path, name, value, vtype, label=None, log_widget=None):\n        label = label or name\n        exists, current, current_type = self._reg_get(hive, path, name)\n        if exists and current_type == vtype and self._same_reg_value(current, value, vtype):\n            if log_widget is not None:\n                self._append_log(log_widget, f\"Already done: {label}\", C[\"warning\"])\n            return {\"state\": \"already\", \"label\": label}\n        try:\n            self._reg_set(hive, path, name, value, vtype)\n            if log_widget is not None:\n                self._append_log(log_widget, f\"Applied: {label}\", C[\"success\"])\n            return {\"state\": \"changed\", \"label\": label}\n        except Exception as e:\n            if log_widget is not None:\n                self._append_log(log_widget, f\"Failed: {label} - {e}\", C[\"error\"])\n            return {\"state\": \"failed\", \"label\": label, \"error\": str(e)}\n\n    def _service_state(self, name):\n        out, rc = self._run_cmd(f'sc query \"{name}\"', timeout=20)\n        if rc != 0:\n            return \"\", out\n        match = re.search(r\"STATE\\s*:\\s*\\d+\\s+([A-Z_]+)\", out, re.I)\n        return (match.group(1).upper() if match else \"\"), out\n\n    def _service_start_mode(self, name):\n        out, rc = self._run_cmd(f'sc qc \"{name}\"', timeout=20)\n        if rc != 0:\n            return \"\", out\n        match = re.search(r\"START_TYPE\\s*:\\s*\\d+\\s+([A-Z_]+)\", out, re.I)\n        return (match.group(1).upper() if match else \"\"), out\n\n    def _service_dependents(self, name):\n        \"\"\"\n        Return list of dependent service names (best-effort).\n        Uses: sc enumdepend \n        \"\"\"\n        out, rc = self._run_cmd(f'sc enumdepend \"{name}\"', timeout=25)\n        if rc != 0 or not out:\n            return []\n        deps = []\n        for ln in out.splitlines():\n            ln = ln.strip()\n            if not ln:\n                continue\n            m = re.search(r\"^SERVICE_NAME:\\s*(.+)$\", ln, re.I)\n            if m:\n                dep = m.group(1).strip()\n                if dep and dep.lower() not in {name.lower()}:\n                    deps.append(dep)\n        # Dedupe preserve order\n        seen = set()\n        uniq = []\n        for d in deps:\n            dl = d.lower()\n            if dl in seen:\n                continue\n            seen.add(dl)\n            uniq.append(d)\n        return uniq\n\n    def _svc_snapshot_path(self):\n        base = getattr(self, \"backup_dir\", \"\") or os.getcwd()\n        return os.path.join(base, \"service_startmode_snapshot.json\")\n\n    def _svc_save_start_mode_snapshot(self, names):\n        try:\n            items = {}\n            for n in names:\n                mode, _ = self._service_start_mode(n)\n                if mode:\n                    items[n] = mode\n            if not items:\n                return\n            payload = {\n                \"ts\": datetime.datetime.now().isoformat(timespec=\"seconds\"),\n                \"items\": items,\n            }\n            with open(self._svc_snapshot_path(), \"w\", encoding=\"utf-8\") as f:\n                json.dump(payload, f, ensure_ascii=False, indent=2)\n        except Exception:\n            pass\n\n    def _svc_restore_snapshot(self):\n        path = self._svc_snapshot_path()\n        if not os.path.exists(path):\n            messagebox.showwarning(\"No Snapshot\", f\"Snapshot file nahi mili:\\n{path}\\n\\nPehle disable actions chalao (snapshot auto save hota hai).\")\n            return\n        if not messagebox.askyesno(\"Restore Snapshot\", \"Snapshot se previous service start-modes restore karein?\\n(Admin required for some services)\"):\n            return\n        try:\n            with open(path, \"r\", encoding=\"utf-8\") as f:\n                payload = json.load(f)\n            items = (payload or {}).get(\"items\", {}) if isinstance(payload, dict) else {}\n        except Exception as e:\n            messagebox.showerror(\"Snapshot Error\", str(e))\n            return\n        if not items:\n            messagebox.showinfo(\"Empty Snapshot\", \"Snapshot empty hai.\")\n            return\n        # Map SC qc START_TYPE to sc config value\n        map_mode = {\n            \"DISABLED\": \"disabled\",\n            \"AUTO_START\": \"auto\",\n            \"DEMAND_START\": \"demand\",\n        }\n        results = []\n        for name, mode in items.items():\n            start_type = map_mode.get(str(mode).upper(), \"demand\")\n            results.append(self._service_config_checked(name, start_type, f\"{name} start={start_type}\", None))\n        summary = self._action_summary(\"Service Snapshot Restore\", results)\n        messagebox.showinfo(\"Restore Result\", summary[\"message\"])\n        self._scan_impacting_services()\n\n    def _svc_apply_pack(self, pack):\n        if not messagebox.askyesno(\"Apply Service Pack\", f\"Apply recommended pack: {pack}?\\n\\nReboot recommended.\"):\n            return\n        # Keep it conservative; snapshot first for rollback\n        targets = []\n        if pack == \"ssd_laptop\":\n            targets = [\n                (\"SysMain\", \"disabled\"),\n                (\"WSearch\", \"disabled\"),\n                (\"DiagTrack\", \"disabled\"),\n            ]\n        elif pack == \"hdd_desktop\":\n            targets = [\n                (\"DiagTrack\", \"disabled\"),\n                (\"WSearch\", \"disabled\"),\n            ]\n        names = [t[0] for t in targets]\n        self._svc_save_start_mode_snapshot(names)\n        results = []\n        for svc, start in targets:\n            results.append(self._service_config_checked(svc, start, f\"{svc} start={start}\", None))\n            if start == \"disabled\":\n                results.append(self._service_stop_checked(svc, svc, None))\n        summary = self._action_summary(f\"Service Pack: {pack}\", results)\n        messagebox.showinfo(\"Pack Result\", summary[\"message\"] + \"\\nRestart recommended.\")\n        self._scan_impacting_services()\n\n    def _service_stop_checked(self, name, label=None, log_widget=None):\n        label = label or name\n        state, detail = self._service_state(name)\n        if state == \"STOPPED\":\n            if log_widget is not None:\n                self._append_log(log_widget, f\"Already stopped: {label}\", C[\"warning\"])\n            return {\"state\": \"already\", \"label\": label}\n        out, rc = self._run_cmd(f'sc stop \"{name}\"', timeout=40)\n        combined = f\"{detail}\\n{out}\".lower()\n        if rc == 0 or \"stop_pending\" in combined or \"stopped\" in combined:\n            if log_widget is not None:\n                self._append_log(log_widget, f\"Stopped: {label}\", C[\"success\"])\n            return {\"state\": \"changed\", \"label\": label}\n        if \"not been started\" in combined or \"service has not been started\" in combined:\n            if log_widget is not None:\n                self._append_log(log_widget, f\"Already stopped: {label}\", C[\"warning\"])\n            return {\"state\": \"already\", \"label\": label}\n        if log_widget is not None:\n            self._append_log(log_widget, f\"Stop failed: {label} - {out[:120]}\", C[\"error\"])\n        return {\"state\": \"failed\", \"label\": label, \"error\": out[:300]}\n\n    def _service_start_checked(self, name, label=None, log_widget=None):\n        label = label or name\n        state, _ = self._service_state(name)\n        if state == \"RUNNING\":\n            if log_widget is not None:\n                self._append_log(log_widget, f\"Already running: {label}\", C[\"warning\"])\n            return {\"state\": \"already\", \"label\": label}\n        out, rc = self._run_cmd(f'sc start \"{name}\"', timeout=40)\n        combined = out.lower()\n        if rc == 0 or \"running\" in combined or \"start_pending\" in combined:\n            if log_widget is not None:\n                self._append_log(log_widget, f\"Started: {label}\", C[\"success\"])\n            return {\"state\": \"changed\", \"label\": label}\n        if \"already running\" in combined or \"instance of the service is already running\" in combined:\n            if log_widget is not None:\n                self._append_log(log_widget, f\"Already running: {label}\", C[\"warning\"])\n            return {\"state\": \"already\", \"label\": label}\n        if log_widget is not None:\n            self._append_log(log_widget, f\"Start failed: {label} - {out[:120]}\", C[\"error\"])\n        return {\"state\": \"failed\", \"label\": label, \"error\": out[:300]}\n\n    def _service_config_checked(self, name, start_type, label=None, log_widget=None):\n        label = label or name\n        desired = {\n            \"disabled\": \"DISABLED\",\n            \"auto\": \"AUTO_START\",\n            \"demand\": \"DEMAND_START\",\n            \"manual\": \"DEMAND_START\",\n        }.get(str(start_type).lower(), str(start_type).upper())\n        current, _ = self._service_start_mode(name)\n        if current == desired:\n            if log_widget is not None:\n                self._append_log(log_widget, f\"Already configured: {label} start={start_type}\", C[\"warning\"])\n            return {\"state\": \"already\", \"label\": label}\n        out, rc = self._run_cmd(f'sc config \"{name}\" start= {start_type}', timeout=30)\n        if rc == 0:\n            if log_widget is not None:\n                self._append_log(log_widget, f\"Configured: {label} start={start_type}\", C[\"success\"])\n            return {\"state\": \"changed\", \"label\": label}\n        if log_widget is not None:\n            self._append_log(log_widget, f\"Config failed: {label} - {out[:120]}\", C[\"error\"])\n        return {\"state\": \"failed\", \"label\": label, \"error\": out[:300]}\n\n    def _fsutil_last_access_checked(self, log_widget=None):\n        label = \"NTFS last access timestamp\"\n        out, _ = self._run_cmd(\"fsutil behavior query disablelastaccess\", timeout=20)\n        match = re.search(r\"DisableLastAccess\\s*=\\s*(\\d+)\", out, re.I)\n        if match and int(match.group(1)) in (1, 3):\n            if log_widget is not None:\n                self._append_log(log_widget, f\"Already done: {label}\", C[\"warning\"])\n            return {\"state\": \"already\", \"label\": label}\n        out, rc = self._run_cmd(\"fsutil behavior set disablelastaccess 1\", timeout=30)\n        if rc == 0:\n            if log_widget is not None:\n                self._append_log(log_widget, f\"Applied: {label}\", C[\"success\"])\n            return {\"state\": \"changed\", \"label\": label}\n        if log_widget is not None:\n            self._append_log(log_widget, f\"Failed: {label} - {out[:120]}\", C[\"error\"])\n        return {\"state\": \"failed\", \"label\": label, \"error\": out[:300]}\n\n    def _task_records_from_schtasks(self, out):\n        try:\n            reader = csv.DictReader(io.StringIO(out))\n            records = []\n            for row in reader:\n                task_name = (row.get(\"TaskName\") or row.get(\"Task Name\") or \"\").strip()\n                if task_name:\n                    records.append(row)\n            if records:\n                return records\n        except Exception:\n            pass\n        records = []\n        try:\n            for row in csv.reader(io.StringIO(out)):\n                if len(row) &lt; 2:\n                    continue\n                first = row[0].strip()\n                if first in (\"HostName\", \"TaskName\"):\n                    continue\n                task_name = row[1].strip() if len(row) &gt; 1 else first\n                if task_name:\n                    records.append({\n                        \"TaskName\": task_name,\n                        \"Status\": row[3].strip() if len(row) &gt; 3 else \"\",\n                        \"Last Run Time\": row[5].strip() if len(row) &gt; 5 else \"\",\n                        \"Run As User\": row[14].strip() if len(row) &gt; 14 else \"\",\n                        \"Task To Run\": row[8].strip() if len(row) &gt; 8 else \"\",\n                        \"Scheduled Task State\": row[11].strip() if len(row) &gt; 11 else \"\",\n                    })\n        except Exception:\n            pass\n        return records\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # SUSPICIOUS / UNKNOWN PROCESS SCANNER\n    # Checks: Running processes, Startup (Registry + Folder),\n    #         Hidden folders, Scheduled tasks \u2014 flags unknown ones\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _build_suspicion_scanner(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udd34 Suspicious Process &amp; Entry Scanner\",\n                             \"Unknown processes in RAM, Startup, Registry &amp; Hidden Folders\")\n        body = self._scrollable_section_body(frame)\n\n        self._action_card_grid(body, [\n            (\"\ud83d\udd0d\", \"Full Scan\",           \"Processes, startup, folders, tasks sab scan\",C[\"btn_danger\"], self._susp_full_scan),\n            (\"\u26a1\", \"Scan Running Procs\",  \"RAM mein chal rahe unknown processes\",       C[\"btn_warn\"],   self._susp_scan_procs),\n            (\"\ud83d\ude80\", \"Scan Startup\",        \"Startup entries mein suspicious cheezein\",   C[\"btn_info\"],   self._susp_scan_startup),\n            (\"\ud83d\udcc1\", \"Scan Hidden Folders\", \"Hidden folders dhundho\",                     C[\"btn_hw\"],     self._susp_scan_hidden),\n            (\"\ud83d\udcc5\", \"Scan Unknown Tasks\",  \"Unknown scheduled tasks flag karo\",          C[\"btn_chip\"],   self._susp_scan_tasks),\n            (\"\ud83d\uddd1\",  \"Kill Selected\",      \"Selected process terminate karo\",            C[\"btn_danger\"], self._susp_kill_selected),\n            (\"\ud83d\udd12\", \"Disable Selected\",    \"Selected entry disable karo\",                C[\"btn_warn\"],   self._susp_disable_selected),\n            (\"\ud83d\udce6\", \"Quarantine Selected\", \"Selected file quarantine mein bhejo\",        C[\"btn_info\"],   self._susp_quarantine_selected),\n            (\"\ud83d\udd17\", \"VirusTotal URL\",      \"URL clipboard mein copy karo\",               C[\"btn_chip\"],   self._susp_copy_virustotal_url),\n        ], cols=3)\n\n        # \u2500\u2500 Stats row \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        stats_row = tk.Frame(body, bg=C[\"bg\"])\n        stats_row.pack(fill=\"x\", padx=16, pady=6)\n        self.susp_count_vars = {}\n        for i, (k, lbl, col) in enumerate([\n            (\"proc\",    \"Running Procs\",   C[\"error\"]),\n            (\"startup\", \"Startup Entries\", C[\"warning\"]),\n            (\"hidden\",  \"Hidden Items\",    C[\"hw_accent\"]),\n            (\"tasks\",   \"Unknown Tasks\",   C[\"accent4\"]),\n            (\"total\",   \"TOTAL FLAGS\",     C[\"accent\"]),\n        ]):\n            card = tk.Frame(stats_row, bg=C[\"card\"], padx=12, pady=8)\n            card.grid(row=0, column=i, padx=5, sticky=\"ew\")\n            stats_row.columnconfigure(i, weight=1)\n            tk.Label(card, text=lbl,  font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\")\n            v = tk.StringVar(value=\"--\")\n            self.susp_count_vars[k] = v\n            tk.Label(card, textvariable=v, font=(\"Segoe UI\",16,\"bold\"), fg=col, bg=C[\"card\"]).pack(anchor=\"w\")\n\n        # \u2500\u2500 Full-width flagged entries list \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        list_frame = tk.Frame(body, bg=C[\"card\"])\n        list_frame.pack(fill=\"both\", expand=True, padx=16, pady=(4,0))\n        list_frame.rowconfigure(0, weight=1)\n        list_frame.columnconfigure(0, weight=1)\n\n        tk.Label(list_frame, text=\"  \ud83d\udea8 Flagged Entries  (saari entries ek sath \u2014 click karo detail ke liye)\",\n                 font=FONTS[\"subhead\"], fg=C[\"error\"], bg=C[\"card\"]).grid(\n                 row=0, column=0, columnspan=2, sticky=\"w\", pady=(8,4), padx=8)\n\n        cols = (\"Category\",\"Name\",\"Risk\",\"Location/PID\",\"Action\")\n        self.susp_tree = ttk.Treeview(list_frame, columns=cols, show=\"headings\",\n                                      height=24, style=\"Custom.Treeview\")\n        widths = [110, 220, 80, 380, 100]\n        for col, w in zip(cols, widths):\n            self.susp_tree.heading(col, text=col)\n            self.susp_tree.column(col, width=w, anchor=\"w\")\n        self.susp_tree.tag_configure(\"high\",   foreground=C[\"error\"])\n        self.susp_tree.tag_configure(\"medium\", foreground=C[\"warning\"])\n        self.susp_tree.tag_configure(\"low\",    foreground=C[\"text_dim\"])\n        lsb = ttk.Scrollbar(list_frame, orient=\"vertical\", command=self.susp_tree.yview)\n        hsb2 = ttk.Scrollbar(list_frame, orient=\"horizontal\", command=self.susp_tree.xview)\n        self.susp_tree.configure(yscrollcommand=lsb.set, xscrollcommand=hsb2.set)\n        self.susp_tree.grid(row=1, column=0, sticky=\"nsew\", padx=(8,0), pady=(0,0))\n        lsb.grid(row=1, column=1, sticky=\"ns\", pady=(0,0))\n        hsb2.grid(row=2, column=0, sticky=\"ew\", padx=(8,0), pady=(0,4))\n        list_frame.rowconfigure(1, weight=1)\n        self._bind_tree_responsive_columns(self.susp_tree, [\n            (\"Category\", 110, 1), (\"Name\", 220, 3), (\"Risk\", 80, 0),\n            (\"Location/PID\", 380, 5), (\"Action\", 100, 1)\n        ])\n        self.susp_tree.bind(\"&lt;&gt;\", self._susp_on_select)\n\n        # \u2500\u2500 Bottom: detail strip + legend \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        bot = tk.Frame(body, bg=C[\"panel\"])\n        bot.pack(fill=\"x\", padx=16, pady=(2,4))\n        bot.columnconfigure(0, weight=1)\n        bot.columnconfigure(1, weight=0)\n\n        # Detail box\n        detail_wrap = tk.Frame(bot, bg=C[\"card\"])\n        detail_wrap.grid(row=0, column=0, sticky=\"nsew\", padx=(0,6), pady=4)\n        detail_wrap.rowconfigure(1, weight=1)\n        detail_wrap.columnconfigure(0, weight=1)\n\n        hdr_d = tk.Frame(detail_wrap, bg=C[\"card\"])\n        hdr_d.grid(row=0, column=0, sticky=\"ew\", padx=6, pady=(4,2))\n        tk.Label(hdr_d, text=\"  \ud83d\udd0d Entry Details &amp; Recommendation\",\n                 font=FONTS[\"subhead\"], fg=C[\"warning\"], bg=C[\"card\"]).pack(side=\"left\")\n        tk.Label(hdr_d, text=\"(entry click karo \u2014 yahan detail dikhegi)\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\", padx=6)\n\n        self.susp_detail = scrolledtext.ScrolledText(\n            detail_wrap, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"],\n            height=5, bd=0, relief=\"flat\", state=\"disabled\", wrap=\"word\")\n        self.susp_detail.grid(row=1, column=0, sticky=\"nsew\", padx=6, pady=(0,4))\n\n        # Legend (right side of bottom strip)\n        leg_wrap = tk.Frame(bot, bg=C[\"card\"])\n        leg_wrap.grid(row=0, column=1, sticky=\"nsew\", padx=(0,0), pady=4)\n        tk.Label(leg_wrap, text=\"  Legend\", font=FONTS[\"small\"],\n                 fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=8, pady=(6,2))\n        for color, label in [(C[\"error\"],   \"\ud83d\udd34 High Risk\"),\n                             (C[\"warning\"], \"\ud83d\udfe1 Medium Risk\"),\n                             (C[\"text_dim\"],\"\u26aa Low / Safe\")]:\n            tk.Label(leg_wrap, text=label, font=FONTS[\"small\"],\n                     fg=color, bg=C[\"card\"]).pack(anchor=\"w\", padx=12, pady=2)\n\n        self.susp_status = tk.Label(body, text=\"  Click 'Full Scan' to detect suspicious entries\",\n                                    font=FONTS[\"small\"], fg=C[\"accent2\"], bg=C[\"bg\"], anchor=\"w\")\n        self.susp_status.pack(fill=\"x\", padx=16, pady=(0,4))\n\n        # Internal store: {iid: meta_dict}\n        self._susp_meta = {}\n        return frame\n\n    def _susp_quarantine_dir(self):\n        base = getattr(self, \"backup_dir\", \"\") or os.path.join(os.path.expanduser(\"~\"), \"Desktop\")\n        q = os.path.join(base, \"Godawari_Quarantine\")\n        try:\n            os.makedirs(q, exist_ok=True)\n        except Exception:\n            pass\n        return q\n\n    def _susp_quarantine_selected(self):\n        sel = self.susp_tree.selection()\n        if not sel:\n            messagebox.showinfo(\"No Selection\", \"Select entries first.\")\n            return\n        qdir = self._susp_quarantine_dir()\n        moved = 0\n        for iid in sel:\n            meta = self._susp_meta.get(iid, {})\n            p = meta.get(\"exe\") or meta.get(\"path\") or \"\"\n            if not p or not os.path.exists(p) or os.path.isdir(p):\n                continue\n            dst = os.path.join(qdir, os.path.basename(p))\n            if os.path.exists(dst):\n                root, ext = os.path.splitext(dst)\n                dst = f\"{root}_{int(time.time())}{ext}\"\n            try:\n                shutil.move(p, dst)\n                moved += 1\n                self.susp_tree.delete(iid)\n            except Exception as e:\n                messagebox.showwarning(\"Move failed\", f\"{p}\\n{e}\")\n        self._set_status(f\"Quarantined {moved} file(s)\", C[\"success\"] if moved else C[\"warning\"])\n        messagebox.showinfo(\"Quarantine\", f\"\u2705 Quarantined: {moved}\\nFolder:\\n{qdir}\")\n\n    def _susp_copy_virustotal_url(self):\n        sel = self.susp_tree.selection()\n        if not sel:\n            messagebox.showinfo(\"No Selection\", \"Select a file/process entry first.\")\n            return\n        iid = sel[0]\n        meta = self._susp_meta.get(iid, {})\n        p = meta.get(\"exe\") or meta.get(\"path\") or \"\"\n        if not p or not os.path.exists(p) or os.path.isdir(p):\n            messagebox.showwarning(\"No File\", \"Selected entry ke paas valid file path nahi hai.\")\n            return\n        try:\n            h = self._sha256_file(p)\n            url = f\"https://www.virustotal.com/gui/file/{h}\"\n            self.clipboard_clear()\n            self.clipboard_append(url)\n            self.update()\n            messagebox.showinfo(\"Copied\", f\"\u2705 VirusTotal URL copied:\\n{url}\")\n        except Exception as e:\n            messagebox.showerror(\"Error\", str(e))\n\n    # \u2500\u2500 Scan orchestrators \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _susp_full_scan(self):\n        self.susp_status.config(text=\"  \ud83d\udd0d Full scan running...\", fg=C[\"accent4\"])\n        for i in self.susp_tree.get_children():\n            self.susp_tree.delete(i)\n        self._susp_meta.clear()\n        for k in self.susp_count_vars:\n            self.susp_count_vars[k].set(\"...\")\n        self._launch_job(\"susp_full_scan\", self._do_susp_full_scan)\n\n    def _do_susp_full_scan(self):\n        pc = self._do_susp_scan_procs(batch=True)\n        sc = self._do_susp_scan_startup(batch=True)\n        hc = self._do_susp_scan_hidden(batch=True)\n        tc = self._do_susp_scan_tasks(batch=True)\n        total = pc + sc + hc + tc\n        def update():\n            self.susp_count_vars[\"proc\"].set(str(pc))\n            self.susp_count_vars[\"startup\"].set(str(sc))\n            self.susp_count_vars[\"hidden\"].set(str(hc))\n            self.susp_count_vars[\"tasks\"].set(str(tc))\n            self.susp_count_vars[\"total\"].set(str(total))\n            self.susp_status.config(\n                text=f\"  \u2705 Scan complete \u2014 {total} suspicious entries found\",\n                fg=C[\"success\"] if total == 0 else C[\"error\"])\n        self.after(0, update)\n\n    def _susp_scan_procs(self):\n        self._launch_job(\"susp_scan_procs\", self._do_susp_scan_procs)\n\n    def _susp_scan_startup(self):\n        self._launch_job(\"susp_scan_startup\", self._do_susp_scan_startup)\n\n    def _susp_scan_hidden(self):\n        self._launch_job(\"susp_scan_hidden\", self._do_susp_scan_hidden)\n\n    def _susp_scan_tasks(self):\n        self._launch_job(\"susp_scan_tasks\", self._do_susp_scan_tasks)\n\n    # \u2500\u2500 Known-safe whitelist (lowercase) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    _KNOWN_SAFE = {\n        \"system\",\"system idle process\",\"svchost.exe\",\"lsass.exe\",\"winlogon.exe\",\n        \"csrss.exe\",\"smss.exe\",\"wininit.exe\",\"services.exe\",\"explorer.exe\",\n        \"taskhostw.exe\",\"taskhost.exe\",\"dwm.exe\",\"spoolsv.exe\",\"searchindexer.exe\",\n        \"antimalware service executable\",\"msmpeng.exe\",\"msseces.exe\",\n        \"audiodg.exe\",\"fontdrvhost.exe\",\"sihost.exe\",\"runtimebroker.exe\",\n        \"ctfmon.exe\",\"dllhost.exe\",\"conhost.exe\",\"cmd.exe\",\"powershell.exe\",\n        \"python.exe\",\"pythonw.exe\",\"msiexec.exe\",\"wuauclt.exe\",\"wermgr.exe\",\n        \"backgroundtaskhost.exe\",\"settingsynchost.exe\",\"compattelrunner.exe\",\n        \"dashost.exe\",\"searchhost.exe\",\"securityhealthsystray.exe\",\n        \"shellexperiencehost.exe\",\"startmenuexperiencehost.exe\",\n        \"textinputhost.exe\",\"useroobebroker.exe\",\"applicationframehost.exe\",\n    }\n\n    _SUSPICIOUS_INDICATORS = [\n        \"temp\",\"tmp\",\"appdata\\\\local\\\\temp\",\"appdata\\\\roaming\",\n        \"programdata\",\"users\\\\public\",\"recycle\",\"windows\\\\temp\",\n        \"\\\\downloads\\\\\",\"no description\",\"unknown\",\"(null)\",\n    ]\n\n    _HIGH_RISK_NAMES = {\n        \"cryptominer\",\"miner\",\"torrent\",\"hack\",\"crack\",\"keygen\",\"patch\",\n        \"loader\",\"injector\",\"rat\",\"trojan\",\"worm\",\"virus\",\"malware\",\n        \"spyware\",\"adware\",\"pup\",\"hijack\",\"rootkit\",\n    }\n\n    def _susp_risk(self, name, path):\n        n = name.lower()\n        p = (path or \"\").lower()\n        if any(h in n for h in self._HIGH_RISK_NAMES):\n            return \"High\"\n        if any(ind in p for ind in self._SUSPICIOUS_INDICATORS):\n            return \"Medium\"\n        if n not in self._KNOWN_SAFE and name.endswith(\".exe\"):\n            if any(c.isdigit() for c in name[:6]):\n                return \"Medium\"\n        return \"Low\"\n\n    def _susp_insert(self, category, name, risk, location, action, meta=None):\n        tag = {\"High\":\"high\",\"Medium\":\"medium\"}.get(risk,\"low\")\n        iid = self.susp_tree.insert(\"\",\"end\",\n            values=(category, name, risk, location, action), tags=(tag,))\n        self._susp_meta[iid] = meta or {}\n\n    # \u2500\u2500 Running Process scan \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _do_susp_scan_procs(self, batch=False):\n        rows = []\n        for proc in psutil.process_iter(['pid','name','exe','cmdline','username','cpu_percent','memory_info']):\n            try:\n                pname = (proc.info.get('name') or \"\").strip()\n                exe   = (proc.info.get('exe')  or \"\").strip()\n                pid   = proc.info['pid']\n                if pid in (0, 4) or not pname:\n                    continue\n                risk = self._susp_risk(pname, exe)\n                try:\n                    mem_mb = round((proc.info.get('memory_info') or proc.memory_info()).rss / (1024*1024), 1)\n                    mem_str = f\"{mem_mb} MB\"\n                except:\n                    mem_str = \"--\"\n                rows.append((\"Running Proc\", pname, risk,\n                             f\"PID:{pid}  {exe[:55]}  RAM:{mem_str}\", \"Kill\",\n                             {\"pid\":pid,\"exe\":exe,\"type\":\"proc\",\n                              \"cmdline\":\" \".join(proc.info.get('cmdline') or [])}))\n            except:\n                pass\n\n        # Sort: High risk pehle, phir naam se\n        risk_order = {\"High\": 0, \"Medium\": 1, \"Low\": 2}\n        rows.sort(key=lambda r: (risk_order.get(r[2], 3), r[1].lower()))\n\n        def insert():\n            for r in rows:\n                self._susp_insert(*r)\n            if not batch:\n                flagged = sum(1 for r in rows if r[2] in (\"High\",\"Medium\"))\n                self.susp_count_vars[\"proc\"].set(str(len(rows)))\n                self.susp_status.config(\n                    text=f\"  Processes: {len(rows)} total  |  {flagged} flagged (High/Medium)\",\n                    fg=C[\"warning\"] if flagged else C[\"success\"])\n        self.after(0, insert)\n        return len(rows)\n\n    # \u2500\u2500 Startup scan (Registry + Folder) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _do_susp_scan_startup(self, batch=False):\n        rows = []\n        reg_paths = [\n            (winreg.HKEY_CURRENT_USER,  r\"Software\\Microsoft\\Windows\\CurrentVersion\\Run\",     \"HKCU Run\"),\n            (winreg.HKEY_LOCAL_MACHINE, r\"Software\\Microsoft\\Windows\\CurrentVersion\\Run\",     \"HKLM Run\"),\n            (winreg.HKEY_CURRENT_USER,  r\"Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce\", \"HKCU RunOnce\"),\n            (winreg.HKEY_LOCAL_MACHINE, r\"Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce\", \"HKLM RunOnce\"),\n            (winreg.HKEY_LOCAL_MACHINE, r\"Software\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Run\", \"HKLM Run(32)\"),\n        ]\n        for hive, path, label in reg_paths:\n            try:\n                key = winreg.OpenKey(hive, path, 0, winreg.KEY_READ)\n                i = 0\n                while True:\n                    try:\n                        name, value, _ = winreg.EnumValue(key, i)\n                        risk = self._susp_risk(name, value)\n                        # Flag anything in risky paths or unknown names\n                        if risk != \"Low\" or any(ind in value.lower()\n                                                 for ind in self._SUSPICIOUS_INDICATORS):\n                            rows.append((f\"Startup/{label}\", name, risk,\n                                         value[:80], \"Disable\",\n                                         {\"type\":\"reg_startup\",\"hive\":hive,\n                                          \"path\":path,\"name\":name,\"value\":value}))\n                        i += 1\n                    except OSError:\n                        break\n                winreg.CloseKey(key)\n            except:\n                pass\n\n        # Startup folders\n        for folder, label in [\n            (os.path.join(os.environ.get(\"APPDATA\",\"\"),\n                          r\"Microsoft\\Windows\\Start Menu\\Programs\\Startup\"), \"User Startup Folder\"),\n            (os.path.join(os.environ.get(\"PROGRAMDATA\",\"\"),\n                          r\"Microsoft\\Windows\\Start Menu\\Programs\\StartUp\"),  \"Common Startup Folder\"),\n        ]:\n            if not os.path.exists(folder):\n                continue\n            for f in Path(folder).glob(\"*\"):\n                if f.is_file():\n                    risk = self._susp_risk(f.name, str(f))\n                    rows.append((f\"Startup Folder\", f.name, risk,\n                                 str(f)[:80], \"Open Folder\",\n                                 {\"type\":\"folder_startup\",\"path\":str(f)}))\n\n        def insert():\n            for r in rows:\n                self._susp_insert(*r)\n            if not batch:\n                self.susp_count_vars[\"startup\"].set(str(len(rows)))\n                self.susp_status.config(\n                    text=f\"  Startup scan: {len(rows)} flagged\", fg=C[\"warning\"] if rows else C[\"success\"])\n        self.after(0, insert)\n        return len(rows)\n\n    # \u2500\u2500 Hidden folder scan \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _do_susp_scan_hidden(self, batch=False):\n        rows = []\n        scan_roots = [\n            os.environ.get(\"APPDATA\",\"\"),\n            os.environ.get(\"LOCALAPPDATA\",\"\"),\n            os.environ.get(\"PROGRAMDATA\",\"\"),\n            os.path.join(os.environ.get(\"SYSTEMROOT\",\"C:\\\\Windows\"), \"Temp\"),\n            os.path.join(os.environ.get(\"SYSTEMROOT\",\"C:\\\\Windows\"), \"System32\\\\Tasks\"),\n        ]\n        exe_exts = {\".exe\",\".bat\",\".cmd\",\".vbs\",\".ps1\",\".js\",\".scr\",\".pif\",\".com\"}\n        count = 0\n        for root_path in scan_roots:\n            if not os.path.exists(root_path):\n                continue\n            try:\n                for entry in os.scandir(root_path):\n                    try:\n                        # Hidden attribute check (Windows: FILE_ATTRIBUTE_HIDDEN = 2)\n                        attrs = entry.stat().st_file_attributes if hasattr(entry.stat(), 'st_file_attributes') else 0\n                        is_hidden = bool(attrs &amp; 2)\n                        ext = os.path.splitext(entry.name)[1].lower()\n                        is_exec = ext in exe_exts\n                        if is_hidden and is_exec:\n                            risk = \"High\"\n                        elif is_hidden and entry.is_dir():\n                            risk = \"Medium\"\n                        elif is_exec and any(\n                                ind in entry.path.lower()\n                                for ind in [\"temp\",\"tmp\",\"appdata\",\"programdata\"]):\n                            risk = \"Medium\"\n                        else:\n                            continue\n                        rows.append((\"Hidden/Temp Exec\",\n                                     entry.name, risk,\n                                     entry.path[:80], \"Open Folder\",\n                                     {\"type\":\"hidden_file\",\"path\":entry.path}))\n                        count += 1\n                        if count &gt;= 50:\n                            break\n                    except:\n                        pass\n            except:\n                pass\n            if count &gt;= 50:\n                break\n\n        def insert():\n            for r in rows:\n                self._susp_insert(*r)\n            if not batch:\n                self.susp_count_vars[\"hidden\"].set(str(len(rows)))\n                self.susp_status.config(\n                    text=f\"  Hidden scan: {len(rows)} flagged\", fg=C[\"warning\"] if rows else C[\"success\"])\n        self.after(0, insert)\n        return len(rows)\n\n    # \u2500\u2500 Unknown Scheduled Task scan \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _do_susp_scan_tasks(self, batch=False):\n        rows = []\n        out, _ = self._run_cmd('schtasks /query /fo CSV /v', timeout=20)\n        ms_paths = {\"\\\\microsoft\\\\\", \"\\\\windows\\\\\"}\n        seen = set()\n        for record in self._task_records_from_schtasks(out):\n            task_path = (record.get(\"TaskName\") or \"\").strip()\n            status = (record.get(\"Status\") or record.get(\"Scheduled Task State\") or \"\").strip()\n            run_as = (record.get(\"Run As User\") or \"\").strip()\n            task_to_run = (record.get(\"Task To Run\") or \"\").strip()\n            if not task_path or task_path in seen:\n                continue\n            seen.add(task_path)\n            path_low = task_path.lower()\n            process_text = task_to_run or task_path\n            if any(ms in path_low for ms in ms_paths):\n                continue\n            if status.lower() == \"disabled\":\n                continue\n            risk = \"High\" if any(x in (path_low + \" \" + process_text.lower()) for x in [\"temp\",\"tmp\",\"appdata\",\"programdata\",\"public\"]) else \"Medium\"\n            rows.append((\"Unknown Task\", task_path, risk,\n                         f\"Status:{status}  RunAs:{run_as[:30]}  Process:{process_text[:60]}\", \"Disable\",\n                         {\"type\":\"task\",\"path\":task_path}))\n\n        def insert():\n            for r in rows:\n                self._susp_insert(*r)\n            if not batch:\n                self.susp_count_vars[\"tasks\"].set(str(len(rows)))\n                self.susp_status.config(\n                    text=f\"  Task scan: {len(rows)} flagged\", fg=C[\"warning\"] if rows else C[\"success\"])\n        self.after(0, insert)\n        return len(rows)\n\n    # \u2500\u2500 Selection handler \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _susp_on_select(self, event=None):\n        sel = self.susp_tree.selection()\n        if not sel:\n            return\n        iid = sel[0]\n        vals = self.susp_tree.item(iid, \"values\")\n        meta = self._susp_meta.get(iid, {})\n        cat, name, risk, location, action = vals\n        lines = [\n            f\"Category  : {cat}\",\n            f\"Name      : {name}\",\n            f\"Risk      : {risk}\",\n            f\"Location  : {location}\",\n            f\"Action    : {action}\",\n            \"\",\n        ]\n        if meta.get(\"exe\"):\n            lines.append(f\"EXE Path  : {meta['exe']}\")\n        if meta.get(\"cmdline\"):\n            lines.append(f\"CMD Line  : {meta['cmdline'][:200]}\")\n        if meta.get(\"value\"):\n            lines.append(f\"Reg Value : {meta['value']}\")\n        lines += [\"\", \"\u2500\"*50, \"\"]\n        t = meta.get(\"type\",\"\")\n        if risk == \"High\":\n            lines.append(\"\u26a0 RECOMMENDATION: High-risk entry detected!\")\n            lines.append(\"  \u2192 Terminate/disable immediately if you don't recognize it.\")\n            lines.append(\"  \u2192 Upload the EXE to virustotal.com for verification.\")\n        elif risk == \"Medium\":\n            lines.append(\"\u26a0 RECOMMENDATION: Unknown entry \u2014 verify before disabling.\")\n            lines.append(\"  \u2192 Search the process name online.\")\n            lines.append(\"  \u2192 If not recognized, use 'Disable Selected'.\")\n        else:\n            lines.append(\"\u2139 LOW RISK \u2014 Unusual location but may be legitimate.\")\n            lines.append(\"  \u2192 Monitor if CPU/RAM usage is high.\")\n        if t == \"proc\":\n            lines.append(f\"\\nKill command: taskkill /PID {meta.get('pid','')} /F\")\n        elif t in (\"reg_startup\",\"folder_startup\"):\n            lines.append(\"\\nTo remove: use 'Disable Selected' button above.\")\n        elif t == \"task\":\n            lines.append(f\"\\nDisable: schtasks /Change /TN \\\"{meta.get('path','')}\\\" /Disable\")\n\n        self.susp_detail.config(state=\"normal\")\n        self.susp_detail.delete(\"1.0\",\"end\")\n        self.susp_detail.insert(\"end\", \"\\n\".join(lines))\n        self.susp_detail.config(state=\"disabled\")\n\n    # \u2500\u2500 Action buttons \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _susp_kill_selected(self):\n        sel = self.susp_tree.selection()\n        if not sel:\n            messagebox.showinfo(\"No Selection\",\"Select a running process entry to kill.\")\n            return\n        killed = 0\n        for iid in sel:\n            meta = self._susp_meta.get(iid, {})\n            if meta.get(\"type\") == \"proc\":\n                pid = meta.get(\"pid\")\n                if pid and messagebox.askyesno(\"Kill Process\",\n                        f\"Kill PID {pid} ({self.susp_tree.item(iid,'values')[1]})?\"):\n                    out, rc = self._run_cmd(f'taskkill /PID {pid} /F')\n                    if rc == 0:\n                        self.susp_tree.delete(iid)\n                        killed += 1\n                    else:\n                        messagebox.showerror(\"Failed\", f\"Could not kill PID {pid}:\\n{out}\")\n        if killed:\n            self._set_status(f\"Killed {killed} process(es)\", C[\"success\"])\n\n    def _susp_disable_selected(self):\n        sel = self.susp_tree.selection()\n        if not sel:\n            messagebox.showinfo(\"No Selection\",\"Select an entry to disable.\")\n            return\n        disabled = 0\n        for iid in sel:\n            meta = self._susp_meta.get(iid, {})\n            t = meta.get(\"type\",\"\")\n            name_disp = self.susp_tree.item(iid,\"values\")[1]\n            if not messagebox.askyesno(\"Disable Entry\", f\"Disable '{name_disp}'?\"):\n                continue\n            try:\n                if t == \"reg_startup\":\n                    hive = meta[\"hive\"]\n                    path = meta[\"path\"]\n                    name = meta[\"name\"]\n                    value = meta[\"value\"]\n                    key = winreg.OpenKey(hive, path, 0,\n                                        winreg.KEY_SET_VALUE | winreg.KEY_READ)\n                    # Rename with disabled prefix\n                    winreg.SetValueEx(key, \"__GodawariDisabled__\"+name, 0,\n                                      winreg.REG_SZ, value)\n                    winreg.DeleteValue(key, name)\n                    winreg.CloseKey(key)\n                    disabled += 1\n                    self.susp_tree.delete(iid)\n                elif t == \"folder_startup\":\n                    src = Path(meta[\"path\"])\n                    dst = src.with_name(src.name + \".disabled\")\n                    if src.exists():\n                        src.rename(dst)\n                    disabled += 1\n                    self.susp_tree.delete(iid)\n                elif t == \"task\":\n                    task_path = meta.get(\"path\",\"\")\n                    self._run_cmd(f'schtasks /Change /TN \"{task_path}\" /Disable')\n                    disabled += 1\n                    self.susp_tree.delete(iid)\n                elif t == \"hidden_file\":\n                    path = meta.get(\"path\",\"\")\n                    if messagebox.askyesno(\"Delete File\",\n                            f\"Delete this suspicious file?\\n{path}\"):\n                        try:\n                            os.remove(path)\n                        except Exception as e:\n                            messagebox.showerror(\"Error\", str(e))\n                    disabled += 1\n                    self.susp_tree.delete(iid)\n            except Exception as e:\n                messagebox.showerror(\"Error\", f\"Could not disable {name_disp}:\\n{e}\")\n        if disabled:\n            self._set_status(f\"Disabled {disabled} suspicious entry(ies)\", C[\"success\"])\n\n    def _create_restore_point(self, description=\"Godawari Optimizer\"):\n        if self._restore_prompt_count &gt; 0:\n            return True\n        mgr = getattr(self, \"restore_point_manager\", None)\n        if mgr is None:\n            return True\n\n        if not is_admin():\n            if messagebox.askyesno(\"Administrator Required\", \"Restore point creation needs administrator rights. Relaunch as admin?\"):\n                run_as_admin()\n            return False\n\n        def _ask(desc):\n            return messagebox.askyesno(\"Restore Point\", f\"Create restore point?\\n{desc}\")\n\n        self._restore_prompt_count += 1\n        self._set_status(\"Creating restore point...\", C[\"warning\"])\n        ok = mgr.create(description, ask_callback=_ask, force=False)\n        if ok:\n            self._audit_event(\"restore_point_created\", {\"description\": description})\n            return True\n        return messagebox.askyesno(\"Failed\", \"Restore point failed. Continue anyway?\")\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # HDD / SSD REPAIR SECTION \u2014 Real Actions with Before/After Proof\n    # Features: SMART, Bad Sector Repair, MBR/BCD Fix, NTFS Fix,\n    #           Partition Repair, VSS Repair, Defrag/TRIM, Offline Mode\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _build_hdd_repair(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n\n        # \u2500\u2500 Section Header \u2500\u2500\n        hdr = tk.Frame(frame, bg=C[\"panel\"], pady=10)\n        hdr.pack(fill=\"x\")\n        tk.Label(hdr, text=\"\ud83d\udcbe  HDD / SSD REPAIR CENTER\",\n                 font=(\"Segoe UI\", 15, \"bold\"), fg=C[\"accent\"], bg=C[\"panel\"]).pack(side=\"left\", padx=18)\n        tk.Label(hdr, text=\"Real Repair \u2022 Bad Sector Fix \u2022 MBR/BCD \u2022 NTFS \u2022 Partition \u2022 WinPE Mode\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"left\", padx=6)\n        tk.Frame(hdr, bg=C[\"accent\"], height=2).pack(side=\"bottom\", fill=\"x\")\n\n        # \u2500\u2500 Scrollable content \u2500\u2500\n        outer = tk.Frame(frame, bg=C[\"bg\"])\n        outer.pack(fill=\"both\", expand=True)\n        canvas2 = tk.Canvas(outer, bg=C[\"bg\"], highlightthickness=0)\n        vsb = tk.Scrollbar(outer, orient=\"vertical\", command=canvas2.yview)\n        self.hdd_scroll_frame = tk.Frame(canvas2, bg=C[\"bg\"])\n        self.hdd_scroll_frame.bind(\"\",\n            lambda e: canvas2.configure(scrollregion=canvas2.bbox(\"all\")))\n        hdd_window = canvas2.create_window((0, 0), window=self.hdd_scroll_frame, anchor=\"nw\")\n        canvas2.configure(yscrollcommand=vsb.set)\n        vsb.pack(side=\"right\", fill=\"y\")\n        canvas2.pack(side=\"left\", fill=\"both\", expand=True)\n\n        def _hdd_resize(e):\n            try:\n                canvas2.itemconfig(hdd_window, width=e.width)\n                canvas2.configure(scrollregion=canvas2.bbox(\"all\"))\n            except Exception:\n                pass\n        canvas2.bind(\"\", _hdd_resize)\n\n        def _hdd_scroll(e):\n            canvas2.yview_scroll(int(-1*(e.delta/120)), \"units\")\n        self._bind_scoped_mousewheel(self.hdd_scroll_frame, canvas2)\n        sf = self.hdd_scroll_frame  # shorthand\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # ROW 1 \u2014 Drive Selector + SMART Info\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        row1 = tk.Frame(sf, bg=C[\"bg\"])\n        row1.pack(fill=\"x\", padx=14, pady=(12, 4))\n\n        # Drive Selector Card\n        drv_card = tk.LabelFrame(row1, text=\" \ud83d\uddb4  Drive Selector \",\n                                 font=FONTS[\"subhead\"], fg=C[\"accent\"],\n                                 bg=C[\"card\"], bd=1, relief=\"flat\")\n        drv_card.pack(side=\"left\", fill=\"y\", padx=(0, 8))\n\n        tk.Label(drv_card, text=\"Target Drive:\", font=FONTS[\"body\"],\n                 fg=C[\"text_dim\"], bg=C[\"card\"]).grid(row=0, column=0, padx=10, pady=6, sticky=\"w\")\n        self.hdd_drive_var = tk.StringVar(value=\"C:\")\n        drives = self._get_available_drives()\n        drv_cb = ttk.Combobox(drv_card, textvariable=self.hdd_drive_var,\n                               values=drives, width=8, state=\"readonly\")\n        drv_cb.grid(row=0, column=1, padx=8, pady=6)\n\n        tk.Label(drv_card, text=\"Mode:\", font=FONTS[\"body\"],\n                 fg=C[\"text_dim\"], bg=C[\"card\"]).grid(row=1, column=0, padx=10, pady=4, sticky=\"w\")\n        self.hdd_mode_var = tk.StringVar(value=\"Online (Live Windows)\")\n        mode_cb = ttk.Combobox(drv_card, textvariable=self.hdd_mode_var,\n                                values=[\"Online (Live Windows)\", \"Offline / WinPE Mode\"],\n                                width=22, state=\"readonly\")\n        mode_cb.grid(row=1, column=1, padx=8, pady=4)\n\n        tk.Button(drv_card, text=\"\ud83d\udd04  Refresh Drives\", font=FONTS[\"small\"],\n                  bg=C[\"btn\"], fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=self._hdd_refresh_drives(drv_cb)).grid(row=2, column=0, columnspan=2,\n                                                                   padx=10, pady=8, sticky=\"ew\")\n\n        # SMART Status Card\n        smart_card = tk.LabelFrame(row1, text=\" \ud83d\udcca  S.M.A.R.T. Drive Health \",\n                                    font=FONTS[\"subhead\"], fg=C[\"accent\"],\n                                    bg=C[\"card\"], bd=1, relief=\"flat\")\n        smart_card.pack(side=\"left\", fill=\"both\", expand=True)\n\n        self.smart_log = scrolledtext.ScrolledText(smart_card, font=FONTS[\"mono\"],\n                                                    bg=\"#050D1A\", fg=C[\"success\"],\n                                                    height=7, state=\"disabled\",\n                                                    insertbackground=C[\"accent\"])\n        self.smart_log.pack(fill=\"both\", expand=True, padx=8, pady=6)\n\n        btn_smart_row = tk.Frame(smart_card, bg=C[\"card\"])\n        btn_smart_row.pack(fill=\"x\", padx=8, pady=(0, 8))\n        tk.Button(btn_smart_row, text=\"\ud83d\udcca Full SMART Report\",\n                  font=FONTS[\"small\"], bg=C[\"btn_info\"], fg=C[\"text\"],\n                  bd=0, padx=10, pady=5, cursor=\"hand2\",\n                  command=self._hdd_smart_report).pack(side=\"left\", padx=4)\n        tk.Button(btn_smart_row, text=\"\u26a1 Quick SMART Check\",\n                  font=FONTS[\"small\"], bg=C[\"btn\"], fg=C[\"text\"],\n                  bd=0, padx=10, pady=5, cursor=\"hand2\",\n                  command=self._hdd_smart_quick).pack(side=\"left\", padx=4)\n        tk.Button(btn_smart_row, text=\"\ud83d\udcbe Save Report\",\n                  font=FONTS[\"small\"], bg=C[\"accent2\"], fg=\"#000\",\n                  bd=0, padx=10, pady=5, cursor=\"hand2\",\n                  command=lambda: self._hdd_save_log(self.smart_log, \"SMART_Report\")).pack(side=\"left\", padx=4)\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # ROW 2 \u2014 Action Buttons Grid\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        row2_lbl = tk.Frame(sf, bg=C[\"bg\"])\n        row2_lbl.pack(fill=\"x\", padx=14, pady=(10, 2))\n        tk.Label(row2_lbl, text=\"\ud83d\udd27  REPAIR ACTIONS  \u2014  Har button real command chalata hai. Proof log mein dikh'ta hai.\",\n                 font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"bg\"]).pack(side=\"left\")\n\n        row2 = tk.Frame(sf, bg=C[\"bg\"])\n        row2.pack(fill=\"x\", padx=14, pady=2)\n\n        def repair_btn(parent, emoji, title, subtitle, color, cmd_func, col, row_n):\n            card = tk.Frame(parent, bg=C[\"card\"], bd=1, relief=\"flat\",\n                            highlightbackground=color, highlightthickness=1)\n            card.grid(row=row_n, column=col, padx=5, pady=5, sticky=\"nsew\")\n            parent.columnconfigure(col, weight=1)\n            tk.Label(card, text=emoji, font=(\"Segoe UI\", 20),\n                     fg=color, bg=C[\"card\"]).pack(pady=(8, 2))\n            tk.Label(card, text=title, font=FONTS[\"subhead\"],\n                     fg=C[\"text\"], bg=C[\"card\"]).pack()\n            tk.Label(card, text=subtitle, font=FONTS[\"small\"],\n                     fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=170).pack(padx=6)\n            tk.Button(card, text=\"\u25b6  Run\", font=FONTS[\"small\"],\n                      bg=color, fg=\"#000\" if color in [C[\"accent\"], C[\"accent2\"]] else C[\"text\"],\n                      bd=0, padx=12, pady=5, cursor=\"hand2\",\n                      command=cmd_func).pack(pady=(6, 10))\n\n        repair_btn(row2, \"\ud83e\ude7a\", \"Bad Sector Scan+Fix\",\n                   \"chkdsk /f /r /x\\nBad sectors mark+recover\", C[\"warning\"],\n                   self._hdd_bad_sector_fix, 0, 0)\n        repair_btn(row2, \"\ud83d\udd11\", \"MBR / Boot Repair\",\n                   \"bootrec /fixmbr\\nbootrec /fixboot\\nbootrec /rebuildbcd\", C[\"accent3\"],\n                   self._hdd_mbr_repair, 1, 0)\n        repair_btn(row2, \"\ud83d\udcc1\", \"NTFS File System Fix\",\n                   \"fsutil dirty bit\\nNTFS journal reset\\nchkdsk /f\", C[\"accent\"],\n                   self._hdd_ntfs_fix, 2, 0)\n        repair_btn(row2, \"\ud83d\udcc2\", \"Partition Table Repair\",\n                   \"diskpart automount\\nPartition visibility\\nDrive letter assign\", C[\"btn_info\"],\n                   self._hdd_partition_repair, 3, 0)\n\n        row2b = tk.Frame(sf, bg=C[\"bg\"])\n        row2b.pack(fill=\"x\", padx=14, pady=2)\n        repair_btn(row2b, \"\ud83d\udd04\", \"VSS / Shadow Copy Fix\",\n                   \"VSS service repair\\nShadow storage reset\", C[\"accent2\"],\n                   self._hdd_vss_repair, 0, 0)\n        repair_btn(row2b, \"\u26a1\", \"SSD TRIM + Optimize\",\n                   \"Optimize-Volume -ReTrim\\nSSD best practice\", C[\"hw_accent\"],\n                   self._hdd_ssd_trim, 1, 0)\n        repair_btn(row2b, \"\ud83d\uddc2\", \"HDD Defrag\",\n                   \"defrag /U /V /X\\nFull defrag + report\", C[\"accent4\"],\n                   self._hdd_defrag, 2, 0)\n        repair_btn(row2b, \"\ud83e\udd16\", \"Auto Optimize (TRIM/Defrag)\",\n                   \"Detect SSD/HDD\\nRun best optimize\", C[\"btn_chip\"],\n                   self._hdd_auto_optimize, 3, 0)\n        repair_btn(row2b, \"\ud83e\uddf9\", \"Disk Cleanup (Deep)\",\n                   \"cleanmgr /sagerun:1\\nSystem files bhi clean\", C[\"btn\"],\n                   self._hdd_deep_cleanup, 3, 0)\n\n        row2c = tk.Frame(sf, bg=C[\"bg\"])\n        row2c.pack(fill=\"x\", padx=14, pady=2)\n        repair_btn(row2c, \"\ud83c\udfe5\", \"SFC + DISM Full Repair\",\n                   \"SFC /scannow output\\nDISM RestoreHealth live\", C[\"accent3\"],\n                   self._hdd_sfc_dism_full, 0, 0)\n        repair_btn(row2c, \"\ud83d\udccb\", \"Error Event Log\",\n                   \"Last 20 Disk errors\\nEvent Viewer data\", C[\"accent\"],\n                   self._hdd_error_log, 1, 0)\n        repair_btn(row2c, \"\ud83d\udca5\", \"BSoD / Crash Dump Info\",\n                   \"Last crash details\\nMinidump analysis\", C[\"accent3\"],\n                   self._hdd_bsod_info, 2, 0)\n        repair_btn(row2c, \"\ud83d\ude80\", \"One-Click Full Repair\",\n                   \"SMART+SFC+CHKDSK\\n+MBR+VSS \u2014 All in one\", C[\"warning\"],\n                   self._hdd_full_repair, 3, 0)\n\n        svc_card = tk.LabelFrame(sf, text=\" \ud83d\udee1\ufe0f  Win32 Telemetry Service Control Panel \",\n                                 font=FONTS[\"subhead\"], fg=C[\"accent4\"],\n                                 bg=C[\"card\"], bd=1, relief=\"flat\")\n        svc_card.pack(fill=\"x\", padx=14, pady=(10, 4))\n        tk.Label(svc_card,\n                 text=\"Only safe, non-essential telemetry services are shown here. Critical OS services are excluded.\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\").pack(anchor=\"w\", padx=10, pady=(10, 2))\n        svc_row = tk.Frame(svc_card, bg=C[\"card\"])\n        svc_row.pack(fill=\"x\", padx=10, pady=(0, 6))\n        self.hdd_service_status_lbl = tk.Label(svc_row, text=\"Telemetry panel ready\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"])\n        self.hdd_service_status_lbl.pack(side=\"left\", anchor=\"w\")\n        tk.Button(svc_row, text=\"\ud83d\udd0d Scan Safe Services\", font=FONTS[\"small\"], bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=10, pady=4, cursor=\"hand2\",\n                  command=self._hdd_refresh_service_list).pack(side=\"right\", padx=4)\n        list_frame = tk.Frame(svc_card, bg=C[\"card\"])\n        list_frame.pack(fill=\"x\", padx=10, pady=(0, 6))\n        self.hdd_service_listbox = tk.Listbox(list_frame, height=4, selectmode=\"extended\",\n                                              bg=C[\"bg\"], fg=C[\"text\"], font=FONTS[\"small\"], relief=\"flat\", bd=0)\n        self.hdd_service_listbox.pack(side=\"left\", fill=\"both\", expand=True)\n        scrollbar = tk.Scrollbar(list_frame, orient=\"vertical\", command=self.hdd_service_listbox.yview)\n        scrollbar.pack(side=\"right\", fill=\"y\")\n        self.hdd_service_listbox.config(yscrollcommand=scrollbar.set)\n        action_row = tk.Frame(svc_card, bg=C[\"card\"])\n        action_row.pack(fill=\"x\", padx=10, pady=(0, 10))\n        tk.Button(action_row, text=\"\u26d4 Stop Selected\", font=FONTS[\"small\"], bg=C[\"btn_warn\"], fg=C[\"text\"], bd=0, padx=10, pady=4, cursor=\"hand2\",\n                  command=self._hdd_stop_selected_telemetry_services).pack(side=\"left\", padx=4)\n        tk.Button(action_row, text=\"\u267b\ufe0f Refresh Status\", font=FONTS[\"small\"], bg=C[\"btn\"], fg=C[\"text\"], bd=0, padx=10, pady=4, cursor=\"hand2\",\n                  command=self._hdd_refresh_service_list).pack(side=\"left\", padx=4)\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # ROW 3 \u2014 WinPE / Offline Mode\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        winpe_card = tk.LabelFrame(sf, text=\" \ud83d\udda5\ufe0f  WinPE / Offline Mode \u2014 Boot-Level Repair Commands \",\n                                    font=FONTS[\"subhead\"], fg=C[\"accent4\"],\n                                    bg=C[\"card\"], bd=1, relief=\"flat\")\n        winpe_card.pack(fill=\"x\", padx=14, pady=(10, 4))\n\n        winpe_info = tk.Frame(winpe_card, bg=C[\"card\"])\n        winpe_info.pack(fill=\"x\", padx=10, pady=(6, 4))\n        info_text = (\"WinPE / Offline Mode mein yeh tool Windows Recovery Environment (RE) ke saath kaam karta hai.\\n\"\n                     \"Jab Windows boot nahi hota \u2014 tab bhi yeh commands kaam karte hain.\\n\"\n                     \"How to use: PC restart karo \u2192 F8/Shift+F8 dabao \u2192 Troubleshoot \u2192 Command Prompt \u2192 script chalao\")\n        tk.Label(winpe_info, text=info_text, font=FONTS[\"small\"], fg=C[\"accent4\"],\n                 bg=C[\"card\"], justify=\"left\").pack(anchor=\"w\")\n\n        winpe_btns = tk.Frame(winpe_card, bg=C[\"card\"])\n        winpe_btns.pack(fill=\"x\", padx=10, pady=(2, 10))\n\n        def wbtn(txt, cmd, col):\n            tk.Button(winpe_btns, text=txt, font=FONTS[\"small\"],\n                      bg=C[\"btn_warn\"], fg=C[\"text\"], bd=0, padx=10, pady=6,\n                      cursor=\"hand2\", command=cmd).grid(row=0, column=col, padx=4, pady=2, sticky=\"ew\")\n            winpe_btns.columnconfigure(col, weight=1)\n\n        wbtn(\"\ud83d\udd11 Generate MBR Fix .bat\", self._winpe_gen_mbr_bat, 0)\n        wbtn(\"\ud83e\ude7a Generate ChkDsk .bat\", self._winpe_gen_chkdsk_bat, 1)\n        wbtn(\"\ud83d\udccb Generate Full Repair .bat\", self._winpe_gen_full_bat, 2)\n        wbtn(\"\ud83d\udcbf Open Windows RE\", self._winpe_open_recovery, 3)\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # ROW 4 \u2014 Action Log\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        log_card = tk.LabelFrame(sf, text=\" \ud83d\udccb  Repair Action Log \u2014 Proof of Every Action \",\n                                  font=FONTS[\"subhead\"], fg=C[\"accent2\"],\n                                  bg=C[\"card\"], bd=1, relief=\"flat\")\n        log_card.pack(fill=\"x\", padx=14, pady=(6, 14))\n\n        log_btns = tk.Frame(log_card, bg=C[\"card\"])\n        log_btns.pack(fill=\"x\", padx=8, pady=(6, 2))\n        tk.Button(log_btns, text=\"\ud83d\uddd1 Clear Log\", font=FONTS[\"small\"],\n                  bg=C[\"btn_danger\"], fg=C[\"text\"], bd=0, padx=8, pady=4,\n                  cursor=\"hand2\",\n                  command=lambda: self._hdd_clear_log()).pack(side=\"left\", padx=4)\n        tk.Button(log_btns, text=\"\ud83d\udcbe Save Log to Desktop\", font=FONTS[\"small\"],\n                  bg=C[\"accent2\"], fg=\"#000\", bd=0, padx=8, pady=4,\n                  cursor=\"hand2\",\n                  command=lambda: self._hdd_save_log(self.hdd_log, \"HDD_Repair_Log\")).pack(side=\"left\", padx=4)\n\n        self.hdd_log = scrolledtext.ScrolledText(log_card, font=FONTS[\"mono\"],\n                                                  bg=\"#030810\", fg=C[\"text\"],\n                                                  height=12, state=\"disabled\",\n                                                  insertbackground=C[\"accent\"])\n        self.hdd_log.pack(fill=\"both\", expand=True, padx=8, pady=(2, 10))\n        self._hdd_log(\"\ud83d\udcbe HDD/SSD Repair Center Ready. Drive select karo aur action lo.\", C[\"accent\"])\n        self._hdd_log(f\"\ud83d\udda5  Mode: {self.hdd_mode_var.get()} | Drive: {self.hdd_drive_var.get()}\", C[\"text_dim\"])\n\n        return frame\n\n    # \u2500\u2500 Drive helpers \u2500\u2500\n    def _get_available_drives(self):\n        drives = []\n        for letter in \"CDEFGHIJKLMNOPQRSTUVWXYZ\":\n            path = f\"{letter}:\\\\\"\n            if os.path.exists(path):\n                drives.append(f\"{letter}:\")\n        return drives if drives else [\"C:\"]\n\n    def _hdd_refresh_drives(self, cb):\n        def _do():\n            drives = self._get_available_drives()\n            cb[\"values\"] = drives\n            self._hdd_log(f\"\ud83d\udd04 Drives refreshed: {', '.join(drives)}\", C[\"accent2\"])\n        return _do\n\n    def _hdd_log(self, msg, color=None):\n        ts = datetime.datetime.now().strftime(\"%H:%M:%S\")\n        full = f\"[{ts}]  {msg}\"\n        self._append_log(self.hdd_log, full, color or C[\"text\"])\n\n    def _hdd_clear_log(self):\n        try:\n            self.hdd_log.config(state=\"normal\")\n            self.hdd_log.delete(\"1.0\", \"end\")\n            self.hdd_log.config(state=\"disabled\")\n        except:\n            pass\n\n    def _hdd_save_log(self, widget, prefix):\n        try:\n            content = widget.get(\"1.0\", \"end\")\n            desktop = os.path.join(os.path.expanduser(\"~\"), \"Desktop\")\n            ts = datetime.datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n            fpath = os.path.join(desktop, f\"{prefix}_{ts}.txt\")\n            with open(fpath, \"w\", encoding=\"utf-8\") as f:\n                f.write(content)\n            messagebox.showinfo(\"Saved\", f\"Log saved to:\\n{fpath}\")\n            self._hdd_log(f\"\ud83d\udcbe Log saved: {fpath}\", C[\"accent2\"])\n        except Exception as e:\n            messagebox.showerror(\"Error\", str(e))\n\n    def _hdd_safe_telemetry_services(self):\n        return {\n            \"diagtrack\": \"Connected User Experiences and Telemetry\",\n            \"wersvc\": \"Windows Error Reporting Service\",\n            \"wmpnetworksvc\": \"WMP Network Sharing Service\",\n            \"dmwappushservice\": \"Device Management WAP Push Service\",\n            \"wsearch\": \"Windows Search\",\n        }\n\n    def _hdd_refresh_service_list(self):\n        try:\n            self.hdd_service_listbox.delete(0, \"end\")\n            safe_services = self._hdd_safe_telemetry_services()\n            found = []\n            for svc in psutil.win_service_iter():\n                try:\n                    info = svc.as_dict(attrs=[\"name\", \"display_name\", \"status\"])\n                except Exception:\n                    continue\n                name = str(info.get(\"name\", \"\") or \"\").lower()\n                if name not in safe_services:\n                    continue\n                display = safe_services.get(name, info.get(\"display_name\", \"Unknown\"))\n                status = str(info.get(\"status\", \"unknown\")).capitalize()\n                entry = f\"{name} | {display} | {status}\"\n                self.hdd_service_listbox.insert(\"end\", entry)\n                found.append(entry)\n            self.hdd_service_status_lbl.config(text=f\"{len(found)} safe telemetry services listed.\")\n            if not found:\n                self.hdd_service_status_lbl.config(text=\"No safe telemetry services found on this system.\")\n        except Exception as e:\n            self.hdd_service_status_lbl.config(text=f\"Service scan failed: {str(e)[:80]}\")\n\n    def _hdd_stop_selected_telemetry_services(self):\n        selected = [self.hdd_service_listbox.get(i) for i in self.hdd_service_listbox.curselection()]\n        if not selected:\n            messagebox.showinfo(\"Select Service\", \"Pehele ek ya zyada service select karo.\")\n            return\n        if not messagebox.askyesno(\"Stop Services\", \"Selected telemetry services ko stop karna safe hai. Continue karo?\"):\n            return\n        stopped = 0\n        errors = []\n        for row in selected:\n            name = row.split(\"|\")[0].strip()\n            try:\n                svc = psutil.win_service_get(name)\n                status = svc.status()\n                if status.lower() == \"running\":\n                    svc.stop()\n                    stopped += 1\n                    self._hdd_service_status_lbl.config(text=f\"Stopping {name}...\")\n                else:\n                    errors.append(f\"{name} already {status}\")\n            except Exception as e:\n                errors.append(f\"{name}: {e}\")\n        if stopped:\n            self._hdd_service_status_lbl.config(text=f\"{stopped} telemetry service(s) stop requested.\")\n        if errors:\n            self._hdd_service_status_lbl.config(text=f\"Errors: {len(errors)} (see log)\")\n        self._hdd_recovery_emit_metrics({\n            \"service_control\": f\"Stopped {stopped} services | Errors: {len(errors)}\",\n            \"status_text\": \"Telemetry service control action complete.\",\n            \"progress_pct\": None,\n        })\n\n    def _hdd_action_submit(self, name, target, *args, **kwargs):\n        if not hasattr(self, \"_hdd_action_lock\"):\n            self._hdd_action_lock = threading.Lock()\n            self._hdd_action_running = False\n        with self._hdd_action_lock:\n            if getattr(self, \"_hdd_action_running\", False):\n                self._hdd_log(\"\u26a0\ufe0f HDD/Recovery action already running \u2014 duplicate request skipped.\", C[\"warning\"])\n                return False\n            self._hdd_action_running = True\n\n        def _wrapped(*args, **kwargs):\n            try:\n                return target(*args, **kwargs)\n            finally:\n                with self._hdd_action_lock:\n                    self._hdd_action_running = False\n                try:\n                    gc.collect()\n                except Exception:\n                    pass\n\n        manager = getattr(self, \"worker_manager\", None)\n        if manager is not None and hasattr(manager, \"submit\"):\n            try:\n                manager.submit(name, _wrapped, *args, **kwargs)\n                return True\n            except Exception:\n                pass\n        try:\n            threading.Thread(target=_wrapped, args=args, kwargs=kwargs, daemon=True).start()\n            return True\n        except Exception:\n            return False\n\n    def _do_kernel_working_set_trim(self):\n        batch = {\n            \"phase\": \"kernel_trim\",\n            \"status_text\": \"Kernel working-set trim running...\",\n            \"progress_pct\": 0.0,\n            \"trimmed_processes\": 0,\n            \"errors\": 0,\n            \"delta_mb\": 0,\n        }\n        self._hdd_recovery_emit_metrics(batch)\n        before = psutil.virtual_memory()\n        kernel32 = ctypes.windll.kernel32\n        psapi = ctypes.windll.psapi\n        last_dispatch = time.monotonic()\n        safe_system = {\n            \"system\", \"idle\", \"csrss.exe\", \"wininit.exe\", \"services.exe\",\n            \"lsass.exe\", \"smss.exe\", \"svchost.exe\", \"explorer.exe\", \"dwm.exe\",\n            \"taskeng.exe\", \"taskhostw.exe\", \"winlogon.exe\",\n        }\n        for proc in psutil.process_iter(['pid', 'name']):\n            try:\n                pid = int(proc.info.get('pid') or 0)\n                if pid &lt;= 0 or pid == os.getpid():\n                    continue\n                name = str(proc.info.get('name') or '').lower()\n                if name in safe_system:\n                    continue\n                handle = kernel32.OpenProcess(0x001F0FFF, False, pid)\n                if not handle:\n                    continue\n                try:\n                    if psapi.EmptyWorkingSet(handle):\n                        batch[\"trimmed_processes\"] += 1\n                    try:\n                        kernel32.SetProcessWorkingSetSize(handle, -1, -1)\n                    except Exception:\n                        pass\n                finally:\n                    kernel32.CloseHandle(handle)\n            except (PermissionError, psutil.AccessDenied):\n                batch[\"errors\"] += 1\n            except Exception:\n                batch[\"errors\"] += 1\n            if time.monotonic() - last_dispatch &gt;= 0.120:\n                batch[\"status_text\"] = f\"Kernel trim scanning processes... {batch['trimmed_processes']} trimmed\"\n                batch[\"progress_pct\"] = min(100.0, (batch[\"trimmed_processes\"] / max(1, psutil.cpu_count(logical=False) * 3)) * 100.0)\n                self._hdd_recovery_emit_metrics(batch.copy())\n                last_dispatch = time.monotonic()\n        after = psutil.virtual_memory()\n        batch[\"status_text\"] = f\"Kernel trim complete \u2014 {batch['trimmed_processes']} processes trimmed\"\n        batch[\"progress_pct\"] = 100.0\n        batch[\"delta_mb\"] = int((after.available - before.available) / 1024**2)\n        self._hdd_recovery_emit_metrics(batch.copy())\n        self._hdd_log(f\"\u2705 Kernel working set trim complete, freed {self._fmt_size(batch['delta_mb'] * 1024**2)}\", C[\"success\"])\n\n    def _do_background_priority_demotion(self):\n        before = psutil.virtual_memory()\n        batch = {\n            \"phase\": \"priority_demotion\",\n            \"status_text\": \"Background process priority demotion running...\",\n            \"progress_pct\": 0.0,\n            \"demoted\": 0,\n            \"scanned\": 0,\n            \"errors\": 0,\n            \"delta_mb\": 0,\n        }\n        self._hdd_recovery_emit_metrics(batch)\n        idle_class = getattr(psutil, 'IDLE_PRIORITY_CLASS', getattr(psutil, 'BELOW_NORMAL_PRIORITY_CLASS', 64))\n        keep_names = {\n            'explorer.exe', 'taskmgr.exe', 'chrome.exe', 'firefox.exe', 'msedge.exe',\n            'dwm.exe', 'svchost.exe', 'services.exe', 'lsass.exe', 'wininit.exe',\n            'winlogon.exe', 'csrss.exe', 'system', 'idle', 'spoolsv.exe', 'steam.exe',\n        }\n        last_dispatch = time.monotonic()\n        for proc in psutil.process_iter(['pid', 'name', 'username', 'nice']):\n            batch[\"scanned\"] += 1\n            try:\n                pid = int(proc.info.get('pid') or 0)\n                if pid &lt;= 0 or pid == os.getpid():\n                    continue\n                name = str(proc.info.get('name') or '').lower()\n                username = str(proc.info.get('username') or '').lower()\n                if name in keep_names or any(term in name for term in ('microsoft', 'windows', 'service', 'system', 'sql', 'svchost')):\n                    continue\n                if username in ('nt authority\\\\system', 'local service', 'network service'):\n                    continue\n                current = proc.info.get('nice')\n                if current == idle_class:\n                    continue\n                try:\n                    proc.nice(idle_class)\n                    batch[\"demoted\"] += 1\n                except (PermissionError, psutil.AccessDenied):\n                    batch[\"errors\"] += 1\n                except Exception:\n                    batch[\"errors\"] += 1\n            except (PermissionError, psutil.AccessDenied):\n                batch[\"errors\"] += 1\n            except Exception:\n                batch[\"errors\"] += 1\n            if time.monotonic() - last_dispatch &gt;= 0.120:\n                batch[\"status_text\"] = f\"Demoting background apps... {batch['demoted']} demoted\"\n                batch[\"progress_pct\"] = min(100.0, (batch[\"scanned\"] / max(1, psutil.cpu_count(logical=False) * 10)) * 100.0)\n                self._hdd_recovery_emit_metrics(batch.copy())\n                last_dispatch = time.monotonic()\n        after = psutil.virtual_memory()\n        batch[\"status_text\"] = f\"Priority demotion done \u2014 {batch['demoted']} apps moved to idle\"\n        batch[\"progress_pct\"] = 100.0\n        batch[\"delta_mb\"] = int((after.available - before.available) / 1024**2) if 'before' in locals() else 0\n        self._hdd_recovery_emit_metrics(batch.copy())\n        self._hdd_log(f\"\u2705 Background process demotion complete: {batch['demoted']} processes\", C[\"success\"])\n\n    def _do_smart_standby_boost(self):\n        batch = {\n            \"phase\": \"standby_boost\",\n            \"status_text\": \"Smart standby booster evaluating memory...\",\n            \"progress_pct\": 0.0,\n            \"predicted_ram_mb\": 0,\n            \"confidence_score\": 0,\n            \"delta_mb\": 0,\n        }\n        vm = psutil.virtual_memory()\n        before = vm.available\n        standby_bytes = getattr(vm, 'standby', None) or getattr(vm, 'cached', 0)\n        standby_mb = int(standby_bytes / 1024**2)\n        predicted_free_mb = int(min(standby_mb * 0.65, before / 1024**2 * 0.60))\n        batch[\"predicted_ram_mb\"] = predicted_free_mb\n        batch[\"confidence_score\"] = min(98, max(35, int((standby_mb / max(1, vm.total / 1024**2)) * 100)))\n        batch[\"status_text\"] = f\"Standby booster ready \u2014 {self._fmt_size(standby_bytes)} standby memory detected\"\n        self._hdd_recovery_emit_metrics(batch.copy())\n        if standby_mb &lt; 64:\n            batch[\"status_text\"] = \"Standby memory low; no booster action required.\"\n            batch[\"progress_pct\"] = 100.0\n            self._hdd_recovery_emit_metrics(batch.copy())\n            self._hdd_log(\"\u2139\ufe0f Standby booster skipped; standby cache low.\", C[\"text_dim\"])\n            return\n        self._purge_memory_lists()\n        after = psutil.virtual_memory()\n        batch[\"delta_mb\"] = int((after.available - before) / 1024**2)\n        batch[\"status_text\"] = f\"Standby boost complete \u2014 freed {self._fmt_size(batch['delta_mb'] * 1024**2)}\"\n        batch[\"progress_pct\"] = 100.0\n        self._hdd_recovery_emit_metrics(batch.copy())\n        self._hdd_log(f\"\u2705 Standby booster freed {self._fmt_size(batch['delta_mb'] * 1024**2)}\", C[\"success\"])\n\n    def _do_ram_compression_predictor(self):\n        try:\n            vm = psutil.virtual_memory()\n            predicted_free_mb = int(min(vm.available / 1024**2 * 0.20, vm.total / 1024**2 * 0.08))\n            confidence = min(95, max(30, int((100 - vm.percent) * 0.55 + 10)))\n            score_text = f\"Prediction: {self._fmt_size(predicted_free_mb * 1024**2)} free | Confidence {confidence}%\"\n            self.after(0, lambda: self.hdd_compression_pred_var.set(score_text))\n            self._hdd_recovery_emit_metrics({\n                \"phase\": \"compression_predictor\",\n                \"status_text\": \"RAM compression prediction ready\",\n                \"progress_pct\": 100.0,\n                \"predicted_ram_mb\": predicted_free_mb,\n                \"confidence_score\": confidence,\n            })\n            self._hdd_log(f\"\ud83e\udde0 {score_text}\", C[\"accent4\"])\n        except Exception as e:\n            self._hdd_log(f\"Compression predictor failed: {e}\", C[\"warning\"])\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # 1. SMART REPORT\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _hdd_smart_quick(self):\n        drive = self.hdd_drive_var.get().replace(\":\", \"\")\n        self._hdd_log(f\"\ud83d\udcca Quick SMART check: {drive}:\", C[\"accent\"])\n        self._append_log(self.smart_log, f\"[SMART QUICK CHECK \u2014 Drive {drive}:]\\n\", C[\"accent\"])\n\n        def _run():\n            # WMIC disk status\n            out1, rc1 = self._run_cmd(\n                f'wmic diskdrive get Caption,Status,MediaType,Size /format:list', timeout=15)\n            # PowerShell physical disk health\n            out2, rc2 = self._run_cmd(\n                'powershell -Command \"Get-PhysicalDisk | Select FriendlyName,HealthStatus,OperationalStatus,Size | Format-List\"',\n                timeout=15)\n            # Disk space info\n            out3, rc3 = self._run_cmd(\n                f'wmic logicaldisk where \"DeviceID=\\'{drive}:\\'\" get Caption,FreeSpace,Size,FileSystem,VolumeName /format:list',\n                timeout=10)\n\n            self.after(0, lambda: self._append_log(self.smart_log,\n                f\"\u2500\u2500 Physical Disk Status \u2500\u2500\\n{out1}\\n\\n\u2500\u2500 Health Status \u2500\u2500\\n{out2}\\n\\n\u2500\u2500 Logical Disk \u2500\u2500\\n{out3}\\n\",\n                C[\"text\"]))\n            status = \"OK\" if (\"OK\" in out1.upper() or \"HEALTHY\" in out2.upper()) else \"WARNING\"\n            color = C[\"success\"] if status == \"OK\" else C[\"error\"]\n            self.after(0, lambda: self._hdd_log(\n                f\"\u2705 SMART Quick: Drive {drive}: \u2014 Status: {status}\", color))\n            self.after(0, lambda: self._set_status(f\"SMART check done: {status}\", color))\n            if status != \"OK\":\n                self.after(0, lambda: self._hdd_log(\"\u26a0\ufe0f SMART warning detected \u2014 backup data immediately!\", C[\"warning\"]))\n\n        self._launch_job(\"hdd_smart_quick\", _run)\n\n    def _hdd_smart_report(self):\n        drive = self.hdd_drive_var.get().replace(\":\", \"\")\n        self._hdd_log(f\"\ud83d\udcca Full SMART Report starting for {drive}:\", C[\"accent\"])\n        self._append_log(self.smart_log, \"\\n[\u2550\u2550\u2550 FULL SMART REPORT \u2550\u2550\u2550]\\n\", C[\"accent\"])\n\n        def _run():\n            cmds = [\n                (\"Physical Disk Info\",\n                 'wmic diskdrive get Caption,Model,Status,MediaType,Size,InterfaceType,FirmwareRevision /format:list'),\n                (\"Volume Info\",\n                 f'wmic logicaldisk where \"DeviceID=\\'{drive}:\\'\" get Caption,FreeSpace,Size,FileSystem,VolumeName,DriveType /format:list'),\n                (\"Disk Partition\",\n                 f'wmic partition where \"DriveLetter=\\'{drive}:\\'\" get BlockSize,Bootable,Caption,DiskIndex,Index,Size,Type /format:list'),\n                (\"Physical Disk Health (PS)\",\n                 'powershell -Command \"Get-PhysicalDisk | Format-List *\"'),\n                (\"Disk Reliability (PS)\",\n                 'powershell -Command \"Get-Disk | Select Number,FriendlyName,HealthStatus,OperationalStatus,PartitionStyle,Size | Format-List\"'),\n                (\"Disk Errors (Event Log)\",\n                 'powershell -Command \"Get-EventLog -LogName System -Source \\\\\"disk\\\\\" -Newest 10 -ErrorAction SilentlyContinue | Select TimeGenerated,EntryType,Message | Format-List\"'),\n            ]\n            for label, cmd in cmds:\n                out, rc = self._run_cmd(cmd, timeout=20)\n                self.after(0, lambda l=label, o=out: self._append_log(\n                    self.smart_log, f\"\\n\u2500\u2500 {l} \u2500\u2500\\n{o}\\n\", C[\"text_dim\"]))\n\n            self.after(0, lambda: self._hdd_log(\"\u2705 Full SMART Report complete. Smart log mein dekho.\", C[\"success\"]))\n            self.after(0, lambda: self._set_status(\"SMART Report Complete\", C[\"success\"]))\n\n        self._launch_job(\"hdd_smart_report\", _run)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # 2. BAD SECTOR SCAN + FIX\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _hdd_bad_sector_fix(self):\n        drive = self.hdd_drive_var.get()\n        letter = drive.replace(\":\", \"\")\n        is_system = letter.upper() == \"C\"\n\n        if is_system:\n            msg = (f\"Drive {drive} system drive hai (Windows isi pe hai).\\n\\n\"\n                   f\"chkdsk /f /r NEXT BOOT pe schedule hoga.\\n\"\n                   f\"PC restart hoga aur chkdsk boot se pehle chalega.\\n\\n\"\n                   f\"Kya aap restart karke chkdsk schedule karna chahte hain?\")\n        else:\n            msg = (f\"Drive {drive} pe Bad Sector Scan + Fix chalega.\\n\\n\"\n                   f\"Command: chkdsk {drive} /f /r /x\\n\"\n                   f\"  /f = Errors fix karega\\n\"\n                   f\"  /r = Bad sectors dhundega aur data recover karega\\n\"\n                   f\"  /x = Drive forcefully dismount karega\\n\\n\"\n                   f\"\u26a0\ufe0f  Yeh 30-90 minutes le sakta hai!\\n\\n\"\n                   f\"BEFORE:\\n{self._hdd_disk_info_before(drive)}\\n\\nProceed?\")\n\n        if not messagebox.askyesno(\"Bad Sector Repair\", msg):\n            return\n\n        def _run():\n            self.after(0, lambda: self._hdd_log(f\"\ud83e\ude7a Bad Sector Fix started: {drive}\", C[\"accent4\"]))\n            self.after(0, lambda: self._set_status(f\"chkdsk {drive} running...\", C[\"accent4\"]))\n\n            if is_system:\n                # Schedule for next boot\n                out, rc = self._run_cmd(f'echo Y | chkdsk {drive} /f /r', timeout=15)\n                self.after(0, lambda: self._hdd_log(\n                    f\"\ud83d\udccb chkdsk output:\\n{out}\", C[\"text\"]))\n                if rc == 0 or \"schedule\" in out.lower() or \"next time\" in out.lower():\n                    self.after(0, lambda: self._hdd_log(\n                        \"\u2705 PROOF: chkdsk next boot ke liye schedule ho gaya!\", C[\"success\"]))\n                    self.after(0, lambda: messagebox.showinfo(\"Scheduled\",\n                        f\"\u2705 chkdsk {drive}: next restart pe automatically chalega.\\n\\n\"\n                        f\"PROOF: 'chkdsk schedule' registry mein set ho gayi hai.\\n\"\n                        f\"Verify: regedit \u2192 HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Session Manager\\\\BootExecute\"))\n                else:\n                    self.after(0, lambda: self._hdd_log(f\"\u26a0\ufe0f Output: {out}\", C[\"warning\"]))\n            else:\n                # Run immediately on non-system drive\n                out, rc = self._run_cmd(f'chkdsk {drive} /f /r /x', timeout=3600)\n                self.after(0, lambda: self._hdd_log(\n                    f\"\ud83d\udccb chkdsk Full Output:\\n{out[-1000:]}\", C[\"text\"]))\n\n                # Parse results\n                errors_found = any(k in out.lower() for k in\n                    [\"bad sector\", \"error\", \"found\", \"repaired\", \"corrupt\"])\n                clean = any(k in out.lower() for k in\n                    [\"no errors\", \"0 bad sectors\", \"found no problems\"])\n\n                if clean:\n                    self.after(0, lambda: self._hdd_log(\n                        f\"\u2705 PROOF: Drive {drive} \u2014 No bad sectors found. Drive clean hai!\", C[\"success\"]))\n                    self.after(0, lambda: messagebox.showinfo(\"Clean Drive\",\n                        f\"\u2705 Drive {drive}: CLEAN\\n\\nchkdsk ne koi bad sector nahi paaya.\\n\\nFull output log mein hai.\"))\n                elif errors_found:\n                    self.after(0, lambda: self._hdd_log(\n                        f\"\u26a0\ufe0f PROOF: Bad sectors mili/repair ki gayi. Output check karo.\", C[\"warning\"]))\n                    self.after(0, lambda: messagebox.showwarning(\"Repaired\",\n                        f\"\u26a0\ufe0f Drive {drive}: Issues found and repaired.\\n\\nBad sectors data lost ho sakta hai.\\n\\nBackup ASAP recommended!\"))\n                else:\n                    self.after(0, lambda: self._hdd_log(\n                        f\"\ud83d\udccb chkdsk complete. Output log mein hai.\", C[\"text_dim\"]))\n\n            self.after(0, lambda: self._set_status(\"chkdsk Done\", C[\"success\"]))\n\n        self._launch_job(\"hdd_bad_sector_fix\", _run)\n\n    def _hdd_disk_info_before(self, drive):\n        try:\n            usage = psutil.disk_usage(drive + \"\\\\\")\n            total_gb = usage.total / (1024**3)\n            used_gb = usage.used / (1024**3)\n            free_gb = usage.free / (1024**3)\n            return (f\"Drive: {drive}\\n\"\n                    f\"Total: {total_gb:.1f} GB\\n\"\n                    f\"Used:  {used_gb:.1f} GB\\n\"\n                    f\"Free:  {free_gb:.1f} GB ({100 - usage.percent:.1f}% free)\")\n        except:\n            return f\"Drive: {drive} (size info unavailable)\"\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # 3. MBR / BCD REPAIR\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _hdd_mbr_repair(self):\n        msg = (\"\u26a0\ufe0f  MBR / Boot Repair \u2014 Ye sirf tab use karo jab:\\n\\n\"\n               \"\u2022 PC boot nahi ho raha\\n\"\n               \"\u2022 'Boot sector not found' error aa raha hai\\n\"\n               \"\u2022 BCD (Boot Configuration Data) corrupt hai\\n\\n\"\n               \"Commands jo chalenge:\\n\"\n               \"  1. bootrec /fixmbr      \u2190 MBR rewrite\\n\"\n               \"  2. bootrec /fixboot     \u2190 Boot sector fix\\n\"\n               \"  3. bootrec /scanos      \u2190 Windows installations scan\\n\"\n               \"  4. bootrec /rebuildbcd  \u2190 BCD rebuild\\n\\n\"\n               \"REQUIRE: Admin rights (already have) + Restart recommended after.\\n\\n\"\n               \"Proceed?\")\n        if not messagebox.askyesno(\"MBR / Boot Repair\", msg):\n            return\n\n        def _run():\n            self.after(0, lambda: self._hdd_log(\"\ud83d\udd11 MBR/BCD Repair starting...\", C[\"accent3\"]))\n            results = []\n            steps = [\n                (\"bootrec /fixmbr\",     \"MBR rewrite\"),\n                (\"bootrec /fixboot\",    \"Boot sector fix\"),\n                (\"bootrec /scanos\",     \"OS scan\"),\n                (\"bootrec /rebuildbcd\", \"BCD rebuild\"),\n            ]\n            for cmd, label in steps:\n                out, rc = self._run_cmd(cmd, timeout=60)\n                status = \"\u2705\" if rc == 0 else \"\u26a0\ufe0f\"\n                color = C[\"success\"] if rc == 0 else C[\"warning\"]\n                result_line = f\"{status} {label}: rc={rc} | {out[:120]}\"\n                results.append(result_line)\n                self.after(0, lambda r=result_line, c=color: self._hdd_log(r, c))\n\n            summary = \"\\n\".join(results)\n            self.after(0, lambda: messagebox.showinfo(\"MBR/BCD Repair Complete\",\n                f\"\u2705 MBR/BCD Repair Done!\\n\\n{summary}\\n\\n\"\n                f\"PROOF: bootrec commands ran with above return codes.\\n\"\n                f\"Restart karo aur check karo PC boot hota hai ya nahi.\"))\n            self.after(0, lambda: self._set_status(\"MBR/BCD Repair Done\", C[\"success\"]))\n\n        threading.Thread(target=_run, daemon=True).start()\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # 4. NTFS FILE SYSTEM FIX\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _hdd_ntfs_fix(self):\n        drive = self.hdd_drive_var.get()\n        letter = drive.replace(\":\", \"\")\n        msg = (f\"NTFS File System Fix \u2014 Drive {drive}\\n\\n\"\n               f\"Steps:\\n\"\n               f\"  1. Dirty bit check (fsutil dirty query)\\n\"\n               f\"  2. NTFS USN Journal reset\\n\"\n               f\"  3. chkdsk /f (errors fix, no bad sector scan)\\n\\n\"\n               f\"Ye fast hai (5-15 min). System drive pe next boot schedule hoga.\\n\\nProceed?\")\n        if not messagebox.askyesno(\"NTFS Fix\", msg):\n            return\n\n        def _run():\n            self.after(0, lambda: self._hdd_log(f\"\ud83d\udcc1 NTFS Fix: {drive}\", C[\"accent\"]))\n\n            # Step 1: dirty bit\n            out1, _ = self._run_cmd(f'fsutil dirty query {drive}', timeout=10)\n            dirty = \"dirty\" in out1.lower()\n            self.after(0, lambda: self._hdd_log(\n                f\"{'\u26a0\ufe0f Dirty bit SET \u2014 NTFS needs repair' if dirty else '\u2705 Dirty bit: Clean'}\",\n                C[\"warning\"] if dirty else C[\"success\"]))\n\n            # Step 2: USN Journal reset\n            out2, rc2 = self._run_cmd(\n                f'fsutil usn deletejournal /d {drive}', timeout=15)\n            out3, rc3 = self._run_cmd(\n                f'fsutil usn createjournal m=1000 a=100 {drive}', timeout=15)\n            j_ok = rc2 == 0 and rc3 == 0\n            self.after(0, lambda: self._hdd_log(\n                f\"{'\u2705' if j_ok else '\u26a0\ufe0f'} NTFS Journal reset: {'Done' if j_ok else 'Partial (may need admin)'}\",\n                C[\"success\"] if j_ok else C[\"warning\"]))\n\n            # Step 3: chkdsk /f\n            if letter.upper() == \"C\":\n                out4, rc4 = self._run_cmd(f'echo Y | chkdsk {drive} /f', timeout=15)\n                scheduled = True\n            else:\n                out4, rc4 = self._run_cmd(f'chkdsk {drive} /f', timeout=1800)\n                scheduled = False\n\n            self.after(0, lambda: self._hdd_log(\n                f\"\ud83d\udccb chkdsk /f output:\\n{out4[-500:]}\", C[\"text\"]))\n\n            proof = (f\"PROOF:\\n\"\n                     f\"1. Dirty bit: {'SET (needed fix)' if dirty else 'Clean'}\\n\"\n                     f\"2. USN Journal: {'Reset OK' if j_ok else 'Partial'}\\n\"\n                     f\"3. chkdsk /f: {'Scheduled next boot' if scheduled else 'Ran immediately'} (rc={rc4})\\n\\n\"\n                     f\"Full output log mein hai.\")\n            self.after(0, lambda: messagebox.showinfo(\"NTFS Fix Complete\", proof))\n            self.after(0, lambda: self._hdd_log(\"\u2705 NTFS Fix complete.\", C[\"success\"]))\n            self.after(0, lambda: self._set_status(\"NTFS Fix Done\", C[\"success\"]))\n\n        self._launch_job(\"hdd_ntfs_fix\", _run)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # 5. PARTITION TABLE REPAIR\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _hdd_partition_repair(self):\n        drive = self.hdd_drive_var.get()\n        msg = (f\"Partition Repair \u2014 Drive {drive}\\n\\n\"\n               f\"Kya karega:\\n\"\n               f\"  1. Disk list \u2014 saare disks + partitions dikhayega\\n\"\n               f\"  2. Automount enable \u2014 hidden drives visible karega\\n\"\n               f\"  3. Drive letter assign karega agar missing ho\\n\"\n               f\"  4. Volume info + filesystem type check\\n\\n\"\n               f\"Proceed?\")\n        if not messagebox.askyesno(\"Partition Repair\", msg):\n            return\n\n        def _run():\n            self.after(0, lambda: self._hdd_log(\"\ud83d\udcc2 Partition Repair starting...\", C[\"btn_info\"]))\n\n            # Step 1: List disks\n            out1, _ = self._run_cmd(\n                'powershell -Command \"Get-Disk | Select Number,FriendlyName,PartitionStyle,HealthStatus,Size | Format-Table -AutoSize\"',\n                timeout=15)\n            self.after(0, lambda: self._hdd_log(f\"\ud83d\udccb Disk List:\\n{out1}\", C[\"text\"]))\n\n            # Step 2: List volumes\n            out2, _ = self._run_cmd(\n                'powershell -Command \"Get-Volume | Select DriveLetter,FileSystemLabel,FileSystem,HealthStatus,DriveType,Size,SizeRemaining | Format-Table -AutoSize\"',\n                timeout=15)\n            self.after(0, lambda: self._hdd_log(f\"\ud83d\udccb Volume List:\\n{out2}\", C[\"text\"]))\n\n            # Step 3: Enable automount\n            diskpart_script = \"automount enable\\nexit\\n\"\n            tmp = os.path.join(tempfile.gettempdir(), \"goda_diskpart.txt\")\n            with open(tmp, \"w\") as f:\n                f.write(diskpart_script)\n            out3, rc3 = self._run_cmd(f'diskpart /s \"{tmp}\"', timeout=20)\n            self.after(0, lambda: self._hdd_log(\n                f\"{'\u2705' if rc3 == 0 else '\u26a0\ufe0f'} Automount: {out3[:100]}\", C[\"success\"] if rc3 == 0 else C[\"warning\"]))\n\n            # Step 4: Check if target drive letter exists\n            letter = drive.replace(\":\", \"\")\n            out4, _ = self._run_cmd(\n                f'powershell -Command \"Get-Partition | Where-Object DriveLetter -eq \\'{letter}\\' | Format-List *\"',\n                timeout=10)\n            if out4.strip():\n                self.after(0, lambda: self._hdd_log(\n                    f\"\u2705 Drive {drive} partition info:\\n{out4[:300]}\", C[\"success\"]))\n            else:\n                self.after(0, lambda: self._hdd_log(\n                    f\"\u26a0\ufe0f Drive {drive} partition na mile \u2014 drive letter assign karni pad sakti hai\", C[\"warning\"]))\n\n            proof = (f\"PROOF \u2014 Partition Repair Done:\\n\"\n                     f\"1. Disk list fetched: {len(out1.splitlines())} lines\\n\"\n                     f\"2. Volume list fetched: {len(out2.splitlines())} volumes\\n\"\n                     f\"3. Automount enabled: rc={rc3}\\n\"\n                     f\"4. Partition check: {'Found' if out4.strip() else 'Not found (manual assign needed)'}\\n\\n\"\n                     f\"Full details log mein hain.\")\n            self.after(0, lambda: messagebox.showinfo(\"Partition Repair\", proof))\n            self.after(0, lambda: self._set_status(\"Partition Repair Done\", C[\"success\"]))\n\n        threading.Thread(target=_run, daemon=True).start()\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # 6. VSS / SHADOW COPY FIX\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _hdd_vss_repair(self):\n        msg = (\"VSS / Shadow Copy Fix\\n\\n\"\n               \"Steps:\\n\"\n               \"  1. VSS service stop\\n\"\n               \"  2. Old shadow copies delete\\n\"\n               \"  3. Shadow storage resize\\n\"\n               \"  4. VSS service restart\\n\"\n               \"  5. Volume Shadow Copy verify\\n\\n\"\n               \"\u26a0\ufe0f Existing restore points delete ho jayenge!\\n\\nProceed?\")\n        if not messagebox.askyesno(\"VSS Fix\", msg):\n            return\n\n        def _run():\n            self.after(0, lambda: self._hdd_log(\"\ud83d\udd04 VSS Repair starting...\", C[\"accent2\"]))\n            drive = self.hdd_drive_var.get()\n            steps_done = []\n\n            cmds = [\n                (\"net stop vss\",                               \"VSS stop\"),\n                (\"net stop swprv\",                             \"SWPRV stop\"),\n                (\"vssadmin delete shadows /all /quiet\",        \"Delete old shadows\"),\n                (f\"vssadmin resize shadowstorage /for={drive} /on={drive} /maxsize=10%\",\n                                                               \"Resize shadow storage\"),\n                (\"net start swprv\",                            \"SWPRV start\"),\n                (\"net start vss\",                              \"VSS start\"),\n            ]\n            for cmd, label in cmds:\n                out, rc = self._run_cmd(cmd, timeout=30)\n                ok = rc == 0\n                steps_done.append(f\"{'\u2705' if ok else '\u26a0\ufe0f'} {label}\")\n                self.after(0, lambda l=label, o=out, c=(C[\"success\"] if ok else C[\"warning\"]):\n                    self._hdd_log(f\"{'\u2705' if c==C['success'] else '\u26a0\ufe0f'} {l}: {o[:80]}\", c))\n\n            # Verify VSS running\n            out_v, _ = self._run_cmd('sc query vss', timeout=10)\n            running = \"running\" in out_v.lower()\n            self.after(0, lambda: self._hdd_log(\n                f\"{'\u2705 VSS service: RUNNING' if running else '\u26a0\ufe0f VSS service: Not running'}\",\n                C[\"success\"] if running else C[\"warning\"]))\n\n            proof = \"\\n\".join(steps_done) + f\"\\n\\nVSS Final Status: {'RUNNING \u2705' if running else 'Stopped \u26a0\ufe0f'}\"\n            self.after(0, lambda: messagebox.showinfo(\"VSS Repair Complete\",\n                f\"VSS / Shadow Copy Repair Done!\\n\\n{proof}\"))\n            self.after(0, lambda: self._set_status(\"VSS Repair Done\", C[\"success\"]))\n\n        threading.Thread(target=_run, daemon=True).start()\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # 7. SSD TRIM\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _hdd_ssd_trim(self):\n        drive = self.hdd_drive_var.get()\n        letter = drive.replace(\":\", \"\")\n\n        def _run():\n            self.after(0, lambda: self._hdd_log(f\"\u26a1 SSD TRIM + Optimize: {drive}\", C[\"hw_accent\"]))\n\n            # Check if SSD\n            out_type, _ = self._run_cmd(\n                f'powershell -Command \"(Get-PhysicalDisk | Where-Object {{ $_.DeviceId -eq (Get-Partition -DriveLetter \\'{letter}\\' -ErrorAction SilentlyContinue | Select -ExpandProperty DiskNumber) }}).MediaType\"',\n                timeout=10)\n            is_ssd = \"SSD\" in out_type.upper() or \"Solid\" in out_type\n\n            self.after(0, lambda: self._hdd_log(\n                f\"{'\u26a1 SSD detected' if is_ssd else '\u26a0\ufe0f HDD detected \u2014 TRIM not applicable, use Defrag instead'}\",\n                C[\"hw_accent\"] if is_ssd else C[\"warning\"]))\n\n            # TRIM\n            out1, rc1 = self._run_cmd(\n                f'powershell -Command \"Optimize-Volume -DriveLetter {letter} -ReTrim -Verbose\"',\n                timeout=120)\n            # Also optimize\n            out2, rc2 = self._run_cmd(\n                f'defrag {drive} /U /H /L', timeout=120)\n\n            self.after(0, lambda: self._hdd_log(f\"\ud83d\udccb TRIM output:\\n{out1[-300:]}\", C[\"text\"]))\n            self.after(0, lambda: self._hdd_log(\n                f\"{'\u2705' if rc1 == 0 else '\u26a0\ufe0f'} TRIM: rc={rc1}\", C[\"success\"] if rc1 == 0 else C[\"warning\"]))\n\n            proof = (f\"PROOF \u2014 SSD TRIM Done:\\n\"\n                     f\"Drive: {drive}\\n\"\n                     f\"Optimize-Volume -ReTrim: rc={rc1}\\n\"\n                     f\"defrag /L (thin provision): rc={rc2}\\n\"\n                     f\"Output: {out1[:200]}\")\n            self.after(0, lambda: messagebox.showinfo(\"SSD TRIM Complete\", proof))\n            self.after(0, lambda: self._set_status(\"SSD TRIM Done\", C[\"success\"]))\n\n        threading.Thread(target=_run, daemon=True).start()\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # 8. HDD DEFRAG\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _hdd_defrag(self):\n        drive = self.hdd_drive_var.get()\n        letter = drive.replace(\":\", \"\")\n        if not messagebox.askyesno(\"HDD Defrag\",\n            f\"Drive {drive} ko defragment karein?\\n\\n\"\n            f\"Command: defrag {drive} /U /V /X\\n\"\n            f\"  /U = Progress dikhao\\n  /V = Verbose report\\n  /X = Free space consolidate\\n\\n\"\n            f\"\u26a0\ufe0f 30-120 min lag sakta hai!\\n\\nProceed?\"):\n            return\n\n        def _run():\n            # Safety: avoid defrag on SSD (best-effort detection)\n            try:\n                ana, _ = self._run_cmd(f'defrag {drive} /A', timeout=120)\n                low = (ana or \"\").lower()\n                if \"solid state\" in low or \"ssd\" in low:\n                    self.after(0, lambda: self._hdd_log(\n                        f\"\u26a0\ufe0f Detected SSD for {drive}. Defrag skip. Use SSD TRIM instead.\", C[\"warning\"]))\n                    self.after(0, lambda: messagebox.showwarning(\n                        \"SSD Detected\",\n                        f\"Drive {drive} SSD lag rahi hai.\\n\\nSSD pe Defrag recommend nahi hota.\\n'\ud83d\udca8 SSD TRIM' use karo.\"\n                    ))\n                    return\n            except Exception:\n                pass\n            self.after(0, lambda: self._hdd_log(f\"\ud83d\uddc2 Defrag starting: {drive}\", C[\"accent4\"]))\n            self.after(0, lambda: self._set_status(f\"Defrag {drive}...\", C[\"accent4\"]))\n\n            before_info = self._hdd_disk_info_before(drive)\n            out, rc = self._run_cmd(f'defrag {drive} /U /V /X', timeout=7200)\n\n            self.after(0, lambda: self._hdd_log(f\"\ud83d\udccb Defrag output:\\n{out[-800:]}\", C[\"text\"]))\n\n            # Parse fragmentation info\n            lines = out.splitlines()\n            frag_lines = [l for l in lines if \"fragment\" in l.lower() or \"%\" in l]\n\n            proof = (f\"PROOF \u2014 HDD Defrag Done:\\n\\n\"\n                     f\"BEFORE:\\n{before_info}\\n\\n\"\n                     f\"Defrag rc: {rc}\\n\"\n                     f\"Fragmentation info:\\n\" + \"\\n\".join(frag_lines[:5]) +\n                     f\"\\n\\nFull output log mein hai.\")\n            self.after(0, lambda: messagebox.showinfo(\"Defrag Complete\", proof))\n            self.after(0, lambda: self._hdd_log(\"\u2705 Defrag complete!\", C[\"success\"]))\n            self.after(0, lambda: self._set_status(\"Defrag Done\", C[\"success\"]))\n\n        threading.Thread(target=_run, daemon=True).start()\n\n    def _hdd_auto_optimize(self):\n        drive = self.hdd_drive_var.get()\n        if not messagebox.askyesno(\"Auto Optimize\",\n                                   f\"Drive {drive} ke liye best optimize run karein?\\n\\nSSD \u2192 TRIM\\nHDD \u2192 Defrag\"):\n            return\n\n        def _run():\n            # Best-effort detection (simple, robust quoting)\n            out, _ = self._run_cmd(\n                'powershell -Command \"Get-PhysicalDisk | Select FriendlyName,MediaType,HealthStatus | Format-List *\"',\n                timeout=15\n            )\n            low = (out or \"\").lower()\n            if \"ssd\" in low or \"solid state\" in low:\n                self.after(0, lambda: self._hdd_log(\"\ud83e\udd16 Auto: SSD detected \u2192 running TRIM\", C[\"hw_accent\"]))\n                self.after(0, self._hdd_ssd_trim)\n            else:\n                self.after(0, lambda: self._hdd_log(\"\ud83e\udd16 Auto: HDD assumed \u2192 running Defrag\", C[\"accent4\"]))\n                self.after(0, self._hdd_defrag)\n\n        threading.Thread(target=_run, daemon=True).start()\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # 9. DEEP DISK CLEANUP\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _hdd_deep_cleanup(self):\n        drive = self.hdd_drive_var.get()\n        if not messagebox.askyesno(\"Deep Disk Cleanup\",\n            f\"Drive {drive} ka deep cleanup karein?\\n\\n\"\n            f\"Steps:\\n\"\n            f\"  1. cleanmgr /sageset:1 \u2192 all categories select\\n\"\n            f\"  2. cleanmgr /sagerun:1 \u2192 cleanup run\\n\"\n            f\"  3. Windows.old folder check\\n\"\n            f\"  4. Temp/Prefetch cleanup\\n\\nProceed?\"):\n            return\n\n        def _run():\n            self.after(0, lambda: self._hdd_log(\"\ud83e\uddf9 Deep Cleanup starting...\", C[\"btn\"]))\n\n            before = psutil.disk_usage(drive + \"\\\\\").free / (1024**3)\n\n            # Configure cleanup categories before running cleanup\n            cleanup_root = r\"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\VolumeCaches\"\n            categories = [\n                \"Temporary Files\", \"Recycle Bin\", \"Temporary Internet Files\",\n                \"Old ChkDsk Files\", \"Windows Error Reporting Files\",\n                \"Delivery Optimization Files\", \"Thumbnail Cache\",\n                \"Downloaded Program Files\",\n            ]\n            for cat in categories:\n                try:\n                    self._run_cmd(\n                        f'reg add \"{cleanup_root}\\\\{cat}\" /v StateFlags0099 /t REG_DWORD /d 2 /f',\n                        timeout=10)\n                except Exception:\n                    pass\n            self._run_cmd('cleanmgr /sageset:1', timeout=30)\n            out1, rc1 = self._run_cmd('cleanmgr /sagerun:1', timeout=300)\n            self.after(0, lambda: self._hdd_log(\n                f\"{'\u2705' if rc1 == 0 else '\u26a0\ufe0f'} cleanmgr: rc={rc1}\", C[\"success\"] if rc1 == 0 else C[\"warning\"]))\n\n            # Remove Windows.old if exists\n            wold = os.path.join(drive + \"\\\\\", \"Windows.old\")\n            if os.path.exists(wold):\n                try:\n                    out2, rc2 = self._run_cmd(f'rd /s /q \"{wold}\"', timeout=120)\n                    self.after(0, lambda: self._hdd_log(\"\u2705 Windows.old deleted!\", C[\"success\"]))\n                except:\n                    self.after(0, lambda: self._hdd_log(\"\u26a0\ufe0f Windows.old delete failed (in use)\", C[\"warning\"]))\n\n            # Temp cleanup\n            for path in [os.environ.get(\"TEMP\",\"\"), os.environ.get(\"TMP\",\"\"),\n                          \"C:\\\\Windows\\\\Temp\"]:\n                if path and os.path.exists(path):\n                    for f in Path(path).glob(\"*\"):\n                        try:\n                            if f.is_file():\n                                f.unlink()\n                            elif f.is_dir():\n                                shutil.rmtree(str(f), ignore_errors=True)\n                        except:\n                            pass\n\n            after = psutil.disk_usage(drive + \"\\\\\").free / (1024**3)\n            freed = after - before\n            color = C[\"success\"] if freed &gt; 0.1 else C[\"text_dim\"]\n            self.after(0, lambda: self._hdd_log(\n                f\"\u2705 PROOF: Free space {before:.1f} GB \u2192 {after:.1f} GB | Freed: {freed:.2f} GB\", color))\n            self.after(0, lambda: messagebox.showinfo(\"Deep Cleanup Complete\",\n                f\"\u2705 Deep Cleanup Done!\\n\\n\"\n                f\"BEFORE Free: {before:.2f} GB\\n\"\n                f\"AFTER Free:  {after:.2f} GB\\n\"\n                f\"Freed:       {freed:.2f} GB\"))\n            self.after(0, lambda: self._set_status(f\"Cleanup Done \u2014 {freed:.1f}GB freed\", C[\"success\"]))\n\n        threading.Thread(target=_run, daemon=True).start()\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # 10. SFC + DISM (FULL WITH OUTPUT)\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _hdd_sfc_dism_full(self):\n        if not messagebox.askyesno(\"SFC + DISM Full Repair\",\n            \"Windows File Integrity Repair chalein?\\n\\n\"\n            \"Step 1: SFC /scannow (5-15 min)\\n\"\n            \"Step 2: DISM /RestoreHealth (10-30 min)\\n\\n\"\n            \"\u26a0\ufe0f Internet needed for DISM.\\n\"\n            \"Full output log mein dikhega (pehle sirf 'Done' dikh'ta tha \u2014 ab full proof milega)\\n\\nProceed?\"):\n            return\n\n        def _run():\n            self.after(0, lambda: self._hdd_log(\"\ud83c\udfe5 SFC starting...\", C[\"accent3\"]))\n            self.after(0, lambda: self._set_status(\"SFC /scannow running...\", C[\"accent3\"]))\n\n            # SFC with full output capture\n            out_sfc, rc_sfc = self._run_cmd('sfc /scannow', timeout=900)\n            self.after(0, lambda: self._hdd_log(f\"\ud83d\udccb SFC Output:\\n{out_sfc}\", C[\"text\"]))\n\n            if \"no integrity violations\" in out_sfc.lower():\n                sfc_result = \"\u2705 No corrupt files found\"\n                sfc_color = C[\"success\"]\n            elif \"found and repaired\" in out_sfc.lower() or \"repaired\" in out_sfc.lower():\n                sfc_result = \"\u2705 Corrupt files found AND REPAIRED\"\n                sfc_color = C[\"accent4\"]\n            elif \"unable to fix\" in out_sfc.lower():\n                sfc_result = \"\u26a0\ufe0f Some files could not be repaired \u2014 run DISM then retry SFC\"\n                sfc_color = C[\"warning\"]\n            else:\n                sfc_result = f\"\ud83d\udccb SFC rc={rc_sfc} \u2014 check output above\"\n                sfc_color = C[\"text_dim\"]\n\n            self.after(0, lambda: self._hdd_log(f\"SFC PROOF: {sfc_result}\", sfc_color))\n\n            # DISM\n            self.after(0, lambda: self._hdd_log(\"\ud83c\udfe5 DISM RestoreHealth starting...\", C[\"accent3\"]))\n            self.after(0, lambda: self._set_status(\"DISM RestoreHealth...\", C[\"accent3\"]))\n            out_dism, rc_dism = self._run_cmd(\n                'DISM /Online /Cleanup-Image /RestoreHealth', timeout=3600)\n            self.after(0, lambda: self._hdd_log(f\"\ud83d\udccb DISM Output:\\n{out_dism[-800:]}\", C[\"text\"]))\n\n            if rc_dism == 0:\n                dism_result = \"\u2705 DISM RestoreHealth: SUCCESS\"\n                dism_color = C[\"success\"]\n            else:\n                dism_result = f\"\u26a0\ufe0f DISM rc={rc_dism} \u2014 internet check karo ya CBS log dekho\"\n                dism_color = C[\"warning\"]\n\n            self.after(0, lambda: self._hdd_log(f\"DISM PROOF: {dism_result}\", dism_color))\n\n            proof = (f\"FULL PROOF:\\n\\n\"\n                     f\"SFC /scannow:\\n  rc={rc_sfc}\\n  Result: {sfc_result}\\n\\n\"\n                     f\"DISM RestoreHealth:\\n  rc={rc_dism}\\n  Result: {dism_result}\\n\\n\"\n                     f\"Full output HDD log mein hai.\")\n            self.after(0, lambda: messagebox.showinfo(\"SFC + DISM Complete\", proof))\n            self.after(0, lambda: self._set_status(\"SFC + DISM Done\", C[\"success\"]))\n\n        threading.Thread(target=_run, daemon=True).start()\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # 11. ERROR EVENT LOG\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _hdd_error_log(self):\n        def _run():\n            self.after(0, lambda: self._hdd_log(\"\ud83d\udccb Fetching disk error events...\", C[\"accent\"]))\n            out, rc = self._run_cmd(\n                'powershell -Command \"Get-EventLog -LogName System -EntryType Error,Warning -Newest 30 '\n                '-ErrorAction SilentlyContinue | Where-Object {$_.Source -match \\'disk|ntfs|volsnap|storport|iaStorV\\'} '\n                '| Select-Object TimeGenerated,EntryType,Source,Message | Format-List\"',\n                timeout=30)\n            if not out.strip() or rc != 0:\n                out2, _ = self._run_cmd(\n                    'powershell -Command \"Get-WinEvent -LogName System -MaxEvents 50 -ErrorAction SilentlyContinue '\n                    '| Where-Object {$_.Message -match \\'disk|NTFS|sector\\'} '\n                    '| Select-Object TimeCreated,LevelDisplayName,Message | Format-List\"',\n                    timeout=30)\n                out = out2\n\n            self.after(0, lambda: self._hdd_log(\n                f\"\ud83d\udccb Disk Error Events:\\n{out if out.strip() else 'No recent disk errors found \u2014 system clean!'}\",\n                C[\"text\"]))\n\n            if not out.strip():\n                self.after(0, lambda: messagebox.showinfo(\"Event Log\",\n                    \"\u2705 No recent disk errors in Event Log!\\n\\nDisk system clean hai.\"))\n            else:\n                error_count = out.count(\"TimeGenerated\") + out.count(\"TimeCreated\")\n                self.after(0, lambda: messagebox.showwarning(\"Disk Errors Found\",\n                    f\"\u26a0\ufe0f {error_count} disk-related events found!\\n\\n\"\n                    f\"PROOF: Event Log se real data fetch kiya.\\n\"\n                    f\"Full details HDD log mein hain.\\n\\n\"\n                    f\"Recommendation: Bad sector scan chalao.\"))\n            self.after(0, lambda: self._set_status(\"Error Log Fetched\", C[\"success\"]))\n\n        threading.Thread(target=_run, daemon=True).start()\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # 12. BSOD / CRASH INFO\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _hdd_bsod_info(self):\n        def _run():\n            self.after(0, lambda: self._hdd_log(\"\ud83d\udca5 Fetching BSoD / Crash info...\", C[\"accent3\"]))\n\n            # Check minidump folder\n            minidump_path = r\"C:\\Windows\\Minidump\"\n            dumps = []\n            if os.path.exists(minidump_path):\n                dumps = sorted(Path(minidump_path).glob(\"*.dmp\"),\n                               key=lambda x: x.stat().st_mtime, reverse=True)[:5]\n\n            # Get last crash from Event Log\n            out_crash, _ = self._run_cmd(\n                'powershell -Command \"Get-EventLog -LogName System -Source \\'Microsoft-Windows-WER-SystemErrorReporting\\' '\n                '-Newest 5 -ErrorAction SilentlyContinue | Select TimeGenerated,Message | Format-List\"',\n                timeout=20)\n            # Reliability history\n            out_rel, _ = self._run_cmd(\n                'powershell -Command \"Get-WinEvent -ProviderName Microsoft-Windows-Kernel-Power -MaxEvents 5 '\n                '-ErrorAction SilentlyContinue | Select TimeCreated,LevelDisplayName,Message | Format-List\"',\n                timeout=20)\n            # Last BSOD from registry\n            out_reg, _ = self._run_cmd(\n                r'reg query \"HKLM\\SYSTEM\\CurrentControlSet\\Control\\CrashControl\" /v DumpFile',\n                timeout=10)\n\n            dump_info = \"\"\n            if dumps:\n                dump_info = f\"Recent Minidumps ({len(dumps)} files):\\n\"\n                for d in dumps:\n                    mtime = datetime.datetime.fromtimestamp(d.stat().st_mtime).strftime(\"%Y-%m-%d %H:%M\")\n                    dump_info += f\"  \u2022 {d.name} ({mtime}, {d.stat().st_size//1024} KB)\\n\"\n            else:\n                dump_info = \"No minidumps found \u2014 system stable hai ya dump disabled hai\\n\"\n\n            full_info = (f\"[BSoD / Crash Analysis]\\n\\n\"\n                         f\"{dump_info}\\n\"\n                         f\"\u2500\u2500 Event Log Crashes \u2500\u2500\\n{out_crash or 'No crash events'}\\n\\n\"\n                         f\"\u2500\u2500 Kernel Power Events \u2500\u2500\\n{out_rel or 'No power events'}\\n\\n\"\n                         f\"\u2500\u2500 Dump Config \u2500\u2500\\n{out_reg}\")\n\n            self.after(0, lambda: self._hdd_log(full_info, C[\"text\"]))\n            try:\n                deep_report, deep_severity, deep_count = self._build_bsod_deep_report()\n                deep_color = C[\"warning\"] if deep_severity == \"warning\" else C[\"success\"]\n                self.after(0, lambda r=deep_report, c=deep_color: self._hdd_log(\n                    \"\\n[Advanced BSoD Troubleshooting + Solution]\\n\" + r, c))\n            except Exception as e:\n                self.after(0, lambda err=e: self._hdd_log(\n                    f\"Advanced BSoD diagnosis failed: {err}\", C[\"warning\"]))\n\n            if dumps:\n                self.after(0, lambda: messagebox.showwarning(\"Crash Dumps Found\",\n                    f\"\u26a0\ufe0f {len(dumps)} minidump file(s) found!\\n\\n\"\n                    f\"PROOF: C:\\\\Windows\\\\Minidump mein actual .dmp files hain.\\n\\n\"\n                    f\"Latest: {dumps[0].name}\\n\\n\"\n                    f\"Analysis ke liye WinDbg ya WhoCrashed use karo.\"))\n            else:\n                self.after(0, lambda: messagebox.showinfo(\"BSoD Info\",\n                    \"\u2705 No recent BSoD/crash dumps found!\\n\\nSystem stable lag raha hai.\"))\n\n        threading.Thread(target=_run, daemon=True).start()\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # 13. ONE-CLICK FULL REPAIR\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _hdd_full_repair(self):\n        drive = self.hdd_drive_var.get()\n        msg = (f\"\u26a1 ONE-CLICK FULL HDD/SSD REPAIR\\n\\n\"\n               f\"Drive: {drive}\\n\\n\"\n               f\"Ye kya karega:\\n\"\n               f\"  1. \u2705 SMART Quick Check\\n\"\n               f\"  2. \u2705 NTFS Dirty Bit + Journal Reset\\n\"\n               f\"  3. \u2705 VSS / Shadow Copy Repair\\n\"\n               f\"  4. \u2705 SFC /scannow (file integrity)\\n\"\n               f\"  5. \u2705 DISM RestoreHealth\\n\"\n               f\"  6. \u2705 chkdsk /f (next boot if C:)\\n\"\n               f\"  7. \u2705 Deep Temp Cleanup\\n\"\n               f\"  8. \u2705 Error Event Log check\\n\\n\"\n               f\"\u26a0\ufe0f 45-90 minutes lag sakta hai!\\n\"\n               f\"\u26a0\ufe0f Internet DISM ke liye chahiye.\\n\\n\"\n               f\"Proceed?\")\n        if not messagebox.askyesno(\"Full Repair\", msg):\n            return\n\n        def _run():\n            results = []\n            def log_step(msg, color=None):\n                self.after(0, lambda m=msg, c=color: self._hdd_log(m, c or C[\"text\"]))\n                results.append(msg)\n\n            log_step(f\"\ud83d\ude80 FULL REPAIR STARTED \u2014 Drive {drive}\", C[\"accent\"])\n\n            # 1. SMART\n            log_step(\"Step 1/8: SMART Quick Check...\", C[\"text_dim\"])\n            out1, _ = self._run_cmd('wmic diskdrive get Caption,Status /format:list', timeout=15)\n            smart_ok = \"OK\" in out1.upper()\n            log_step(f\"{'\u2705' if smart_ok else '\u26a0\ufe0f'} SMART: {'OK' if smart_ok else 'Warning \u2014 check output'}\",\n                     C[\"success\"] if smart_ok else C[\"warning\"])\n\n            # 2. NTFS\n            log_step(\"Step 2/8: NTFS Journal Reset...\", C[\"text_dim\"])\n            self._run_cmd(f'fsutil usn deletejournal /d {drive}', timeout=15)\n            self._run_cmd(f'fsutil usn createjournal m=1000 a=100 {drive}', timeout=15)\n            log_step(\"\u2705 NTFS Journal reset done\", C[\"success\"])\n\n            # 3. VSS\n            log_step(\"Step 3/8: VSS Repair...\", C[\"text_dim\"])\n            self._run_cmd('net stop vss', timeout=20)\n            self._run_cmd('vssadmin delete shadows /all /quiet', timeout=30)\n            self._run_cmd('net start vss', timeout=20)\n            log_step(\"\u2705 VSS repaired\", C[\"success\"])\n\n            # 4. SFC\n            log_step(\"Step 4/8: SFC /scannow...\", C[\"text_dim\"])\n            out_sfc, rc_sfc = self._run_cmd('sfc /scannow', timeout=900)\n            if \"no integrity violations\" in out_sfc.lower():\n                log_step(\"\u2705 SFC: No corrupt files\", C[\"success\"])\n            elif \"repaired\" in out_sfc.lower():\n                log_step(\"\u2705 SFC: Files repaired!\", C[\"accent4\"])\n            else:\n                log_step(f\"\u26a0\ufe0f SFC rc={rc_sfc}\", C[\"warning\"])\n\n            # 5. DISM\n            log_step(\"Step 5/8: DISM RestoreHealth...\", C[\"text_dim\"])\n            out_dism, rc_dism = self._run_cmd(\n                'DISM /Online /Cleanup-Image /RestoreHealth', timeout=3600)\n            log_step(f\"{'\u2705' if rc_dism == 0 else '\u26a0\ufe0f'} DISM: rc={rc_dism}\",\n                     C[\"success\"] if rc_dism == 0 else C[\"warning\"])\n\n            # 6. chkdsk\n            log_step(\"Step 6/8: chkdsk...\", C[\"text_dim\"])\n            letter = drive.replace(\":\", \"\")\n            if letter.upper() == \"C\":\n                self._run_cmd(f'echo Y | chkdsk {drive} /f', timeout=15)\n                log_step(\"\u2705 chkdsk: Scheduled for next boot (C: drive)\", C[\"success\"])\n            else:\n                out_ck, rc_ck = self._run_cmd(f'chkdsk {drive} /f', timeout=1800)\n                log_step(f\"{'\u2705' if rc_ck == 0 else '\u26a0\ufe0f'} chkdsk: rc={rc_ck}\", C[\"success\"] if rc_ck == 0 else C[\"warning\"])\n\n            # 7. Temp cleanup\n            log_step(\"Step 7/8: Temp cleanup...\", C[\"text_dim\"])\n            before_free = psutil.disk_usage(drive + \"\\\\\").free / (1024**3)\n            for path in [os.environ.get(\"TEMP\",\"\"), \"C:\\\\Windows\\\\Temp\"]:\n                if path and os.path.exists(path):\n                    for f in Path(path).glob(\"*\"):\n                        try:\n                            if f.is_file(): f.unlink()\n                            elif f.is_dir(): shutil.rmtree(str(f), ignore_errors=True)\n                        except: pass\n            after_free = psutil.disk_usage(drive + \"\\\\\").free / (1024**3)\n            log_step(f\"\u2705 Temp cleanup: {after_free - before_free:.1f} GB freed\", C[\"success\"])\n\n            # 8. Error log check\n            log_step(\"Step 8/8: Error log check...\", C[\"text_dim\"])\n            out_err, _ = self._run_cmd(\n                'powershell -Command \"Get-EventLog -LogName System -EntryType Error -Newest 5 '\n                '-ErrorAction SilentlyContinue | Where-Object {$_.Source -match \\'disk|ntfs\\'} | Measure-Object | Select-Object Count\"',\n                timeout=20)\n            log_step(f\"\u2705 Error log checked: {out_err.strip()}\", C[\"success\"])\n\n            # Final summary\n            summary = \"\\n\".join(results[-10:])\n            self.after(0, lambda: messagebox.showinfo(\"\u2705 Full Repair Complete!\",\n                f\"ONE-CLICK FULL REPAIR DONE!\\n\\nDrive: {drive}\\n\\n\"\n                f\"PROOF \u2014 Steps completed:\\n{summary}\\n\\n\"\n                f\"\u26a0\ufe0f Restart karo aur chkdsk boot pe chalega (agar C: drive tha).\\n\"\n                f\"Full details HDD log mein hain.\"))\n            self.after(0, lambda: self._set_status(\"Full Repair DONE!\", C[\"success\"]))\n\n        threading.Thread(target=_run, daemon=True).start()\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # WINPE \u2014 Generate .bat scripts\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _winpe_gen_mbr_bat(self):\n        drive = self.hdd_drive_var.get()\n        content = f\"\"\"@echo off\n:: Godawari Computers \u2014 MBR / BCD Repair Script\n:: WinPE / Recovery Mode mein chalao\n:: Drive: {drive}\necho.\necho ========================================\necho  GODAWARI COMPUTERS \u2014 MBR REPAIR\necho ========================================\necho.\necho Step 1: Fixing MBR...\nbootrec /fixmbr\necho.\necho Step 2: Fixing Boot Sector...\nbootrec /fixboot\necho.\necho Step 3: Scanning OS installations...\nbootrec /scanos\necho.\necho Step 4: Rebuilding BCD...\nbootrec /rebuildbcd\necho.\necho Step 5: Disk list check...\ndiskpart /s %~dp0diskpart_list.txt\necho.\necho ========================================\necho  DONE! Restart karo.\necho ========================================\npause\n\"\"\"\n        diskpart_content = \"list disk\\nlist volume\\nexit\\n\"\n        desktop = os.path.join(os.path.expanduser(\"~\"), \"Desktop\")\n        fpath = os.path.join(desktop, \"Godawari_MBR_Fix.bat\")\n        fpath2 = os.path.join(desktop, \"diskpart_list.txt\")\n        try:\n            with open(fpath, \"w\") as f: f.write(content)\n            with open(fpath2, \"w\") as f: f.write(diskpart_content)\n            self._hdd_log(f\"\u2705 MBR Fix .bat saved: {fpath}\", C[\"success\"])\n            messagebox.showinfo(\"Saved\",\n                f\"\u2705 MBR Repair .bat file Desktop pe save ho gayi!\\n\\n{fpath}\\n\\n\"\n                f\"WinPE mein USB pe copy karo aur chalao.\")\n        except Exception as e:\n            messagebox.showerror(\"Error\", str(e))\n\n    def _winpe_gen_chkdsk_bat(self):\n        drive = self.hdd_drive_var.get()\n        content = f\"\"\"@echo off\n:: Godawari Computers \u2014 ChkDsk Repair Script\n:: WinPE / Recovery Mode mein chalao\necho.\necho ========================================\necho  GODAWARI COMPUTERS \u2014 CHKDSK REPAIR\necho  Drive: {drive}\necho ========================================\necho.\necho Bad Sector Scan + Fix starting...\necho (Yeh 30-90 min le sakta hai)\necho.\nchkdsk {drive} /f /r /x\necho.\necho NTFS Journal Reset...\nfsutil usn deletejournal /d {drive}\nfsutil usn createjournal m=1000 a=100 {drive}\necho.\necho ========================================\necho  DONE!\necho ========================================\npause\n\"\"\"\n        desktop = os.path.join(os.path.expanduser(\"~\"), \"Desktop\")\n        fpath = os.path.join(desktop, \"Godawari_ChkDsk_Fix.bat\")\n        try:\n            with open(fpath, \"w\") as f: f.write(content)\n            self._hdd_log(f\"\u2705 ChkDsk .bat saved: {fpath}\", C[\"success\"])\n            messagebox.showinfo(\"Saved\",\n                f\"\u2705 ChkDsk .bat Desktop pe save ho gayi!\\n\\n{fpath}\\n\\n\"\n                f\"WinPE ya Recovery CMD mein chalao.\")\n        except Exception as e:\n            messagebox.showerror(\"Error\", str(e))\n\n    def _winpe_gen_full_bat(self):\n        drive = self.hdd_drive_var.get()\n        content = f\"\"\"@echo off\n:: Godawari Computers \u2014 Full Repair Script\n:: WinPE / Recovery Mode mein chalao\necho.\necho ========================================\necho  GODAWARI COMPUTERS \u2014 FULL REPAIR\necho  Drive: {drive}\necho ========================================\necho.\necho [1/6] MBR Fix...\nbootrec /fixmbr\nbootrec /fixboot\nbootrec /rebuildbcd\necho.\necho [2/6] Bad Sector Scan...\nchkdsk {drive} /f /r /x\necho.\necho [3/6] NTFS Fix...\nfsutil usn deletejournal /d {drive}\nfsutil usn createjournal m=1000 a=100 {drive}\necho.\necho [4/6] SFC Scan...\nsfc /scannow\necho.\necho [5/6] DISM Repair...\nDISM /Online /Cleanup-Image /RestoreHealth\necho.\necho [6/6] DNS + Network Reset...\nipconfig /flushdns\nnetsh winsock reset\nnetsh int ip reset\necho.\necho ========================================\necho  ALL DONE! Restart karo.\necho ========================================\npause\n\"\"\"\n        desktop = os.path.join(os.path.expanduser(\"~\"), \"Desktop\")\n        fpath = os.path.join(desktop, \"Godawari_Full_Repair.bat\")\n        try:\n            with open(fpath, \"w\") as f: f.write(content)\n            self._hdd_log(f\"\u2705 Full Repair .bat saved: {fpath}\", C[\"success\"])\n            messagebox.showinfo(\"Saved\",\n                f\"\u2705 Full Repair .bat Desktop pe save ho gayi!\\n\\n{fpath}\\n\\n\"\n                f\"USB pe copy karo \u2192 WinPE/Recovery CMD mein chalao \u2192 Admin rights se.\")\n        except Exception as e:\n            messagebox.showerror(\"Error\", str(e))\n\n    def _winpe_open_recovery(self):\n        if not messagebox.askyesno(\"Open Windows Recovery\",\n            \"Windows Recovery Environment (RE) kholein?\\n\\n\"\n            \"PC restart hoga aur Recovery menu aayega.\\n\\n\"\n            \"Wahan se: Troubleshoot \u2192 Advanced \u2192 Command Prompt\\n\\n\"\n            \"Proceed?\"):\n            return\n        out, rc = self._run_cmd('reagentc /boottore', timeout=15)\n        if rc == 0:\n            self._hdd_log(\"\u2705 Recovery mode set \u2014 restarting...\", C[\"accent4\"])\n            messagebox.showinfo(\"Restarting\",\n                \"\u2705 System Recovery mode mein restart ho raha hai!\\n\\n\"\n                \"Wahan se Command Prompt select karo aur .bat script chalao.\")\n            self._run_cmd('shutdown /r /t 5 /c \"Godawari: Restarting to Recovery\"', timeout=10)\n        else:\n            self._hdd_log(f\"\u26a0\ufe0f reagentc failed: {out} \u2014 manual restart karo F8 dabao\", C[\"warning\"])\n            messagebox.showwarning(\"Manual Method\",\n                \"\u26a0\ufe0f Automatic recovery boot nahi hua.\\n\\n\"\n                \"Manual method:\\n\"\n                \"1. PC restart karo\\n\"\n                \"2. Boot ke time F8 dabao\\n\"\n                \"3. Troubleshoot \u2192 Advanced Options \u2192 Command Prompt\\n\"\n                \"4. Wahan .bat script chalao\")\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # OFFICE &amp; PDF TOOLS SECTION\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _build_office_tools(self, parent):\n        \"\"\"\n        Professional Office &amp; PDF Tools section.\n        Sub-tabs:\n          1. Image / PDF Converter  (JPG\u2192PDF, PDF\u2192Images)\n          2. PDF Operations         (Merge, Split, Rotate, Compress)\n          3. Office Converter       (DOC/XLS/PPT \u2192 PDF, PDF \u2192 Word/Excel)\n          4. Office File Repair     (DOCX, XLSX, PPTX, PDF recovery)\n        Dependencies must be available locally/offline; no runtime downloads.\n        \"\"\"\n        import threading\n\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n\n        # \u2500\u2500 Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        hdr = tk.Frame(frame, bg=C[\"panel\"])\n        hdr.pack(fill=\"x\")\n        tk.Label(hdr, text=\"  \ud83d\udcc4 Office &amp; PDF Tools\",\n                 font=FONTS[\"heading\"], fg=C[\"accent\"], bg=C[\"panel\"]).pack(side=\"left\", pady=10, padx=8)\n        tk.Label(hdr, text=\"Image\u2194PDF \u00b7 Merge \u00b7 Split \u00b7 Convert \u00b7 Repair  |  Offline local engines only\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"left\", pady=10, padx=4)\n\n        # \u2500\u2500 Sub-tab bar \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        tab_bar = tk.Frame(frame, bg=C[\"card\"])\n        tab_bar.pack(fill=\"x\", padx=0, pady=0)\n        tk.Frame(tab_bar, bg=C[\"border\"], height=1).pack(side=\"bottom\", fill=\"x\")\n\n        content_host = tk.Frame(frame, bg=C[\"bg\"])\n        content_host.pack(fill=\"both\", expand=True)\n\n        self._office_tab_frames = {}\n        self._office_active_tab = tk.StringVar(value=\"img_pdf\")\n\n        subtabs = [\n            (\"img_pdf\",    \"\ud83d\uddbc  Image \u2194 PDF\"),\n            (\"pdf_ops\",    \"\ud83d\udccb  PDF Operations\"),\n            (\"office_conv\",\"\ud83d\udcca  Office Converter\"),\n            (\"file_repair\",\"\ud83d\udd27  File Repair\"),\n        ]\n        self._office_tab_btns = {}\n\n        def _switch_office_tab(key):\n            self._office_active_tab.set(key)\n            for k, btn in self._office_tab_btns.items():\n                btn.config(bg=C[\"accent\"] if k == key else C[\"panel\"],\n                           fg=C[\"bg\"]     if k == key else C[\"text\"])\n            for k, f in self._office_tab_frames.items():\n                if k == key:\n                    f.pack(fill=\"both\", expand=True)\n                else:\n                    f.pack_forget()\n\n        for key, label in subtabs:\n            btn = tk.Button(tab_bar, text=label, font=FONTS[\"body\"],\n                            bg=C[\"panel\"], fg=C[\"text\"], bd=0,\n                            padx=18, pady=8, cursor=\"hand2\",\n                            command=lambda k=key: _switch_office_tab(k))\n            btn.pack(side=\"left\")\n            self._office_tab_btns[key] = btn\n\n        # \u2500\u2500 Shared log widget \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        log_host = tk.Frame(frame, bg=C[\"card\"])\n        log_host.pack(fill=\"x\", side=\"bottom\")\n        tk.Label(log_host, text=\"  Activity Log\", font=FONTS[\"small\"],\n                 fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=8, pady=(6,0))\n        self._ot_log = scrolledtext.ScrolledText(log_host, height=5, state=\"disabled\",\n                                                  bg=C[\"bg\"], fg=C[\"text\"], font=FONTS[\"small\"],\n                                                  bd=0, relief=\"flat\")\n        self._ot_log.pack(fill=\"x\", padx=8, pady=(2,6))\n\n        def ot_log(msg, color=None):\n            ts = datetime.datetime.now().strftime(\"%H:%M:%S\")\n            full = f\"[{ts}] {msg}\\n\"\n            self._ot_log.config(state=\"normal\")\n            tag = f\"c{abs(hash(color or 'def'))}\"\n            self._ot_log.tag_config(tag, foreground=color or C[\"text\"])\n            self._ot_log.insert(\"end\", full, tag)\n            self._ot_log.see(\"end\")\n            self._ot_log.config(state=\"disabled\")\n\n        self._ot_log_fn = ot_log\n\n        def _ensure_pkg(pkg_import, pip_name=None):\n            \"\"\"Return True only when an offline/local dependency is already available.\"\"\"\n            pip_name = pip_name or pkg_import\n            try:\n                __import__(pkg_import)\n                return True\n            except ImportError:\n                ot_log(\n                    f\"\u274c Missing local dependency: {pip_name}. Runtime download/install is disabled; bundle the offline wheel/package.\",\n                    C[\"error\"],\n                )\n            return False\n\n        self._ot_ensure_pkg = _ensure_pkg\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # TAB 1 \u2014 Image \u2194 PDF\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        t1 = tk.Frame(content_host, bg=C[\"bg\"])\n        self._office_tab_frames[\"img_pdf\"] = t1\n\n        def _make_card(parent, title):\n            card = tk.Frame(parent, bg=C[\"card\"])\n            card.pack(fill=\"x\", padx=16, pady=8)\n            tk.Label(card, text=title, font=FONTS[\"subhead\"],\n                     fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=10, pady=(8,4))\n            tk.Frame(card, bg=C[\"border\"], height=1).pack(fill=\"x\", padx=10)\n            body = tk.Frame(card, bg=C[\"card\"])\n            body.pack(fill=\"x\", padx=10, pady=8)\n            return body\n\n        # \u2500\u2500 JPG / PNG \u2192 single PDF \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        c1a = _make_card(t1, \"\ud83d\uddbc  Images \u2192 PDF  (JPG / PNG / BMP / TIFF \u2192 one PDF)\")\n        tk.Label(c1a, text=\"Images select karo (multiple Ctrl+click):\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\")\n\n        self._ot_img2pdf_files = tk.StringVar(value=\"\")\n        img2pdf_entry = tk.Entry(c1a, textvariable=self._ot_img2pdf_files,\n                                  font=FONTS[\"small\"], bg=C[\"bg\"], fg=C[\"text\"],\n                                  insertbackground=C[\"text\"], width=60)\n        img2pdf_entry.pack(side=\"left\", padx=(0,6), pady=4)\n\n        def _browse_images():\n            files = filedialog.askopenfilenames(\n                title=\"Images select karo\",\n                filetypes=[(\"Image files\",\"*.jpg *.jpeg *.png *.bmp *.tiff *.tif *.gif *.webp\"),\n                           (\"All files\",\"*.*\")])\n            if files:\n                self._ot_img2pdf_files.set(\";\".join(files))\n\n        tk.Button(c1a, text=\"Browse\u2026\", font=FONTS[\"small\"], bg=C[\"btn_info\"],\n                  fg=C[\"text\"], bd=0, padx=10, pady=4, cursor=\"hand2\",\n                  command=_browse_images).pack(side=\"left\", padx=4)\n\n        def _do_img2pdf():\n            paths = [p.strip() for p in self._ot_img2pdf_files.get().split(\";\") if p.strip()]\n            if not paths:\n                messagebox.showwarning(\"Warning\", \"Pehle images select karo.\")\n                return\n            # Pehli image ke naam se default PDF naam suggest karo\n            first_base = os.path.splitext(os.path.basename(paths[0]))[0] if paths else \"output\"\n            out = filedialog.asksaveasfilename(title=\"Output PDF save karein\",\n                                               defaultextension=\".pdf\",\n                                               initialfile=first_base,\n                                               filetypes=[(\"PDF\",\"*.pdf\")])\n            if not out:\n                return\n            def _run():\n                try:\n                    result = offline_images_to_pdf(\n                        paths,\n                        out,\n                        dpi=150,\n                        margin_mm=10,\n                        quality=85,\n                        auto_orientation=True,\n                        progress=lambda i, total, msg: ot_log(f\"  {i}/{total}: {msg}\", C[\"text_dim\"]),\n                    )\n                    ot_log(f\"\u2705 PDF bana diya: {out}  ({result.get('pages', 0)} images)\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"Done!\",\n                        f\"\u2705 {result.get('pages', 0)} images \u2192 PDF\\n\\n{out}\"))\n                except Exception as ex:\n                    ot_log(f\"\u274c Error: {ex}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n            threading.Thread(target=_run, daemon=True).start()\n\n        tk.Button(c1a, text=\"\u25b6 Convert to PDF\", font=FONTS[\"body\"],\n                  bg=C[\"accent\"], fg=C[\"bg\"], bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=_do_img2pdf).pack(side=\"left\", padx=10)\n\n        # \u2500\u2500 PDF \u2192 Images \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        c1b = _make_card(t1, \"\ud83d\udcc4  PDF \u2192 Images  (choose format: JPG / PNG / BMP / TIFF)\")\n        r1b = tk.Frame(c1b, bg=C[\"card\"])\n        r1b.pack(fill=\"x\")\n        tk.Label(r1b, text=\"PDF file:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_pdf2img_path = tk.StringVar()\n        tk.Entry(r1b, textvariable=self._ot_pdf2img_path, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=48).pack(side=\"left\", padx=4)\n        tk.Button(r1b, text=\"Browse\u2026\", font=FONTS[\"small\"], bg=C[\"btn_info\"],\n                  fg=C[\"text\"], bd=0, padx=10, pady=4, cursor=\"hand2\",\n                  command=lambda: self._ot_pdf2img_path.set(\n                      filedialog.askopenfilename(filetypes=[(\"PDF\",\"*.pdf\"),(\"All\",\"*.*\")])\n                  )).pack(side=\"left\", padx=4)\n\n        r1b2 = tk.Frame(c1b, bg=C[\"card\"])\n        r1b2.pack(fill=\"x\", pady=(4,0))\n        tk.Label(r1b2, text=\"Output format:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_pdf2img_fmt = tk.StringVar(value=\"JPG\")\n        for fmt in (\"JPG\", \"PNG\", \"BMP\", \"TIFF\"):\n            tk.Radiobutton(r1b2, text=fmt, variable=self._ot_pdf2img_fmt, value=fmt,\n                           font=FONTS[\"small\"], bg=C[\"card\"], fg=C[\"text\"],\n                           selectcolor=C[\"bg\"], activebackground=C[\"card\"]).pack(side=\"left\", padx=6)\n\n        tk.Label(r1b2, text=\"  DPI:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_pdf2img_dpi = tk.StringVar(value=\"150\")\n        tk.Entry(r1b2, textvariable=self._ot_pdf2img_dpi, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=5).pack(side=\"left\", padx=4)\n\n        def _do_pdf2img():\n            pdf_path = self._ot_pdf2img_path.get().strip()\n            if not pdf_path or not os.path.isfile(pdf_path):\n                messagebox.showwarning(\"Warning\", \"Valid PDF select karo.\")\n                return\n            out_dir = filedialog.askdirectory(title=\"Output folder choose karo\")\n            if not out_dir:\n                return\n            fmt  = self._ot_pdf2img_fmt.get()\n            try:\n                dpi = int(self._ot_pdf2img_dpi.get())\n            except Exception:\n                dpi = 150\n            def _run():\n                try:\n                    result = offline_pdf_to_images(\n                        pdf_path,\n                        out_dir,\n                        fmt=fmt.lower(),\n                        dpi=dpi,\n                        pages=None,\n                        jpeg_quality=90,\n                        progress=lambda i, total, msg: ot_log(f\"  {i}/{total}: {msg}\", C[\"text_dim\"]),\n                    )\n                    saved = result.get(\"count\", 0)\n                    ot_log(f\"\u2705 {saved} pages saved to: {out_dir}\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"Done!\", f\"\u2705 {saved} images saved!\\n\\n{out_dir}\"))\n                except Exception as ex:\n                    ot_log(f\"\u274c Error: {ex}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n            threading.Thread(target=_run, daemon=True).start()\n\n        tk.Button(c1b, text=\"\u25b6 Convert to Images\", font=FONTS[\"body\"],\n                  bg=C[\"accent\"], fg=C[\"bg\"], bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=_do_pdf2img).pack(anchor=\"w\", pady=(6,0))\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # TAB 2 \u2014 PDF Operations\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        t2 = tk.Frame(content_host, bg=C[\"bg\"])\n        self._office_tab_frames[\"pdf_ops\"] = t2\n\n        # \u2500\u2500 PDF Merge \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        c2a = _make_card(t2, \"\ud83d\udcce  PDF Merge  (multiple PDFs \u2192 ek PDF)\")\n        tk.Label(c2a, text=\"PDFs select karo (order matters):\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\")\n\n        self._ot_merge_list = tk.Listbox(c2a, bg=C[\"bg\"], fg=C[\"text\"], font=FONTS[\"small\"],\n                                          height=4, selectmode=\"extended\",\n                                          selectbackground=C[\"accent\"], activestyle=\"none\")\n        self._ot_merge_list.pack(fill=\"x\", pady=4)\n\n        mr = tk.Frame(c2a, bg=C[\"card\"])\n        mr.pack(fill=\"x\")\n        def _merge_add():\n            files = filedialog.askopenfilenames(filetypes=[(\"PDF\",\"*.pdf\"),(\"All\",\"*.*\")])\n            for f in files:\n                self._ot_merge_list.insert(\"end\", f)\n        def _merge_remove():\n            for i in reversed(self._ot_merge_list.curselection()):\n                self._ot_merge_list.delete(i)\n        def _merge_up():\n            sel = self._ot_merge_list.curselection()\n            for i in sel:\n                if i == 0: continue\n                txt = self._ot_merge_list.get(i)\n                self._ot_merge_list.delete(i)\n                self._ot_merge_list.insert(i-1, txt)\n                self._ot_merge_list.selection_set(i-1)\n        def _merge_down():\n            sel = list(self._ot_merge_list.curselection())\n            for i in reversed(sel):\n                if i &gt;= self._ot_merge_list.size()-1: continue\n                txt = self._ot_merge_list.get(i)\n                self._ot_merge_list.delete(i)\n                self._ot_merge_list.insert(i+1, txt)\n                self._ot_merge_list.selection_set(i+1)\n\n        for txt, cmd in [(\"+ Add PDFs\", _merge_add), (\"\u2715 Remove\", _merge_remove),\n                          (\"\u2191 Up\", _merge_up), (\"\u2193 Down\", _merge_down)]:\n            tk.Button(mr, text=txt, font=FONTS[\"small\"], bg=C[\"btn_info\"], fg=C[\"text\"],\n                      bd=0, padx=8, pady=4, cursor=\"hand2\", command=cmd).pack(side=\"left\", padx=3)\n\n        def _do_merge():\n            files = list(self._ot_merge_list.get(0, \"end\"))\n            if len(files) &lt; 2:\n                messagebox.showwarning(\"Warning\", \"Kam se kam 2 PDFs add karo.\")\n                return\n            out = filedialog.asksaveasfilename(title=\"Merged PDF save karein\",\n                                               defaultextension=\".pdf\",\n                                               filetypes=[(\"PDF\",\"*.pdf\")])\n            if not out:\n                return\n            def _run():\n                try:\n                    if not _ensure_pkg(\"pikepdf\"):\n                        return\n                    import pikepdf\n                    pdf_out = pikepdf.Pdf.new()\n                    for f in files:\n                        with pikepdf.open(f) as src:\n                            pdf_out.pages.extend(src.pages)\n                    pdf_out.save(out)\n                    ot_log(f\"\u2705 Merged {len(files)} PDFs \u2192 {out}\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"Done!\", f\"\u2705 {len(files)} PDFs merge ho gaye!\\n\\n{out}\"))\n                except Exception as ex:\n                    ot_log(f\"\u274c Merge error: {ex}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n            threading.Thread(target=_run, daemon=True).start()\n\n        tk.Button(c2a, text=\"\u25b6 Merge PDFs\", font=FONTS[\"body\"],\n                  bg=C[\"accent\"], fg=C[\"bg\"], bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=_do_merge).pack(anchor=\"w\", pady=(6,0))\n\n        # \u2500\u2500 PDF Split \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        c2b = _make_card(t2, \"\u2702\ufe0f  PDF Split  (ek PDF \u2192 alag alag pages ya ranges)\")\n        r2b = tk.Frame(c2b, bg=C[\"card\"])\n        r2b.pack(fill=\"x\")\n        tk.Label(r2b, text=\"PDF:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_split_path = tk.StringVar()\n        tk.Entry(r2b, textvariable=self._ot_split_path, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=46).pack(side=\"left\", padx=4)\n        tk.Button(r2b, text=\"Browse\u2026\", font=FONTS[\"small\"], bg=C[\"btn_info\"],\n                  fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=lambda: self._ot_split_path.set(\n                      filedialog.askopenfilename(filetypes=[(\"PDF\",\"*.pdf\"),(\"All\",\"*.*\")]))).pack(side=\"left\")\n\n        r2b2 = tk.Frame(c2b, bg=C[\"card\"])\n        r2b2.pack(fill=\"x\", pady=4)\n        tk.Label(r2b2, text=\"Mode:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_split_mode = tk.StringVar(value=\"all\")\n        tk.Radiobutton(r2b2, text=\"Har page alag file\", variable=self._ot_split_mode, value=\"all\",\n                       font=FONTS[\"small\"], bg=C[\"card\"], fg=C[\"text\"],\n                       selectcolor=C[\"bg\"], activebackground=C[\"card\"]).pack(side=\"left\", padx=6)\n        tk.Radiobutton(r2b2, text=\"Range (e.g. 1-3, 5, 7-9):\", variable=self._ot_split_mode, value=\"range\",\n                       font=FONTS[\"small\"], bg=C[\"card\"], fg=C[\"text\"],\n                       selectcolor=C[\"bg\"], activebackground=C[\"card\"]).pack(side=\"left\")\n        self._ot_split_range = tk.StringVar(value=\"1-3, 4-6\")\n        tk.Entry(r2b2, textvariable=self._ot_split_range, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=18).pack(side=\"left\", padx=4)\n\n        def _parse_ranges(text, total):\n            pages = set()\n            for part in text.split(\",\"):\n                part = part.strip()\n                if \"-\" in part:\n                    try:\n                        a, b = part.split(\"-\")\n                        pages.update(range(int(a)-1, int(b)))\n                    except Exception:\n                        pass\n                else:\n                    try:\n                        pages.add(int(part)-1)\n                    except Exception:\n                        pass\n            return sorted(p for p in pages if 0 &lt;= p &lt; total)\n\n        def _do_split():\n            pdf_path = self._ot_split_path.get().strip()\n            if not pdf_path or not os.path.isfile(pdf_path):\n                messagebox.showwarning(\"Warning\", \"Valid PDF select karo.\")\n                return\n            out_dir = filedialog.askdirectory(title=\"Output folder choose karo\")\n            if not out_dir:\n                return\n            mode = self._ot_split_mode.get()\n            def _run():\n                try:\n                    if not _ensure_pkg(\"pikepdf\"):\n                        return\n                    import pikepdf\n                    base = os.path.splitext(os.path.basename(pdf_path))[0]\n                    with pikepdf.open(pdf_path) as src:\n                        total = len(src.pages)\n                        if mode == \"all\":\n                            page_groups = [(i, [i]) for i in range(total)]\n                        else:\n                            idxs = _parse_ranges(self._ot_split_range.get(), total)\n                            if not idxs:\n                                ot_log(\"\u274c Range invalid hai.\", C[\"error\"]); return\n                            # Split on commas \u2192 each comma-segment = one file\n                            raw_parts = [p.strip() for p in self._ot_split_range.get().split(\",\") if p.strip()]\n                            page_groups = []\n                            for seg in raw_parts:\n                                grp = _parse_ranges(seg, total)\n                                page_groups.append((seg, grp))\n                        saved = 0\n                        for label, pages in page_groups:\n                            if not pages:\n                                continue\n                            out_pdf = pikepdf.Pdf.new()\n                            for idx in pages:\n                                out_pdf.pages.append(src.pages[idx])\n                            out_name = f\"{base}_p{label}.pdf\" if mode == \"range\" else f\"{base}_page{label+1:04d}.pdf\"\n                            out_pdf.save(os.path.join(out_dir, out_name))\n                            saved += 1\n                    ot_log(f\"\u2705 Split done: {saved} files \u2192 {out_dir}\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"Done!\", f\"\u2705 {saved} files split!\\n\\n{out_dir}\"))\n                except Exception as ex:\n                    ot_log(f\"\u274c Split error: {ex}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n            threading.Thread(target=_run, daemon=True).start()\n\n        tk.Button(c2b, text=\"\u25b6 Split PDF\", font=FONTS[\"body\"],\n                  bg=C[\"accent\"], fg=C[\"bg\"], bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=_do_split).pack(anchor=\"w\", pady=(6,0))\n\n        # \u2500\u2500 PDF Rotate \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        c2c = _make_card(t2, \"\ud83d\udd04  PDF Rotate  (pages ko rotate karo)\")\n        r2c = tk.Frame(c2c, bg=C[\"card\"])\n        r2c.pack(fill=\"x\")\n        tk.Label(r2c, text=\"PDF:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_rot_path = tk.StringVar()\n        tk.Entry(r2c, textvariable=self._ot_rot_path, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=46).pack(side=\"left\", padx=4)\n        tk.Button(r2c, text=\"Browse\u2026\", font=FONTS[\"small\"], bg=C[\"btn_info\"],\n                  fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=lambda: self._ot_rot_path.set(\n                      filedialog.askopenfilename(filetypes=[(\"PDF\",\"*.pdf\"),(\"All\",\"*.*\")]))).pack(side=\"left\")\n        r2c2 = tk.Frame(c2c, bg=C[\"card\"])\n        r2c2.pack(fill=\"x\", pady=4)\n        tk.Label(r2c2, text=\"Rotation:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_rot_deg = tk.StringVar(value=\"90\")\n        for d in (\"90\", \"180\", \"270\"):\n            tk.Radiobutton(r2c2, text=f\"{d}\u00b0\", variable=self._ot_rot_deg, value=d,\n                           font=FONTS[\"small\"], bg=C[\"card\"], fg=C[\"text\"],\n                           selectcolor=C[\"bg\"], activebackground=C[\"card\"]).pack(side=\"left\", padx=8)\n        tk.Label(r2c2, text=\"  Pages (blank=all, e.g. 1,3,5):\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_rot_pages = tk.StringVar(value=\"\")\n        tk.Entry(r2c2, textvariable=self._ot_rot_pages, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=14).pack(side=\"left\", padx=4)\n\n        def _do_rotate():\n            pdf_path = self._ot_rot_path.get().strip()\n            if not pdf_path or not os.path.isfile(pdf_path):\n                messagebox.showwarning(\"Warning\",\"Valid PDF select karo.\"); return\n            out = filedialog.asksaveasfilename(title=\"Rotated PDF save karein\",\n                                               defaultextension=\".pdf\",\n                                               filetypes=[(\"PDF\",\"*.pdf\")])\n            if not out: return\n            deg = int(self._ot_rot_deg.get())\n            def _run():\n                try:\n                    if not _ensure_pkg(\"pikepdf\"): return\n                    import pikepdf\n                    pages_raw = self._ot_rot_pages.get().strip()\n                    with pikepdf.open(pdf_path) as pdf:\n                        total = len(pdf.pages)\n                        if pages_raw:\n                            idxs = set()\n                            for p in pages_raw.split(\",\"):\n                                try: idxs.add(int(p.strip())-1)\n                                except Exception: pass\n                        else:\n                            idxs = set(range(total))\n                        for i, page in enumerate(pdf.pages):\n                            if i in idxs:\n                                cur = int(page.get(\"/Rotate\", 0))\n                                page[\"/Rotate\"] = (cur + deg) % 360\n                        pdf.save(out)\n                    ot_log(f\"\u2705 Rotated {len(idxs)} pages by {deg}\u00b0 \u2192 {out}\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"Done!\", f\"\u2705 PDF rotated!\\n\\n{out}\"))\n                except Exception as ex:\n                    ot_log(f\"\u274c Rotate error: {ex}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n            threading.Thread(target=_run, daemon=True).start()\n\n        tk.Button(c2c, text=\"\u25b6 Rotate PDF\", font=FONTS[\"body\"],\n                  bg=C[\"accent\"], fg=C[\"bg\"], bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=_do_rotate).pack(anchor=\"w\", pady=(6,0))\n\n        # \u2500\u2500 PDF Compress \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        c2d = _make_card(t2, \"\ud83d\udce6  PDF Compress  (file size kam karo)\")\n        r2d = tk.Frame(c2d, bg=C[\"card\"])\n        r2d.pack(fill=\"x\")\n        tk.Label(r2d, text=\"PDF:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_comp_path = tk.StringVar()\n        tk.Entry(r2d, textvariable=self._ot_comp_path, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=46).pack(side=\"left\", padx=4)\n        tk.Button(r2d, text=\"Browse\u2026\", font=FONTS[\"small\"], bg=C[\"btn_info\"],\n                  fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=lambda: self._ot_comp_path.set(\n                      filedialog.askopenfilename(filetypes=[(\"PDF\",\"*.pdf\"),(\"All\",\"*.*\")]))).pack(side=\"left\")\n\n        def _do_compress():\n            pdf_path = self._ot_comp_path.get().strip()\n            if not pdf_path or not os.path.isfile(pdf_path):\n                messagebox.showwarning(\"Warning\",\"Valid PDF select karo.\"); return\n            out = filedialog.asksaveasfilename(title=\"Compressed PDF save karein\",\n                                               defaultextension=\".pdf\",\n                                               filetypes=[(\"PDF\",\"*.pdf\")])\n            if not out: return\n            def _run():\n                try:\n                    if not _ensure_pkg(\"pikepdf\"): return\n                    import pikepdf\n                    before = os.path.getsize(pdf_path)\n                    with pikepdf.open(pdf_path) as pdf:\n                        pdf.save(out, compress_streams=True, object_stream_mode=pikepdf.ObjectStreamMode.generate)\n                    after = os.path.getsize(out)\n                    saved_pct = max(0, (before-after)/before*100) if before else 0\n                    msg = (f\"\u2705 Compressed!\\n\"\n                           f\"Before: {_human_size(before)}\\n\"\n                           f\"After:  {_human_size(after)}\\n\"\n                           f\"Saved:  {saved_pct:.1f}%\")\n                    ot_log(msg, C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"Done!\", f\"{msg}\\n\\n{out}\"))\n                except Exception as ex:\n                    ot_log(f\"\u274c Compress error: {ex}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n            threading.Thread(target=_run, daemon=True).start()\n\n        tk.Button(c2d, text=\"\u25b6 Compress PDF\", font=FONTS[\"body\"],\n                  bg=C[\"accent\"], fg=C[\"bg\"], bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=_do_compress).pack(anchor=\"w\", pady=(6,0))\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # TAB 3 \u2014 Office Converter\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        t3 = tk.Frame(content_host, bg=C[\"bg\"])\n        self._office_tab_frames[\"office_conv\"] = t3\n\n        tk.Label(t3, text=\"  \u2139\ufe0f  Office Converter requires Microsoft Office (Word/Excel) to be installed.\",\n                 font=FONTS[\"small\"], fg=C[\"accent4\"], bg=C[\"bg\"]).pack(anchor=\"w\", padx=16, pady=(8,2))\n        tk.Label(t3, text=\"  PDF \u2192 Word/Excel uses python-docx + openpyxl (no Office needed).\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"]).pack(anchor=\"w\", padx=16, pady=(0,4))\n\n        # \u2500\u2500 DOC/DOCX/XLS/XLSX/PPT/PPTX \u2192 PDF via Word/Excel COM \u2500\n        c3a = _make_card(t3, \"\ud83d\udcdd  Office File \u2192 PDF  (Word / Excel / PowerPoint)\")\n        r3a = tk.Frame(c3a, bg=C[\"card\"])\n        r3a.pack(fill=\"x\")\n        tk.Label(r3a, text=\"File:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_o2p_path = tk.StringVar()\n        tk.Entry(r3a, textvariable=self._ot_o2p_path, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=46).pack(side=\"left\", padx=4)\n        tk.Button(r3a, text=\"Browse\u2026\", font=FONTS[\"small\"], bg=C[\"btn_info\"],\n                  fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=lambda: self._ot_o2p_path.set(\n                      filedialog.askopenfilename(\n                          filetypes=[(\"Office files\",\"*.doc *.docx *.xls *.xlsx *.ppt *.pptx *.odt *.ods *.odp\"),\n                                     (\"All\",\"*.*\")]))).pack(side=\"left\")\n\n        def _do_office2pdf():\n            src = self._ot_o2p_path.get().strip()\n            if not src or not os.path.isfile(src):\n                messagebox.showwarning(\"Warning\",\"Valid Office file select karo.\"); return\n            out = filedialog.asksaveasfilename(title=\"Output PDF save karein\",\n                                               defaultextension=\".pdf\",\n                                               filetypes=[(\"PDF\",\"*.pdf\")])\n            if not out: return\n            def _run():\n                try:\n                    src_abs = os.path.abspath(src)\n                    out_abs = os.path.abspath(out)\n                    ext = os.path.splitext(src_abs)[1].lower()\n                    try:\n                        ot_log(\"LibreOffice offline engine se convert ho raha hai...\", C[\"text_dim\"])\n                        offline_office_to_pdf(src_abs, out_abs, timeout=180)\n                        ot_log(f\"OK LibreOffice convert done -&gt; {out_abs}\", C[\"success\"])\n                        self.after(0, lambda: messagebox.showinfo(\"Done!\", f\"PDF ready!\\n\\n{out_abs}\"))\n                        return\n                    except Exception as lo_ex:\n                        ot_log(f\"LibreOffice unavailable/failed: {lo_ex}\", C[\"warning\"])\n\n                    try:\n                        offline_office_com_to_pdf(src_abs, out_abs)\n                        ot_log(f\"OK Microsoft Office COM convert done -&gt; {out_abs}\", C[\"success\"])\n                        self.after(0, lambda: messagebox.showinfo(\"Done!\", f\"PDF ready!\\n\\n{out_abs}\"))\n                        return\n                    except Exception as com_ex:\n                        ot_log(f\"Microsoft Office COM unavailable/failed: {com_ex}\", C[\"warning\"])\n\n                    raise RuntimeError(\"No local Office PDF engine available. Install LibreOffice or Microsoft Office.\")\n\n                    # Try LibreOffice first (free)\n                    lo_paths = [\n                        r\"C:\\Program Files\\LibreOffice\\program\\soffice.exe\",\n                        r\"C:\\Program Files (x86)\\LibreOffice\\program\\soffice.exe\",\n                    ]\n                    lo_found = None  # handled by offline_office_to_pdf above\n                    if lo_found:\n                        ot_log(\"LibreOffice se convert ho raha hai\u2026\", C[\"text_dim\"])\n                        tmp_dir = tempfile.mkdtemp()\n                        res = safe_run([lo_found, \"--headless\", \"--convert-to\", \"pdf\",\n                                        \"--outdir\", tmp_dir, src_abs], timeout=120)\n                        gen = os.path.join(tmp_dir, os.path.splitext(os.path.basename(src_abs))[0]+\".pdf\")\n                        if os.path.isfile(gen):\n                            shutil.move(gen, out_abs)\n                            ot_log(f\"\u2705 LibreOffice convert done \u2192 {out_abs}\", C[\"success\"])\n                            self.after(0, lambda: messagebox.showinfo(\"Done!\", f\"\u2705 PDF ready!\\n\\n{out_abs}\"))\n                            return\n                    # COM automation fallback (MS Office required)\n                    try:\n                        import win32com.client\n                    except ImportError:\n                        _ensure_pkg(\"win32com\", \"pywin32\")\n                        import win32com.client\n\n                    if ext in (\".doc\", \".docx\", \".odt\"):\n                        app_prog = \"Word.Application\"\n                        wdFormatPDF = 17\n                        word = win32com.client.DispatchEx(app_prog)\n                        word.Visible = False\n                        try:\n                            doc = word.Documents.Open(src_abs)\n                            doc.SaveAs(out_abs, FileFormat=wdFormatPDF)\n                            doc.Close()\n                        finally:\n                            word.Quit()\n                        ot_log(f\"\u2705 Word \u2192 PDF: {out_abs}\", C[\"success\"])\n                    elif ext in (\".xls\", \".xlsx\", \".ods\"):\n                        xl = win32com.client.DispatchEx(\"Excel.Application\")\n                        xl.Visible = False\n                        try:\n                            wb = xl.Workbooks.Open(src_abs)\n                            wb.ExportAsFixedFormat(0, out_abs)\n                            wb.Close(False)\n                        finally:\n                            xl.Quit()\n                        ot_log(f\"\u2705 Excel \u2192 PDF: {out_abs}\", C[\"success\"])\n                    elif ext in (\".ppt\", \".pptx\", \".odp\"):\n                        pp = win32com.client.DispatchEx(\"PowerPoint.Application\")\n                        pp.Visible = True\n                        try:\n                            prs = pp.Presentations.Open(src_abs, WithWindow=False)\n                            prs.SaveAs(out_abs, 32)   # ppSaveAsPDF = 32\n                            prs.Close()\n                        finally:\n                            pp.Quit()\n                        ot_log(f\"\u2705 PowerPoint \u2192 PDF: {out_abs}\", C[\"success\"])\n                    else:\n                        ot_log(\"\u274c Format supported nahi hai COM automation ke liye.\", C[\"error\"])\n                        return\n                    self.after(0, lambda: messagebox.showinfo(\"Done!\", f\"\u2705 PDF ready!\\n\\n{out_abs}\"))\n                except Exception as ex:\n                    ot_log(f\"Convert error: {ex}\\n(Tip: LibreOffice ya Microsoft Office local/offline install chahiye)\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\",\n                        f\"{ex}\\n\\nTip: LibreOffice ya Microsoft Office local/offline install karke dobara try karo.\"))\n            if getattr(self, \"worker_manager\", None):\n                self.worker_manager.submit(_run, name=\"office_to_pdf\")\n            else:\n                threading.Thread(target=_run, daemon=True).start()\n\n        tk.Button(c3a, text=\"\u25b6 Convert to PDF\", font=FONTS[\"body\"],\n                  bg=C[\"accent\"], fg=C[\"bg\"], bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=_do_office2pdf).pack(anchor=\"w\", pady=(6,0))\n\n        # \u2500\u2500 PDF \u2192 Word (text extraction) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        c3b = _make_card(t3, \"\ud83d\udcc4\u2192\ud83d\udcdd  PDF \u2192 Word  (text extraction \u2014 python-docx)\")\n        r3b = tk.Frame(c3b, bg=C[\"card\"])\n        r3b.pack(fill=\"x\")\n        tk.Label(r3b, text=\"PDF:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_p2w_path = tk.StringVar()\n        tk.Entry(r3b, textvariable=self._ot_p2w_path, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=46).pack(side=\"left\", padx=4)\n        tk.Button(r3b, text=\"Browse\u2026\", font=FONTS[\"small\"], bg=C[\"btn_info\"],\n                  fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=lambda: self._ot_p2w_path.set(\n                      filedialog.askopenfilename(filetypes=[(\"PDF\",\"*.pdf\"),(\"All\",\"*.*\")]))).pack(side=\"left\")\n\n        def _do_pdf2word():\n            pdf_path = self._ot_p2w_path.get().strip()\n            if not pdf_path or not os.path.isfile(pdf_path):\n                messagebox.showwarning(\"Warning\",\"Valid PDF select karo.\"); return\n            out = filedialog.asksaveasfilename(title=\"Word file save karein\",\n                                               defaultextension=\".docx\",\n                                               filetypes=[(\"Word\",\"*.docx\")])\n            if not out: return\n            def _run():\n                try:\n                    if not _ensure_pkg(\"pikepdf\"): return\n                    if not _ensure_pkg(\"docx\", \"python-docx\"): return\n                    import pikepdf, docx\n                    doc = docx.Document()\n                    doc.add_heading(\"PDF \u2192 Word Conversion\", 0)\n                    doc.add_paragraph(f\"Source: {pdf_path}\")\n                    doc.add_paragraph(\"\u2500\" * 60)\n                    # Text extraction via pikepdf content streams\n                    with pikepdf.open(pdf_path) as pdf:\n                        for page_num, page in enumerate(pdf.pages):\n                            doc.add_heading(f\"Page {page_num+1}\", level=2)\n                            try:\n                                raw = page.obj.get(\"/Contents\")\n                                if raw is None:\n                                    doc.add_paragraph(\"[Empty page]\")\n                                    continue\n                                contents = pdf.get_object(raw.objgen) if hasattr(raw, 'objgen') else raw\n                                if hasattr(contents, 'read_bytes'):\n                                    data = contents.read_bytes()\n                                elif hasattr(contents, '__iter__'):\n                                    data = b\"\".join(s.read_bytes() for s in contents if hasattr(s, 'read_bytes'))\n                                else:\n                                    data = b\"\"\n                                try:\n                                    data = zlib.decompress(data)\n                                except Exception:\n                                    pass\n                                text_bits = re.findall(rb'\\(([^)]*)\\)', data)\n                                plain = \" \".join(b.decode(\"latin-1\", errors=\"replace\") for b in text_bits)\n                                doc.add_paragraph(plain[:4000] or \"[Could not extract text \u2014 scanned PDF?]\")\n                            except Exception as pe:\n                                doc.add_paragraph(f\"[Page extract error: {pe}]\")\n                    doc.save(out)\n                    ot_log(f\"\u2705 PDF \u2192 Word done: {out}\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"Done!\",\n                        f\"\u2705 Word file ready!\\n\\n{out}\\n\\n\"\n                        \"Note: Scanned PDFs ke liye OCR (Tesseract) ki zaroorat hoti hai.\"))\n                except Exception as ex:\n                    ot_log(f\"\u274c PDF\u2192Word error: {ex}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n            threading.Thread(target=_run, daemon=True).start()\n\n        tk.Button(c3b, text=\"\u25b6 PDF \u2192 Word\", font=FONTS[\"body\"],\n                  bg=C[\"accent\"], fg=C[\"bg\"], bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=_do_pdf2word).pack(anchor=\"w\", pady=(6,0))\n\n        # \u2500\u2500 PDF \u2192 Excel (table extraction) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        c3c = _make_card(t3, \"\ud83d\udcc4\u2192\ud83d\udcca  PDF \u2192 Excel  (table/text extraction \u2014 openpyxl)\")\n        r3c = tk.Frame(c3c, bg=C[\"card\"])\n        r3c.pack(fill=\"x\")\n        tk.Label(r3c, text=\"PDF:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_p2x_path = tk.StringVar()\n        tk.Entry(r3c, textvariable=self._ot_p2x_path, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=46).pack(side=\"left\", padx=4)\n        tk.Button(r3c, text=\"Browse\u2026\", font=FONTS[\"small\"], bg=C[\"btn_info\"],\n                  fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=lambda: self._ot_p2x_path.set(\n                      filedialog.askopenfilename(filetypes=[(\"PDF\",\"*.pdf\"),(\"All\",\"*.*\")]))).pack(side=\"left\")\n\n        def _do_pdf2excel():\n            pdf_path = self._ot_p2x_path.get().strip()\n            if not pdf_path or not os.path.isfile(pdf_path):\n                messagebox.showwarning(\"Warning\",\"Valid PDF select karo.\"); return\n            out = filedialog.asksaveasfilename(title=\"Excel file save karein\",\n                                               defaultextension=\".xlsx\",\n                                               filetypes=[(\"Excel\",\"*.xlsx\")])\n            if not out: return\n            def _run():\n                try:\n                    if not _ensure_pkg(\"pikepdf\"): return\n                    if not _ensure_pkg(\"openpyxl\"): return\n                    import pikepdf, openpyxl\n                    wb = openpyxl.Workbook()\n                    with pikepdf.open(pdf_path) as pdf:\n                        for page_num, page in enumerate(pdf.pages):\n                            ws = wb.create_sheet(title=f\"Page {page_num+1}\")\n                            ws.append([f\"=== PDF Page {page_num+1} ===\"])\n                            try:\n                                raw = page.obj.get(\"/Contents\")\n                                if raw is None:\n                                    ws.append([\"[Empty page]\"]); continue\n                                contents = pdf.get_object(raw.objgen) if hasattr(raw,'objgen') else raw\n                                if hasattr(contents,'read_bytes'):\n                                    data = contents.read_bytes()\n                                elif hasattr(contents,'__iter__'):\n                                    data = b\"\".join(s.read_bytes() for s in contents if hasattr(s,'read_bytes'))\n                                else:\n                                    data = b\"\"\n                                try: data = zlib.decompress(data)\n                                except Exception: pass\n                                text_bits = re.findall(rb'\\(([^)]*)\\)', data)\n                                lines = \" \".join(b.decode(\"latin-1\",errors=\"replace\") for b in text_bits)\n                                for row in lines.split(\"  \"):\n                                    row = row.strip()\n                                    if row:\n                                        ws.append([row])\n                            except Exception as pe:\n                                ws.append([f\"[Error: {pe}]\"])\n                    if \"Sheet\" in wb.sheetnames:\n                        del wb[\"Sheet\"]\n                    wb.save(out)\n                    ot_log(f\"\u2705 PDF \u2192 Excel done: {out}\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"Done!\",\n                        f\"\u2705 Excel ready!\\n\\n{out}\\n\\n\"\n                        \"Tip: Complex tables ke liye Tabula-py try karo.\"))\n                except Exception as ex:\n                    ot_log(f\"\u274c PDF\u2192Excel error: {ex}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n            threading.Thread(target=_run, daemon=True).start()\n\n        tk.Button(c3c, text=\"\u25b6 PDF \u2192 Excel\", font=FONTS[\"body\"],\n                  bg=C[\"accent\"], fg=C[\"bg\"], bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=_do_pdf2excel).pack(anchor=\"w\", pady=(6,0))\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # TAB 4 \u2014 Office File Repair\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        t4 = tk.Frame(content_host, bg=C[\"bg\"])\n        self._office_tab_frames[\"file_repair\"] = t4\n\n        # \u2500\u2500 Info banner \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        info_bar = tk.Frame(t4, bg=C[\"panel\"])\n        info_bar.pack(fill=\"x\", padx=16, pady=8)\n        tk.Label(info_bar,\n                 text=(\"  \ud83d\udd27  Office File Repair Engine\\n\"\n                       \"  DOCX/XLSX/PPTX = ZIP-based repair (pikepdf/python-docx/openpyxl)\\n\"\n                       \"  PDF = cross-reference table rebuild (pikepdf)\\n\"\n                       \"  Corrupt/truncated files ke liye best-effort recovery\"),\n                 font=FONTS[\"small\"], fg=C[\"text\"], bg=C[\"panel\"],\n                 justify=\"left\").pack(anchor=\"w\", padx=10, pady=8)\n\n        # \u2500\u2500 DOCX Repair \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        c4a = _make_card(t4, \"\ud83d\udcdd  Corrupt DOCX Repair\")\n        r4a = tk.Frame(c4a, bg=C[\"card\"])\n        r4a.pack(fill=\"x\")\n        tk.Label(r4a, text=\"Corrupt DOCX:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_fix_docx_path = tk.StringVar()\n        tk.Entry(r4a, textvariable=self._ot_fix_docx_path, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=44).pack(side=\"left\", padx=4)\n        tk.Button(r4a, text=\"Browse\u2026\", font=FONTS[\"small\"], bg=C[\"btn_info\"],\n                  fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=lambda: self._ot_fix_docx_path.set(\n                      filedialog.askopenfilename(filetypes=[(\"Word\",\"*.docx *.doc\"),(\"All\",\"*.*\")]))).pack(side=\"left\")\n\n        def _do_repair_docx():\n            src = self._ot_fix_docx_path.get().strip()\n            if not src or not os.path.isfile(src):\n                messagebox.showwarning(\"Warning\",\"Valid DOCX select karo.\"); return\n            out = filedialog.asksaveasfilename(title=\"Repaired DOCX save karein\",\n                                               defaultextension=\".docx\",\n                                               filetypes=[(\"Word\",\"*.docx\")])\n            if not out: return\n            def _run():\n                import zipfile\n                try:\n                    # Step 1: try python-docx direct open\n                    if not _ensure_pkg(\"docx\",\"python-docx\"): return\n                    import docx as _docx_mod\n                    try:\n                        doc = _docx_mod.Document(src)\n                        doc.save(out)\n                        ot_log(f\"\u2705 DOCX repair (direct): {out}\", C[\"success\"])\n                        self.after(0, lambda: messagebox.showinfo(\"Done!\", f\"\u2705 DOCX repaired!\\n\\n{out}\"))\n                        return\n                    except Exception as e1:\n                        ot_log(f\"  Direct open failed ({e1}), ZIP recovery try kar raha hai\u2026\", C[\"warning\"])\n\n                    # Step 2: ZIP-level recovery\n                    with zipfile.ZipFile(src, \"r\") as z:\n                        names = z.namelist()\n                    # Try to recover word/document.xml\n                    with zipfile.ZipFile(src, \"r\") as z_in:\n                        tmp_dir = tempfile.mkdtemp()\n                        recovered = []\n                        for name in names:\n                            try:\n                                data = z_in.read(name)\n                                dest = os.path.join(tmp_dir, name)\n                                os.makedirs(os.path.dirname(dest), exist_ok=True)\n                                with open(dest, \"wb\") as f:\n                                    f.write(data)\n                                recovered.append(name)\n                            except Exception:\n                                ot_log(f\"  \u26a0\ufe0f Skip: {name}\", C[\"warning\"])\n                    # Repack\n                    with zipfile.ZipFile(out, \"w\", compression=zipfile.ZIP_DEFLATED) as z_out:\n                        for name in recovered:\n                            z_out.write(os.path.join(tmp_dir, name), name)\n                    shutil.rmtree(tmp_dir, ignore_errors=True)\n                    ot_log(f\"\u2705 DOCX ZIP recovery: {len(recovered)}/{len(names)} parts saved \u2192 {out}\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"Done!\",\n                        f\"\u2705 DOCX ZIP repair done!\\n{len(recovered)}/{len(names)} parts recovered.\\n\\n{out}\"))\n                except Exception as ex:\n                    ot_log(f\"\u274c DOCX repair error: {ex}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n            threading.Thread(target=_run, daemon=True).start()\n\n        tk.Button(c4a, text=\"\u25b6 Repair DOCX\", font=FONTS[\"body\"],\n                  bg=C[\"warning\"], fg=C[\"bg\"], bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=_do_repair_docx).pack(anchor=\"w\", pady=(6,0))\n\n        # \u2500\u2500 XLSX Repair \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        c4b = _make_card(t4, \"\ud83d\udcca  Corrupt XLSX Repair\")\n        r4b = tk.Frame(c4b, bg=C[\"card\"])\n        r4b.pack(fill=\"x\")\n        tk.Label(r4b, text=\"Corrupt XLSX:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_fix_xlsx_path = tk.StringVar()\n        tk.Entry(r4b, textvariable=self._ot_fix_xlsx_path, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=44).pack(side=\"left\", padx=4)\n        tk.Button(r4b, text=\"Browse\u2026\", font=FONTS[\"small\"], bg=C[\"btn_info\"],\n                  fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=lambda: self._ot_fix_xlsx_path.set(\n                      filedialog.askopenfilename(filetypes=[(\"Excel\",\"*.xlsx *.xls\"),(\"All\",\"*.*\")]))).pack(side=\"left\")\n\n        def _do_repair_xlsx():\n            src = self._ot_fix_xlsx_path.get().strip()\n            if not src or not os.path.isfile(src):\n                messagebox.showwarning(\"Warning\",\"Valid XLSX select karo.\"); return\n            out = filedialog.asksaveasfilename(title=\"Repaired XLSX save karein\",\n                                               defaultextension=\".xlsx\",\n                                               filetypes=[(\"Excel\",\"*.xlsx\")])\n            if not out: return\n            def _run():\n                import zipfile\n                try:\n                    if not _ensure_pkg(\"openpyxl\"): return\n                    import openpyxl\n                    # Step 1: direct open\n                    try:\n                        wb = openpyxl.load_workbook(src, read_only=False, data_only=True, keep_links=False)\n                        wb.save(out)\n                        ot_log(f\"\u2705 XLSX repair (direct): {out}\", C[\"success\"])\n                        self.after(0, lambda: messagebox.showinfo(\"Done!\", f\"\u2705 XLSX repaired!\\n\\n{out}\"))\n                        return\n                    except Exception as e1:\n                        ot_log(f\"  Direct open failed ({e1}), ZIP recovery\u2026\", C[\"warning\"])\n                    # Step 2: ZIP recovery\n                    with zipfile.ZipFile(src,\"r\") as z:\n                        names = z.namelist()\n                    tmp_dir = tempfile.mkdtemp()\n                    recovered = []\n                    with zipfile.ZipFile(src,\"r\") as z_in:\n                        for name in names:\n                            try:\n                                data = z_in.read(name)\n                                dest = os.path.join(tmp_dir, name)\n                                os.makedirs(os.path.dirname(dest), exist_ok=True)\n                                with open(dest,\"wb\") as f: f.write(data)\n                                recovered.append(name)\n                            except Exception:\n                                ot_log(f\"  \u26a0\ufe0f Skip: {name}\", C[\"warning\"])\n                    with zipfile.ZipFile(out,\"w\",compression=zipfile.ZIP_DEFLATED) as z_out:\n                        for name in recovered:\n                            z_out.write(os.path.join(tmp_dir,name), name)\n                    shutil.rmtree(tmp_dir, ignore_errors=True)\n                    ot_log(f\"\u2705 XLSX ZIP recovery: {len(recovered)}/{len(names)} \u2192 {out}\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"Done!\",\n                        f\"\u2705 XLSX ZIP repair done!\\n{len(recovered)}/{len(names)} parts recovered.\\n\\n{out}\"))\n                except Exception as ex:\n                    ot_log(f\"\u274c XLSX repair error: {ex}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n            threading.Thread(target=_run, daemon=True).start()\n\n        tk.Button(c4b, text=\"\u25b6 Repair XLSX\", font=FONTS[\"body\"],\n                  bg=C[\"warning\"], fg=C[\"bg\"], bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=_do_repair_xlsx).pack(anchor=\"w\", pady=(6,0))\n\n        # \u2500\u2500 PDF Repair \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        c4c = _make_card(t4, \"\ud83d\udcc4  Corrupt PDF Repair  (cross-reference rebuild \u2014 pikepdf)\")\n        r4c = tk.Frame(c4c, bg=C[\"card\"])\n        r4c.pack(fill=\"x\")\n        tk.Label(r4c, text=\"Corrupt PDF:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_fix_pdf_path = tk.StringVar()\n        tk.Entry(r4c, textvariable=self._ot_fix_pdf_path, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=44).pack(side=\"left\", padx=4)\n        tk.Button(r4c, text=\"Browse\u2026\", font=FONTS[\"small\"], bg=C[\"btn_info\"],\n                  fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=lambda: self._ot_fix_pdf_path.set(\n                      filedialog.askopenfilename(filetypes=[(\"PDF\",\"*.pdf\"),(\"All\",\"*.*\")]))).pack(side=\"left\")\n\n        def _do_repair_pdf():\n            src = self._ot_fix_pdf_path.get().strip()\n            if not src or not os.path.isfile(src):\n                messagebox.showwarning(\"Warning\",\"Valid PDF select karo.\"); return\n            out = filedialog.asksaveasfilename(title=\"Repaired PDF save karein\",\n                                               defaultextension=\".pdf\",\n                                               filetypes=[(\"PDF\",\"*.pdf\")])\n            if not out: return\n            def _run():\n                try:\n                    if not _ensure_pkg(\"pikepdf\"): return\n                    import pikepdf\n                    before = os.path.getsize(src)\n                    with pikepdf.open(src, suppress_warnings=False,\n                                      allow_overwriting_input=False) as pdf:\n                        # pikepdf auto-rebuilds xref table on save\n                        pdf.save(out, fix_metadata_version=True,\n                                 compress_streams=True,\n                                 object_stream_mode=pikepdf.ObjectStreamMode.generate)\n                    after = os.path.getsize(out)\n                    ot_log(f\"\u2705 PDF repair done: {out}  ({_human_size(before)} \u2192 {_human_size(after)})\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"Done!\",\n                        f\"\u2705 PDF repaired!\\n\"\n                        f\"Before: {_human_size(before)}\\nAfter: {_human_size(after)}\\n\\n{out}\"))\n                except Exception as ex:\n                    ot_log(f\"\u274c PDF repair error: {ex}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n            threading.Thread(target=_run, daemon=True).start()\n\n        tk.Button(c4c, text=\"\u25b6 Repair PDF\", font=FONTS[\"body\"],\n                  bg=C[\"warning\"], fg=C[\"bg\"], bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=_do_repair_pdf).pack(anchor=\"w\", pady=(6,0))\n\n        # \u2500\u2500 PPTX Repair \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        c4d = _make_card(t4, \"\ud83d\udcca  Corrupt PPTX Repair  (PowerPoint ZIP recovery)\")\n        r4d = tk.Frame(c4d, bg=C[\"card\"])\n        r4d.pack(fill=\"x\")\n        tk.Label(r4d, text=\"Corrupt PPTX:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_fix_pptx_path = tk.StringVar()\n        tk.Entry(r4d, textvariable=self._ot_fix_pptx_path, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=44).pack(side=\"left\", padx=4)\n        tk.Button(r4d, text=\"Browse\u2026\", font=FONTS[\"small\"], bg=C[\"btn_info\"],\n                  fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=lambda: self._ot_fix_pptx_path.set(\n                      filedialog.askopenfilename(filetypes=[(\"PowerPoint\",\"*.pptx *.ppt\"),(\"All\",\"*.*\")]))).pack(side=\"left\")\n\n        def _do_repair_pptx():\n            src = self._ot_fix_pptx_path.get().strip()\n            if not src or not os.path.isfile(src):\n                messagebox.showwarning(\"Warning\",\"Valid PPTX select karo.\"); return\n            out = filedialog.asksaveasfilename(title=\"Repaired PPTX save karein\",\n                                               defaultextension=\".pptx\",\n                                               filetypes=[(\"PowerPoint\",\"*.pptx\")])\n            if not out: return\n            def _run():\n                import zipfile\n                try:\n                    with zipfile.ZipFile(src,\"r\") as z:\n                        names = z.namelist()\n                    tmp_dir = tempfile.mkdtemp()\n                    recovered = []\n                    with zipfile.ZipFile(src,\"r\") as z_in:\n                        for name in names:\n                            try:\n                                data = z_in.read(name)\n                                dest = os.path.join(tmp_dir,name)\n                                os.makedirs(os.path.dirname(dest),exist_ok=True)\n                                with open(dest,\"wb\") as f: f.write(data)\n                                recovered.append(name)\n                            except Exception:\n                                ot_log(f\"  \u26a0\ufe0f Skip: {name}\", C[\"warning\"])\n                    with zipfile.ZipFile(out,\"w\",compression=zipfile.ZIP_DEFLATED) as z_out:\n                        for name in recovered:\n                            z_out.write(os.path.join(tmp_dir,name), name)\n                    shutil.rmtree(tmp_dir, ignore_errors=True)\n                    ot_log(f\"\u2705 PPTX repair: {len(recovered)}/{len(names)} parts \u2192 {out}\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"Done!\",\n                        f\"\u2705 PPTX repaired!\\n{len(recovered)}/{len(names)} parts recovered.\\n\\n{out}\"))\n                except Exception as ex:\n                    ot_log(f\"\u274c PPTX repair error: {ex}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n            threading.Thread(target=_run, daemon=True).start()\n\n        tk.Button(c4d, text=\"\u25b6 Repair PPTX\", font=FONTS[\"body\"],\n                  bg=C[\"warning\"], fg=C[\"bg\"], bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=_do_repair_pptx).pack(anchor=\"w\", pady=(6,0))\n\n        # \u2500\u2500 Activate first tab \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _switch_office_tab(\"img_pdf\")\n        return frame\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # EXCEL TOOLS SECTION\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _build_excel_tools(self, parent):\n        \"\"\"\n        Excel Tools:\n          Tab 1 \u2014 Format Conversion   (Excel\u2194CSV, sheet splitter)\n          Tab 2 \u2014 Data Cleaning       (duplicate rows, bulk formatter, password remove)\n          Tab 3 \u2014 Merge &amp; Audit       (bulk merge, formula auditor)\n          Tab 4 \u2014 DOCX Security       (password protect / remove Word files)\n        \"\"\"\n        import threading, zipfile\n\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n\n        # \u2500\u2500 Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        hdr = tk.Frame(frame, bg=C[\"panel\"])\n        hdr.pack(fill=\"x\")\n        tk.Label(hdr, text=\"  \ud83d\udcca Excel &amp; Word Tools\",\n                 font=FONTS[\"heading\"], fg=C[\"accent\"], bg=C[\"panel\"]).pack(side=\"left\", pady=10, padx=8)\n        tk.Label(hdr, text=\"CSV \u00b7 Merge \u00b7 Clean \u00b7 Audit \u00b7 Password  |  Offline local dependencies only\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"left\", pady=10)\n\n        # \u2500\u2500 Sub-tab bar \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        tab_bar = tk.Frame(frame, bg=C[\"card\"])\n        tab_bar.pack(fill=\"x\")\n        tk.Frame(tab_bar, bg=C[\"border\"], height=1).pack(side=\"bottom\", fill=\"x\")\n        content_host = tk.Frame(frame, bg=C[\"bg\"])\n        content_host.pack(fill=\"both\", expand=True)\n\n        _xt_frames = {}\n        _xt_btns   = {}\n\n        def _xt_switch(key):\n            for k, b in _xt_btns.items():\n                b.config(bg=C[\"accent\"] if k==key else C[\"panel\"],\n                         fg=C[\"bg\"]     if k==key else C[\"text\"])\n            for k, f in _xt_frames.items():\n                (f.pack if k==key else f.pack_forget)(fill=\"both\", expand=True) if k==key else f.pack_forget()\n\n        subtabs = [(\"conv\",\"\u21c4  Conversion\"), (\"clean\",\"\ud83e\uddf9  Data Clean\"),\n                   (\"merge\",\"\ud83d\udd17  Merge &amp; Audit\"), (\"security\",\"\ud83d\udd10  Security\")]\n        for key, label in subtabs:\n            b = tk.Button(tab_bar, text=label, font=FONTS[\"body\"],\n                          bg=C[\"panel\"], fg=C[\"text\"], bd=0, padx=18, pady=8, cursor=\"hand2\",\n                          command=lambda k=key: _xt_switch(k))\n            b.pack(side=\"left\")\n            _xt_btns[key] = b\n\n        # \u2500\u2500 Shared log \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        log_host = tk.Frame(frame, bg=C[\"card\"])\n        log_host.pack(fill=\"x\", side=\"bottom\")\n        tk.Label(log_host, text=\"  Activity Log\", font=FONTS[\"small\"],\n                 fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=8, pady=(5,0))\n        _xt_log_w = scrolledtext.ScrolledText(log_host, height=4, state=\"disabled\",\n                                               bg=C[\"bg\"], fg=C[\"text\"], font=FONTS[\"small\"], bd=0)\n        _xt_log_w.pack(fill=\"x\", padx=8, pady=(2,6))\n\n        def xt_log(msg, color=None):\n            ts = datetime.datetime.now().strftime(\"%H:%M:%S\")\n            _xt_log_w.config(state=\"normal\")\n            tag = f\"t{abs(hash(color or ''))}\"\n            _xt_log_w.tag_config(tag, foreground=color or C[\"text\"])\n            _xt_log_w.insert(\"end\", f\"[{ts}] {msg}\\n\", tag)\n            _xt_log_w.see(\"end\")\n            _xt_log_w.config(state=\"disabled\")\n\n        def _xpkg(imp, pip=None):\n            pip = pip or imp\n            try: __import__(imp); return True\n            except ImportError:\n                xt_log(f\"\u274c Missing local dependency: {pip}. Runtime download/install is disabled.\", C[\"error\"])\n                return False\n\n        def _card(par, title):\n            c = tk.Frame(par, bg=C[\"card\"])\n            c.pack(fill=\"x\", padx=16, pady=10)\n            tk.Label(c, text=title, font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=10, pady=(8,4))\n            tk.Frame(c, bg=C[\"border\"], height=1).pack(fill=\"x\", padx=10)\n            b = tk.Frame(c, bg=C[\"card\"])\n            b.pack(fill=\"x\", padx=10, pady=10)\n            return b\n\n        def _row(par): r=tk.Frame(par,bg=C[\"card\"]); r.pack(fill=\"x\",pady=3); return r\n        def _lbl(par,txt): tk.Label(par,text=txt,font=FONTS[\"small\"],fg=C[\"text_dim\"],bg=C[\"card\"]).pack(side=\"left\",padx=(0,4))\n        def _entry(par,var,w=44): return tk.Entry(par,textvariable=var,font=FONTS[\"small\"],bg=C[\"bg\"],fg=C[\"text\"],insertbackground=C[\"text\"],width=w)\n        def _browse_btn(par,cmd): tk.Button(par,text=\"Browse\u2026\",font=FONTS[\"small\"],bg=C[\"btn_info\"],fg=C[\"text\"],bd=0,padx=8,pady=3,cursor=\"hand2\",command=cmd).pack(side=\"left\",padx=4)\n        def _action_btn(par,txt,cmd,color=None): tk.Button(par,text=txt,font=FONTS[\"body\"],bg=color or C[\"accent\"],fg=C[\"bg\"],bd=0,padx=14,pady=6,cursor=\"hand2\",command=cmd).pack(anchor=\"w\",pady=(8,2))\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # TAB 1 \u2014 Conversion\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        t1 = tk.Frame(content_host, bg=C[\"bg\"])\n        _xt_frames[\"conv\"] = t1\n\n        # Excel \u2192 CSV\n        b1a = _card(t1, \"\ud83d\udce4  Excel \u2192 CSV  (each sheet = one CSV)\")\n        r = _row(b1a); _lbl(r,\"XLSX:\"); v1a=tk.StringVar(); _entry(r,v1a).pack(side=\"left\",padx=4)\n        _browse_btn(r, lambda: v1a.set(filedialog.askopenfilename(filetypes=[(\"Excel\",\"*.xlsx *.xls\"),(\"All\",\"*.*\")])))\n        def _do_xl2csv():\n            src=v1a.get().strip()\n            if not src or not os.path.isfile(src): messagebox.showwarning(\"\",\"Valid XLSX select karo.\"); return\n            out_dir=filedialog.askdirectory(title=\"Output folder\")\n            if not out_dir: return\n            def _r():\n                try:\n                    if not _xpkg(\"openpyxl\"): return\n                    import openpyxl\n                    wb=openpyxl.load_workbook(src,data_only=True)\n                    saved=0\n                    for sh in wb.sheetnames:\n                        ws=wb[sh]\n                        out_path=os.path.join(out_dir,f\"{os.path.splitext(os.path.basename(src))[0]}_{sh}.csv\")\n                        with open(out_path,\"w\",newline=\"\",encoding=\"utf-8-sig\") as f:\n                            import csv as _csv\n                            w=_csv.writer(f)\n                            for row in ws.iter_rows(values_only=True): w.writerow([c if c is not None else \"\" for c in row])\n                        saved+=1\n                    xt_log(f\"\u2705 {saved} CSV files \u2192 {out_dir}\", C[\"success\"])\n                    self.after(0,lambda: messagebox.showinfo(\"Done!\",f\"\u2705 {saved} sheets exported!\\n{out_dir}\"))\n                except Exception as ex: xt_log(f\"\u274c {ex}\",C[\"error\"]); self.after(0,lambda: messagebox.showerror(\"Error\",str(ex)))\n            threading.Thread(target=_r,daemon=True).start()\n        _action_btn(b1a,\"\u25b6 Excel \u2192 CSV\",_do_xl2csv)\n\n        # CSV \u2192 Excel\n        b1b = _card(t1, \"\ud83d\udce5  CSV \u2192 Excel  (multiple CSVs \u2192 one XLSX, each = sheet)\")\n        r=_row(b1b); _lbl(r,\"CSVs:\"); v1b=tk.StringVar(); _entry(r,v1b,52).pack(side=\"left\",padx=4)\n        _browse_btn(r,lambda: v1b.set(\";\".join(filedialog.askopenfilenames(filetypes=[(\"CSV\",\"*.csv\"),(\"All\",\"*.*\")]))))\n        def _do_csv2xl():\n            files=[f.strip() for f in v1b.get().split(\";\") if f.strip()]\n            if not files: messagebox.showwarning(\"\",\"CSV select karo.\"); return\n            out=filedialog.asksaveasfilename(title=\"Output XLSX\",defaultextension=\".xlsx\",filetypes=[(\"Excel\",\"*.xlsx\")])\n            if not out: return\n            def _r():\n                try:\n                    if not _xpkg(\"openpyxl\"): return\n                    import openpyxl, csv as _csv\n                    wb=openpyxl.Workbook()\n                    wb.remove(wb.active)\n                    for f in files:\n                        sh_name=os.path.splitext(os.path.basename(f))[0][:31]\n                        ws=wb.create_sheet(title=sh_name)\n                        with open(f,newline=\"\",encoding=\"utf-8-sig\",errors=\"replace\") as fh:\n                            for row in _csv.reader(fh): ws.append(row)\n                    wb.save(out)\n                    xt_log(f\"\u2705 {len(files)} CSVs \u2192 {out}\",C[\"success\"])\n                    self.after(0,lambda: messagebox.showinfo(\"Done!\",f\"\u2705 Excel ready!\\n{out}\"))\n                except Exception as ex: xt_log(f\"\u274c {ex}\",C[\"error\"]); self.after(0,lambda: messagebox.showerror(\"Error\",str(ex)))\n            threading.Thread(target=_r,daemon=True).start()\n        _action_btn(b1b,\"\u25b6 CSV \u2192 Excel\",_do_csv2xl)\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # TAB 2 \u2014 Data Cleaning\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        t2 = tk.Frame(content_host, bg=C[\"bg\"])\n        _xt_frames[\"clean\"] = t2\n\n        # Duplicate row remover\n        b2a = _card(t2, \"\ud83e\uddf9  Duplicate Row Finder &amp; Remover\")\n        r=_row(b2a); _lbl(r,\"XLSX:\"); v2a=tk.StringVar(); _entry(r,v2a).pack(side=\"left\",padx=4)\n        _browse_btn(r,lambda: v2a.set(filedialog.askopenfilename(filetypes=[(\"Excel\",\"*.xlsx\"),(\"All\",\"*.*\")])))\n        r2=_row(b2a); _lbl(r2,\"Sheet name (blank=first):\"); v2a_sh=tk.StringVar(); _entry(r2,v2a_sh,16).pack(side=\"left\",padx=4)\n        _lbl(r2,\"  Key columns (e.g. A,B or blank=all):\"); v2a_col=tk.StringVar(); _entry(r2,v2a_col,14).pack(side=\"left\",padx=4)\n        self._xt_dup_mode = tk.StringVar(value=\"remove\")\n        r3=_row(b2a)\n        tk.Radiobutton(r3,text=\"Remove duplicates\",variable=self._xt_dup_mode,value=\"remove\",\n                       font=FONTS[\"small\"],bg=C[\"card\"],fg=C[\"text\"],selectcolor=C[\"bg\"],activebackground=C[\"card\"]).pack(side=\"left\",padx=6)\n        tk.Radiobutton(r3,text=\"Only mark/highlight\",variable=self._xt_dup_mode,value=\"mark\",\n                       font=FONTS[\"small\"],bg=C[\"card\"],fg=C[\"text\"],selectcolor=C[\"bg\"],activebackground=C[\"card\"]).pack(side=\"left\",padx=6)\n\n        def _do_dedup():\n            src=v2a.get().strip()\n            if not src or not os.path.isfile(src): messagebox.showwarning(\"\",\"Valid XLSX select karo.\"); return\n            out=filedialog.asksaveasfilename(title=\"Output XLSX\",defaultextension=\".xlsx\",filetypes=[(\"Excel\",\"*.xlsx\")])\n            if not out: return\n            def _r():\n                try:\n                    if not _xpkg(\"openpyxl\"): return\n                    import openpyxl\n                    from openpyxl.styles import PatternFill\n                    wb=openpyxl.load_workbook(src)\n                    sh_name=v2a_sh.get().strip() or wb.sheetnames[0]\n                    ws=wb[sh_name]\n                    data=list(ws.iter_rows(values_only=False))\n                    if not data: xt_log(\"\u26a0\ufe0f Sheet empty.\",C[\"warning\"]); return\n                    col_raw=v2a_col.get().strip()\n                    if col_raw:\n                        col_idxs=[ord(c.strip().upper())-65 for c in col_raw.split(\",\") if c.strip()]\n                    else:\n                        col_idxs=list(range(ws.max_column))\n                    seen=set(); dup_rows=[]; keep_rows=[]\n                    for i,row in enumerate(data):\n                        key=tuple((row[c].value if cmw:\n                                    img=img.resize((mw,int(img.height*mw/img.width)),Image.LANCZOS)\n                            base=os.path.splitext(os.path.basename(fp))[0]\n                            ext=\".jpg\" if fmt==\"JPEG\" else f\".{fmt.lower()}\"\n                            out_path=os.path.join(out_dir,f\"{base}{v1_suf.get()}{ext}\")\n                            save_kw={\"quality\":q} if fmt in (\"JPEG\",\"WEBP\") else {}\n                            img.convert(\"RGB\").save(out_path,fmt,**save_kw)\n                            done+=1\n                        except Exception as e: it_log(f\"\u26a0\ufe0f {fp}: {e}\",C[\"warning\"])\n                    it_log(f\"\u2705 {done}/{len(files)} images processed \u2192 {out_dir}\",C[\"success\"])\n                    self.after(0,lambda: messagebox.showinfo(\"Done!\",f\"\u2705 {done} images done!\\n{out_dir}\"))\n                except Exception as ex: it_log(f\"\u274c {ex}\",C[\"error\"]); self.after(0,lambda: messagebox.showerror(\"Error\",str(ex)))\n            threading.Thread(target=_r,daemon=True).start()\n        _abtn(b1,\"\u25b6 Resize &amp; Compress\",_do_resize)\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # TAB 2 \u2014 OCR\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        t2=tk.Frame(content_host,bg=C[\"bg\"]); _it_frames[\"ocr\"]=t2\n\n        b2=_card(t2,\"\ud83d\udcd6  OCR \u2014 Image / Screenshot \u2192 Text / Word / Excel\")\n        tk.Label(b2,text=\"\u26a0\ufe0f  Tesseract OCR pehle install karna hoga: https://github.com/UB-Mannheim/tesseract/wiki\",\n                 font=FONTS[\"small\"],fg=C[\"accent4\"],bg=C[\"card\"],cursor=\"hand2\").pack(anchor=\"w\",pady=(0,6))\n        r=_row(b2); _lbl(r,\"Images (multi-select):\"); v2_files=tk.StringVar(); _entry(r,v2_files,48)\n        _browse(r,lambda: v2_files.set(\";\".join(filedialog.askopenfilenames(\n            filetypes=[(\"Images\",\"*.jpg *.jpeg *.png *.bmp *.tiff *.webp\"),(\"All\",\"*.*\")]))))\n\n        r2=_row(b2)\n        _lbl(r2,\"Language:\"); v2_lang=tk.StringVar(value=\"eng+hin\")\n        for l in [(\"eng+hin\",\"Hindi+English\"),(\"eng\",\"English only\"),(\"hin\",\"Hindi only\")]:\n            tk.Radiobutton(r2,text=l[1],variable=v2_lang,value=l[0],font=FONTS[\"small\"],bg=C[\"card\"],fg=C[\"text\"],selectcolor=C[\"bg\"],activebackground=C[\"card\"]).pack(side=\"left\",padx=6)\n\n        r3=_row(b2); _lbl(r3,\"Output format:\"); v2_out=tk.StringVar(value=\"txt\")\n        for t,l in [(\"txt\",\"Plain Text\"),(\"docx\",\"Word DOCX\"),(\"xlsx\",\"Excel XLSX\")]:\n            tk.Radiobutton(r3,text=l,variable=v2_out,value=t,font=FONTS[\"small\"],bg=C[\"card\"],fg=C[\"text\"],selectcolor=C[\"bg\"],activebackground=C[\"card\"]).pack(side=\"left\",padx=6)\n\n        r4=_row(b2); _lbl(r4,\"Tesseract path (agar auto-detect fail ho):\"); v2_tess=tk.StringVar(value=r\"C:\\Program Files\\Tesseract-OCR\\tesseract.exe\")\n        _entry(r4,v2_tess,38)\n\n        def _do_ocr():\n            files=[f.strip() for f in v2_files.get().split(\";\") if f.strip()]\n            if not files: messagebox.showwarning(\"\",\"Images select karo.\"); return\n            out=filedialog.asksaveasfilename(title=\"Output file save\",\n                defaultextension=f\".{v2_out.get()}\",\n                filetypes=[(\"Output\",f\"*.{v2_out.get()}\"),(\"All\",\"*.*\")])\n            if not out: return\n            def _r():\n                try:\n                    if not _ipkg(\"PIL\",\"Pillow\"): return\n                    if not _ipkg(\"pytesseract\"): return\n                    import pytesseract\n                    from PIL import Image\n                    tp=v2_tess.get().strip()\n                    if tp and os.path.isfile(tp): pytesseract.pytesseract.tesseract_cmd=tp\n                    all_text=[]\n                    for fp in files:\n                        it_log(f\"  OCR: {os.path.basename(fp)}\u2026\",C[\"text_dim\"])\n                        img=Image.open(fp)\n                        txt=pytesseract.image_to_string(img,lang=v2_lang.get())\n                        all_text.append(f\"=== {os.path.basename(fp)} ===\\n{txt}\\n\")\n                    out_fmt=v2_out.get()\n                    if out_fmt==\"txt\":\n                        with open(out,\"w\",encoding=\"utf-8\") as f: f.write(\"\\n\".join(all_text))\n                    elif out_fmt==\"docx\":\n                        if not _ipkg(\"docx\",\"python-docx\"): return\n                        import docx\n                        doc=docx.Document()\n                        for block in all_text: doc.add_paragraph(block)\n                        doc.save(out)\n                    elif out_fmt==\"xlsx\":\n                        if not _ipkg(\"openpyxl\"): return\n                        import openpyxl\n                        wb=openpyxl.Workbook(); ws=wb.active; ws.title=\"OCR\"\n                        ws.append([\"Source File\",\"Extracted Text\"])\n                        for fp,txt in zip(files,all_text): ws.append([os.path.basename(fp),txt])\n                        wb.save(out)\n                    it_log(f\"\u2705 OCR done: {len(files)} files \u2192 {out}\",C[\"success\"])\n                    self.after(0,lambda: messagebox.showinfo(\"Done!\",f\"\u2705 OCR complete!\\n{out}\"))\n                except Exception as ex: it_log(f\"\u274c {ex}\\nTip: Tesseract install karo aur path sahi set karo.\",C[\"error\"]); self.after(0,lambda: messagebox.showerror(\"Error\",str(ex)))\n            threading.Thread(target=_r,daemon=True).start()\n        _abtn(b2,\"\u25b6 Run OCR\",_do_ocr)\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # TAB 3 \u2014 Background Remove\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        t3=tk.Frame(content_host,bg=C[\"bg\"]); _it_frames[\"bg\"]=t3\n\n        b3=_card(t3,\"\u2702  Background Remover  (rembg \u2014 AI-powered, first run ~100MB download)\")\n        tk.Label(b3,text=\"\u2139\ufe0f  First use mein model download hoga (~100 MB). Internet chahiye.\",\n                 font=FONTS[\"small\"],fg=C[\"accent4\"],bg=C[\"card\"]).pack(anchor=\"w\",pady=(0,6))\n        r=_row(b3); _lbl(r,\"Images:\"); v3_files=tk.StringVar(); _entry(r,v3_files,50)\n        _browse(r,lambda: v3_files.set(\";\".join(filedialog.askopenfilenames(\n            filetypes=[(\"Images\",\"*.jpg *.jpeg *.png *.webp *.bmp\"),(\"All\",\"*.*\")]))))\n        r2=_row(b3); _lbl(r2,\"Output suffix:\"); v3_suf=tk.StringVar(value=\"_nobg\"); _entry(r2,v3_suf,12)\n        _lbl(r2,\"  Output format (PNG recommended for transparency):\"); v3_fmt=tk.StringVar(value=\"PNG\")\n        for f in (\"PNG\",\"WEBP\"):\n            tk.Radiobutton(r2,text=f,variable=v3_fmt,value=f,font=FONTS[\"small\"],bg=C[\"card\"],fg=C[\"text\"],selectcolor=C[\"bg\"],activebackground=C[\"card\"]).pack(side=\"left\",padx=5)\n\n        def _do_bgrem():\n            files=[f.strip() for f in v3_files.get().split(\";\") if f.strip()]\n            if not files: messagebox.showwarning(\"\",\"Images select karo.\"); return\n            out_dir=filedialog.askdirectory(title=\"Output folder\")\n            if not out_dir: return\n            def _r():\n                try:\n                    if not _ipkg(\"rembg\"): return\n                    if not _ipkg(\"PIL\",\"Pillow\"): return\n                    from rembg import remove\n                    from PIL import Image\n                    import io\n                    done=0\n                    for fp in files:\n                        try:\n                            it_log(f\"  Processing: {os.path.basename(fp)}\u2026\",C[\"text_dim\"])\n                            with open(fp,\"rb\") as f: inp=f.read()\n                            out_bytes=remove(inp)\n                            base=os.path.splitext(os.path.basename(fp))[0]\n                            fmt=v3_fmt.get(); ext=\".png\" if fmt==\"PNG\" else \".webp\"\n                            out_path=os.path.join(out_dir,f\"{base}{v3_suf.get()}{ext}\")\n                            img=Image.open(io.BytesIO(out_bytes))\n                            img.save(out_path,fmt)\n                            done+=1\n                        except Exception as e: it_log(f\"\u26a0\ufe0f {os.path.basename(fp)}: {e}\",C[\"warning\"])\n                    it_log(f\"\u2705 Background removed: {done}/{len(files)} \u2192 {out_dir}\",C[\"success\"])\n                    self.after(0,lambda: messagebox.showinfo(\"Done!\",f\"\u2705 {done} images processed!\\n{out_dir}\"))\n                except Exception as ex: it_log(f\"\u274c {ex}\",C[\"error\"]); self.after(0,lambda: messagebox.showerror(\"Error\",str(ex)))\n            threading.Thread(target=_r,daemon=True).start()\n        _abtn(b3,\"\u25b6 Remove Background\",_do_bgrem)\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # TAB 4 \u2014 Crop (Images + PDF)\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        t4=tk.Frame(content_host,bg=C[\"bg\"]); _it_frames[\"crop\"]=t4\n\n        # Image crop\n        b4a=_card(t4,\"\u2702\ufe0f  Image Crop  (pixels \u2014 left, top, right, bottom)\")\n        r=_row(b4a); _lbl(r,\"Images:\"); v4a_files=tk.StringVar(); _entry(r,v4a_files,48)\n        _browse(r,lambda: v4a_files.set(\";\".join(filedialog.askopenfilenames(\n            filetypes=[(\"Images\",\"*.jpg *.jpeg *.png *.bmp *.tiff *.webp\"),(\"All\",\"*.*\")]))))\n        r2=_row(b4a)\n        _lbl(r2,\"Left:\"); v4a_l=tk.StringVar(value=\"0\"); _entry(r2,v4a_l,6)\n        _lbl(r2,\"Top:\"); v4a_t=tk.StringVar(value=\"0\"); _entry(r2,v4a_t,6)\n        _lbl(r2,\"Right:\"); v4a_r=tk.StringVar(value=\"800\"); _entry(r2,v4a_r,6)\n        _lbl(r2,\"Bottom:\"); v4a_b=tk.StringVar(value=\"600\"); _entry(r2,v4a_b,6)\n        # Suffix nahi \u2014 output folder alag hai, naam same rahega\n\n        def _do_img_crop():\n            files=[f.strip() for f in v4a_files.get().split(\";\") if f.strip()]\n            if not files: messagebox.showwarning(\"\",\"Images select karo.\"); return\n            out_dir=filedialog.askdirectory(title=\"Output folder\")\n            if not out_dir: return\n            def _r():\n                try:\n                    if not _ipkg(\"PIL\",\"Pillow\"): return\n                    from PIL import Image\n                    box=(int(v4a_l.get()),int(v4a_t.get()),int(v4a_r.get()),int(v4a_b.get()))\n                    done=0\n                    for fp in files:\n                        try:\n                            img=Image.open(fp)\n                            cropped=img.crop(box)\n                            base,ext=os.path.splitext(os.path.basename(fp))\n                            out_path=os.path.join(out_dir,f\"{base}{ext}\")  # same naam, alag folder\n                            cropped.save(out_path)\n                            done+=1\n                        except Exception as e: it_log(f\"\u26a0\ufe0f {os.path.basename(fp)}: {e}\",C[\"warning\"])\n                    it_log(f\"\u2705 Cropped {done}/{len(files)} images \u2192 {out_dir}\",C[\"success\"])\n                    self.after(0,lambda: messagebox.showinfo(\"Done!\",f\"\u2705 {done} images cropped!\\n{out_dir}\"))\n                except Exception as ex: it_log(f\"\u274c {ex}\",C[\"error\"]); self.after(0,lambda: messagebox.showerror(\"Error\",str(ex)))\n            threading.Thread(target=_r,daemon=True).start()\n        _abtn(b4a,\"\u25b6 Crop Images (pixel values)\",_do_img_crop)\n\n        # \u2500\u2500 Visual Mouse Crop for Images \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        def _do_visual_img_crop():\n            \"\"\"Mouse se drag karke image ka area select karo aur crop karo.\"\"\"\n            files=[f.strip() for f in v4a_files.get().split(\";\") if f.strip()]\n            if not files:\n                messagebox.showwarning(\"\",\"Pehle images select karo (upar wale entry mein).\")\n                return\n            if not _ipkg(\"PIL\",\"Pillow\"):\n                return\n            from PIL import Image as _PILImg, ImageTk as _ITk\n\n            # File index state\n            img_state = {\n                \"idx\": 0,\n                \"files\": files,\n                \"rect\": None,\n                \"drag_start\": None,\n                \"photo\": None,\n                \"scale\": 1.0,\n                \"orig_w\": 1, \"orig_h\": 1,\n                \"img_x\": 0, \"img_y\": 0,\n            }\n\n            iwin = tk.Toplevel(self)\n            iwin.title(\"\ud83d\uddb1  Visual Image Crop \u2014 Mouse se area select karo\")\n            iwin.geometry(\"980x700\")\n            iwin.configure(bg=C[\"bg\"])\n            iwin.grab_set()\n\n            # \u2500\u2500 Top controls \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            ictrl = tk.Frame(iwin, bg=C[\"panel\"])\n            ictrl.pack(fill=\"x\")\n            tk.Label(ictrl, text=\"Image:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"left\", padx=(10,4))\n            ifile_var = tk.StringVar(value=\"1\")\n            ifile_spin = tk.Spinbox(ictrl, from_=1, to=len(files), textvariable=ifile_var,\n                                    width=5, font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"],\n                                    buttonbackground=C[\"card\"])\n            ifile_spin.pack(side=\"left\", padx=4)\n            tk.Label(ictrl, text=f\"/ {len(files)}\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"left\")\n\n            iname_lbl = tk.Label(ictrl, text=\"\", font=FONTS[\"small\"], fg=C[\"accent4\"], bg=C[\"panel\"])\n            iname_lbl.pack(side=\"left\", padx=10)\n\n            icoord_lbl = tk.Label(ictrl, text=\"Selection: None\", font=FONTS[\"small\"],\n                                   fg=C[\"accent\"], bg=C[\"panel\"])\n            icoord_lbl.pack(side=\"left\", padx=16)\n\n            tk.Label(ictrl, text=\"\ud83d\uddb1 Drag to select crop area\", font=FONTS[\"small\"],\n                     fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"right\", padx=14)\n\n            # \u2500\u2500 Canvas \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            icf = tk.Frame(iwin, bg=C[\"bg\"])\n            icf.pack(fill=\"both\", expand=True, padx=8, pady=4)\n            icanvas = tk.Canvas(icf, bg=\"#1a1a2e\", cursor=\"crosshair\", highlightthickness=0)\n            icanvas.pack(fill=\"both\", expand=True)\n\n            def render_image(idx):\n                img_state[\"idx\"] = idx\n                img_state[\"rect\"] = None\n                icanvas.delete(\"all\")\n                fp = files[idx]\n                iname_lbl.config(text=os.path.basename(fp))\n                try:\n                    pil = _PILImg.open(fp)\n                    cw = icanvas.winfo_width() or 900\n                    ch = icanvas.winfo_height() or 560\n                    ow, oh = pil.size\n                    img_state[\"orig_w\"] = ow\n                    img_state[\"orig_h\"] = oh\n                    scale = min((cw-20)/ow, (ch-20)/oh, 1.0)\n                    img_state[\"scale\"] = scale\n                    disp = pil.resize((int(ow*scale), int(oh*scale)), _PILImg.LANCZOS)\n                    photo = _ITk.PhotoImage(disp)\n                    img_state[\"photo\"] = photo\n                    ix = (cw - int(ow*scale)) // 2\n                    iy = (ch - int(oh*scale)) // 2\n                    img_state[\"img_x\"] = ix\n                    img_state[\"img_y\"] = iy\n                    icanvas.create_image(ix, iy, anchor=\"nw\", image=photo, tags=\"img\")\n                    icanvas.create_rectangle(ix-1, iy-1, ix+int(ow*scale)+1, iy+int(oh*scale)+1,\n                                             outline=C[\"accent\"], width=1, tags=\"border\")\n                    icoord_lbl.config(text=\"Selection: None \u2014 drag karke area choose karo\")\n                except Exception as e:\n                    icoord_lbl.config(text=f\"Error loading image: {e}\")\n\n            irect_id = [None]\n\n            def ion_press(event):\n                img_state[\"drag_start\"] = (event.x, event.y)\n                img_state[\"rect\"] = None\n                if irect_id[0]:\n                    icanvas.delete(irect_id[0])\n                    irect_id[0] = None\n\n            def ion_drag(event):\n                if not img_state[\"drag_start\"]:\n                    return\n                x0,y0 = img_state[\"drag_start\"]\n                x1,y1 = event.x, event.y\n                if irect_id[0]:\n                    icanvas.delete(irect_id[0])\n                irect_id[0] = icanvas.create_rectangle(x0,y0,x1,y1,\n                    outline=\"#00FF88\", width=2, dash=(4,2), tags=\"isel\")\n                ix, iy = img_state[\"img_x\"], img_state[\"img_y\"]\n                sc = img_state[\"scale\"]\n                px0 = max(0, (min(x0,x1)-ix)/sc)\n                py0 = max(0, (min(y0,y1)-iy)/sc)\n                px1 = min(img_state[\"orig_w\"], (max(x0,x1)-ix)/sc)\n                py1 = min(img_state[\"orig_h\"], (max(y0,y1)-iy)/sc)\n                icoord_lbl.config(text=f\"Selection: ({px0:.0f},{py0:.0f}) \u2192 ({px1:.0f},{py1:.0f}) px  |  {px1-px0:.0f}\u00d7{py1-py0:.0f} px\")\n\n            def ion_release(event):\n                if not img_state[\"drag_start\"]:\n                    return\n                x0,y0 = img_state[\"drag_start\"]\n                x1,y1 = event.x, event.y\n                if abs(x1-x0)&lt;8 or abs(y1-y0)&lt;8:\n                    img_state[\"rect\"] = None\n                    icoord_lbl.config(text=\"Too small \u2014 thoda bada area select karo\")\n                    return\n                ix, iy = img_state[\"img_x\"], img_state[\"img_y\"]\n                sc = img_state[\"scale\"]\n                cx0,cy0 = min(x0,x1), min(y0,y1)\n                cx1,cy1 = max(x0,x1), max(y0,y1)\n                px0 = max(0, (cx0-ix)/sc)\n                py0 = max(0, (cy0-iy)/sc)\n                px1 = min(img_state[\"orig_w\"], (cx1-ix)/sc)\n                py1 = min(img_state[\"orig_h\"], (cy1-iy)/sc)\n                img_state[\"rect\"] = (int(px0), int(py0), int(px1), int(py1))\n                icoord_lbl.config(text=f\"\u2705 Selected: ({int(px0)},{int(py0)}) \u2192 ({int(px1)},{int(py1)}) px  |  Click 'Apply Crop'\")\n\n            icanvas.bind(\"\", ion_press)\n            icanvas.bind(\"\", ion_drag)\n            icanvas.bind(\"\", ion_release)\n\n            def igo_img(*_):\n                try:\n                    idx = int(ifile_var.get())-1\n                    idx = max(0, min(idx, len(files)-1))\n                    render_image(idx)\n                except Exception:\n                    pass\n            ifile_spin.config(command=igo_img)\n            ifile_spin.bind(\"\", igo_img)\n            icanvas.bind(\"\", lambda e: self.after(100, lambda: render_image(img_state[\"idx\"])))\n\n            # \u2500\u2500 Bottom buttons \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            ibtn_row = tk.Frame(iwin, bg=C[\"panel\"])\n            ibtn_row.pack(fill=\"x\", pady=4)\n\n            def apply_img_visual_crop():\n                if not img_state[\"rect\"]:\n                    messagebox.showwarning(\"\", \"Pehle mouse se area select karo.\")\n                    return\n                out_dir = filedialog.askdirectory(title=\"Cropped images save karne ke liye folder\")\n                if not out_dir:\n                    return\n                box = img_state[\"rect\"]\n                crop_all = crop_all_var.get()\n                target_idxs = list(range(len(files))) if crop_all else [img_state[\"idx\"]]\n                def _icrop_run():\n                    try:\n                        done = 0\n                        for idx in target_idxs:\n                            fp = files[idx]\n                            try:\n                                pil = _PILImg.open(fp)\n                                # Clamp box to actual image size\n                                ow, oh = pil.size\n                                safe_box = (\n                                    max(0, box[0]), max(0, box[1]),\n                                    min(ow, box[2]), min(oh, box[3])\n                                )\n                                cropped = pil.crop(safe_box)\n                                base, ext = os.path.splitext(os.path.basename(fp))\n                                suf = v4a_suf.get()\n                                out_path = os.path.join(out_dir, f\"{base}{ext}\")  # same naam, alag folder\n                                cropped.save(out_path)\n                                done += 1\n                            except Exception as e:\n                                it_log(f\"\u26a0\ufe0f {os.path.basename(fp)}: {e}\", C[\"warning\"])\n                        it_log(f\"\u2705 Visual crop: {done}/{len(target_idxs)} images \u2192 {out_dir}\", C[\"success\"])\n                        self.after(0, lambda: messagebox.showinfo(\"Done!\", f\"\u2705 {done} images cropped!\\n{out_dir}\"))\n                        self.after(0, iwin.destroy)\n                    except Exception as ex:\n                        it_log(f\"\u274c {ex}\", C[\"error\"])\n                        self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n                threading.Thread(target=_icrop_run, daemon=True).start()\n\n            crop_all_var = tk.BooleanVar(value=False)\n            tk.Checkbutton(ibtn_row, text=\"Sab images pe same crop apply karo\",\n                           variable=crop_all_var, font=FONTS[\"small\"],\n                           bg=C[\"panel\"], fg=C[\"text\"], selectcolor=C[\"bg\"],\n                           activebackground=C[\"panel\"]).pack(side=\"left\", padx=12, pady=6)\n\n            def ireset_sel():\n                img_state[\"rect\"] = None\n                if irect_id[0]:\n                    icanvas.delete(irect_id[0])\n                    irect_id[0] = None\n                icoord_lbl.config(text=\"Selection: Reset \u2014 dobara drag karo\")\n\n            tk.Button(ibtn_row, text=\"\u2705 Apply Crop\", font=FONTS[\"body\"],\n                      bg=C[\"success\"], fg=C[\"bg\"], bd=0, padx=20, pady=8,\n                      cursor=\"hand2\", command=apply_img_visual_crop).pack(side=\"left\", padx=8, pady=6)\n            tk.Button(ibtn_row, text=\"\ud83d\udd04 Reset\", font=FONTS[\"body\"],\n                      bg=C[\"btn_warn\"], fg=C[\"text\"], bd=0, padx=12, pady=8,\n                      cursor=\"hand2\", command=ireset_sel).pack(side=\"left\", padx=4)\n            tk.Button(ibtn_row, text=\"\u25c0 Prev\", font=FONTS[\"body\"],\n                      bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=10, pady=8,\n                      cursor=\"hand2\",\n                      command=lambda: (ifile_var.set(max(1, int(ifile_var.get())-1)), igo_img())).pack(side=\"left\", padx=4)\n            tk.Button(ibtn_row, text=\"Next \u25b6\", font=FONTS[\"body\"],\n                      bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=10, pady=8,\n                      cursor=\"hand2\",\n                      command=lambda: (ifile_var.set(min(len(files), int(ifile_var.get())+1)), igo_img())).pack(side=\"left\", padx=4)\n            tk.Button(ibtn_row, text=\"\u274c Cancel\", font=FONTS[\"body\"],\n                      bg=C[\"btn_danger\"], fg=C[\"text\"], bd=0, padx=12, pady=8,\n                      cursor=\"hand2\", command=iwin.destroy).pack(side=\"right\", padx=12)\n\n            iwin.update_idletasks()\n            self.after(150, lambda: render_image(0))\n\n        _abtn(b4a, \"\ud83d\uddb1  Visual Mouse Crop \u2014 Image (interactive)\", _do_visual_img_crop)\n\n        # PDF crop (page margins) + Visual Mouse Crop\n        b4b=_card(t4,\"\u2702\ufe0f  PDF Page Crop  (trim margins mm se  OR  mouse se visually select karo)\")\n        r=_row(b4b); _lbl(r,\"PDF:\"); v4b_pdf=tk.StringVar(); _entry(r,v4b_pdf,46)\n        _browse(r,lambda: v4b_pdf.set(filedialog.askopenfilename(filetypes=[(\"PDF\",\"*.pdf\"),(\"All\",\"*.*\")])))\n        r2=_row(b4b)\n        _lbl(r2,\"Left mm:\"); v4b_l=tk.StringVar(value=\"10\"); _entry(r2,v4b_l,5)\n        _lbl(r2,\"Bottom mm:\"); v4b_bot=tk.StringVar(value=\"10\"); _entry(r2,v4b_bot,5)\n        _lbl(r2,\"Right mm:\"); v4b_rr=tk.StringVar(value=\"10\"); _entry(r2,v4b_rr,5)\n        _lbl(r2,\"Top mm:\"); v4b_top=tk.StringVar(value=\"10\"); _entry(r2,v4b_top,5)\n        _lbl(r2,\"  Pages (blank=all):\"); v4b_pg=tk.StringVar(value=\"\"); _entry(r2,v4b_pg,10)\n\n        def _do_pdf_crop():\n            src=v4b_pdf.get().strip()\n            if not src or not os.path.isfile(src): messagebox.showwarning(\"\",\"Valid PDF select karo.\"); return\n            # Original PDF naam se default naam suggest karo\n            src_base=os.path.splitext(os.path.basename(src))[0]\n            out=filedialog.asksaveasfilename(title=\"Cropped PDF\",defaultextension=\".pdf\",\n                                             initialfile=src_base,\n                                             filetypes=[(\"PDF\",\"*.pdf\")])\n            if not out: return\n            def _r():\n                try:\n                    if not _ipkg(\"pikepdf\"): return\n                    import pikepdf\n                    # 1 mm \u2248 2.8346 PDF points\n                    mm2pt=lambda mm: float(mm)*2.8346\n                    l=mm2pt(v4b_l.get()); b=mm2pt(v4b_bot.get())\n                    rr=mm2pt(v4b_rr.get()); t=mm2pt(v4b_top.get())\n                    pages_raw=v4b_pg.get().strip()\n                    def _pk(v): return pikepdf.Real(round(v,4))\n                    with pikepdf.open(src) as pdf:\n                        total=len(pdf.pages)\n                        if pages_raw:\n                            idxs=set()\n                            for p in pages_raw.split(\",\"):\n                                p=p.strip()\n                                if \"-\" in p:\n                                    a,bb=p.split(\"-\"); [idxs.add(i) for i in range(int(a)-1,int(bb))]\n                                else:\n                                    try: idxs.add(int(p)-1)\n                                    except: pass\n                        else:\n                            idxs=set(range(total))\n                        for i,page in enumerate(pdf.pages):\n                            if i not in idxs: continue\n                            mb=page.mediabox\n                            x0,y0,x1,y1=float(mb[0]),float(mb[1]),float(mb[2]),float(mb[3])\n                            page.cropbox=pikepdf.Array([_pk(x0+l),_pk(y0+b),_pk(x1-rr),_pk(y1-t)])\n                        pdf.save(out)\n                    it_log(f\"\u2705 PDF cropped ({len(idxs)} pages) \u2192 {out}\",C[\"success\"])\n                    self.after(0,lambda: messagebox.showinfo(\"Done!\",f\"\u2705 PDF cropped!\\n{out}\"))\n                except Exception as ex: it_log(f\"\u274c {ex}\",C[\"error\"]); self.after(0,lambda: messagebox.showerror(\"Error\",str(ex)))\n            threading.Thread(target=_r,daemon=True).start()\n        _abtn(b4b,\"\u25b6 Crop PDF (mm margins)\",_do_pdf_crop)\n\n        # \u2500\u2500 Visual Mouse Crop \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        def _do_visual_pdf_crop():\n            \"\"\"Mouse se drag karke PDF page ka area select karo aur crop karo.\"\"\"\n            src = v4b_pdf.get().strip()\n            if not src or not os.path.isfile(src):\n                messagebox.showwarning(\"\", \"Pehle PDF select karo.\")\n                return\n            # Ensure dependencies\n            fitz_ok = _ipkg(\"fitz\", \"PyMuPDF\")\n            if not fitz_ok:\n                messagebox.showerror(\"Error\", \"PyMuPDF local package missing hai. Offline bundle/wheel se install karein.\")\n                return\n            import fitz\n            doc = fitz.open(src)\n            total_pages = len(doc)\n            if total_pages == 0:\n                messagebox.showerror(\"Error\", \"PDF mein koi page nahi hai.\")\n                doc.close()\n                return\n\n            # \u2500\u2500 Visual Crop Window \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            crop_win = tk.Toplevel(self)\n            crop_win.title(\"\ud83d\uddb1  Visual PDF Crop \u2014 Mouse se area select karo\")\n            crop_win.geometry(\"950x720\")\n            crop_win.configure(bg=C[\"bg\"])\n            crop_win.grab_set()\n\n            # State\n            state = {\n                \"page_idx\": 0,\n                \"rect\": None,       # (x1,y1,x2,y2) in canvas coords\n                \"drag_start\": None,\n                \"photo\": None,\n                \"scale\": 1.0,\n                \"page_w\": 1, \"page_h\": 1,\n                \"canvas_w\": 780, \"canvas_h\": 540,\n            }\n\n            # \u2500\u2500 Top controls \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            ctrl = tk.Frame(crop_win, bg=C[\"panel\"])\n            ctrl.pack(fill=\"x\", pady=0)\n            tk.Label(ctrl, text=\"Page:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"left\", padx=(10,4))\n            page_var = tk.StringVar(value=\"1\")\n            page_spin = tk.Spinbox(ctrl, from_=1, to=total_pages, textvariable=page_var,\n                                   width=5, font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"],\n                                   buttonbackground=C[\"card\"])\n            page_spin.pack(side=\"left\", padx=4)\n            tk.Label(ctrl, text=f\"/ {total_pages}\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"left\")\n\n            apply_all_var = tk.BooleanVar(value=False)\n            tk.Checkbutton(ctrl, text=\"Sab pages pe apply karo\", variable=apply_all_var,\n                           font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text\"],\n                           selectcolor=C[\"bg\"], activebackground=C[\"panel\"]).pack(side=\"left\", padx=16)\n\n            coord_lbl = tk.Label(ctrl, text=\"Selection: None\", font=FONTS[\"small\"],\n                                 fg=C[\"accent\"], bg=C[\"panel\"])\n            coord_lbl.pack(side=\"left\", padx=10)\n\n            tk.Label(ctrl, text=\"\ud83d\uddb1 Drag to select crop area\", font=FONTS[\"small\"],\n                     fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"right\", padx=14)\n\n            # \u2500\u2500 Canvas \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            canvas_frame = tk.Frame(crop_win, bg=C[\"bg\"])\n            canvas_frame.pack(fill=\"both\", expand=True, padx=8, pady=4)\n            canvas = tk.Canvas(canvas_frame, bg=\"#1a1a2e\", cursor=\"crosshair\",\n                                highlightthickness=0)\n            canvas.pack(fill=\"both\", expand=True)\n\n            def render_page(page_idx):\n                \"\"\"Render a PDF page onto the canvas.\"\"\"\n                state[\"page_idx\"] = page_idx\n                state[\"rect\"] = None\n                canvas.delete(\"all\")\n                page = doc[page_idx]\n                cw = canvas.winfo_width() or 780\n                ch = canvas.winfo_height() or 540\n                state[\"canvas_w\"] = cw\n                state[\"canvas_h\"] = ch\n                pw = page.rect.width\n                ph = page.rect.height\n                state[\"page_w\"] = pw\n                state[\"page_h\"] = ph\n                # Scale to fit canvas with padding\n                scale = min((cw - 20) / pw, (ch - 20) / ph)\n                state[\"scale\"] = scale\n                mat = fitz.Matrix(scale, scale)\n                pix = page.get_pixmap(matrix=mat)\n                import io as _io\n                from PIL import Image as _PILImg, ImageTk as _ITk\n                pil = _PILImg.open(_io.BytesIO(pix.tobytes(\"ppm\")))\n                photo = _ITk.PhotoImage(pil)\n                state[\"photo\"] = photo  # keep reference\n                state[\"img_x\"] = (cw - pix.width)  // 2\n                state[\"img_y\"] = (ch - pix.height) // 2\n                canvas.create_image(state[\"img_x\"], state[\"img_y\"], anchor=\"nw\", image=photo, tags=\"page\")\n                # Border\n                canvas.create_rectangle(\n                    state[\"img_x\"]-1, state[\"img_y\"]-1,\n                    state[\"img_x\"]+pix.width+1, state[\"img_y\"]+pix.height+1,\n                    outline=C[\"accent\"], width=1, tags=\"border\")\n                coord_lbl.config(text=\"Selection: None \u2014 drag karke area choose karo\")\n\n            # \u2500\u2500 Mouse drag for selection \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            rect_id = [None]\n\n            def on_press(event):\n                state[\"drag_start\"] = (event.x, event.y)\n                state[\"rect\"] = None\n                if rect_id[0]:\n                    canvas.delete(rect_id[0])\n                    rect_id[0] = None\n\n            def on_drag(event):\n                if not state[\"drag_start\"]:\n                    return\n                x0, y0 = state[\"drag_start\"]\n                x1, y1 = event.x, event.y\n                if rect_id[0]:\n                    canvas.delete(rect_id[0])\n                rect_id[0] = canvas.create_rectangle(\n                    x0, y0, x1, y1,\n                    outline=\"#00FF88\", width=2, dash=(4,2), tags=\"sel\")\n                # Show size hint\n                ix, iy = state[\"img_x\"], state[\"img_y\"]\n                sc = state[\"scale\"]\n                # Clamp to page\n                px0 = max(0, (min(x0,x1) - ix) / sc)\n                py0 = max(0, (min(y0,y1) - iy) / sc)\n                px1 = min(state[\"page_w\"], (max(x0,x1) - ix) / sc)\n                py1 = min(state[\"page_h\"], (max(y0,y1) - iy) / sc)\n                coord_lbl.config(text=f\"Selection: ({px0:.0f},{py0:.0f}) \u2192 ({px1:.0f},{py1:.0f}) pt  |  {px1-px0:.0f}\u00d7{py1-py0:.0f} pt\")\n\n            def on_release(event):\n                if not state[\"drag_start\"]:\n                    return\n                x0, y0 = state[\"drag_start\"]\n                x1, y1 = event.x, event.y\n                if abs(x1-x0) &lt; 10 or abs(y1-y0) &lt; 10:\n                    state[\"rect\"] = None\n                    coord_lbl.config(text=\"Too small \u2014 thoda bada area select karo\")\n                    return\n                # Convert canvas coords \u2192 PDF points\n                ix, iy = state[\"img_x\"], state[\"img_y\"]\n                sc = state[\"scale\"]\n                pw, ph = state[\"page_w\"], state[\"page_h\"]\n                # PDF origin is bottom-left, canvas top-left\n                cx0, cy0 = min(x0,x1), min(y0,y1)\n                cx1, cy1 = max(x0,x1), max(y0,y1)\n                # Clamp\n                pdf_x0 = max(0.0, (cx0 - ix) / sc)\n                pdf_y0_top = max(0.0, (cy0 - iy) / sc)  # distance from top\n                pdf_x1 = min(pw, (cx1 - ix) / sc)\n                pdf_y1_top = min(ph, (cy1 - iy) / sc)\n                # Convert to PDF coords (y flipped): pdf_y = ph - canvas_y\n                pdf_y1 = ph - pdf_y0_top   # top of selection in PDF coords\n                pdf_y0 = ph - pdf_y1_top   # bottom of selection in PDF coords\n                state[\"rect\"] = (pdf_x0, pdf_y0, pdf_x1, pdf_y1)\n                coord_lbl.config(text=f\"\u2705 Selected: ({pdf_x0:.0f},{pdf_y0:.0f}) \u2192 ({pdf_x1:.0f},{pdf_y1:.0f}) pt  |  Click 'Apply Crop'\")\n\n            canvas.bind(\"\", on_press)\n            canvas.bind(\"\", on_drag)\n            canvas.bind(\"\", on_release)\n\n            def go_page(*_):\n                try:\n                    idx = int(page_var.get()) - 1\n                    idx = max(0, min(idx, total_pages-1))\n                    render_page(idx)\n                except Exception:\n                    pass\n            page_spin.config(command=go_page)\n            page_spin.bind(\"\", go_page)\n\n            # Render on canvas resize\n            def on_resize(event):\n                render_page(state[\"page_idx\"])\n            canvas.bind(\"\", lambda e: self.after(100, lambda: render_page(state[\"page_idx\"])))\n\n            # \u2500\u2500 Bottom buttons \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            btn_row = tk.Frame(crop_win, bg=C[\"panel\"])\n            btn_row.pack(fill=\"x\", pady=4)\n\n            def apply_visual_crop():\n                if not state[\"rect\"]:\n                    messagebox.showwarning(\"\", \"Pehle mouse se area select karo.\")\n                    return\n                src_base = os.path.splitext(os.path.basename(src))[0]\n                out = filedialog.asksaveasfilename(\n                    title=\"Cropped PDF save karein\",\n                    defaultextension=\".pdf\",\n                    initialfile=src_base,\n                    filetypes=[(\"PDF\", \"*.pdf\")])\n                if not out:\n                    return\n                crop_box = state[\"rect\"]   # (x0, y0, x1, y1) in PDF points\n                apply_all = apply_all_var.get()\n                target_pages = list(range(total_pages)) if apply_all else [state[\"page_idx\"]]\n                def _crop_run():\n                    try:\n                        if not _ipkg(\"pikepdf\"): return\n                        import pikepdf\n                        def _pkv(v): return pikepdf.Real(round(v,4))\n                        with pikepdf.open(src) as pdf:\n                            for pidx in range(len(pdf.pages)):\n                                if pidx not in target_pages:\n                                    continue\n                                page = pdf.pages[pidx]\n                                mb = page.mediabox\n                                page.cropbox = pikepdf.Array([\n                                    _pkv(crop_box[0]),\n                                    _pkv(crop_box[1]),\n                                    _pkv(crop_box[2]),\n                                    _pkv(crop_box[3]),\n                                ])\n                            pdf.save(out)\n                        it_log(f\"\u2705 Visual crop applied ({len(target_pages)} pages) \u2192 {out}\", C[\"success\"])\n                        self.after(0, lambda: messagebox.showinfo(\"Done!\",\n                            f\"\u2705 PDF visually cropped!\\n{out}\"))\n                        self.after(0, crop_win.destroy)\n                    except Exception as ex:\n                        it_log(f\"\u274c Visual crop error: {ex}\", C[\"error\"])\n                        self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n                threading.Thread(target=_crop_run, daemon=True).start()\n\n            def reset_selection():\n                state[\"rect\"] = None\n                if rect_id[0]:\n                    canvas.delete(rect_id[0])\n                    rect_id[0] = None\n                coord_lbl.config(text=\"Selection: Reset \u2014 dobara drag karo\")\n\n            tk.Button(btn_row, text=\"\u2705 Apply Crop\", font=FONTS[\"body\"],\n                      bg=C[\"success\"], fg=C[\"bg\"], bd=0, padx=20, pady=8,\n                      cursor=\"hand2\", command=apply_visual_crop).pack(side=\"left\", padx=12, pady=6)\n            tk.Button(btn_row, text=\"\ud83d\udd04 Reset Selection\", font=FONTS[\"body\"],\n                      bg=C[\"btn_warn\"], fg=C[\"text\"], bd=0, padx=14, pady=8,\n                      cursor=\"hand2\", command=reset_selection).pack(side=\"left\", padx=6)\n            tk.Button(btn_row, text=\"\u25c0 Prev Page\", font=FONTS[\"body\"],\n                      bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=12, pady=8,\n                      cursor=\"hand2\",\n                      command=lambda: (page_var.set(max(1, int(page_var.get())-1)), go_page())).pack(side=\"left\", padx=4)\n            tk.Button(btn_row, text=\"Next Page \u25b6\", font=FONTS[\"body\"],\n                      bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=12, pady=8,\n                      cursor=\"hand2\",\n                      command=lambda: (page_var.set(min(total_pages, int(page_var.get())+1)), go_page())).pack(side=\"left\", padx=4)\n            tk.Button(btn_row, text=\"\u274c Cancel\", font=FONTS[\"body\"],\n                      bg=C[\"btn_danger\"], fg=C[\"text\"], bd=0, padx=12, pady=8,\n                      cursor=\"hand2\",\n                      command=lambda: (doc.close(), crop_win.destroy())).pack(side=\"right\", padx=12)\n\n            # Initial render after window shows\n            crop_win.update_idletasks()\n            self.after(150, lambda: render_page(0))\n\n        _abtn(b4b, \"\ud83d\uddb1  Visual Mouse Crop (interactive)\", _do_visual_pdf_crop)\n\n        _it_switch(\"resize\")\n        return frame\n\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # FILE MANAGER TOOLS SECTION\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _build_file_tools(self, parent):\n        \"\"\"\n        File Manager Tools:\n          Tab 1 \u2014 Bulk Rename         (counter, date, prefix/suffix, regex)\n          Tab 2 \u2014 Duplicate Finder    (MD5/SHA256 content-based)\n        \"\"\"\n        import threading, hashlib\n\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n\n        hdr=tk.Frame(frame,bg=C[\"panel\"]); hdr.pack(fill=\"x\")\n        tk.Label(hdr,text=\"  \ud83d\uddc2 File Manager Tools\",font=FONTS[\"heading\"],fg=C[\"accent\"],bg=C[\"panel\"]).pack(side=\"left\",pady=10,padx=8)\n        tk.Label(hdr,text=\"Bulk Rename \u00b7 Duplicate Finder  |  No extra installs needed\",\n                 font=FONTS[\"small\"],fg=C[\"text_dim\"],bg=C[\"panel\"]).pack(side=\"left\",pady=10)\n\n        tab_bar=tk.Frame(frame,bg=C[\"card\"]); tab_bar.pack(fill=\"x\")\n        tk.Frame(tab_bar,bg=C[\"border\"],height=1).pack(side=\"bottom\",fill=\"x\")\n        content_host=tk.Frame(frame,bg=C[\"bg\"]); content_host.pack(fill=\"both\",expand=True)\n\n        _ft_frames={}; _ft_btns={}\n        def _ft_switch(key):\n            for k,b in _ft_btns.items():\n                b.config(bg=C[\"accent\"] if k==key else C[\"panel\"],\n                         fg=C[\"bg\"]     if k==key else C[\"text\"])\n            for k,f in _ft_frames.items():\n                f.pack(fill=\"both\",expand=True) if k==key else f.pack_forget()\n\n        for key,label in [(\"rename\",\"\u270f  Bulk Rename\"),(\"dupfind\",\"\ud83d\udd0d  Duplicate Finder\")]:\n            b=tk.Button(tab_bar,text=label,font=FONTS[\"body\"],bg=C[\"panel\"],fg=C[\"text\"],\n                        bd=0,padx=18,pady=8,cursor=\"hand2\",command=lambda k=key: _ft_switch(k))\n            b.pack(side=\"left\"); _ft_btns[key]=b\n\n        log_host=tk.Frame(frame,bg=C[\"card\"]); log_host.pack(fill=\"x\",side=\"bottom\")\n        tk.Label(log_host,text=\"  Activity Log\",font=FONTS[\"small\"],fg=C[\"accent\"],bg=C[\"card\"]).pack(anchor=\"w\",padx=8,pady=(5,0))\n        _ft_log_w=scrolledtext.ScrolledText(log_host,height=4,state=\"disabled\",bg=C[\"bg\"],fg=C[\"text\"],font=FONTS[\"small\"],bd=0)\n        _ft_log_w.pack(fill=\"x\",padx=8,pady=(2,6))\n\n        def ft_log(msg,color=None):\n            ts=datetime.datetime.now().strftime(\"%H:%M:%S\")\n            _ft_log_w.config(state=\"normal\")\n            tag=f\"t{abs(hash(color or ''))}\"\n            _ft_log_w.tag_config(tag,foreground=color or C[\"text\"])\n            _ft_log_w.insert(\"end\",f\"[{ts}] {msg}\\n\",tag)\n            _ft_log_w.see(\"end\"); _ft_log_w.config(state=\"disabled\")\n\n        def _card(par,title):\n            c=tk.Frame(par,bg=C[\"card\"]); c.pack(fill=\"x\",padx=16,pady=10)\n            tk.Label(c,text=title,font=FONTS[\"subhead\"],fg=C[\"accent\"],bg=C[\"card\"]).pack(anchor=\"w\",padx=10,pady=(8,4))\n            tk.Frame(c,bg=C[\"border\"],height=1).pack(fill=\"x\",padx=10)\n            b=tk.Frame(c,bg=C[\"card\"]); b.pack(fill=\"x\",padx=10,pady=10); return b\n\n        def _row(par): r=tk.Frame(par,bg=C[\"card\"]); r.pack(fill=\"x\",pady=3); return r\n        def _lbl(par,txt): tk.Label(par,text=txt,font=FONTS[\"small\"],fg=C[\"text_dim\"],bg=C[\"card\"]).pack(side=\"left\",padx=(0,4))\n        def _entry(par,var,w=44): e=tk.Entry(par,textvariable=var,font=FONTS[\"small\"],bg=C[\"bg\"],fg=C[\"text\"],insertbackground=C[\"text\"],width=w); e.pack(side=\"left\",padx=4); return e\n        def _browse(par,cmd): tk.Button(par,text=\"Browse\u2026\",font=FONTS[\"small\"],bg=C[\"btn_info\"],fg=C[\"text\"],bd=0,padx=8,pady=3,cursor=\"hand2\",command=cmd).pack(side=\"left\",padx=4)\n        def _abtn(par,txt,cmd,color=None): tk.Button(par,text=txt,font=FONTS[\"body\"],bg=color or C[\"accent\"],fg=C[\"bg\"],bd=0,padx=14,pady=6,cursor=\"hand2\",command=cmd).pack(anchor=\"w\",pady=(8,2))\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # TAB 1 \u2014 Bulk Rename\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        t1=tk.Frame(content_host,bg=C[\"bg\"]); _ft_frames[\"rename\"]=t1\n\n        b1=_card(t1,\"\u270f\ufe0f  Bulk File Rename\")\n        r=_row(b1); _lbl(r,\"Folder:\"); v1_dir=tk.StringVar(); _entry(r,v1_dir,48)\n        _browse(r,lambda: v1_dir.set(filedialog.askdirectory(title=\"Folder select karo\")))\n        r2=_row(b1); _lbl(r2,\"Filter extension (e.g. .jpg or blank=all):\"); v1_ext=tk.StringVar(value=\"\"); _entry(r2,v1_ext,8)\n\n        # Pattern options\n        opt_frame=tk.LabelFrame(b1,text=\"  Rename Pattern  (all options combine karein)\",\n                                 font=FONTS[\"small\"],fg=C[\"accent\"],bg=C[\"card\"],bd=1,relief=\"groove\")\n        opt_frame.pack(fill=\"x\",pady=6)\n        or1=tk.Frame(opt_frame,bg=C[\"card\"]); or1.pack(fill=\"x\",padx=8,pady=4)\n        _lbl(or1,\"Prefix:\"); v1_pre=tk.StringVar(); _entry(or1,v1_pre,12)\n        _lbl(or1,\"  Suffix (before ext):\"); v1_suf=tk.StringVar(); _entry(or1,v1_suf,12)\n        or2=tk.Frame(opt_frame,bg=C[\"card\"]); or2.pack(fill=\"x\",padx=8,pady=4)\n        v1_counter=tk.BooleanVar(value=True)\n        tk.Checkbutton(or2,text=\"Add counter\",variable=v1_counter,font=FONTS[\"small\"],bg=C[\"card\"],fg=C[\"text\"],selectcolor=C[\"bg\"],activebackground=C[\"card\"]).pack(side=\"left\")\n        _lbl(or2,\"  Start:\"); v1_start=tk.StringVar(value=\"1\"); _entry(or2,v1_start,5)\n        _lbl(or2,\"  Padding (digits):\"); v1_pad=tk.StringVar(value=\"3\"); _entry(or2,v1_pad,4)\n        or3=tk.Frame(opt_frame,bg=C[\"card\"]); or3.pack(fill=\"x\",padx=8,pady=4)\n        v1_date=tk.BooleanVar(value=False)\n        tk.Checkbutton(or3,text=\"Add date\",variable=v1_date,font=FONTS[\"small\"],bg=C[\"card\"],fg=C[\"text\"],selectcolor=C[\"bg\"],activebackground=C[\"card\"]).pack(side=\"left\")\n        _lbl(or3,\"  Date source:\"); v1_datesrc=tk.StringVar(value=\"today\")\n        tk.Radiobutton(or3,text=\"Today\",variable=v1_datesrc,value=\"today\",font=FONTS[\"small\"],bg=C[\"card\"],fg=C[\"text\"],selectcolor=C[\"bg\"],activebackground=C[\"card\"]).pack(side=\"left\",padx=4)\n        tk.Radiobutton(or3,text=\"File modified date\",variable=v1_datesrc,value=\"mtime\",font=FONTS[\"small\"],bg=C[\"card\"],fg=C[\"text\"],selectcolor=C[\"bg\"],activebackground=C[\"card\"]).pack(side=\"left\",padx=4)\n        or4=tk.Frame(opt_frame,bg=C[\"card\"]); or4.pack(fill=\"x\",padx=8,pady=4)\n        v1_replace=tk.BooleanVar(value=False)\n        tk.Checkbutton(or4,text=\"Find &amp; Replace in name:\",variable=v1_replace,font=FONTS[\"small\"],bg=C[\"card\"],fg=C[\"text\"],selectcolor=C[\"bg\"],activebackground=C[\"card\"]).pack(side=\"left\")\n        _lbl(or4,\"Find:\"); v1_find=tk.StringVar(); _entry(or4,v1_find,14)\n        _lbl(or4,\"Replace:\"); v1_rep=tk.StringVar(); _entry(or4,v1_rep,14)\n\n        # Preview\n        prev_lbl=tk.Label(b1,text=\"Preview: (click 'Preview' to see)\",\n                           font=FONTS[\"small\"],fg=C[\"text_dim\"],bg=C[\"card\"],anchor=\"w\")\n        prev_lbl.pack(fill=\"x\",pady=(4,0))\n        prev_box=scrolledtext.ScrolledText(b1,height=5,state=\"disabled\",bg=C[\"bg\"],fg=C[\"text\"],font=FONTS[\"small\"],bd=0)\n        prev_box.pack(fill=\"x\",pady=4)\n\n        def _build_new_name(orig_name, idx, folder):\n            base,ext=os.path.splitext(orig_name)\n            filt=v1_ext.get().strip()\n            if filt and ext.lower()!=filt.lower(): return None  # skip\n            name=base\n            if v1_replace.get():\n                name=name.replace(v1_find.get(),v1_rep.get())\n            date_str=\"\"\n            if v1_date.get():\n                if v1_datesrc.get()==\"today\":\n                    date_str=datetime.datetime.now().strftime(\"%Y%m%d\")\n                else:\n                    try:\n                        mtime=os.path.getmtime(os.path.join(folder,orig_name))\n                        date_str=datetime.datetime.fromtimestamp(mtime).strftime(\"%Y%m%d\")\n                    except: date_str=\"\"\n            ctr_str=\"\"\n            if v1_counter.get():\n                try: start=int(v1_start.get()); pad=int(v1_pad.get())\n                except: start=1; pad=3\n                ctr_str=str(start+idx).zfill(pad)\n            new=v1_pre.get()+date_str+ctr_str+name+v1_suf.get()\n            return new+ext\n\n        def _do_preview():\n            folder=v1_dir.get().strip()\n            if not folder or not os.path.isdir(folder): messagebox.showwarning(\"\",\"Valid folder select karo.\"); return\n            files=sorted(os.listdir(folder))\n            lines=[]; idx=0\n            for f in files:\n                if not os.path.isfile(os.path.join(folder,f)): continue\n                nn=_build_new_name(f,idx,folder)\n                if nn:\n                    lines.append(f\"  {f}  \u2192  {nn}\"); idx+=1\n            prev_box.config(state=\"normal\"); prev_box.delete(\"1.0\",\"end\")\n            prev_box.insert(\"end\",\"\\n\".join(lines) if lines else \"No files match.\"); prev_box.config(state=\"disabled\")\n\n        def _do_rename():\n            folder=v1_dir.get().strip()\n            if not folder or not os.path.isdir(folder): messagebox.showwarning(\"\",\"Valid folder select karo.\"); return\n            if not messagebox.askyesno(\"Confirm Rename\",\"Files rename honge. Undo possible nahi. Proceed?\"): return\n            def _r():\n                files=sorted(os.listdir(folder))\n                done=0; idx=0\n                for f in files:\n                    if not os.path.isfile(os.path.join(folder,f)): continue\n                    nn=_build_new_name(f,idx,folder)\n                    if nn and nn!=f:\n                        try:\n                            os.rename(os.path.join(folder,f),os.path.join(folder,nn))\n                            done+=1\n                        except Exception as e: ft_log(f\"\u26a0\ufe0f {f}: {e}\",C[\"warning\"])\n                    idx+=1\n                ft_log(f\"\u2705 {done} files renamed in {folder}\",C[\"success\"])\n                self.after(0,lambda: messagebox.showinfo(\"Done!\",f\"\u2705 {done} files renamed!\"))\n            threading.Thread(target=_r,daemon=True).start()\n\n        br=_row(b1)\n        tk.Button(br,text=\"\ud83d\udc41 Preview\",font=FONTS[\"body\"],bg=C[\"btn_info\"],fg=C[\"text\"],bd=0,padx=12,pady=6,cursor=\"hand2\",command=_do_preview).pack(side=\"left\",padx=(0,8))\n        tk.Button(br,text=\"\u25b6 Rename Files\",font=FONTS[\"body\"],bg=C[\"accent\"],fg=C[\"bg\"],bd=0,padx=14,pady=6,cursor=\"hand2\",command=_do_rename).pack(side=\"left\")\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # TAB 2 \u2014 Duplicate Finder\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        t2=tk.Frame(content_host,bg=C[\"bg\"]); _ft_frames[\"dupfind\"]=t2\n\n        b2=_card(t2,\"\ud83d\udd0d  Duplicate File Finder  (MD5 / SHA256 content-based)\")\n        r=_row(b2); _lbl(r,\"Folder to scan:\"); v2_dir=tk.StringVar(); _entry(r,v2_dir,46)\n        _browse(r,lambda: v2_dir.set(filedialog.askdirectory(title=\"Folder select karo\")))\n        r2=_row(b2)\n        v2_sub=tk.BooleanVar(value=True)\n        tk.Checkbutton(r2,text=\"Include subfolders\",variable=v2_sub,font=FONTS[\"small\"],bg=C[\"card\"],fg=C[\"text\"],selectcolor=C[\"bg\"],activebackground=C[\"card\"]).pack(side=\"left\",padx=4)\n        _lbl(r2,\"  Hash:\"); v2_hash=tk.StringVar(value=\"md5\")\n        tk.Radiobutton(r2,text=\"MD5 (fast)\",variable=v2_hash,value=\"md5\",font=FONTS[\"small\"],bg=C[\"card\"],fg=C[\"text\"],selectcolor=C[\"bg\"],activebackground=C[\"card\"]).pack(side=\"left\",padx=4)\n        tk.Radiobutton(r2,text=\"SHA256 (accurate)\",variable=v2_hash,value=\"sha256\",font=FONTS[\"small\"],bg=C[\"card\"],fg=C[\"text\"],selectcolor=C[\"bg\"],activebackground=C[\"card\"]).pack(side=\"left\",padx=4)\n        _lbl(r2,\"  Min size (KB):\"); v2_min=tk.StringVar(value=\"1\"); _entry(r2,v2_min,6)\n        _lbl(r2,\"  Extension filter (blank=all):\"); v2_ext=tk.StringVar(); _entry(r2,v2_ext,8)\n\n        # Results tree\n        dup_cols=(\"File\",\"Size\",\"Hash\",\"Group\")\n        dup_tree=ttk.Treeview(b2,columns=dup_cols,show=\"headings\",height=10,style=\"Custom.Treeview\")\n        for col,w in zip(dup_cols,[380,80,120,60]):\n            dup_tree.heading(col,text=col); dup_tree.column(col,width=w,anchor=\"w\")\n        dup_sb=ttk.Scrollbar(b2,orient=\"vertical\",command=dup_tree.yview)\n        dup_tree.configure(yscrollcommand=dup_sb.set)\n        dup_tree.pack(side=\"left\",fill=\"both\",expand=True,pady=6)\n        dup_sb.pack(side=\"right\",fill=\"y\",pady=6)\n\n        dup_stat=tk.Label(b2,text=\"\",font=FONTS[\"small\"],fg=C[\"text_dim\"],bg=C[\"card\"]); dup_stat.pack(anchor=\"w\")\n\n        def _file_hash(path, algo):\n            h=hashlib.md5() if algo==\"md5\" else hashlib.sha256()\n            try:\n                with open(path,\"rb\") as f:\n                    for chunk in iter(lambda: f.read(65536),b\"\"): h.update(chunk)\n                return h.hexdigest()\n            except Exception: return None\n\n        def _do_scan_dups():\n            folder=v2_dir.get().strip()\n            if not folder or not os.path.isdir(folder): messagebox.showwarning(\"\",\"Valid folder select karo.\"); return\n            def _r():\n                try:\n                    ft_log(\"\ud83d\udd0d Scanning for duplicates\u2026\",C[\"accent4\"])\n                    algo=v2_hash.get(); sub=v2_sub.get()\n                    try: min_bytes=int(v2_min.get())*1024\n                    except: min_bytes=1024\n                    ext_filter=v2_ext.get().strip().lower()\n                    all_files=[]\n                    if sub:\n                        for root_d,dirs,files in os.walk(folder):\n                            for f in files:\n                                fp=os.path.join(root_d,f)\n                                if ext_filter and not f.lower().endswith(ext_filter): continue\n                                try:\n                                    if os.path.getsize(fp)&gt;=min_bytes: all_files.append(fp)\n                                except: pass\n                    else:\n                        for f in os.listdir(folder):\n                            fp=os.path.join(folder,f)\n                            if not os.path.isfile(fp): continue\n                            if ext_filter and not f.lower().endswith(ext_filter): continue\n                            try:\n                                if os.path.getsize(fp)&gt;=min_bytes: all_files.append(fp)\n                            except: pass\n                    ft_log(f\"  {len(all_files)} files found, hashing\u2026\",C[\"text_dim\"])\n                    hashes={}\n                    for fp in all_files:\n                        h=_file_hash(fp,algo)\n                        if h:\n                            hashes.setdefault(h,[]).append(fp)\n                    dups={h:paths for h,paths in hashes.items() if len(paths)&gt;1}\n                    # Update tree\n                    self.after(0,lambda: dup_tree.delete(*dup_tree.get_children()))\n                    grp=0\n                    for h,paths in dups.items():\n                        grp+=1\n                        for p in paths:\n                            try: sz=_human_size(os.path.getsize(p))\n                            except: sz=\"?\"\n                            self.after(0,lambda p=p,sz=sz,h=h,g=grp: dup_tree.insert(\"\",\"end\",values=(p,sz,h[:12]+\"\u2026\",f\"#{g}\")))\n                    total_dup_files=sum(len(v) for v in dups.values())\n                    stat_msg=f\"\u2705 Found {len(dups)} duplicate groups, {total_dup_files} files\"\n                    self.after(0,lambda: dup_stat.config(text=stat_msg))\n                    ft_log(stat_msg,C[\"success\"] if dups else C[\"text_dim\"])\n                except Exception as ex: ft_log(f\"\u274c {ex}\",C[\"error\"]); self.after(0,lambda: messagebox.showerror(\"Error\",str(ex)))\n            threading.Thread(target=_r,daemon=True).start()\n\n        def _del_selected_dups():\n            sel=dup_tree.selection()\n            if not sel: messagebox.showwarning(\"\",\"Tree mein files select karo.\"); return\n            paths=[dup_tree.item(s)[\"values\"][0] for s in sel]\n            if not messagebox.askyesno(\"Delete?\",f\"{len(paths)} files permanently delete honge?\\n\\nUNDO POSSIBLE NAHI!\\n\\n\"+\"\\n\".join(paths[:10])): return\n            deleted=0\n            for p in paths:\n                try: os.remove(p); deleted+=1\n                except Exception as e: ft_log(f\"\u26a0\ufe0f {p}: {e}\",C[\"warning\"])\n            [dup_tree.delete(s) for s in sel]\n            ft_log(f\"\u2705 {deleted}/{len(paths)} duplicate files deleted.\",C[\"success\"])\n            messagebox.showinfo(\"Done!\",f\"\u2705 {deleted} files deleted.\")\n\n        def _export_dup_report():\n            out=filedialog.asksaveasfilename(title=\"Save Report\",defaultextension=\".csv\",filetypes=[(\"CSV\",\"*.csv\")])\n            if not out: return\n            import csv\n            rows=[dup_tree.item(r)[\"values\"] for r in dup_tree.get_children()]\n            with open(out,\"w\",newline=\"\",encoding=\"utf-8-sig\") as f:\n                w=csv.writer(f); w.writerow(dup_cols); w.writerows(rows)\n            ft_log(f\"\u2705 Report saved: {out}\",C[\"success\"])\n            messagebox.showinfo(\"Done!\",f\"\u2705 Report saved!\\n{out}\")\n\n        br=_row(b2)\n        tk.Button(br,text=\"\u25b6 Scan for Duplicates\",font=FONTS[\"body\"],bg=C[\"accent\"],fg=C[\"bg\"],bd=0,padx=14,pady=6,cursor=\"hand2\",command=_do_scan_dups).pack(side=\"left\",padx=(0,8))\n        tk.Button(br,text=\"\ud83d\uddd1 Delete Selected\",font=FONTS[\"body\"],bg=C[\"error\"],fg=C[\"text\"],bd=0,padx=12,pady=6,cursor=\"hand2\",command=_del_selected_dups).pack(side=\"left\",padx=(0,8))\n        tk.Button(br,text=\"\ud83d\udce5 Export CSV Report\",font=FONTS[\"body\"],bg=C[\"btn_info\"],fg=C[\"text\"],bd=0,padx=12,pady=6,cursor=\"hand2\",command=_export_dup_report).pack(side=\"left\")\n\n        _ft_switch(\"rename\")\n        return frame\n\n# ---------- RUN ----------\nif __name__ == \"__main__\":\n    # Windows + tkinter + psutil already verified at top\n    try:\n        # The maintenance UI needs elevation for printer, disk and recovery actions.\n        if not is_admin() and _admin_elevation_enabled():\n            run_as_admin()\n            sys.exit(0)\n        app = GodawariUltimateOptimizer()\n        app.mainloop()\n    except Exception as e:\n        import traceback\n        err = traceback.format_exc()\n        try:\n            messagebox.showerror(\"Startup Error \u2014 Godawari Optimizer\",\n                f\"App start nahi ho saki:\\n\\n{err[-600:]}\")\n        except:\n            print(\"STARTUP ERROR:\\n\", err)\n            input(\"Press Enter...\")\n", "creation_timestamp": "2026-05-30T17:19:02.000000Z"}, {"uuid": "5994bffb-16a2-4c24-8a7d-b435c259c29f", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2021-1678", "type": "seen", "source": "https://t.me/CyberSecurityTechnologies/2558", "content": "#Threat_Research\n1. Playing with Process Memory Integrity on Linux\nhttps://redcanary.com/blog/process-memory-integrity-linux\n2. Security Advisory: MSRPC Printer Spooler Relay (CVE-2021-1678)\nhttps://www.crowdstrike.com/blog/cve-2021-1678-printer-spooler-relay-security-advisory", "creation_timestamp": "2021-01-24T13:17:01.000000Z"}, {"uuid": "f0dfe12d-14c9-453a-951e-8d5bb7fd717b", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2021-1678", "type": "seen", "source": "https://gist.github.com/shreeshyamagency78/d0e9915d26f2af1cdfa3c422a1f2e7c4", "content": "\"\"\"\n\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\n\u2551     Godawari Computers Ultimate Optimizer Pro - v11.0           \u2551\n\u2551     Professional Edition | Real Actions | Before/After Stats    \u2551\n\u2551     Developed by: Shravan Shrimali                               \u2551\n\u2551     FULLY FIXED - READY TO RUN                                   \u2551\n\u255a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255d\n\"\"\"\n\nimport sys\nimport os\nimport struct\nimport subprocess\nimport platform\nimport base64\nimport re\nimport io\nimport zlib\nimport csv\nimport hashlib\nimport sqlite3\nimport zipfile\nimport html\nimport uuid\n\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n#  SAFE STARTUP \u2014 errors ko pakdo, user ko batao\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n# 1) Windows check\nif platform.system() != \"Windows\":\n    print(\"\u274c Yeh tool sirf Windows ke liye hai.\")\n    input(\"Press Enter to exit...\")\n    sys.exit(1)\n\n# 2) tkinter check\ntry:\n    import tkinter as tk\n    from tkinter import ttk, messagebox, scrolledtext, filedialog, simpledialog\nexcept ImportError:\n    print(\"\u274c tkinter nahi mila. Python ko reinstall karo (Include Tcl/Tk checkbox tick karo).\")\n    input(\"Press Enter to exit...\")\n    sys.exit(1)\n\ntry:\n    import customtkinter as ctk\n    ctk.set_appearance_mode(\"System\")\n    ctk.set_default_color_theme(\"blue\")\nexcept Exception:\n    ctk = None\n\n# 3) psutil offline dependency check\ndef _show_dependency_splash(title, message):\n    try:\n        splash = tk.Tk()\n        splash.withdraw()\n        win = tk.Toplevel(splash)\n        win.title(title)\n        win.configure(bg=\"#121826\")\n        win.resizable(False, False)\n        tk.Label(win, text=title, font=(\"Segoe UI\", 12, \"bold\"), fg=\"#FFB347\", bg=win[\"bg\"]).pack(padx=18, pady=(14, 6))\n        tk.Message(win, text=message, width=420, font=(\"Segoe UI\", 10), fg=\"#F0F4FA\", bg=win[\"bg\"]).pack(padx=18, pady=(0, 14))\n        tk.Button(win, text=\"OK\", command=win.destroy, bg=\"#2E5A9C\", fg=\"#F0F4FA\", bd=0, padx=12, pady=8).pack(pady=(0, 14))\n        win.update_idletasks()\n        win.lift()\n        win.attributes(\"-topmost\", True)\n        win.mainloop()\n    except Exception:\n        try:\n            root = tk.Tk(); root.withdraw()\n            messagebox.showerror(title, message)\n            root.destroy()\n        except Exception:\n            print(f\"{title}: {message}\")\n\n\ndef _ensure_psutil():\n    try:\n        import psutil\n        return psutil\n    except ImportError:\n        try:\n            _show_dependency_splash(\n                \"psutil Missing\",\n                \"psutil library nahi mili.\\n\\n\"\n                \"Runtime internet install disabled hai production/offline safety ke liye.\\n\"\n                \"Portable package me psutil bundled rakhein ya offline wheel se install karein.\"\n            )\n        except Exception:\n            pass\n        try:\n            root = tk.Tk(); root.withdraw()\n            messagebox.showerror(\n                \"psutil Missing\",\n                \"psutil library nahi mili.\\n\\n\"\n                \"Runtime internet install disabled hai production/offline safety ke liye.\\n\"\n                \"Portable package me psutil bundled rakhein ya offline wheel se install karein.\")\n            root.destroy()\n        except Exception as e:\n            print(f\"psutil dependency error: {e}\")\n        input(\"Press Enter to exit...\")\n        sys.exit(1)\n\npsutil = _ensure_psutil()\n\n# 4) winreg (Windows built-in \u2014 should always exist on Windows)\ntry:\n    import winreg\nexcept ImportError:\n    root = tk.Tk(); root.withdraw()\n    messagebox.showerror(\"Error\", \"winreg module nahi mila.\\nPython Windows version use karo.\")\n    root.destroy()\n    sys.exit(1)\n\n# 5) Standard library imports\nimport threading\nimport queue as _queue_module\nimport ctypes\nimport json\nimport inspect\nimport importlib\nfrom concurrent.futures import ThreadPoolExecutor\n\n# Windows DPI awareness ensures UI scales correctly on high-DPI displays.\nif sys.platform == \"win32\":\n    try:\n        ctypes.windll.shcore.SetProcessDpiAwareness(1)\n    except Exception:\n        pass\nimport datetime\nimport time\nimport shutil\nfrom pathlib import Path\nimport gc\nimport tempfile\nimport collections\n\ntry:\n    from godawari.optimization_profiles import get_cleaner_profiles, get_group_policy_profiles\nexcept ImportError:\n    def get_cleaner_profiles():\n        import os\n        return {\n            \"safe\": {\n                \"name\": \"Safe Clean\",\n                \"description\": \"Temp files, recycle bin, thumbnail cache \u2014 bilkul safe\",\n                \"paths\": [\n                    os.environ.get(\"TEMP\", \"\"),\n                    os.path.join(os.environ.get(\"LOCALAPPDATA\", \"\"), \"Temp\"),\n                    r\"C:\\Windows\\Temp\",\n                    os.path.join(os.environ.get(\"LOCALAPPDATA\", \"\"), \"Microsoft\", \"Windows\", \"Explorer\"),\n                ],\n                \"commands\": []\n            },\n            \"deep\": {\n                \"name\": \"Deep Clean\",\n                \"description\": \"Windows Update cache, prefetch, installer cache\",\n                \"paths\": [\n                    r\"C:\\Windows\\SoftwareDistribution\\Download\",\n                    r\"C:\\Windows\\Prefetch\",\n                ],\n                \"commands\": [\n                    'cleanmgr /sageset:99',\n                    'cleanmgr /sagerun:99',\n                ]\n            }\n        }\n\n    def get_group_policy_profiles():\n        return {\n            \"performance\": {\n                \"name\": \"Performance Mode\",\n                \"policies\": [\n                    {\"hive\": \"HKLM\",\n                     \"key\": r\"SOFTWARE\\Policies\\Microsoft\\Windows\\DataCollection\",\n                     \"name\": \"AllowTelemetry\", \"value\": 0, \"type\": \"DWORD\"},\n                    {\"hive\": \"HKLM\",\n                     \"key\": r\"SOFTWARE\\Policies\\Microsoft\\Windows\\CloudContent\",\n                     \"name\": \"DisableWindowsConsumerFeatures\", \"value\": 1, \"type\": \"DWORD\"},\n                ]\n            }\n        }\n\n\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n#  SAFE SUBPROCESS HELPERS (inline implementation)\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nclass SafeRunResult:\n    def __init__(self, output, returncode, args=None,\n                 elapsed_ms=0, timed_out=False):\n        self.output     = output\n        self.returncode = returncode\n        self.args       = args or []\n        self.elapsed_ms = elapsed_ms\n        self.timed_out  = timed_out\n\nclass PowerShellResult:\n    def __init__(self, output, returncode, elapsed_ms=0, timed_out=False):\n        self.output     = output\n        self.returncode = returncode\n        self.elapsed_ms = elapsed_ms\n        self.timed_out  = timed_out\n        self.args       = []\n\ndef safe_powershell(script, timeout=60):\n    \"\"\"Safe PowerShell execution wrapper\"\"\"\n    started = time.time()\n    try:\n        startupinfo = None\n        creationflags = 0\n        if sys.platform == \"win32\":\n            startupinfo = subprocess.STARTUPINFO()\n            startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW\n            creationflags = subprocess.CREATE_NO_WINDOW\n        encoded = base64.b64encode(script.encode(\"utf-16-le\")).decode(\"ascii\")\n        env = os.environ.copy()\n        env[\"PSModuleAnalysisCacheWriteDisabled\"] = \"1\"\n        result = subprocess.run(\n            [\"powershell\", \"-NoProfile\", \"-ExecutionPolicy\", \"Bypass\", \"-EncodedCommand\", encoded],\n            capture_output=True,\n            text=True,\n            encoding=\"utf-8\",\n            errors=\"replace\",\n            timeout=timeout,\n            startupinfo=startupinfo,\n            creationflags=creationflags,\n            env=env,\n        )\n        elapsed = int((time.time() - started) * 1000)\n        return PowerShellResult(\n            result.stdout, result.returncode, elapsed_ms=elapsed)\n    except subprocess.TimeoutExpired:\n        elapsed = int((time.time() - started) * 1000)\n        return PowerShellResult(\n            \"Timeout\", -1, elapsed_ms=elapsed, timed_out=True)\n    except Exception as e:\n        return PowerShellResult(str(e), -1)\n\ndef safe_run(cmd, timeout=60):\n    \"\"\"Safe command execution wrapper\"\"\"\n    started = time.time()\n    try:\n        result = subprocess.run(\n            cmd, capture_output=True, text=True, timeout=timeout)\n        elapsed = int((time.time() - started) * 1000)\n        return SafeRunResult(\n            result.stdout, result.returncode,\n            args=list(cmd), elapsed_ms=elapsed)\n    except subprocess.TimeoutExpired:\n        elapsed = int((time.time() - started) * 1000)\n        return SafeRunResult(\n            \"Timeout\", -1,\n            args=list(cmd), elapsed_ms=elapsed, timed_out=True)\n    except Exception as e:\n        return SafeRunResult(\n            str(e), -1,\n            args=list(cmd) if isinstance(cmd, (list, tuple)) else [])\n\ndef safe_stream_lines(cmd, callback=None):\n    \"\"\"Safe streaming command execution\"\"\"\n    try:\n        process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)\n        for line in iter(process.stdout.readline, \"\"):\n            if line and callback:\n                callback(line.strip())\n        process.wait()\n    except Exception as e:\n        if callback:\n            callback(f\"Error: {e}\")\n\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n#  WORKER MANAGER &amp; STRUCTURED LOGGER STUBS\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nclass TkWorkerManager:\n    \"\"\"Manages background worker threads for the GUI.\"\"\"\n    def __init__(self, root, workers=3, logger=None):\n        self.root = root\n        self.workers = max(1, int(workers or 1))\n        self.logger = logger\n        self._task_queue = _queue_module.Queue()\n        self._executor = ThreadPoolExecutor(max_workers=self.workers)\n        self._shutdown = False\n        self._safe_mode = False\n        try:\n            from godawari import startup_control as _startup_control\n            self._safe_mode = bool(getattr(_startup_control, \"STARTUP_FLAGS\", {}).get(\"safe_mode\", False))\n        except Exception:\n            self._safe_mode = False\n        if self._safe_mode and self.logger:\n            try:\n                self.logger.log(\"startup\", \"Safe-mode enabled: GUI background worker threads disabled\", {})\n            except Exception:\n                pass\n\n    def _execute_task(self, name, target, args, kwargs):\n        try:\n            target(*args, **kwargs)\n        except Exception as e:\n            if self.logger:\n                try:\n                    self.logger.log(\"worker_error\", f\"Worker task '{name}' failed\", {\"error\": str(e)})\n                except Exception:\n                    pass\n            try:\n                if hasattr(self.root, \"after\"):\n                    def _report(msg=str(e), task=name):\n                        if hasattr(self.root, \"_set_status\"):\n                            self.root._set_status(f\"Background task '{task}' failed: {msg}\", C.get(\"error\", \"red\"))\n                    self.root.after(0, _report)\n            except Exception:\n                pass\n\n    def submit(self, name, target, *args, **kwargs):\n        if self._safe_mode:\n            try:\n                threading.Thread(target=target, args=args, kwargs=kwargs, daemon=True).start()\n                return\n            except Exception:\n                pass\n        try:\n            self._executor.submit(self._execute_task, name, target, args, kwargs)\n        except Exception:\n            threading.Thread(target=target, args=args, kwargs=kwargs, daemon=True).start()\n\n# \u2500\u2500 Enterprise modular backend (godawari package) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n_SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))\nif _SCRIPT_DIR not in sys.path:\n    sys.path.insert(0, _SCRIPT_DIR)\ntry:\n    from godawari.system.powershell_tools import (\n        SafeRunResult,\n        PowerShellResult,\n        safe_powershell,\n        safe_run,\n        safe_stream_lines,\n    )\n    from godawari.system.admin_tools import is_admin, run_as_admin\n    from godawari.services.logger import StructuredLogger\n    from godawari.services.restore_points import RestorePointManager\n    from godawari.services.rollback import OperationRollbackVault\n    from godawari.services.session_manager import RecoverySessionManager\n    from godawari.core.health_engine import SystemHealthEngine\n    from godawari.core.menu_introspection import MenuIntrospectionEngine\n    from godawari.core.product_audit import ProductAuditEngine\n    from godawari.core.recommendations import RecommendationEngine\n    from godawari.services.maintenance_profiles import MaintenanceProfileEngine\n    from godawari.security.preflight import OperationPreflightEngine\n    from godawari.security.powershell_guard import SecurePowerShellEngine\n    from godawari.services.crash_recovery import CrashRecoveryCoordinator\n    from godawari.bootstrap import create_backend\n    _GODAWARI_BACKEND = True\nexcept ImportError:\n    _GODAWARI_BACKEND = False\n\nif not _GODAWARI_BACKEND:\n    # Minimal inline fallback \u2014 full backend: run via python main.py from project root\n    class StructuredLogger:\n        def __init__(self, log_file=\"\"):\n            self.log_file = log_file or \"\"\n        def log(self, event_type, message, data=None):\n            pass\n        def event(self, category, action, **kwargs):\n            pass\n        def read_recent(self, limit=200):\n            return []\n\n    class RestorePointManager:\n        def __init__(self, base_dir, logger=None):\n            self.base_dir = base_dir\n            self.logger = logger\n            self.policy = {\"mode\": \"ask\"}\n        def create(self, description, ask_callback=None, force=False):\n            if ask_callback and not ask_callback(description):\n                return False\n            return safe_powershell(\n                f'Checkpoint-Computer -Description \"{description}\" -RestorePointType MODIFY_SETTINGS',\n                timeout=120,\n            ).returncode == 0\n        def list_recent(self, limit=8):\n            return []\n\n    class OperationRollbackVault:\n        def __init__(self, vault_dir, logger=None):\n            self.vault_dir = vault_dir\n        def list_sessions(self, limit=50):\n            return []\n        def restore_session(self, session_id):\n            return False, \"Rollback vault unavailable\"\n\n    class RecoverySessionManager:\n        def __init__(self, sessions_dir, logger=None):\n            self.sessions_dir = sessions_dir\n        def start(self, kind, meta=None):\n            return uuid.uuid4().hex\n        def complete(self, session_id, status=\"completed\"):\n            pass\n        def list_sessions(self, include_completed=False, limit=30):\n            return []\n        def find_orphaned(self):\n            return []\n\n    class SystemHealthEngine:\n        def analyze(self):\n            return {\"score\": 0, \"grade\": \"Unknown\", \"color\": \"warning\", \"checks\": [], \"recommendations\": []}\n\n    class SecurePowerShellEngine:\n        def __init__(self, logger=None):\n            self.logger = logger\n        def run(self, script, timeout=60):\n            return safe_powershell(script, timeout=timeout)\n\n    class ProductAuditEngine:\n        def list_audits(self):\n            return []\n        def summary(self):\n            return {\"menus\": 0, \"average_maturity\": 0, \"highest_risk\": []}\n        def to_markdown(self, audits=None):\n            return \"# Godawari Optimizer Pro - Professional Menu Audit\\n\\nBackend unavailable.\\n\"\n\n    class MenuIntrospectionEngine:\n        def scan(self):\n            return {\"menus\": [], \"menu_count\": 0, \"button_count\": 0, \"option_count\": 0}\n        def to_markdown(self):\n            return \"# Godawari Optimizer Pro - Detected Software Map\\n\\nBackend unavailable.\\n\"\n\n    class OperationPreflightEngine:\n        def analyze(self, title, commands=None):\n            class _Result:\n                risk = \"medium\"\n                score = 50\n                requires_admin = True\n                requires_restore_point = True\n                requires_rollback_snapshot = True\n                dry_run_recommended = True\n                typed_confirmation = False\n                findings = []\n            return _Result()\n\n    class RecommendationEngine:\n        def build(self, health_report, audits, limit=10):\n            return {\"generated\": \"\", \"count\": 0, \"items\": []}\n\n    class MaintenanceProfileEngine:\n        def list_profiles(self):\n            return []\n\n    class CrashRecoveryCoordinator:\n        def __init__(self, session_manager, marker_file):\n            self.session_manager = session_manager\n            self.marker_file = marker_file\n        def mark_running(self):\n            pass\n        def clear_running(self):\n            pass\n        def had_unclean_exit(self):\n            return False\n        def orphaned_sessions(self):\n            return []\n\n# Legacy duplicate classes removed \u2014 use godawari package (see main.py)\n\n# \u2500\u2500 Recovery/Forensics stubs (when godawari package unavailable) \u2500\u2500\ntry:\n    from godawari.recovery.manager import RecoveryManager\n    from godawari.recovery.results import RecoveryResultItem, RecoveryResultStore\n    from godawari.recovery.safety import get_recovery_safety\n    from godawari.recovery.validation import validate_recovered_file\n    from godawari.recovery.mft import recover_deleted_mft_files\n    from godawari.recovery.progress import make_progress_callback\n    from godawari.forensics import (\n        is_forensic_engine_available,\n        scan_disk_with_forensic_engine,\n        scan_disk_entropy,\n        validate_media_headers,\n        detect_nand_erase_state,\n        raw_read,\n    )\n    import math\nexcept ImportError:\n    import math\n\n    class RecoveryResultItem:\n        def __init__(self, *a, **kw): pass\n\n    class RecoveryResultStore:\n        def __init__(self, *a, **kw): self._items = []\n        def add(self, item): self._items.append(item)\n        def all(self): return self._items\n        def clear(self): self._items = []\n        def count(self): return len(self._items)\n\n    class RecoveryManager:\n        def __init__(self, *a, **kw): pass\n        def start(self, *a, **kw): return None\n        def stop(self): pass\n\n    def get_recovery_safety(*a, **kw):\n        class _Safety:\n            def validate_output_dir(self, d, *a): return d\n        return _Safety()\n\n    def validate_recovered_file(*a, **kw): return True\n    def recover_deleted_mft_files(*a, **kw): return []\n    def make_progress_callback(*a, **kw): return lambda *x: None\n    def is_forensic_engine_available(): return False\n    def scan_disk_with_forensic_engine(*a, **kw): return []\n    def scan_disk_entropy(*a, **kw): return []\n    def validate_media_headers(*a, **kw): return {}\n    def detect_nand_erase_state(*a, **kw): return False\n    def raw_read(*a, **kw): return b\"\"\n\n\n# 6) Global exception handler \u2014 koi bhi crash user ko dikhai de\ndef _global_exc_handler(exc_type, exc_value, exc_tb):\n    import traceback\n    err = \"\".join(traceback.format_exception(exc_type, exc_value, exc_tb))\n    try:\n        root = tk.Tk(); root.withdraw()\n        messagebox.showerror(\"Unexpected Error \u2014 Godawari Optimizer\",\n            f\"Ek error aayi:\\n\\n{err[-800:]}\\n\\n\"\n            \"Screenshot lo aur developer ko bhejo.\")\n        root.destroy()\n    except:\n        print(\"FATAL ERROR:\\n\", err)\n        input(\"Press Enter to exit...\")\n    sys.exit(1)\n\nsys.excepthook = _global_exc_handler\n\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n#  SCRIPT LAST UPDATED \u2014 File modification time\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\ndef _get_script_last_updated():\n    \"\"\"Script file ki last modification date/time return karta hai.\"\"\"\n    try:\n        script_path = os.path.abspath(sys.argv[0])\n        if os.path.exists(script_path):\n            mtime = os.path.getmtime(script_path)\n            dt = datetime.datetime.fromtimestamp(mtime)\n            return dt.strftime(\"%d/%m/%Y  %H:%M\")\n    except Exception:\n        pass\n    return \"Unknown\"\n\nSCRIPT_LAST_UPDATED = _get_script_last_updated()\n\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n#  ADMIN CHECK\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\ndef is_admin():\n    try:\n        return bool(ctypes.windll.shell32.IsUserAnAdmin())\n    except Exception:\n        return False\n\ndef _gui_python_executable():\n    \"\"\"Use pythonw for GUI relaunch so the console window does not flash.\"\"\"\n    exe = sys.executable\n    try:\n        if exe and os.path.basename(exe).lower() == \"python.exe\":\n            pythonw = os.path.join(os.path.dirname(exe), \"pythonw.exe\")\n            if os.path.exists(pythonw):\n                return pythonw\n    except Exception:\n        pass\n    return exe\n\ndef run_as_admin():\n    if not is_admin():\n        script = os.path.abspath(sys.argv[0])\n        params = subprocess.list2cmdline([script] + sys.argv[1:])\n        workdir = os.path.dirname(script) or None\n        rc = ctypes.windll.shell32.ShellExecuteW(\n            None, \"runas\", _gui_python_executable(), params, workdir, 1\n        )\n        if rc &lt;= 32:\n            raise OSError(f\"Admin restart failed. ShellExecuteW code: {rc}\")\n        sys.exit()\n\ndef _admin_elevation_enabled():\n    return os.environ.get(\"GODAWARI_NO_ELEVATE\", \"0\").lower() not in (\"1\", \"true\", \"yes\")\n\ndef powershell_helper(script, timeout=60):\n    \"\"\"PowerShell helper: returns (output, return_code) with full error handling.\"\"\"\n    try:\n        result = safe_powershell(script, timeout=timeout)\n        return result.output, result.returncode\n    except FileNotFoundError:\n        return \"PowerShell nahi mila.\", -1\n    except Exception as e:\n        return f\"PowerShell error: {e}\", -1\n\ndef _ps_single_quote(value):\n    return \"'\" + str(value).replace(\"'\", \"''\") + \"'\"\n\ndef _same_windows_path(left, right):\n    try:\n        return os.path.normcase(os.path.abspath(left)) == os.path.normcase(os.path.abspath(right))\n    except Exception:\n        return False\n\ndef _console_confirm(title, message):\n    print(\"\\n\" + \"=\" * 70)\n    print(title)\n    print(\"=\" * 70)\n    print(message)\n    try:\n        answer = input(\"\\nConfirm karein? (haan/y = yes): \").strip().lower()\n        return answer in (\"y\", \"yes\", \"haan\", \"ha\", \"h\")\n    except Exception:\n        return False\n\ndef _safe_callback(callback, *args):\n    if callback:\n        try:\n            callback(*args)\n        except InterruptedError:\n            raise\n        except Exception:\n            return \"unknown\"\n\ndef _find_locking_processes_with_psutil(file_path):\n    matches = {}\n    for proc in psutil.process_iter([\"pid\", \"name\", \"exe\"]):\n        try:\n            pid = proc.info.get(\"pid\")\n            if pid == os.getpid():\n                continue\n            paths = []\n            exe = proc.info.get(\"exe\")\n            if exe:\n                paths.append(exe)\n            try:\n                for opened in proc.open_files() or []:\n                    if getattr(opened, \"path\", None):\n                        paths.append(opened.path)\n            except (psutil.AccessDenied, psutil.NoSuchProcess, psutil.ZombieProcess):\n                pass\n            if any(_same_windows_path(p, file_path) for p in paths):\n                matches[int(pid)] = {\n                    \"pid\": int(pid),\n                    \"name\": proc.info.get(\"name\") or \"Unknown\",\n                    \"exe\": exe or \"\",\n                    \"source\": \"psutil\",\n                }\n        except (psutil.AccessDenied, psutil.NoSuchProcess, psutil.ZombieProcess):\n            continue\n        except Exception:\n            continue\n    return matches\n\ndef _find_locking_processes_with_powershell(file_path):\n    # PowerShell fallback requested:\n    # Get-Process | Where-Object {$_.Modules.FileName -contains file}\n    target = _ps_single_quote(file_path)\n    script = f\"\"\"\n$target = {target}\nGet-Process | Where-Object {{\n    try {{ $_.Modules.FileName -contains $target }} catch {{ $false }}\n}} | ForEach-Object {{\n    $p = ''\n    try {{ $p = $_.Path }} catch {{ $p = '' }}\n    \"$($_.Id)|$($_.ProcessName)|$p\"\n}}\n\"\"\"\n    output, rc = powershell_helper(script, timeout=90)\n    matches = {}\n    if rc != 0 and not output:\n        return matches\n    for line in output.splitlines():\n        parts = line.strip().split(\"|\", 2)\n        if len(parts) &lt; 2 or not parts[0].isdigit():\n            continue\n        pid = int(parts[0])\n        if pid == os.getpid():\n            continue\n        matches[pid] = {\n            \"pid\": pid,\n            \"name\": parts[1] or \"Unknown\",\n            \"exe\": parts[2] if len(parts) &gt; 2 else \"\",\n            \"source\": \"powershell\",\n        }\n    return matches\n\ndef _format_process_list(processes):\n    lines = []\n    for item in processes:\n        exe = item.get(\"exe\") or \"Path unavailable\"\n        lines.append(f\"PID {item['pid']} - {item.get('name', 'Unknown')} - {exe} [{item.get('source','')}]\")\n    return \"\\n\".join(lines)\n\ndef unlock_file_if_locked(file_path, confirm_callback=None, log_callback=None):\n    \"\"\"\n    Locked file ko release karne ke liye process scan karta hai.\n    psutil first, PowerShell Modules fallback, PID show, user confirm, then terminate.\n    \"\"\"\n    try:\n        target = os.path.abspath(os.path.expandvars(os.path.expanduser(str(file_path).strip().strip('\"'))))\n        if not target:\n            raise ValueError(\"File path empty hai.\")\n        if not os.path.exists(target):\n            raise FileNotFoundError(f\"File nahi mili: {target}\")\n\n        _safe_callback(log_callback, f\"Locked file scan start: {target}\")\n        matches = _find_locking_processes_with_psutil(target)\n        ps_matches = _find_locking_processes_with_powershell(target)\n        matches.update(ps_matches)\n\n        processes = sorted(matches.values(), key=lambda x: x[\"pid\"])\n        if not processes:\n            msg = \"Koi locking process nahi mila. File abhi locked nahi lag rahi.\"\n            _safe_callback(log_callback, msg)\n            print(msg)\n            return {\"ok\": True, \"file\": target, \"terminated\": [], \"errors\": [], \"message\": msg}\n\n        details = _format_process_list(processes)\n        prompt = (\n            f\"Ye process file use kar rahe hain:\\n\\n{details}\\n\\n\"\n            \"In PID ko terminate karne se unsaved data loss ho sakta hai.\\n\"\n            \"Terminate karna hai?\"\n        )\n        confirm = confirm_callback or _console_confirm\n        if not confirm(\"Locked File Unlock\", prompt):\n            msg = \"User ne terminate cancel kiya.\"\n            _safe_callback(log_callback, msg)\n            return {\"ok\": False, \"file\": target, \"terminated\": [], \"errors\": [], \"message\": msg}\n\n        terminated = []\n        errors = []\n        for info in processes:\n            pid = info[\"pid\"]\n            try:\n                proc = psutil.Process(pid)\n                proc.terminate()\n                try:\n                    proc.wait(timeout=8)\n                except psutil.TimeoutExpired:\n                    pass\n                terminated.append(pid)\n                _safe_callback(log_callback, f\"PID terminate kiya: {pid} ({info.get('name','Unknown')})\")\n            except psutil.NoSuchProcess:\n                terminated.append(pid)\n            except psutil.AccessDenied:\n                errors.append(f\"PID {pid}: access denied. Admin mode me run karein.\")\n            except Exception as e:\n                errors.append(f\"PID {pid}: {e}\")\n\n        ok = len(errors) == 0\n        msg = f\"Terminate complete. Terminated: {len(terminated)}, Errors: {len(errors)}\"\n        _safe_callback(log_callback, msg)\n        if errors:\n            _safe_callback(log_callback, \"\\n\".join(errors))\n        return {\"ok\": ok, \"file\": target, \"terminated\": terminated, \"errors\": errors, \"message\": msg}\n    except Exception as e:\n        msg = f\"Unlock error: {e}\"\n        _safe_callback(log_callback, msg)\n        print(msg)\n        return {\"ok\": False, \"file\": str(file_path), \"terminated\": [], \"errors\": [msg], \"message\": msg}\n\ndef _human_size(num_bytes):\n    try:\n        value = float(num_bytes)\n        for unit in (\"B\", \"KB\", \"MB\", \"GB\", \"TB\"):\n            if value &lt; 1024 or unit == \"TB\":\n                return f\"{value:.1f} {unit}\" if unit != \"B\" else f\"{int(value)} B\"\n            value /= 1024\n    except Exception:\n        return \"0 B\"\n\ndef _is_dangerous_cleanup_target(folder_path):\n    try:\n        path = os.path.normcase(os.path.abspath(folder_path))\n        drive, tail = os.path.splitdrive(path)\n        if tail in (\"\\\\\", \"\"):\n            return True, \"Drive root delete nahi kar sakte.\"\n        protected = [\n            os.environ.get(\"SystemRoot\", r\"C:\\Windows\"),\n            os.environ.get(\"ProgramFiles\", r\"C:\\Program Files\"),\n            os.environ.get(\"ProgramFiles(x86)\", r\"C:\\Program Files (x86)\"),\n            os.environ.get(\"ProgramData\", r\"C:\\ProgramData\"),\n            os.environ.get(\"USERPROFILE\", \"\"),\n        ]\n        for item in protected:\n            if item and path == os.path.normcase(os.path.abspath(item)):\n                return True, f\"Protected folder delete block kiya: {item}\"\n    except Exception as e:\n        return True, f\"Path safety check failed: {e}\"\n    return False, \"\"\n\ndef _program_terms_from_folder(folder_path):\n    base = os.path.basename(os.path.normpath(folder_path)).lower()\n    raw = \"\".join(ch if ch.isalnum() else \" \" for ch in base).split()\n    blocked = {\"app\", \"program\", \"files\", \"setup\", \"install\", \"windows\", \"system\"}\n    return [w for w in raw if len(w) &gt;= 3 and w not in blocked]\n\ndef _registry_value_text(key):\n    chunks = []\n    try:\n        i = 0\n        while True:\n            try:\n                name, value, _ = winreg.EnumValue(key, i)\n                chunks.append(str(name))\n                chunks.append(str(value))\n                i += 1\n            except OSError:\n                break\n    except Exception:\n        pass\n    return \" \".join(chunks).lower()\n\ndef _find_registry_entries_for_program(folder_path, max_results=100):\n    folder_text = os.path.normcase(os.path.abspath(folder_path)).lower()\n    terms = _program_terms_from_folder(folder_path)\n    if not terms:\n        terms = [os.path.basename(os.path.normpath(folder_path)).lower()]\n    roots = [\n        (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\"),\n        (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\"),\n        (\"HKCU\", winreg.HKEY_CURRENT_USER, r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\"),\n        (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\"),\n        (\"HKCU\", winreg.HKEY_CURRENT_USER, r\"SOFTWARE\"),\n        (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Services\"),\n    ]\n    found = []\n    deadline = time.time() + 8\n\n    def check_subkey(hive_name, hive, path):\n        if len(found) &gt;= max_results or time.time() &gt; deadline:\n            return\n        try:\n            key = winreg.OpenKey(hive, path, 0, winreg.KEY_READ)\n        except Exception:\n            return\n        try:\n            text = f\"{path.lower()} {_registry_value_text(key)}\"\n            if folder_text in text or any(term in text for term in terms):\n                found.append(f\"{hive_name}\\\\{path}\")\n        finally:\n            try:\n                winreg.CloseKey(key)\n            except Exception:\n                pass\n\n    for hive_name, hive, root_path in roots:\n        if len(found) &gt;= max_results or time.time() &gt; deadline:\n            break\n        try:\n            root = winreg.OpenKey(hive, root_path, 0, winreg.KEY_READ)\n        except Exception:\n            continue\n        try:\n            i = 0\n            while len(found) &lt; max_results and time.time() &lt;= deadline:\n                try:\n                    sub = winreg.EnumKey(root, i)\n                    i += 1\n                    check_subkey(hive_name, hive, root_path + \"\\\\\" + sub)\n                except OSError:\n                    break\n                except Exception:\n                    continue\n        finally:\n            try:\n                winreg.CloseKey(root)\n            except Exception:\n                pass\n    return found\n\ndef _scan_folder_with_os_walk(folder_path, max_preview=80):\n    info = {\"files\": 0, \"dirs\": 0, \"size\": 0, \"preview\": [], \"errors\": []}\n\n    def on_error(error):\n        info[\"errors\"].append(str(error))\n\n    for root, dirs, files in os.walk(folder_path, onerror=on_error):\n        info[\"dirs\"] += len(dirs)\n        for name in files:\n            path = os.path.join(root, name)\n            info[\"files\"] += 1\n            try:\n                info[\"size\"] += os.path.getsize(path)\n            except Exception as e:\n                info[\"errors\"].append(f\"{path}: {e}\")\n            if len(info[\"preview\"]) &lt; max_preview:\n                info[\"preview\"].append(path)\n    return info\n\ndef _rmtree_error_handler(func, path, exc_info):\n    try:\n        os.chmod(path, 0o700)\n        func(path)\n    except Exception:\n        raise\n\ndef deep_cleanup_program(folder_path, confirm_callback=None, log_callback=None):\n    \"\"\"\n    Program folder ka deep cleanup: os.walk scan, winreg registry clues, user confirm, shutil.rmtree.\n    Registry entries sirf list hoti hain; delete folder ko shutil.rmtree se kiya jata hai.\n    \"\"\"\n    try:\n        target = os.path.abspath(os.path.expandvars(os.path.expanduser(str(folder_path).strip().strip('\"'))))\n        if not target:\n            raise ValueError(\"Folder path empty hai.\")\n        if not os.path.isdir(target):\n            raise NotADirectoryError(f\"Folder nahi mila: {target}\")\n\n        blocked, reason = _is_dangerous_cleanup_target(target)\n        if blocked:\n            raise PermissionError(reason)\n\n        admin_note = \"\"\n        if not is_admin():\n            admin_note = \"Warning: App admin mode me nahi hai; kuch files delete nahi ho sakti.\\n\\n\"\n            _safe_callback(log_callback, admin_note.strip())\n\n        _safe_callback(log_callback, f\"Deep cleanup scan start: {target}\")\n        scan = _scan_folder_with_os_walk(target)\n        reg_entries = _find_registry_entries_for_program(target)\n\n        preview = \"\\n\".join(scan[\"preview\"][:40])\n        if scan[\"files\"] &gt; 40:\n            preview += f\"\\n... aur {scan['files'] - 40} file(s)\"\n        reg_preview = \"\\n\".join(reg_entries[:40]) if reg_entries else \"Koi matching registry clue nahi mila.\"\n        if len(reg_entries) &gt; 40:\n            reg_preview += f\"\\n... aur {len(reg_entries) - 40} registry entry\"\n\n        prompt = (\n            f\"{admin_note}\"\n            f\"Folder: {target}\\n\"\n            f\"Files: {scan['files']}\\n\"\n            f\"Subfolders: {scan['dirs']}\\n\"\n            f\"Approx Size: {_human_size(scan['size'])}\\n\"\n            f\"Registry clues: {len(reg_entries)}\\n\"\n        )\n        if scan[\"errors\"]:\n            prompt += f\"Scan warnings: {len(scan['errors'])}\\n\"\n        prompt += (\n            f\"\\nFile list preview:\\n{preview or 'Folder empty hai.'}\\n\\n\"\n            f\"Registry list preview:\\n{reg_preview}\\n\\n\"\n            \"Confirm karne par folder permanently delete hoga:\\n\"\n            \"shutil.rmtree(folder_path)\\n\\n\"\n            \"Delete karein?\"\n        )\n\n        confirm = confirm_callback or _console_confirm\n        if not confirm(\"Deep Cleanup Program\", prompt):\n            msg = \"User ne deep cleanup cancel kiya.\"\n            _safe_callback(log_callback, msg)\n            return {\"ok\": False, \"folder\": target, \"deleted\": False, \"registry_entries\": reg_entries, \"message\": msg}\n\n        shutil.rmtree(target, onerror=_rmtree_error_handler)\n        msg = f\"Deep cleanup complete: {target} delete ho gaya.\"\n        _safe_callback(log_callback, msg)\n        return {\n            \"ok\": True,\n            \"folder\": target,\n            \"deleted\": True,\n            \"files\": scan[\"files\"],\n            \"dirs\": scan[\"dirs\"],\n            \"size\": scan[\"size\"],\n            \"registry_entries\": reg_entries,\n            \"scan_errors\": scan[\"errors\"],\n            \"message\": msg,\n        }\n    except Exception as e:\n        msg = f\"Deep cleanup error: {e}\"\n        _safe_callback(log_callback, msg)\n        print(msg)\n        return {\"ok\": False, \"folder\": str(folder_path), \"deleted\": False, \"registry_entries\": [], \"errors\": [msg], \"message\": msg}\n\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n#  COLOR THEME\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n# ---------------------------------------------------------------------\n# RAW DATA RECOVERY ENGINE\n# ---------------------------------------------------------------------\nSECTOR_SIZE = 512\nDEFAULT_RAW_DISK = \"\"  # User ko disk select karni hogi \u2014 PhysicalDrive0 default unsafe tha\nRAW_READ_RETRIES = 3\nRAW_MIN_READ_CHUNK = 4096\nRAW_SCAN_DEVICE_CHUNK = 2 * 1024 * 1024\nRAW_SCAN_IMAGE_CHUNK = 8 * 1024 * 1024\nRAW_SCAN_OVERLAP = 1024 * 1024\nRAW_SCAN_DEVICE_PAUSE_MS = 25\nRAW_SCAN_PROGRESS_STEP = 32 * 1024 * 1024\n\nSIGNATURES = {\n    \"JPG\": {\n        \"ext\": \".jpg\",\n        \"headers\": [b\"\\xFF\\xD8\\xFF\"],\n        \"footer\": b\"\\xFF\\xD9\",\n        \"max_size\": 50 * 1024 * 1024,\n        \"description\": \"JPEG image\",\n    },\n    \"PDF\": {\n        \"ext\": \".pdf\",\n        \"headers\": [b\"%PDF\"],\n        \"footer\": b\"%%EOF\",\n        \"max_size\": 200 * 1024 * 1024,\n        \"description\": \"PDF document\",\n    },\n    \"MP4\": {\n        \"ext\": \".mp4\",\n        \"headers\": [b\"ftyp\"],\n        \"footer\": None,\n        \"max_size\": 2 * 1024 * 1024 * 1024,\n        \"description\": \"MP4 video\",\n    },\n    \"ZIP\": {\n        \"ext\": \".zip\",\n        \"headers\": [b\"PK\\x03\\x04\"],\n        \"footer\": b\"PK\\x05\\x06\",\n        \"max_size\": 500 * 1024 * 1024,\n        \"description\": \"ZIP archive\",\n    },\n    \"EXE\": {\n        \"ext\": \".exe\",\n        \"headers\": [b\"MZ\"],\n        \"footer\": None,\n        \"max_size\": 200 * 1024 * 1024,\n        \"description\": \"Windows executable\",\n    },\n}\n\ndef _raw_progress(progress_callback, message):\n    _safe_callback(progress_callback, message)\n\ndef _is_raw_device_path(path):\n    return bool(re.match(r\"^\\\\\\\\\\.\\\\(PhysicalDrive\\d+|[A-Z]:)$\", str(path or \"\"), re.I))\n\ndef _require_raw_admin(disk_path=None):\n    if (disk_path is None or _is_raw_device_path(disk_path)) and not is_admin():\n        raise PermissionError(\"Admin rights chahiye. Raw disk access ke liye Run as Administrator karein.\")\n\ndef _powershell_read_raw_bytes(disk_path, offset, length):\n    script = f\"\"\"\n$path = {_ps_single_quote(disk_path)}\n$offset = [Int64]{int(offset)}\n$length = [Int32]{int(length)}\n$fs = [System.IO.File]::Open($path, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::ReadWrite)\ntry {{\n    [void]$fs.Seek($offset, [System.IO.SeekOrigin]::Begin)\n    $buffer = New-Object byte[] $length\n    $read = $fs.Read($buffer, 0, $length)\n    if ($read -le 0) {{ \"\" }} else {{ [Convert]::ToBase64String($buffer, 0, $read) }}\n}} finally {{\n    $fs.Close()\n}}\n\"\"\"\n    output, rc = powershell_helper(script, timeout=120)\n    if rc != 0:\n        raise OSError(f\"PowerShell raw read failed: {output}\")\n    output = output.strip()\n    if not output:\n        return b\"\"\n    try:\n        return base64.b64decode(output)\n    except Exception as e:\n        raise OSError(f\"PowerShell fallback decode failed: {e}. Output: {output[:120]}\")\n\ndef _read_raw_at(disk_path, offset, length, disk_handle=None):\n    if length &lt;= 0:\n        return b\"\"\n    if disk_handle is not None:\n        try:\n            disk_handle.seek(offset)\n            return disk_handle.read(length)\n        except Exception:\n            return \"Unknown\"\n\n    try:\n        from godawari.forensics.engine import raw_read as _forensic_raw_read\n    except Exception:\n        _forensic_raw_read = None\n\n    if _forensic_raw_read is not None:\n        try:\n            return _forensic_raw_read(disk_path, offset, int(length))\n        except Exception:\n            pass\n\n    last_error = None\n    read_len = int(length)\n    for _ in range(RAW_READ_RETRIES):\n        try:\n            with open(disk_path, \"rb\", buffering=0) as disk:\n                disk.seek(offset)\n                return disk.read(read_len)\n        except Exception as e:\n            last_error = e\n            read_len = max(RAW_MIN_READ_CHUNK, read_len // 2)\n    try:\n        return _powershell_read_raw_bytes(disk_path, offset, length)\n    except Exception:\n        if last_error:\n            raise last_error\n        raise\n\ndef _scan_chunk_profile(disk_path, block_size):\n    base = max(int(block_size or SECTOR_SIZE) * 1024, RAW_SCAN_DEVICE_CHUNK)\n    if _is_raw_device_path(disk_path):\n        chunk_size = min(max(base, RAW_SCAN_DEVICE_CHUNK), 4 * 1024 * 1024)\n        pause_s = RAW_SCAN_DEVICE_PAUSE_MS / 1000.0\n    else:\n        chunk_size = min(max(base, RAW_SCAN_IMAGE_CHUNK), 16 * 1024 * 1024)\n        pause_s = 0.0\n    return chunk_size, pause_s\n\ndef _detect_signature_in_sector(sector, sector_offset, file_types):\n    hits = []\n    for file_type in file_types:\n        meta = SIGNATURES.get(file_type)\n        if not meta:\n            continue\n        for header in meta[\"headers\"]:\n            start = 0\n            while True:\n                pos = sector.find(header, start)\n                if pos &lt; 0:\n                    break\n                real_offset = sector_offset + pos\n                confidence = \"medium\"\n                if file_type == \"MP4\":\n                    if pos &lt; 4:\n                        start = pos + 1\n                        continue\n                    box_start = pos - 4\n                    try:\n                        box_size = struct.unpack(\"&gt;I\", sector[box_start:box_start + 4])[0]\n                    except Exception:\n                        box_size = 0\n                    if box_size &lt; 8 or box_size &gt; 1024 * 1024 * 1024:\n                        start = pos + 1\n                        continue\n                    real_offset = sector_offset + box_start\n                    confidence = \"high\"\n                elif pos == 0:\n                    confidence = \"high\"\n                hits.append({\n                    \"disk_path\": \"\",\n                    \"offset\": real_offset,\n                    \"sector\": real_offset // SECTOR_SIZE,\n                    \"file_type\": file_type,\n                    \"extension\": meta[\"ext\"],\n                    \"signature\": header.hex(\" \").upper(),\n                    \"confidence\": confidence,\n                    \"description\": meta[\"description\"],\n                })\n                start = pos + 1\n    return hits\n\ndef scan_disk_for_files(disk_path, max_bytes=None, start_offset=0, file_types=None, progress_callback=None, stats_callback=None):\n    \"\"\"\n    Raw disk ko 512-byte sector-by-sector scan karta hai aur JPG/PDF/MP4/ZIP/EXE signatures dhundta hai.\n    Example: scan_disk_for_files(DEFAULT_RAW_DISK)\n    \"\"\"\n    disk_path = str(disk_path or DEFAULT_RAW_DISK).strip()\n    if not disk_path:\n        raise ValueError(\"Scan ke liye source disk/image select karein\")\n    _require_raw_admin(disk_path)\n    file_types = [ft.upper().strip(\".\") for ft in (file_types or SIGNATURES.keys()) if ft]\n    file_types = [ft for ft in file_types if ft in SIGNATURES]\n    if not file_types:\n        file_types = list(SIGNATURES.keys())\n    chunk_size = 1024 * 1024\n    chunk_size -= chunk_size % SECTOR_SIZE\n    offset = int(start_offset)\n    scanned = 0\n    found = []\n    seen = set()\n    disk = None\n    use_powershell = False\n    total_size = int(max_bytes) if max_bytes is not None else _disk_source_size(disk_path)\n    try:\n        try:\n            from godawari.forensics.engine import scan_disk_with_forensic_engine as _forensic_scan\n        except Exception:\n            _forensic_scan = None\n\n        if _forensic_scan is not None:\n            try:\n                found = _forensic_scan(disk_path, max_bytes=max_bytes, start_offset=offset, file_types=file_types, progress_callback=progress_callback)\n                if found:\n                    return found\n                _raw_progress(progress_callback, \"Forensic scan empty \u2014 Python sector scan fallback\")\n            except Exception as e:\n                _raw_progress(progress_callback, f\"Forensic engine failed, Python fallback use ho raha hai: {e}\")\n\n        try:\n            disk = open(disk_path, \"rb\", buffering=0)\n            disk.seek(offset)\n            _raw_progress(progress_callback, f\"Raw disk open ho gaya: {disk_path}\")\n        except Exception as e:\n            use_powershell = True\n            _raw_progress(progress_callback, f\"Python raw open failed, PowerShell fallback use ho raha hai: {e}\")\n\n        while True:\n            if max_bytes is not None:\n                remaining = int(max_bytes) - scanned\n                if remaining &lt;= 0:\n                    break\n                read_len = min(chunk_size, remaining)\n            else:\n                read_len = chunk_size\n\n            if use_powershell:\n                data = _powershell_read_raw_bytes(disk_path, offset + scanned, read_len)\n            else:\n                data = disk.read(read_len)\n            if not data:\n                break\n\n            usable = len(data) - (len(data) % SECTOR_SIZE)\n            for pos in range(0, usable, SECTOR_SIZE):\n                sector_offset = offset + scanned + pos\n                sector = data[pos:pos + SECTOR_SIZE]\n                for hit in _detect_signature_in_sector(sector, sector_offset, file_types):\n                    key = (hit[\"offset\"], hit[\"file_type\"])\n                    if key in seen:\n                        continue\n                    seen.add(key)\n                    hit[\"disk_path\"] = disk_path\n                    found.append(hit)\n\n            scanned += len(data)\n            if scanned % (4 * 1024 * 1024) &lt; chunk_size:\n                if total_size:\n                    pct = min(100, int((scanned / total_size) * 100))\n                    _raw_progress(progress_callback, f\"Raw scan {pct}% complete \u2014 {_human_size(scanned)} scanned, {len(found)} signatures mili\")\n                else:\n                    _raw_progress(progress_callback, f\"Raw scan: {_human_size(scanned)} scanned, {len(found)} file signature mile\")\n                if stats_callback:\n                    try:\n                        stats_callback({\n                            \"pct\": pct if total_size else min(99, scanned // (32 * 1024 * 1024)),\n                            \"files_found\": len(found),\n                            \"bytes_scanned\": scanned,\n                            \"message\": f\"{len(found)} signatures \u2014 {_human_size(scanned)} scanned\",\n                        })\n                    except Exception:\n                        pass\n    except Exception as e:\n        _raw_progress(progress_callback, f\"Raw scan error: {e}\")\n        raise\n    finally:\n        if disk is not None:\n            try:\n                disk.close()\n            except Exception:\n                pass\n    _raw_progress(progress_callback, f\"Scan complete: {len(found)} signatures mile\")\n    return found\n\ndef _read_until_footer(disk_path, offset, footer, max_size, disk_handle=None, progress_callback=None):\n    data = bytearray()\n    read_pos = int(offset)\n    overlap = max(len(footer) + 16, 64)\n    while len(data) &lt; max_size:\n        to_read = min(1024 * 1024, max_size - len(data))\n        chunk = _read_raw_at(disk_path, read_pos, to_read, disk_handle=disk_handle)\n        if not chunk:\n            break\n        previous_tail = bytes(data[-overlap:])\n        data.extend(chunk)\n        search_area = previous_tail + chunk\n        idx = search_area.find(footer)\n        if idx &gt;= 0:\n            absolute_end = len(data) - len(chunk) - len(previous_tail) + idx + len(footer)\n            if absolute_end &lt; 0:\n                absolute_end = len(data)\n            return bytes(data[:absolute_end])\n        read_pos += len(chunk)\n        if len(data) % (32 * 1024 * 1024) &lt; 1024 * 1024:\n            _raw_progress(progress_callback, f\"Boundary dhund rahe hain: {_human_size(len(data))} read\")\n    return bytes(data)\n\ndef _estimate_mp4_size(disk_path, offset, max_size, disk_handle=None):\n    pos = int(offset)\n    total = 0\n    boxes = 0\n    while total &lt; max_size and boxes &lt; 10000:\n        header = _read_raw_at(disk_path, pos, 16, disk_handle=disk_handle)\n        if len(header) &lt; 8:\n            break\n        box_size, box_type = struct.unpack(\"&gt;I4s\", header[:8])\n        header_len = 8\n        if boxes == 0 and box_type != b\"ftyp\":\n            return None\n        if box_size == 1:\n            if len(header) &lt; 16:\n                break\n            box_size = struct.unpack(\"&gt;Q\", header[8:16])[0]\n            header_len = 16\n        elif box_size == 0:\n            break\n        if box_size &lt; header_len or box_size &gt; (max_size - total):\n            break\n        total += box_size\n        pos += box_size\n        boxes += 1\n    return total if total &gt;= 8 else None\n\ndef _estimate_exe_size(disk_path, offset, max_size, disk_handle=None):\n    head = _read_raw_at(disk_path, offset, 4096, disk_handle=disk_handle)\n    if len(head) &lt; 0x40 or head[:2] != b\"MZ\":\n        return None\n    try:\n        pe_offset = struct.unpack_from(\"= 0 and len(data) &gt;= eocd + 22:\n            comment_len = struct.unpack_from(\" len(data):\n                extra = _read_raw_at(disk_path, offset + len(data), wanted - len(data), disk_handle=disk_handle)\n                data += extra\n            data = data[:wanted]\n    else:\n        data = _read_until_footer(disk_path, offset, meta[\"footer\"], limit, disk_handle=disk_handle, progress_callback=progress_callback)\n\n    if not data:\n        raise OSError(\"Koi data extract nahi hua.\")\n    safe_offset = f\"{offset:012X}\"\n    out_path = safety.validate_write_path(\n        os.path.join(output_dir, f\"recovered_{file_type.lower()}_{safe_offset}{meta['ext']}\"),\n        disk_path,\n    )\n    with open(out_path, \"wb\") as out:\n        out.write(data)\n    complete = True\n    if meta.get(\"footer\") and meta[\"footer\"] not in data[-4096:]:\n        complete = False\n    _raw_progress(progress_callback, f\"Extraction done: {out_path} ({_human_size(len(data))})\")\n    return {\n        \"ok\": True,\n        \"path\": out_path,\n        \"bytes\": len(data),\n        \"file_type\": file_type,\n        \"offset\": offset,\n        \"complete_boundary\": complete,\n    }\n\ndef create_disk_image(source_disk, img_path, max_bytes=None, progress_callback=None):\n    \"\"\"Raw disk/volume ka IMG backup banata hai. Example source: DEFAULT_RAW_DISK.\"\"\"\n    source_disk = str(source_disk or DEFAULT_RAW_DISK)\n    if not source_disk:\n        raise ValueError(\"Source disk select karein \u2014 default PhysicalDrive0 ab disabled hai\")\n    _require_raw_admin(source_disk)\n    try:\n        from godawari.services.config_manager import ConfigManager\n        safety = get_recovery_safety(ConfigManager())\n    except Exception:\n        safety = get_recovery_safety()\n    img_path = safety.validate_write_path(os.path.abspath(os.path.expanduser(str(img_path))), source_disk)\n    os.makedirs(os.path.dirname(img_path) or os.getcwd(), exist_ok=True)\n    chunk_size = 4 * 1024 * 1024\n    copied = 0\n    disk = None\n    use_powershell = False\n    total_size = int(max_bytes) if max_bytes is not None else _disk_source_size(source_disk)\n    last_pct = -1\n    last_update = 0\n    try:\n        try:\n            disk = open(source_disk, \"rb\", buffering=0)\n            _raw_progress(progress_callback, f\"IMG source open ho gaya: {source_disk}\")\n        except Exception as e:\n            use_powershell = True\n            _raw_progress(progress_callback, f\"Python raw open failed, PowerShell fallback use hoga: {e}\")\n        with open(img_path, \"wb\") as out:\n            while True:\n                if max_bytes is not None:\n                    remaining = int(max_bytes) - copied\n                    if remaining &lt;= 0:\n                        break\n                    read_len = min(chunk_size, remaining)\n                else:\n                    read_len = chunk_size\n                if use_powershell:\n                    data = _powershell_read_raw_bytes(source_disk, copied, read_len)\n                else:\n                    data = disk.read(read_len)\n                if not data:\n                    break\n                out.write(data)\n                copied += len(data)\n                now = time.time()\n                progress_text = None\n                if total_size:\n                    pct = min(100, int((copied / total_size) * 100))\n                    if pct != last_pct or now - last_update &gt; 1:\n                        last_pct = pct\n                        last_update = now\n                        progress_text = f\"IMG creation: {pct}% complete ({_human_size(copied)} copied)\"\n                elif now - last_update &gt; 1:\n                    last_update = now\n                    progress_text = f\"IMG ban rahi hai: {_human_size(copied)} copied\"\n                if progress_text:\n                    _raw_progress(progress_callback, progress_text)\n    finally:\n        if disk is not None:\n            try:\n                disk.close()\n            except Exception:\n                pass\n    _raw_progress(progress_callback, f\"IMG complete: {img_path} ({_human_size(copied)})\")\n    return {\"ok\": True, \"img_path\": img_path, \"bytes\": copied}\n\ndef copy_disk_range_to_img(source_disk, img_path, start_offset=0, max_bytes=None, progress_callback=None):\n    \"\"\"Hex/sector viewer se selected range ko IMG me export karta hai.\"\"\"\n    source_disk = str(source_disk or DEFAULT_RAW_DISK)\n    if not source_disk:\n        raise ValueError(\"Source disk select karein\")\n    _require_raw_admin(source_disk)\n    try:\n        from godawari.services.config_manager import ConfigManager\n        safety = get_recovery_safety(ConfigManager())\n    except Exception:\n        safety = get_recovery_safety()\n    img_path = safety.validate_write_path(os.path.abspath(os.path.expanduser(str(img_path))), source_disk)\n    os.makedirs(os.path.dirname(img_path) or os.getcwd(), exist_ok=True)\n    start_offset = int(start_offset)\n    chunk_size = 4 * 1024 * 1024\n    copied = 0\n    source_size = _disk_source_size(source_disk)\n    if max_bytes is None and source_size:\n        max_bytes = max(0, source_size - start_offset)\n    total_size = int(max_bytes) if max_bytes is not None else None\n    last_pct = -1\n    last_update = 0\n    with open(img_path, \"wb\") as out:\n        while True:\n            if max_bytes is not None:\n                remaining = int(max_bytes) - copied\n                if remaining &lt;= 0:\n                    break\n                read_len = min(chunk_size, remaining)\n            else:\n                read_len = chunk_size\n            data = _read_raw_at(source_disk, start_offset + copied, read_len)\n            if not data:\n                break\n            out.write(data)\n            copied += len(data)\n            now = time.time()\n            progress_text = None\n            if total_size:\n                pct = min(100, int((copied / total_size) * 100))\n                if pct != last_pct or now - last_update &gt; 1:\n                    last_pct = pct\n                    last_update = now\n                    progress_text = f\"Sector IMG export: {pct}% complete ({_human_size(copied)} copied)\"\n            elif now - last_update &gt; 1:\n                last_update = now\n                progress_text = f\"Sector IMG export: {_human_size(copied)} copied\"\n            if progress_text:\n                _raw_progress(progress_callback, progress_text)\n    _raw_progress(progress_callback, f\"Sector IMG complete: {img_path} ({_human_size(copied)})\")\n    return {\"ok\": True, \"img_path\": img_path, \"bytes\": copied, \"start_offset\": start_offset}\n\ndef raw_hex_viewer(sector_num, disk_path=DEFAULT_RAW_DISK, sectors=1, bytes_per_line=16):\n    \"\"\"DiskGenius style raw hex view return karta hai.\"\"\"\n    _require_raw_admin(disk_path)\n    sector_num = int(sector_num)\n    sectors = max(1, int(sectors))\n    offset = sector_num * SECTOR_SIZE\n    data = _read_raw_at(disk_path, offset, sectors * SECTOR_SIZE)\n    if not data:\n        raise OSError(f\"No bytes read at sector {sector_num}. Source/sector may be invalid or access is blocked.\")\n    checksum = sum(data) &amp; 0xFFFFFFFF\n    non_zero = sum(1 for b in data if b)\n    lines = [\n        f\"Disk: {disk_path}\",\n        f\"REAL RAW READ: open/read from disk device, not simulated\",\n        f\"Sector: {sector_num}  Offset: 0x{offset:016X}  Bytes: {len(data)}  NonZero: {non_zero}  Checksum32: 0x{checksum:08X}\",\n        \"-\" * 78,\n    ]\n    for i in range(0, len(data), bytes_per_line):\n        chunk = data[i:i + bytes_per_line]\n        hex_part = \" \".join(f\"{b:02X}\" for b in chunk)\n        hex_part = hex_part.ljust(bytes_per_line * 3 - 1)\n        ascii_part = \"\".join(chr(b) if 32 &lt;= b &lt; 127 else \".\" for b in chunk)\n        lines.append(f\"{offset + i:016X}  {hex_part}  |{ascii_part}|\")\n    return \"\\n\".join(lines)\n\n# ---------------------------------------------------------------------\n# PHOTOREC-STYLE DEEP SCAN ENGINE\n# ---------------------------------------------------------------------\nPHOTOREC_SIGNATURES = {\n    b\"\\xFF\\xD8\\xFF\": (\"jpg\", b\"\\xFF\\xD9\"),\n    b\"\\x89PNG\\r\\n\\x1A\\n\": (\"png\", b\"IEND\"),\n    b\"%PDF-\": (\"pdf\", b\"%%EOF\"),\n    b\"PK\\x03\\x04\": (\"zip\", b\"PK\\x05\\x06\"),\n    b\"MZ\": (\"exe\", None),\n    b\"GIF87a\": (\"gif\", b\"\\x3B\"),\n    b\"GIF89a\": (\"gif\", b\"\\x3B\"),\n    b\"BM\": (\"bmp\", None),\n    b\"RIFF\": (\"riff\", None),\n    b\"ID3\": (\"mp3\", None),\n    b\"\\xFF\\xFB\": (\"mp3\", None),\n    b\"fLaC\": (\"flac\", None),\n    b\"OggS\": (\"ogg\", None),\n    b\"\\x1F\\x8B\\x08\": (\"gz\", None),\n    b\"BZh\": (\"bz2\", None),\n    b\"\\xFD7zXZ\\x00\": (\"xz\", b\"YZ\"),\n    b\"7z\\xBC\\xAF\\x27\\x1C\": (\"7z\", None),\n    b\"Rar!\\x1A\\x07\\x00\": (\"rar\", None),\n    b\"Rar!\\x1A\\x07\\x01\\x00\": (\"rar5\", None),\n    b\"\\xD0\\xCF\\x11\\xE0\\xA1\\xB1\\x1A\\xE1\": (\"ole\", None),\n    b\"{\\\\rtf\": (\"rtf\", b\"}\"),\n    b\"SQLite format 3\\x00\": (\"sqlite\", None),\n    b\"\\x00\\x00\\x01\\x00\": (\"ico\", None),\n    b\"8BPS\": (\"psd\", None),\n    b\"MSCF\": (\"cab\", None),\n    b\"\\x25!PS\": (\"ps\", b\"%%EOF\"),\n    b\"FLV\\x01\": (\"flv\", None),\n    b\"\\x1A\\x45\\xDF\\xA3\": (\"mkv\", None),\n    b\"\\x00\\x00\\x01\\xBA\": (\"mpg\", None),\n    b\"\\x00\\x00\\x01\\xB3\": (\"mpg\", None),\n}\n\nSIGNATURE_BYTES = PHOTOREC_SIGNATURES\n\nPHOTOREC_REGEX_SIGNATURES = [\n    (re.compile(br\"\\x00\\x00\\x00[\\x08-\\xFF]ftyp\"), \"mp4\", None),\n]\n\nPHOTOREC_EXT_MAP = {\n    \"riff\": \"wav\",\n    \"ole\": \"doc\",\n    \"rar5\": \"rar\",\n}\n\ndef _load_custom_signature_config():\n    base_dir = os.path.join(os.environ.get(\"APPDATA\", \"\"), \"GodawariOptimizer\")\n    cfg_path = os.path.join(base_dir, \"custom_signatures.json\")\n    if not os.path.isfile(cfg_path):\n        return 0\n    loaded = 0\n    try:\n        with open(cfg_path, \"r\", encoding=\"utf-8\") as f:\n            payload = json.load(f)\n        items = payload if isinstance(payload, list) else payload.get(\"signatures\", [])\n        for item in items:\n            if not isinstance(item, dict):\n                continue\n            header_hex = str(item.get(\"header_hex\", \"\")).replace(\" \", \"\")\n            file_type = str(item.get(\"file_type\", \"\")).strip().lower()\n            if not header_hex or not file_type:\n                continue\n            try:\n                header = bytes.fromhex(header_hex)\n            except Exception:\n                continue\n            footer_hex = str(item.get(\"footer_hex\", \"\") or \"\").replace(\" \", \"\")\n            footer = bytes.fromhex(footer_hex) if footer_hex else None\n            PHOTOREC_SIGNATURES[header] = (file_type, footer)\n            loaded += 1\n    except Exception:\n        return 0\n    return loaded\n\nCUSTOM_SIGNATURE_COUNT = _load_custom_signature_config()\n\ndef _photorec_progress(progress_callback, message):\n    _safe_callback(progress_callback, message)\n\ndef _normalize_recovery_type(file_type):\n    file_type = str(file_type).lower().strip(\".\")\n    return PHOTOREC_EXT_MAP.get(file_type, file_type)\n\ndef _next_recup_dir(output_dir):\n    os.makedirs(output_dir, exist_ok=True)\n    idx = 1\n    while True:\n        path = os.path.join(output_dir, f\"recup_dir.{idx}\")\n        if not os.path.exists(path):\n            os.makedirs(path, exist_ok=True)\n            return path\n        idx += 1\n\ndef _disk_source_size(disk_path):\n    try:\n        if os.path.isfile(disk_path):\n            return os.path.getsize(disk_path)\n    except Exception:\n        pass\n    vol = re.match(r\"^\\\\\\\\\\.\\\\([A-Z]):$\", str(disk_path), re.I)\n    if vol:\n        letter = vol.group(1).upper() + \":\"\n        script = f\"$d=Get-CimInstance Win32_LogicalDisk -Filter \\\"DeviceID='{letter}'\\\"; if($d){{[string]$d.Size}}\"\n        out, rc = powershell_helper(script, timeout=20)\n        if rc == 0:\n            try:\n                return int(out.strip().splitlines()[-1])\n            except Exception:\n                pass\n    m = re.match(r\"^\\\\\\\\\\.\\\\PhysicalDrive(\\d+)$\", str(disk_path), re.I)\n    if m:\n        script = (\n            f\"$d=Get-CimInstance Win32_DiskDrive | Where-Object {{$_.Index -eq {int(m.group(1))}}}; \"\n            \"if($d){[string]$d.Size}\"\n        )\n        out, rc = powershell_helper(script, timeout=20)\n        if rc == 0:\n            try:\n                return int(out.strip().splitlines()[-1])\n            except Exception:\n                pass\n    return None\n\ndef _auto_detect_block_size(disk_path):\n    path = str(disk_path)\n    vol = re.match(r\"^\\\\\\\\\\.\\\\([A-Z]):$\", path, re.I)\n    if vol:\n        out, rc = powershell_helper(f\"fsutil fsinfo ntfsinfo {vol.group(1)}:\", timeout=20)\n        if rc == 0:\n            m = re.search(r\"Bytes Per Cluster\\s*:\\s*(\\d+)\", out, re.I)\n            if m:\n                return int(m.group(1))\n    phy = re.match(r\"^\\\\\\\\\\.\\\\PhysicalDrive(\\d+)$\", path, re.I)\n    if phy:\n        script = (\n            f\"$d=Get-CimInstance Win32_DiskDrive | Where-Object {{$_.Index -eq {int(phy.group(1))}}}; \"\n            \"if($d){[string]$d.BytesPerSector}\"\n        )\n        out, rc = powershell_helper(script, timeout=20)\n        if rc == 0:\n            try:\n                sector = int(out.strip().splitlines()[-1])\n                return 4096 if sector &gt;= 4096 else 512\n            except Exception:\n                pass\n    try:\n        sample = _read_raw_at(path, 0, 4 * 1024 * 1024)\n        offsets = []\n        for sig in PHOTOREC_SIGNATURES:\n            pos = sample.find(sig)\n            if pos &gt; 0:\n                offsets.append(pos)\n        for pattern, _, _ in PHOTOREC_REGEX_SIGNATURES:\n            match = pattern.search(sample)\n            if match:\n                offsets.append(match.start())\n        if offsets and all(pos % 4096 == 0 for pos in offsets):\n            return 4096\n    except Exception:\n        pass\n    return 512\n\ndef _detect_photorec_signature(buffer, absolute_base, aligned_only=False, block_size=512):\n    hits = []\n    for sig, (file_type, footer) in PHOTOREC_SIGNATURES.items():\n        start = 0\n        while True:\n            pos = buffer.find(sig, start)\n            if pos &lt; 0:\n                break\n            absolute = absolute_base + pos\n            if not aligned_only or absolute % block_size == 0:\n                hits.append((absolute, _normalize_recovery_type(file_type), sig, footer))\n            start = pos + 1\n    for pattern, file_type, footer in PHOTOREC_REGEX_SIGNATURES:\n        for match in pattern.finditer(buffer):\n            absolute = absolute_base + match.start()\n            if not aligned_only or absolute % block_size == 0:\n                hits.append((absolute, _normalize_recovery_type(file_type), match.group(0), footer))\n    hits.sort(key=lambda item: item[0])\n    return hits\n\ndef detect_file_boundaries(chunk, sig_type):\n    sig_type = _normalize_recovery_type(sig_type)\n    if sig_type == \"jpg\":\n        pos = chunk.find(b\"\\xFF\\xD9\", 2)\n        return pos + 2 if pos &gt;= 0 else None\n    if sig_type == \"png\":\n        pos = chunk.find(b\"IEND\")\n        return pos + 8 if pos &gt;= 0 else None\n    if sig_type == \"pdf\":\n        match = re.search(br\"%%EOF[\\r\\n\\t ]*\", chunk)\n        return match.end() if match else None\n    if sig_type == \"zip\":\n        pos = chunk.rfind(b\"PK\\x05\\x06\")\n        if pos &gt;= 0 and len(chunk) &gt;= pos + 22:\n            try:\n                comment_len = struct.unpack_from(\"I4s\", chunk[total:total + 8])\n            except Exception:\n                break\n            header_len = 8\n            if boxes == 0 and box_type != b\"ftyp\":\n                return None\n            if box_size == 1 and total + 16 &lt;= len(chunk):\n                box_size = struct.unpack(\"&gt;Q\", chunk[total + 8:total + 16])[0]\n                header_len = 16\n            elif box_size == 0:\n                return total if total else None\n            if box_size &lt; header_len or total + box_size &gt; len(chunk):\n                return None\n            total += box_size\n            boxes += 1\n            if box_type in (b\"mdat\", b\"moov\") and boxes &gt; 1:\n                continue\n        return total if total else None\n    if sig_type in (\"exe\", \"dll\"):\n        return _estimate_exe_size_from_bytes(chunk)\n    if sig_type == \"bmp\" and len(chunk) &gt;= 6:\n        size = struct.unpack_from(\" 14 else None\n    if sig_type == \"wav\" and chunk.startswith(b\"RIFF\") and len(chunk) &gt;= 8:\n        return struct.unpack_from(\"= 0 else None\n    return None\n\ndef _estimate_exe_size_from_bytes(data):\n    if len(data) &lt; 0x40 or data[:2] != b\"MZ\":\n        return None\n    try:\n        pe_offset = struct.unpack_from(\" len(data) or data[pe_offset:pe_offset + 4] != b\"PE\\0\\0\":\n            return None\n        sections = struct.unpack_from(\" len(data):\n                return None\n            raw_size = struct.unpack_from(\" 0 else None\n    except Exception:\n        return None\n\ndef validate_file(data, file_type):\n    file_type = _normalize_recovery_type(file_type)\n    try:\n        if file_type == \"jpg\":\n            if not (data.startswith(b\"\\xFF\\xD8\\xFF\") and b\"\\xFF\\xD9\" in data[-4096:]):\n                return False\n            pos = 2\n            while pos + 4 &lt; len(data):\n                if data[pos] != 0xFF:\n                    pos += 1\n                    continue\n                marker = data[pos + 1]\n                if marker == 0xD9:\n                    return True\n                if marker in (0x01,) or 0xD0 &lt;= marker &lt;= 0xD8:\n                    pos += 2\n                    continue\n                seg_len = struct.unpack(\"&gt;H\", data[pos + 2:pos + 4])[0]\n                if seg_len &lt; 2:\n                    return False\n                pos += 2 + seg_len\n            return False\n        if file_type == \"png\":\n            if not data.startswith(b\"\\x89PNG\\r\\n\\x1A\\n\"):\n                return False\n            pos = 8\n            while pos + 12 &lt;= len(data):\n                length = struct.unpack(\"&gt;I\", data[pos:pos + 4])[0]\n                ctype = data[pos + 4:pos + 8]\n                end = pos + 12 + length\n                if end &gt; len(data):\n                    return False\n                payload = data[pos + 4:pos + 8 + length]\n                expected = struct.unpack(\"&gt;I\", data[pos + 8 + length:end])[0]\n                if zlib.crc32(payload) &amp; 0xFFFFFFFF != expected:\n                    return False\n                pos = end\n                if ctype == b\"IEND\":\n                    return True\n            return False\n        if file_type == \"pdf\":\n            return data.startswith(b\"%PDF-\") and b\"%%EOF\" in data[-8192:]\n        if file_type == \"zip\":\n            if not data.startswith(b\"PK\\x03\\x04\"):\n                return False\n            import zipfile\n            with zipfile.ZipFile(io.BytesIO(data)) as zf:\n                return zf.testzip() is None\n        if file_type == \"mp4\":\n            return detect_file_boundaries(data, \"mp4\") is not None\n        if file_type == \"exe\":\n            return _estimate_exe_size_from_bytes(data) is not None\n        if file_type == \"gif\":\n            return data.startswith((b\"GIF87a\", b\"GIF89a\")) and data.endswith(b\"\\x3B\")\n        if file_type == \"bmp\":\n            return data.startswith(b\"BM\") and detect_file_boundaries(data, \"bmp\") == len(data)\n        if file_type == \"wav\":\n            return data.startswith(b\"RIFF\") and data[8:12] in (b\"WAVE\", b\"AVI \")\n        if file_type in (\"gz\", \"bz2\", \"xz\", \"7z\", \"rar\", \"flac\", \"ogg\", \"sqlite\", \"ico\", \"psd\", \"cab\", \"ps\", \"flv\", \"mkv\", \"mpg\", \"doc\", \"rtf\"):\n            return len(data) &gt; 16\n    except Exception:\n        return False\n    return len(data) &gt; 0\n\ndef _read_file_candidate(disk_path, offset, file_type, search_limit=None, progress_callback=None):\n    file_type = _normalize_recovery_type(file_type)\n    first = _read_raw_at(disk_path, offset, 16 * 1024 * 1024)\n    boundary = detect_file_boundaries(first, file_type)\n    if boundary:\n        return first[:boundary]\n    if file_type in (\"mp4\", \"exe\", \"bmp\", \"wav\") and boundary is None:\n        return None\n    data = bytearray(first)\n    read_pos = offset + len(first)\n    while True:\n        if search_limit is not None and len(data) &gt;= search_limit:\n            break\n        to_read = 16 * 1024 * 1024\n        if search_limit is not None:\n            to_read = min(to_read, search_limit - len(data))\n            if to_read &lt;= 0:\n                break\n        chunk = _read_raw_at(disk_path, read_pos, to_read)\n        if not chunk:\n            break\n        data.extend(chunk)\n        boundary = detect_file_boundaries(bytes(data[-(len(chunk) + 8192):]), file_type)\n        if boundary:\n            real_end = len(data) - (len(chunk) + 8192) + boundary\n            if real_end &gt; 0:\n                return bytes(data[:real_end])\n        read_pos += len(chunk)\n        _photorec_progress(progress_callback, f\"Boundary search: offset 0x{offset:X}, {len(data)//(1024*1024)} MB read\")\n    return bytes(data) if validate_file(bytes(data), file_type) else None\n\ndef _write_recovered_candidate(recup_dir, offset, file_type, data, counter, source=None):\n    safety = get_recovery_safety()\n    recup_dir = safety.validate_output_dir(recup_dir, source)\n    ext = _normalize_recovery_type(file_type)\n    name = f\"f{counter:07d}_off_{offset:012X}.{ext}\"\n    path = safety.validate_write_path(os.path.join(recup_dir, name), source)\n    with open(path, \"wb\") as out:\n        out.write(data)\n    return path\n\ndef _fragment_reassemble_nearby(disk_path, offset, file_type, block_size, progress_callback=None):\n    # Best-effort fragmented recovery: read a larger nearby window and validate candidate.\n    start = max(0, offset - block_size)\n    data = _read_raw_at(disk_path, start, block_size * 512)\n    rel = offset - start\n    if rel &lt; 0 or rel &gt;= len(data):\n        return None\n    candidate = data[rel:]\n    boundary = detect_file_boundaries(candidate, file_type)\n    if boundary:\n        candidate = candidate[:boundary]\n    if validate_file(candidate, file_type):\n        _photorec_progress(progress_callback, f\"Fragment reassembly OK: offset 0x{offset:X}\")\n        return candidate\n    return None\n\ndef _scan_pass(disk_path, recup_dir, block_size, pass_num, aligned_only, seen_offsets, progress_callback=None):\n    source_size = _disk_source_size(disk_path)\n    chunk_size, pause_s = _scan_chunk_profile(disk_path, block_size)\n    overlap = RAW_SCAN_OVERLAP\n    offset = 0\n    recovered = []\n    counter = len(seen_offsets) + 1\n    previous_tail = b\"\"\n    last_pct = -1\n    last_report_offset = -RAW_SCAN_PROGRESS_STEP\n    while True:\n        chunk = _read_raw_at(disk_path, offset, chunk_size)\n        if not chunk:\n            break\n        scan_buffer = previous_tail + chunk\n        scan_base = offset - len(previous_tail)\n        hits = _detect_photorec_signature(scan_buffer, scan_base, aligned_only=aligned_only, block_size=block_size)\n        for hit_offset, file_type, _sig, _footer in hits:\n            if hit_offset &lt; 0 or hit_offset in seen_offsets:\n                continue\n            seen_offsets.add(hit_offset)\n            try:\n                data = _read_file_candidate(disk_path, hit_offset, file_type, progress_callback=progress_callback)\n                if data is None or not validate_file(data, file_type):\n                    data = _fragment_reassemble_nearby(disk_path, hit_offset, file_type, block_size, progress_callback=progress_callback)\n                if data and validate_file(data, file_type):\n                    path = _write_recovered_candidate(recup_dir, hit_offset, file_type, data, counter, source=disk_path)\n                    counter += 1\n                    recovered.append({\"path\": path, \"offset\": hit_offset, \"file_type\": file_type, \"bytes\": len(data), \"pass\": pass_num})\n                    _photorec_progress(progress_callback, f\"Pass {pass_num}: recovered {os.path.basename(path)}\")\n            except Exception as e:\n                _photorec_progress(progress_callback, f\"Pass {pass_num}: offset 0x{hit_offset:X} skip ({e})\")\n        offset += len(chunk)\n        previous_tail = scan_buffer[-overlap:]\n        if source_size:\n            pct = min(100, int((offset / source_size) * 100))\n            if pct != last_pct:\n                last_pct = pct\n                _photorec_progress(progress_callback, f\"Pass {pass_num}: {pct}% complete\")\n        elif (offset - last_report_offset) &gt;= RAW_SCAN_PROGRESS_STEP:\n            last_report_offset = offset\n            _photorec_progress(progress_callback, f\"Pass {pass_num}: {_human_size(offset)} scanned\")\n        if pause_s:\n            time.sleep(pause_s)\n    return recovered\n\ndef multi_pass_recovery(disk_path, output_dir, block_size=None, progress_callback=None):\n    _require_raw_admin(disk_path)\n    output_dir = get_recovery_safety().validate_output_dir(output_dir, disk_path)\n    block_size = int(block_size or _auto_detect_block_size(disk_path))\n    recup_base = _next_recup_dir(output_dir)\n    seen_offsets = set()\n    all_recovered = []\n    _photorec_progress(progress_callback, f\"Block size auto-detected: {block_size} bytes\")\n    if CUSTOM_SIGNATURE_COUNT:\n        _photorec_progress(progress_callback, f\"Custom signature engine active: {CUSTOM_SIGNATURE_COUNT} extra signatures\")\n    if _is_raw_device_path(disk_path):\n        _photorec_progress(progress_callback, f\"Low-impact mode active: {RAW_SCAN_DEVICE_CHUNK // (1024 * 1024)} MB buffered reads + {RAW_SCAN_DEVICE_PAUSE_MS} ms pause\")\n    _photorec_progress(progress_callback, \"Pass 1: block-aligned carving start\")\n    all_recovered.extend(_scan_pass(disk_path, recup_base, block_size, 1, True, seen_offsets, progress_callback))\n    _photorec_progress(progress_callback, \"Pass 2: unaligned signature carving start\")\n    all_recovered.extend(_scan_pass(disk_path, recup_base, block_size, 2, False, seen_offsets, progress_callback))\n    _photorec_progress(progress_callback, f\"Carving complete: {len(all_recovered)} files (2 passes + validation)\")\n    return {\"recup_dir\": recup_base, \"block_size\": block_size, \"files\": all_recovered}\n\ndef deep_scan_disk(disk_path, output_dir):\n    \"\"\"PhotoRec-style main scanner: raw disk access, auto block size, multi-pass carving.\"\"\"\n    _require_raw_admin(disk_path)\n    return multi_pass_recovery(disk_path, output_dir, block_size=None, progress_callback=print)\n\n# \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n#  CORPORATE PROFESSIONAL COLOR SCHEME - Enterprise-Grade Theme\n#  Modern, clean, professional appearance for business environments\n# \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\nC = {\n    \"bg\":         \"#0A0F1A\",\n    \"panel\":      \"#121826\",\n    \"card\":       \"#182032\",\n    \"border\":     \"#2A3A5A\",\n    \"accent\":     \"#FFB347\",\n    \"accent2\":    \"#4CAF50\",\n    \"accent3\":    \"#F44336\",\n    \"accent4\":    \"#FF9800\",\n    \"text\":       \"#F0F4FA\",\n    \"text_dim\":   \"#A0B0C8\",\n    \"text_dark\":  \"#3A4A6A\",\n    \"btn\":        \"#2E5A9C\",\n    \"btn_hover\":  \"#1E4A8C\",\n    \"btn_danger\": \"#D32F2F\",\n    \"btn_info\":   \"#1976D2\",\n    \"btn_warn\":   \"#FF8C00\",\n    \"btn_hw\":     \"#6A1B9A\",\n    \"btn_chip\":   \"#00838F\",\n    \"header_bg\":  \"#0A0F1A\",\n    \"sidebar\":    \"#0E1422\",\n    \"progress\":   \"#FFB347\",\n    \"success\":    \"#4CAF50\",\n    \"warning\":    \"#FF9800\",\n    \"error\":      \"#F44336\",\n    \"hw_accent\":  \"#CE93D8\",\n}\n\n\n  # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n  #  CORPORATE PROFESSIONAL FONTS - Enterprise-Grade Typography\n  #  Clean, readable, professional font hierarchy\n  # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\nFONTS = {\n    \"title\":    (\"Segoe UI\", 20, \"bold\"),\n    \"heading\":  (\"Segoe UI\", 13, \"bold\"),\n    \"subhead\":  (\"Segoe UI\", 11, \"bold\"),\n    \"body\":     (\"Segoe UI\", 10),\n    \"small\":    (\"Segoe UI\", 9),\n    \"xsmall\":   (\"Segoe UI\", 8),\n    \"mono\":     (\"Consolas\", 9),\n}\n\nSIDEBAR_CATEGORIES = [\n    (\"\ud83d\udee0 SHOP WORKFLOW\", \"accent4\", [\n        (\"shop\", \"\ud83d\udee0\", \"Repair Shop Mode\"),\n    ]),\n    (\"\u26a1 PERFORMANCE\", \"accent\", [\n        (\"cleaner\", \"\ud83e\uddf9\", \"Junk Cleaner\"),\n        (\"memory\", \"\ud83e\udde0\", \"RAM + Services\"),\n        (\"startup\", \"\ud83d\ude80\", \"Startup + Scheduler\"),\n        (\"boost\", \"\u26a1\", \"Power Boost\"),\n    ]),\n    (\"\ud83d\udd27 SYSTEM REPAIR\", \"warning\", [\n        (\"registry\", \"\ud83d\udcdd\", \"Registry + Group Policy\"),\n        (\"network\", \"\ud83c\udf10\", \"Network + Troubleshooter\"),\n        (\"power\", \"\ud83d\udd0b\", \"Power Plan\"),\n        (\"hdd_repair\", \"\ud83d\udcbe\", \"HDD/SSD + File Recovery\"),\n        (\"data_recovery\", \"\ud83d\udd2c\", \"Data Recovery\"),\n        (\"activation\", \"\ud83d\udd11\", \"Windows Activation\"),\n    ]),\n    (\"\ud83d\udee0 RESCUE &amp; RECOVERY\", \"warning\", [\n        (\"rescue_center\", \"\ud83d\udee0\", \"Rescue &amp; Recovery Center\"),\n    ]),\n    (\"\ud83d\udd0d SECURITY &amp; AUDIT\", \"accent3\", [\n        (\"suspicion\", \"\ud83d\udd34\", \"Process Scanner\"),\n        (\"realtime_security\", \"\ud83d\udee1\", \"Realtime Security\"),\n        (\"eventviewer\", \"\ud83d\udccb\", \"Event Viewer\"),\n        (\"log\", \"\ud83d\udcc4\", \"Activity Log\"),\n    ]),\n    (\"\ud83d\uddc2 TOOLS\", \"accent2\", [\n        (\"printer\", \"\ud83d\udda8\", \"Printer + Driver\"),\n        (\"uninstall\", \"\ud83d\uddd1\", \"Uninstall + Backup\"),\n        (\"dupfinder\", \"\ud83d\udd0d\", \"Dup Finder + Report\"),\n    ]),\n    (\"\ud83d\udcc1 OFFICE &amp; FILES\", \"hw_accent\", [\n        (\"office_tools\", \"\ud83d\udcc4\", \"PDF &amp; Doc Tools\"),\n        (\"excel_tools\", \"\ud83d\udcca\", \"Excel Tools\"),\n        (\"image_tools\", \"\ud83d\uddbc\", \"Image Tools\"),\n        (\"file_tools\", \"\ud83d\uddc2\", \"File Manager\"),\n    ]),\n]\n\n\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n#  MAIN APPLICATION\n# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nSIDEBAR_CATEGORIES.append((\"\ud83d\udd27 ADVANCED TOOLS\", \"accent3\", [\n    (\"partition_manager\",\"\ud83d\udcbd\", \"Partition Manager\"),\n    (\"easy_driver\",      \"\ud83d\udda5\", \"Easy Driver\"),\n    (\"driver_manager\",    \"\ud83d\udda5\",  \"Driver Manager\"),\n    (\"svc_presets\",       \"\u2699\",  \"Services Preset Manager\"),\n    (\"disk_analyzer\",     \"\ud83d\udcca\", \"Disk Space Analyzer\"),\n    (\"bsod_history\",      \"\ud83d\udc80\", \"BSOD History\"),\n    (\"corrupt_wizard\",    \"\ud83d\udd28\", \"Corrupt Windows Wizard\"),\n    (\"password_audit\",    \"\ud83d\udd10\", \"Password &amp; Security Audit\"),\n    (\"auto_backup\",       \"\ud83d\udcbe\", \"Auto Backup\"),\n]))\n\nclass GodawariUltimateOptimizer(tk.Tk):\n    def __init__(self):\n        super().__init__()\n        self.title(\"Godawari Computers Ultimate Optimizer Pro v11.0 | Safety &amp; Recovery Edition\")\n        self.geometry(\"1400x850\")\n        self.minsize(1120, 680)\n        self.configure(bg=C[\"bg\"])\n        self.resizable(True, True)\n\n        self.active_section = tk.StringVar(value=\"dashboard\")\n        self.log_lines = []\n        self.current_theme = \"dark\"\n        self.settings_file = os.path.join(os.environ.get(\"APPDATA\", \"\"), \"GodawariOptimizer\", \"settings.json\")\n        self.reg_vars = {}\n        self.gp_vars = {}\n        self.clean_vars = {}\n        self._restore_prompt_count = 0\n        self.uninst_data = []\n        self._recovery_stop_flag = False\n        self._recovery_pause_flag = False\n        self._clean_job_running = False\n        self._clean_job_cancel_event = threading.Event()\n        self._clean_job_summary = {}\n        self._recovery_active = False\n        self._partition_op_lock = threading.Lock()\n        self._partition_operation_active = False\n        self._partition_operation_session = None\n        self._partition_cancel_event = threading.Event()\n        self._partition_operation_log = []\n        self._partition_operation_start_time = None\n        self._job_lock = threading.Lock()\n        self._jobs = {}\n        self._job_counter = 0\n        self._task_manager = {}\n        self._task_counter = 0\n        self._event_bus = collections.defaultdict(list)\n        self.system_health = {\n            \"disk\": 100,\n            \"ram\": 100,\n            \"startup\": 100,\n            \"security\": 100,\n            \"windows\": 100,\n            \"drivers\": 100,\n            \"network\": 100,\n        }\n        self._health_trend = {key: 100 for key in self.system_health}\n        self._rollback_points = []\n        self._security_alerts = []\n        self._security_watch_running = False\n        self._security_watch_thread = None\n        self._security_baselines = {}\n        self._last_security_snapshot = {}\n        self._enterprise_log_dir = os.path.join(os.environ.get(\"APPDATA\", \"\"), \"GodawariOptimizer\", \"logs\")\n        self._enterprise_log_file = os.path.join(self._enterprise_log_dir, \"enterprise.log\")\n        self._enterprise_error_log = os.path.join(self._enterprise_log_dir, \"errors.log\")\n        self._enterprise_forensic_log = os.path.join(self._enterprise_log_dir, \"forensic.log\")\n        self._ensure_enterprise_logs()\n        self.backup_config_file = os.path.join(os.environ.get(\"APPDATA\",\"\"), \"GodawariOptimizer\", \"backup_config.json\")\n        self.backup_sources = []\n        self.backup_dest_var = tk.StringVar()\n        self.backup_schedule_var = tk.StringVar(value=\"Manual Only\")\n        self.backup_time_var = tk.StringVar(value=\"02:00\")\n        self.backup_overwrite_mode = tk.StringVar(value=\"mirror\")\n        self.backup_keep_n = tk.IntVar(value=3)\n        self.regback_enabled = tk.BooleanVar(value=True)\n        self._corrupt_wizard_step = 0\n        self._corrupt_wizard_running = False\n\n        # \u2500\u2500 Thread-safe UI update queue \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        # Background threads put (msg_type, payload) tuples here.\n        # The main thread drains this queue every ~50 ms via _poll_ui_queue().\n        # This is the ONLY safe way to touch Tkinter widgets from threads.\n        self._ui_queue = _queue_module.Queue()\n        # Specialized metric queues for RAM/Services, Registry/Group Policy and HDD/Recovery menus.\n        self._ram_service_metrics_queue = _queue_module.Queue()\n        self._ram_service_last_dispatch = time.time()\n        self._ram_service_metrics_lock = threading.Lock()\n        self._ram_service_pending_metrics = None\n        self._registry_gp_metrics_queue = _queue_module.Queue()\n        self._registry_gp_last_dispatch = time.time()\n        self._hdd_recovery_metrics_queue = _queue_module.Queue()\n        self._hdd_recovery_last_dispatch = time.monotonic()\n        self._hdd_recovery_pending_metrics = None\n        self._hdd_recovery_metrics_lock = threading.Lock()\n        self._hdd_recovery_job_lock = threading.Lock()\n        # Dedicated printer action queue and metrics throttling for the Printer + Driver menu.\n        self._printer_metrics_queue = _queue_module.Queue()\n        self._printer_metrics_last_dispatch = time.monotonic()\n        self._printer_metrics_pending = None\n        self._printer_metrics_lock = threading.Lock()\n        self._printer_action_buttons = []\n        self._printer_action_lock = threading.Lock()\n        self._printer_action_running = False\n        # Threading Event: set by _stop_file_recovery() so the scan loop\n        # can check it without touching any Tk widget from a background thread.\n        self._scan_stop_event = threading.Event()\n        # \u2500\u2500 PHASE 2: Atomic debounce lock for File Recovery menu \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        self._recovery_is_processing = False          # atomic boolean guard\n        self._rec_integrity_lock     = threading.Lock()\n        self._rec_timeline_lock      = threading.Lock()\n        self._rec_integrity_queue    = _queue_module.Queue()\n        self._rec_timeline_queue     = _queue_module.Queue()\n        self._rec_integrity_last_dispatch  = time.monotonic()\n        self._rec_timeline_last_dispatch   = time.monotonic()\n\n        try:\n            os.makedirs(os.path.dirname(self.settings_file), exist_ok=True)\n        except:\n            pass\n        self._init_backend_reliability()\n        self.worker_manager = TkWorkerManager(self, workers=3, logger=getattr(self, \"structured_logger\", None))\n        self.recovery_manager = RecoveryManager(workers=3, callback=self._on_recovery_task_update, logger=getattr(self, \"structured_logger\", None))\n        self.recovery_results = RecoveryResultStore()\n        self._recovery_progress_panels = {}\n        self._recovery_live_stats = {}\n\n        self._build_style()\n        self._build_header()\n        self._build_body()\n        self._build_statusbar()\n        self._build_footer()\n        self._load_settings()\n        self._show_section(\"dashboard\")\n        # Startup fast karo: dashboard refresh aur graph deferred\n        self.after(800, self._refresh_dashboard)\n        self.after(1500, self._start_real_time_graph)\n\n        # Start the UI queue poller \u2014 drains _ui_queue on the main thread\n        self._poll_ui_queue()\n        self._poll_ram_service_metrics()\n        self._poll_registry_gp_metrics()\n        self._poll_hdd_recovery_metrics()\n        self._poll_printer_metrics()\n        self._tick_printer_action_timer()\n\n        if not is_admin():\n            self._set_status(\"\u26a0\ufe0f Admin rights required! Some features may not work.\", C[\"warning\"])\n            self._log(\"Not running as Administrator. Right-click -&gt; Run as Administrator.\", \"WARN\")\n\n        self.after(1200, self._check_crash_recovery_startup)\n        self.after(1600, self._prompt_admin_elevation)\n        self.protocol(\"WM_DELETE_WINDOW\", self._on_app_close)\n\n    def _on_app_close(self):\n        try:\n            if hasattr(self, \"crash_recovery\"):\n                self.crash_recovery.clear_running()\n        except Exception:\n            pass\n        self.destroy()\n\n    def _check_crash_recovery_startup(self):\n        try:\n            orphans = self.crash_recovery.orphaned_sessions()\n            if not orphans:\n                return\n            lines = []\n            for s in orphans[:5]:\n                lines.append(\n                    f\"\u2022 {s.get('kind', 'job')} \u2014 started {s.get('started', '?')}\"\n                )\n            self._log(\n                \"Crash recovery detected unfinished sessions on startup. \"\n                + \"Review in Safety Center if needed. \"\n                + \" | \".join(lines),\n                \"WARN\",\n            )\n        except Exception:\n            pass\n\n    def _prompt_admin_elevation(self):\n        try:\n            if is_admin() or not _admin_elevation_enabled():\n                return\n            if messagebox.askyesno(\n                \"Administrator Required\",\n                \"Some recovery and repair features require elevated privileges. Relaunch elevated now?\",\n            ):\n                run_as_admin()\n        except Exception:\n            pass\n\n    def _init_backend_reliability(self):\n        if _GODAWARI_BACKEND:\n            try:\n                self._backend = create_backend()\n                base_dir = self._backend.config.get(\"app\", default={})  # noqa \u2014 paths via package\n                from godawari import paths as _paths\n                self.audit_dir = _paths.audit_dir()\n                self.backup_dir = _paths.backup_dir()\n                self.rollback_dir = _paths.rollback_dir()\n                self.recovery_sessions_dir = _paths.sessions_dir()\n                self.crash_marker_file = _paths.crash_marker_path()\n                self.audit_file = _paths.legacy_audit_path()\n                self.structured_log_file = _paths.structured_log_path()\n                self.structured_logger = self._backend.logger\n                self.event_bus = self._backend.event_bus\n                self.telemetry_store = self._backend.telemetry_store\n                self.job_manager = self._backend.job_manager\n                self.change_coordinator = self._backend.change_coordinator\n                self.policy_engine = self._backend.policy_engine\n                self.system_adapters = self._backend.system_adapters\n                self.restore_point_manager = self._backend.restore_points\n                self.rollback_vault = self._backend.rollback_vault\n                self.recovery_session_manager = self._backend.recovery_sessions\n                self.health_engine = self._backend.health_engine\n                self.menu_introspection_engine = self._backend.menu_introspection\n                self.product_audit_engine = self._backend.product_audit\n                self.recommendation_engine = self._backend.recommendations\n                self.maintenance_profile_engine = self._backend.maintenance_profiles\n                self.preflight_engine = self._backend.preflight\n                self.secure_powershell = self._backend.secure_powershell\n                self.crash_recovery = self._backend.crash_recovery\n                self.task_queue_manager = self._backend.task_queue\n                self.audit_store = self._backend.audit_store\n                self.app_config = self._backend.config\n                self.crash_recovery.mark_running()\n                self._last_health_report = None\n                return\n            except Exception:\n                pass\n        base_dir = os.path.join(os.environ.get(\"APPDATA\", \"\"), \"GodawariOptimizer\")\n        self.audit_dir = os.path.join(base_dir, \"audit\")\n        self.backup_dir = os.path.join(base_dir, \"backups\")\n        self.rollback_dir = os.path.join(base_dir, \"rollback_vault\")\n        self.recovery_sessions_dir = os.path.join(base_dir, \"recovery_sessions\")\n        self.crash_marker_file = os.path.join(base_dir, \"runtime.marker\")\n        try:\n            os.makedirs(self.audit_dir, exist_ok=True)\n            os.makedirs(self.backup_dir, exist_ok=True)\n            os.makedirs(self.rollback_dir, exist_ok=True)\n            os.makedirs(self.recovery_sessions_dir, exist_ok=True)\n            self.audit_file = os.path.join(self.audit_dir, \"actions.jsonl\")\n            self.structured_log_file = os.path.join(self.audit_dir, \"structured_runtime.jsonl\")\n        except Exception:\n            self.audit_file = \"\"\n            self.structured_log_file = \"\"\n        # Initialize structured logger and backend helpers\n        try:\n            from godawari.services.logger import StructuredLogger as _StructuredLogger\n            from godawari.jobs.manager import JobManager as _JobManager\n            from godawari.events.bus import EventBus as _EventBus\n            from godawari.telemetry.store import TelemetryStore as _TelemetryStore\n            from godawari.change_coordinator import ChangeCoordinator as _ChangeCoordinator\n            from godawari.policies.engine import PolicyEngine as _PolicyEngine\n            from godawari.system.adapters import RegistryAdapter, ServiceAdapter, DiskAdapter\n        except Exception:\n            _StructuredLogger = globals().get(\"StructuredLogger\")\n            _JobManager = None\n            _EventBus = None\n            _TelemetryStore = None\n            _ChangeCoordinator = None\n            _PolicyEngine = None\n            RegistryAdapter = ServiceAdapter = DiskAdapter = None\n\n        self.event_bus = _EventBus.get_instance() if _EventBus else None\n        self.telemetry_store = _TelemetryStore(db_path=_paths.database_path()) if _TelemetryStore else None\n        self.structured_logger = _StructuredLogger(getattr(self, \"structured_log_file\", \"\"))\n        self.restore_point_manager = RestorePointManager(\n            base_dir,\n            self.structured_logger,\n            event_bus=self.event_bus,\n            telemetry=self.telemetry_store,\n        )\n        self.rollback_vault = OperationRollbackVault(\n            self.rollback_dir,\n            self.structured_logger,\n            event_bus=self.event_bus,\n            telemetry=self.telemetry_store,\n        )\n        self.recovery_session_manager = RecoverySessionManager(\n            self.recovery_sessions_dir, self.structured_logger\n        )\n        # EventBus and JobManager\n        try:\n            self.job_manager = _JobManager(db_path=_paths.database_path(), workers=3, logger=self.structured_logger, event_bus=self.event_bus, telemetry=self.telemetry_store) if _JobManager else None\n            self.change_coordinator = _ChangeCoordinator(self.restore_point_manager, self.rollback_vault, logger=self.structured_logger, job_manager=self.job_manager, event_bus=self.event_bus, telemetry_store=self.telemetry_store) if _ChangeCoordinator else None\n            self.policy_engine = _PolicyEngine(logger=self.structured_logger) if _PolicyEngine else None\n            self.system_adapters = {\n                \"registry\": RegistryAdapter() if RegistryAdapter else None,\n                \"service\": ServiceAdapter() if ServiceAdapter else None,\n                \"disk\": DiskAdapter() if DiskAdapter else None,\n            }\n        except Exception:\n            self.job_manager = None\n            self.change_coordinator = None\n            self.policy_engine = None\n            self.system_adapters = {}\n        self.health_engine = SystemHealthEngine()\n        self.menu_introspection_engine = MenuIntrospectionEngine()\n        self.product_audit_engine = ProductAuditEngine()\n        self.recommendation_engine = RecommendationEngine()\n        self.maintenance_profile_engine = MaintenanceProfileEngine()\n        self.preflight_engine = OperationPreflightEngine()\n        self.secure_powershell = SecurePowerShellEngine(self.structured_logger)\n        self.crash_recovery = CrashRecoveryCoordinator(\n            self.recovery_session_manager, self.crash_marker_file)\n        self.crash_recovery.mark_running()\n        self._last_health_report = None\n\n    def _ensure_enterprise_logs(self):\n        try:\n            os.makedirs(self._enterprise_log_dir, exist_ok=True)\n            for path in (self._enterprise_log_file, self._enterprise_error_log, self._enterprise_forensic_log):\n                if not os.path.exists(path):\n                    with open(path, \"a\", encoding=\"utf-8\"):\n                        pass\n        except Exception:\n            pass\n\n    def _write_enterprise_log(self, path, message, level=\"INFO\"):\n        try:\n            os.makedirs(self._enterprise_log_dir, exist_ok=True)\n            if os.path.exists(path) and os.path.getsize(path) &gt; (1024 * 1024):\n                suffix = datetime.datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n                rotated = f\"{path}.{suffix}\"\n                try:\n                    os.replace(path, rotated)\n                except Exception:\n                    pass\n            timestamp = datetime.datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\")\n            with open(path, \"a\", encoding=\"utf-8\") as handle:\n                handle.write(f\"[{timestamp}] [{level}] {message}\\n\")\n        except Exception:\n            pass\n\n    def _log_module(self, module, message, level=\"INFO\"):\n        try:\n            module_path = os.path.join(self._enterprise_log_dir, f\"{module}.log\")\n            self._write_enterprise_log(module_path, message, level)\n        except Exception:\n            pass\n\n    def _register_event(self, event_name, callback):\n        try:\n            self._event_bus.setdefault(str(event_name), []).append(callback)\n            return True\n        except Exception:\n            return False\n\n    def _emit_event(self, event_name, data=None):\n        try:\n            for callback in list(self._event_bus.get(str(event_name), [])):\n                try:\n                    callback(data)\n                except Exception:\n                    pass\n            if getattr(self, \"event_bus\", None) is not None:\n                try:\n                    self.event_bus.emit(str(event_name), data)\n                except Exception:\n                    pass\n            return True\n        except Exception:\n            return False\n\n    def _set_health_score(self, key, value, note=\"\"):\n        try:\n            previous = self.system_health.get(key, 100)\n            self._health_trend[key] = previous\n            self.system_health[key] = max(0, min(100, int(value)))\n            if note:\n                self._log_module(\"health\", f\"{key}: {self.system_health[key]} ({note})\", \"INFO\")\n        except Exception:\n            pass\n\n    def _calculate_global_health(self):\n        try:\n            scores = [max(0, min(100, int(v))) for v in self.system_health.values()]\n            global_score = int(sum(scores) / len(scores)) if scores else 100\n            if global_score &gt;= 85:\n                grade, color = \"Excellent\", C[\"success\"]\n            elif global_score &gt;= 70:\n                grade, color = \"Good\", C[\"accent4\"]\n            elif global_score &gt;= 50:\n                grade, color = \"Fair\", C[\"warning\"]\n            else:\n                grade, color = \"Critical\", C[\"error\"]\n            trend = {key: f\"{('\u25b2' if self.system_health[key] &gt;= self._health_trend.get(key, self.system_health[key]) else '\u25bc')} {abs(self.system_health[key] - self._health_trend.get(key, self.system_health[key]))}\" for key in self.system_health}\n            return {\n                \"score\": global_score,\n                \"grade\": grade,\n                \"color\": color,\n                \"per_category\": dict(self.system_health),\n                \"trend\": trend,\n            }\n        except Exception:\n            return {\"score\": 100, \"grade\": \"Excellent\", \"color\": C[\"success\"], \"per_category\": dict(self.system_health), \"trend\": {}}\n\n    def _refresh_health_snapshot(self):\n        try:\n            vm = psutil.virtual_memory()\n            du = psutil.disk_usage(\"C:\")\n            proc_count = len(list(psutil.process_iter(['pid'])))\n            startup_path = os.path.join(os.environ.get(\"APPDATA\", \"\"), \"Microsoft\", \"Windows\", \"Start Menu\", \"Programs\", \"Startup\")\n            startup_items = len([name for name in os.listdir(startup_path) if os.path.isfile(os.path.join(startup_path, name))]) if os.path.isdir(startup_path) else 0\n            self._set_health_score(\"ram\", max(0, 100 - int(vm.percent)), \"RAM usage\")\n            self._set_health_score(\"disk\", max(0, 100 - int(du.percent)), \"Disk usage\")\n            self._set_health_score(\"startup\", max(20, 100 - min(80, startup_items * 2)), \"Startup items\")\n            self._set_health_score(\"network\", 100 if self._last_security_snapshot.get(\"network\", {}).get(\"status\") == \"healthy\" else 70)\n            driver_cmd = 'powershell -NoProfile -Command \"Get-WmiObject Win32_PnPSignedDriver | Select-Object -ExpandProperty DeviceName\"'\n            out, rc = self._run_cmd(driver_cmd, timeout=20)\n            if rc == 0:\n                driver_count = len([line for line in out.splitlines() if line.strip()])\n                self._set_health_score(\"drivers\", max(40, 100 - min(60, driver_count // 20)), \"Driver inventory\")\n            security_status = self._last_security_snapshot.get(\"defender\", {})\n            sec_score = 100\n            if not security_status.get(\"enabled\", False):\n                sec_score = 0\n            if not security_status.get(\"realtime\", True):\n                sec_score = max(0, sec_score - 20)\n            self._set_health_score(\"security\", sec_score, \"Defender status\")\n            windows_score = 100\n            health_report = getattr(self, \"_last_health_report\", None)\n            if health_report and isinstance(health_report, dict):\n                windows_score = int(health_report.get(\"score\", 100))\n            self._set_health_score(\"windows\", windows_score, \"Windows health\")\n            self._last_security_snapshot[\"process_count\"] = proc_count\n            self._last_security_snapshot[\"disk_percent\"] = int(du.percent)\n            self._last_security_snapshot[\"ram_percent\"] = int(vm.percent)\n            return self._calculate_global_health()\n        except Exception:\n            return self._calculate_global_health()\n\n    def _task_start(self, title, progress=0, metadata=None):\n        try:\n            self._task_counter += 1\n            task_id = f\"task-{self._task_counter}\"\n            self._task_manager[task_id] = {\n                \"id\": task_id,\n                \"title\": str(title),\n                \"status\": \"running\",\n                \"progress\": max(0, min(100, int(progress))),\n                \"metadata\": metadata or {},\n                \"cancel_requested\": False,\n                \"pause_requested\": False,\n                \"cancel_event\": threading.Event(),\n                \"pause_event\": threading.Event(),\n                \"started_at\": datetime.datetime.now().isoformat(timespec=\"seconds\"),\n            }\n            self._task_manager[task_id][\"pause_event\"].set()\n            self._log_module(\"tasks\", f\"Started {task_id}: {title}\", \"INFO\")\n            if hasattr(self, \"task_center_tree\"):\n                self.after(0, self._refresh_task_center)\n            return task_id\n        except Exception:\n            return \"task-0\"\n\n    def _task_status(self, task_id):\n        return dict(self._task_manager.get(str(task_id), {})) if str(task_id) in self._task_manager else {}\n\n    def _task_update_progress(self, task_id, progress, status=None):\n        try:\n            record = self._task_manager.get(str(task_id))\n            if record is None:\n                return False\n            record[\"progress\"] = max(0, min(100, int(progress)))\n            if status:\n                record[\"status\"] = str(status)\n            if hasattr(self, \"task_center_tree\"):\n                self.after(0, self._refresh_task_center)\n            return True\n        except Exception:\n            return False\n\n    def _task_cancel(self, task_id):\n        try:\n            record = self._task_manager.get(str(task_id))\n            if record is None:\n                return False\n            record[\"cancel_requested\"] = True\n            record[\"status\"] = \"cancelled\"\n            if record.get(\"cancel_event\") is not None:\n                record[\"cancel_event\"].set()\n            self._log_module(\"tasks\", f\"Cancelled {task_id}\", \"WARNING\")\n            if hasattr(self, \"task_center_tree\"):\n                self.after(0, self._refresh_task_center)\n            return True\n        except Exception:\n            return False\n\n    def _task_pause(self, task_id):\n        try:\n            record = self._task_manager.get(str(task_id))\n            if record is None:\n                return False\n            record[\"pause_requested\"] = True\n            record[\"status\"] = \"paused\"\n            if record.get(\"pause_event\") is not None:\n                record[\"pause_event\"].clear()\n            if hasattr(self, \"task_center_tree\"):\n                self.after(0, self._refresh_task_center)\n            return True\n        except Exception:\n            return False\n\n    def _task_resume(self, task_id):\n        try:\n            record = self._task_manager.get(str(task_id))\n            if record is None:\n                return False\n            record[\"pause_requested\"] = False\n            record[\"status\"] = \"running\"\n            if record.get(\"pause_event\") is not None:\n                record[\"pause_event\"].set()\n            if hasattr(self, \"task_center_tree\"):\n                self.after(0, self._refresh_task_center)\n            return True\n        except Exception:\n            return False\n\n    def _task_wait_if_paused(self, task_id, timeout=0.1):\n        record = self._task_manager.get(str(task_id))\n        if not record:\n            return\n        pause_event = record.get(\"pause_event\")\n        cancel_event = record.get(\"cancel_event\")\n        if pause_event is None:\n            return\n        while not pause_event.wait(timeout=timeout):\n            if cancel_event is not None and cancel_event.is_set():\n                raise RuntimeError(\"Task cancelled\")\n\n    def _task_is_cancelled(self, task_id):\n        record = self._task_manager.get(str(task_id))\n        return bool(record and record.get(\"cancel_requested\"))\n\n    def _refresh_task_center(self):\n        tree = getattr(self, \"task_center_tree\", None)\n        if tree is None:\n            return\n        for iid in tree.get_children():\n            tree.delete(iid)\n        for record in sorted(self._task_manager.values(), key=lambda item: item.get(\"started_at\", \"\"), reverse=True):\n            status = record.get(\"status\", \"running\")\n            tag = \"running\" if status == \"running\" else \"cancelled\"\n            tree.insert(\n                \"\",\n                \"end\",\n                values=(record.get(\"id\", \"\"), record.get(\"title\", \"\"), status, f\"{record.get('progress', 0)}%\"),\n                tags=(tag,),\n            )\n        try:\n            tree.tag_configure(\"running\", foreground=C[\"success\"])\n            tree.tag_configure(\"cancelled\", foreground=C[\"warning\"])\n        except Exception:\n            pass\n\n    def _record_rollback_point(self, action, details=None, snapshot_path=None):\n        try:\n            point = {\n                \"action\": str(action),\n                \"details\": details or {},\n                \"snapshot_path\": snapshot_path or \"\", \n                \"timestamp\": datetime.datetime.now().isoformat(timespec=\"seconds\"),\n            }\n            self._rollback_points.append(point)\n            self._log_module(\"rollback\", f\"Rollback point captured: {action}\", \"INFO\")\n            return point\n        except Exception:\n            return None\n\n    def _restore_last_rollback(self):\n        try:\n            if not self._rollback_points:\n                return False, \"No rollback points available\"\n            point = self._rollback_points[-1]\n            snapshot = point.get(\"snapshot_path\")\n            details = point.get(\"details\") or {}\n            if snapshot and os.path.exists(snapshot) and os.path.isdir(snapshot):\n                if point.get(\"action\") == \"partition_merge\":\n                    target_letter = details.get(\"source_letter\")\n                    if target_letter and os.path.isdir(f\"{target_letter}:\\\\\"):\n                        copy_cmd = [\"robocopy\", snapshot, f\"{target_letter}:\\\\\", \"/MIR\", \"/R:2\", \"/W:2\", \"/NFL\"]\n                        result = safe_run(copy_cmd, timeout=7200)\n                        if result.returncode &lt; 8:\n                            return True, f\"Rollback restored backup to {target_letter}:\"\n                        return False, f\"Rollback failed during restore copy (rc={result.returncode})\"\n                return True, f\"Rollback point available for {point.get('action')} \u2014 backup exists at {snapshot}\"\n            return True, f\"Rollback point prepared for {point.get('action')}\"\n        except Exception:\n            return False, \"Rollback restore failed\"\n\n    # \u2500\u2500 UI Queue Poller \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _poll_ui_queue(self):\n        \"\"\"\n        Main-thread poller: drains _ui_queue every 50 ms.\n\n        Background threads NEVER touch Tkinter widgets directly.\n        They put (msg_type, payload) into self._ui_queue and this method\n        applies all pending updates in one go, keeping the GUI responsive.\n\n        Supported message types\n        \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        (\"progress_label\",  str)           \u2013 raw_progress_label text\n        (\"log_line\",        str)           \u2013 append line to raw_progress_log\n        (\"progress_pct\",   float)         \u2013 set raw_progress_var (0-100)\n        (\"status\",         (str, color))  \u2013 bottom status bar\n        (\"tree_row\",       (row, entry))  \u2013 insert row into rec_tree\n        (\"scan_mode\",      (str, color))  \u2013 scan_mode_label update\n        (\"rec_stats\",      None)          \u2013 refresh rec_stats_label\n        (\"finish_op\",      None)          \u2013 call _finish_recovery_operation\n        (\"progress_bar_mode\", str)        \u2013 \"indeterminate\" or \"determinate\"\n        (\"progress_bar_start\", int)       \u2013 start indeterminate animation\n        (\"progress_bar_stop\",  None)      \u2013 stop animation\n        \"\"\"\n        try:\n            processed = 0\n            while not self._ui_queue.empty() and processed &lt; 100:\n                msg_type, payload = self._ui_queue.get_nowait()\n                processed += 1\n\n                if msg_type == \"progress_label\":\n                    if hasattr(self, \"raw_progress_label\"):\n                        self.raw_progress_label.config(text=str(payload)[:200])\n\n                elif msg_type == \"log_line\":\n                    if hasattr(self, \"raw_progress_log\"):\n                        try:\n                            self.raw_progress_log.config(state=\"normal\")\n                            self.raw_progress_log.insert(\"end\", self._fix_text(str(payload)) + \"\\n\")\n                            # Keep log from growing unbounded\n                            lines = float(self.raw_progress_log.index(\"end-1c\").split(\".\")[0])\n                            if lines &gt; 300:\n                                self.raw_progress_log.delete(\"1.0\", \"100.0\")\n                            self.raw_progress_log.see(\"end\")\n                            self.raw_progress_log.config(state=\"disabled\")\n                        except Exception:\n                            pass\n\n                elif msg_type == \"progress_pct\":\n                    if hasattr(self, \"raw_progress_var\") and hasattr(self, \"raw_progress_bar\"):\n                        try:\n                            self.raw_progress_bar.stop()\n                        except Exception:\n                            pass\n                        self.raw_progress_bar.config(mode=\"determinate\")\n                        self.raw_progress_var.set(max(0.0, min(100.0, float(payload))))\n\n                elif msg_type == \"status\":\n                    msg, color = payload\n                    self._set_status(msg, color)\n\n                elif msg_type == \"tree_row\":\n                    row, entry = payload\n                    if hasattr(self, \"rec_tree\"):\n                        try:\n                            iid = self.rec_tree.insert(\"\", \"end\", values=row, tags=(\"found\",))\n                            if not hasattr(self, \"rec_found_files\") or not isinstance(self.rec_found_files, dict):\n                                self.rec_found_files = {}\n                            self.rec_found_files[iid] = entry\n                        except Exception:\n                            pass\n\n                elif msg_type == \"scan_mode\":\n                    text, color = payload\n                    if hasattr(self, \"scan_mode_label\"):\n                        self.scan_mode_label.config(text=text, fg=color or C[\"accent4\"])\n\n                elif msg_type == \"rec_stats\":\n                    self._on_rec_select()\n\n                elif msg_type == \"recovery_queue\":\n                    self._refresh_recovery_queue_tree()\n\n                elif msg_type == \"recovery_refresh\":\n                    self._refresh_recovery_tree(getattr(self, \"quick_recovery_tree\", None), category=\"Quick Recovery\")\n                    self._refresh_recovery_tree(getattr(self, \"deep_recovery_tree\", None), category=\"Deep Recovery\")\n\n                elif msg_type == \"photorec_tree_row\":\n                    if hasattr(self, \"photorec_tree\"):\n                        try:\n                            self.photorec_tree.insert(\"\", \"end\", values=payload)\n                        except Exception:\n                            pass\n\n                elif msg_type == \"mft_tree_row\":\n                    if hasattr(self, \"mft_tree\"):\n                        try:\n                            self.mft_tree.insert(\"\", \"end\", values=payload)\n                        except Exception:\n                            pass\n\n                elif msg_type == \"recovery_log\":\n                    self._append_recovery_log(str(payload))\n\n                elif msg_type == \"recovery_scan_stats\":\n                    self._apply_recovery_scan_stats(payload)\n\n                elif msg_type == \"clone_progress\":\n                    # payload: (pct:int, text:str, mode:str)\n                    try:\n                        if isinstance(payload, (list, tuple)) and len(payload) &gt;= 3:\n                            pct, text, mode = payload[0], payload[1], payload[2]\n                        elif isinstance(payload, (list, tuple)) and len(payload) &gt;= 2:\n                            pct, text, mode = payload[0], payload[1], \"clone\"\n                        else:\n                            pct, text, mode = int(payload), None, \"clone\"\n                    except Exception:\n                        try:\n                            pct = int(payload)\n                        except Exception:\n                            pct = 0\n                        text = None\n                        mode = \"clone\"\n                    if mode == \"partition\":\n                        if hasattr(self, \"partition_progress_bar\"):\n                            try:\n                                if pct is not None and float(pct) &gt; 0:\n                                    self.partition_progress_bar.stop()\n                                    self.partition_progress_bar.config(mode=\"determinate\")\n                                elif text is not None:\n                                    self.partition_progress_bar.config(mode=\"indeterminate\")\n                                    self.partition_progress_bar.start(10)\n                            except Exception:\n                                pass\n                        if hasattr(self, \"partition_progress_var\"):\n                            try:\n                                self.partition_progress_var.set(max(0.0, min(100.0, float(pct))))\n                            except Exception:\n                                pass\n                        if hasattr(self, \"partition_status_label\") and text is not None:\n                            try:\n                                self.partition_status_label.config(text=str(text)[:200])\n                            except Exception:\n                                pass\n                    else:\n                        if hasattr(self, \"clone_progress_bar\"):\n                            try:\n                                if pct is not None and float(pct) &gt; 0:\n                                    self.clone_progress_bar.stop()\n                                    self.clone_progress_bar.config(mode=\"determinate\")\n                                elif text is not None:\n                                    self.clone_progress_bar.config(mode=\"indeterminate\")\n                                    self.clone_progress_bar.start(10)\n                            except Exception:\n                                pass\n                        if hasattr(self, \"clone_progress_var\"):\n                            try:\n                                self.clone_progress_var.set(max(0.0, min(100.0, float(pct))))\n                            except Exception:\n                                pass\n                        if hasattr(self, \"clone_status_label\") and text is not None:\n                            try:\n                                self.clone_status_label.config(text=str(text)[:200])\n                            except Exception:\n                                pass\n\n                elif msg_type == \"finish_op\":\n                    self._finish_recovery_operation()\n                    self._on_rec_select()\n\n                elif msg_type == \"progress_bar_mode\":\n                    if hasattr(self, \"raw_progress_bar\"):\n                        try:\n                            self.raw_progress_bar.stop()\n                        except Exception:\n                            pass\n                        self.raw_progress_bar.config(mode=str(payload))\n\n                elif msg_type == \"progress_bar_start\":\n                    if hasattr(self, \"raw_progress_bar\"):\n                        try:\n                            self.raw_progress_bar.stop()\n                        except Exception:\n                            pass\n                        self.raw_progress_bar.config(mode=\"indeterminate\")\n                        self.raw_progress_bar.start(int(payload))\n\n                elif msg_type == \"progress_bar_stop\":\n                    if hasattr(self, \"raw_progress_bar\"):\n                        try:\n                            self.raw_progress_bar.stop()\n                        except Exception:\n                            pass\n                        self.raw_progress_bar.config(mode=\"determinate\")\n\n        except _queue_module.Empty:\n            pass\n        except Exception:\n            pass\n        finally:\n            # Re-schedule \u2014 always keep polling while the app is alive\n            self.after(50, self._poll_ui_queue)\n\n    def _poll_ram_service_metrics(self):\n        latest = None\n        try:\n            while not self._ram_service_metrics_queue.empty():\n                latest = self._ram_service_metrics_queue.get_nowait()\n        except Exception:\n            latest = None\n        if latest is not None:\n            try:\n                self._update_ram_service_metrics_ui(latest)\n            except Exception:\n                pass\n        self.after(35, self._poll_ram_service_metrics)\n\n    def _poll_hdd_recovery_metrics(self):\n        latest = None\n        try:\n            while not self._hdd_recovery_metrics_queue.empty():\n                latest = self._hdd_recovery_metrics_queue.get_nowait()\n        except Exception:\n            latest = None\n        if latest is not None:\n            try:\n                self._update_hdd_recovery_metrics_ui(latest)\n            except Exception:\n                pass\n        self._hdd_recovery_flush_pending_metrics()\n        self.after(30, self._poll_hdd_recovery_metrics)\n\n    def _hdd_recovery_flush_pending_metrics(self):\n        try:\n            with self._hdd_recovery_metrics_lock:\n                if self._hdd_recovery_pending_metrics is None:\n                    return\n                now = time.monotonic()\n                if now - self._hdd_recovery_last_dispatch &gt;= 0.120:\n                    self._hdd_recovery_last_dispatch = now\n                    self._hdd_recovery_metrics_queue.put(self._hdd_recovery_pending_metrics.copy())\n                    self._hdd_recovery_pending_metrics = None\n        except Exception:\n            pass\n\n    def _update_hdd_recovery_metrics_ui(self, data):\n        try:\n            if hasattr(self, \"raw_progress_var\") and data.get(\"progress_pct\") is not None:\n                self.raw_progress_var.set(max(0.0, min(100.0, float(data[\"progress_pct\"]))))\n            if hasattr(self, \"raw_progress_label\") and data.get(\"status_text\") is not None:\n                self.raw_progress_label.config(text=self._fix_text(str(data[\"status_text\"])))\n            if hasattr(self, \"scan_mode_label\") and data.get(\"scan_mode\") is not None:\n                self.scan_mode_label.config(text=self._fix_text(str(data[\"scan_mode\"])))\n            if hasattr(self, \"rec_stats_label\") and data.get(\"files_found\") is not None:\n                total = int(data.get(\"files_found\", 0))\n                selected = len(self.rec_tree.selection()) if hasattr(self, \"rec_tree\") else 0\n                self.rec_stats_label.config(text=f\"{total} files found | {selected} selected\")\n            if hasattr(self, \"hdd_resource_delta_lbl\") and data.get(\"delta_mb\") is not None:\n                before_mb = int(data.get(\"resource_before_mb\", 0))\n                after_mb = int(data.get(\"resource_after_mb\", 0))\n                delta_mb = int(data.get(\"delta_mb\", 0))\n                self.hdd_resource_delta_lbl.config(\n                    text=f\"Memory Delta: {self._fmt_size(delta_mb)} ({before_mb} MB \u2192 {after_mb} MB)\")\n            if hasattr(self, \"hdd_service_status_lbl\") and data.get(\"service_control\") is not None:\n                self.hdd_service_status_lbl.config(text=self._fix_text(str(data.get(\"service_control\"))))\n            if hasattr(self, \"ram_execution_log\") and data.get(\"log_line\") is not None:\n                self._append_log(self.ram_execution_log, str(data[\"log_line\"]), C[\"text\"])\n        except Exception:\n            pass\n\n    def _hdd_recovery_emit_metrics(self, batch):\n        try:\n            if not isinstance(batch, dict):\n                batch = {\"status_text\": str(batch)}\n            batch = {**batch, \"ts\": datetime.datetime.now().isoformat(timespec=\"milliseconds\")}\n            now = time.monotonic()\n            with self._hdd_recovery_metrics_lock:\n                self._hdd_recovery_pending_metrics = batch.copy()\n                if now - self._hdd_recovery_last_dispatch &gt;= 0.120:\n                    self._hdd_recovery_last_dispatch = now\n                    self._hdd_recovery_metrics_queue.put(batch.copy())\n                    self._hdd_recovery_pending_metrics = None\n        except Exception:\n            pass\n\n    def _ram_service_emit_metrics(self, batch, force=False):\n        try:\n            if not isinstance(batch, dict):\n                batch = {\"status_text\": str(batch)}\n            batch = {**batch, \"ts\": datetime.datetime.now().isoformat(timespec=\"milliseconds\")}\n            now = time.monotonic()\n            with self._ram_service_metrics_lock:\n                self._ram_service_pending_metrics = batch.copy()\n                if force or now - self._ram_service_last_dispatch &gt;= 0.120:\n                    self._ram_service_last_dispatch = now\n                    self._ram_service_metrics_queue.put(batch.copy())\n                    self._ram_service_pending_metrics = None\n        except Exception:\n            pass\n\n    def _snapshot_resource_state(self):\n        try:\n            vm = psutil.virtual_memory()\n            return {\n                \"available_mb\": int(vm.available / 1024**2),\n                \"used_mb\": int((vm.total - vm.available) / 1024**2),\n                \"total_mb\": int(vm.total / 1024**2),\n                \"percent\": round(vm.percent, 2),\n            }\n        except Exception:\n            return None\n\n    def _reclaim_memory(self):\n        try:\n            gc.collect()\n        except Exception:\n            pass\n        try:\n            kernel32 = ctypes.windll.kernel32\n            psapi = ctypes.windll.psapi\n            handle = kernel32.GetCurrentProcess()\n            psapi.EmptyWorkingSet(handle)\n        except Exception:\n            pass\n\n    def _submit_ram_service_job(self, name, target, *args, **kwargs):\n        jm = getattr(self, \"job_manager\", None)\n        if jm is not None and hasattr(jm, \"submit_callable\"):\n            try:\n                jm.submit_callable(name, target, *args, **kwargs)\n                return True\n            except Exception:\n                pass\n        manager = getattr(self, \"worker_manager\", None)\n        if manager is not None and hasattr(manager, \"submit\"):\n            try:\n                manager.submit(name, target, *args, **kwargs)\n                return True\n            except Exception:\n                pass\n        try:\n            threading.Thread(target=target, args=args, kwargs=kwargs, daemon=True).start()\n            return True\n        except Exception:\n            return False\n\n    def _ram_service_action_submit(self, name, target, button=None, *args, **kwargs):\n        if not hasattr(self, \"_ram_service_action_lock\"):\n            self._ram_service_action_lock = threading.Lock()\n            self._ram_service_action_running = False\n        with self._ram_service_action_lock:\n            if getattr(self, \"_ram_service_action_running\", False):\n                if hasattr(self, \"ram_log\"):\n                    self._append_log(self.ram_log, \"\u26a0\ufe0f RAM/Service action already running \u2014 duplicate request skipped\", C[\"warning\"])\n                return False\n            self._ram_service_action_running = True\n            if button is not None:\n                try:\n                    button.config(state=\"disabled\")\n                except Exception:\n                    pass\n\n        def _wrapped(*args, **kwargs):\n            try:\n                return target(*args, **kwargs)\n            finally:\n                with self._ram_service_action_lock:\n                    self._ram_service_action_running = False\n                if button is not None:\n                    try:\n                        button.config(state=\"normal\")\n                    except Exception:\n                        pass\n                try:\n                    gc.collect()\n                except Exception:\n                    pass\n\n        return self._submit_ram_service_job(name, _wrapped, *args, **kwargs)\n\n    def _submit_printer_job(self, name, target, *args, **kwargs):\n        jm = getattr(self, \"job_manager\", None)\n        if jm is not None and hasattr(jm, \"submit_callable\"):\n            try:\n                jm.submit_callable(name, target, *args, **kwargs)\n                return True\n            except Exception:\n                pass\n        manager = getattr(self, \"worker_manager\", None)\n        if manager is not None and hasattr(manager, \"submit\"):\n            try:\n                manager.submit(name, target, *args, **kwargs)\n                return True\n            except Exception:\n                pass\n        try:\n            threading.Thread(target=target, args=args, kwargs=kwargs, daemon=True).start()\n            return True\n        except Exception:\n            return False\n\n    def _set_printer_action_controls_enabled(self, enabled):\n        for btn in getattr(self, \"_printer_action_buttons\", []):\n            try:\n                btn.config(state=\"normal\" if enabled else \"disabled\")\n            except Exception:\n                pass\n\n    def _printer_action_submit(self, name, target, *args, button=None, **kwargs):\n        with self._printer_action_lock:\n            if getattr(self, \"_printer_action_running\", False):\n                self._printer_log(\"\u26a0\ufe0f Printer action already running \u2014 duplicate request skipped\", C[\"warning\"])\n                return False\n            self._printer_action_running = True\n            self._printer_action_started_at = time.time()\n            self._printer_action_name = name\n            self._set_printer_action_controls_enabled(False)\n            if button is not None:\n                try:\n                    button.config(state=\"disabled\")\n                except Exception:\n                    pass\n\n        def _wrapped(*args, **kwargs):\n            try:\n                self._printer_emit_metrics({\"status_text\": f\"{name} running... elapsed 00:00\"})\n                return target(*args, **kwargs)\n            finally:\n                with self._printer_action_lock:\n                    self._printer_action_running = False\n                    self._printer_action_started_at = None\n                    self._printer_action_name = \"\"\n                self._printer_emit_metrics({\"status_text\": f\"{name} finished\"})\n                self._set_printer_action_controls_enabled(True)\n                if button is not None:\n                    try:\n                        button.config(state=\"normal\")\n                    except Exception:\n                        pass\n                try:\n                    gc.collect()\n                except Exception:\n                    pass\n\n        return self._submit_printer_job(name, _wrapped, *args, **kwargs)\n\n    def _tick_printer_action_timer(self):\n        try:\n            if getattr(self, \"_printer_action_running\", False) and getattr(self, \"_printer_action_started_at\", None):\n                elapsed = time.time() - float(self._printer_action_started_at)\n                name = getattr(self, \"_printer_action_name\", \"Printer action\") or \"Printer action\"\n                if hasattr(self, \"printer_exec_time_lbl\"):\n                    self.printer_exec_time_lbl.config(text=f\"Elapsed: {self._format_seconds(elapsed)} | ETA: depends on Windows service response\")\n                if hasattr(self, \"printer_exec_status_lbl\"):\n                    self.printer_exec_status_lbl.config(text=f\"{name} running...\")\n            elif hasattr(self, \"printer_exec_time_lbl\"):\n                self.printer_exec_time_lbl.config(text=\"Elapsed: 00:00 | ETA: --\")\n        except Exception:\n            pass\n        self.after(1000, self._tick_printer_action_timer)\n\n    def _poll_printer_metrics(self):\n        latest = None\n        try:\n            while not self._printer_metrics_queue.empty():\n                latest = self._printer_metrics_queue.get_nowait()\n        except Exception:\n            latest = None\n        if latest is not None:\n            try:\n                self._update_printer_metrics_ui(latest)\n            except Exception:\n                pass\n        self.after(30, self._poll_printer_metrics)\n\n    def _update_printer_metrics_ui(self, data):\n        try:\n            if hasattr(self, \"printer_exec_status_lbl\") and data.get(\"status_text\") is not None:\n                self.printer_exec_status_lbl.config(text=self._fix_text(str(data[\"status_text\"])), fg=C.get(\"accent4\", C[\"text\"]))\n            if hasattr(self, \"spooler_status_lbl\") and data.get(\"service_status\") is not None:\n                self.spooler_status_lbl.config(text=self._fix_text(str(data.get(\"service_status\"))))\n            if hasattr(self, \"printer_log\") and data.get(\"log_line\") is not None:\n                self._append_log(self.printer_log, str(data[\"log_line\"]), data.get(\"log_color\", C[\"text\"]))\n            if hasattr(self, \"printer_trace_log\") and data.get(\"trace_line\") is not None:\n                self._append_log(self.printer_trace_log, str(data[\"trace_line\"]), data.get(\"trace_color\", C[\"text_dim\"]))\n        except Exception:\n            pass\n\n    def _printer_emit_metrics(self, batch, force=False):\n        try:\n            if not isinstance(batch, dict):\n                batch = {\"status_text\": str(batch)}\n            batch = {**batch, \"ts\": datetime.datetime.now().isoformat(timespec=\"milliseconds\")}\n            with self._printer_metrics_lock:\n                self._printer_metrics_queue.put(batch.copy())\n        except Exception:\n            pass\n\n    def _printer_log(self, msg, color=C[\"text\"]):\n        self._printer_emit_metrics({\"log_line\": msg, \"log_color\": color})\n\n    def _printer_trace(self, msg, color=C[\"text_dim\"]):\n        self._printer_emit_metrics({\"trace_line\": msg, \"trace_color\": color})\n\n    def _submit_registry_gp_job(self, name, target, *args, **kwargs):\n        jm = getattr(self, \"job_manager\", None)\n        if jm is not None and hasattr(jm, \"submit_callable\"):\n            try:\n                jm.submit_callable(name, target, *args, **kwargs)\n                return True\n            except Exception:\n                pass\n        manager = getattr(self, \"worker_manager\", None)\n        if manager is not None and hasattr(manager, \"submit\"):\n            try:\n                manager.submit(name, target, *args, **kwargs)\n                return True\n            except Exception:\n                pass\n        try:\n            threading.Thread(target=target, args=args, kwargs=kwargs, daemon=True).start()\n            return True\n        except Exception:\n            return False\n\n    def _poll_registry_gp_metrics(self):\n        latest = None\n        try:\n            while not self._registry_gp_metrics_queue.empty():\n                latest = self._registry_gp_metrics_queue.get_nowait()\n        except Exception:\n            latest = None\n        if latest is not None:\n            try:\n                self._update_registry_gp_metrics_ui(latest)\n            except Exception:\n                pass\n        self.after(40, self._poll_registry_gp_metrics)\n\n    def _update_registry_gp_metrics_ui(self, data):\n        try:\n            if hasattr(self, \"reg_progress_var\") and data.get(\"progress_pct\") is not None:\n                self.reg_progress_var.set(max(0.0, min(100.0, float(data[\"progress_pct\"]))))\n            if hasattr(self, \"reg_status_lbl\") and data.get(\"status_text\") is not None:\n                self.reg_status_lbl.config(text=self._fix_text(str(data[\"status_text\"])))\n            if hasattr(self, \"reg_keys_changed_var\") and data.get(\"keys_changed\") is not None:\n                self.reg_keys_changed_var.set(str(int(data[\"keys_changed\"])))\n            if hasattr(self, \"reg_predicted_impact_var\") and data.get(\"predicted_impact\") is not None:\n                self.reg_predicted_impact_var.set(str(int(data.get(\"predicted_impact\", 0))))\n            if hasattr(self, \"reg_confidence_var\") and data.get(\"confidence_score\") is not None:\n                self.reg_confidence_var.set(f\"{int(data.get('confidence_score', 0))}%\")\n            if hasattr(self, \"gp_progress_var\") and data.get(\"progress_pct\") is not None:\n                self.gp_progress_var.set(max(0.0, min(100.0, float(data[\"progress_pct\"]))))\n            if hasattr(self, \"gp_status_lbl\") and data.get(\"status_text\") is not None:\n                self.gp_status_lbl.config(text=self._fix_text(str(data[\"status_text\"])))\n            if hasattr(self, \"gp_action_count_var\") and data.get(\"actions_done\") is not None:\n                self.gp_action_count_var.set(str(int(data[\"actions_done\"])))\n            if hasattr(self, \"gp_policy_score_var\") and data.get(\"policy_score\") is not None:\n                self.gp_policy_score_var.set(f\"{int(data[\"policy_score\"])}%\")\n            if hasattr(self, \"gp_restart_risk_var\") and data.get(\"restart_risk\") is not None:\n                self.gp_restart_risk_var.set(str(data[\"restart_risk\"]))\n        except Exception:\n            pass\n\n    # \u2500\u2500 Thread-safe queue helpers (called from background threads) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _q(self, msg_type, payload=None):\n        \"\"\"Thread-safe: enqueue a UI update message.\"\"\"\n        try:\n            self._ui_queue.put_nowait((msg_type, payload))\n        except Exception:\n            pass\n\n    def _q_progress(self, text, pct=None):\n        \"\"\"Enqueue a progress label + optional percentage update.\"\"\"\n        self._q(\"progress_label\", text)\n        if pct is not None:\n            self._q(\"progress_pct\", pct)\n\n    def _q_log(self, text):\n        \"\"\"Enqueue a log line append.\"\"\"\n        self._q(\"log_line\", text)\n\n    def _q_tree_row(self, row, entry):\n        \"\"\"Enqueue a tree row insertion.\"\"\"\n        self._q(\"tree_row\", (row, entry))\n\n    # \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _safe_json(self, value):\n        try:\n            json.dumps(value)\n            return value\n        except Exception:\n            return str(value)\n\n    def _audit_event(self, event_type, payload):\n        try:\n            if not getattr(self, \"audit_file\", \"\"):\n                return\n            rec = {\n                \"ts\": datetime.datetime.now().isoformat(timespec=\"seconds\"),\n                \"event\": str(event_type),\n                \"payload\": self._safe_json(payload),\n            }\n            with open(self.audit_file, \"a\", encoding=\"utf-8\") as f:\n                f.write(json.dumps(rec, ensure_ascii=False) + \"\\n\")\n            try:\n                if hasattr(self, \"structured_logger\"):\n                    self.structured_logger.event(\"legacy_app\", str(event_type), legacy_payload=payload)\n                store = getattr(self, \"audit_store\", None)\n                if store is not None:\n                    store.append(\"legacy_app\", str(event_type), payload)\n            except Exception:\n                pass\n        except Exception:\n            pass\n\n    def _snapshot_system_state(self):\n        try:\n            vm = psutil.virtual_memory()\n            du = psutil.disk_usage(\"C:\\\\\")\n            cpu = psutil.cpu_percent(interval=None)\n            proc_count = len(list(psutil.process_iter([\"pid\"])))\n            return {\n                \"cpu_percent\": round(cpu, 2),\n                \"ram_percent\": round(vm.percent, 2),\n                \"disk_percent\": round(du.percent, 2),\n                \"process_count\": proc_count,\n                \"ts\": datetime.datetime.now().isoformat(timespec=\"seconds\"),\n            }\n        except Exception as e:\n            return {\"error\": str(e)}\n\n    def _launch_job(self, name, target, *args, **kwargs):\n        with self._job_lock:\n            self._job_counter += 1\n            jid = f\"job-{self._job_counter}\"\n            self._jobs[jid] = {\n                \"name\": name,\n                \"status\": \"queued\",\n                \"started_at\": datetime.datetime.now().isoformat(timespec=\"seconds\"),\n            }\n\n        task_id = self._task_start(name, progress=0, metadata={\"job_id\": jid})\n\n        def runner():\n            with self._job_lock:\n                if jid in self._jobs:\n                    self._jobs[jid][\"status\"] = \"running\"\n            self._audit_event(\"job_started\", {\"job_id\": jid, \"name\": name, \"task_id\": task_id})\n            try:\n                target_kwargs = dict(kwargs)\n                try:\n                    sig = inspect.signature(target)\n                    if \"task_id\" in sig.parameters:\n                        target_kwargs[\"task_id\"] = task_id\n                except Exception:\n                    pass\n                target(*args, **target_kwargs)\n                with self._job_lock:\n                    if jid in self._jobs:\n                        self._jobs[jid][\"status\"] = \"done\"\n                        self._jobs[jid][\"ended_at\"] = datetime.datetime.now().isoformat(timespec=\"seconds\")\n                task_record = self._task_manager.get(task_id)\n                if task_record is not None and not task_record.get(\"cancel_requested\", False) and task_record.get(\"status\") != \"failed\":\n                    task_record[\"progress\"] = 100\n                    task_record[\"status\"] = \"done\"\n            except Exception as e:\n                with self._job_lock:\n                    if jid in self._jobs:\n                        self._jobs[jid][\"status\"] = \"failed\"\n                        self._jobs[jid][\"error\"] = str(e)\n                if task_id in self._task_manager:\n                    self._task_manager[task_id][\"status\"] = \"failed\"\n                    self._task_manager[task_id][\"error\"] = str(e)\n                self._audit_event(\"job_failed\", {\"job_id\": jid, \"name\": name, \"error\": str(e), \"task_id\": task_id})\n                self.after(0, lambda: self._log(f\"Background job failed [{name}]: {e}\", \"ERR\"))\n            finally:\n                with self._job_lock:\n                    if jid in self._jobs and \"ended_at\" not in self._jobs[jid]:\n                        self._jobs[jid][\"ended_at\"] = datetime.datetime.now().isoformat(timespec=\"seconds\")\n                self._audit_event(\"job_finished\", {\"job_id\": jid, \"name\": name, \"task_id\": task_id})\n                if hasattr(self, \"task_center_tree\"):\n                    self.after(0, self._refresh_task_center)\n\n        manager = getattr(self, \"worker_manager\", None)\n        jm = getattr(self, \"job_manager\", None)\n        if jm is not None and hasattr(jm, \"submit_callable\"):\n            try:\n                jm.submit_callable(name, runner)\n                return task_id\n            except Exception:\n                pass\n        if manager is not None and hasattr(manager, \"submit\"):\n            try:\n                manager.submit(name, runner)\n            except Exception:\n                threading.Thread(target=runner, daemon=True).start()\n        else:\n            threading.Thread(target=runner, daemon=True).start()\n        return task_id\n    \n    def _create_tooltip(self, widget, text, delay=430):\n        \"\"\"Attach a small hover tooltip to a widget.\"\"\"\n        if not widget or not text:\n            return\n        tipdata = {\"id\": None, \"window\": None}\n\n        def _show(event=None):\n            if tipdata[\"window\"] or not text:\n                return\n            try:\n                x = widget.winfo_rootx() + 18\n                y = widget.winfo_rooty() + widget.winfo_height() + 6\n                win = tk.Toplevel(widget)\n                win.wm_overrideredirect(True)\n                win.attributes(\"-topmost\", True)\n                win.config(bg=C[\"text_dark\"])\n                lbl = tk.Label(win, text=text, justify=\"left\", bg=C[\"text_dark\"], fg=C[\"text\"],\n                               font=FONTS[\"xsmall\"], wraplength=320, relief=\"solid\", bd=1, padx=6, pady=4)\n                lbl.pack()\n                win.wm_geometry(f\"+{x}+{y}\")\n                tipdata[\"window\"] = win\n            except Exception:\n                tipdata[\"window\"] = None\n\n        def _hide(event=None):\n            try:\n                if tipdata[\"id\"]:\n                    self.after_cancel(tipdata[\"id\"])\n                    tipdata[\"id\"] = None\n                if tipdata[\"window\"]:\n                    tipdata[\"window\"].destroy()\n                    tipdata[\"window\"] = None\n            except Exception:\n                pass\n\n        def _schedule(event=None):\n            _hide()\n            try:\n                tipdata[\"id\"] = self.after(delay, _show)\n            except Exception:\n                tipdata[\"id\"] = None\n\n        widget.bind(\"\", _schedule)\n        widget.bind(\"\", _hide)\n        widget.bind(\"\", _hide)\n        return tipdata\n\n    # ---------- STYLE ----------\n    def _build_style(self):\n        self.style = ttk.Style(self)\n        self.style.theme_use(\"clam\")\n        self.style.configure(\"TFrame\", background=C[\"bg\"])\n        self.style.configure(\"Card.TFrame\", background=C[\"card\"])\n        self.style.configure(\"Panel.TFrame\", background=C[\"panel\"])\n        self.style.configure(\"Sidebar.TFrame\", background=C[\"sidebar\"])\n        self.style.configure(\"TProgressbar\", troughcolor=C[\"border\"], background=C[\"accent\"], thickness=6)\n        self.style.configure(\"TNotebook\", background=C[\"bg\"], borderwidth=0)\n        self.style.configure(\"TNotebook.Tab\", background=C[\"panel\"], foreground=C[\"text_dim\"], padding=[16, 6], borderwidth=0)\n        self.style.map(\"TNotebook.Tab\",\n                        background=[(\"selected\", C[\"card\"]), (\"active\", C[\"panel\"]), (\"!active\", C[\"panel\"])],\n                        foreground=[(\"selected\", C[\"accent\"]), (\"active\", C[\"text\"]), (\"!active\", C[\"text_dim\"])])\n        self.style.configure(\"Custom.Treeview\", background=C[\"card\"], foreground=C[\"text\"],\n                             fieldbackground=C[\"card\"], rowheight=22, font=FONTS[\"small\"])\n        self.style.configure(\"Custom.Treeview.Heading\", background=C[\"panel\"],\n                             foreground=C[\"accent\"], font=FONTS[\"small\"])\n\n    # ---------- HEADER ----------\n    def _build_header(self):\n        hdr = tk.Frame(self, bg=C[\"header_bg\"], height=62)\n        hdr.pack(side=\"top\", fill=\"x\")\n        hdr.pack_propagate(False)\n        tk.Frame(hdr, bg=C[\"accent\"], height=2).pack(side=\"bottom\", fill=\"x\")\n\n        logo_frame = tk.Frame(hdr, bg=C[\"header_bg\"])\n        logo_frame.pack(side=\"left\", padx=20, pady=8)\n        tk.Label(logo_frame, text=\"\u26a1\", font=(\"Segoe UI\", 24), fg=C[\"accent\"], bg=C[\"header_bg\"]).pack(side=\"left\", padx=(0,8))\n        tk.Label(logo_frame, text=\"Godawari\", font=(\"Segoe UI\", 18, \"bold\"), fg=C[\"text\"], bg=C[\"header_bg\"]).pack(side=\"left\")\n        tk.Label(logo_frame, text=\" Computers\", font=(\"Segoe UI\", 18, \"bold\"), fg=C[\"accent\"], bg=C[\"header_bg\"]).pack(side=\"left\")\n        tk.Label(logo_frame, text=\"  Optimizer Pro v11.0\", font=(\"Segoe UI\", 10, \"bold\"), fg=C[\"accent2\"], bg=C[\"header_bg\"]).pack(side=\"left\", pady=(6,0))\n        tk.Label(logo_frame, text=f\"  |  Last Updated: {SCRIPT_LAST_UPDATED}\", font=(\"Segoe UI\", 9), fg=C[\"text_dim\"], bg=C[\"header_bg\"]).pack(side=\"left\", pady=(6,0))\n\n        right = tk.Frame(hdr, bg=C[\"header_bg\"])\n        right.pack(side=\"right\", padx=20, pady=10)\n        self.clock_lbl = tk.Label(right, font=FONTS[\"small\"], fg=C[\"accent\"], bg=C[\"header_bg\"])\n        self.clock_lbl.pack(side=\"right\")\n        tk.Label(right, text=f\"  {platform.node()}  |  {platform.system()} {platform.release()}  |  \",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"header_bg\"]).pack(side=\"right\")\n        self._tick_clock()\n\n        badge_color = C[\"success\"] if is_admin() else C[\"error\"]\n        badge_text = \"\u25cf ADMIN MODE ON\" if is_admin() else \"\u25cf USER MODE (Admin required!)\"\n        tk.Label(hdr, text=badge_text, font=FONTS[\"small\"], fg=badge_color, bg=C[\"header_bg\"]).pack(side=\"right\", padx=12)\n\n        self.theme_btn = tk.Button(hdr, text=\"\ud83c\udf19\", font=(\"Segoe UI\", 10), bg=C[\"panel\"],\n                                   fg=C[\"accent\"], bd=0, padx=6, cursor=\"hand2\", command=self._toggle_theme)\n        self.theme_btn.pack(side=\"right\", padx=10)\n        tk.Label(hdr, text=\"Shravan Shrimali\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"header_bg\"]).pack(side=\"right\", padx=10)\n\n    def _tick_clock(self):\n        self.clock_lbl.config(text=datetime.datetime.now().strftime(\"%d/%m/%Y  %H:%M:%S\"))\n        self.after(1000, self._tick_clock)\n\n    # ---------- BODY ----------\n    # Section builder map \u2014 lazy loading ke liye\n    _SECTION_BUILDERS = {\n        \"dashboard\":      \"_build_dashboard\",\n        \"shop\":           \"_build_shop_mode\",\n        \"cleaner\":        \"_build_cleaner\",\n        \"services\":       \"_build_services\",\n        \"memory\":         \"_build_memory_services_merged\",\n        \"startup\":        \"_build_startup_scheduler_merged\",\n        \"registry\":       \"_build_registry_gp_merged\",\n        \"network\":        \"_build_network_troubleshooter_merged\",\n        \"hdd_repair\":     \"_build_hdd_recovery_merged\",\n        \"data_recovery\":  \"_build_data_recovery\",\n        \"rescue_center\":  \"_build_rescue_recovery_center\",\n        \"printer\":        \"_build_printer_driver_merged\",\n        \"uninstall\":      \"_build_uninstall_backup_merged\",\n        \"dupfinder\":      \"_build_dup_report_merged\",\n        \"grouppolicy\":    \"_build_grouppolicy\",\n        \"scheduler\":      \"_build_scheduler\",\n        \"troubleshooter\": \"_build_troubleshooter\",\n        \"power\":          \"_build_power\",\n        \"driver\":         \"_build_driver\",\n        \"backup\":         \"_build_backup\",\n        \"report\":         \"_build_report\",\n        \"log\":            \"_build_log\",\n        \"boost\":          \"_build_boost_section\",\n        \"suspicion\":      \"_build_suspicion_scanner\",\n        \"realtime_security\": \"_build_realtime_security\",\n        \"activation\":     \"_build_activation\",\n        \"eventviewer\":    \"_build_event_viewer\",\n        \"office_tools\":   \"_build_office_tools\",\n        \"excel_tools\":    \"_build_excel_tools\",\n        \"image_tools\":    \"_build_image_tools\",\n        \"file_tools\":     \"_build_file_tools\",\n        \"safety_center\":  \"_build_safety_center\",\n        \"driver_manager\": \"_build_driver_manager\",\n        \"partition_manager\": \"_build_partition_manager\",\n        \"easy_driver\":    \"_build_easy_driver_clone\",\n        \"svc_presets\":    \"_build_svc_presets\",\n        \"disk_analyzer\":  \"_build_disk_analyzer\",\n        \"bsod_history\":   \"_build_bsod_history\",\n        \"corrupt_wizard\": \"_build_corrupt_wizard\",\n        \"password_audit\": \"_build_password_audit\",\n        \"auto_backup\":    \"_build_auto_backup\",\n    }\n\n    def _build_body(self):\n        body = tk.Frame(self, bg=C[\"bg\"])\n        body.pack(fill=\"both\", expand=True)\n        self.sidebar = tk.Frame(body, bg=C[\"sidebar\"], width=260)\n        self.sidebar.pack(side=\"left\", fill=\"y\")\n        self.sidebar.pack_propagate(False)\n        tk.Frame(self.sidebar, bg=C[\"border\"], width=1).pack(side=\"right\", fill=\"y\")\n        self._build_sidebar()\n        self.main = tk.Frame(body, bg=C[\"bg\"])\n        self.main.pack(side=\"left\", fill=\"both\", expand=True)\n        self.sections = {}\n        self._sections_built = set()\n        self._build_queue = []\n\n        # Sirf dashboard abhi banaao \u2014 baki lazy load honge\n        self.sections[\"dashboard\"] = self._build_dashboard(self.main)\n        self._sections_built.add(\"dashboard\")\n\n        # Baki ke liye placeholder frames\n        for key in self._SECTION_BUILDERS:\n            if key == \"dashboard\":\n                continue\n            ph = tk.Frame(self.main, bg=C[\"bg\"])\n            tk.Label(ph, text=\"\u23f3\", font=(\"Segoe UI\", 28),\n                     fg=C[\"accent\"], bg=C[\"bg\"]).place(relx=0.5, rely=0.42, anchor=\"center\")\n            tk.Label(ph, text=\"Loading...\", font=FONTS[\"heading\"],\n                     fg=C[\"text_dim\"], bg=C[\"bg\"]).place(relx=0.5, rely=0.52, anchor=\"center\")\n            self.sections[key] = ph\n            self._build_queue.append(key)\n\n        # Keep startup fast: sections are built when the user opens them.\n        self.after(600, self._sanitize_ui_texts)\n\n    def _lazy_build_next(self):\n        if not self._build_queue:\n            return\n        key = self._build_queue.pop(0)\n        try:\n            real = getattr(self, self._SECTION_BUILDERS[key])(self.main)\n            self.sections[key] = real\n            self._sections_built.add(key)\n            if self.active_section.get() == key:\n                for s in self.sections.values():\n                    s.pack_forget()\n                real.pack(fill=\"both\", expand=True)\n        except Exception as e:\n            import traceback\n            err_detail = traceback.format_exc()\n            self._log(f\"Lazy build [{key}] ERROR: {err_detail}\", \"WARN\")\n            # Replace placeholder with error frame so user knows something failed\n            err_frame = tk.Frame(self.main, bg=C[\"bg\"])\n            tk.Label(err_frame, text=f\"\u274c '{key}' section load nahi hua\",\n                     font=FONTS[\"heading\"], fg=C[\"error\"], bg=C[\"bg\"]).place(relx=0.5, rely=0.40, anchor=\"center\")\n            tk.Label(err_frame, text=str(e)[:200],\n                     font=FONTS[\"small\"], fg=C[\"warning\"], bg=C[\"bg\"], wraplength=500).place(relx=0.5, rely=0.50, anchor=\"center\")\n            tk.Button(err_frame, text=\"\ud83d\udd04 Retry\",\n                      font=FONTS[\"body\"], bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=16, pady=8,\n                      cursor=\"hand2\",\n                      command=lambda k=key: (self._sections_built.discard(k),\n                                              self._show_section(k))).place(relx=0.5, rely=0.62, anchor=\"center\")\n            self.sections[key] = err_frame\n        if self._build_queue:\n            self.after(40, self._lazy_build_next)\n\n    def _build_sidebar(self):\n        canvas = tk.Canvas(self.sidebar, bg=C[\"sidebar\"], highlightthickness=0)\n        scrollbar = tk.Scrollbar(self.sidebar, orient=\"vertical\", command=canvas.yview)\n        self.sidebar_frame = tk.Frame(canvas, bg=C[\"sidebar\"])\n        self.sidebar_frame.bind(\"\", lambda e: canvas.configure(scrollregion=canvas.bbox(\"all\")))\n        sidebar_window = canvas.create_window((0, 0), window=self.sidebar_frame, anchor=\"nw\")\n        canvas.configure(yscrollcommand=scrollbar.set)\n        scrollbar.pack(side=\"right\", fill=\"y\")\n        canvas.pack(side=\"left\", fill=\"both\", expand=True)\n\n        def _sidebar_resize(event=None):\n            canvas.itemconfig(sidebar_window, width=event.width)\n            canvas.configure(scrollregion=canvas.bbox(\"all\"))\n        canvas.bind(\"\", _sidebar_resize)\n\n        self._bind_scoped_mousewheel(self.sidebar_frame, canvas)\n\n        tk.Label(self.sidebar_frame, text=\"GODAWARI COMPUTERS\", font=(\"Segoe UI\", 10, \"bold\"),\n                 fg=C[\"accent\"], bg=C[\"sidebar\"]).pack(pady=(12,2), padx=14, anchor=\"w\")\n        tk.Label(self.sidebar_frame, text=\"Optimizer Pro v11.0\", font=FONTS[\"small\"],\n                 fg=C[\"text_dim\"], bg=C[\"sidebar\"]).pack(pady=(0,8), padx=14, anchor=\"w\")\n\n        categories = SIDEBAR_CATEGORIES\n        self.nav_btns = {}\n        for heading, color_key, items in categories:\n            color = C[color_key]\n            # Category separator line\n            tk.Frame(self.sidebar_frame, bg=C[\"border\"], height=1).pack(fill=\"x\", padx=10, pady=(8,0))\n            tk.Label(self.sidebar_frame, text=heading, font=(\"Segoe UI\", 8, \"bold\"), fg=color, bg=C[\"sidebar\"]).pack(pady=(4,3), padx=14, anchor=\"w\")\n            for key, icon, label in items:\n                frame = tk.Frame(self.sidebar_frame, bg=C[\"sidebar\"], cursor=\"hand2\")\n                frame.pack(fill=\"x\", padx=8, pady=1)\n                hw_keys = set()\n                icon_fg = C[\"hw_accent\"] if key in hw_keys else C[\"accent\"]\n                tk.Label(frame, text=icon, font=(\"Segoe UI\", 8, \"bold\"), bg=C[\"sidebar\"], fg=icon_fg, width=5, anchor=\"center\").pack(side=\"left\", padx=(8,6), pady=6)\n                tk.Label(frame, text=label, font=FONTS[\"body\"], bg=C[\"sidebar\"], fg=C[\"text\"], anchor=\"w\").pack(side=\"left\", fill=\"x\", expand=True)\n                def on_enter(e, k=key, f=frame): \n                    if self.active_section.get() != k:\n                        f.config(bg=C[\"card\"])\n                        for w in f.winfo_children():\n                            w.config(bg=C[\"card\"])\n                def on_leave(e, k=key, f=frame): \n                    if self.active_section.get() != k:\n                        f.config(bg=C[\"sidebar\"])\n                        for w in f.winfo_children():\n                            w.config(bg=C[\"sidebar\"])\n                def on_click(e, k=key):\n                    self._show_section(k)\n                frame.bind(\"\", on_enter)\n                frame.bind(\"\", on_leave)\n                frame.bind(\"\", on_click)\n                for child in frame.winfo_children():\n                    child.bind(\"\", on_enter)\n                    child.bind(\"\", on_leave)\n                    child.bind(\"\", on_click)\n                self.nav_btns[key] = frame\n\n        tk.Frame(self.sidebar_frame, bg=C[\"border\"], height=1).pack(fill=\"x\", padx=10, pady=10)\n        info = tk.Frame(self.sidebar_frame, bg=C[\"panel\"])\n        info.pack(fill=\"x\", padx=10, pady=(0,10))\n        ram_gb = round(psutil.virtual_memory().total / (1024**3), 1)\n        for line in [f\"CPU: {psutil.cpu_count()} cores\", f\"RAM: {ram_gb} GB\", f\"OS: Windows {platform.release()}\"]:\n            tk.Label(info, text=line, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(anchor=\"w\", padx=8, pady=2)\n\n    def _show_section(self, key):\n        if key not in self.sections:\n            return\n        # On-demand build agar abhi tak nahi bana\n        if hasattr(self, \"_sections_built\") and key not in self._sections_built:\n            if key in getattr(self, \"_build_queue\", []):\n                self._build_queue.remove(key)\n            try:\n                real = getattr(self, self._SECTION_BUILDERS[key])(self.main)\n                self.sections[key] = real\n                self._sections_built.add(key)\n                self.after(50, self._sanitize_ui_texts)\n            except Exception as e:\n                import traceback\n                err_msg = traceback.format_exc()\n                self._log(f\"On-demand build [{key}]: {e}\", \"WARN\")\n                # Show error frame instead of silent loading screen\n                err_frame = tk.Frame(self.main, bg=C[\"bg\"])\n                tk.Label(err_frame, text=\"\u274c Section load nahi hua\",\n                         font=FONTS[\"heading\"], fg=C[\"error\"], bg=C[\"bg\"]).place(relx=0.5, rely=0.40, anchor=\"center\")\n                tk.Label(err_frame, text=str(e)[:200],\n                         font=FONTS[\"small\"], fg=C[\"warning\"], bg=C[\"bg\"], wraplength=500).place(relx=0.5, rely=0.50, anchor=\"center\")\n                tk.Button(err_frame, text=\"\ud83d\udd04 Retry\", font=FONTS[\"body\"],\n                          bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=16, pady=8,\n                          cursor=\"hand2\",\n                          command=lambda k=key: (self._sections_built.discard(k),\n                                                  self._show_section(k))).place(relx=0.5, rely=0.62, anchor=\"center\")\n                self.sections[key] = err_frame\n        old = self.active_section.get()\n        if old in self.nav_btns:\n            self.nav_btns[old].config(bg=C[\"sidebar\"])\n            for w in self.nav_btns[old].winfo_children():\n                w.config(bg=C[\"sidebar\"])\n        self.active_section.set(key)\n        if key in self.nav_btns:\n            self.nav_btns[key].config(bg=C[\"btn_info\"])\n            for w in self.nav_btns[key].winfo_children():\n                w.config(bg=C[\"btn_info\"])\n        for k, sec in self.sections.items():\n            sec.pack_forget()\n        self.sections[key].pack(fill=\"both\", expand=True)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  MERGED SECTION BUILDERS \u2014 2 sections ek tabbed view mein\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _build_tabbed_merger(self, parent, tabs):\n        \"\"\"\n        tabs = [(tab_label, builder_method_name), ...]\n        Ek frame return karta hai jisme top mein tab buttons hain,\n        niche active tab ka content.\n        \"\"\"\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        tab_bar = tk.Frame(frame, bg=C[\"panel\"])\n        tab_bar.pack(fill=\"x\")\n        content_area = tk.Frame(frame, bg=C[\"bg\"])\n        content_area.pack(fill=\"both\", expand=True)\n\n        built = {}\n        active_btn = [None]\n\n        def show_tab(idx, btn):\n            if active_btn[0]:\n                active_btn[0].config(bg=C[\"panel\"], fg=C[\"text_dim\"])\n            btn.config(bg=C[\"accent\"], fg=C[\"bg\"])\n            active_btn[0] = btn\n            for w in content_area.winfo_children():\n                w.pack_forget()\n            key = tabs[idx][0]\n            if key not in built:\n                built[key] = getattr(self, tabs[idx][1])(content_area)\n            built[key].pack(fill=\"both\", expand=True)\n\n        btns = []\n        for i, (label, _) in enumerate(tabs):\n            b = tk.Button(tab_bar, text=label, font=FONTS[\"subhead\"],\n                          bg=C[\"panel\"], fg=C[\"text_dim\"], bd=0, padx=20, pady=8,\n                          cursor=\"hand2\", relief=\"flat\",\n                          command=lambda idx=i: show_tab(idx, btns[idx]))\n            b.pack(side=\"left\")\n            btns.append(b)\n        tk.Frame(tab_bar, bg=C[\"border\"], height=2).pack(side=\"bottom\", fill=\"x\")\n\n        # Default: first tab\n        frame.after(10, lambda: show_tab(0, btns[0]))\n        return frame\n\n    def _build_memory_services_merged(self, parent):\n        return self._build_tabbed_merger(parent, [\n            (\"\ud83e\udde0  RAM Optimizer\", \"_build_memory\"),\n            (\"\u2699\ufe0f  Smart Services\", \"_build_services\"),\n        ])\n\n    def _build_startup_scheduler_merged(self, parent):\n        return self._build_tabbed_merger(parent, [\n            (\"\ud83d\ude80  Startup Manager\", \"_build_startup\"),\n            (\"\ud83d\udcc5  Task Scheduler\", \"_build_scheduler\"),\n        ])\n\n    def _build_registry_gp_merged(self, parent):\n        return self._build_tabbed_merger(parent, [\n            (\"\ud83d\udcdd  Registry Tweaks\", \"_build_registry\"),\n            (\"\ud83d\udee1  Group Policy\", \"_build_grouppolicy\"),\n        ])\n\n    def _build_network_troubleshooter_merged(self, parent):\n        return self._build_tabbed_merger(parent, [\n            (\"\ud83c\udf10  Network Optimizer\", \"_build_network\"),\n            (\"\ud83d\udd27  System Troubleshooter\", \"_build_troubleshooter\"),\n        ])\n\n    def _build_hdd_recovery_merged(self, parent):\n        return self._build_tabbed_merger(parent, [\n            (\"\ud83d\udcbe  HDD/SSD Repair\", \"_build_hdd_repair\"),\n            (\"\ud83d\udcc2  File Recovery\", \"_build_recovery_center\"),\n        ])\n\n    def _build_data_recovery(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(\n            frame,\n            \"\ud83d\udd2c Data Recovery\",\n            \"Forensic-grade imaging, deep carving, partition recovery, and raw sector inspection.\",\n        )\n\n        self._data_recovery_state = getattr(self, \"_data_recovery_state\", {\n            \"running\": False,\n            \"paused\": False,\n            \"cancelled\": False,\n            \"last_img\": \"\",\n            \"last_report\": \"\",\n            \"preview\": [],\n            \"scan_mode\": \"quick\",\n            \"history\": [],\n            \"queue\": [],\n            \"task_id\": None,\n            \"session_id\": None,\n        })\n\n        hero = tk.Frame(frame, bg=C[\"panel\"], highlightbackground=C[\"border\"], highlightthickness=1)\n        hero.pack(fill=\"x\", padx=16, pady=(8, 10))\n        hero.columnconfigure(0, weight=2)\n        hero.columnconfigure(1, weight=1)\n\n        left = tk.Frame(hero, bg=C[\"panel\"])\n        left.grid(row=0, column=0, sticky=\"nsew\", padx=(16, 10), pady=16)\n        tk.Label(\n            left,\n            text=\"Godawari Ultimate Optimizer v11 \u2014 Data Recovery\",\n            font=(\"Segoe UI\", 18, \"bold\"),\n            fg=C[\"text\"],\n            bg=C[\"panel\"],\n        ).pack(anchor=\"w\")\n        tk.Label(\n            left,\n            text=\"Forensic-grade imaging, deep carving, partition recovery, and safe raw-sector inspection in one premium control center.\",\n            font=FONTS[\"small\"],\n            fg=C[\"text_dim\"],\n            bg=C[\"panel\"],\n            justify=\"left\",\n            wraplength=760,\n        ).pack(anchor=\"w\", pady=(4, 10))\n\n        chip_row = tk.Frame(left, bg=C[\"panel\"])\n        chip_row.pack(fill=\"x\")\n        for text, color in [(\"Quick Recovery\", C[\"accent2\"]), (\"Deep Carve\", C[\"warning\"]), (\"Partition Audit\", C[\"hw_accent\"]), (\"Sector Imaging\", C[\"accent\"]), (\"Audit Report\", C[\"btn_info\"]), (\"Evidence Safe\", C[\"success\"])]:\n            chip = tk.Frame(chip_row, bg=color, height=20)\n            chip.pack(side=\"left\", padx=(0, 8), pady=2)\n            tk.Label(chip, text=text, font=FONTS[\"xsmall\"], fg=\"#0A0F1A\", bg=color, padx=8, pady=2).pack()\n\n        right = tk.Frame(hero, bg=C[\"panel\"])\n        right.grid(row=0, column=1, sticky=\"nsew\", padx=(10, 16), pady=16)\n        tk.Label(\n            right,\n            text=\"Recovery Flow\",\n            font=FONTS[\"subhead\"],\n            fg=C[\"accent\"],\n            bg=C[\"panel\"],\n        ).pack(anchor=\"w\")\n        tk.Label(\n            right,\n            text=\"1. Select source \u2022 2. Validate target \u2022 3. Recover or image \u2022 4. Export report\",\n            font=FONTS[\"small\"],\n            fg=C[\"text\"],\n            bg=C[\"panel\"],\n            justify=\"left\",\n            wraplength=320,\n        ).pack(anchor=\"w\", pady=(4, 10))\n        tk.Frame(right, bg=C[\"border\"], height=1).pack(fill=\"x\", pady=(0, 8))\n        tk.Label(\n            right,\n            text=\"Live status: Ready for a new evidence session.\",\n            font=FONTS[\"small\"],\n            fg=C[\"text_dim\"],\n            bg=C[\"panel\"],\n            anchor=\"w\",\n        ).pack(fill=\"x\")\n\n        safety = tk.Frame(frame, bg=C[\"card\"], highlightbackground=C[\"warning\"], highlightthickness=1)\n        safety.pack(fill=\"x\", padx=16, pady=(0, 10))\n        top_bar = tk.Frame(safety, bg=C[\"card\"])\n        top_bar.pack(fill=\"x\", padx=12, pady=(12, 6))\n        tk.Label(\n            top_bar,\n            text=\"\u26a0\ufe0f Safety Gate \u2014 Raw Operations\",\n            font=FONTS[\"subhead\"],\n            fg=C[\"warning\"],\n            bg=C[\"card\"],\n        ).pack(anchor=\"w\")\n        tk.Label(\n            safety,\n            text=\"Raw disk access, sector imaging, and partition recovery can alter evidence and metadata. Use only on authorized disks and always image first.\",\n            font=FONTS[\"small\"],\n            fg=C[\"text\"],\n            bg=C[\"card\"],\n            justify=\"left\",\n            wraplength=1100,\n        ).pack(anchor=\"w\", padx=12, pady=(0, 12))\n\n        summary = tk.Frame(frame, bg=C[\"bg\"])\n        summary.pack(fill=\"x\", padx=16, pady=(0, 8))\n        for idx in range(4):\n            summary.columnconfigure(idx, weight=1)\n\n        self._data_recovery_summary_labels = getattr(self, \"_data_recovery_summary_labels\", {})\n        for idx, (label, value, fg) in enumerate([\n            (\"Source\", \"Ready\", C[\"accent\"]),\n            (\"Recovered\", \"0 files\", C[\"accent2\"]),\n            (\"Chance\", \"Low\", C[\"warning\"]),\n            (\"Image\", \"No image yet\", C[\"hw_accent\"]),\n        ]):\n            if label not in self._data_recovery_summary_labels:\n                card = tk.Frame(summary, bg=C[\"card\"], highlightbackground=C[\"border\"], highlightthickness=1)\n                card.grid(row=0, column=idx, padx=5, pady=0, sticky=\"nsew\")\n                tk.Label(card, text=label, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=10, pady=(8, 2))\n                lbl = tk.Label(card, text=value, font=FONTS[\"heading\"], fg=fg, bg=C[\"card\"])\n                lbl.pack(anchor=\"w\", padx=10, pady=(0, 8))\n                self._data_recovery_summary_labels[label] = lbl\n            else:\n                self._data_recovery_summary_labels[label].config(text=value, fg=fg)\n\n        explain = tk.Frame(frame, bg=C[\"panel\"])\n        explain.pack(fill=\"x\", padx=16, pady=(0, 10))\n        tk.Label(explain, text=\"Quick Recovery \u2014 Fast file recovery / \u0924\u094d\u0935\u0930\u093f\u0924 \u092b\u093c\u093e\u0907\u0932 \u0930\u093f\u0915\u0935\u0930\u0940\", font=FONTS[\"small\"], fg=C[\"accent\"], bg=C[\"panel\"]).pack(anchor=\"w\", padx=10, pady=(6, 0))\n        tk.Label(explain, text=\"Deep Recovery \u2014 Signature carving and raw scan / \u0938\u093f\u0917\u094d\u0928\u0947\u091a\u0930-\u0906\u0927\u093e\u0930\u093f\u0924 \u0917\u0939\u0930\u0940 \u0916\u094b\u091c\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(anchor=\"w\", padx=10, pady=(0, 6))\n\n        notebook = ttk.Notebook(frame)\n        notebook.pack(fill=\"both\", expand=True, padx=16, pady=(0, 12))\n\n        quick_tab = tk.Frame(notebook, bg=C[\"bg\"])\n        notebook.add(quick_tab, text=\"Quick Recovery\")\n        quick_body = self._scrollable_section_body(quick_tab)\n        quick_card = tk.LabelFrame(\n            quick_body,\n            text=\"\ud83d\udcc1 Quick Recovery \u2014 Existing Files / \u092e\u094c\u091c\u0942\u0926\u093e \u092b\u093c\u093e\u0907\u0932\u094b\u0902 \u0915\u0940 \u0924\u094d\u0935\u0930\u093f\u0924 \u0930\u093f\u0915\u0935\u0930\u0940\",\n            font=FONTS[\"subhead\"],\n            fg=C[\"accent2\"],\n            bg=C[\"card\"],\n            bd=1,\n            relief=\"flat\",\n        )\n        quick_card.pack(fill=\"x\", padx=14, pady=10)\n        quick_card.columnconfigure(1, weight=1)\n\n        self._data_recovery_quick_disk_var = tk.StringVar(value=\"\")\n        self._data_recovery_filter_var = tk.StringVar(value=\"All\")\n        self._data_recovery_quick_output_var = tk.StringVar(value=os.path.join(os.path.expanduser(\"~\"), \"Desktop\", \"Godawari_DataRecovery_Quick\"))\n        self._data_recovery_quick_disk_combo = ttk.Combobox(quick_card, textvariable=self._data_recovery_quick_disk_var, values=[], width=42, state=\"readonly\")\n        self._data_recovery_quick_disk_combo.pack_forget()\n\n        quick_rows = tk.Frame(quick_card, bg=C[\"card\"])\n        quick_rows.pack(fill=\"x\", padx=10, pady=(8, 2))\n        tk.Label(quick_rows, text=\"Disk / Volume:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._data_recovery_quick_disk_combo = ttk.Combobox(quick_rows, textvariable=self._data_recovery_quick_disk_var, values=[], width=42, state=\"readonly\")\n        self._data_recovery_quick_disk_combo.pack(side=\"left\", padx=(8, 12))\n        tk.Label(quick_rows, text=\"Output Folder:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\")\n        tk.Entry(quick_rows, textvariable=self._data_recovery_quick_output_var, width=48, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).pack(side=\"left\", padx=(8, 8))\n        tk.Button(\n            quick_rows,\n            text=\"Browse\",\n            font=FONTS[\"small\"],\n            bg=C[\"panel\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=10,\n            pady=5,\n            cursor=\"hand2\",\n            command=lambda: self._data_recovery_choose_output(self._data_recovery_quick_output_var),\n        ).pack(side=\"left\")\n\n        filter_row = tk.Frame(quick_card, bg=C[\"card\"])\n        filter_row.pack(fill=\"x\", padx=10, pady=(6, 8))\n        tk.Label(filter_row, text=\"File type filter:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._data_recovery_filter_buttons = {}\n        for icon, label in [(\"\ud83d\uddbc\ufe0f\", \"Photos\"), (\"\ud83c\udfac\", \"Videos\"), (\"\ud83d\udcc4\", \"Documents\"), (\"\ud83d\udddc\ufe0f\", \"Archives\"), (\"\ud83d\udce6\", \"All\")]:\n            btn = tk.Button(\n                filter_row,\n                text=f\"{icon} {label}\",\n                font=FONTS[\"small\"],\n                bg=C[\"panel\"] if label != \"All\" else C[\"btn_chip\"],\n                fg=C[\"text\"],\n                bd=0,\n                padx=10,\n                pady=5,\n                cursor=\"hand2\",\n                command=lambda l=label: self._data_recovery_set_filter(l),\n            )\n            btn.pack(side=\"left\", padx=4)\n            self._data_recovery_filter_buttons[label] = btn\n\n        controls = tk.Frame(quick_card, bg=C[\"card\"])\n        controls.pack(fill=\"x\", padx=10, pady=(6, 8))\n        self._data_recovery_quick_pause_btn = tk.Button(\n            controls,\n            text=\"\u23f8 Pause Scan\",\n            font=FONTS[\"small\"],\n            bg=C[\"warning\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_pause_resume_scan,\n        )\n        self._data_recovery_quick_pause_btn.pack(side=\"left\", padx=(0, 8))\n        self._data_recovery_quick_cancel_btn = tk.Button(\n            controls,\n            text=\"\u2716 Cancel\",\n            font=FONTS[\"small\"],\n            bg=C[\"btn_danger\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_cancel_scan,\n        )\n        self._data_recovery_quick_cancel_btn.pack(side=\"left\", padx=4)\n        self._data_recovery_quick_start_btn = tk.Button(\n            controls,\n            text=\"\u25b6 Start Quick Recovery\",\n            font=FONTS[\"subhead\"],\n            bg=C[\"accent2\"],\n            fg=\"#0A0F1A\",\n            bd=0,\n            padx=14,\n            pady=8,\n            cursor=\"hand2\",\n            command=self._data_recovery_start_quick_recovery,\n        )\n        self._data_recovery_quick_start_btn.pack(side=\"left\", padx=4)\n        tk.Button(\n            controls,\n            text=\"\ud83d\udee0 Auto Repair\",\n            font=FONTS[\"small\"],\n            bg=C[\"btn_chip\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_run_auto_repair,\n        ).pack(side=\"left\", padx=4)\n        tk.Button(\n            controls,\n            text=\"\ud83d\udccb Export HTML Report\",\n            font=FONTS[\"small\"],\n            bg=C[\"btn_info\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_export_report,\n        ).pack(side=\"left\", padx=4)\n\n        self._data_recovery_quick_preview = ttk.Treeview(\n            quick_body,\n            columns=(\"Type\", \"Path\", \"Size\", \"Chance\"),\n            show=\"headings\",\n            height=10,\n            style=\"Custom.Treeview\",\n        )\n        for col, title, width in [(\"Type\", \"Type\", 90), (\"Path\", \"Recovered Path\", 320), (\"Size\", \"Size\", 90), (\"Chance\", \"Chance\", 90)]:\n            self._data_recovery_quick_preview.heading(col, text=title)\n            self._data_recovery_quick_preview.column(col, width=width)\n        self._data_recovery_quick_preview.pack(fill=\"both\", expand=True, padx=14, pady=(0, 10))\n\n        quick_progress = tk.LabelFrame(quick_body, text=\"\ud83d\udcc8 Quick Recovery Progress / \u0928\u093f\u0937\u094d\u0915\u094d\u0930\u093f\u092f \u0938\u094d\u0915\u0948\u0928 \u092a\u094d\u0930\u0917\u0924\u093f\", font=FONTS[\"small\"], fg=C[\"accent2\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        quick_progress.pack(fill=\"x\", padx=14, pady=(0, 10))\n        self._data_recovery_quick_status = tk.Label(quick_progress, text=\"Ready \u2014 choose a source and start the scan.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], anchor=\"w\")\n        self._data_recovery_quick_status.pack(fill=\"x\", padx=10, pady=(8, 2))\n        self._data_recovery_quick_speed = tk.Label(quick_progress, text=\"Speed: 0 MB/s | ETA: --\", font=FONTS[\"small\"], fg=C[\"accent\"], bg=C[\"card\"], anchor=\"w\")\n        self._data_recovery_quick_speed.pack(fill=\"x\", padx=10, pady=(0, 4))\n        self._data_recovery_quick_progress = ttk.Progressbar(quick_progress, maximum=100.0, mode=\"determinate\")\n        self._data_recovery_quick_progress.pack(fill=\"x\", padx=10, pady=(0, 10))\n\n        deep_tab = tk.Frame(notebook, bg=C[\"bg\"])\n        notebook.add(deep_tab, text=\"Deep Recovery\")\n        deep_body = self._scrollable_section_body(deep_tab)\n        deep_card = tk.LabelFrame(\n            deep_body,\n            text=\"\ud83e\uddec Deep Recovery (PhotoRec Style) / \u0917\u0939\u0930\u0940 \u0930\u093f\u0915\u0935\u0930\u0940\",\n            font=FONTS[\"subhead\"],\n            fg=C[\"warning\"],\n            bg=C[\"card\"],\n            bd=1,\n            relief=\"flat\",\n        )\n        deep_card.pack(fill=\"x\", padx=14, pady=10)\n\n        self._data_recovery_deep_source_var = tk.StringVar(value=\"\")\n        self._data_recovery_deep_output_var = tk.StringVar(value=os.path.join(os.path.expanduser(\"~\"), \"Desktop\", \"Godawari_DataRecovery_Deep\"))\n        self._data_recovery_deep_chunk_var = tk.StringVar(value=\"4\")\n        self._data_recovery_deep_depth_var = tk.StringVar(value=\"High\")\n        self._data_recovery_deep_source_combo = ttk.Combobox(deep_card, textvariable=self._data_recovery_deep_source_var, values=[], width=42, state=\"readonly\")\n        self._data_recovery_deep_source_combo.pack_forget()\n\n        deep_rows = tk.Frame(deep_card, bg=C[\"card\"])\n        deep_rows.pack(fill=\"x\", padx=10, pady=(8, 2))\n        tk.Label(deep_rows, text=\"Source:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._data_recovery_deep_source_combo = ttk.Combobox(deep_rows, textvariable=self._data_recovery_deep_source_var, values=[], width=42, state=\"readonly\")\n        self._data_recovery_deep_source_combo.pack(side=\"left\", padx=(8, 12))\n        tk.Label(deep_rows, text=\"Output Folder:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\")\n        tk.Entry(deep_rows, textvariable=self._data_recovery_deep_output_var, width=48, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).pack(side=\"left\", padx=(8, 8))\n        tk.Button(\n            deep_rows,\n            text=\"Browse\",\n            font=FONTS[\"small\"],\n            bg=C[\"panel\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=10,\n            pady=5,\n            cursor=\"hand2\",\n            command=lambda: self._data_recovery_choose_output(self._data_recovery_deep_output_var),\n        ).pack(side=\"left\")\n\n        filters = tk.Frame(deep_card, bg=C[\"card\"])\n        filters.pack(fill=\"x\", padx=10, pady=(6, 8))\n        tk.Label(filters, text=\"Carving targets:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._data_recovery_deep_flags = {\n            \"Photos\": tk.BooleanVar(value=True),\n            \"Videos\": tk.BooleanVar(value=True),\n            \"Documents\": tk.BooleanVar(value=True),\n            \"Archives\": tk.BooleanVar(value=True),\n        }\n        for label in (\"Photos\", \"Videos\", \"Documents\", \"Archives\"):\n            ttk.Checkbutton(filters, text=label, variable=self._data_recovery_deep_flags[label]).pack(side=\"left\", padx=6)\n\n        deep_controls = tk.Frame(deep_card, bg=C[\"card\"])\n        deep_controls.pack(fill=\"x\", padx=10, pady=(6, 8))\n        self._data_recovery_deep_start_btn = tk.Button(\n            deep_controls,\n            text=\"\ud83e\uddec Start Deep Carve\",\n            font=FONTS[\"subhead\"],\n            bg=C[\"warning\"],\n            fg=\"#0A0F1A\",\n            bd=0,\n            padx=14,\n            pady=8,\n            cursor=\"hand2\",\n            command=self._data_recovery_start_deep_recovery,\n        )\n        self._data_recovery_deep_start_btn.pack(side=\"left\", padx=(0, 8))\n        self._data_recovery_deep_pause_btn = tk.Button(\n            deep_controls,\n            text=\"\u23f8 Pause Scan\",\n            font=FONTS[\"small\"],\n            bg=C[\"btn_info\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_pause_resume_scan,\n        )\n        self._data_recovery_deep_pause_btn.pack(side=\"left\", padx=4)\n        self._data_recovery_deep_cancel_btn = tk.Button(\n            deep_controls,\n            text=\"\u2716 Cancel\",\n            font=FONTS[\"small\"],\n            bg=C[\"btn_danger\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_cancel_scan,\n        )\n        self._data_recovery_deep_cancel_btn.pack(side=\"left\", padx=4)\n        tk.Button(\n            deep_controls,\n            text=\"\ud83e\udde9 Preview Candidate\",\n            font=FONTS[\"small\"],\n            bg=C[\"panel\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_preview_selected_candidate,\n        ).pack(side=\"left\", padx=4)\n\n        self._data_recovery_deep_preview = ttk.Treeview(\n            deep_body,\n            columns=(\"Signature\", \"Offset\", \"Size\", \"Chance\"),\n            show=\"headings\",\n            height=8,\n            style=\"Custom.Treeview\",\n        )\n        for col, title, width in [(\"Signature\", \"Signature\", 120), (\"Offset\", \"Offset\", 140), (\"Size\", \"Size\", 100), (\"Chance\", \"Chance\", 100)]:\n            self._data_recovery_deep_preview.heading(col, text=title)\n            self._data_recovery_deep_preview.column(col, width=width)\n        self._data_recovery_deep_preview.pack(fill=\"both\", expand=True, padx=14, pady=(0, 10))\n\n        deep_progress = tk.LabelFrame(deep_body, text=\"\ud83d\udcca Deep Scan Progress / \u0917\u0939\u0930\u0947 \u0938\u094d\u0915\u0948\u0928 \u0915\u0940 \u092a\u094d\u0930\u0917\u0924\u093f\", font=FONTS[\"small\"], fg=C[\"warning\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        deep_progress.pack(fill=\"x\", padx=14, pady=(0, 10))\n        self._data_recovery_deep_status = tk.Label(deep_progress, text=\"Ready \u2014 choose a source and start the scan.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], anchor=\"w\")\n        self._data_recovery_deep_status.pack(fill=\"x\", padx=10, pady=(8, 2))\n        self._data_recovery_deep_speed = tk.Label(deep_progress, text=\"Speed: 0 MB/s | ETA: --\", font=FONTS[\"small\"], fg=C[\"accent\"], bg=C[\"card\"], anchor=\"w\")\n        self._data_recovery_deep_speed.pack(fill=\"x\", padx=10, pady=(0, 4))\n        self._data_recovery_deep_progress = ttk.Progressbar(deep_progress, maximum=100.0, mode=\"determinate\")\n        self._data_recovery_deep_progress.pack(fill=\"x\", padx=10, pady=(0, 10))\n\n        part_tab = tk.Frame(notebook, bg=C[\"bg\"])\n        notebook.add(part_tab, text=\"Partition Recovery\")\n        part_body = self._scrollable_section_body(part_tab)\n        part_card = tk.LabelFrame(\n            part_body,\n            text=\"\ud83d\uddc2\ufe0f Formatted / Lost Partition Recovery / \u092b\u093c\u0949\u0930\u094d\u092e\u0947\u091f\u0947\u0921 \u092f\u093e \u0916\u094b\u0908 \u0939\u0941\u0908 partition \u0930\u093f\u0915\u0935\u0930\u0940\",\n            font=FONTS[\"subhead\"],\n            fg=C[\"accent\"],\n            bg=C[\"card\"],\n            bd=1,\n            relief=\"flat\",\n        )\n        part_card.pack(fill=\"x\", padx=14, pady=10)\n        self._data_recovery_partition_tree = ttk.Treeview(\n            part_body,\n            columns=(\"Partition\", \"Start\", \"End\", \"Type\", \"Status\"),\n            show=\"headings\",\n            height=12,\n            style=\"Custom.Treeview\",\n        )\n        for col, title in [(\"Partition\", \"Partition\"), (\"Start\", \"Start Sector\"), (\"End\", \"End Sector\"), (\"Type\", \"Type\"), (\"Status\", \"Status\")]:\n            self._data_recovery_partition_tree.heading(col, text=title)\n        self._data_recovery_partition_tree.pack(fill=\"both\", expand=True, padx=14, pady=(0, 10))\n        part_controls = tk.Frame(part_card, bg=C[\"card\"])\n        part_controls.pack(fill=\"x\", padx=10, pady=(6, 8))\n        tk.Button(\n            part_controls,\n            text=\"\ud83d\udd0e Refresh Partitions\",\n            font=FONTS[\"small\"],\n            bg=C[\"btn_info\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_refresh_partition_list,\n        ).pack(side=\"left\", padx=(0, 8))\n        tk.Button(\n            part_controls,\n            text=\"\ud83d\udee1 Recover Lost Partition\",\n            font=FONTS[\"small\"],\n            bg=C[\"accent2\"],\n            fg=\"#0A0F1A\",\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_recover_partition_table,\n        ).pack(side=\"left\", padx=4)\n        tk.Button(\n            part_controls,\n            text=\"\ud83d\udccd Verify MBR/GPT\",\n            font=FONTS[\"small\"],\n            bg=C[\"panel\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_verify_partition_table,\n        ).pack(side=\"left\", padx=4)\n\n        adv_tab = tk.Frame(notebook, bg=C[\"bg\"])\n        notebook.add(adv_tab, text=\"Advanced Tools &amp; Imaging\")\n        adv_body = self._scrollable_section_body(adv_tab)\n        adv_card = tk.LabelFrame(\n            adv_body,\n            text=\"\ud83d\udcbe DiskGenius Style Sector Utility / \u0938\u0947\u0915\u094d\u091f\u0930-\u0938\u094d\u0924\u0930\u0940\u092f \u0907\u092e\u0947\u091c\u093f\u0902\u0917 \u091f\u0942\u0932\",\n            font=FONTS[\"subhead\"],\n            fg=C[\"hw_accent\"],\n            bg=C[\"card\"],\n            bd=1,\n            relief=\"flat\",\n        )\n        adv_card.pack(fill=\"x\", padx=14, pady=10)\n\n        self._data_recovery_imaging_disk_var = tk.StringVar(value=\"\")\n        self._data_recovery_start_sector_var = tk.StringVar(value=\"0\")\n        self._data_recovery_end_sector_var = tk.StringVar(value=\"1023\")\n        self._data_recovery_img_output_var = tk.StringVar(value=os.path.join(os.path.expanduser(\"~\"), \"Desktop\", \"Godawari_DataRecovery_Image.img\"))\n        self._data_recovery_imaging_disk_combo = ttk.Combobox(adv_card, textvariable=self._data_recovery_imaging_disk_var, values=[], width=42, state=\"readonly\")\n        self._data_recovery_imaging_disk_combo.pack_forget()\n\n        imaging_rows = tk.Frame(adv_card, bg=C[\"card\"])\n        imaging_rows.pack(fill=\"x\", padx=10, pady=(8, 2))\n        tk.Label(imaging_rows, text=\"Disk:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._data_recovery_imaging_disk_combo = ttk.Combobox(imaging_rows, textvariable=self._data_recovery_imaging_disk_var, values=[], width=42, state=\"readonly\")\n        self._data_recovery_imaging_disk_combo.pack(side=\"left\", padx=(8, 12))\n        tk.Label(imaging_rows, text=\"Start Sector:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\")\n        tk.Entry(imaging_rows, textvariable=self._data_recovery_start_sector_var, width=12, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).pack(side=\"left\", padx=(8, 12))\n        tk.Label(imaging_rows, text=\"End Sector:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\")\n        tk.Entry(imaging_rows, textvariable=self._data_recovery_end_sector_var, width=12, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).pack(side=\"left\", padx=(8, 12))\n        tk.Label(imaging_rows, text=\"Output:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\")\n        tk.Entry(imaging_rows, textvariable=self._data_recovery_img_output_var, width=46, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).pack(side=\"left\", padx=(8, 8))\n        tk.Button(\n            imaging_rows,\n            text=\"Browse\",\n            font=FONTS[\"small\"],\n            bg=C[\"panel\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=10,\n            pady=5,\n            cursor=\"hand2\",\n            command=lambda: self._data_recovery_choose_output(self._data_recovery_img_output_var),\n        ).pack(side=\"left\")\n\n        adv_controls = tk.Frame(adv_card, bg=C[\"card\"])\n        adv_controls.pack(fill=\"x\", padx=10, pady=(6, 8))\n        self._data_recovery_hex_load_btn = tk.Button(\n            adv_controls,\n            text=\"\ud83d\udd0e Load Sector / Hex\",\n            font=FONTS[\"small\"],\n            bg=C[\"btn_info\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_load_sector_hex,\n        )\n        self._data_recovery_hex_load_btn.pack(side=\"left\", padx=(0, 8))\n        tk.Button(\n            adv_controls,\n            text=\"\ud83d\udcbe Create Range .img\",\n            font=FONTS[\"small\"],\n            bg=C[\"accent2\"],\n            fg=\"#0A0F1A\",\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_create_range_img,\n        ).pack(side=\"left\", padx=4)\n        tk.Button(\n            adv_controls,\n            text=\"\ud83d\udda5\ufe0f Full Disk .img\",\n            font=FONTS[\"small\"],\n            bg=C[\"warning\"],\n            fg=\"#0A0F1A\",\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_create_full_disk_img,\n        ).pack(side=\"left\", padx=4)\n        tk.Button(\n            adv_controls,\n            text=\"\ud83d\udcc2 Open Output Folder\",\n            font=FONTS[\"small\"],\n            bg=C[\"panel\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_open_last_output,\n        ).pack(side=\"left\", padx=4)\n        tk.Button(\n            adv_controls,\n            text=\"\ud83e\uddea Use in Existing Recovery\",\n            font=FONTS[\"small\"],\n            bg=C[\"hw_accent\"],\n            fg=C[\"text\"],\n            bd=0,\n            padx=12,\n            pady=7,\n            cursor=\"hand2\",\n            command=self._data_recovery_route_img_to_existing_recovery,\n        ).pack(side=\"left\", padx=4)\n\n        self._data_recovery_hex_view = scrolledtext.ScrolledText(\n            adv_body,\n            font=FONTS[\"mono\"],\n            bg=C[\"bg\"],\n            fg=C[\"text\"],\n            insertbackground=C[\"text\"],\n            wrap=\"word\",\n            height=18,\n            bd=0,\n            relief=\"flat\",\n        )\n        self._data_recovery_hex_view.pack(fill=\"both\", expand=True, padx=14, pady=(0, 10))\n\n        self._data_recovery_image_chance = tk.Label(\n            adv_card,\n            text=\"Recovery Chance: Low \u2014 image not loaded yet\",\n            font=FONTS[\"small\"],\n            fg=C[\"warning\"],\n            bg=C[\"card\"],\n            anchor=\"w\",\n        )\n        self._data_recovery_image_chance.pack(fill=\"x\", padx=10, pady=(6, 0))\n        self._data_recovery_auto_repair_label = tk.Label(\n            adv_card,\n            text=\"Auto Repair: Ready for JPG / PNG / PDF / DOCX headers\",\n            font=FONTS[\"small\"],\n            fg=C[\"text_dim\"],\n            bg=C[\"card\"],\n            anchor=\"w\",\n        )\n        self._data_recovery_auto_repair_label.pack(fill=\"x\", padx=10, pady=(2, 8))\n\n        self._data_recovery_refresh_disk_sources()\n        self._data_recovery_refresh_partition_list()\n        self._data_recovery_set_filter(\"All\")\n        self._data_recovery_set_recovery_chance(\"Low\")\n        self._data_recovery_update_summary(\"Source\", \"Ready\")\n        self._data_recovery_update_summary(\"Recovered\", \"0 files\")\n        self._data_recovery_update_summary(\"Image\", \"No image yet\")\n\n        return frame\n\n    def _data_recovery_refresh_disk_sources(self):\n        try:\n            self._populate_recovery_disks()\n        except Exception:\n            pass\n\n        disk_values = list(getattr(self, \"_recovery_disk_map\", {}).keys())\n        if not disk_values:\n            disk_values = self._get_recovery_disk_values()\n\n        uniq = []\n        for src in disk_values:\n            if src not in uniq:\n                uniq.append(src)\n\n        for combo in (\n            getattr(self, \"_data_recovery_quick_disk_combo\", None),\n            getattr(self, \"_data_recovery_deep_source_combo\", None),\n            getattr(self, \"_data_recovery_imaging_disk_combo\", None),\n        ):\n            if combo is not None:\n                combo.config(values=uniq)\n\n        current = uniq[0] if uniq else \"\"\n        if current:\n            self._data_recovery_quick_disk_var.set(current)\n            self._data_recovery_deep_source_var.set(current)\n            self._data_recovery_imaging_disk_var.set(current)\n\n    def _data_recovery_set_filter(self, label):\n        self._data_recovery_filter_var.set(label)\n        self._data_recovery_quick_status.config(text=f\"Filter updated to {label}.\")\n        for name, btn in getattr(self, \"_data_recovery_filter_buttons\", {}).items():\n            bg = C[\"btn_chip\"] if name == label else C[\"panel\"]\n            try:\n                btn.config(bg=bg)\n            except Exception:\n                pass\n        if label == \"All\":\n            self._data_recovery_set_recovery_chance(\"Medium\")\n        elif label in (\"Photos\", \"Videos\"):\n            self._data_recovery_set_recovery_chance(\"High\")\n        else:\n            self._data_recovery_set_recovery_chance(\"Medium\")\n\n    def _data_recovery_update_summary(self, key, value):\n        if key in self._data_recovery_summary_labels:\n            self._data_recovery_summary_labels[key].config(text=value)\n\n    def _data_recovery_set_recovery_chance(self, level):\n        color = C[\"success\"] if level == \"High\" else C[\"warning\"] if level == \"Medium\" else C[\"error\"]\n        self._data_recovery_summary_labels[\"Chance\"].config(text=level, fg=color)\n        if hasattr(self, \"_data_recovery_image_chance\"):\n            self._data_recovery_image_chance.config(text=f\"Recovery Chance: {level}\", fg=color)\n\n    def _data_recovery_choose_output(self, var):\n        path = filedialog.asksaveasfilename(defaultextension=\".img\", filetypes=[(\"Image File\", \"*.img\"), (\"All Files\", \"*.*\")], title=\"Choose output file\")\n        if path:\n            var.set(path)\n\n    def _data_recovery_get_source_path(self, source_value):\n        source_value = (source_value or \"\").strip()\n        if not source_value:\n            return \"\"\n        if hasattr(self, \"_resolve_disk_path\"):\n            return self._resolve_disk_path(source_value)\n        return source_value.split(\" (\")[0]\n\n    def _data_recovery_refresh_partition_list(self):\n        if not hasattr(self, \"_data_recovery_partition_tree\"):\n            return\n        for iid in self._data_recovery_partition_tree.get_children():\n            self._data_recovery_partition_tree.delete(iid)\n        source = self._data_recovery_get_source_path(self._data_recovery_imaging_disk_var.get() or self._data_recovery_quick_disk_var.get())\n        if not source:\n            return\n        partitions = self._data_recovery_parse_partitions(source)\n        if not partitions:\n            self._data_recovery_partition_tree.insert(\"\", \"end\", values=(\"No partition table detected\", \"\", \"\", \"\", \"Unknown\"))\n            if hasattr(self, \"partition_tree\"):\n                self.partition_tree.delete(*self.partition_tree.get_children())\n            return\n        for part in partitions:\n            self._data_recovery_partition_tree.insert(\"\", \"end\", values=(part[\"name\"], part[\"start\"], part[\"end\"], part[\"type\"], part[\"status\"]))\n        if hasattr(self, \"partition_tree\"):\n            for iid in self.partition_tree.get_children():\n                self.partition_tree.delete(iid)\n            for part in partitions:\n                self.partition_tree.insert(\"\", \"end\", values=(part[\"name\"], part[\"start\"], part[\"end\"], part[\"type\"], part[\"status\"]))\n\n    def _data_recovery_parse_partitions(self, source_path):\n        source_path = self._data_recovery_get_source_path(source_path)\n        try:\n            first_sector = self._forensic_read_at(source_path, 0, 512)\n        except Exception:\n            return []\n        if len(first_sector) &lt; 512 or first_sector[510:512] != b\"\\x55\\xAA\":\n            return []\n        partitions = []\n        for idx in range(4):\n            entry = first_sector[446 + idx * 16:446 + (idx + 1) * 16]\n            part_type = entry[4]\n            start = int.from_bytes(entry[8:12], \"little\")\n            size = int.from_bytes(entry[12:16], \"little\")\n            if part_type and size:\n                partitions.append({\n                    \"name\": f\"Partition {idx + 1}\",\n                    \"start\": str(start),\n                    \"end\": str(start + size - 1),\n                    \"type\": f\"0x{part_type:02X}\",\n                    \"status\": \"Candidate\",\n                })\n        return partitions\n\n    def _data_recovery_read_sector_bytes(self, source_path, start_sector, end_sector):\n        try:\n            start_sector = int(start_sector)\n            end_sector = int(end_sector)\n            if end_sector &lt; start_sector:\n                start_sector, end_sector = end_sector, start_sector\n            source_path = self._data_recovery_get_source_path(source_path)\n            raw = self._forensic_read_at(source_path, start_sector * 512, (end_sector - start_sector + 1) * 512)\n            return raw\n        except Exception as exc:\n            messagebox.showerror(\"Sector Read Error\", str(exc))\n            return b\"\"\n\n    def _data_recovery_format_hex_dump(self, raw_bytes):\n        if not raw_bytes:\n            return \"No bytes available.\"\n        lines = []\n        for offset in range(0, len(raw_bytes), 16):\n            chunk = raw_bytes[offset:offset + 16]\n            hex_text = \" \".join(f\"{b:02X}\" for b in chunk)\n            ascii_text = \"\".join(chr(b) if 32 &lt;= b &lt; 127 else \".\" for b in chunk)\n            lines.append(f\"{offset:08X}  {hex_text:&lt;47}  {ascii_text}\")\n        return \"\\n\".join(lines)\n\n    def _data_recovery_load_sector_hex(self):\n        source = self._data_recovery_imaging_disk_var.get()\n        if not source:\n            messagebox.showwarning(\"No Disk Selected\", \"Select a disk or raw volume first.\")\n            return\n        try:\n            start = int(self._data_recovery_start_sector_var.get())\n            end = int(self._data_recovery_end_sector_var.get())\n        except Exception:\n            messagebox.showwarning(\"Invalid Sector Range\", \"Enter numeric start and end sectors.\")\n            return\n        sector_count = abs(end - start) + 1\n        if sector_count &gt; 4096:\n            messagebox.showwarning(\n                \"Range Too Large\",\n                \"Hex preview ek baar me max 4096 sectors (2 MB) read karega.\\n\"\n                \"Bade range ke liye 'Create Range IMG' use karein.\"\n            )\n            return\n\n        def load_hex():\n            try:\n                if hasattr(self, \"_data_recovery_hex_load_btn\"):\n                    self.after(0, lambda: self._data_recovery_hex_load_btn.config(state=\"disabled\"))\n                raw = self._data_recovery_read_sector_bytes(source, start, end)\n                formatted = self._data_recovery_format_hex_dump(raw)\n                self.after(0, lambda: self._data_recovery_hex_view.delete(\"1.0\", tk.END))\n                self.after(0, lambda: self._data_recovery_hex_view.insert(tk.END, formatted))\n                self.after(0, lambda: self._data_recovery_update_summary(\"Image\", f\"{start} -&gt; {end}\"))\n                self.after(0, lambda: self._data_recovery_set_recovery_chance(\"Medium\"))\n            finally:\n                if hasattr(self, \"_data_recovery_hex_load_btn\"):\n                    self.after(0, lambda: self._data_recovery_hex_load_btn.config(state=\"normal\"))\n\n        self._launch_job(\"data_recovery_load_hex\", load_hex)\n\n    def _data_recovery_create_sector_range_img(self, source_path, start_sector, end_sector, output_path, progress_callback=None, confirm=True):\n        if not source_path or not output_path:\n            return {\"ok\": False, \"message\": \"Source or output path missing.\"}\n        try:\n            start_sector = int(start_sector)\n            end_sector = int(end_sector)\n            if end_sector &lt; start_sector:\n                start_sector, end_sector = end_sector, start_sector\n        except Exception:\n            return {\"ok\": False, \"message\": \"Invalid sector values.\"}\n        if confirm and not messagebox.askyesno(\"Raw Imaging Confirmation\", \"This will create a raw sector image from the selected range. Continue only if you have authorization.\"):\n            return {\"ok\": False, \"message\": \"User cancelled imaging.\"}\n\n        source_path = self._data_recovery_get_source_path(source_path)\n        if _is_raw_device_path(source_path) and not self._ensure_admin_for_raw_recovery(source_path):\n            return {\"ok\": False, \"message\": \"Administrator rights required for raw imaging.\"}\n\n        output_path = os.path.abspath(output_path)\n        os.makedirs(os.path.dirname(output_path) or \".\", exist_ok=True)\n        try:\n            start_byte = start_sector * 512\n            end_byte = (end_sector + 1) * 512\n            remaining = max(0, end_byte - start_byte)\n            total_bytes = remaining\n            copied = 0\n            current = start_byte\n            file_source = source_path and os.path.exists(source_path) and not _is_raw_device_path(source_path)\n            src = open(source_path, \"rb\") if file_source else None\n            try:\n                if src:\n                    src.seek(start_byte)\n                with open(output_path, \"wb\") as dst:\n                    while remaining &gt; 0:\n                        if self._data_recovery_state.get(\"cancelled\", False):\n                            return {\"ok\": False, \"message\": \"Imaging cancelled by user.\"}\n                        while self._data_recovery_state.get(\"paused\", False):\n                            time.sleep(0.12)\n                            if self._data_recovery_state.get(\"cancelled\", False):\n                                return {\"ok\": False, \"message\": \"Imaging cancelled by user.\"}\n                        chunk_len = min(1024 * 1024, remaining)\n                        chunk = src.read(chunk_len) if src else self._forensic_read_at(source_path, current, chunk_len)\n                        if not chunk:\n                            break\n                        dst.write(chunk)\n                        current += len(chunk)\n                        remaining -= len(chunk)\n                        copied += len(chunk)\n                        if progress_callback:\n                            progress_callback(copied, total_bytes, output_path)\n            finally:\n                if src:\n                    src.close()\n            if remaining &gt; 0:\n                return {\"ok\": False, \"message\": \"Imaging stopped early: source shorter than requested range.\"}\n            self._data_recovery_state[\"last_img\"] = output_path\n            return {\"ok\": True, \"message\": f\"Image created: {output_path}\", \"path\": output_path}\n        except Exception as exc:\n            return {\"ok\": False, \"message\": str(exc)}\n\n    def _data_recovery_create_range_img(self):\n        source = self._data_recovery_imaging_disk_var.get()\n        output_path = self._data_recovery_img_output_var.get()\n        start_sector = self._data_recovery_start_sector_var.get()\n        end_sector = self._data_recovery_end_sector_var.get()\n        if not source:\n            messagebox.showwarning(\"No Disk Selected\", \"Select a disk or raw volume first.\")\n            return\n        if not output_path:\n            messagebox.showwarning(\"No Output Path\", \"Choose an output image path.\")\n            return\n        if self._data_recovery_state.get(\"running\", False):\n            messagebox.showwarning(\"Data Recovery Busy\", \"Ek recovery/imaging job already chal raha hai. Pehle usko cancel/complete hone dein.\")\n            return\n        if not messagebox.askyesno(\"Raw Imaging Confirmation\", \"This will create a raw sector image from the selected range. Continue only if you have authorization?\"):\n            return\n        self._data_recovery_state[\"running\"] = True\n        self._data_recovery_state[\"paused\"] = False\n        self._data_recovery_state[\"cancelled\"] = False\n        self._data_recovery_quick_progress[\"value\"] = 0\n        self._data_recovery_quick_status.config(text=\"Range imaging queued...\")\n        self._launch_job(\"data_recovery_range_img\", self._data_recovery_img_worker, source, start_sector, end_sector, output_path, \"Range Image\")\n\n    def _data_recovery_img_worker(self, source, start_sector, end_sector, output_path, label):\n        started = time.time()\n\n        def progress(copied, total, path):\n            pct = (copied / total * 100.0) if total else 0.0\n            elapsed = max(0.1, time.time() - started)\n            speed = copied / elapsed\n            remaining = max(0, total - copied)\n            eta = int(remaining / speed) if speed &gt; 0 else 0\n            msg = (\n                f\"{label}: {pct:.1f}% | {self._fmt_size(copied)} / {self._fmt_size(total)} | \"\n                f\"Elapsed {self._format_seconds(elapsed)} | Left {self._format_seconds(eta)}\"\n            )\n            self.after(0, lambda m=msg, p=pct: (\n                self._data_recovery_quick_progress.config(value=p),\n                self._data_recovery_deep_progress.config(value=p),\n                self._data_recovery_quick_status.config(text=m),\n                self._data_recovery_deep_status.config(text=m),\n                self._data_recovery_quick_speed.config(text=f\"Speed: {self._fmt_size(speed)}/s | ETA: {self._format_seconds(eta)}\"),\n                self._data_recovery_deep_speed.config(text=f\"Speed: {self._fmt_size(speed)}/s | ETA: {self._format_seconds(eta)}\"),\n            ))\n\n        result = self._data_recovery_create_sector_range_img(\n            source, start_sector, end_sector, output_path,\n            progress_callback=progress,\n            confirm=False,\n        )\n        if result[\"ok\"]:\n            self.after(0, lambda: (\n                self._data_recovery_update_summary(\"Image\", os.path.basename(result[\"path\"])),\n                self._data_recovery_quick_progress.config(value=100),\n                self._data_recovery_deep_progress.config(value=100),\n                self._data_recovery_quick_status.config(text=result[\"message\"]),\n                self._data_recovery_deep_status.config(text=result[\"message\"]),\n                messagebox.showinfo(f\"{label} Created\", result[\"message\"]),\n            ))\n        else:\n            self.after(0, lambda: (\n                self._data_recovery_quick_status.config(text=result[\"message\"]),\n                self._data_recovery_deep_status.config(text=result[\"message\"]),\n                messagebox.showerror(f\"{label} Failed\", result[\"message\"]),\n            ))\n        self._data_recovery_state[\"running\"] = False\n\n    def _data_recovery_create_full_disk_img(self):\n        source = self._data_recovery_imaging_disk_var.get() or self._data_recovery_quick_disk_var.get()\n        output_path = self._data_recovery_img_output_var.get()\n        if not source:\n            messagebox.showwarning(\"No Disk Selected\", \"Select a disk or raw volume first.\")\n            return\n        if not output_path:\n            messagebox.showwarning(\"No Output Path\", \"Choose an output image path.\")\n            return\n        if self._data_recovery_state.get(\"running\", False):\n            messagebox.showwarning(\"Data Recovery Busy\", \"Ek recovery/imaging job already chal raha hai. Pehle usko cancel/complete hone dein.\")\n            return\n        try:\n            source_path = self._data_recovery_get_source_path(source)\n            size = _disk_source_size(source_path)\n        except Exception:\n            size = None\n        if not size:\n            messagebox.showwarning(\"Size Error\", \"Unable to determine disk size.\")\n            return\n        if not messagebox.askyesno(\"Full Disk Imaging\", f\"Create a full raw image of {source}? This is a raw disk operation and should only be done with authorization.\"):\n            return\n        self._data_recovery_state[\"running\"] = True\n        self._data_recovery_state[\"paused\"] = False\n        self._data_recovery_state[\"cancelled\"] = False\n        self._data_recovery_quick_progress[\"value\"] = 0\n        self._data_recovery_quick_status.config(text=\"Full disk imaging queued...\")\n        self._launch_job(\"data_recovery_full_img\", self._data_recovery_img_worker, source, 0, max(0, size // 512 - 1), output_path, \"Full Disk Image\")\n\n    def _data_recovery_open_last_output(self):\n        path = self._data_recovery_state.get(\"last_img\", \"\")\n        if not path or not os.path.exists(path):\n            messagebox.showwarning(\"No Image\", \"Create or load an image first.\")\n            return\n        try:\n            subprocess.Popen([\"explorer\", os.path.dirname(path)])\n        except Exception as exc:\n            messagebox.showerror(\"Open Failed\", str(exc))\n\n    def _data_recovery_route_img_to_existing_recovery(self):\n        if not self._data_recovery_state.get(\"last_img\"):\n            messagebox.showwarning(\"No Image\", \"Create or load a .img first.\")\n            return\n        img_path = self._data_recovery_state.get(\"last_img\", \"\")\n        routed = []\n        for attr in (\"raw_disk_var\", \"deep_recovery_source_var\", \"photorec_source_var\", \"mft_source_var\"):\n            var = getattr(self, attr, None)\n            if var is not None:\n                try:\n                    var.set(img_path)\n                    routed.append(attr)\n                except Exception:\n                    pass\n        messagebox.showinfo(\n            \"Use in Existing Recovery\",\n            f\"Image route ho gayi:\\n{img_path}\\n\\nUpdated fields: {', '.join(routed) if routed else 'HDD/File Recovery section open hote hi source set karein.'}\"\n        )\n        self._show_section(\"hdd_repair\")\n\n    def _data_recovery_signature_map(self, kind):\n        return {\n            \"Photos\": [b\"\\xff\\xd8\\xff\", b\"\\x89PNG\\r\\n\\x1a\\n\", b\"GIF87a\", b\"GIF89a\"],\n            \"Videos\": [b\"RIFF\", b\"\\x00\\x00\\x00\\x18ftyp\", b\"\\x1A\\x45\\xDF\\xA3\"],\n            \"Documents\": [b\"%PDF-\", b\"PK\\x03\\x04\", b\"Microsoft Word\", b\"\\xd0\\xcf\\x11\\xe0\\xa1\\xb1\\x1a\\xe1\"],\n            \"Archives\": [b\"PK\\x03\\x04\", b\"Rar!\", b\"7z\\xBC\\xAF\\x27\\x1C\", b\"\\x42\\x5A\\x68\"],\n        }.get(kind, [])\n\n    def _data_recovery_find_signature_offsets(self, data, kind):\n        offsets = []\n        for signature in self._data_recovery_signature_map(kind):\n            start = 0\n            while True:\n                idx = data.find(signature, start)\n                if idx == -1:\n                    break\n                offsets.append((idx, signature))\n                start = idx + 1\n        return offsets\n\n    def _data_recovery_carve_candidate(self, source_path, offset, signature, kind):\n        try:\n            with open(self._data_recovery_get_source_path(source_path), \"rb\") as handle:\n                handle.seek(max(0, offset))\n                payload = handle.read(512 * 1024)\n        except Exception:\n            return None\n        if not payload:\n            return None\n        ext = \".bin\"\n        if kind == \"Photos\":\n            ext = \".jpg\" if signature == b\"\\xff\\xd8\\xff\" else \".png\" if signature == b\"\\x89PNG\\r\\n\\x1a\\n\" else \".gif\"\n        elif kind == \"Videos\":\n            ext = \".mp4\" if signature == b\"\\x00\\x00\\x00\\x18ftyp\" else \".avi\" if signature == b\"RIFF\" else \".mkv\"\n        elif kind == \"Documents\":\n            if signature == b\"%PDF-\":\n                ext = \".pdf\"\n            elif signature == b\"PK\\x03\\x04\":\n                ext = \".docx\"\n            elif signature == b\"\\xd0\\xcf\\x11\\xe0\\xa1\\xb1\\x1a\\xe1\":\n                ext = \".doc\"\n        elif kind == \"Archives\":\n            if signature == b\"PK\\x03\\x04\":\n                ext = \".zip\"\n            elif signature == b\"Rar!\":\n                ext = \".rar\"\n            elif signature == b\"7z\\xBC\\xAF\\x27\\x1C\":\n                ext = \".7z\"\n            elif signature == b\"\\x42\\x5A\\x68\":\n                ext = \".bz2\"\n        return payload, ext\n\n    def _data_recovery_add_preview_row(self, mode, kind, offset, size, path):\n        tree = self._data_recovery_quick_preview if mode == \"quick\" else self._data_recovery_deep_preview\n        tree.insert(\"\", \"end\", values=(kind, f\"0x{offset:X}\", self._fmt_size(size), \"Medium\"))\n        self._data_recovery_last_preview_path = path\n        self._data_recovery_state.setdefault(\"preview\", []).append({\n            \"kind\": kind,\n            \"offset\": offset,\n            \"size\": size,\n            \"path\": path,\n        })\n        # Update recovered counters and UI summary\n        recovered_count = len(tree.get_children())\n        self._data_recovery_update_summary(\"Recovered\", f\"{recovered_count} files\")\n        if mode == \"deep\":\n            # maintain a numeric recovered counter for deep scans for progress reporting\n            try:\n                self._data_recovery_state[\"recovered\"] = int(self._data_recovery_state.get(\"recovered\", 0)) + 1\n            except Exception:\n                self._data_recovery_state[\"recovered\"] = recovered_count\n\n    def _data_recovery_preview_selected_candidate(self):\n        path = getattr(self, \"_data_recovery_last_preview_path\", \"\")\n        if not path or not os.path.exists(path):\n            messagebox.showwarning(\"Preview\", \"Select a recovered candidate first.\")\n            return\n        try:\n            subprocess.Popen([\"explorer\", path])\n        except Exception as exc:\n            messagebox.showerror(\"Preview Error\", str(exc))\n\n    def _data_recovery_run_auto_repair(self):\n        path = getattr(self, \"_data_recovery_last_preview_path\", \"\")\n        if not path or not os.path.exists(path):\n            messagebox.showwarning(\"No Candidate\", \"Run a recovery scan first to create a candidate.\")\n            return\n        repaired = self._data_recovery_auto_repair_file(path)\n        if repaired:\n            self._data_recovery_auto_repair_label.config(text=f\"Auto Repair: repaired -&gt; {os.path.basename(repaired)}\")\n            messagebox.showinfo(\"Auto Repair\", f\"Repair complete:\\n{repaired}\")\n        else:\n            messagebox.showwarning(\"Auto Repair\", \"No repair rule matched the recovered file.\")\n\n    def _data_recovery_auto_repair_file(self, path):\n        try:\n            data = Path(path).read_bytes()\n        except Exception:\n            return None\n        ext = Path(path).suffix.lower()\n        if ext == \".jpg\" and not data.endswith(b\"\\xff\\xd9\"):\n            data += b\"\\xff\\xd9\"\n        elif ext == \".png\" and b\"IEND\" not in data:\n            data += b\"\\x00\\x00\\x00\\x00IEND\\xaeB`\\x82\"\n        elif ext == \".pdf\" and b\"%%EOF\" not in data:\n            data += b\"\\n%%EOF\\n\"\n        elif ext == \".zip\" and not data.endswith(b\"PK\\x05\\x06\"):\n            data += b\"PK\\x05\\x06\\x00\\x00\\x00\\x00\"\n        else:\n            return None\n        repaired_path = str(Path(path).with_name(Path(path).stem + \"_repaired\" + ext))\n        Path(repaired_path).write_bytes(data)\n        return repaired_path\n\n    def _data_recovery_pause_resume_scan(self):\n        state = self._data_recovery_state\n        if not state.get(\"running\", False):\n            return\n        state[\"paused\"] = not state.get(\"paused\", False)\n        label = \"\u25b6 Resume Scan\" if state[\"paused\"] else \"\u23f8 Pause Scan\"\n        if hasattr(self, \"_data_recovery_quick_pause_btn\"):\n            self._data_recovery_quick_pause_btn.config(text=label)\n        if hasattr(self, \"_data_recovery_deep_pause_btn\"):\n            self._data_recovery_deep_pause_btn.config(text=label)\n        if state[\"paused\"]:\n            self._data_recovery_quick_status.config(text=\"Scan paused.\")\n            self._data_recovery_deep_status.config(text=\"Scan paused.\")\n            self._data_recovery_record_history(\"pause_scan\", {\"task_id\": self._data_recovery_state.get(\"task_id\")})\n        else:\n            self._data_recovery_quick_status.config(text=\"Scan resumed.\")\n            self._data_recovery_deep_status.config(text=\"Scan resumed.\")\n            self._data_recovery_record_history(\"resume_scan\", {\"task_id\": self._data_recovery_state.get(\"task_id\")})\n        task_id = self._data_recovery_state.get(\"task_id\")\n        if task_id:\n            if state[\"paused\"]:\n                self._task_pause(task_id)\n            else:\n                self._task_resume(task_id)\n\n    def _data_recovery_cancel_scan(self):\n        state = self._data_recovery_state\n        if not state.get(\"running\", False):\n            return\n        state[\"cancelled\"] = True\n        state[\"paused\"] = False\n        self._data_recovery_quick_status.config(text=\"Scan cancellation requested...\")\n        self._data_recovery_deep_status.config(text=\"Scan cancellation requested...\")\n        if hasattr(self, \"_data_recovery_quick_pause_btn\"):\n            self._data_recovery_quick_pause_btn.config(text=\"\u25b6 Resume Scan\", state=\"disabled\")\n        if hasattr(self, \"_data_recovery_deep_pause_btn\"):\n            self._data_recovery_deep_pause_btn.config(text=\"\u25b6 Resume Scan\", state=\"disabled\")\n        if hasattr(self, \"_data_recovery_quick_cancel_btn\"):\n            self._data_recovery_quick_cancel_btn.config(state=\"disabled\")\n        if hasattr(self, \"_data_recovery_deep_cancel_btn\"):\n            self._data_recovery_deep_cancel_btn.config(state=\"disabled\")\n        task_id = self._data_recovery_state.get(\"task_id\")\n        if task_id:\n            self._task_cancel(task_id)\n        self._data_recovery_record_history(\"cancel_scan\", {\"task_id\": task_id})\n\n    def _data_recovery_record_history(self, action, details=None):\n        entry = {\n            \"timestamp\": datetime.datetime.now().isoformat(timespec=\"seconds\"),\n            \"action\": action,\n            \"details\": details or {},\n        }\n        self._data_recovery_state.setdefault(\"history\", []).append(entry)\n        self._data_recovery_state.setdefault(\"queue\", []).append(entry)\n\n    def _data_recovery_run_quick_scan_worker(self, source_path, output_folder, filter_label, task_id=None):\n        cancelled = False\n        try:\n            source_path = self._data_recovery_get_source_path(source_path)\n            if not source_path or not os.path.exists(source_path):\n                raise RuntimeError(\"Selected quick recovery source is missing.\")\n            if _is_raw_device_path(source_path):\n                raise PermissionError(\"Quick Recovery works on mounted volumes. Use Deep Recovery for raw disk sources.\")\n\n            def _should_stop():\n                nonlocal cancelled\n                if self._data_recovery_state.get(\"cancelled\", False) or self._task_is_cancelled(task_id):\n                    cancelled = True\n                    return True\n                return False\n\n            def _wait_for_resume():\n                if task_id:\n                    try:\n                        self._task_wait_if_paused(task_id)\n                    except RuntimeError:\n                        nonlocal cancelled\n                        cancelled = True\n                        return True\n                return False\n\n            allowed = None\n            if filter_label == \"Photos\":\n                allowed = {\"jpg\", \"jpeg\", \"png\", \"gif\", \"bmp\", \"tif\", \"tiff\"}\n            elif filter_label == \"Videos\":\n                allowed = {\"mp4\", \"mov\", \"mkv\", \"avi\", \"wmv\", \"flv\", \"mpeg\", \"mpg\"}\n            elif filter_label == \"Documents\":\n                allowed = {\"pdf\", \"doc\", \"docx\", \"xls\", \"xlsx\", \"ppt\", \"pptx\", \"txt\", \"rtf\", \"csv\", \"json\"}\n            elif filter_label == \"Archives\":\n                allowed = {\"zip\", \"7z\", \"rar\", \"tar\", \"gz\", \"bz2\", \"xz\"}\n\n            start = time.time()\n            processed = 0\n            scanned = 0\n            copied = 0\n            total_candidates = 0\n            last_ui = 0\n            skip_dirs = {\"$recycle.bin\", \"system volume information\", \"windows\", \"program files\", \"program files (x86)\"}\n            for root, dirs, files in os.walk(source_path):\n                if _should_stop():\n                    return\n                if _wait_for_resume():\n                    return\n                while self._data_recovery_state.get(\"paused\", False):\n                    if _should_stop():\n                        return\n                    if _wait_for_resume():\n                        return\n                    time.sleep(0.12)\n                dirs[:] = [\n                    d for d in dirs\n                    if not d.startswith(\".\") and d.lower() not in skip_dirs\n                    and not os.path.islink(os.path.join(root, d))\n                ]\n                total_candidates += len(files)\n                for name in files:\n                    if _should_stop():\n                        return\n                    if _wait_for_resume():\n                        return\n                    while self._data_recovery_state.get(\"paused\", False):\n                        if _should_stop():\n                            return\n                        if _wait_for_resume():\n                            return\n                        time.sleep(0.12)\n                    src_path = os.path.join(root, name)\n                    scanned += 1\n                    try:\n                        size_bytes = os.path.getsize(src_path)\n                    except Exception:\n                        continue\n                    ext = os.path.splitext(name)[1].lstrip(\".\").lower()\n                    if allowed is not None and ext not in allowed:\n                        now = time.time()\n                        if now - last_ui &gt;= 1.0:\n                            elapsed = max(0.1, now - start)\n                            speed = (processed / (1024 * 1024)) / elapsed\n                            pct = min(99.0, (scanned / max(1, total_candidates)) * 100.0)\n                            self.after(0, lambda p=pct, s=speed, r=copied: self._data_recovery_update_scan_ui(\"quick\", p, r, s, \"--\"))\n                            if task_id:\n                                self._task_update_progress(task_id, pct)\n                            last_ui = now\n                        continue\n                    rel_path = os.path.relpath(src_path, source_path)\n                    out_path = os.path.join(output_folder, rel_path)\n                    os.makedirs(os.path.dirname(out_path), exist_ok=True)\n                    if not os.path.exists(out_path):\n                        with open(src_path, \"rb\") as src, open(out_path, \"wb\") as dst:\n                            while True:\n                                if _should_stop():\n                                    return\n                                if _wait_for_resume():\n                                    return\n                                while self._data_recovery_state.get(\"paused\", False):\n                                    if _should_stop():\n                                        return\n                                    if _wait_for_resume():\n                                        return\n                                    time.sleep(0.12)\n                                chunk = src.read(1024 * 1024)\n                                if not chunk:\n                                    break\n                                dst.write(chunk)\n                                processed += len(chunk)\n                                now = time.time()\n                                if now - last_ui &gt;= 1.0:\n                                    elapsed = max(0.1, now - start)\n                                    speed = (processed / (1024 * 1024)) / elapsed\n                                    pct = min(99.0, (scanned / max(1, total_candidates)) * 100.0)\n                                    self.after(0, lambda p=pct, s=speed, r=copied: self._data_recovery_update_scan_ui(\"quick\", p, r, s, \"--\"))\n                                    if task_id:\n                                        self._task_update_progress(task_id, pct)\n                                    last_ui = now\n                        try:\n                            shutil.copystat(src_path, out_path)\n                        except Exception:\n                            pass\n                    else:\n                        processed += size_bytes\n                    copied += 1\n                    self.after(0, lambda _kind=ext.upper() or \"FILE\", _offset=0, _size=size_bytes, _path=out_path: self._data_recovery_add_preview_row(\"quick\", _kind, _offset, _size, _path))\n                    if copied % 10 == 0:\n                        elapsed = max(0.1, time.time() - start)\n                        speed = (processed / (1024 * 1024)) / elapsed\n                        file_rate = copied / elapsed\n                        remaining = max(0, total_candidates - copied)\n                        eta = \"--\" if file_rate &lt;= 0 else f\"{max(0, int(remaining / file_rate))} s\"\n                        pct = min(100.0, (copied / max(1, total_candidates)) * 100.0)\n                        self.after(0, lambda p=pct, s=speed, e=eta, r=copied: self._data_recovery_update_scan_ui(\"quick\", p, r, s, e))\n                        if task_id:\n                            self._task_update_progress(task_id, pct)\n            self.after(0, lambda c=copied: self._data_recovery_finish_scan(\"quick\", c))\n        except Exception as exc:\n            self.after(0, lambda e=exc: messagebox.showerror(\"Quick Recovery Error\", str(e)))\n        finally:\n            if cancelled:\n                self.after(0, lambda c=copied: self._data_recovery_finish_scan(\"quick\", c, cancelled=True))\n\n    def _data_recovery_start_quick_recovery(self):\n        source = self._data_recovery_get_source_path(self._data_recovery_quick_disk_var.get())\n        if not source:\n            messagebox.showwarning(\"No Source\", \"Select a disk or volume first.\")\n            return\n        if not os.path.exists(source):\n            messagebox.showwarning(\"No Source\", \"The selected source path does not exist.\")\n            return\n        if _is_raw_device_path(source):\n            messagebox.showwarning(\"Quick Recovery\", \"Quick Recovery works on mounted volumes. Use Deep Recovery for raw disk sources.\")\n            return\n        if self._data_recovery_state.get(\"running\", False):\n            messagebox.showwarning(\"Data Recovery Busy\", \"Ek recovery/imaging job already chal raha hai. Pehle usko cancel/complete hone dein.\")\n            return\n        if not messagebox.askyesno(\"Quick Recovery Warning\", \"Quick recovery will copy matching files to the selected destination. Continue only on an authorized target.\"):\n            return\n        output_folder = self._data_recovery_quick_output_var.get()\n        os.makedirs(output_folder, exist_ok=True)\n        self._data_recovery_state[\"running\"] = True\n        self._data_recovery_state[\"paused\"] = False\n        self._data_recovery_state[\"cancelled\"] = False\n        self._data_recovery_state[\"session_id\"] = self.recovery_session_manager.start(\"data_recovery_quick\", {\n            \"source\": source,\n            \"output\": output_folder,\n            \"filter\": self._data_recovery_filter_var.get(),\n        })\n        self._data_recovery_state[\"history\"] = self._data_recovery_state.get(\"history\", [])\n        self._data_recovery_quick_preview.delete(*self._data_recovery_quick_preview.get_children())\n        self._data_recovery_quick_status.config(text=\"Quick recovery started.\")\n        self._data_recovery_quick_progress.config(value=0)\n        self._data_recovery_quick_speed.config(text=\"Speed: 0 MB/s | ETA: --\")\n        self._data_recovery_update_summary(\"Source\", source)\n        self._data_recovery_update_summary(\"Recovered\", \"0 files\")\n        if hasattr(self, \"_data_recovery_quick_start_btn\"):\n            try:\n                self._data_recovery_quick_start_btn.config(state=\"disabled\")\n            except Exception:\n                pass\n        if hasattr(self, \"_data_recovery_quick_pause_btn\"):\n            self._data_recovery_quick_pause_btn.config(state=\"normal\", text=\"\u23f8 Pause Scan\")\n        if hasattr(self, \"_data_recovery_quick_cancel_btn\"):\n            self._data_recovery_quick_cancel_btn.config(state=\"normal\")\n        task_id = self._launch_job(\"data_recovery_quick_scan\", self._data_recovery_run_quick_scan_worker, source, output_folder, self._data_recovery_filter_var.get())\n        self._data_recovery_state[\"task_id\"] = task_id\n        self._data_recovery_record_history(\"start_quick_recovery\", {\"task_id\": task_id, \"session_id\": self._data_recovery_state.get(\"session_id\")})\n\n    def _data_recovery_run_deep_scan_worker(self, source_path, output_folder, filters, task_id=None):\n        cancelled = False\n        try:\n            source_path = self._data_recovery_get_source_path(source_path)\n            if not source_path:\n                raise RuntimeError(\"Deep recovery source missing.\")\n            if _is_raw_device_path(source_path) and not self._ensure_admin_for_raw_recovery(source_path):\n                return\n\n            def _should_stop():\n                nonlocal cancelled\n                if self._data_recovery_state.get(\"cancelled\", False) or self._task_is_cancelled(task_id):\n                    cancelled = True\n                    return True\n                return False\n\n            def _wait_for_resume():\n                if task_id:\n                    try:\n                        self._task_wait_if_paused(task_id)\n                    except RuntimeError:\n                        nonlocal cancelled\n                        cancelled = True\n                        return True\n                return False\n\n            recovered = 0\n            self._data_recovery_state[\"recovered\"] = 0\n\n            def progress_cb(message):\n                text = str(message or \"\")[:180]\n                pct = 0\n                try:\n                    m = re.search(r\"(\\d{1,3})%\", text)\n                    if m:\n                        pct = int(m.group(1))\n                except Exception:\n                    pct = 0\n                self.after(0, lambda: self._data_recovery_update_scan_ui(\"deep\", pct, recovered, 0.0, \"--\"))\n                self.after(0, lambda: self._data_recovery_deep_status.config(text=text))\n                if task_id:\n                    self._task_update_progress(task_id, pct)\n\n            result = multi_pass_recovery(source_path, output_folder, progress_callback=progress_cb)\n            recovered = 0\n            for entry in result.get(\"files\", []):\n                if _should_stop():\n                    return\n                if _wait_for_resume():\n                    return\n                path = entry.get(\"path\")\n                if not path or not os.path.exists(path):\n                    continue\n                size = os.path.getsize(path)\n                kind = entry.get(\"file_type\") or os.path.splitext(path)[1].lstrip(\".\").upper() or \"BIN\"\n                offset = entry.get(\"offset\", 0)\n                recovered += 1\n                self.after(0, lambda _kind=kind, _offset=offset, _size=size, _path=path: self._data_recovery_add_preview_row(\"deep\", _kind, _offset, _size, _path))\n            self.after(0, lambda c=recovered: self._data_recovery_finish_scan(\"deep\", c))\n        except Exception as exc:\n            self.after(0, lambda e=exc: messagebox.showerror(\"Deep Scan Error\", str(e)))\n        finally:\n            if cancelled:\n                self.after(0, lambda c=recovered: self._data_recovery_finish_scan(\"deep\", c, cancelled=True))\n\n    def _data_recovery_start_deep_recovery(self):\n        source = self._data_recovery_get_source_path(self._data_recovery_deep_source_var.get())\n        if not source:\n            messagebox.showwarning(\"No Source\", \"Select a disk or volume first.\")\n            return\n        if not os.path.exists(source) and not _is_raw_device_path(source):\n            messagebox.showwarning(\"No Source\", \"The selected source path does not exist.\")\n            return\n        if _is_raw_device_path(source) and not self._ensure_admin_for_raw_recovery(source):\n            return\n        if self._data_recovery_state.get(\"running\", False):\n            messagebox.showwarning(\"Data Recovery Busy\", \"Ek recovery/imaging job already chal raha hai. Pehle usko cancel/complete hone dein.\")\n            return\n        filters = [kind for kind, var in self._data_recovery_deep_flags.items() if var.get()]\n        output_folder = self._data_recovery_deep_output_var.get()\n        os.makedirs(output_folder, exist_ok=True)\n        self._data_recovery_state[\"running\"] = True\n        self._data_recovery_state[\"paused\"] = False\n        self._data_recovery_state[\"cancelled\"] = False\n        self._data_recovery_state[\"session_id\"] = self.recovery_session_manager.start(\"data_recovery_deep\", {\n            \"source\": source,\n            \"output\": output_folder,\n            \"filters\": filters,\n        })\n        self._data_recovery_deep_preview.delete(*self._data_recovery_deep_preview.get_children())\n        self._data_recovery_deep_status.config(text=\"Deep carve started.\")\n        self._data_recovery_deep_progress.config(value=0)\n        self._data_recovery_deep_speed.config(text=\"Speed: 0 MB/s | ETA: --\")\n        self._data_recovery_update_summary(\"Source\", source)\n        self._data_recovery_update_summary(\"Recovered\", \"0 files\")\n        if hasattr(self, \"_data_recovery_deep_start_btn\"):\n            try:\n                self._data_recovery_deep_start_btn.config(state=\"disabled\")\n            except Exception:\n                pass\n        if hasattr(self, \"_data_recovery_deep_pause_btn\"):\n            self._data_recovery_deep_pause_btn.config(state=\"normal\", text=\"\u23f8 Pause Scan\")\n        if hasattr(self, \"_data_recovery_deep_cancel_btn\"):\n            self._data_recovery_deep_cancel_btn.config(state=\"normal\")\n        task_id = self._launch_job(\"data_recovery_deep_scan\", self._data_recovery_run_deep_scan_worker, source, output_folder, filters)\n        self._data_recovery_state[\"task_id\"] = task_id\n        self._data_recovery_record_history(\"start_deep_recovery\", {\"task_id\": task_id, \"session_id\": self._data_recovery_state.get(\"session_id\")})\n\n    def _data_recovery_update_scan_ui(self, mode, pct, found, speed, eta):\n        if mode == \"quick\":\n            self._data_recovery_quick_progress.config(value=max(0, min(100.0, pct)))\n            self._data_recovery_quick_status.config(text=f\"Recovered {found} candidates.\")\n            self._data_recovery_quick_speed.config(text=f\"Speed: {speed:.2f} MB/s | ETA: {eta}\")\n        else:\n            self._data_recovery_deep_progress.config(value=max(0, min(100.0, pct)))\n            self._data_recovery_deep_status.config(text=f\"Recovered {found} candidates.\")\n            self._data_recovery_deep_speed.config(text=f\"Speed: {speed:.2f} MB/s | ETA: {eta}\")\n        self._data_recovery_update_summary(\"Recovered\", f\"{found} files\")\n\n    def _data_recovery_finish_scan(self, mode, found, cancelled=False):\n        self._data_recovery_state[\"running\"] = False\n        display_text = \"\"\n        if cancelled:\n            display_text = f\"Scan cancelled. {found} candidate(s) recovered before stop.\"\n        elif mode == \"quick\":\n            display_text = f\"Quick scan complete. {found} candidate(s) recovered.\"\n        else:\n            display_text = f\"Deep carve complete. {found} candidate(s) recovered.\"\n\n        if mode == \"quick\":\n            self._data_recovery_quick_status.config(text=display_text)\n            if not cancelled:\n                self._data_recovery_quick_progress.config(value=100.0 if found &gt;= 1 else 0)\n            if hasattr(self, \"_data_recovery_quick_start_btn\"):\n                try:\n                    self._data_recovery_quick_start_btn.config(state=\"normal\")\n                except Exception:\n                    pass\n            if hasattr(self, \"_data_recovery_quick_pause_btn\"):\n                self._data_recovery_quick_pause_btn.config(state=\"disabled\", text=\"\u23f8 Pause Scan\")\n            if hasattr(self, \"_data_recovery_quick_cancel_btn\"):\n                self._data_recovery_quick_cancel_btn.config(state=\"disabled\")\n        else:\n            self._data_recovery_deep_status.config(text=display_text)\n            if not cancelled:\n                self._data_recovery_deep_progress.config(value=100.0 if found &gt;= 1 else 0)\n            if hasattr(self, \"_data_recovery_deep_start_btn\"):\n                try:\n                    self._data_recovery_deep_start_btn.config(state=\"normal\")\n                except Exception:\n                    pass\n            if hasattr(self, \"_data_recovery_deep_pause_btn\"):\n                self._data_recovery_deep_pause_btn.config(state=\"disabled\", text=\"\u23f8 Pause Scan\")\n            if hasattr(self, \"_data_recovery_deep_cancel_btn\"):\n                self._data_recovery_deep_cancel_btn.config(state=\"disabled\")\n\n        self._data_recovery_state[\"cancelled\"] = False\n        self._data_recovery_state[\"task_id\"] = None\n        self._data_recovery_record_history(\n            \"finish_scan\",\n            {\n                \"mode\": mode,\n                \"found\": found,\n                \"cancelled\": cancelled,\n                \"session_id\": self._data_recovery_state.get(\"session_id\"),\n            },\n        )\n        self._data_recovery_set_recovery_chance(\"High\" if found &gt;= 1 else \"Low\")\n        self._data_recovery_generate_report_html()\n\n    def _data_recovery_recover_partition_table(self):\n        source = self._data_recovery_imaging_disk_var.get() or self._data_recovery_quick_disk_var.get()\n        if not source:\n            messagebox.showwarning(\"No Disk\", \"Select a disk or raw volume first.\")\n            return\n        if not messagebox.askyesno(\"Partition Recovery Warning\", \"Recovering partition metadata is a forensic operation. Continue only if authorized and an image exists.\"):\n            return\n        partitions = self._data_recovery_parse_partitions(self._data_recovery_get_source_path(source))\n        if not partitions:\n            messagebox.showinfo(\"Partition Recovery\", \"No partition candidates detected.\")\n            return\n        self._data_recovery_refresh_partition_list()\n        messagebox.showinfo(\"Partition Recovery\", f\"Recovered {len(partitions)} partition candidate(s).\")\n\n    def _data_recovery_verify_partition_table(self):\n        source = self._data_recovery_get_source_path(self._data_recovery_imaging_disk_var.get() or self._data_recovery_quick_disk_var.get())\n        if not source:\n            messagebox.showwarning(\"No Disk\", \"Select a disk or raw volume first.\")\n            return\n        partitions = self._data_recovery_parse_partitions(source)\n        self._data_recovery_refresh_partition_list()\n        if partitions:\n            messagebox.showinfo(\"Partition Verification\", f\"Partition table appears present: {len(partitions)} candidate entry/entries found.\")\n        else:\n            messagebox.showwarning(\"Partition Verification\", \"No valid MBR signature found.\")\n\n    def _data_recovery_export_report(self):\n        report_path = os.path.join(os.path.expanduser(\"~\"), \"Desktop\", \"Godawari_DataRecovery_Report.html\")\n        try:\n            self._data_recovery_generate_report_html(report_path)\n            self._data_recovery_state[\"last_report\"] = report_path\n            messagebox.showinfo(\"Report Saved\", f\"HTML report saved to:\\n{report_path}\")\n        except Exception as exc:\n            messagebox.showerror(\"Report Error\", str(exc))\n\n    def _data_recovery_generate_report_html(self, output_path=None):\n        output_path = output_path or os.path.join(os.path.expanduser(\"~\"), \"Desktop\", \"Godawari_DataRecovery_Report.html\")\n        os.makedirs(os.path.dirname(output_path), exist_ok=True)\n        preview = self._data_recovery_state.get(\"preview\", [])\n        total = len(preview)\n        pie = f\"conic-gradient({C['accent']} 0% 45%, {C['accent2']} 45% 75%, {C['warning']} 75% 92%, {C['hw_accent']} 92% 100%)\"\n        html_doc = f\"\"\"\n\n\n\n\nGodawari Data Recovery Report\n\nbody {{ font-family: Segoe UI, Arial, sans-serif; background:#0A0F1A; color:#F0F4FA; margin:0; padding:20px; }}\nh1 {{ color:#FFB347; }}\n.card {{ background:#121826; border:1px solid #2A3A5A; border-radius:12px; padding:16px; margin-bottom:16px; }}\n.summary {{ display:flex; gap:16px; flex-wrap:wrap; }}\n.metric {{ background:#182032; border-radius:12px; padding:14px 18px; min-width:160px; }}\n.metric strong {{ display:block; font-size:20px; margin-top:6px; }}\n.chart {{ width:240px; height:240px; border-radius:50%; background:{pie}; }}\ntable {{ width:100%; border-collapse:collapse; margin-top:10px; }}\nth, td {{ border-bottom:1px solid #2A3A5A; padding:8px; text-align:left; }}\nth {{ color:#FFB347; }}\n\n\n\n\n\n  \nGodawari Data Recovery Report\n  \nGenerated on {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}.\n\n\n\n  \nRecovered Candidates{total}\n  \nRecovery ChanceHigh\n  \nLast Image{os.path.basename(self._data_recovery_state.get('last_img', 'none'))}\n\n\n\nRecovery Distribution\n\n\n\nCandidate Table\nTypeOffsetSizePath\n\"\"\"\n        for item in preview:\n            html_doc += f\"{html.escape(str(item.get('kind', '')))}{item.get('offset', 0)}{self._fmt_size(item.get('size', 0))}{html.escape(str(item.get('path', '')))}\"\n        html_doc += \"\"\n        Path(output_path).write_text(html_doc, encoding=\"utf-8\")\n        self._data_recovery_state[\"last_report\"] = output_path\n        return output_path\n\n    def _build_printer_driver_merged(self, parent):\n        return self._build_tabbed_merger(parent, [\n            (\"\ud83d\udda8  Printer Fixer + Sharing\", \"_build_printer\"),\n            (\"\ud83d\udce6  Driver Checker\", \"_build_driver\"),\n        ])\n\n    def _build_uninstall_backup_merged(self, parent):\n        return self._build_tabbed_merger(parent, [\n            (\"\ud83d\uddd1  Batch Uninstall\", \"_build_uninstaller\"),\n            (\"\ud83d\udcbe  Backup / Restore\", \"_build_backup\"),\n        ])\n\n    def _build_realtime_security(self, parent):\n        return self._build_tabbed_merger(parent, [\n            (\"Security Audit\", \"_build_password_audit\"),\n            (\"Process Scanner\", \"_build_suspicion_scanner\"),\n        ])\n\n    def _build_dup_report_merged(self, parent):\n        return self._build_tabbed_merger(parent, [\n            (\"\ud83d\udd0d  Duplicate Finder\", \"_build_dupfinder\"),\n            (\"\ud83d\udcca  Export Report\", \"_build_report\"),\n        ])\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  END MERGED SECTION BUILDERS\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _build_statusbar(self):\n        sb = tk.Frame(self, bg=C[\"panel\"], height=28)\n        sb.pack(side=\"bottom\", fill=\"x\")\n        tk.Frame(sb, bg=C[\"accent\"], height=1).pack(side=\"top\", fill=\"x\")\n        self.status_lbl = tk.Label(sb, text=\"\u25cf Ready\", font=FONTS[\"small\"], fg=C[\"accent\"], bg=C[\"panel\"])\n        self.status_lbl.pack(side=\"left\", padx=12)\n        self.cpu_lbl = tk.Label(sb, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"])\n        self.ram_lbl = tk.Label(sb, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"])\n        self.disk_lbl = tk.Label(sb, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"])\n        self.security_lbl = tk.Label(sb, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"])\n        self.task_lbl = tk.Label(sb, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"])\n        self.task_lbl.pack(side=\"right\", padx=12)\n        self.security_lbl.pack(side=\"right\", padx=12)\n        self.disk_lbl.pack(side=\"right\", padx=12)\n        self.ram_lbl.pack(side=\"right\", padx=4)\n        self.cpu_lbl.pack(side=\"right\", padx=4)\n        self._update_statusbar()\n\n    def _update_statusbar(self):\n        try:\n            cpu = psutil.cpu_percent(interval=None)\n            ram = psutil.virtual_memory().percent\n            disk = psutil.disk_usage(\"C:\\\\\").percent\n            health = self._calculate_global_health()\n            security_status = \"Secure\" if health[\"per_category\"].get(\"security\", 100) &gt;= 80 else \"Alert\"\n            active_tasks = len([t for t in self._task_manager.values() if t.get(\"status\") == \"running\"])\n            self.cpu_lbl.config(text=f\"CPU: {cpu:.1f}%\", fg=C[\"error\"] if cpu &gt; 80 else C[\"text_dim\"])\n            self.ram_lbl.config(text=f\"RAM: {ram:.1f}%\", fg=C[\"error\"] if ram &gt; 85 else C[\"text_dim\"])\n            self.disk_lbl.config(text=f\"Disk: {disk:.1f}%\", fg=C[\"warning\"] if disk &gt; 85 else C[\"text_dim\"])\n            self.security_lbl.config(text=f\"Security: {security_status}\", fg=C[\"success\"] if security_status == \"Secure\" else C[\"error\"])\n            self.task_lbl.config(text=f\"Active Tasks: {active_tasks}\", fg=C[\"accent\"] if active_tasks else C[\"text_dim\"])\n        except Exception:\n            pass\n        self.after(2000, self._update_statusbar)\n\n    def _build_footer(self):\n        footer = tk.Frame(self, bg=C[\"header_bg\"], height=24)\n        footer.pack(side=\"bottom\", fill=\"x\")\n        tk.Label(footer, text=\"\u00a9 2025 Godawari Computers | v11.0 Safety &amp; Recovery | Developer: Shravan Shrimali\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"header_bg\"]).pack(pady=3)\n\n    # ---------- CORE HELPERS ----------\n    def _set_status(self, msg, color=None):\n        self.status_lbl.config(text=f\"\u25cf {msg}\", fg=color or C[\"accent\"])\n\n    def _log(self, msg, level=\"INFO\", path=None, size=None):\n        ts = datetime.datetime.now().strftime(\"%H:%M:%S\")\n        colors = {\"INFO\": C[\"text\"], \"OK\": C[\"success\"], \"WARN\": C[\"warning\"], \"ERR\": C[\"error\"], \"CRITICAL\": C[\"error\"]}\n        color = colors.get(level, C[\"text\"])\n        if path:\n            msg += f\"\\n   \ud83d\udccd Path: {path}\"\n        if size:\n            msg += f\"\\n   \ud83d\udce6 Size: {size}\"\n        line = self._fix_text(f\"[{ts}] [{level:4s}] {msg}\")\n        self.log_lines.append((line, color))\n        if hasattr(self, \"log_text\"):\n            self.log_text.config(state=\"normal\")\n            self.log_text.insert(\"end\", line + \"\\n\", f\"lvl_{level}\")\n            self.log_text.tag_config(f\"lvl_{level}\", foreground=color)\n            self.log_text.see(\"end\")\n            self.log_text.config(state=\"disabled\")\n        try:\n            self._write_enterprise_log(self._enterprise_log_file, line, level)\n            if level in (\"ERR\", \"CRITICAL\"):\n                self._write_enterprise_log(self._enterprise_error_log, line, level)\n        except Exception:\n            pass\n        # Structured logging to runtime store\n        try:\n            if getattr(self, \"structured_logger\", None):\n                try:\n                    self.structured_logger.log(level, msg, {\"path\": path, \"size\": size})\n                except Exception:\n                    pass\n        except Exception:\n            pass\n\n    def _fix_text(self, value):\n        if not isinstance(value, str):\n            return value\n        if any(t in value for t in (\"\\u00e2\", \"\\u00f0\", \"\\u00c2\", \"\u00c3\u00a2\", \"\u00c3\u00b0\", \"\u00c3\u201a\")):\n            try:\n                return value.encode(\"cp1252\", errors=\"ignore\").decode(\"utf-8\", errors=\"ignore\")\n            except:\n                return value\n        return value\n\n    def _sanitize_ui_texts(self):\n        def walk(widget):\n            try:\n                text = widget.cget(\"text\")\n                fixed = self._fix_text(text)\n                if fixed != text:\n                    widget.config(text=fixed)\n            except:\n                pass\n            for child in widget.winfo_children():\n                walk(child)\n        walk(self)\n\n    def _dpi_px(self, value):\n        try:\n            scaling = float(self.tk.call(\"tk\", \"scaling\"))\n            factor = max(0.85, min(1.45, scaling / 1.3333333333))\n            return max(1, int(round(value * factor)))\n        except Exception:\n            return int(value)\n\n    def _bind_scoped_mousewheel(self, widget, canvas, units=3):\n        if not getattr(self, \"_scroll_mousewheel_targets\", None):\n            self._scroll_mousewheel_targets = {}\n\n        self._scroll_mousewheel_targets[widget] = (canvas, units)\n        self._scroll_mousewheel_targets[canvas] = (canvas, units)\n\n        def _wheel(event):\n            target = event.widget\n            targets = getattr(self, \"_scroll_mousewheel_targets\", {})\n            while target is not None:\n                if target in targets:\n                    canvas_target, unit_target = targets[target]\n                    try:\n                        if getattr(event, \"num\", None) == 4:\n                            canvas_target.yview_scroll(-unit_target, \"units\")\n                        elif getattr(event, \"num\", None) == 5:\n                            canvas_target.yview_scroll(unit_target, \"units\")\n                        else:\n                            step = int(-1 * (event.delta / 120))\n                            canvas_target.yview_scroll(step * unit_target, \"units\")\n                    except Exception:\n                        pass\n                    return \"break\"\n                target = getattr(target, \"master\", None)\n            return None\n\n        if not getattr(self, \"_mousewheel_binding_installed\", False):\n            self._mousewheel_binding_installed = True\n            self.bind_all(\"\", _wheel, add=\"+\")\n            self.bind_all(\"\", _wheel, add=\"+\")\n            self.bind_all(\"\", _wheel, add=\"+\")\n\n    def _scrollable_section_body(self, parent, bg=None):\n        \"\"\"Create a responsive scrollable section with proper width management.\n        \n        ENGINEERING FIX #4: Improved canvas+scrollbar layout to prevent content clipping.\n        Uses the same pattern as the fixed sidebar for consistency.\n        \"\"\"\n        bg = bg or C[\"bg\"]\n        outer = tk.Frame(parent, bg=bg)\n        outer.pack(fill=\"both\", expand=True)\n        \n        # Create canvas and scrollbar\n        canvas = tk.Canvas(outer, bg=bg, highlightthickness=0, borderwidth=0)\n        yscroll = ttk.Scrollbar(outer, orient=\"vertical\", command=canvas.yview)\n        \n        # Create body frame with proper sizing\n        body = tk.Frame(canvas, bg=bg)\n        \n        # Embed body in canvas\n        win = canvas.create_window((0, 0), window=body, anchor=\"nw\")\n\n        def _on_body_configure(event=None):\n            \"\"\"Update scroll region when body content changes.\"\"\"\n            try:\n                canvas.configure(scrollregion=canvas.bbox(\"all\"))\n                # Get available width (canvas width, not including scrollbar)\n                available_width = canvas.winfo_width()\n                if available_width &gt; 1:\n                    # Set window width to match canvas width\n                    canvas.itemconfig(win, width=available_width)\n            except tk.TclError:\n                pass  # Canvas destroyed\n\n        def _on_canvas_configure(event):\n            \"\"\"Update scroll region when canvas is resized.\"\"\"\n            try:\n                # Ensure window width matches available canvas space\n                canvas.itemconfig(win, width=event.width)\n                canvas.configure(scrollregion=canvas.bbox(\"all\"))\n            except tk.TclError:\n                pass  # Canvas destroyed\n\n        # Bind configuration events\n        body.bind(\"\", _on_body_configure)\n        canvas.bind(\"\", _on_canvas_configure)\n        \n        # Configure canvas scrolling\n        canvas.configure(yscrollcommand=yscroll.set)\n        \n        # Pack scrollbar first (right), then canvas (left) for proper z-ordering\n        yscroll.pack(side=\"right\", fill=\"y\", expand=False)  # expand=False prevents scrollbar from stretching\n        canvas.pack(side=\"left\", fill=\"both\", expand=True)\n        \n        # Setup mousewheel scrolling\n        self._bind_scoped_mousewheel(body, canvas)\n        body._scroll_canvas = canvas\n        body._scroll_outer = outer\n        return body\n\n    def _set_uninst_progress(self, pct=None, text=None, color=None):\n        def _do():\n            try:\n                if pct is not None and hasattr(self, \"uninst_progress_var\"):\n                    pct_float = max(0, min(100, float(pct)))\n                    self.uninst_progress_var.set(pct_float)\n                    if pct_float &lt;= 0 or not getattr(self, \"_uninst_progress_started_at\", None):\n                        self._uninst_progress_started_at = time.time()\n                    elapsed = max(0.0, time.time() - float(getattr(self, \"_uninst_progress_started_at\", time.time())))\n                    if pct_float &gt; 0:\n                        total_est = elapsed / (pct_float / 100.0)\n                        left = max(0.0, total_est - elapsed)\n                        total_txt = self._format_seconds(total_est)\n                        left_txt = self._format_seconds(left)\n                    else:\n                        total_txt = \"--\"\n                        left_txt = \"--\"\n                    if hasattr(self, \"uninst_timing_lbl\"):\n                        self.uninst_timing_lbl.config(\n                            text=f\"Elapsed: {self._format_seconds(elapsed)} | Left: {left_txt} | Total: {total_txt}\"\n                        )\n                    if pct_float &gt;= 100:\n                        self._uninst_progress_started_at = None\n                if text is not None and hasattr(self, \"uninst_status\"):\n                    self.uninst_status.config(text=\"  \" + self._fix_text(str(text)), fg=color or C[\"accent2\"])\n            except Exception:\n                pass\n\n        if threading.current_thread() is threading.main_thread():\n            _do()\n        else:\n            self.after(0, _do)\n\n    def _check_uninst_control(self):\n        if getattr(self, \"_uninst_cancel_flag\", False):\n            raise InterruptedError(\"User cancelled uninstall scan\")\n        paused_notice = False\n        while getattr(self, \"_uninst_pause_flag\", False):\n            if getattr(self, \"_uninst_cancel_flag\", False):\n                raise InterruptedError(\"User cancelled uninstall scan\")\n            if not paused_notice:\n                paused_notice = True\n                self._set_uninst_progress(text=\"Scan paused. Press Resume to continue.\", color=C[\"warning\"])\n            time.sleep(0.15)\n\n    def _pause_resume_uninst_scan(self):\n        self._uninst_pause_flag = not getattr(self, \"_uninst_pause_flag\", False)\n        if hasattr(self, \"uninst_pause_btn\"):\n            self.uninst_pause_btn.config(text=\"Resume Scan\" if self._uninst_pause_flag else \"Pause Scan\")\n        self._set_uninst_progress(\n            text=\"Scan paused. Press Resume to continue.\" if self._uninst_pause_flag else \"Scan resumed.\",\n            color=C[\"warning\"] if self._uninst_pause_flag else C[\"accent4\"],\n        )\n\n    def _stop_uninst_scan(self):\n        self._uninst_cancel_flag = True\n        self._set_uninst_progress(text=\"Stop requested. Current safe checkpoint will finish first.\", color=C[\"warning\"])\n\n    def _leftover_record(self, ftype, path, confidence=70, risk=None, source=\"\", action=\"delete\", meta=None):\n        ftype = str(ftype or \"ITEM\").upper()\n        path = str(path or \"\")\n        if risk is None:\n            if ftype in {\"REG\", \"SERVICE\", \"TASK\", \"STARTUP\"}:\n                risk = \"Risky\"\n            elif ftype in {\"SHORTCUT\"}:\n                risk = \"Safe\"\n            else:\n                risk = \"Safe\"\n        try:\n            confidence = int(confidence)\n        except Exception:\n            confidence = 60\n        return {\n            \"type\": ftype,\n            \"path\": path,\n            \"risk\": risk,\n            \"confidence\": max(0, min(100, confidence)),\n            \"source\": source,\n            \"action\": action,\n            \"meta\": meta or {},\n        }\n\n    def _leftover_parts(self, item):\n        if isinstance(item, dict):\n            return (\n                str(item.get(\"type\", \"ITEM\")),\n                str(item.get(\"path\", \"\")),\n                str(item.get(\"risk\", \"\")),\n                int(item.get(\"confidence\", 0) or 0),\n                item.get(\"meta\", {}) or {},\n            )\n        try:\n            ftype, path = item\n            return str(ftype), str(path), \"Risky\" if str(ftype).upper() == \"REG\" else \"Safe\", 60, {}\n        except Exception:\n            return \"ITEM\", str(item), \"Risky\", 0, {}\n\n    def _add_leftover_item(self, found, seen, ftype, path, confidence=70, risk=None, source=\"\", action=\"delete\", meta=None):\n        if not path:\n            return\n        key = (str(ftype).upper(), str(path).lower())\n        if key in seen:\n            return\n        seen.add(key)\n        found.append(self._leftover_record(ftype, path, confidence, risk, source, action, meta))\n\n    def _native_delete_file(self, path):\n        try:\n            from ctypes import wintypes\n            ctypes.windll.kernel32.DeleteFileW.argtypes = [wintypes.LPCWSTR]\n            ctypes.windll.kernel32.DeleteFileW.restype = wintypes.BOOL\n            return bool(ctypes.windll.kernel32.DeleteFileW(str(path)))\n        except Exception:\n            return False\n\n    def _native_remove_empty_dir(self, path):\n        try:\n            from ctypes import wintypes\n            ctypes.windll.kernel32.RemoveDirectoryW.argtypes = [wintypes.LPCWSTR]\n            ctypes.windll.kernel32.RemoveDirectoryW.restype = wintypes.BOOL\n            return bool(ctypes.windll.kernel32.RemoveDirectoryW(str(path)))\n        except Exception:\n            return False\n\n    def _native_delete_service(self, service_name):\n        try:\n            from ctypes import wintypes\n            advapi = ctypes.windll.advapi32\n            advapi.OpenSCManagerW.argtypes = [wintypes.LPCWSTR, wintypes.LPCWSTR, wintypes.DWORD]\n            advapi.OpenSCManagerW.restype = wintypes.HANDLE\n            advapi.OpenServiceW.argtypes = [wintypes.HANDLE, wintypes.LPCWSTR, wintypes.DWORD]\n            advapi.OpenServiceW.restype = wintypes.HANDLE\n            advapi.DeleteService.argtypes = [wintypes.HANDLE]\n            advapi.DeleteService.restype = wintypes.BOOL\n            advapi.CloseServiceHandle.argtypes = [wintypes.HANDLE]\n            advapi.CloseServiceHandle.restype = wintypes.BOOL\n            SC_MANAGER_CONNECT = 0x0001\n            DELETE = 0x00010000\n            SERVICE_STOP = 0x0020\n            SERVICE_QUERY_STATUS = 0x0004\n            scm = advapi.OpenSCManagerW(None, None, SC_MANAGER_CONNECT)\n            if not scm:\n                return False, \"OpenSCManagerW failed\"\n            try:\n                svc = advapi.OpenServiceW(scm, str(service_name), DELETE | SERVICE_STOP | SERVICE_QUERY_STATUS)\n                if not svc:\n                    return False, \"OpenServiceW failed\"\n                try:\n                    ok = bool(advapi.DeleteService(svc))\n                    return ok, \"\" if ok else \"DeleteService failed\"\n                finally:\n                    advapi.CloseServiceHandle(svc)\n            finally:\n                advapi.CloseServiceHandle(scm)\n        except Exception as e:\n            return False, str(e)\n\n    def _delete_leftover_path(self, path, ftype):\n        ftype = str(ftype or \"\").upper()\n        if ftype == \"FOLDER\":\n            blocked, reason = _is_dangerous_cleanup_target(path)\n            if blocked:\n                raise PermissionError(reason)\n            if self._native_remove_empty_dir(path):\n                return\n            shutil.rmtree(path, ignore_errors=False)\n            return\n        if ftype in {\"FILE\", \"SHORTCUT\"}:\n            if self._native_delete_file(path):\n                return\n            os.remove(path)\n\n    def _normalize_uninstall_command(self, item, quiet=True):\n        cmd = (item.get(\"quiet\") if quiet else \"\") or item.get(\"uninst\", \"\") or \"\"\n        cmd = str(cmd).strip()\n        if not cmd:\n            return \"\"\n        low = cmd.lower()\n        if \"msiexec\" in low:\n            product = re.search(r\"\\{[0-9a-fA-F\\-]{36}\\}\", cmd)\n            if product:\n                cmd = f\"msiexec.exe /x {product.group(0)}\"\n            elif \" /i\" in low or low.endswith(\"/i\"):\n                cmd = re.sub(r\"(?i)\\s/i\\s*\", \" /x \", cmd)\n            if quiet and \"/qn\" not in cmd.lower() and \"/quiet\" not in cmd.lower():\n                cmd += \" /qn\"\n            if quiet and \"/norestart\" not in cmd.lower():\n                cmd += \" /norestart\"\n        return cmd\n\n    def _command_requires_shell(self, cmd):\n        if not isinstance(cmd, str):\n            return False\n        text = cmd.strip()\n        lower = text.lower()\n        metachars = (\"|\", \"&amp;&amp;\", \"||\", \"&gt;\", \"&lt;\")\n        builtins = (\"start \", \"rd \", \"del \", \"copy \", \"move \", \"echo \")\n        return (\n            any(token in text for token in metachars)\n            or lower.startswith(builtins)\n            or \"%\" in text\n        )\n\n    def _run_cmd(self, cmd, shell=None, timeout=120):\n        if shell is None:\n            shell = True\n        started = time.time()\n        if isinstance(cmd, (list, tuple)):\n            try:\n                result = safe_run(cmd, timeout=timeout)\n                self._audit_event(\"safe_command\", {\n                    \"cmd\": result.args[:20],\n                    \"rc\": result.returncode,\n                    \"timeout_s\": timeout,\n                    \"elapsed_ms\": result.elapsed_ms,\n                    \"timed_out\": result.timed_out,\n                    \"output_tail\": result.output[-300:],\n                })\n                return result.output, result.returncode\n            except Exception as e:\n                return str(e), -1\n        actual_shell = bool(shell and self._command_requires_shell(cmd))\n        if shell and actual_shell:\n            self._audit_event(\"restricted_shell_command_legacy\", {\n                \"cmd\": str(cmd)[:500],\n                \"note\": \"Shell kept only for legacy commands that require cmd.exe semantics.\",\n            })\n        elif shell:\n            self._audit_event(\"legacy_string_command_safened\", {\n                \"cmd\": str(cmd)[:500],\n                \"note\": \"Shell bypassed; migrate caller to list args/safe_run.\",\n            })\n        try:\n            startupinfo = None\n            creationflags = 0\n            if sys.platform == \"win32\":\n                startupinfo = subprocess.STARTUPINFO()\n                startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW\n                creationflags = subprocess.CREATE_NO_WINDOW\n            result = subprocess.run(\n                cmd,\n                shell=actual_shell,\n                capture_output=True,\n                text=True,\n                timeout=timeout,\n                encoding=\"utf-8\",\n                errors=\"replace\",\n                startupinfo=startupinfo,\n                creationflags=creationflags,\n            )\n            output = (result.stdout or \"\").strip()\n            err = (result.stderr or \"\").strip()\n            if err:\n                output = f\"{output}\\n{err}\".strip()\n            self._audit_event(\"command\", {\n                \"cmd\": str(cmd)[:500],\n                \"rc\": result.returncode,\n                \"timeout_s\": timeout,\n                \"elapsed_ms\": int((time.time() - started) * 1000),\n                \"output_tail\": output[-300:],\n            })\n            return output, result.returncode\n        except subprocess.TimeoutExpired:\n            self._audit_event(\"command_timeout\", {\n                \"cmd\": str(cmd)[:500],\n                \"timeout_s\": timeout,\n                \"elapsed_ms\": int((time.time() - started) * 1000),\n            })\n            return f\"Command timed out: {cmd}\", -1\n        except Exception as e:\n            self._audit_event(\"command_error\", {\n                \"cmd\": str(cmd)[:500],\n                \"error\": str(e),\n                \"elapsed_ms\": int((time.time() - started) * 1000),\n            })\n            return str(e), -1\n\n    def _run_powershell(self, script, timeout=120):\n        \"\"\"PowerShell ko EncodedCommand se run karta hai taaki quoting issues na aayein.\"\"\"\n        try:\n            result = safe_powershell(script, timeout=timeout)\n            self._audit_event(\"safe_powershell\", {\n                \"rc\": result.returncode,\n                \"timeout_s\": timeout,\n                \"elapsed_ms\": result.elapsed_ms,\n                \"timed_out\": result.timed_out,\n                \"output_tail\": result.output[-300:],\n            })\n            return result.output, result.returncode\n        except Exception as e:\n            return str(e), -1\n\n    def _stream_cmd_to_log(self, cmd, log_widget, timeout_s=1800, stop_attr=\"_repair_stop_flag\"):\n        \"\"\"\n        Existing logging ko use karke command output live stream karta hai.\n        Return: (full_output, rc, timed_out, stopped)\n        \"\"\"\n        output = []\n        started = time.time()\n        timed_out = False\n        stopped = False\n        proc = None\n        try:\n            setattr(self, stop_attr, False)\n            startupinfo = None\n            creationflags = 0\n            if sys.platform == \"win32\":\n                startupinfo = subprocess.STARTUPINFO()\n                startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW\n                creationflags = subprocess.CREATE_NO_WINDOW\n            proc = subprocess.Popen(\n                cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,\n                text=True, encoding=\"utf-8\", errors=\"replace\",\n                startupinfo=startupinfo,\n                creationflags=creationflags,\n            )\n            if stop_attr == \"_repair_stop_flag\":\n                self._repair_proc = proc\n            for line in iter(proc.stdout.readline, \"\"):\n                if not line and proc.poll() is not None:\n                    break\n                clean = line.rstrip(\"\\n\")\n                if clean:\n                    output.append(clean)\n                    self._append_log(log_widget, clean, C[\"text_dim\"])\n                if getattr(self, stop_attr, False):\n                    stopped = True\n                    try:\n                        proc.terminate()\n                    except Exception:\n                        pass\n                    break\n                if timeout_s and (time.time() - started) &gt; timeout_s:\n                    timed_out = True\n                    try:\n                        proc.terminate()\n                    except Exception:\n                        pass\n                    break\n            try:\n                rc = proc.wait(timeout=5)\n            except Exception:\n                rc = -1\n        except Exception as e:\n            output.append(str(e))\n            rc = -1\n            self._append_log(log_widget, f\"Command stream failed: {e}\", C[\"error\"])\n        finally:\n            if stop_attr == \"_repair_stop_flag\":\n                self._repair_proc = None\n        return \"\\n\".join(output), rc, timed_out, stopped\n\n    # ---------- CONFIRMATION WITH BEFORE/AFTER ----------\n    def _operation_preflight_summary(self, title, commands=None):\n        engine = getattr(self, \"preflight_engine\", None)\n        if not engine:\n            return None\n        try:\n            return engine.analyze(title, commands or [])\n        except Exception:\n            return None\n\n    def _format_preflight_for_dialog(self, preflight):\n        if not preflight:\n            return \"Preflight: unavailable\"\n        lines = [\n            f\"Risk: {str(preflight.risk).upper()} ({preflight.score}/100)\",\n            f\"Admin required: {'yes' if preflight.requires_admin else 'no'}\",\n            f\"Restore point required: {'yes' if preflight.requires_restore_point else 'no'}\",\n            f\"Rollback snapshot required: {'yes' if preflight.requires_rollback_snapshot else 'no'}\",\n            f\"Dry-run recommended: {'yes' if preflight.dry_run_recommended else 'no'}\",\n        ]\n        for finding in getattr(preflight, \"findings\", [])[:3]:\n            lines.append(f\"- {finding.message} Recommendation: {finding.recommendation}\")\n        return \"\\n\".join(lines)\n\n    def _confirm_and_run(self, title, description, before_callback, action_callback, after_callback=None):\n        before_info = before_callback() if before_callback else \"No before data\"\n        preflight = self._operation_preflight_summary(title)\n        msg = (\n            f\"{description}\\n\\n\"\n            f\"SAFETY PREFLIGHT:\\n{self._format_preflight_for_dialog(preflight)}\\n\\n\"\n            f\"\ud83d\udcca BEFORE:\\n{before_info}\\n\\nDo you want to proceed?\"\n        )\n        if not messagebox.askyesno(title, msg):\n            self._audit_event(\"action_cancelled\", {\"title\": title})\n            return False\n        if preflight and getattr(preflight, \"typed_confirmation\", False):\n            token = str(title).strip()[:24]\n            typed = simpledialog.askstring(\n                \"Critical Confirmation\",\n                f\"Type this action name to continue:\\n\\n{token}\",\n            )\n            if typed != token:\n                self._audit_event(\"action_cancelled\", {\"title\": title, \"reason\": \"typed_confirmation_failed\"})\n                return False\n        risky_words = (\"delete\", \"clean\", \"disable\", \"registry\", \"policy\", \"remove\", \"repair\", \"force\")\n        lower_title = str(title).lower()\n        if any(w in lower_title for w in risky_words) or (preflight and preflight.requires_restore_point):\n            try:\n                self._create_restore_point(f\"Pre-Action: {title}\")\n            except Exception:\n                pass\n\n        state_before = self._snapshot_system_state()\n        self._audit_event(\"action_started\", {\n            \"title\": title,\n            \"before_info\": str(before_info)[:800],\n            \"state\": state_before,\n            \"preflight\": {\n                \"risk\": getattr(preflight, \"risk\", \"\"),\n                \"score\": getattr(preflight, \"score\", 0),\n                \"restore_point\": getattr(preflight, \"requires_restore_point\", False),\n                \"rollback_snapshot\": getattr(preflight, \"requires_rollback_snapshot\", False),\n            },\n        })\n        self._set_status(f\"Executing: {title}...\", C[\"accent4\"])\n        action_result = action_callback()\n        success_guess = True\n        if isinstance(action_result, dict) and action_result.get(\"ok\") is False:\n            success_guess = False\n        if after_callback:\n            after_info = after_callback()\n            diff_msg = f\"\\n\\n\ud83d\udcc8 AFTER:\\n{after_info}\"\n            if isinstance(action_result, dict) and action_result.get(\"message\"):\n                messagebox.showinfo(\"Complete\", f\"{action_result['message']}{diff_msg}\")\n            else:\n                messagebox.showinfo(\"Complete\", f\"{title} completed successfully.{diff_msg}\")\n        else:\n            if isinstance(action_result, dict) and action_result.get(\"message\"):\n                box_title = \"Already Done\" if action_result.get(\"already_done\") else \"Complete\"\n                messagebox.showinfo(box_title, action_result[\"message\"])\n            else:\n                messagebox.showinfo(\"Complete\", f\"{title} completed.\")\n            after_info = \"No after data\"\n        state_after = self._snapshot_system_state()\n        self._audit_event(\"action_finished\", {\n            \"title\": title,\n            \"success\": success_guess,\n            \"after_info\": str(after_info)[:800],\n            \"state_before\": state_before,\n            \"state_after\": state_after,\n        })\n        self._set_status(\"Ready\", C[\"success\"])\n        return True\n\n    def _confirm_and_launch_job(self, title, description, before_callback, job_name, target, *args):\n        before_info = before_callback() if before_callback else \"No before data\"\n        preflight = self._operation_preflight_summary(title)\n        msg = (\n            f\"{description}\\n\\n\"\n            f\"SAFETY PREFLIGHT:\\n{self._format_preflight_for_dialog(preflight)}\\n\\n\"\n            f\"\ud83d\udcca BEFORE:\\n{before_info}\\n\\nDo you want to proceed?\"\n        )\n        if not messagebox.askyesno(title, msg):\n            self._audit_event(\"action_cancelled\", {\"title\": title})\n            return False\n        risky_words = (\"delete\", \"clean\", \"disable\", \"registry\", \"policy\", \"remove\", \"repair\", \"force\")\n        lower_title = str(title).lower()\n        if any(w in lower_title for w in risky_words) or (preflight and preflight.requires_restore_point):\n            try:\n                self._create_restore_point(f\"Pre-Action: {title}\")\n            except Exception:\n                pass\n\n        state_before = self._snapshot_system_state()\n        self._audit_event(\"action_started\", {\n            \"title\": title,\n            \"before_info\": str(before_info)[:800],\n            \"state\": state_before,\n            \"preflight\": {\n                \"risk\": getattr(preflight, \"risk\", \"\"),\n                \"score\": getattr(preflight, \"score\", 0),\n                \"restore_point\": getattr(preflight, \"requires_restore_point\", False),\n                \"rollback_snapshot\": getattr(preflight, \"requires_rollback_snapshot\", False),\n            },\n        })\n        self._set_status(f\"Queued: {title}...\", C[\"accent4\"])\n        jid = self._launch_job(job_name, target, *args)\n        self._audit_event(\"action_launched\", {\"title\": title, \"job_id\": jid, \"name\": job_name})\n        return jid\n\n    def _set_clean_job_state(self, running=False, export_ready=False):\n        self._clean_job_running = bool(running)\n        try:\n            if hasattr(self, \"clean_cancel_btn\"):\n                self.clean_cancel_btn.config(state=\"normal\" if running else \"disabled\")\n        except Exception:\n            pass\n        try:\n            if hasattr(self, \"clean_report_btn\"):\n                self.clean_report_btn.config(state=\"normal\" if export_ready and not running else \"disabled\")\n        except Exception:\n            pass\n\n    def _cancel_clean_job(self):\n        if not getattr(self, \"_clean_job_running\", False):\n            return\n        self._clean_job_cancel_event.set()\n        self._set_status(\"Clean operation cancellation requested...\", C[\"warning\"])\n        self._append_log(self.clean_log, \"\u23f9 Requested cancellation of current clean operation.\", C[\"warning\"])\n\n    def _export_clean_report(self):\n        summary = getattr(self, \"_clean_job_summary\", {}) or {}\n        if not summary:\n            messagebox.showwarning(\"No Report\", \"Run a scan or clean operation first, then export the report.\")\n            return\n        fpath = filedialog.asksaveasfilename(defaultextension=\".txt\", filetypes=[(\"Text Report\",\"*.txt\")], title=\"Save Cleaner Report\")\n        if not fpath:\n            return\n        try:\n            report_lines = [\"Godawari Cleaner Report\", f\"Date: {datetime.datetime.now()}\", \"\"]\n            report_lines.append(\"Junk Cleaner Summary:\")\n            report_lines.append(f\"Targets processed: {summary.get('processed', 0)} / {summary.get('total_paths', 0)}\")\n            if summary.get('total_size') is not None:\n                report_lines.append(f\"Total junk found: {self._fmt_size(summary.get('total_size', 0))}\")\n            if summary.get('freed') is not None:\n                report_lines.append(f\"Freed: {self._fmt_size(summary.get('freed', 0))}\")\n                report_lines.append(f\"Remaining junk: {self._fmt_size(summary.get('remaining', 0))}\")\n            if summary.get('preview'):\n                report_lines.append(\"Preview mode: yes\")\n            if summary.get('canceled'):\n                report_lines.append(\"Canceled: yes\")\n            report_lines.append(f\"Errors: {summary.get('errors', 0)}\")\n            report_lines.append(\"\")\n            report_lines.append(\"Detailed Clean Log:\")\n            report_lines.append(self.clean_log.get(\"1.0\", \"end\").strip())\n            with open(fpath, \"w\", encoding=\"utf-8\") as f:\n                f.write(\"\\n\".join(report_lines))\n            self._append_log(self.clean_log, f\"\u2705 Exported cleaner report: {fpath}\", C[\"success\"])\n        except Exception as e:\n            messagebox.showerror(\"Export Failed\", str(e))\n\n    def _finalize_clean_job(self, job_type, summary):\n        try:\n            self._set_clean_job_state(running=False, export_ready=True)\n            self._clean_job_summary = summary\n            canceled = summary.get(\"canceled\", False)\n            total_paths = summary.get(\"total_paths\", 0)\n            processed = summary.get(\"processed\", 0)\n            summary_lines = [f\"{job_type.title()} Summary:\"]\n            summary_lines.append(f\"Targets processed: {processed} / {total_paths}\")\n            if job_type == \"scan\":\n                total_size = summary.get(\"total_size\", 0)\n                summary_lines.append(f\"Total junk found: {self._fmt_size(total_size)}\")\n                self.clean_size_lbl.config(text=f\"Total junk found: {self._fmt_size(total_size)}\")\n                self.clean_progress_lbl.config(text=f\"Scan complete: {self._fmt_size(total_size)}\")\n            else:\n                freed = summary.get(\"freed\", 0)\n                remaining = summary.get(\"remaining\", 0)\n                summary_lines.append(f\"Freed: {self._fmt_size(freed)}\")\n                summary_lines.append(f\"Remaining junk: {self._fmt_size(remaining)}\")\n                if summary.get(\"preview\"):\n                    summary_lines.append(\"Preview mode: no files were deleted.\")\n                self.clean_size_lbl.config(text=f\"Total junk found: {self._fmt_size(remaining)} remaining\")\n                self.clean_progress_lbl.config(text=f\"Clean complete: {self._fmt_size(freed)} freed\")\n            if summary.get(\"errors\", 0):\n                summary_lines.append(f\"Errors: {summary.get('errors', 0)}\")\n            if canceled:\n                summary_lines.append(\"Operation canceled by user.\")\n                self._set_status(f\"{job_type.title()} canceled.\", C[\"warning\"])\n            else:\n                self._set_status(f\"{job_type.title()} complete.\", C[\"success\"])\n            if hasattr(self, \"clean_progress_bar\"):\n                try:\n                    if total_paths &gt; 0:\n                        self.clean_progress_bar.config(value=min(processed, total_paths))\n                except Exception:\n                    pass\n            self._append_log(self.clean_log, \"\\n\".join(summary_lines), C[\"accent\"])\n            messagebox.showinfo(f\"{job_type.title()} Complete\", \"\\n\".join(summary_lines))\n        except Exception:\n            pass\n\n    # ---------- DASHBOARD ----------\n    def _build_dashboard(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        tb = tk.Frame(frame, bg=C[\"panel\"])\n        tb.pack(fill=\"x\")\n        tk.Label(tb, text=\"  System Dashboard\", font=FONTS[\"heading\"], fg=C[\"accent\"], bg=C[\"panel\"]).pack(side=\"left\", pady=10, padx=8)\n        tk.Button(tb, text=\"\u27f3 Refresh\", font=FONTS[\"small\"], bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=10, pady=4, cursor=\"hand2\", command=self._refresh_dashboard).pack(side=\"right\", padx=12, pady=8)\n        tk.Button(tb, text=\"\ud83d\ude80 Live Internet Speed Test\", font=FONTS[\"small\"], bg=C[\"btn_warn\"], fg=C[\"text\"], bd=0, padx=10, pady=4, cursor=\"hand2\", command=self._live_speed_test).pack(side=\"right\", padx=5, pady=8)\n        tk.Button(tb, text=\"\ud83d\udd0d One-Click Health Scan\", font=FONTS[\"small\"], bg=C[\"btn_warn\"], fg=C[\"text\"], bd=0, padx=10, pady=4, cursor=\"hand2\", command=self._one_click_health_scan).pack(side=\"right\", padx=5, pady=8)\n        grid = tk.Frame(frame, bg=C[\"bg\"])\n        grid.pack(fill=\"x\", padx=16, pady=(12,0))\n        self.dash_cards = {}\n        cards_def = [(\"cpu\",\"CPU Usage\",C[\"accent\"],\"0%\"), (\"ram\",\"RAM Usage\",C[\"success\"],\"0%\"),\n                     (\"disk\",\"Disk Usage\",C[\"accent4\"],\"0%\"), (\"health\",\"Health Score\",C[\"accent2\"],\"--\"),\n                     (\"uptime\",\"Uptime\",C[\"accent2\"],\"--\")]\n        for i, (k, title, color, val) in enumerate(cards_def):\n            card = self._stat_card(grid, title, val, color)\n            card.grid(row=0, column=i, padx=6, pady=6, sticky=\"ew\")\n            grid.columnconfigure(i, weight=1)\n            self.dash_cards[k] = card\n        self.after(2000, self._refresh_health_score_card)\n        graph_frame = tk.Frame(frame, bg=C[\"card\"])\n        graph_frame.pack(fill=\"x\", padx=16, pady=6)\n        tk.Label(graph_frame, text=\"  Live CPU/RAM History (60s)\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8,4), padx=8)\n        self.graph_canvas = tk.Canvas(graph_frame, bg=C[\"bg\"], height=self._dpi_px(82), highlightthickness=0)\n        self.graph_canvas.pack(fill=\"x\", padx=8, pady=8)\n        self.graph_data = {\"cpu\": [], \"ram\": []}\n\n        rec_panel = tk.Frame(frame, bg=C[\"card\"])\n        rec_panel.pack(fill=\"x\", padx=16, pady=(0, 8))\n        rec_head = tk.Frame(rec_panel, bg=C[\"card\"])\n        rec_head.pack(fill=\"x\", padx=8, pady=(8, 4))\n        tk.Label(rec_head, text=\"  Intelligent Recommendations\", font=FONTS[\"subhead\"],\n                 fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._btn(rec_head, \"Refresh\", C[\"btn_info\"], self._refresh_intelligent_recommendations).pack(side=\"right\")\n        rec_cols = (\"Priority\", \"Menu\", \"Action\")\n        self.dashboard_recommendation_tree = ttk.Treeview(\n            rec_panel, columns=rec_cols, show=\"headings\", height=5, style=\"Custom.Treeview\")\n        for col, w in zip(rec_cols, (90, 210, 720)):\n            self.dashboard_recommendation_tree.heading(col, text=col)\n            self.dashboard_recommendation_tree.column(col, width=w, anchor=\"w\")\n        self.dashboard_recommendation_tree.pack(fill=\"x\", padx=8, pady=(0, 8))\n        self.dashboard_recommendation_tree.bind(\"\", lambda _e: self._show_section(\"safety_center\"))\n        self.after(2600, self._refresh_intelligent_recommendations)\n\n        lower = tk.Frame(frame, bg=C[\"bg\"])\n        lower.pack(fill=\"both\", expand=True, padx=16, pady=10)\n        lower.columnconfigure(0, weight=5)\n        lower.columnconfigure(1, weight=2)\n        lower.rowconfigure(0, weight=1)\n        proc_frame = tk.Frame(lower, bg=C[\"card\"])\n        proc_frame.grid(row=0, column=0, sticky=\"nsew\", padx=(0,6))\n        proc_frame.rowconfigure(1, weight=1)\n        proc_frame.columnconfigure(0, weight=1)\n        tk.Label(proc_frame, text=\"  Process Center - Top CPU Processes\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=0, column=0, columnspan=2, sticky=\"w\", pady=(8,4), padx=8)\n        cols = (\"PID\",\"Name\",\"CPU%\",\"RAM MB\",\"Status\")\n        self.proc_tree = ttk.Treeview(proc_frame, columns=cols, show=\"headings\", height=24, style=\"Custom.Treeview\")\n        for col, w in zip(cols, [60,200,70,80,80]):\n            self.proc_tree.heading(col, text=col)\n            self.proc_tree.column(col, width=w, anchor=\"center\")\n        sb2 = ttk.Scrollbar(proc_frame, orient=\"vertical\", command=self.proc_tree.yview)\n        xsb2 = ttk.Scrollbar(proc_frame, orient=\"horizontal\", command=self.proc_tree.xview)\n        self.proc_tree.configure(yscrollcommand=sb2.set, xscrollcommand=xsb2.set)\n        self.proc_tree.grid(row=1, column=0, sticky=\"nsew\", padx=(8,0), pady=(0,0))\n        sb2.grid(row=1, column=1, sticky=\"ns\", pady=(0,0), padx=(0,8))\n        xsb2.grid(row=2, column=0, sticky=\"ew\", padx=(8,0), pady=(0,8))\n        self._bind_tree_responsive_columns(self.proc_tree, [\n            (\"PID\", 60, 0), (\"Name\", 220, 5), (\"CPU%\", 70, 1), (\"RAM MB\", 90, 1), (\"Status\", 100, 2)\n        ])\n        qa = tk.Frame(lower, bg=C[\"card\"])\n        qa.grid(row=0, column=1, sticky=\"nsew\", padx=(6,0))\n        tk.Label(qa, text=\"  Quick Actions\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8,6), padx=8)\n        self._action_card_grid(qa, [\n            (\"\ud83e\uddf9\", \"Clean + RAM\",         \"Temp clean + RAM optimize\",        C[\"btn\"],      self._quick_clean_and_ram),\n            (\"\u2699\",  \"Services + Registry\", \"Services + Registry tweaks\",       C[\"btn_info\"], self._quick_services_and_registry),\n            (\"\ud83d\udd0d\", \"Full Health Scan\",    \"Poora system scan karo\",           C[\"btn\"],      self._full_scan),\n            (\"\u26a1\", \"One-Click ALL\",        \"Sabhi boosts ek saath chalao\",     C[\"accent4\"],  self._one_click_all_boosts),\n            (\"\ud83d\udee1\", \"Safety Center\",        \"Health, rollback, sessions\",       C[\"btn_chip\"], lambda: self._show_section(\"safety_center\")),\n        ], cols=2)\n\n        workflow = tk.Frame(lower, bg=C[\"card\"])\n        workflow.grid(row=1, column=0, columnspan=2, sticky=\"ew\", pady=(8,0))\n        tk.Label(workflow, text=\"  Guided Workflows\", font=FONTS[\"subhead\"], fg=C[\"accent2\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=8, pady=(8,4))\n        self.dashboard_workflow_lbl = tk.Label(\n            workflow,\n            text=\"Health scan not run yet \u2014 use One-Click Health Scan or Safety Center to generate guided actions.\",\n            font=FONTS[\"small\"],\n            fg=C[\"text_dim\"],\n            bg=C[\"card\"],\n            justify=\"left\",\n            wraplength=1150,\n            anchor=\"w\",\n        )\n        self.dashboard_workflow_lbl.pack(fill=\"x\", padx=8, pady=(0,8))\n        wf_actions = tk.Frame(workflow, bg=C[\"card\"])\n        wf_actions.pack(fill=\"x\", padx=8, pady=(0,8))\n        for label, color, cmd in [\n            (\"\ud83d\udee1 Safety + Restore\", C[\"btn_warn\"], lambda: (self._show_section(\"safety_center\"), self._create_restore_point(\"Guided workflow\"))),\n            (\"\ud83c\udf10 Network + Repair\", C[\"btn_info\"], lambda: self._show_section(\"network\")),\n            (\"\ud83d\udcbe Recovery + Rescue\", C[\"btn_chip\"], lambda: self._show_section(\"rescue_center\")),\n            (\"\ud83e\uddf9 Clean + RAM\", C[\"btn\"], self._quick_clean_and_ram),\n        ]:\n            tk.Button(wf_actions, text=label, font=FONTS[\"small\"], bg=color, fg=C[\"text\"], bd=0, padx=12, pady=8,\n                      cursor=\"hand2\", command=cmd).pack(side=\"left\", padx=4, pady=4)\n        return frame\n\n    def _build_safety_center(self, parent):\n        \"\"\"Professional safety hub: health scoring, rollback vault, sessions, timeline.\"\"\"\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(\n            frame,\n            \"\ud83d\udee1 Safety &amp; Recovery Center\",\n            \"Health scoring \u2022 Restore Point Manager \u2022 Rollback vault \u2022 Operation timeline\",\n        )\n\n        canvas = tk.Canvas(frame, bg=C[\"bg\"], highlightthickness=0)\n        scrollbar = ttk.Scrollbar(frame, orient=\"vertical\", command=canvas.yview)\n        content = tk.Frame(canvas, bg=C[\"bg\"])\n        content.bind(\"\", lambda e: canvas.configure(scrollregion=canvas.bbox(\"all\")))\n        canvas_window = canvas.create_window((0, 0), window=content, anchor=\"nw\")\n        canvas.configure(yscrollcommand=scrollbar.set)\n        canvas.pack(side=\"left\", fill=\"both\", expand=True)\n        scrollbar.pack(side=\"right\", fill=\"y\")\n\n        def _resize_content(event):\n            try:\n                canvas.itemconfigure(canvas_window, width=event.width)\n                canvas.configure(scrollregion=canvas.bbox(\"all\"))\n            except Exception:\n                pass\n\n        canvas.bind(\"\", _resize_content)\n        self._bind_scoped_mousewheel(content, canvas)\n\n        top = tk.Frame(content, bg=C[\"card\"])\n        top.pack(fill=\"x\", padx=16, pady=10)\n        self.safety_health_lbl = tk.Label(\n            top, text=\"Health: analyzing\u2026\",\n            font=(\"Segoe UI\", 22, \"bold\"), fg=C[\"accent\"], bg=C[\"card\"])\n        self.safety_health_lbl.pack(side=\"left\", padx=12, pady=10)\n        btn_row = tk.Frame(top, bg=C[\"card\"])\n        btn_row.pack(side=\"right\", padx=12)\n        self._btn(btn_row, \"\ud83d\udd0d Run Health Scan\", C[\"btn_warn\"], self._one_click_health_scan).pack(side=\"left\", padx=4)\n        self._btn(btn_row, \"\ud83d\udcbe Create Restore Point\", C[\"btn_info\"],\n                  lambda: self._create_restore_point(\"Safety Center manual\")).pack(side=\"left\", padx=4)\n        self._btn(btn_row, \"Generate Audit\", C[\"accent4\"], self._safety_export_product_audit).pack(side=\"left\", padx=4)\n        self._btn(btn_row, \"Export Menu Map\", C[\"btn_chip\"], self._safety_export_menu_map).pack(side=\"left\", padx=4)\n        self._btn(btn_row, \"\ud83d\udd04 Refresh\", C[\"btn\"], self._safety_refresh_all).pack(side=\"left\", padx=4)\n\n        mid = tk.Frame(content, bg=C[\"bg\"])\n        mid.pack(fill=\"x\", padx=16, pady=(0, 10))\n        mid.columnconfigure(0, weight=1)\n        mid.columnconfigure(1, weight=1)\n\n        # Rollback vault\n        rb_card = tk.LabelFrame(mid, text=\" Rollback Vault \", font=FONTS[\"subhead\"],\n                                fg=C[\"accent\"], bg=C[\"card\"])\n        rb_card.grid(row=0, column=0, sticky=\"nsew\", padx=(0, 6), pady=(0, 6))\n        rb_cols = (\"Session\", \"Items\", \"Created\")\n        self.safety_rollback_tree = ttk.Treeview(\n            rb_card, columns=rb_cols, show=\"headings\", height=8, style=\"Custom.Treeview\")\n        for col, w in zip(rb_cols, (200, 60, 160)):\n            self.safety_rollback_tree.heading(col, text=col)\n            self.safety_rollback_tree.column(col, width=w)\n        self.safety_rollback_tree.pack(fill=\"both\", expand=True, padx=8, pady=8)\n        rb_btns = tk.Frame(rb_card, bg=C[\"card\"])\n        rb_btns.pack(fill=\"x\", padx=8, pady=(0, 8))\n        self._btn(rb_btns, \"\u21a9 Restore Selected\", C[\"btn_warn\"], self._safety_restore_rollback).pack(side=\"left\", padx=4)\n        self._btn(rb_btns, \"\ud83d\udcc2 Open Vault Folder\", C[\"btn_chip\"], self._safety_open_rollback_dir).pack(side=\"left\", padx=4)\n\n        # Recovery sessions\n        rs_card = tk.LabelFrame(mid, text=\" Recovery Sessions \", font=FONTS[\"subhead\"],\n                                fg=C[\"accent4\"], bg=C[\"card\"])\n        rs_card.grid(row=0, column=1, sticky=\"nsew\", padx=(6, 0), pady=(0, 6))\n        rs_cols = (\"ID\", \"Kind\", \"Status\", \"Started\")\n        self.safety_session_tree = ttk.Treeview(\n            rs_card, columns=rs_cols, show=\"headings\", height=8, style=\"Custom.Treeview\")\n        for col, w in zip(rs_cols, (120, 100, 80, 140)):\n            self.safety_session_tree.heading(col, text=col)\n            self.safety_session_tree.column(col, width=w)\n        self.safety_session_tree.pack(fill=\"both\", expand=True, padx=8, pady=8)\n        rs_btns = tk.Frame(rs_card, bg=C[\"card\"])\n        rs_btns.pack(fill=\"x\", padx=8, pady=(0, 8))\n        self._btn(rs_btns, \"\u2713 Mark Completed\", C[\"btn_info\"], self._safety_clear_session).pack(side=\"left\", padx=4)\n        self._btn(rs_btns, \"\ud83e\uddf9 Clear Crash Flag\", C[\"btn\"], self._safety_clear_crash_marker).pack(side=\"left\", padx=4)\n\n        rp_card = tk.LabelFrame(mid, text=\" Restore Point Manager \", font=FONTS[\"subhead\"],\n                                fg=C[\"accent4\"], bg=C[\"card\"])\n        rp_card.grid(row=1, column=0, columnspan=2, sticky=\"ew\", pady=(6, 0), padx=(0,0))\n        rp_toolbar = tk.Frame(rp_card, bg=C[\"card\"])\n        rp_toolbar.pack(fill=\"x\", padx=8, pady=(8, 0))\n        tk.Label(rp_toolbar, text=\"Recent Restore Points\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._btn(rp_toolbar, \"Refresh\", C[\"btn\"], self._safety_refresh_restore_points).pack(side=\"right\", padx=4)\n        self._btn(rp_toolbar, \"Open System Restore\", C[\"btn_warn\"], self._open_system_restore).pack(side=\"right\", padx=4)\n        rp_cols = (\"Sequence\", \"Description\", \"Created\")\n        self.safety_restore_tree = ttk.Treeview(\n            rp_card, columns=rp_cols, show=\"headings\", height=5, style=\"Custom.Treeview\")\n        for col, w in zip(rp_cols, (100, 420, 180)):\n            self.safety_restore_tree.heading(col, text=col)\n            self.safety_restore_tree.column(col, width=w, anchor=\"w\")\n        self.safety_restore_tree.pack(fill=\"both\", expand=True, padx=8, pady=8)\n\n        tl_card = tk.LabelFrame(mid, text=\" Operation Timeline (structured log) \", font=FONTS[\"subhead\"],\n                                fg=C[\"accent2\"], bg=C[\"card\"])\n        tl_card.grid(row=2, column=0, columnspan=2, sticky=\"ew\", pady=(6, 0))\n        self.safety_timeline = self._scrolled_text(tl_card, height=12)\n        self.safety_timeline.pack(fill=\"both\", expand=True, padx=8, pady=8)\n\n        # Recommendations\n        rec_card = tk.LabelFrame(mid, text=\" Smart Recommendations \", font=FONTS[\"subhead\"],\n                                 fg=C[\"hw_accent\"], bg=C[\"card\"])\n        rec_card.grid(row=3, column=0, columnspan=2, sticky=\"ew\", pady=(6, 0))\n        self.safety_recommendations = tk.Label(\n            rec_card, text=\"Run a health scan for personalized recommendations.\",\n            font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"],\n            anchor=\"w\", justify=\"left\", wraplength=1100)\n        self.safety_recommendations.pack(fill=\"x\", padx=12, pady=10)\n\n        map_card = tk.LabelFrame(mid, text=\" Detected Software Map \", font=FONTS[\"subhead\"],\n                                 fg=C[\"accent2\"], bg=C[\"card\"])\n        map_card.grid(row=4, column=0, columnspan=2, sticky=\"ew\", pady=(6, 0))\n        map_cols = (\"Category\", \"Menu\", \"Tabs\", \"Buttons\", \"Options\")\n        self.safety_menu_map_tree = ttk.Treeview(\n            map_card, columns=map_cols, show=\"headings\", height=8, style=\"Custom.Treeview\")\n        for col, w in zip(map_cols, (210, 230, 70, 80, 80)):\n            self.safety_menu_map_tree.heading(col, text=col)\n            self.safety_menu_map_tree.column(col, width=w, anchor=\"w\")\n        self.safety_menu_map_tree.pack(fill=\"x\", padx=8, pady=8)\n\n        prof_card = tk.LabelFrame(mid, text=\" Guided Maintenance Profiles \", font=FONTS[\"subhead\"],\n                                  fg=C[\"accent4\"], bg=C[\"card\"])\n        prof_card.grid(row=5, column=0, columnspan=2, sticky=\"ew\", pady=(6, 0))\n        prof_cols = (\"Profile\", \"Risk\", \"Minutes\", \"Menus\")\n        self.safety_profile_tree = ttk.Treeview(\n            prof_card, columns=prof_cols, show=\"headings\", height=5, style=\"Custom.Treeview\")\n        for col, w in zip(prof_cols, (190, 80, 80, 520)):\n            self.safety_profile_tree.heading(col, text=col)\n            self.safety_profile_tree.column(col, width=w, anchor=\"w\")\n        self.safety_profile_tree.pack(fill=\"both\", expand=True, padx=8, pady=8)\n        prof_btns = tk.Frame(prof_card, bg=C[\"card\"])\n        prof_btns.pack(fill=\"x\", padx=8, pady=(0, 8))\n        self._btn(prof_btns, \"View Workflow\", C[\"btn_info\"], self._safety_show_selected_profile).pack(side=\"left\", padx=4)\n        self._btn(prof_btns, \"Open First Menu\", C[\"btn_chip\"], self._safety_open_selected_profile_menu).pack(side=\"left\", padx=4)\n\n        audit_card = tk.LabelFrame(mid, text=\" Product Audit Heat Map \", font=FONTS[\"subhead\"],\n                                   fg=C[\"accent\"], bg=C[\"card\"])\n        audit_card.grid(row=6, column=0, columnspan=2, sticky=\"ew\", pady=(6, 0))\n        audit_cols = (\"Menu\", \"Maturity\", \"Risk\", \"Top upgrade\")\n        self.safety_audit_tree = ttk.Treeview(\n            audit_card, columns=audit_cols, show=\"headings\", height=7, style=\"Custom.Treeview\")\n        for col, w in zip(audit_cols, (220, 80, 70, 520)):\n            self.safety_audit_tree.heading(col, text=col)\n            self.safety_audit_tree.column(col, width=w, anchor=\"w\")\n        self.safety_audit_tree.pack(fill=\"both\", expand=True, padx=8, pady=8)\n\n        self.after(300, self._safety_refresh_all)\n        return frame\n\n    def _build_recommendations_payload(self, limit=10):\n        engine = getattr(self, \"recommendation_engine\", None)\n        audit_engine = getattr(self, \"product_audit_engine\", None)\n        if not engine or not audit_engine:\n            return {\"items\": []}\n        try:\n            return engine.build(\n                getattr(self, \"_last_health_report\", None),\n                audit_engine.list_audits(),\n                limit=limit,\n            )\n        except Exception:\n            return {\"items\": []}\n\n    def _refresh_intelligent_recommendations(self):\n        tree = getattr(self, \"dashboard_recommendation_tree\", None)\n        if not tree:\n            return\n        for iid in tree.get_children():\n            tree.delete(iid)\n        payload = self._build_recommendations_payload(limit=8)\n        for item in payload.get(\"items\", []):\n            tree.insert(\n                \"\", \"end\",\n                values=(\n                    str(item.get(\"priority\", \"\")).upper(),\n                    item.get(\"menu\", \"\"),\n                    item.get(\"action\", \"\"),\n                ),\n            )\n\n    def _recommendations_as_text(self, limit=12):\n        payload = self._build_recommendations_payload(limit=limit)\n        lines = []\n        for item in payload.get(\"items\", []):\n            lines.append(\n                f\"[{str(item.get('priority', '')).upper()}] {item.get('menu', '')}: \"\n                f\"{item.get('title', '')} - {item.get('action', '')}\"\n            )\n        return \"\\n\".join(lines) if lines else \"No recommendations yet. Run a health scan first.\"\n\n    def _safety_refresh_all(self):\n        self._refresh_health_score_card()\n        self._safety_refresh_rollback_tree()\n        self._safety_refresh_restore_points()\n        self._safety_refresh_sessions_tree()\n        self._safety_refresh_timeline()\n        self._safety_refresh_menu_map()\n        self._safety_refresh_product_audit()\n        self._safety_refresh_profiles()\n        if hasattr(self, \"dashboard_recommendation_tree\"):\n            self._refresh_intelligent_recommendations()\n        if self._last_health_report and self._last_health_report.get(\"recommendations\"):\n            text = \"\\n\".join(f\"\u2022 {r}\" for r in self._last_health_report[\"recommendations\"])\n            self.safety_recommendations.config(text=text, fg=C[\"text\"])\n        elif hasattr(self, \"safety_recommendations\"):\n            self.safety_recommendations.config(text=self._recommendations_as_text(limit=6), fg=C[\"text\"])\n\n    def _safety_refresh_menu_map(self):\n        if not hasattr(self, \"safety_menu_map_tree\"):\n            return\n        for iid in self.safety_menu_map_tree.get_children():\n            self.safety_menu_map_tree.delete(iid)\n        engine = getattr(self, \"menu_introspection_engine\", None)\n        if not engine:\n            return\n        try:\n            data = engine.scan()\n        except Exception:\n            return\n        for menu in data.get(\"menus\", []):\n            self.safety_menu_map_tree.insert(\n                \"\", \"end\",\n                values=(\n                    getattr(menu, \"category\", \"\"),\n                    getattr(menu, \"label\", \"\"),\n                    len(getattr(menu, \"tabs\", []) or []),\n                    len(getattr(menu, \"buttons\", []) or []),\n                    len(getattr(menu, \"options\", []) or []),\n                ),\n            )\n\n    def _safety_export_menu_map(self):\n        engine = getattr(self, \"menu_introspection_engine\", None)\n        if not engine:\n            messagebox.showerror(\"Menu Map\", \"Menu introspection engine is unavailable.\")\n            return\n        fpath = filedialog.asksaveasfilename(\n            defaultextension=\".md\",\n            filetypes=[(\"Markdown Report\", \"*.md\"), (\"Text Report\", \"*.txt\")],\n            title=\"Save Detected Software Menu Map\",\n        )\n        if not fpath:\n            return\n        try:\n            with open(fpath, \"w\", encoding=\"utf-8\") as f:\n                f.write(engine.to_markdown())\n            self._audit_event(\"menu_map_exported\", {\"path\": fpath})\n            messagebox.showinfo(\"Menu Map Exported\", f\"Detected software map saved:\\n\\n{fpath}\")\n            self._set_status(\"Detected software map exported.\", C[\"success\"])\n        except Exception as e:\n            messagebox.showerror(\"Export Failed\", str(e))\n\n    def _safety_refresh_profiles(self):\n        if not hasattr(self, \"safety_profile_tree\"):\n            return\n        for iid in self.safety_profile_tree.get_children():\n            self.safety_profile_tree.delete(iid)\n        engine = getattr(self, \"maintenance_profile_engine\", None)\n        if not engine:\n            return\n        for profile in engine.list_profiles():\n            self.safety_profile_tree.insert(\n                \"\", \"end\",\n                iid=profile.key,\n                values=(\n                    profile.name,\n                    str(profile.risk).upper(),\n                    profile.estimated_minutes,\n                    \", \".join(profile.menus),\n                ),\n            )\n\n    def _safety_selected_profile(self):\n        tree = getattr(self, \"safety_profile_tree\", None)\n        engine = getattr(self, \"maintenance_profile_engine\", None)\n        if not tree or not engine:\n            return None\n        sel = tree.selection()\n        if not sel:\n            messagebox.showwarning(\"Maintenance Profile\", \"Select a profile first.\")\n            return None\n        return engine.get(sel[0])\n\n    def _safety_show_selected_profile(self):\n        profile = self._safety_selected_profile()\n        if not profile:\n            return\n        msg = [\n            f\"{profile.name}\",\n            \"\",\n            profile.purpose,\n            \"\",\n            f\"Risk: {profile.risk.upper()}\",\n            f\"Estimated time: {profile.estimated_minutes} minutes\",\n            \"\",\n            \"Workflow:\",\n        ]\n        msg.extend(f\"- {action}\" for action in profile.actions)\n        msg.append(\"\")\n        msg.append(\"Protections:\")\n        msg.extend(f\"- {item}\" for item in profile.protections)\n        messagebox.showinfo(\"Guided Maintenance Profile\", \"\\n\".join(msg))\n\n    def _safety_open_selected_profile_menu(self):\n        profile = self._safety_selected_profile()\n        if not profile or not profile.menus:\n            return\n        menu_name = profile.menus[0]\n        mapping = {\n            \"Dashboard\": \"dashboard\",\n            \"Junk Cleaner\": \"cleaner\",\n            \"Safety Center\": \"safety_center\",\n            \"RAM + Services\": \"memory\",\n            \"Startup + Scheduler\": \"startup\",\n            \"Power Plan\": \"power\",\n            \"Printer + Driver\": \"printer\",\n            \"HDD/SSD + File Recovery\": \"hdd_repair\",\n            \"Event Viewer\": \"events\",\n        }\n        self._show_section(mapping.get(menu_name, \"safety_center\"))\n\n    def _safety_refresh_product_audit(self):\n        if not hasattr(self, \"safety_audit_tree\"):\n            return\n        for iid in self.safety_audit_tree.get_children():\n            self.safety_audit_tree.delete(iid)\n        engine = getattr(self, \"product_audit_engine\", None)\n        if not engine:\n            return\n        for audit in sorted(engine.list_audits(), key=lambda a: a.risk_score(), reverse=True):\n            self.safety_audit_tree.insert(\n                \"\", \"end\",\n                values=(\n                    audit.title,\n                    audit.maturity_score(),\n                    audit.risk_score(),\n                    audit.redesign_plan[0] if audit.redesign_plan else audit.final_design,\n                ),\n            )\n\n    def _safety_export_product_audit(self):\n        engine = getattr(self, \"product_audit_engine\", None)\n        if not engine:\n            messagebox.showerror(\"Audit\", \"Product audit engine is unavailable.\")\n            return\n        fpath = filedialog.asksaveasfilename(\n            defaultextension=\".md\",\n            filetypes=[(\"Markdown Report\", \"*.md\"), (\"Text Report\", \"*.txt\")],\n            title=\"Save Professional Product Audit\",\n        )\n        if not fpath:\n            return\n        try:\n            with open(fpath, \"w\", encoding=\"utf-8\") as f:\n                f.write(engine.to_markdown())\n            self._audit_event(\"product_audit_exported\", {\"path\": fpath})\n            messagebox.showinfo(\"Audit Exported\", f\"Professional product audit saved:\\n\\n{fpath}\")\n            self._set_status(\"Professional product audit exported.\", C[\"success\"])\n        except Exception as e:\n            messagebox.showerror(\"Export Failed\", str(e))\n\n    def _safety_refresh_rollback_tree(self):\n        if not hasattr(self, \"safety_rollback_tree\"):\n            return\n        for iid in self.safety_rollback_tree.get_children():\n            self.safety_rollback_tree.delete(iid)\n        vault = getattr(self, \"rollback_vault\", None)\n        if not vault:\n            return\n        for s in vault.list_sessions(40):\n            self.safety_rollback_tree.insert(\n                \"\", \"end\",\n                values=(s.get(\"id\", \"\"), s.get(\"items\", 0), s.get(\"created\", \"\")),\n            )\n\n    def _safety_refresh_sessions_tree(self):\n        if not hasattr(self, \"safety_session_tree\"):\n            return\n        for iid in self.safety_session_tree.get_children():\n            self.safety_session_tree.delete(iid)\n        mgr = getattr(self, \"recovery_session_manager\", None)\n        if not mgr:\n            return\n        for s in mgr.list_sessions(include_completed=True, limit=40):\n            self.safety_session_tree.insert(\n                \"\", \"end\",\n                values=(\n                    (s.get(\"id\", \"\") or \"\")[:12] + \"\u2026\",\n                    s.get(\"kind\", \"\"),\n                    s.get(\"status\", \"\"),\n                    s.get(\"started\", \"\"),\n                ),\n            )\n\n    def _safety_refresh_restore_points(self):\n        if not hasattr(self, \"safety_restore_tree\"):\n            return\n        for iid in self.safety_restore_tree.get_children():\n            self.safety_restore_tree.delete(iid)\n        mgr = getattr(self, \"restore_point_manager\", None)\n        if not mgr:\n            self.safety_restore_tree.insert(\"\", \"end\", values=(\"N/A\", \"Restore point manager unavailable\", \"\"))\n            return\n        points = mgr.list_recent(12)\n        if not points:\n            self.safety_restore_tree.insert(\"\", \"end\", values=(\"None\", \"No recent restore points found\", \"\"))\n            return\n        for p in points:\n            self.safety_restore_tree.insert(\n                \"\", \"end\",\n                values=(\n                    str(p.get(\"SequenceNumber\", \"\")),\n                    str(p.get(\"Description\", \"\")),\n                    str(p.get(\"Created\", \"\")),\n                ),\n            )\n\n    def _open_system_restore(self):\n        try:\n            if sys.platform != \"win32\":\n                messagebox.showwarning(\"System Restore\", \"System Restore is only available on Windows.\")\n                return\n            self._run_cmd(\"rstrui.exe\", timeout=10)\n            self._set_status(\"System Restore wizard opened.\", C[\"success\"])\n        except Exception as e:\n            messagebox.showerror(\"System Restore\", f\"Unable to open System Restore: {e}\")\n            self._set_status(\"Failed to open System Restore.\", C[\"error\"])\n\n    def _safety_refresh_timeline(self):\n        if not hasattr(self, \"safety_timeline\"):\n            return\n        logger = getattr(self, \"structured_logger\", None)\n        rows = logger.read_recent(80) if logger else []\n        self.safety_timeline.config(state=\"normal\")\n        self.safety_timeline.delete(\"1.0\", \"end\")\n        for rec in reversed(rows):\n            ts = rec.get(\"ts\", \"\")\n            action = rec.get(\"action\") or rec.get(\"type\") or rec.get(\"message\", \"\")\n            cat = rec.get(\"category\", rec.get(\"event\", \"\"))\n            line = f\"[{ts}] {cat}/{action}\\n\"\n            self.safety_timeline.insert(\"end\", line)\n        self.safety_timeline.config(state=\"disabled\")\n\n    def _safety_restore_rollback(self):\n        sel = self.safety_rollback_tree.selection() if hasattr(self, \"safety_rollback_tree\") else ()\n        if not sel:\n            messagebox.showwarning(\"Rollback\", \"Select a rollback session first.\")\n            return\n        sid = self.safety_rollback_tree.item(sel[0])[\"values\"][0]\n        if not messagebox.askyesno(\n            \"Restore Rollback\",\n            f\"Restore files/registry from session?\\n\\n{sid}\\n\\nThis overwrites current data.\",\n        ):\n            return\n        ok, msg = self.rollback_vault.restore_session(sid)\n        color = C[\"success\"] if ok else C[\"error\"]\n        messagebox.showinfo(\"Rollback\", msg)\n        self._audit_event(\"rollback_restored\", {\"session\": sid, \"ok\": ok})\n        self._set_status(msg, color)\n\n    def _safety_open_rollback_dir(self):\n        path = getattr(self, \"rollback_dir\", \"\")\n        if path and os.path.isdir(path):\n            os.startfile(path)\n        else:\n            messagebox.showinfo(\"Rollback Vault\", \"Vault folder not initialized yet.\")\n\n    def _safety_clear_session(self):\n        sel = self.safety_session_tree.selection() if hasattr(self, \"safety_session_tree\") else ()\n        if not sel:\n            messagebox.showwarning(\"Sessions\", \"Select a session row first.\")\n            return\n        short_id = str(self.safety_session_tree.item(sel[0])[\"values\"][0]).replace(\"\u2026\", \"\")\n        mgr = self.recovery_session_manager\n        for s in mgr.list_sessions(include_completed=True, limit=100):\n            if (s.get(\"id\") or \"\").startswith(short_id):\n                mgr.complete(s[\"id\"], status=\"completed\")\n                break\n        self._safety_refresh_sessions_tree()\n        self._set_status(\"Session marked completed\", C[\"success\"])\n\n    def _safety_clear_crash_marker(self):\n        try:\n            self.crash_recovery.clear_running()\n            self._log(\"Crash recovery marker cleared silently.\", \"OK\")\n            self._set_status(\"Crash recovery marker cleared\", C[\"success\"])\n        except Exception as e:\n            messagebox.showerror(\"Error\", str(e))\n\n    def _build_activation(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udd11 Windows Activation\", \"Real status check + legal activation actions\")\n        top = tk.Frame(frame, bg=C[\"card\"])\n        top.pack(fill=\"x\", padx=16, pady=10)\n        self.activation_status_lbl = tk.Label(\n            top, text=\"Activation status: checking...\",\n            font=FONTS[\"subhead\"], fg=C[\"accent4\"], bg=C[\"card\"], anchor=\"w\", justify=\"left\"\n        )\n        self.activation_status_lbl.pack(fill=\"x\", padx=10, pady=(8, 4))\n        self.activation_detail_lbl = tk.Label(\n            top, text=\"\",\n            font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], anchor=\"w\", justify=\"left\", wraplength=900\n        )\n        self.activation_detail_lbl.pack(fill=\"x\", padx=10, pady=(0, 8))\n\n        key_row = tk.Frame(top, bg=C[\"card\"])\n        key_row.pack(fill=\"x\", padx=10, pady=(0, 8))\n        tk.Label(key_row, text=\"Product Key (XXXXX-XXXXX-XXXXX-XXXXX-XXXXX):\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\", padx=(0, 8))\n        self.activation_key_entry = tk.Entry(key_row, width=40, font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"])\n        self.activation_key_entry.pack(side=\"left\", padx=(0, 8))\n        self._btn(key_row, \"Install Key\", C[\"btn_warn\"], self._activation_install_key).pack(side=\"left\", padx=4)\n        self._btn(key_row, \"Activate Online\", C[\"btn_info\"], self._activation_online).pack(side=\"left\", padx=4)\n\n        self._action_card_grid(frame, [\n            (\"\ud83d\udd04\", \"Refresh Status\",         \"Activation status check karo\",     C[\"btn\"],      self._refresh_activation_status),\n            (\"\u2699\",  \"Open Settings\",          \"Windows activation settings kholo\",C[\"btn_info\"], self._open_activation_settings),\n        ], cols=2)\n\n        log_wrap = tk.Frame(frame, bg=C[\"card\"])\n        log_wrap.pack(fill=\"both\", expand=True, padx=16, pady=(0, 10))\n        tk.Label(log_wrap, text=\"  Activation Log\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8, 4), padx=8)\n        self.activation_log = self._scrolled_text(log_wrap, height=16)\n        self.after(100, self._refresh_activation_status)\n        return frame\n\n    def _refresh_activation_status(self):\n        self._set_status(\"Checking Windows activation status...\", C[\"accent4\"])\n        self._launch_job(\"activation_status_refresh\", self._do_refresh_activation_status)\n\n    def _do_refresh_activation_status(self):\n        try:\n            ps_cmd = (\n                'powershell -NoProfile -ExecutionPolicy Bypass -Command \"'\n                '$lic=Get-CimInstance SoftwareLicensingProduct | '\n                'Where-Object {$_.PartialProductKey -and $_.ApplicationID -eq ''55c92734-d682-4d71-983e-d6ec3f16059f''} | '\n                'Select-Object -First 1 Name,Description,LicenseStatus,PartialProductKey; '\n                'if($lic){'\n                '$map=@{0=''Unlicensed'';1=''Licensed'';2=''OOBGrace'';3=''OOTGrace'';4=''NonGenuineGrace'';5=''Notification'';6=''ExtendedGrace''}; '\n                '$status=if($map.ContainsKey([int]$lic.LicenseStatus)){$map[[int]$lic.LicenseStatus]}else{''Unknown''}; '\n                'Write-Output (''STATUS=''+$status); '\n                'Write-Output (''NAME=''+$lic.Name); '\n                'Write-Output (''CHANNEL=''+$lic.Description); '\n                'Write-Output (''PARTIAL=''+$lic.PartialProductKey)'\n                '} else { Write-Output ''STATUS=Unknown'' }\"'\n            )\n            out, code = self._run_cmd(ps_cmd, timeout=90)\n            status_line = \"Unknown\"\n            name_line = \"\"\n            channel_line = \"\"\n            partial_line = \"\"\n            for ln in (out or \"\").splitlines():\n                s = ln.strip()\n                if s.startswith(\"STATUS=\"):\n                    status_line = s.split(\"=\", 1)[1].strip() or \"Unknown\"\n                elif s.startswith(\"NAME=\"):\n                    name_line = s.split(\"=\", 1)[1].strip()\n                elif s.startswith(\"CHANNEL=\"):\n                    channel_line = s.split(\"=\", 1)[1].strip()\n                elif s.startswith(\"PARTIAL=\"):\n                    partial_line = s.split(\"=\", 1)[1].strip()\n\n            color = C[\"warning\"]\n            if status_line.lower() == \"licensed\":\n                color = C[\"success\"]\n            elif status_line.lower() in (\"notification\", \"unlicensed\", \"nongenuinegrace\"):\n                color = C[\"error\"]\n\n            detail_parts = []\n            if name_line:\n                detail_parts.append(f\"Edition: {name_line}\")\n            if channel_line:\n                detail_parts.append(f\"Channel: {channel_line}\")\n            if partial_line:\n                detail_parts.append(f\"Partial key: *****-*****-*****-*****-{partial_line}\")\n            if code not in (0, None):\n                detail_parts.append(f\"(Status command exit code: {code})\")\n            details = \"\\n\".join(detail_parts) if detail_parts else \"No detailed activation data available.\"\n\n            self.after(0, lambda: self.activation_status_lbl.config(text=f\"Activation status: {status_line}\", fg=color))\n            self.after(0, lambda: self.activation_detail_lbl.config(text=details))\n            self.after(0, lambda: self._append_log(self.activation_log, f\"Status refreshed: {status_line}\", color))\n            self.after(0, lambda: self._set_status(\"Activation status updated\", C[\"success\"]))\n        except Exception as e:\n            self.after(0, lambda: self._append_log(self.activation_log, f\"Status check failed: {e}\", C[\"error\"]))\n            self.after(0, lambda: self._set_status(\"Activation status check failed\", C[\"error\"]))\n\n    def _activation_install_key(self):\n        key = (self.activation_key_entry.get() if hasattr(self, \"activation_key_entry\") else \"\").strip().upper()\n        if not re.match(r\"^[A-Z0-9]{5}(?:-[A-Z0-9]{5}){4}$\", key):\n            messagebox.showerror(\"Invalid Key\", \"Valid 25-char key format enter karein:\\nXXXXX-XXXXX-XXXXX-XXXXX-XXXXX\")\n            return\n        if not messagebox.askyesno(\"Install Product Key\", f\"Install this key?\\n\\n{key}\\n\\nProceed only if this is your legal license key.\"):\n            return\n        self._set_status(\"Installing product key...\", C[\"accent4\"])\n        self._launch_job(\"activation_install_key\", self._do_activation_install_key, key)\n\n    def _do_activation_install_key(self, key):\n        cmd = f'cscript //nologo \"%windir%\\\\system32\\\\slmgr.vbs\" /ipk {key}'\n        out, code = self._run_cmd(cmd, timeout=180)\n        color = C[\"success\"] if code == 0 else C[\"error\"]\n        msg = out.strip() if out else (\"Product key installed.\" if code == 0 else \"Product key install failed.\")\n        self.after(0, lambda: self._append_log(self.activation_log, msg, color))\n        self.after(0, lambda: self._set_status(\"Product key installed\" if code == 0 else \"Product key install failed\", color))\n        if code == 0:\n            self.after(500, self._refresh_activation_status)\n\n    def _activation_online(self):\n        if not messagebox.askyesno(\"Activate Windows\", \"Try online activation now? Internet connection required.\"):\n            return\n        self._set_status(\"Activating Windows...\", C[\"accent4\"])\n        self._launch_job(\"activation_online\", self._do_activation_online)\n\n    def _do_activation_online(self):\n        cmd = 'cscript //nologo \"%windir%\\\\system32\\\\slmgr.vbs\" /ato'\n        out, code = self._run_cmd(cmd, timeout=240)\n        color = C[\"success\"] if code == 0 else C[\"error\"]\n        msg = out.strip() if out else (\"Activation attempt finished.\" if code == 0 else \"Activation attempt failed.\")\n        self.after(0, lambda: self._append_log(self.activation_log, msg, color))\n        self.after(0, lambda: self._set_status(\"Activation completed\" if code == 0 else \"Activation failed\", color))\n        self.after(500, self._refresh_activation_status)\n\n    def _open_activation_settings(self):\n        out, code = self._run_cmd(\"start ms-settings:activation\")\n        if code == 0:\n            self._append_log(self.activation_log, \"Opened Windows Activation settings.\", C[\"success\"])\n        else:\n            self._append_log(self.activation_log, f\"Could not open settings: {out}\", C[\"error\"])\n\n    def _live_speed_test(self):\n        self._set_status(\"Checking Internet Speed...\", C[\"accent4\"])\n        self._launch_job(\"speed_test\", self._do_speed_test)\n\n    def _do_speed_test(self):\n        import urllib.request\n        import urllib.error\n        targets = [\n            (\"http://speedtest.tele2.net/10MB.zip\", 10),\n            (\"http://ipv4.download.thinkbroadband.com/10MB.zip\", 10),\n            (\"http://proof.ovh.net/files/10Mb.dat\", 10),\n            (\"http://speedtest.tele2.net/1MB.zip\", 1),\n        ]\n        tmp_file = os.path.join(tempfile.gettempdir(), \"godawari_speedtest.tmp\")\n        self._log(\"Starting internet speed test...\", \"INFO\")\n        self._set_status(\"Running speed test...\", C[\"accent4\"])\n        for url, expected_mb in targets:\n            try:\n                start = time.perf_counter()\n                with urllib.request.urlopen(url, timeout=30) as response, open(tmp_file, \"wb\") as out_file:\n                    downloaded = 0\n                    while True:\n                        chunk = response.read(65536)\n                        if not chunk:\n                            break\n                        out_file.write(chunk)\n                        downloaded += len(chunk)\n                elapsed = time.perf_counter() - start\n                if elapsed &lt; 0.1:\n                    continue\n                actual_mb = downloaded / (1024 * 1024)\n                speed_mbps = (actual_mb * 8) / elapsed\n                try:\n                    os.remove(tmp_file)\n                except Exception:\n                    pass\n                msg = (f\"\u2705 Download Speed: {speed_mbps:.2f} Mbps \"\n                       f\"({actual_mb:.1f} MB in {elapsed:.1f}s from {url.split('/')[2]})\")\n                self._set_status(msg, C[\"success\"])\n                self._log(msg, \"OK\")\n                return speed_mbps\n            except Exception as e:\n                self._log(f\"Speed test URL failed ({url}): {e}\", \"WARN\")\n                continue\n        self._set_status(\"Speed test failed \u2014 Internet check karo\", C[\"error\"])\n        self._log(\"All speed test URLs failed.\", \"ERR\")\n        return 0.0\n\n    def _refresh_dashboard(self):\n        def task():\n            try:\n                cpu = psutil.cpu_percent(interval=None)\n                vm = psutil.virtual_memory()\n                du = psutil.disk_usage(\"/\")\n                up = time.time() - psutil.boot_time()\n                up_str = str(datetime.timedelta(seconds=int(up)))\n                self.dash_cards[\"cpu\"]._value_lbl.config(text=f\"{cpu:.1f}%\")\n                self.dash_cards[\"cpu\"]._bar.config(value=cpu)\n                self.dash_cards[\"ram\"]._value_lbl.config(text=f\"{vm.percent:.1f}%\")\n                self.dash_cards[\"ram\"]._bar.config(value=vm.percent)\n                self.dash_cards[\"disk\"]._value_lbl.config(text=f\"{du.percent:.1f}%\")\n                self.dash_cards[\"disk\"]._bar.config(value=du.percent)\n                self.dash_cards[\"uptime\"]._value_lbl.config(text=up_str)\n                if hasattr(self, \"dashboard_workflow_lbl\"):\n                    report = getattr(self, \"_last_health_report\", None)\n                    if report:\n                        score = report.get(\"score\")\n                        recs = report.get(\"recommendations\", []) or []\n                        rollout = [f\"Health {score}/100\" if score is not None else \"Health scan ready\"]\n                        if recs:\n                            rollout.append(f\"{len(recs)} action(s) ready\")\n                            rollout.append(recs[0])\n                        self.dashboard_workflow_lbl.config(text=\" \u2022 \".join(rollout), fg=C[\"text\"])\n                    else:\n                        self.dashboard_workflow_lbl.config(\n                            text=\"Health scan not run yet \u2014 use One-Click Health Scan or Safety Center to generate guided actions.\",\n                            fg=C[\"text_dim\"],\n                        )\n                for item in self.proc_tree.get_children():\n                    self.proc_tree.delete(item)\n                procs = sorted(psutil.process_iter(['pid','name','cpu_percent','memory_info','status']),\n                               key=lambda p: p.info.get('cpu_percent',0) or 0, reverse=True)\n                for p in procs[:25]:\n                    try:\n                        mem = round((p.info.get('memory_info') or psutil.Process(p.info['pid']).memory_info()).rss / (1024**2), 1)\n                        self.proc_tree.insert(\"\", \"end\", values=(p.info['pid'], p.info['name'] or \"?\", f\"{p.info.get('cpu_percent',0):.1f}%\", f\"{mem} MB\", p.info.get('status','?')))\n                    except:\n                        pass\n            except Exception as e:\n                self._log(str(e), \"ERR\")\n        self._launch_job(\"dashboard_refresh\", task)\n\n    def _start_real_time_graph(self):\n        def update_graph():\n            try:\n                cpu = psutil.cpu_percent(interval=None)\n                ram = psutil.virtual_memory().percent\n                self.graph_data[\"cpu\"].append(cpu)\n                self.graph_data[\"ram\"].append(ram)\n                if len(self.graph_data[\"cpu\"]) &gt; 60:\n                    self.graph_data[\"cpu\"].pop(0)\n                    self.graph_data[\"ram\"].pop(0)\n                self._draw_graph()\n            except:\n                pass\n            self.after(2000, update_graph)\n        update_graph()\n\n    def _draw_graph(self):\n        try:\n            self.graph_canvas.delete(\"all\")\n            w = self.graph_canvas.winfo_width()\n            h = 80\n            if w &lt; 10:\n                return\n            n = len(self.graph_data[\"cpu\"])\n            if n &lt; 2:\n                return\n            step = w / max(1, n - 1)\n            cpu_pts = [(i*step, h - (self.graph_data[\"cpu\"][i]/100)*h) for i in range(n)]\n            ram_pts = [(i*step, h - (self.graph_data[\"ram\"][i]/100)*h) for i in range(n)]\n            self.graph_canvas.create_line(cpu_pts, fill=C[\"accent\"], width=2, smooth=True)\n            self.graph_canvas.create_line(ram_pts, fill=C[\"success\"], width=2, smooth=True)\n            self.graph_canvas.create_text(5, 5, anchor=\"nw\", text=f\"CPU (Gold): {self.graph_data['cpu'][-1]:.1f}%  |  RAM (Green): {self.graph_data['ram'][-1]:.1f}%\",\n                                          fill=C[\"text_dim\"], font=FONTS[\"small\"])\n        except:\n            pass\n\n    # ---------- SHOP MODE ----------\n    def _build_shop_mode(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udee0 Repair Shop Mode\", \"Real Customer diagnosis &amp; tune-up\")\n        top = tk.Frame(frame, bg=C[\"card\"])\n        top.pack(fill=\"x\", padx=16, pady=8)\n        self.shop_customer_name = tk.Entry(top, width=24, font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"])\n        self.shop_customer_mobile = tk.Entry(top, width=18, font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"])\n        self.shop_issue = tk.Entry(top, width=55, font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"])\n        for label, widget in [(\"Customer\", self.shop_customer_name), (\"Mobile\", self.shop_customer_mobile), (\"Issue\", self.shop_issue)]:\n            tk.Label(top, text=label, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\", padx=(8,3))\n            widget.pack(side=\"left\", padx=(0,8), pady=8)\n        self.shop_issue.insert(0, \"System hang / slow\")\n        self._action_card_grid(frame, [\n            (\"\u25b6\",  \"Start Job\",              \"Naya customer job shuru karo\",               C[\"btn_info\"],   self._shop_start_job),\n            (\"\ud83d\udd0d\", \"Diagnose Slow PC\",        \"CPU, RAM, Startup, Disk check\",              C[\"btn_danger\"], self._shop_slow_pc_diagnosis),\n            (\"\u26a1\", \"One-Click Tune-Up\",       \"Cache clear + RAM boost + Restore point\",    C[\"btn_warn\"],   self._shop_one_click_tuneup),\n            (\"\ud83d\udd34\", \"Malware + Driver Scan\",   \"Malware scan + Driver repair ek saath\",      C[\"btn_chip\"],   self._shop_malware_driver_combo),\n            (\"\ud83d\udcbe\", \"Disk Health + Backup\",    \"SMART check + Backup combo\",                 C[\"btn_danger\"], self._shop_disk_backup_combo),\n            (\"\ud83c\udf10\", \"Browser + Update Repair\", \"Browser reset + Windows update fix\",         C[\"btn_info\"],   self._shop_browser_update_combo),\n            (\"\u2699\",  \"Service Preset Apply\",   \"Recommended service config lagao\",           C[\"btn_hw\"],     self._shop_service_preset),\n            (\"\ud83d\udcc4\", \"Export Customer Report\",  \"Customer job report save karo\",              C[\"accent2\"],    self._shop_export_customer_report),\n        ], cols=5)\n        self.shop_log = self._scrolled_text(frame, height=23)\n        self.shop_findings = []\n        return frame\n\n    def _shop_start_job(self):\n        self.shop_findings = []\n        self.shop_log.config(state=\"normal\")\n        self.shop_log.delete(\"1.0\",\"end\")\n        self.shop_log.config(state=\"disabled\")\n        self._shop_log(f\"Job started | Customer: {self.shop_customer_name.get()} | Issue: {self.shop_issue.get()}\", \"OK\")\n\n    def _shop_log(self, msg, level=\"INFO\"):\n        color = {\"INFO\": C[\"text\"], \"OK\": C[\"success\"], \"WARN\": C[\"warning\"], \"ERR\": C[\"error\"]}.get(level, C[\"text\"])\n        line = f\"[{datetime.datetime.now().strftime('%H:%M:%S')}] {msg}\"\n        self.shop_findings.append(line)\n        self._append_log(self.shop_log, line, color)\n        self._log(msg, level)\n\n    def _shop_slow_pc_diagnosis(self):\n        self._shop_log(\"\ud83d\udd0d Slow PC Auto Diagnosis started...\", \"INFO\")\n        self._launch_job(\"shop_slow_pc_diagnosis\", self._do_shop_slow_pc_diagnosis)\n\n    def _do_shop_slow_pc_diagnosis(self):\n        self._shop_log(\"1. Checking CPU &amp; RAM Load...\", \"INFO\")\n        cpu = psutil.cpu_percent(interval=None)\n        ram = psutil.virtual_memory()\n        if cpu &gt; 80:\n            self._shop_log(f\"   \u26a0 HIGH CPU USAGE DETECTED: {cpu}%\", \"ERR\")\n        else:\n            self._shop_log(f\"   \u2705 CPU Usage Normal: {cpu}%\", \"OK\")\n        if ram.percent &gt; 85:\n            self._shop_log(f\"   \u26a0 HIGH RAM USAGE DETECTED: {ram.percent}% (Free: {self._fmt_size(ram.available)})\", \"ERR\")\n        else:\n            self._shop_log(f\"   \u2705 RAM Usage Normal: {ram.percent}%\", \"OK\")\n        self._shop_log(\"2. Checking Startup Bloatwares...\", \"INFO\")\n        bloat_count = 0\n        try:\n            key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, r\"Software\\Microsoft\\Windows\\CurrentVersion\\Run\", 0, winreg.KEY_READ)\n            i = 0\n            while True:\n                try:\n                    name, value, _ = winreg.EnumValue(key, i)\n                    if any(x in value.lower() for x in ['zoom', 'skype', 'spotify', 'discord', 'teams']):\n                        self._shop_log(f\"   \u26a0 Bloatware Found: {name}\", \"WARN\")\n                        bloat_count += 1\n                    i += 1\n                except OSError:\n                    break\n            winreg.CloseKey(key)\n        except:\n            pass\n        if bloat_count == 0:\n            self._shop_log(\"   \u2705 No major bloatware in startup\", \"OK\")\n        self._shop_log(\"3. Checking Disk Health (SMART)...\", \"INFO\")\n        out, _ = self._run_cmd(\"wmic diskdrive get status,model /format:list\")\n        if \"OK\" in out:\n            self._shop_log(\"   \u2705 Disk SMART Status: OK\", \"OK\")\n        else:\n            self._shop_log(f\"   \u26a0 Disk Status Check: {out[:100]}\", \"WARN\")\n        self._shop_log(\"\ud83c\udf89 Diagnosis Complete!\", \"OK\")\n\n    def _shop_one_click_tuneup(self):\n        if messagebox.askyesno(\"One Click Shop Tune-Up\", \"Restore point + cache clear + RAM boost run karna hai?\"):\n            if self._create_restore_point(\"One Click Shop Tune-Up se pehle\"):\n                self._shop_log(\"One Click Tune-Up started\", \"INFO\")\n                self._launch_job(\"shop_tuneup\", self._do_shop_tuneup)\n\n    def _do_shop_tuneup(self):\n        self._shop_log(\"Step 1: Clearing Temp Files...\", \"INFO\")\n        self._delete_folder_contents(os.environ.get(\"TEMP\", \"\"))\n        self._delete_folder_contents(r\"C:\\Windows\\Temp\")\n        self._shop_log(\"Step 2: Boosting RAM...\", \"INFO\")\n        gc.collect()\n        try:\n            kernel32 = ctypes.windll.kernel32\n            psapi = ctypes.windll.psapi\n            for proc in psutil.process_iter(['pid']):\n                pid = proc.info.get('pid')\n                if pid and pid not in (0,4):\n                    handle = kernel32.OpenProcess(0x0400|0x0100|0x0010, False, int(pid))\n                    if handle:\n                        psapi.EmptyWorkingSet(handle)\n                        kernel32.CloseHandle(handle)\n        except:\n            pass\n        self._shop_log(\"Step 3: Disabling heavy services...\", \"INFO\")\n        self._run_cmd('sc stop \"SysMain\"')\n        self._shop_log(\"\u2705 Tune-Up complete!\", \"OK\")\n\n    def _shop_malware_pup_scan(self):\n        self._shop_log(\"\ud83d\udd0d Scanning for Malware Clues &amp; PUPs...\", \"INFO\")\n        self._launch_job(\"shop_malware_scan\", self._do_malware_scan)\n\n    def _do_malware_scan(self):\n        suspicious_exts = ['.exe', '.bat', '.cmd', '.ps1', '.vbs', '.js']\n        risk_paths = [os.environ.get('TEMP', ''), os.environ.get('APPDATA', ''), os.path.join(os.environ.get('LOCALAPPDATA', ''), 'Temp')]\n        threats = 0\n        for r_path in risk_paths:\n            if not os.path.exists(r_path):\n                continue\n            for root, dirs, files in os.walk(r_path):\n                if threats &gt; 20:\n                    break\n                for f in files:\n                    if os.path.splitext(f)[1].lower() in suspicious_exts:\n                        full_path = os.path.join(root, f)\n                        if 'microsoft' in full_path.lower():\n                            continue\n                        self._shop_log(f\"\u26a0 Suspicious Script/Exe: {full_path}\", \"WARN\")\n                        threats += 1\n        if threats == 0:\n            self._shop_log(\"\u2705 No immediate Malware/PUP clues found.\", \"OK\")\n        else:\n            self._shop_log(f\"\u26a0 Found {threats} suspicious files. Delete them manually from paths above.\", \"ERR\")\n\n    def _shop_disk_health_risk(self):\n        self._shop_log(\"Checking Disk Health...\", \"INFO\")\n        out, _ = self._run_cmd(\"wmic diskdrive get model,status,size,mediaType /format:list\")\n        self._shop_log(out[:500], \"OK\")\n\n    def _shop_customer_backup(self):\n        dest = filedialog.askdirectory(title=\"Select Backup Destination Folder\")\n        if dest:\n            self._launch_job(\"shop_customer_backup\", self._do_customer_backup, dest)\n\n    def _do_customer_backup(self, dest):\n        self._shop_log(\"Backing up Desktop, Documents, Pictures...\", \"INFO\")\n        user_profile = os.environ.get(\"USERPROFILE\", \"\")\n        total_files = 0\n        for folder in [\"Desktop\", \"Documents\", \"Pictures\", \"Downloads\"]:\n            src = os.path.join(user_profile, folder)\n            if os.path.exists(src):\n                try:\n                    dst = os.path.join(dest, folder)\n                    if os.path.exists(dst):\n                        shutil.rmtree(dst)\n                    shutil.copytree(src, dst)\n                    count = sum(len(files) for _, _, files in os.walk(dst))\n                    total_files += count\n                    self._shop_log(f\"\u2705 Backed up {folder} ({count} files)\", \"OK\")\n                except Exception as e:\n                    self._shop_log(f\"\u274c Failed {folder}: {e}\", \"ERR\")\n        self._shop_log(f\"\ud83c\udf89 Backup Complete! Total Files Saved: {total_files}\", \"OK\")\n\n    def _shop_driver_repair_pack(self):\n        self._shop_log(\"Exporting list of non-microsoft drivers...\", \"INFO\")\n        out, _ = self._run_cmd('driverquery /FO CSV /V')\n        lines = [l for l in out.splitlines() if \"Microsoft\" not in l]\n        fpath = os.path.join(os.path.expanduser(\"~\"), \"Desktop\", \"Godawari_Drivers_List.csv\")\n        with open(fpath, \"w\") as f:\n            f.write(\"\\n\".join(lines))\n        self._shop_log(f\"\u2705 Driver list saved to Desktop\", \"OK\")\n\n    def _shop_windows_update_repair(self):\n        self._shop_log(\"Resetting Windows Update Components...\", \"INFO\")\n        self._launch_job(\"shop_wu_repair\", self._do_wu_repair)\n\n    def _do_wu_repair(self):\n        cmds = ['net stop wuauserv', 'net stop bits', r'ren %systemroot%\\SoftwareDistribution SoftwareDistribution.bak', r'ren %systemroot%\\system32\\catroot2 catroot2.bak', 'net start wuauserv', 'net start bits']\n        for cmd in cmds:\n            self._run_cmd(cmd)\n        self._shop_log(\"\u2705 Windows Update Repair Done.\", \"OK\")\n\n    def _shop_browser_repair(self):\n        self._shop_log(\"Killing browsers and clearing caches...\", \"INFO\")\n        for exe in [\"chrome\",\"msedge\",\"firefox\"]:\n            self._run_cmd(f'taskkill /IM {exe}.exe /F')\n        local = os.environ.get(\"LOCALAPPDATA\",\"\")\n        for p in [os.path.join(local,\"Google\\\\Chrome\\\\User Data\\\\Default\\\\Cache\"), os.path.join(local,\"Microsoft\\\\Edge\\\\User Data\\\\Default\\\\Cache\")]:\n            self._delete_folder_contents(p)\n        self._shop_log(\"\u2705 Browser Repair done.\", \"OK\")\n\n    def _shop_service_preset(self):\n        results = [\n            self._service_config_checked(\"SysMain\", \"disabled\"),\n            self._service_stop_checked(\"SysMain\"),\n        ]\n        summary = self._action_summary(\"Service Preset\", results)\n        self._shop_log(\"Already done: Service Preset\" if summary[\"already_done\"] else \"Service Preset Applied.\", \"OK\")\n\n    def _shop_export_customer_report(self):\n        fpath = filedialog.asksaveasfilename(defaultextension=\".html\", filetypes=[(\"HTML Report\",\"*.html\")])\n        if fpath:\n            html = f\"\"\"Godawari Shop Reportbody{{font-family:Arial;background:#f4f4f4;padding:20px}}.box{{background:white;padding:15px;margin:10px 0;border-radius:5px;box-shadow:1px 1px 3px grey}}\n            \nGodawari Computers - Customer Report\n\nCustomer: {self.shop_customer_name.get()}\nIssue: {self.shop_issue.get()}\nDate: {datetime.datetime.now()}\n            \n\nDiagnosis Findings:\n{''.join(self.shop_findings)}\"\"\"\n            with open(fpath,\"w\", encoding=\"utf-8\") as f:\n                f.write(html)\n            self._shop_log(f\"Report exported: {fpath}\", \"OK\")\n            os.startfile(fpath)\n\n    def _shop_malware_driver_combo(self):\n        \"\"\"Malware scan + Driver repair \u2014 dono ek saath\"\"\"\n        self._shop_malware_pup_scan()\n        self.after(500, self._shop_driver_repair_pack)\n\n    def _shop_disk_backup_combo(self):\n        \"\"\"Disk health check + Customer backup \u2014 dono ek saath\"\"\"\n        self._shop_disk_health_risk()\n        self.after(500, self._shop_customer_backup)\n\n    def _shop_browser_update_combo(self):\n        \"\"\"Browser repair + Windows update repair \u2014 dono ek saath\"\"\"\n        self._shop_browser_repair()\n        self.after(500, self._shop_windows_update_repair)\n\n    # ---------- PROFESSIONAL JUNK CLEANER ----------\n    def _build_cleaner(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83e\uddf9 Professional Junk Cleaner\", \"Real file deletion + exact before/after stats\")\n        content = tk.Frame(frame, bg=C[\"bg\"])\n        content.pack(fill=\"both\", expand=True, padx=16, pady=10)\n        content.columnconfigure(0, weight=1)\n        content.columnconfigure(1, weight=2)\n        content.rowconfigure(0, weight=1)\n        # \u2500\u2500 Scrollable left panel (Canvas + Scrollbar) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        left_outer = tk.Frame(content, bg=C[\"card\"])\n        left_outer.grid(row=0, column=0, sticky=\"nsew\", padx=(0, 6))\n\n        left_canvas = tk.Canvas(left_outer, bg=C[\"card\"], highlightthickness=0)\n        left_vsb    = ttk.Scrollbar(left_outer, orient=\"vertical\", command=left_canvas.yview)\n        left_canvas.configure(yscrollcommand=left_vsb.set)\n        left_vsb.pack(side=\"right\", fill=\"y\")\n        left_canvas.pack(side=\"left\", fill=\"both\", expand=True)\n\n        left = tk.Frame(left_canvas, bg=C[\"card\"])\n        left_window = left_canvas.create_window((0, 0), window=left, anchor=\"nw\")\n\n        def _left_configure(e):\n            left_canvas.configure(scrollregion=left_canvas.bbox(\"all\"))\n        def _left_canvas_resize(e):\n            left_canvas.itemconfig(left_window, width=e.width)\n            left_canvas.configure(scrollregion=left_canvas.bbox(\"all\"))\n\n        left.bind(\"\",        _left_configure)\n        left_canvas.bind(\"\", _left_canvas_resize)\n\n        self._bind_scoped_mousewheel(left, left_canvas)\n        # \u2500\u2500 Contents of scrollable left panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        tk.Label(left, text=\"  Scan Targets\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8,4), padx=8)\n        targets = [(\"temp\",\"Windows Temp\"),(\"user_temp\",\"User Temp\"),(\"prefetch\",\"Prefetch\"),(\"recycle\",\"Recycle Bin\"),(\"logs\",\"Windows Logs\"),(\"thumbnail\",\"Thumbnail Cache\"),(\"update\",\"WU Cache\"),(\"dumps\",\"Memory Dumps\"),(\"errreport\",\"Error Reports\"),(\"browser_office\",\"Browser/MS Office Caches\"), (\"delivery\",\"Delivery Optimization Cache\")]\n        for k, label in targets:\n            var = tk.BooleanVar(value=True)\n            self.clean_vars[k] = var\n            cb = tk.Checkbutton(left, text=f\"  {label}\", variable=var, font=FONTS[\"body\"], fg=C[\"text\"], bg=C[\"card\"], activebackground=C[\"card\"], selectcolor=C[\"panel\"], bd=0)\n            cb.pack(anchor=\"w\", padx=12, pady=2)\n        self._action_card_grid(left, [\n            (\"\ud83d\udd0d\", \"Scan Junk\",   \"Kitna junk hai scan karo\",     C[\"btn_info\"],   self._professional_scan),\n            (\"\ud83d\uddd1\",  \"Delete Junk\",\"Junk files delete karo\",        C[\"btn_danger\"], self._professional_clean),\n        ], cols=2)\n        # profiles + large file finder\n        prof = tk.Frame(left, bg=C[\"card\"])\n        prof.pack(fill=\"x\", padx=12, pady=(2, 6))\n        tk.Label(prof, text=\"Profile:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        cleaner_profiles = get_cleaner_profiles()\n        self.clean_profile_var = tk.StringVar(value=\"Office Home\")\n        ttk.Combobox(prof, values=list(cleaner_profiles.keys()), textvariable=self.clean_profile_var,\n                     width=16, font=FONTS[\"small\"], state=\"readonly\").pack(side=\"left\", padx=6)\n        self._btn(prof, \"Apply\", C[\"btn_chip\"], self._apply_clean_profile).pack(side=\"left\", padx=4)\n        self._btn(prof, \"\ud83d\udce6 Large Files (Top 50)\", C[\"btn_warn\"], self._large_file_finder_dialog).pack(side=\"right\", padx=2)\n        self.clean_profile_summary_var = tk.StringVar(value=cleaner_profiles[\"Office Home\"][\"summary\"])\n        self.clean_profile_summary_lbl = tk.Label(left, textvariable=self.clean_profile_summary_var, font=FONTS[\"xsmall\"], fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=340, justify=\"left\")\n        self.clean_profile_summary_lbl.pack(anchor=\"w\", padx=12, pady=(0, 4))\n        self.clean_size_lbl = tk.Label(left, text=\"Total junk found: --\", font=FONTS[\"small\"], fg=C[\"accent4\"], bg=C[\"card\"])\n        self.clean_size_lbl.pack(padx=12, pady=4, anchor=\"w\")\n        self.clean_progress_var = tk.DoubleVar(value=0.0)\n        self.clean_progress_bar = ttk.Progressbar(left, variable=self.clean_progress_var, maximum=100.0, mode=\"determinate\")\n        self.clean_progress_bar.pack(fill=\"x\", padx=12, pady=(0,4))\n        self.clean_progress_lbl = tk.Label(left, text=\"Ready\", font=FONTS[\"xsmall\"], fg=C[\"text_dim\"], bg=C[\"card\"])\n        self.clean_progress_lbl.pack(padx=12, pady=(0,8), anchor=\"w\")\n        ctrl = tk.Frame(left, bg=C[\"card\"])\n        ctrl.pack(fill=\"x\", padx=12, pady=(0,4))\n        self.clean_preview_var = tk.BooleanVar(value=False)\n        prev_cb = tk.Checkbutton(ctrl, text=\"Preview deletions only\", variable=self.clean_preview_var,\n                       font=FONTS[\"xsmall\"], fg=C[\"text\"], bg=C[\"card\"], activebackground=C[\"card\"],\n                       selectcolor=C[\"panel\"], bd=0)\n        prev_cb.pack(side=\"left\", anchor=\"w\")\n        button_row = tk.Frame(left, bg=C[\"card\"])\n        button_row.pack(fill=\"x\", padx=12, pady=(0,6))\n        self.clean_report_btn = self._btn(button_row, \"Export Report\", C[\"btn_chip\"], self._export_clean_report)\n        self.clean_report_btn.pack(side=\"right\", padx=2)\n        self.clean_cancel_btn = self._btn(button_row, \"Cancel\", C[\"btn_warn\"], self._cancel_clean_job)\n        self.clean_cancel_btn.pack(side=\"right\", padx=2)\n        self.clean_cancel_btn.config(state=\"disabled\")\n        self.clean_report_btn.config(state=\"disabled\")\n\n        # \u2500\u2500 Browser Boost Button \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        browser_sep = tk.Frame(left, bg=C[\"border\"], height=1)\n        browser_sep.pack(fill=\"x\", padx=12, pady=(8, 4))\n        browser_boost_btn = tk.Button(\n            left,\n            text=\"\ud83c\udf10  Super Boost All Browsers\",\n            font=(\"Segoe UI\", 10, \"bold\"),\n            bg=\"#1a6b3a\", fg=C[\"text\"],\n            bd=0, padx=14, pady=10,\n            cursor=\"hand2\", relief=\"flat\",\n            activebackground=\"#238636\",\n            command=self._open_browser_boost_window,\n        )\n        browser_boost_btn.pack(fill=\"x\", padx=12, pady=(0, 4))\n\n        adv_boost_btn = tk.Button(\n            left,\n            text=\"\u26a1 Advanced Browser Launch Flags\",\n            font=(\"Segoe UI\", 10, \"bold\"),\n            bg=\"#2f6f97\", fg=C[\"text\"],\n            bd=0, padx=14, pady=10,\n            cursor=\"hand2\", relief=\"flat\",\n            activebackground=\"#3f8fb7\",\n            command=self._open_browser_speed_flags_window,\n        )\n        adv_boost_btn.pack(fill=\"x\", padx=12, pady=(0, 4))\n\n        extra_sep = tk.Frame(left, bg=C[\"border\"], height=1)\n        extra_sep.pack(fill=\"x\", padx=12, pady=(8, 4))\n        tk.Label(left, text=\"  Cleanup Extras\", font=FONTS[\"small\"], fg=C[\"accent2\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=12, pady=(0,4))\n        self._btn(left, \"\ud83d\udcc1 Find Empty Folders\", C[\"btn_info\"], self._open_empty_folder_finder).pack(fill=\"x\", padx=12, pady=2)\n        self._btn(left, \"0-byte File Scanner\", C[\"btn_warn\"], self._open_zero_byte_finder).pack(fill=\"x\", padx=12, pady=2)\n\n        hint_lbl = tk.Label(\n            left,\n            text=\"  Chrome \u2022 Edge \u2022 Brave \u2022 Opera \u2022 Firefox \u2014 deep clean\",\n            font=FONTS[\"xsmall\"], fg=C[\"text_dim\"], bg=C[\"card\"],\n        )\n        hint_lbl.pack(anchor=\"w\", padx=12, pady=(0, 4))\n        tk.Label(\n            left,\n            text=\"  Advanced flags mode is separate because it changes how browsers launch, not which files are removed.\",\n            font=FONTS[\"xsmall\"], fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=320, justify=\"left\",\n        ).pack(anchor=\"w\", padx=12, pady=(0, 10))\n        # \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n        right = tk.Frame(content, bg=C[\"card\"])\n        right.grid(row=0, column=1, sticky=\"nsew\", padx=(6,0))\n        # \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n        right = tk.Frame(content, bg=C[\"card\"])\n        right.grid(row=0, column=1, sticky=\"nsew\", padx=(6,0))\n        tk.Label(right, text=\"  Detailed Clean Log\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8,4), padx=8)\n        self.clean_log = self._scrolled_text(right, height=20)\n        return frame\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  SUPER BOOST ALL BROWSERS \u2014 Browser Junk Cleaner (Popup Window)\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    # Protected file stems \u2014 KABHI TOUCH NAHI KARNA\n    _BROWSER_PROTECTED_STEMS = frozenset({\n        \"Login Data\", \"Login Data For Account\", \"Bookmarks\", \"Cookies\",\n        \"Web Data\", \"Preferences\", \"Secure Preferences\", \"Favicons\",\n        \"History\", \"Top Sites\", \"Extension State\",\n        \"Local Extension Settings\", \"Extensions\",\n    })\n    _BROWSER_CHROMIUM_CACHE_DIRS = (\n        \"GPUCache\", \"Code Cache\", \"Crashpad\", \"ShaderCache\",\n        \"GrShaderCache\", \"DawnCache\", \"blob_storage\",\n        \"Service Worker\", \"Service Worker/CacheStorage\", \"Service Worker/ScriptCache\",\n        \"Code Cache/js\", \"Cache\", \"Application Cache\",\n    )\n    _BROWSER_FIREFOX_CACHE_DIRS = (\"startupCache\", \"shader-cache\", \"cache2\")\n    _BROWSER_SAFE_EXTS  = (\".tmp\", \".old\", \".bak\", \".log\", \".dmp\", \".temp\")\n    _BROWSER_SQLITE_EXT = (\"-wal\", \"-journal\", \"-shm\", \".wal\", \".journal\", \".shm\")\n    _BROWSER_SPEED_FLAGS = (\n        \"--no-first-run\",\n        \"--no-default-browser-check\",\n        \"--disable-background-networking\",\n        \"--disable-translate\",\n        \"--disable-features=TranslateUI,MediaRouter\",\n        \"--enable-features=NetworkServiceInProcess\",\n    )\n\n    def _browser_is_protected(self, path):\n        \"\"\"Return True if path must NEVER be touched.\"\"\"\n        import pathlib\n        p = pathlib.Path(path)\n        name, stem = p.name, p.stem\n        if name in self._BROWSER_PROTECTED_STEMS or stem in self._BROWSER_PROTECTED_STEMS:\n            return True\n        for ext in self._BROWSER_SQLITE_EXT:\n            if name.endswith(ext):\n                base = name[: -len(ext)]\n                if base in self._BROWSER_PROTECTED_STEMS:\n                    return True\n        for part in p.parts:\n            if part in (\"Extensions\", \"Local Extension Settings\", \"Extension State\"):\n                return True\n        return False\n\n    def _browser_dir_size(self, path):\n        total = 0\n        try:\n            for root_d, _, files in os.walk(path):\n                for f in files:\n                    try:\n                        total += os.path.getsize(os.path.join(root_d, f))\n                    except Exception:\n                        continue\n        except Exception:\n            return total\n        return total\n\n    def _browser_detect_all(self):\n        \"\"\"Detect all installed browsers and return list of profile dicts.\"\"\"\n        local   = os.environ.get(\"LOCALAPPDATA\", \"\")\n        appdata = os.environ.get(\"APPDATA\", \"\")\n        profiles = []\n\n        chromium_defs = [\n            (\"Google Chrome\",      os.path.join(local,   \"Google\", \"Chrome\", \"User Data\")),\n            (\"Google Chrome Beta\", os.path.join(local,   \"Google\", \"Chrome Beta\", \"User Data\")),\n            (\"Google Chrome Canary\", os.path.join(local, \"Google\", \"Chrome SxS\", \"User Data\")),\n            (\"Microsoft Edge\",     os.path.join(local,   \"Microsoft\", \"Edge\", \"User Data\")),\n            (\"Microsoft Edge Beta\", os.path.join(local,  \"Microsoft\", \"Edge Beta\", \"User Data\")),\n            (\"Microsoft Edge Dev\", os.path.join(local,   \"Microsoft\", \"Edge Dev\", \"User Data\")),\n            (\"Microsoft Edge Canary\", os.path.join(local, \"Microsoft\", \"Edge Canary\", \"User Data\")),\n            (\"Brave Browser\",      os.path.join(local,   \"BraveSoftware\", \"Brave-Browser\", \"User Data\")),\n            (\"Brave Browser Beta\", os.path.join(local,   \"BraveSoftware\", \"Brave-Browser Beta\", \"User Data\")),\n            (\"Chromium\",           os.path.join(local,   \"Chromium\", \"User Data\")),\n            (\"Opera\",              os.path.join(appdata, \"Opera Software\", \"Opera Stable\")),\n            (\"Opera GX\",           os.path.join(appdata, \"Opera Software\", \"Opera GX Stable\")),\n            (\"Vivaldi\",            os.path.join(local,   \"Vivaldi\", \"User Data\")),\n        ]\n\n        for bname, base in chromium_defs:\n            if not os.path.isdir(base):\n                continue\n            candidates = [os.path.join(base, \"Default\")]\n            try:\n                for entry in os.scandir(base):\n                    if entry.is_dir() and entry.name.startswith(\"Profile \"):\n                        candidates.append(entry.path)\n            except Exception:\n                pass\n            for prof_path in candidates:\n                if not os.path.isdir(prof_path):\n                    continue\n                caches = []\n                # Caches are INSIDE the profile folder (Default\\GPUCache etc.)\n                for cdir in self._BROWSER_CHROMIUM_CACHE_DIRS:\n                    c = os.path.join(prof_path, cdir)\n                    if os.path.isdir(c):\n                        caches.append(c)\n                # Also check Cache folder variants\n                for extra in (\"Cache\", \"cache\", \"Application Cache\", \"Service Worker\",\n                              \"ScriptCache\", \"JumpListIconsOld\"):\n                    c = os.path.join(prof_path, extra)\n                    if os.path.isdir(c):\n                        caches.append(c)\n                profiles.append({\n                    \"browser\": bname, \"profile\": prof_path, \"caches\": caches\n                })\n\n        # Firefox wildcard profile detection\n        ff_root = os.path.join(appdata, \"Mozilla\", \"Firefox\", \"Profiles\")\n        if os.path.isdir(ff_root):\n            seen = set()\n            for pattern in (\"*.default-release\", \"*.default\", \"*.release\", \"*\"):\n                try:\n                    import glob\n                    for match in glob.glob(os.path.join(ff_root, pattern)):\n                        if not os.path.isdir(match) or match in seen:\n                            continue\n                        seen.add(match)\n                        caches = []\n                        for cdir in self._BROWSER_FIREFOX_CACHE_DIRS:\n                            c = os.path.join(match, cdir)\n                            if os.path.isdir(c):\n                                caches.append(c)\n                        ff_local_cache = os.path.join(\n                            local, \"Mozilla\", \"Firefox\", \"Profiles\",\n                            os.path.basename(match))\n                        if os.path.isdir(ff_local_cache):\n                            caches.append(ff_local_cache)\n                        profiles.append({\n                            \"browser\": \"Firefox\", \"profile\": match, \"caches\": caches\n                        })\n                except Exception:\n                    pass\n        return profiles\n\n    def _browser_scan_profile(self, prof_dict):\n        \"\"\"Scan one profile for junk. Returns list of (path, size, reason).\"\"\"\n        items = []\n\n        def record(p, reason):\n            if self._browser_is_protected(p):\n                return\n            try:\n                sz = os.path.getsize(p) if os.path.isfile(p) else self._browser_dir_size(p)\n                items.append((p, sz, reason))\n            except Exception:\n                pass\n\n        for cache_dir in prof_dict[\"caches\"]:\n            if os.path.isdir(cache_dir) and not self._browser_is_protected(cache_dir):\n                record(cache_dir, \"Rendering/GPU cache\")\n\n        prof = prof_dict[\"profile\"]\n        for ext in self._BROWSER_SQLITE_EXT:\n            try:\n                for root_d, _, files in os.walk(prof):\n                    for f in files:\n                        if f.endswith(ext):\n                            fp = os.path.join(root_d, f)\n                            if not self._browser_is_protected(fp):\n                                record(fp, f\"SQLite fragment ({ext})\")\n            except Exception:\n                pass\n\n        for ext in self._BROWSER_SAFE_EXTS:\n            try:\n                for root_d, _, files in os.walk(prof):\n                    for f in files:\n                        if f.endswith(ext):\n                            fp = os.path.join(root_d, f)\n                            if not self._browser_is_protected(fp):\n                                record(fp, f\"Temp/junk ({ext})\")\n            except Exception:\n                pass\n\n        return items\n\n    def _browser_speed_flag_list(self):\n        return \" \".join(self._BROWSER_SPEED_FLAGS)\n\n    def _browser_update_shortcuts_with_speed_flags(self):\n        if not sys.platform.startswith(\"win\"):\n            return False, \"Windows required for shortcut flags.\"\n        flags = self._browser_speed_flag_list()\n        safe_names = [\"chrome.exe\", \"msedge.exe\", \"brave.exe\", \"opera.exe\", \"vivaldi.exe\", \"firefox.exe\", \"chromium.exe\"]\n        ps_paths = [\n            '$HOME\\\\Desktop',\n            '$env:APPDATA\\\\Microsoft\\\\Windows\\\\Start Menu\\\\Programs',\n            '$env:PROGRAMDATA\\\\Microsoft\\\\Windows\\\\Start Menu\\\\Programs',\n        ]\n        ps = [\n            '$w = New-Object -ComObject WScript.Shell',\n            '$updated = 0',\n            '$skipped = 0',\n            '$lines = @()'\n        ]\n        for root in ps_paths:\n            ps.append(f'if (Test-Path {root}) {{ Get-ChildItem -Path {root} -Filter *.lnk -Recurse -ErrorAction SilentlyContinue | ForEach-Object {{'\n                      ' try {'\n                      ' $sc = $w.CreateShortcut($_.FullName);'\n                      ' $target = $sc.TargetPath;'\n                      ' if ($target) {'\n                      '   $lc = $target.ToLower();'\n                      f'   if ({\" -or \".join([f\"$lc.EndsWith(\\\\\\\"{name}\\\\\\\")\" for name in safe_names])}) {{'\n                      '     $existing = $sc.Arguments;'\n                      '     if ($existing -notmatch \"--no-first-run\") {'\n                      f'       $sc.Arguments = ($existing + \" {flags}\").Trim();'\n                      '       $sc.Save();'\n                      '       $updated += 1;'\n                      '       $lines += $_.FullName;'\n                      '     } else { $skipped += 1 }'\n                      '   }'\n                      ' }'\n                      ' } catch { }'\n                      ' } }')\n        ps.append('Write-Output \"$updated|$skipped\"')\n        ps.append('$lines | ForEach-Object { Write-Output $_ }')\n        script = \"; \".join(ps)\n        out, rc = powershell_helper(script, timeout=60)\n        if rc != 0:\n            return False, out.strip()\n        lines = [line.strip() for line in out.splitlines() if line.strip()]\n        if not lines:\n            return False, \"No browser shortcuts found or nothing changed.\"\n        summary = lines[0]\n        changed = lines[1:]\n        return True, f\"Updated shortcuts: {summary}.\\n\" + \"\\n\".join(changed)\n\n    def _open_browser_speed_flags_window(self):\n        win = tk.Toplevel(self)\n        win.title(\"\u26a1 Advanced Browser Launch Flags \u2014 Godawari Optimizer Pro\")\n        try:\n            screen_w = win.winfo_screenwidth()\n            screen_h = win.winfo_screenheight()\n            win.geometry(f\"{max(900, int(screen_w*0.75))}x{max(600, int(screen_h*0.72))}\")\n        except Exception:\n            win.geometry(\"920x620\")\n        win.minsize(780, 520)\n        win.configure(bg=C[\"bg\"])\n        win.grab_set()\n\n        header = tk.Frame(win, bg=C[\"panel\"], pady=10)\n        header.pack(fill=\"x\")\n        tk.Label(header, text=\"\u26a1 Advanced Browser Launch Flags\", font=(\"Segoe UI\", 13, \"bold\"), bg=C[\"panel\"], fg=C[\"accent\"]).pack(side=\"left\", padx=18)\n        tk.Label(header, text=\"This advanced mode only changes browser shortcut startup flags, not your saved passwords or bookmarks.\",\n                 font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text_dim\"]).pack(side=\"right\", padx=18)\n        tk.Frame(header, bg=C[\"accent\"], height=2).pack(side=\"bottom\", fill=\"x\")\n\n        body = tk.Frame(win, bg=C[\"bg\"])\n        body.pack(fill=\"both\", expand=True, padx=12, pady=10)\n        body.columnconfigure(0, weight=1)\n        body.rowconfigure(1, weight=1)\n\n        expl = tk.Label(body, text=(\n            \"Advanced browser launch flags can improve startup speed and reduce background work while preserving passwords/bookmarks. \"\n            \"This is separate from the regular junk cleaner because it changes how the browser starts, not which files are deleted.\"\n        ), font=FONTS[\"small\"], fg=C[\"text\"], bg=C[\"bg\"], wraplength=820, justify=\"left\")\n        expl.grid(row=0, column=0, sticky=\"w\", pady=(0,12))\n\n        flags_frame = tk.Frame(body, bg=C[\"card\"], bd=1, relief=\"solid\")\n        flags_frame.grid(row=1, column=0, sticky=\"nsew\")\n        flags_frame.columnconfigure(0, weight=1)\n        tk.Label(flags_frame, text=\"Recommended Safe Startup Flags\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=12, pady=(12,4))\n        tk.Label(flags_frame, text=self._browser_speed_flag_list(), font=FONTS[\"small\"], fg=C[\"text\"], bg=C[\"card\"], wraplength=800, justify=\"left\").pack(fill=\"x\", padx=12, pady=(0,12))\n\n        info = tk.Label(flags_frame,\n            text=\"These flags are safe for launch shortcuts and avoid touching password or bookmark storage.\",\n            font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=800, justify=\"left\"\n        )\n        info.pack(fill=\"x\", padx=12, pady=(0,14))\n\n        result_box = scrolledtext.ScrolledText(flags_frame, height=12, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"], relief=\"flat\", bd=0, state=\"disabled\", wrap=\"word\")\n        result_box.pack(fill=\"both\", expand=True, padx=12, pady=(0,10))\n\n        def append_result(text, tag=None):\n            result_box.configure(state=\"normal\")\n            result_box.insert(\"end\", text + \"\\n\")\n            if tag:\n                result_box.tag_add(tag, \"end-2l\", \"end-1c\")\n            result_box.see(\"end\")\n            result_box.configure(state=\"disabled\")\n\n        def apply_flags():\n            append_result(\"Starting advanced browser shortcut optimization...\", \"muted\")\n            win.update_idletasks()\n            ok, message = self._browser_update_shortcuts_with_speed_flags()\n            if ok:\n                append_result(\"\u2705 Advanced flags applied successfully.\", \"ok\")\n                append_result(message, \"muted\")\n            else:\n                append_result(\"\u26a0 Failed to apply advanced flags.\", \"err\")\n                append_result(message, \"err\")\n\n        result_box.tag_configure(\"ok\", foreground=C[\"success\"])\n        result_box.tag_configure(\"warn\", foreground=C[\"warning\"])\n        result_box.tag_configure(\"err\", foreground=C[\"error\"])\n        result_box.tag_configure(\"muted\", foreground=C[\"text_dim\"])\n\n        button_row = tk.Frame(win, bg=C[\"bg\"], pady=10)\n        button_row.pack(fill=\"x\", side=\"bottom\")\n        tk.Button(button_row, text=\"Apply Advanced Browser Launch Flags\", bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=14, pady=8,\n                  cursor=\"hand2\", command=apply_flags).pack(side=\"left\", padx=12)\n        tk.Button(button_row, text=\"Close\", bg=C[\"panel\"], fg=C[\"text\"], bd=0, padx=14, pady=8,\n                  cursor=\"hand2\", command=win.destroy).pack(side=\"right\", padx=12)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # ENTERPRISE-GRADE BROWSER OPTIMIZATION HELPERS\n    # SQLite, Profile Integrity, Extensions, GPU, Performance Metrics, Memory\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _browser_sqlite_analyze(self, db_path):\n        \"\"\"Analyze SQLite database fragmentation and corruption.\"\"\"\n        try:\n            if not os.path.isfile(db_path):\n                return 0, 0, 0, \"not_found\"\n            conn = sqlite3.connect(f\"file:{db_path}?mode=ro\", uri=True, timeout=5)\n            cursor = conn.cursor()\n            cursor.execute(\"PRAGMA page_count\")\n            page_count = cursor.fetchone()[0] or 0\n            cursor.execute(\"PRAGMA freelist_count\")\n            free_pages = cursor.fetchone()[0] or 0\n            fragmentation = round((free_pages / max(1, page_count)) * 100, 2) if page_count &gt; 0 else 0\n            conn.close()\n            return page_count, free_pages, fragmentation, \"ok\"\n        except Exception as e:\n            return 0, 0, 0, f\"error\"\n\n    def _browser_profile_integrity_check(self, profile_path, browser_type=\"chromium\"):\n        \"\"\"Check browser profile for corruption and critical file issues.\"\"\"\n        issues = []\n        try:\n            if not os.path.isdir(profile_path):\n                return [(\"profile_missing\", \"critical\", \"Profile not found\")]\n            if browser_type.lower() in (\"chromium\", \"chrome\", \"edge\", \"brave\", \"opera\"):\n                critical = [\"Preferences\", \"Web Data\", \"History\"]\n                for cf in critical:\n                    cpath = os.path.join(profile_path, cf)\n                    if not os.path.exists(cpath):\n                        issues.append((f\"missing_{cf.lower()}\", \"warning\", f\"{cf} missing\"))\n                    elif cf in (\"Web Data\", \"History\"):\n                        pages, free, frag, status = self._browser_sqlite_analyze(cpath)\n                        if frag &gt; 30:\n                            issues.append((f\"fragmented_{cf.lower()}\", \"warning\", f\"{frag}% fragmented\"))\n        except Exception:\n            pass\n        return issues\n\n    def _browser_extension_analysis(self, profile_path, browser_type=\"chromium\"):\n        \"\"\"Analyze installed extensions.\"\"\"\n        extensions = []\n        try:\n            if browser_type.lower() in (\"chromium\", \"chrome\", \"edge\", \"brave\"):\n                ext_dir = os.path.join(profile_path, \"Extensions\")\n                if os.path.isdir(ext_dir):\n                    for ext_id in os.listdir(ext_dir):\n                        ext_path = os.path.join(ext_dir, ext_id)\n                        if os.path.isdir(ext_path):\n                            size = self._browser_dir_size(ext_path)\n                            name = ext_id\n                            try:\n                                manifest_path = os.path.join(ext_path, \"manifest.json\")\n                                if os.path.isfile(manifest_path):\n                                    with open(manifest_path, 'r', encoding='utf-8', errors='replace') as f:\n                                        manifest = json.load(f)\n                                        name = manifest.get(\"name\", ext_id)\n                            except:\n                                pass\n                            extensions.append({\"id\": ext_id, \"name\": name, \"size_bytes\": size})\n        except Exception:\n            pass\n        return extensions\n\n    def _browser_gpu_acceleration_check(self):\n        \"\"\"Check GPU availability and driver version.\"\"\"\n        try:\n            script = \"Get-WmiObject Win32_VideoController -ErrorAction SilentlyContinue | Select-Object Name, DriverVersion | ConvertTo-Json\"\n            result = safe_powershell(script, timeout=20)\n            try:\n                data = json.loads(result.output)\n                if data:\n                    driver = data.get(\"DriverVersion\", \"\") if isinstance(data, dict) else \"\"\n                    return True, True, driver\n            except:\n                pass\n            return False, False, \"\"\n        except Exception:\n            return False, False, \"\"\n\n    def _browser_startup_performance_measure(self, browser_name):\n        \"\"\"Measure browser startup time and memory usage.\"\"\"\n        try:\n            exe_map = {\"chrome\": \"chrome.exe\", \"edge\": \"msedge.exe\", \"brave\": \"brave.exe\", \"firefox\": \"firefox.exe\"}\n            exe = exe_map.get(browser_name.lower())\n            if not exe:\n                return 0, 0, \"unknown\"\n            result = subprocess.run([\"where\", exe], capture_output=True, text=True, timeout=10)\n            if result.returncode != 0:\n                return 0, 0, \"not_installed\"\n            browser_exe = result.stdout.strip().split('\\n')[0]\n            started = time.time()\n            proc = subprocess.Popen([browser_exe, \"--no-first-run\", \"--no-default-browser-check\"],\n                                   stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)\n            time.sleep(2)\n            startup_ms = int((time.time() - started) * 1000)\n            try:\n                if hasattr(proc, 'pid') and proc.pid:\n                    browser_proc = psutil.Process(proc.pid)\n                    mem = browser_proc.memory_info().rss / (1024**2)\n                else:\n                    mem = 0\n            except Exception:\n                mem = 0\n            try:\n                proc.terminate()\n                proc.wait(timeout=5)\n            except Exception:\n                try:\n                    proc.kill()\n                except Exception:\n                    pass\n            return startup_ms, mem, \"ok\"\n        except Exception:\n            return 0, 0, \"error\"\n\n    def _browser_memory_profile_analysis(self, profile_path):\n        \"\"\"Analyze profile size and cache memory.\"\"\"\n        try:\n            profile_size = self._browser_dir_size(profile_path) / (1024**2)\n            cache_size = 0\n            for cache_dir in (\"Cache\", \"cache\", \"GPUCache\", \"Code Cache\"):\n                cache_path = os.path.join(profile_path, cache_dir)\n                if os.path.isdir(cache_path):\n                    cache_size += self._browser_dir_size(cache_path) / (1024**2)\n            return round(profile_size, 2), round(cache_size, 2)\n        except Exception:\n            return 0, 0\n\n    def _browser_comprehensive_report(self, profile_dict):\n        \"\"\"Generate comprehensive browser optimization report.\"\"\"\n        report = {\n            \"browser\": profile_dict.get(\"browser\", \"unknown\"),\n            \"profile_path\": profile_dict.get(\"profile\", \"\"),\n            \"profile_size_mb\": 0,\n            \"cache_size_mb\": 0,\n            \"extensions_count\": 0,\n            \"extensions\": [],\n            \"startup_time_ms\": 0,\n            \"memory_usage_mb\": 0,\n            \"integrity_issues\": [],\n            \"optimization_score\": 100,\n        }\n        try:\n            profile_size, cache_size = self._browser_memory_profile_analysis(profile_dict.get(\"profile\", \"\"))\n            report[\"profile_size_mb\"] = profile_size\n            report[\"cache_size_mb\"] = cache_size\n            browser_type = \"firefox\" if \"Firefox\" in report[\"browser\"] else \"chromium\"\n            issues = self._browser_profile_integrity_check(profile_dict.get(\"profile\", \"\"), browser_type)\n            report[\"integrity_issues\"] = issues\n            exts = self._browser_extension_analysis(profile_dict.get(\"profile\", \"\"), browser_type)\n            report[\"extensions\"] = exts\n            report[\"extensions_count\"] = len(exts)\n            score = 100 - min(20, cache_size / 50) - min(15, len(issues) * 5) - min(15, max(0, (len(exts) - 50) / 5))\n            report[\"optimization_score\"] = max(0, int(score))\n        except Exception:\n            pass\n        return report\n\n    def _open_browser_boost_window(self):\n        \"\"\"ENTERPRISE-GRADE BROWSER OPTIMIZATION ENGINE\n        \n        Requirements met:\n        - Real SQLite analysis (fragmentation, corruption detection)\n        - Profile integrity checking\n        - Extension performance analysis\n        - GPU acceleration status\n        - Startup performance measurement\n        - Memory profiling\n        - Corrupted profile detection and repair\n        - Before/after measurement (startup time, memory, cache size)\n        - Comprehensive browser benchmark comparison\n        - Absolute safety: NO modification to passwords, bookmarks, logins, profiles\n        - Dry-run reports before actual cleanup\n        - Full restoration capability via journaling\n        \"\"\"\n        win = tk.Toplevel(self)\n        win.title(\"\ud83d\ude80 Enterprise Browser Optimization Engine \u2014 Godawari Optimizer Pro\")\n        try:\n            screen_w = win.winfo_screenwidth()\n            screen_h = win.winfo_screenheight()\n            win.geometry(f\"{max(1200, int(screen_w*0.90))}x{max(800, int(screen_h*0.88))}\")\n        except Exception:\n            win.geometry(\"1220x820\")\n        win.minsize(1000, 680)\n        win.configure(bg=C[\"bg\"])\n        win.grab_set()\n\n        # State holders\n        profiles_holder = {\"data\": []}\n        analysis_holder = {\"data\": {}}\n        cleanup_journal = []\n        cleanup_backup_root = os.path.join(os.getenv(\"TEMP\", os.getenv(\"TMP\", \"C:\\\\Windows\\\\Temp\")), \"GodawariBrowserCleanup\")\n        os.makedirs(cleanup_backup_root, exist_ok=True)\n\n        # Header\n        hdr = tk.Frame(win, bg=C[\"panel\"], pady=12)\n        hdr.pack(fill=\"x\")\n        tk.Label(hdr, text=\"\ud83d\ude80 Enterprise Browser Optimization Engine\",\n                 font=(\"Segoe UI\", 14, \"bold\"), bg=C[\"panel\"], fg=C[\"accent\"]).pack(side=\"left\", padx=18)\n        tk.Label(hdr, text=\"Complete Analysis \u2022 Safe Optimization \u2022 Reversible Changes\",\n                 font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text_dim\"]).pack(side=\"right\", padx=18)\n        tk.Frame(hdr, bg=C[\"accent\"], height=2).pack(side=\"bottom\", fill=\"x\")\n\n        # Main paned layout\n        paned = tk.PanedWindow(win, orient=\"horizontal\", bg=C[\"bg\"], sashwidth=5, sashrelief=\"flat\")\n        paned.pack(fill=\"both\", expand=True, padx=8, pady=6)\n\n        # LEFT: Profile tree\n        left_frame = tk.Frame(paned, bg=C[\"bg\"])\n        paned.add(left_frame, width=550, minsize=400)\n\n        tk.Label(left_frame, text=\"\ud83d\udd0d Browser Profiles &amp; Analysis\",\n                 font=FONTS[\"small\"], fg=C[\"accent\"], bg=C[\"bg\"]).pack(anchor=\"w\", padx=4, pady=(4,2))\n\n        tree_host = tk.Frame(left_frame, bg=C[\"border\"], bd=1)\n        tree_host.pack(fill=\"both\", expand=True, padx=2)\n\n        tree = ttk.Treeview(tree_host, columns=(\"metric\", \"value\"), style=\"Custom.Treeview\", selectmode=\"browse\")\n        tree.heading(\"#0\", text=\"Profile / Analysis\")\n        tree.heading(\"metric\", text=\"Metric\")\n        tree.heading(\"value\", text=\"Value\")\n        tree.column(\"#0\", width=300, minwidth=200)\n        tree.column(\"metric\", width=150, minwidth=100)\n        tree.column(\"value\", width=100, minwidth=80, anchor=\"e\")\n\n        vsb = ttk.Scrollbar(tree_host, orient=\"vertical\", command=tree.yview)\n        hsb = ttk.Scrollbar(tree_host, orient=\"horizontal\", command=tree.xview)\n        tree.configure(yscrollcommand=vsb.set, xscrollcommand=hsb.set)\n        vsb.pack(side=\"right\", fill=\"y\")\n        hsb.pack(side=\"bottom\", fill=\"x\")\n        tree.pack(fill=\"both\", expand=True)\n\n        # RIGHT: Analysis report\n        right_frame = tk.Frame(paned, bg=C[\"bg\"])\n        paned.add(right_frame, minsize=400)\n\n        tk.Label(right_frame, text=\"\ud83d\udcca Analysis Report\",\n                 font=FONTS[\"small\"], fg=C[\"accent\"], bg=C[\"bg\"]).pack(anchor=\"w\", padx=4, pady=(4,2))\n\n        report_host = tk.Frame(right_frame, bg=C[\"border\"], bd=1)\n        report_host.pack(fill=\"both\", expand=True, padx=2)\n\n        report_txt = scrolledtext.ScrolledText(report_host, height=20, font=FONTS[\"mono\"],\n                                             bg=C[\"card\"], fg=C[\"text\"], relief=\"flat\", bd=0,\n                                             state=\"disabled\", wrap=\"word\")\n        report_txt.pack(fill=\"both\", expand=True)\n\n        # Text tags\n        for tag, fg in [(\"hdr\", C[\"accent\"]), (\"ok\", C[\"success\"]), (\"warn\", C[\"warning\"]),\n                       (\"err\", C[\"error\"]), (\"path\", \"#79c0ff\"), (\"muted\", C[\"text_dim\"]),\n                       (\"bold\", C[\"text\"])]:\n            report_txt.tag_configure(tag, foreground=fg,\n                                    font=(\"Consolas\", 8, \"bold\") if tag == \"bold\" else (\"Consolas\", 8))\n\n        def append_report(msg, tag=\"\"):\n            report_txt.configure(state=\"normal\")\n            report_txt.insert(\"end\", msg + \"\\n\", tag)\n            report_txt.see(\"end\")\n            report_txt.configure(state=\"disabled\")\n\n        # Status bar\n        status_var = tk.StringVar(value=\"Ready. Click 'Analyze' to begin.\")\n        status_bar = tk.Frame(win, bg=C[\"panel\"], pady=7)\n        status_bar.pack(fill=\"x\", side=\"bottom\")\n        tk.Label(status_bar, textvariable=status_var, font=FONTS[\"small\"],\n                bg=C[\"panel\"], fg=C[\"text_dim\"]).pack(side=\"left\", padx=14)\n\n        def set_status(msg):\n            try:\n                status_var.set(msg)\n                win.update_idletasks()\n            except:\n                pass\n\n        # Buttons\n        btn_frame = tk.Frame(win, bg=C[\"panel\"], pady=8)\n        btn_frame.pack(fill=\"x\", side=\"bottom\")\n\n        _bc = dict(font=(\"Segoe UI\", 9, \"bold\"), relief=\"flat\", cursor=\"hand2\", padx=12, pady=6, bd=0)\n\n        btn_analyze = tk.Button(btn_frame, text=\"\ud83d\udcca  Analyze All Browsers\", bg=C[\"btn_info\"], fg=C[\"text\"], **_bc)\n        btn_analyze.pack(side=\"left\", padx=(10,5))\n\n        btn_repair = tk.Button(btn_frame, text=\"\ud83d\udd27  Repair Profiles\", bg=C[\"btn_warn\"], fg=C[\"text\"],\n                              state=\"disabled\", **_bc)\n        btn_repair.pack(side=\"left\", padx=5)\n\n        btn_optimize = tk.Button(btn_frame, text=\"\u26a1  Optimize &amp; Clean\", bg=\"#1a6b3a\", fg=C[\"text\"],\n                                state=\"disabled\", **_bc)\n        btn_optimize.pack(side=\"left\", padx=5)\n\n        btn_rollback = tk.Button(btn_frame, text=\"\u21a9\ufe0f  Rollback Last\", bg=C[\"panel\"], fg=C[\"text\"],\n                                state=\"disabled\", **_bc)\n        btn_rollback.pack(side=\"left\", padx=5)\n\n        # ANALYZE \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        def do_analyze():\n            btn_analyze.config(state=\"disabled\")\n            btn_repair.config(state=\"disabled\")\n            btn_optimize.config(state=\"disabled\")\n            report_txt.configure(state=\"normal\")\n            report_txt.delete(\"1.0\", \"end\")\n            report_txt.configure(state=\"disabled\")\n            tree.delete(*tree.get_children())\n            set_status(\"Analyzing browsers\u2026\")\n\n            def worker():\n                try:\n                    profiles = self._browser_detect_all()\n                    profiles_holder[\"data\"] = profiles\n                    analysis = {}\n\n                    append_report(\"\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\", \"hdr\")\n                    append_report(\"\u2551  ENTERPRISE BROWSER ANALYSIS REPORT    \u2551\", \"hdr\")\n                    append_report(\"\u255a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255d\\n\", \"hdr\")\n\n                    for prof in profiles:\n                        bname = prof.get(\"browser\", \"unknown\")\n                        profile_path = prof.get(\"profile\", \"\")\n                        append_report(f\"\\n\u2550\u2550\u2550 {bname} \u2550\u2550\u2550\", \"bold\")\n\n                        # Comprehensive report\n                        report = self._browser_comprehensive_report(prof)\n                        analysis[bname] = report\n\n                        # Profile size\n                        psize = report.get(\"profile_size_mb\", 0)\n                        csize = report.get(\"cache_size_mb\", 0)\n                        append_report(f\"Profile Size    : {psize} MB\", \"path\")\n                        append_report(f\"Cache Size      : {csize} MB\", \"path\")\n\n                        # Integrity issues\n                        issues = report.get(\"integrity_issues\", [])\n                        if issues:\n                            append_report(f\"Integrity Issues: {len(issues)} found\", \"warn\")\n                            for issue_type, severity, desc in issues[:5]:\n                                append_report(f\"  \u2022 [{severity}] {desc}\", \"muted\")\n                        else:\n                            append_report(\"Integrity      : \u2713 OK\", \"ok\")\n\n                        # Extensions\n                        exts = report.get(\"extensions\", [])\n                        append_report(f\"Extensions      : {len(exts)} installed\", \"path\")\n                        for ext in exts[:3]:\n                            size_kb = ext.get(\"size_bytes\", 0) / 1024\n                            append_report(f\"  \u2022 {ext.get('name', 'unknown')} ({size_kb:.0f} KB)\", \"muted\")\n\n                        # Optimization score\n                        score = report.get(\"optimization_score\", 0)\n                        tag = \"ok\" if score &gt;= 80 else (\"warn\" if score &gt;= 50 else \"err\")\n                        append_report(f\"Optimization Score: {score}/100\", tag)\n\n                        # Add to tree\n                        b_node = tree.insert(\"\", \"end\", text=f\"  {bname}\", values=(\"\", \"\"))\n                        tree.insert(b_node, \"end\", text=f\"Profile Size\", values=(\"\", f\"{psize} MB\"))\n                        tree.insert(b_node, \"end\", text=f\"Cache Size\", values=(\"\", f\"{csize} MB\"))\n                        tree.insert(b_node, \"end\", text=f\"Extensions\", values=(\"\", f\"{len(exts)}\"))\n                        tree.insert(b_node, \"end\", text=f\"Issues\", values=(\"\", f\"{len(issues)}\"))\n                        tree.insert(b_node, \"end\", text=f\"Score\", values=(\"\", f\"{score}/100\"))\n\n                    analysis_holder[\"data\"] = analysis\n                    append_report(\"\\n\u2713 Analysis complete!\", \"ok\")\n\n                    win.after(0, lambda: (\n                        btn_analyze.config(state=\"normal\"),\n                        btn_repair.config(state=\"normal\" if any(analysis.get(b, {}).get(\"integrity_issues\") for b in analysis) else \"disabled\"),\n                        btn_optimize.config(state=\"normal\"),\n                        set_status(\"Analysis complete. Review results above.\"),\n                    ))\n                except Exception as e:\n                    append_report(f\"\u2717 Analysis failed: {str(e)[:100]}\", \"err\")\n                    win.after(0, lambda: btn_analyze.config(state=\"normal\"))\n\n            self._launch_job(\"browser_analyze\", worker)\n\n        # REPAIR \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        def do_repair():\n            btn_repair.config(state=\"disabled\")\n            set_status(\"Attempting profile repairs\u2026\")\n            repaired = 0\n\n            def worker():\n                nonlocal repaired\n                try:\n                    analysis = analysis_holder.get(\"data\", {})\n                    for bname, report in analysis.items():\n                        issues = report.get(\"integrity_issues\", [])\n                        if not issues:\n                            continue\n                        profile_path = report.get(\"profile_path\", \"\")\n                        if not profile_path:\n                            for prof in profiles_holder.get(\"data\", []):\n                                if prof.get(\"browser\") == bname:\n                                    profile_path = prof.get(\"profile\", \"\")\n                                    break\n                        if profile_path:\n                            success, message, repairs = self._browser_corrupted_profile_repair(profile_path)\n                            if success:\n                                repaired += len(repairs)\n                                append_report(f\"\u2713 {bname}: {message}\", \"ok\")\n                            else:\n                                append_report(f\"\u26a0 {bname}: {message}\", \"warn\")\n                    append_report(f\"\\n\u2713 Repair complete: {repaired} issues fixed\", \"ok\")\n                except Exception as e:\n                    append_report(f\"\u2717 Repair failed: {str(e)[:100]}\", \"err\")\n                finally:\n                    win.after(0, lambda: btn_repair.config(state=\"normal\"))\n\n            self._launch_job(\"browser_repair\", worker)\n\n        # OPTIMIZE \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        def do_optimize():\n            btn_optimize.config(state=\"disabled\")\n            set_status(\"Optimizing and cleaning\u2026\")\n\n            def worker():\n                try:\n                    append_report(\"\\n\u2550\u2550\u2550 OPTIMIZATION &amp; CLEANUP \u2550\u2550\u2550\\n\", \"bold\")\n                    total_freed = 0\n\n                    for prof in profiles_holder.get(\"data\", []):\n                        bname = prof.get(\"browser\")\n                        items_to_clean = self._browser_scan_profile(prof)\n                        append_report(f\"{bname}: {len(items_to_clean)} junk items\", \"path\")\n\n                        for path, sz, reason in items_to_clean:\n                            if self._browser_is_protected(path):\n                                append_report(f\"  \u2713 Protected: {os.path.basename(path)}\", \"muted\")\n                                continue\n                            try:\n                                backup_name = os.path.basename(path)\n                                backup_path = os.path.join(cleanup_backup_root, f\"{int(time.time())}_{backup_name}\")\n                                if os.path.isdir(path):\n                                    shutil.copytree(path, backup_path, dirs_exist_ok=True)\n                                    shutil.rmtree(path, ignore_errors=True)\n                                elif os.path.isfile(path):\n                                    os.makedirs(os.path.dirname(backup_path), exist_ok=True)\n                                    shutil.copy2(path, backup_path)\n                                    os.remove(path)\n                                total_freed += sz\n                                cleanup_journal.append({\"original\": path, \"backup\": backup_path, \"size\": sz})\n                                append_report(f\"  \u2713 Cleaned: {os.path.basename(path)}\", \"muted\")\n                            except Exception as e:\n                                append_report(f\"  \u26a0 Failed to clean {os.path.basename(path)}: {e}\", \"warn\")\n\n                    append_report(f\"\\n\u2713 Optimization complete: {self._fmt_size(total_freed)} freed\", \"ok\")\n                    win.after(0, lambda: btn_rollback.config(state=\"normal\" if cleanup_journal else \"disabled\"))\n                except Exception as e:\n                    append_report(f\"\u2717 Optimization failed: {str(e)}\", \"err\")\n                finally:\n                    win.after(0, lambda: btn_optimize.config(state=\"normal\"))\n\n            self._launch_job(\"browser_optimize\", worker)\n\n        def do_rollback():\n            btn_rollback.config(state=\"disabled\")\n            set_status(\"Rolling back browser cleanup\u2026\")\n            append_report(\"\\n\u2550\u2550\u2550 ROLLBACK RESTORATION \u2550\u2550\u2550\", \"bold\")\n            restored = 0\n\n            def worker():\n                nonlocal restored\n                try:\n                    for entry in reversed(cleanup_journal):\n                        orig = entry.get(\"original\")\n                        backup = entry.get(\"backup\")\n                        if not orig or not backup:\n                            continue\n                        try:\n                            if os.path.isdir(backup):\n                                shutil.copytree(backup, orig, dirs_exist_ok=True)\n                                restored += 1\n                            elif os.path.isfile(backup):\n                                os.makedirs(os.path.dirname(orig), exist_ok=True)\n                                shutil.copy2(backup, orig)\n                                restored += 1\n                        except Exception as e:\n                            append_report(f\"  \u26a0 Failed to restore {orig}: {e}\", \"warn\")\n                    append_report(f\"\\n\u2713 Rollback complete: restored {restored} items\", \"ok\")\n                except Exception as e:\n                    append_report(f\"\u2717 Rollback failed: {str(e)[:100]}\", \"err\")\n                finally:\n                    win.after(0, lambda: btn_rollback.config(state=\"normal\" if restored else \"disabled\"))\n\n            self._launch_job(\"browser_rollback\", worker)\n\n        btn_analyze.config(command=do_analyze)\n        btn_repair.config(command=do_repair)\n        btn_optimize.config(command=do_optimize)\n        btn_rollback.config(command=do_rollback)\n\n        # Auto-analyze on open\n        win.after(300, do_analyze)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  END BROWSER BOOST\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _apply_clean_profile(self):\n        profile_name = self.clean_profile_var.get() or \"Office Home\"\n        profiles = get_cleaner_profiles()\n        profile = profiles.get(profile_name) or profiles.get(\"Office Home\")\n        v = self.clean_vars\n        for key in v:\n            try:\n                v[key].set(key in profile[\"targets\"])\n            except Exception:\n                pass\n        self.clean_profile_summary_var.set(profile[\"summary\"])\n        self._append_log(self.clean_log, f\"\u2705 Profile applied: {profile_name} | {profile['summary']}\", C[\"success\"])\n\n    def _large_file_finder_dialog(self):\n        root = filedialog.askdirectory(title=\"Select Folder for Large File Finder\")\n        if not root:\n            return\n        self._launch_job(\"large_file_finder\", self._do_large_file_finder, root)\n\n    def _do_large_file_finder(self, root):\n        try:\n            self._append_log(self.clean_log, \"\u2550\"*50, C[\"border\"])\n            self._append_log(self.clean_log, f\"\ud83d\udce6 Large File Finder starting: {root}\", C[\"accent4\"])\n            top = []  # list of (size, path)\n            scanned = 0\n            for dirpath, _, filenames in os.walk(root):\n                for fn in filenames:\n                    full = os.path.join(dirpath, fn)\n                    try:\n                        sz = os.path.getsize(full)\n                        if len(top) &lt; 50:\n                            top.append((sz, full))\n                            top.sort(key=lambda x: x[0], reverse=True)\n                        else:\n                            if sz &gt; top[-1][0]:\n                                top[-1] = (sz, full)\n                                top.sort(key=lambda x: x[0], reverse=True)\n                    except Exception:\n                        continue\n                scanned += 1\n                if scanned % 300 == 0:\n                    self._append_log(self.clean_log, f\"\u2026 scanned {scanned} folders\", C[\"text_dim\"])\n            self._append_log(self.clean_log, \"\u2705 Top 50 largest files:\", C[\"success\"])\n            for i, (sz, p) in enumerate(top, 1):\n                self._append_log(self.clean_log, f\"{i:02d}. {self._fmt_size(sz)}  {p}\", C[\"text\"])\n            self._set_status(\"Large file finder complete\", C[\"success\"])\n        except Exception as e:\n            self._append_log(self.clean_log, f\"\u274c Large file finder failed: {e}\", C[\"error\"])\n\n    def _open_empty_folder_finder(self):\n        root = filedialog.askdirectory(title=\"Select folder to scan for empty directories\")\n        if not root:\n            return\n        self._launch_job(\"empty_folder_finder\", self._do_empty_folder_finder, root)\n\n    def _do_empty_folder_finder(self, root):\n        try:\n            self._append_log(self.clean_log, \"\u2550\"*50, C[\"border\"])\n            self._append_log(self.clean_log, f\"\ud83d\udcc1 Empty folder scan: {root}\", C[\"accent4\"])\n            empty_dirs = []\n            for dirpath, dirnames, filenames in os.walk(root, topdown=False):\n                if self._clean_job_cancel_event.is_set():\n                    self._append_log(self.clean_log, \"\u26a0\ufe0f Empty folder scan cancelled.\", C[\"warning\"])\n                    return\n                if not dirnames and not filenames:\n                    empty_dirs.append(dirpath)\n                    self._append_log(self.clean_log, f\"  Empty: {dirpath}\", C[\"text\"])\n            self._append_log(self.clean_log, f\"\u2705 Empty folders found: {len(empty_dirs)}\", C[\"success\"])\n            if empty_dirs and messagebox.askyesno(\"Delete Empty Folders\", f\"Delete {len(empty_dirs)} empty folders? This is safe.\"):\n                deleted = 0\n                for d in empty_dirs:\n                    try:\n                        os.rmdir(d)\n                        deleted += 1\n                    except Exception:\n                        pass\n                self._append_log(self.clean_log, f\"\u2705 Deleted empty folders: {deleted}\", C[\"success\"])\n            self._set_status(\"Empty folder scan complete\", C[\"success\"])\n        except Exception as e:\n            self._append_log(self.clean_log, f\"\u274c Empty folder finder failed: {e}\", C[\"error\"])\n\n    def _open_zero_byte_finder(self):\n        root = filedialog.askdirectory(title=\"Select folder to scan for zero-byte files\")\n        if not root:\n            return\n        self._launch_job(\"zero_byte_finder\", self._do_zero_byte_finder, root)\n\n    def _do_zero_byte_finder(self, root):\n        try:\n            self._append_log(self.clean_log, \"\u2550\"*50, C[\"border\"])\n            self._append_log(self.clean_log, f\"0-byte file scan: {root}\", C[\"accent4\"])\n            found = []\n            for dirpath, _, filenames in os.walk(root):\n                if self._clean_job_cancel_event.is_set():\n                    self._append_log(self.clean_log, \"\u26a0\ufe0f Zero-byte scan cancelled.\", C[\"warning\"])\n                    return\n                for name in filenames:\n                    path = os.path.join(dirpath, name)\n                    try:\n                        if os.path.getsize(path) == 0:\n                            found.append(path)\n                            self._append_log(self.clean_log, f\"  0-byte: {path}\", C[\"text\"])\n                    except Exception:\n                        continue\n            self._append_log(self.clean_log, f\"\u2705 Zero-byte files found: {len(found)}\", C[\"success\"])\n            if found and messagebox.askyesno(\"Delete Zero-byte Files\", f\"Delete {len(found)} zero-byte files? This is usually safe.\"):\n                deleted = 0\n                for path in found:\n                    try:\n                        os.remove(path)\n                        deleted += 1\n                    except Exception:\n                        pass\n                self._append_log(self.clean_log, f\"\u2705 Deleted zero-byte files: {deleted}\", C[\"success\"])\n            self._set_status(\"Zero-byte scan complete\", C[\"success\"])\n        except Exception as e:\n            self._append_log(self.clean_log, f\"\u274c Zero-byte finder failed: {e}\", C[\"error\"])\n\n    def _professional_scan(self):\n        if getattr(self, \"_clean_job_running\", False):\n            messagebox.showwarning(\"Busy\", \"A clean operation is already running. Please wait or cancel it first.\")\n            return\n        def before_scan_stats():\n            total = self._calculate_total_junk_size()\n            return f\"Total junk size: {self._fmt_size(total)}\"\n        jid = self._confirm_and_launch_job(\n            \"Professional Junk Scan\",\n            \"This will scan selected locations for temporary, cache, and log files.\\nNo files will be deleted yet. You will see the total space that can be freed.\",\n            before_scan_stats,\n            \"junk_scan\",\n            self._do_clean_scan\n        )\n        if jid:\n            self._clean_job_cancel_event.clear()\n            self._set_clean_job_state(running=True)\n            self._set_status(\"Professional Junk Scan started...\", C[\"accent4\"])\n\n    def _professional_clean(self):\n        if getattr(self, \"_clean_job_running\", False):\n            messagebox.showwarning(\"Busy\", \"A clean operation is already running. Please wait or cancel it first.\")\n            return\n        def before_clean_stats():\n            total = self._calculate_total_junk_size()\n            return f\"Junk to delete: {self._fmt_size(total)}\"\n        jid = self._confirm_and_launch_job(\n            \"Professional Junk Clean\",\n            \"This will PERMANENTLY DELETE selected junk files.\\nIt is safe for normal use but cannot be undone.\\nMake sure you have scanned first.\",\n            before_clean_stats,\n            \"junk_clean\",\n            self._do_clean\n        )\n        if jid:\n            self._clean_job_cancel_event.clear()\n            self._set_clean_job_state(running=True)\n            self._set_status(\"Professional Junk Clean started...\", C[\"accent4\"])\n\n    def _calculate_total_junk_size(self):\n        total = 0\n        for label, path in self._get_clean_paths():\n            if not path or not os.path.exists(path):\n                continue\n            total += self._folder_size(path)\n        return total\n\n    def _do_clean_scan(self):\n        paths = list(self._get_clean_paths())\n        total_paths = len(paths)\n\n        def _append_scan_entry(label, size, path, current_total, processed):\n            self._append_log(self.clean_log, f\"\ud83d\udcc1 {label:&lt;30s}  {self._fmt_size(size)}\", C[\"text\"])\n            self._append_log(self.clean_log, f\"      \ud83d\udccd {path}\", C[\"text_dim\"])\n            self.clean_size_lbl.config(text=f\"Total junk found: {self._fmt_size(current_total)}\")\n            self.clean_progress_var.set(processed)\n            self.clean_progress_lbl.config(text=f\"Scanning {processed}/{total_paths} targets\")\n\n        def _append_scan_error(label, error_text, processed):\n            self._append_log(self.clean_log, f\"  \u274c {label:&lt;30s}  [Error: {error_text}]\", C[\"error\"])\n            self.clean_progress_var.set(processed)\n            self.clean_progress_lbl.config(text=f\"Scanning {processed}/{total_paths} targets\")\n\n        self.after(0, lambda: self._set_status(\"Scanning junk...\", C[\"accent4\"]))\n        self.after(0, lambda: self.clean_progress_bar.config(mode=\"determinate\", maximum=max(1, total_paths)))\n        self.after(0, lambda: self.clean_progress_var.set(0))\n        total_size = 0\n        scanned = 0\n        errors = 0\n        canceled = False\n        if total_paths == 0:\n            self.after(0, lambda: self.clean_size_lbl.config(text=\"Total junk found: --\"))\n            self.after(0, self._finalize_clean_job, \"scan\", {\"total_paths\": 0, \"processed\": 0, \"total_size\": 0, \"errors\": 0, \"canceled\": False})\n            return\n\n        for label, path in paths:\n            if self._clean_job_cancel_event.is_set():\n                canceled = True\n                break\n            if not path or not os.path.exists(path):\n                errors += 1\n                scanned += 1\n                self.after(0, _append_scan_error, label, \"Path missing or inaccessible\", scanned)\n                continue\n            try:\n                size = self._folder_size(path)\n                total_size += size\n                scanned += 1\n                self.after(0, _append_scan_entry, label, size, path, total_size, scanned)\n            except Exception as e:\n                errors += 1\n                scanned += 1\n                self.after(0, _append_scan_error, label, str(e), scanned)\n\n        self.after(0, self._finalize_clean_job, \"scan\", {\n            \"total_paths\": total_paths,\n            \"processed\": scanned,\n            \"total_size\": total_size,\n            \"errors\": errors,\n            \"canceled\": canceled,\n        })\n\n    def _do_clean(self):\n        paths = list(self._get_clean_paths())\n        total_paths = len(paths)\n        preview = getattr(self, \"clean_preview_var\", tk.BooleanVar(value=False)).get()\n\n        def _append_clean_entry(label, freed, processed):\n            verb = \"Previewed\" if preview else \"Cleaned\"\n            self._append_log(self.clean_log, f\"\u2705 {verb}: {label} ({self._fmt_size(freed)} freed)\", C[\"success\"])\n            self.clean_progress_var.set(processed)\n            self.clean_progress_lbl.config(text=f\"{verb} {processed}/{total_paths} targets\")\n\n        def _append_clean_error(label, error_text, processed):\n            self._append_log(self.clean_log, f\"  \u274c {label:&lt;30s}  [Error: {error_text}]\", C[\"error\"])\n            self.clean_progress_var.set(processed)\n            self.clean_progress_lbl.config(text=f\"Processing {processed}/{total_paths} targets\")\n\n        self.after(0, lambda: self._set_status(\"Deleting junk...\" if not preview else \"Previewing deletions...\", C[\"accent4\"]))\n        self.after(0, lambda: self.clean_progress_bar.config(mode=\"determinate\", maximum=max(1, total_paths)))\n        self.after(0, lambda: self.clean_progress_var.set(0))\n        total_removed = 0\n        processed = 0\n        errors = 0\n        canceled = False\n        if total_paths == 0:\n            self.after(0, lambda: self.clean_size_lbl.config(text=\"Total junk found: -- (no targets)\"))\n            self.after(0, self._finalize_clean_job, \"clean\", {\n                \"total_paths\": 0,\n                \"processed\": 0,\n                \"freed\": 0,\n                \"remaining\": 0,\n                \"errors\": 0,\n                \"canceled\": False,\n                \"preview\": preview,\n            })\n            return\n\n        for label, path in paths:\n            if self._clean_job_cancel_event.is_set():\n                canceled = True\n                break\n            if not path or not os.path.exists(path):\n                errors += 1\n                processed += 1\n                self.after(0, _append_clean_error, label, \"Path missing or inaccessible\", processed)\n                continue\n            try:\n                if preview:\n                    freed = 0\n                    self.after(0, self._append_log, self.clean_log, f\"\ud83d\udd0e Preview: {label} would be cleaned\", C[\"accent\"])\n                else:\n                    freed = self._delete_folder_contents(path)\n                total_removed += freed\n                processed += 1\n                self.after(0, _append_clean_entry, label, freed, processed)\n            except Exception as e:\n                errors += 1\n                processed += 1\n                self.after(0, _append_clean_error, label, str(e), processed)\n\n        remaining = self._calculate_total_junk_size() if not preview else total_removed\n        self.after(0, self._finalize_clean_job, \"clean\", {\n            \"total_paths\": total_paths,\n            \"processed\": processed,\n            \"freed\": total_removed,\n            \"remaining\": remaining,\n            \"errors\": errors,\n            \"canceled\": canceled,\n            \"preview\": preview,\n        })\n\n    def _get_clean_paths(self):\n        v = self.clean_vars\n        paths = []\n        if v.get(\"temp\") and v[\"temp\"].get():\n            paths.append((\"Windows Temp\", r\"C:\\Windows\\Temp\"))\n        if v.get(\"user_temp\") and v[\"user_temp\"].get():\n            paths.append((\"User Temp\", os.environ.get(\"TEMP\", \"\")))\n        if v.get(\"prefetch\") and v[\"prefetch\"].get():\n            paths.append((\"Prefetch\", r\"C:\\Windows\\Prefetch\"))\n        if v.get(\"recycle\") and v[\"recycle\"].get():\n            paths.append((\"Recycle Bin\", r\"C:\\$Recycle.Bin\"))\n        if v.get(\"logs\") and v[\"logs\"].get():\n            paths.append((\"Windows Logs\", r\"C:\\Windows\\Logs\"))\n        if v.get(\"thumbnail\") and v[\"thumbnail\"].get():\n            paths.append((\"Thumbnails\", os.path.join(os.environ.get(\"LOCALAPPDATA\",\"\"), r\"Microsoft\\Windows\\Explorer\")))\n        if v.get(\"update\") and v[\"update\"].get():\n            paths.append((\"WU Cache\", r\"C:\\Windows\\SoftwareDistribution\\Download\"))\n        if v.get(\"dumps\") and v[\"dumps\"].get():\n            paths.append((\"Memory Dumps\", r\"C:\\Windows\\Minidump\"))\n        if v.get(\"errreport\") and v[\"errreport\"].get():\n            paths.append((\"Error Reports\", os.path.join(os.environ.get(\"LOCALAPPDATA\",\"\"), r\"Microsoft\\Windows\\WER\")))\n        if v.get(\"delivery\") and v[\"delivery\"].get():\n            paths.append((\"DO Cache\", os.path.join(os.environ.get(\"PROGRAMDATA\",\"\"), r\"Microsoft\\Windows\\DeliveryOptimization\\Cache\")))\n        if v.get(\"browser_office\") and v[\"browser_office\"].get():\n            local = os.environ.get(\"LOCALAPPDATA\",\"\")\n            roaming = os.environ.get(\"APPDATA\",\"\")\n            paths.extend([\n                # Browsers (primary caches)\n                (\"Chrome Cache\", os.path.join(local, \"Google\\\\Chrome\\\\User Data\\\\Default\\\\Cache\")),\n                (\"Chrome Code Cache\", os.path.join(local, \"Google\\\\Chrome\\\\User Data\\\\Default\\\\Code Cache\")),\n                (\"Edge Cache\", os.path.join(local, \"Microsoft\\\\Edge\\\\User Data\\\\Default\\\\Cache\")),\n                (\"Edge Code Cache\", os.path.join(local, \"Microsoft\\\\Edge\\\\User Data\\\\Default\\\\Code Cache\")),\n                (\"Firefox Cache\", os.path.join(local, \"Mozilla\\\\Firefox\\\\Profiles\")),\n                # Microsoft apps\n                (\"Office File Cache\", os.path.join(local, \"Microsoft\\\\Office\\\\16.0\\\\OfficeFileCache\")),\n                (\"Teams Cache\", os.path.join(roaming, \"Microsoft\\\\Teams\")),\n                (\"Teams (new) Cache\", os.path.join(local, \"Packages\\\\MSTeams_8wekyb3d8bbwe\\\\LocalCache\")),\n                (\"OneDrive Logs\", os.path.join(local, \"Microsoft\\\\OneDrive\\\\logs\")),\n                # Common app temp\n                (\"INetCache\", os.path.join(local, \"Microsoft\\\\Windows\\\\INetCache\")),\n            ])\n        return paths\n\n    def _is_reparse_point(self, path):\n        try:\n            st = os.stat(path, follow_symlinks=False)\n            attrs = getattr(st, \"st_file_attributes\", 0)\n            # FILE_ATTRIBUTE_REPARSE_POINT = 0x400 (junction/symlink)\n            return bool(attrs &amp; 0x400)\n        except Exception:\n            return False\n\n    def _safe_scandir(self, path):\n        try:\n            with os.scandir(path) as it:\n                for entry in it:\n                    yield entry\n        except Exception:\n            return\n\n    def _folder_size(self, path):\n        def _walk(p):\n            total = 0\n            try:\n                if not p or not os.path.exists(p):\n                    return 0\n                if os.path.isfile(p):\n                    try:\n                        return os.path.getsize(p)\n                    except Exception:\n                        return 0\n                if self._is_reparse_point(p):\n                    return 0\n                for ent in self._safe_scandir(p):\n                    try:\n                        if ent.is_symlink():\n                            continue\n                        if ent.is_file(follow_symlinks=False):\n                            try:\n                                total += ent.stat(follow_symlinks=False).st_size\n                            except Exception:\n                                pass\n                        elif ent.is_dir(follow_symlinks=False):\n                            if self._is_reparse_point(ent.path):\n                                continue\n                            total += _walk(ent.path)\n                    except Exception:\n                        continue\n            except Exception:\n                return total\n            return total\n        return _walk(path)\n\n    def _delete_folder_contents(self, path):\n        removed = 0\n        try:\n            if not path or not os.path.exists(path):\n                return 0\n            if os.path.isfile(path):\n                try:\n                    removed = os.path.getsize(path)\n                except Exception:\n                    removed = 0\n                try:\n                    os.remove(path)\n                except Exception:\n                    return 0\n                return removed\n            # Safety: never delete a reparse-point directory target\n            if self._is_reparse_point(path):\n                return 0\n\n            for ent in self._safe_scandir(path):\n                try:\n                    if ent.is_symlink():\n                        continue\n                    if ent.is_file(follow_symlinks=False):\n                        try:\n                            sz = ent.stat(follow_symlinks=False).st_size\n                        except Exception:\n                            sz = 0\n                        try:\n                            os.remove(ent.path)\n                            removed += sz\n                        except Exception:\n                            continue\n                    elif ent.is_dir(follow_symlinks=False):\n                        if self._is_reparse_point(ent.path):\n                            continue\n                        try:\n                            sz = self._folder_size(ent.path)\n                        except Exception:\n                            sz = 0\n                        try:\n                            shutil.rmtree(ent.path, ignore_errors=True)\n                            removed += sz\n                        except Exception:\n                            continue\n                except Exception:\n                    continue\n        except Exception:\n            return removed\n        return removed\n\n    # ---------- SERVICES (unchanged but with confirm wrappers) ----------\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  SERVICE KNOWLEDGE BASE\n    #  Category:  \"critical\"  = Windows ka dil \u2014 kabhi band mat karo\n    #             \"important\" = Windows ka kaam rukta hai \u2014 soch ke karo\n    #             \"optional\"  = Disable kar sakte ho \u2014 performance badhegi\n    #             \"thirdparty\"= Third-party software ki service\n    #  safe_to_stop: True/False \u2014 kya sirf stop safe hai\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    SVC_DB = {\n        # \u2500\u2500 CRITICAL \u2014 kabhi mat chhuo \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        \"lsass\":         {\"cat\":\"critical\",\"safe_to_stop\":False,\n                          \"desc\":\"Windows Login &amp; Security Authority. Isko band karna = Blue Screen ya instant shutdown.\",\n                          \"display\":\"Local Security Authority Process\"},\n        \"wininit\":       {\"cat\":\"critical\",\"safe_to_stop\":False,\n                          \"desc\":\"Windows Initialization. System start ke liye zaroori hai.\",\n                          \"display\":\"Windows Start-Up Application\"},\n        \"services\":      {\"cat\":\"critical\",\"safe_to_stop\":False,\n                          \"desc\":\"Saari services ka manager. Isko band karna = system crash.\",\n                          \"display\":\"Services and Controller app\"},\n        \"rpcss\":         {\"cat\":\"critical\",\"safe_to_stop\":False,\n                          \"desc\":\"RPC (Remote Procedure Call). Saare Windows components isko use karte hain.\",\n                          \"display\":\"Remote Procedure Call (RPC)\"},\n        \"dcomlaunch\":    {\"cat\":\"critical\",\"safe_to_stop\":False,\n                          \"desc\":\"COM Server launch. Explorer, taskbar sab band ho jaayenge.\",\n                          \"display\":\"DCOM Server Process Launcher\"},\n        \"plugplay\":      {\"cat\":\"critical\",\"safe_to_stop\":False,\n                          \"desc\":\"Hardware detect karta hai. USB, keyboard, mouse sab band ho jaayenge.\",\n                          \"display\":\"Plug and Play\"},\n        \"windefend\":     {\"cat\":\"critical\",\"safe_to_stop\":False,\n                          \"desc\":\"Windows Defender Antivirus. Virus protection band ho jaayegi.\",\n                          \"display\":\"Windows Defender Antivirus Service\"},\n        \"mpssvc\":        {\"cat\":\"critical\",\"safe_to_stop\":False,\n                          \"desc\":\"Windows Firewall. Internet security band ho jaayegi.\",\n                          \"display\":\"Windows Defender Firewall\"},\n        \"eventlog\":      {\"cat\":\"critical\",\"safe_to_stop\":False,\n                          \"desc\":\"System Event Log. Band karne se system instability aa sakti hai.\",\n                          \"display\":\"Windows Event Log\"},\n        \"nsi\":           {\"cat\":\"critical\",\"safe_to_stop\":False,\n                          \"desc\":\"Network Store Interface. Internet/network band ho jaayega.\",\n                          \"display\":\"Network Store Interface Service\"},\n        \"dhcp\":          {\"cat\":\"critical\",\"safe_to_stop\":False,\n                          \"desc\":\"IP Address automatic milti hai isse. Band = no internet.\",\n                          \"display\":\"DHCP Client\"},\n        \"dnscache\":      {\"cat\":\"critical\",\"safe_to_stop\":False,\n                          \"desc\":\"DNS Cache. Band karne se websites nahi khulengi.\",\n                          \"display\":\"DNS Client\"},\n        \"cryptsvc\":      {\"cat\":\"critical\",\"safe_to_stop\":False,\n                          \"desc\":\"Windows Updates aur certificates ke liye zaroori hai.\",\n                          \"display\":\"Cryptographic Services\"},\n        \"wuauserv\":      {\"cat\":\"critical\",\"safe_to_stop\":True,\n                          \"desc\":\"Windows Update. Stop kar sakte ho lekin security risk hai. Disable mat karo permanently.\",\n                          \"display\":\"Windows Update\"},\n        \"bits\":          {\"cat\":\"important\",\"safe_to_stop\":True,\n                          \"desc\":\"Background download manager. Windows updates isi se aate hain.\",\n                          \"display\":\"Background Intelligent Transfer Service\"},\n        \"spooler\":       {\"cat\":\"important\",\"safe_to_stop\":True,\n                          \"desc\":\"Printer service. Agar printer nahi use karte to stop kar sakte ho.\",\n                          \"display\":\"Print Spooler\"},\n        \"audiosrv\":      {\"cat\":\"important\",\"safe_to_stop\":False,\n                          \"desc\":\"Sound service. Band karne se koi awaz nahi aayegi.\",\n                          \"display\":\"Windows Audio\"},\n        \"audioendpointbuilder\":{\"cat\":\"important\",\"safe_to_stop\":False,\n                          \"desc\":\"Audio devices manager. Band = no sound.\",\n                          \"display\":\"Windows Audio Endpoint Builder\"},\n        \"netlogon\":      {\"cat\":\"important\",\"safe_to_stop\":True,\n                          \"desc\":\"Domain/network login ke liye. Home PC pe stop kar sakte ho.\",\n                          \"display\":\"Netlogon\"},\n        \"lanmanworkstation\":{\"cat\":\"important\",\"safe_to_stop\":True,\n                          \"desc\":\"Network shared folders access. Agar network nahi use karte to stop kar sakte ho.\",\n                          \"display\":\"Workstation\"},\n        \"lanmanserver\":  {\"cat\":\"important\",\"safe_to_stop\":True,\n                          \"desc\":\"Apni files share karne ke liye. Home use mein stop kar sakte ho.\",\n                          \"display\":\"Server\"},\n        \"themes\":        {\"cat\":\"important\",\"safe_to_stop\":True,\n                          \"desc\":\"Windows visual theme. Band karne se plain grey Windows dikhegi.\",\n                          \"display\":\"Themes\"},\n        \"winmgmt\":       {\"cat\":\"important\",\"safe_to_stop\":False,\n                          \"desc\":\"WMI \u2014 Hardware info, monitoring tools isi se kaam karte hain.\",\n                          \"display\":\"Windows Management Instrumentation\"},\n        \"schedule\":      {\"cat\":\"important\",\"safe_to_stop\":False,\n                          \"desc\":\"Task Scheduler. Band karne se system tasks nahi chalenge.\",\n                          \"display\":\"Task Scheduler\"},\n        \"seclogon\":      {\"cat\":\"important\",\"safe_to_stop\":True,\n                          \"desc\":\"Secondary Logon. Multiple user accounts ke liye. Home PC pe safe to stop.\",\n                          \"display\":\"Secondary Logon\"},\n        \"usermanager\":   {\"cat\":\"important\",\"safe_to_stop\":False,\n                          \"desc\":\"User account manager. Band karne se login problems.\",\n                          \"display\":\"User Manager\"},\n        # \u2500\u2500 OPTIONAL \u2014 safely disable kar sakte ho \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        \"sysmain\":       {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Superfetch/Prefetch \u2014 RAM mein programs preload karta hai. SSD pe disable karo \u2014 speed badhegi.\",\n                          \"display\":\"SysMain (Superfetch)\"},\n        \"wsearch\":       {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Windows Search Indexing \u2014 continuously disk scan karta hai. Agar search use nahi karte to disable karo.\",\n                          \"display\":\"Windows Search\"},\n        \"diagtrack\":     {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Microsoft Telemetry \u2014 aapki usage data Microsoft ko bhejta hai. Safely disable kar sakte ho.\",\n                          \"display\":\"Connected User Experiences and Telemetry\"},\n        \"dmwappushservice\":{\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"WAP Push Message Routing \u2014 zyada tar unnecessary hai. Safe to disable.\",\n                          \"display\":\"Device Management WAP Push message Routing Service\"},\n        \"xblAuthmanager\":{\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Xbox Live Authentication \u2014 gaming nahi karte to bilkul disable karo.\",\n                          \"display\":\"Xbox Live Auth Manager\"},\n        \"xboxnetapitsvc\":{\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Xbox networking \u2014 Xbox use nahi karte to disable karo.\",\n                          \"display\":\"Xbox Live Networking Service\"},\n        \"xblgamesave\":   {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Xbox game save sync \u2014 Xbox nahi use karte to disable.\",\n                          \"display\":\"Xbox Live Game Save\"},\n        \"retaildemo\":    {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Retail Demo Mode \u2014 shop display ke liye hai. Home PC pe bilkul disable karo.\",\n                          \"display\":\"Retail Demo Service\"},\n        \"mapsbrok\":      {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Windows Maps offline download. Maps use nahi karte to disable.\",\n                          \"display\":\"Downloaded Maps Manager\"},\n        \"fax\":           {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Fax service \u2014 2024 mein fax kaun karta hai? Disable karo.\",\n                          \"display\":\"Fax\"},\n        \"remoteregistry\":{\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Remote Registry access \u2014 Security risk! Disable karo immediately.\",\n                          \"display\":\"Remote Registry\"},\n        \"remoteaccess\":  {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Remote Access \u2014 agar koi remotely connect nahi karta to disable karo.\",\n                          \"display\":\"Routing and Remote Access\"},\n        \"wersvc\":        {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Windows Error Reporting \u2014 crash reports Microsoft ko bhejta hai. Disable kar sakte ho.\",\n                          \"display\":\"Windows Error Reporting Service\"},\n        \"printnotify\":   {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Printer notifications \u2014 printer nahi hai to disable karo.\",\n                          \"display\":\"Printer Extensions and Notifications\"},\n        \"sharedaccess\":  {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Internet Connection Sharing \u2014 router hai to ye zaruri nahi. Disable karo.\",\n                          \"display\":\"Internet Connection Sharing (ICS)\"},\n        \"sensrsvc\":      {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Sensor Service \u2014 laptop sensors (gyroscope etc). Desktop pe disable karo.\",\n                          \"display\":\"Sensor Service\"},\n        \"wbiosrvc\":      {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Windows Biometric (fingerprint/face ID). Use nahi karte to disable.\",\n                          \"display\":\"Windows Biometric Service\"},\n        \"tabletinputservice\":{\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Touch/Pen Input. Touchscreen/stylus nahi hai to disable karo.\",\n                          \"display\":\"Touch Keyboard and Handwriting Panel Service\"},\n        \"stisvc\":        {\"cat\":\"optional\",\"safe_to_stop\":True,\n                          \"desc\":\"Scanner/Camera service. Use nahi karte to disable.\",\n                          \"display\":\"Windows Image Acquisition (WIA)\"},\n    }\n\n    # Tag colors per category\n    SVC_TAG_COLORS = {\n        \"critical\":   \"#FF4444\",   # Lal \u2014 danger\n        \"important\":  \"#FF9800\",   # Orange \u2014 warning\n        \"optional\":   \"#4CAF50\",   # Green \u2014 safe to touch\n        \"thirdparty\": \"#CE93D8\",   # Purple \u2014 third party\n        \"highcpu\":    \"#FF6B35\",   # Deep orange \u2014 high CPU\n        \"highmem\":    \"#FFD700\",   # Gold \u2014 high RAM\n    }\n\n    def _build_services(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\u2699\ufe0f Smart Services Manager\",\n                             \"Color-coded \u2014 Critical / Important / Optional / Third-Party\")\n\n        self._action_card_grid(frame, [\n            (\"\ud83d\udd0d\", \"Scan All Services\",    \"Saari services scan karo\",            C[\"btn_info\"],   self._scan_impacting_services),\n            (\"\u26d4\", \"Stop Selected\",        \"Selected services band karo\",          C[\"btn_danger\"], lambda: self._svc_action_safe(\"stop\")),\n            (\"\u2705\", \"Start Selected\",       \"Selected services shuru karo\",         C[\"btn\"],        lambda: self._with_confirm(\"Start Services\",\"Start selected services?\", self._start_services)),\n            (\"\ud83d\udeab\", \"Disable Selected\",     \"Selected services disable karo\",       C[\"btn_warn\"],   lambda: self._svc_action_safe(\"disable\")),\n            (\"\u26a1\", \"Disable All Optional\", \"Saari optional services ek click mein\",C[\"btn_chip\"],   self._disable_all_optional),\n            (\"\ud83d\udcbb\", \"Pack: SSD Laptop\",     \"SSD laptop ke liye best preset\",       C[\"btn_chip\"],   lambda: self._svc_apply_pack(\"ssd_laptop\")),\n            (\"\ud83d\udda5\",  \"Pack: HDD Desktop\",   \"HDD desktop ke liye best preset\",      C[\"btn_chip\"],   lambda: self._svc_apply_pack(\"hdd_desktop\")),\n            (\"\u21a9\",  \"Restore Snapshot\",    \"Pehle wali state wapas lao\",           C[\"btn_info\"],   self._svc_restore_snapshot),\n        ], cols=4)\n\n        # \u2500\u2500 Legend \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        leg = tk.Frame(frame, bg=C[\"bg\"])\n        leg.pack(fill=\"x\", padx=16, pady=(4,0))\n        legends = [\n            (\"\ud83d\udd34 Critical \u2014 Kabhi band mat karo\",     \"#FF4444\"),\n            (\"\ud83d\udfe0 Important \u2014 Soch ke band karo\",      \"#FF9800\"),\n            (\"\ud83d\udfe2 Optional \u2014 Safely disable kar sakte\", \"#4CAF50\"),\n            (\"\ud83d\udfe3 Third-Party Software\",                \"#CE93D8\"),\n            (\"\ud83d\udfe1 High RAM Use\",                        \"#FFD700\"),\n            (\"\ud83d\udd36 High CPU Use\",                        \"#FF6B35\"),\n        ]\n        for i, (txt, col) in enumerate(legends):\n            tk.Label(leg, text=txt, font=FONTS[\"small\"], fg=col,\n                     bg=C[\"bg\"]).grid(row=i//3, column=i%3, sticky=\"w\", padx=12, pady=1)\n\n        # \u2500\u2500 Filter bar \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        fbar = tk.Frame(frame, bg=C[\"bg\"])\n        fbar.pack(fill=\"x\", padx=16, pady=(4,2))\n        tk.Label(fbar, text=\"Filter:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"]).pack(side=\"left\")\n        self.svc_search = tk.Entry(fbar, width=22, font=FONTS[\"body\"],\n                                   bg=C[\"card\"], fg=C[\"text\"],\n                                   insertbackground=C[\"text\"], relief=\"flat\", bd=4)\n        self.svc_search.pack(side=\"left\", padx=6)\n        self.svc_search.bind(\"\", self._filter_services)\n        for lbl, val in [(\"All\",\"all\"),(\"\ud83d\udd34 Critical\",\"critical\"),\n                         (\"\ud83d\udfe0 Important\",\"important\"),(\"\ud83d\udfe2 Optional\",\"optional\"),\n                         (\"\ud83d\udfe3 3rd Party\",\"thirdparty\"),(\"\ud83d\udfe1 High RAM\",\"highmem\"),\n                         (\"\ud83d\udd36 High CPU\",\"highcpu\")]:\n            tk.Button(fbar, text=lbl, font=FONTS[\"small\"],\n                      bg=C[\"card\"], fg=C[\"text\"], bd=0, padx=8, pady=3,\n                      cursor=\"hand2\",\n                      command=lambda v=val: self._filter_by_cat(v)).pack(side=\"left\", padx=2)\n\n        self.svc_count_lbl = tk.Label(fbar, text=\"\", font=FONTS[\"small\"],\n                                      fg=C[\"accent\"], bg=C[\"bg\"])\n        self.svc_count_lbl.pack(side=\"right\", padx=8)\n\n        metric_bar = tk.Frame(frame, bg=C[\"bg\"])\n        metric_bar.pack(fill=\"x\", padx=16, pady=(4,4))\n        self.svc_scan_status_lbl = tk.Label(metric_bar, text=\"Ready to scan services\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"])\n        self.svc_scan_status_lbl.pack(side=\"left\")\n        self.svc_risk_score_var = tk.StringVar(value=\"--\")\n        self.svc_potential_free_var = tk.StringVar(value=\"--\")\n        for label, var in [(\"Risk Score\", self.svc_risk_score_var), (\"Potential RAM\", self.svc_potential_free_var)]:\n            card = tk.Frame(metric_bar, bg=C[\"card\"], padx=8, pady=6)\n            card.pack(side=\"right\", padx=4)\n            tk.Label(card, text=label, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\")\n            tk.Label(card, textvariable=var, font=(\"Segoe UI\", 13, \"bold\"), fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\")\n\n        # \u2500\u2500 Paned layout \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        paned = tk.Frame(frame, bg=C[\"bg\"])\n        paned.pack(fill=\"both\", expand=True, padx=16, pady=(4,8))\n        paned.columnconfigure(0, weight=3)\n        paned.columnconfigure(1, weight=2)\n        paned.rowconfigure(0, weight=1)\n\n        # Left \u2014 service list\n        left = tk.Frame(paned, bg=C[\"card\"])\n        left.grid(row=0, column=0, sticky=\"nsew\", padx=(0,6))\n        cols = (\"Cat\",\"Name\",\"Display Name\",\"Status\",\"CPU%\",\"RAM MB\",\"Safe Stop?\")\n        self.svc_tree = ttk.Treeview(left, columns=cols, show=\"headings\",\n                                     height=22, style=\"Custom.Treeview\",\n                                     selectmode=\"extended\")\n        widths = [28, 160, 210, 75, 55, 70, 80]\n        for col, w in zip(cols, widths):\n            self.svc_tree.heading(col, text=col,\n                                  command=lambda c=col: self._sort_svc(c))\n            self.svc_tree.column(col, width=w,\n                                 anchor=\"center\" if col in (\"Cat\",\"Status\",\"CPU%\",\"RAM MB\",\"Safe Stop?\") else \"w\")\n\n        # Color tags\n        for tag, color in self.SVC_TAG_COLORS.items():\n            self.svc_tree.tag_configure(tag, foreground=color)\n        self.svc_tree.tag_configure(\"highcpu_bg\", background=\"#2A1500\")\n        self.svc_tree.tag_configure(\"highmem_bg\", background=\"#1A1A00\")\n\n        vsb = ttk.Scrollbar(left, orient=\"vertical\", command=self.svc_tree.yview)\n        self.svc_tree.configure(yscrollcommand=vsb.set)\n        self.svc_tree.pack(side=\"left\", fill=\"both\", expand=True, padx=(4,0), pady=4)\n        vsb.pack(side=\"right\", fill=\"y\", pady=4)\n        self.svc_tree.bind(\"&lt;&gt;\", self._on_svc_select)\n\n        # Right \u2014 detail panel\n        right = tk.Frame(paned, bg=C[\"card\"])\n        right.grid(row=0, column=1, sticky=\"nsew\")\n        right.rowconfigure(1, weight=1)\n        right.columnconfigure(0, weight=1)\n\n        tk.Label(right, text=\"  \ud83d\udccb Service Detail &amp; Risk Info\",\n                 font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(\n                 anchor=\"w\", pady=(8,4), padx=8)\n\n        self.svc_detail = scrolledtext.ScrolledText(\n            right, font=(\"Consolas\", 9), bg=\"#0D1117\", fg=C[\"text\"],\n            height=16, bd=0, relief=\"flat\", state=\"disabled\", wrap=\"word\")\n        self.svc_detail.pack(fill=\"both\", expand=True, padx=8, pady=(0,6))\n        self.svc_action_log = self.svc_detail\n\n        # Risk summary cards at bottom of right panel\n        rsum = tk.Frame(right, bg=C[\"card\"])\n        rsum.pack(fill=\"x\", padx=8, pady=(0,8))\n        self.svc_summary_vars = {}\n        for i, (k, lbl, col) in enumerate([\n            (\"critical\",   \"Critical\",    \"#FF4444\"),\n            (\"important\",  \"Important\",   \"#FF9800\"),\n            (\"optional\",   \"Optional\",    \"#4CAF50\"),\n            (\"thirdparty\", \"3rd Party\",   \"#CE93D8\"),\n        ]):\n            rsum.columnconfigure(i, weight=1)\n            card = tk.Frame(rsum, bg=C[\"bg\"], padx=6, pady=6)\n            card.grid(row=0, column=i, padx=3, sticky=\"ew\")\n            tk.Label(card, text=lbl, font=FONTS[\"small\"],\n                     fg=col, bg=C[\"bg\"]).pack(anchor=\"w\")\n            v = tk.StringVar(value=\"--\")\n            self.svc_summary_vars[k] = v\n            tk.Label(card, textvariable=v, font=(\"Segoe UI\",15,\"bold\"),\n                     fg=col, bg=C[\"bg\"]).pack(anchor=\"w\")\n\n        # Internal state\n        self._svc_all_rows = []   # (values_tuple, tags_tuple, meta_dict)\n        self._svc_cur_filter_cat = \"all\"\n        self._svc_sort_col = \"\"\n        self._svc_sort_rev = False\n        return frame\n\n    def _with_confirm(self, title, msg, action):\n        if messagebox.askyesno(title, msg):\n            action()\n\n    # \u2500\u2500 Service scan \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _scan_impacting_services(self):\n        self._set_status(\"Queued: Scanning services...\", C[\"accent4\"])\n        self._submit_ram_service_job(\"service_scan\", self._do_scan_services)\n\n    def _do_scan_services(self):\n        try:\n            self.after(0, lambda: [self.svc_tree.delete(i) for i in self.svc_tree.get_children()])\n        except Exception:\n            pass\n\n        pid_cpu, pid_mem = {}, {}\n        try:\n            for p in psutil.process_iter(['pid','cpu_percent','memory_info']):\n                try:\n                    pid_cpu[p.info['pid']] = p.info['cpu_percent'] or 0\n                    mem = p.info.get('memory_info')\n                    pid_mem[p.info['pid']] = round(mem.rss/(1024**2),1) if mem else 0\n                except Exception:\n                    pass\n        except Exception:\n            pass\n\n        THIRD_PARTY_PATHS = {\n            \"nvidia\",\"amd\",\"intel graphics\",\"realtek\",\"qualcomm\",\"broadcom\",\n            \"avast\",\"avg\",\"kaspersky\",\"mcafee\",\"norton\",\"malwarebytes\",\"bitdefender\",\n            \"adobe\",\"acrobat\",\"google\",\"chrome\",\"dropbox\",\"onedrive\",\"teams\",\n            \"skype\",\"zoom\",\"spotify\",\"discord\",\"steam\",\"epic games\",\"origin\",\n            \"vmware\",\"virtualbox\",\"ccleaner\",\"iobit\",\"razer\",\"corsair\",\"logitech\",\n            \"hp\",\"dell\",\"lenovo\",\"asus\",\"acer\",\"samsung\",\"brother\",\"canon\",\"epson\",\n        }\n\n        try:\n            services = list(psutil.win_service_iter())\n        except Exception:\n            services = []\n        total_services = max(1, len(services))\n\n        rows = []\n        cat_counts = {\"critical\":0,\"important\":0,\"optional\":0,\"thirdparty\":0}\n        batch = {\n            \"phase\":\"service_scan\",\n            \"status_text\":\"Scanning services...\",\n            \"progress_pct\":0,\n            \"services_scanned\":0,\n            \"high_cpu\":0,\n            \"high_mem\":0,\n            \"critical\":0,\n            \"important\":0,\n            \"optional\":0,\n            \"thirdparty\":0,\n            \"estimated_ram_mb\":0,\n            \"risk_score\":0,\n        }\n        last_dispatch = time.time()\n\n        def dispatch_metrics():\n            try:\n                points = (batch[\"critical\"] * 6 + batch[\"important\"] * 4 + batch[\"thirdparty\"] * 2 + batch[\"high_cpu\"] * 3 + batch[\"high_mem\"] * 3)\n                max_points = max(1, total_services * 6)\n                batch[\"risk_score\"] = min(100, int((points / max_points) * 100))\n                batch[\"progress_pct\"] = min(100.0, (batch[\"services_scanned\"] / total_services) * 100.0)\n                batch[\"status_text\"] = f\"Scanning services... {batch['services_scanned']}/{total_services}\"\n                self._ram_service_metrics_queue.put(batch.copy())\n            except Exception:\n                pass\n\n        for svc in services:\n            try:\n                info = svc.as_dict()\n                name = info.get('name', '')\n                dname = info.get('display_name', '')\n                pid = info.get('pid', 0) or 0\n                cpu_p = pid_cpu.get(pid, 0)\n                mem_mb = pid_mem.get(pid, 0)\n                status = info.get('status', '')\n                start = info.get('start_type', '')\n\n                name_lo = name.lower()\n                in_db = name_lo in self.SVC_DB\n                high_cpu = cpu_p &gt; 10\n                high_mem = mem_mb &gt; 150\n\n                if not in_db and not high_cpu and not high_mem:\n                    continue\n\n                if in_db:\n                    meta = self.SVC_DB[name_lo]\n                    cat = meta[\"cat\"]\n                    safe = meta[\"safe_to_stop\"]\n                    desc = meta[\"desc\"]\n                else:\n                    dname_lo = dname.lower()\n                    is_third = any(tp in dname_lo for tp in THIRD_PARTY_PATHS)\n                    if is_third:\n                        cat = \"thirdparty\"\n                        safe = True\n                        desc = (f\"Third-party service: '{dname}'.\\n\"\n                                \"Yeh kisi installed software ki service hai.\\n\"\n                                \"Agar woh software uninstall kar diya hai to safely disable kar sakte ho.\\n\"\n                                \"Agar software use karte ho to band mat karo.\")\n                    else:\n                        cat = \"optional\"\n                        safe = True\n                        desc = (\"Yeh service hamare database mein nahi hai.\\n\"\n                                \"Stop karne se pehle naam search karo Google pe.\\n\"\n                                \"High resource use ho raha hai \u2014 monitor karein.\")\n\n                tags = [cat]\n                if high_cpu:\n                    tags.append(\"highcpu\")\n                if high_mem:\n                    tags.append(\"highmem\")\n\n                safe_txt = \"\u2705 Haan\" if safe else \"\u274c Nahi\"\n                cat_icon = {\"critical\":\"\ud83d\udd34\",\"important\":\"\ud83d\udfe0\",\n                            \"optional\":\"\ud83d\udfe2\",\"thirdparty\":\"\ud83d\udfe3\"}.get(cat, \"\u26aa\")\n\n                row = (cat_icon, name, dname[:42], status,\n                       f\"{cpu_p:.1f}\", f\"{mem_mb:.1f}\", safe_txt)\n                meta_full = {\n                    \"name\": name, \"dname\": dname, \"cat\": cat,\n                    \"safe\": safe, \"desc\": desc, \"cpu\": cpu_p,\n                    \"mem\": mem_mb, \"status\": status, \"start\": start, \"pid\": pid\n                }\n                rows.append((row, tuple(tags), meta_full))\n                if cat in cat_counts:\n                    cat_counts[cat] += 1\n                batch[\"services_scanned\"] += 1\n                batch[\"high_cpu\"] += 1 if high_cpu else 0\n                batch[\"high_mem\"] += 1 if high_mem else 0\n                batch[cat] += 1\n                batch[\"estimated_ram_mb\"] += mem_mb if high_mem else 0\n            except Exception:\n                pass\n            if time.time() - last_dispatch &gt;= 0.12:\n                dispatch_metrics()\n                last_dispatch = time.time()\n\n        dispatch_metrics()\n        batch[\"status_text\"] = f\"Service scan complete \u2014 {len(rows)} relevant services\"\n        batch[\"progress_pct\"] = 100.0\n        self._ram_service_metrics_queue.put(batch.copy())\n\n        self._svc_all_rows = rows\n\n        def insert():\n            self._render_svc_rows(rows)\n            for k, v in cat_counts.items():\n                self.svc_summary_vars[k].set(str(v))\n            self._set_status(\n                f\"Scan done \u2014 {len(rows)} services | \"\n                f\"\ud83d\udd34{cat_counts['critical']} Critical | \"\n                f\"\ud83d\udfe0{cat_counts['important']} Important | \"\n                f\"\ud83d\udfe2{cat_counts['optional']} Optional | \"\n                f\"\ud83d\udfe3{cat_counts['thirdparty']} 3rd-Party\",\n                C[\"success\"])\n        self.after(0, insert)\n\n    def _render_svc_rows(self, rows):\n        for i in self.svc_tree.get_children():\n            self.svc_tree.delete(i)\n        for row, tags, _ in rows:\n            self.svc_tree.insert(\"\", \"end\", values=row, tags=tags)\n        self.svc_count_lbl.config(text=f\"{len(rows)} services\")\n\n    # \u2500\u2500 Filter / Sort \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _filter_services(self, event=None):\n        text = self.svc_search.get().lower()\n        cat  = self._svc_cur_filter_cat\n        filtered = [\n            r for r in self._svc_all_rows\n            if (cat == \"all\" or cat in r[1])\n            and (not text or text in r[2][\"name\"].lower()\n                 or text in r[2][\"dname\"].lower())\n        ]\n        self._render_svc_rows(filtered)\n\n    def _filter_by_cat(self, cat):\n        self._svc_cur_filter_cat = cat\n        self._filter_services()\n\n    def _sort_svc(self, col):\n        col_map = {\"Cat\":0,\"Name\":1,\"Display Name\":2,\"Status\":3,\n                   \"CPU%\":4,\"RAM MB\":5,\"Safe Stop?\":6}\n        idx = col_map.get(col, 1)\n        if self._svc_sort_col == col:\n            self._svc_sort_rev = not self._svc_sort_rev\n        else:\n            self._svc_sort_col = col\n            self._svc_sort_rev = False\n        try:\n            self._svc_all_rows.sort(\n                key=lambda r: float(r[0][idx]) if r[0][idx].replace('.','').isdigit()\n                              else r[0][idx],\n                reverse=self._svc_sort_rev)\n        except: pass\n        self._filter_services()\n\n    # \u2500\u2500 Selection detail panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _on_svc_select(self, event=None):\n        sel = self.svc_tree.selection()\n        if not sel:\n            return\n        iid = sel[0]\n        idx = self.svc_tree.index(iid)\n        # Find matching meta from filtered list\n        visible = [r for r in self._svc_all_rows\n                   if self._svc_cur_filter_cat == \"all\"\n                   or self._svc_cur_filter_cat in r[1]]\n        search_txt = self.svc_search.get().lower()\n        if search_txt:\n            visible = [r for r in visible\n                       if search_txt in r[2][\"name\"].lower()\n                       or search_txt in r[2][\"dname\"].lower()]\n        if idx &gt;= len(visible):\n            return\n        meta = visible[idx][2]\n\n        cat     = meta[\"cat\"]\n        safe    = meta[\"safe\"]\n        desc    = meta[\"desc\"]\n        cpu     = meta[\"cpu\"]\n        mem     = meta[\"mem\"]\n        status  = meta[\"status\"]\n        name    = meta[\"name\"]\n        dname   = meta[\"dname\"]\n\n        cat_label = {\n            \"critical\":   \"\ud83d\udd34 CRITICAL \u2014 Kabhi band mat karo\",\n            \"important\":  \"\ud83d\udfe0 IMPORTANT \u2014 Soch ke band karo\",\n            \"optional\":   \"\ud83d\udfe2 OPTIONAL \u2014 Safely disable kar sakte ho\",\n            \"thirdparty\": \"\ud83d\udfe3 THIRD-PARTY \u2014 Software ki service\",\n        }.get(cat, \"\u26aa Unknown\")\n\n        stop_warning = {\n            \"critical\": (\n                \"\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\\n\"\n                \"\u2551  \u26d4 DANGER \u2014 IS SERVICE KO BAND MAT KARO \u2551\\n\"\n                \"\u255a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255d\\n\"\n                \"Yeh Windows ka core component hai.\\n\"\n                \"Band karne se BLUE SCREEN / CRASH / FREEZE ho sakta hai!\\n\"\n            ),\n            \"important\": (\n                \"\u26a0\ufe0f  SAWDHAN \u2014 Band karne se Windows ka koi feature\\n\"\n                \"   kaam karna band kar sakta hai. Pehle samjho\\n\"\n                \"   kya hoga, phir decide karo.\\n\"\n            ),\n            \"optional\": (\n                \"\u2705 SAFE \u2014 Yeh service band kar sakte ho.\\n\"\n                \"   Performance behtar hogi. System harm nahi hoga.\\n\"\n            ),\n            \"thirdparty\": (\n                \"\ud83d\udfe3 THIRD-PARTY \u2014 Kisi installed software ki service hai.\\n\"\n                \"   Agar woh software use karte ho: BAND MAT KARO.\\n\"\n                \"   Agar woh software uninstall ho gaya hai: Safely disable karo.\\n\"\n            ),\n        }.get(cat, \"\")\n\n        lines = [\n            f\"Service Name  : {name}\",\n            f\"Display Name  : {dname}\",\n            f\"Category      : {cat_label}\",\n            f\"Current Status: {status}\",\n            f\"CPU Usage     : {cpu:.1f}%{'  \u26a0 HIGH!' if cpu&gt;10 else ''}\",\n            f\"RAM Usage     : {mem:.1f} MB{'  \u26a0 HIGH!' if mem&gt;150 else ''}\",\n            f\"Safe to Stop? : {'\u2705 Haan \u2014 band kar sakte ho' if safe else '\u274c Nahi \u2014 band karna dangerous hai'}\",\n            \"\",\n            \"\u2500\"*50,\n            \"\",\n            \"\ud83d\udcd6 DESCRIPTION:\",\n            desc,\n            \"\",\n            \"\u2500\"*50,\n            \"\",\n            \"\u26a0\ufe0f  STOP/DISABLE KARNE SE KYA HOGA:\",\n            stop_warning,\n        ]\n        if cpu &gt; 10:\n            lines += [\"\",\"\ud83d\udd36 HIGH CPU ALERT:\",\n                      f\"   Yeh service {cpu:.1f}% CPU le rahi hai.\",\n                      \"   Agar zaroori nahi to stop karo.\"]\n        if mem &gt; 150:\n            lines += [\"\",\"\ud83d\udfe1 HIGH RAM ALERT:\",\n                      f\"   Yeh service {mem:.1f} MB RAM use kar rahi hai.\",\n                      \"   Stop karne se RAM free hogi.\"]\n\n        self.svc_detail.config(state=\"normal\")\n        self.svc_detail.delete(\"1.0\",\"end\")\n        # Color different parts\n        self.svc_detail.tag_configure(\"red\",    foreground=\"#FF4444\")\n        self.svc_detail.tag_configure(\"orange\", foreground=\"#FF9800\")\n        self.svc_detail.tag_configure(\"green\",  foreground=\"#4CAF50\")\n        self.svc_detail.tag_configure(\"purple\", foreground=\"#CE93D8\")\n        self.svc_detail.tag_configure(\"gold\",   foreground=\"#FFD700\")\n        self.svc_detail.tag_configure(\"dim\",    foreground=\"#A0B0C8\")\n        self.svc_detail.tag_configure(\"bold\",   foreground=C[\"text\"])\n\n        for line in lines:\n            color_tag = \"bold\"\n            if \"DANGER\" in line or \"\u274c\" in line:     color_tag = \"red\"\n            elif \"SAWDHAN\" in line or \"\u26a0\ufe0f\" in line:  color_tag = \"orange\"\n            elif \"SAFE\" in line or \"\u2705\" in line:     color_tag = \"green\"\n            elif \"THIRD-PARTY\" in line or \"\ud83d\udfe3\" in line: color_tag = \"purple\"\n            elif \"HIGH\" in line and \"ALERT\" in line: color_tag = \"gold\"\n            elif line.startswith(\"\u2500\"):               color_tag = \"dim\"\n            self.svc_detail.insert(\"end\", line+\"\\n\", color_tag)\n        self.svc_detail.config(state=\"disabled\")\n\n    # \u2500\u2500 Safe stop/disable with category warning \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _svc_action_safe(self, action):\n        sel = self.svc_tree.selection()\n        if not sel:\n            messagebox.showinfo(\"No Selection\", \"Pehle ek service select karo.\")\n            return\n        # Check all selected for critical/important\n        block = []\n        warn  = []\n        names = []\n        visible = self._get_visible_svc_rows()\n        for iid in sel:\n            idx = self.svc_tree.index(iid)\n            if idx &gt;= len(visible): continue\n            meta = visible[idx][2]\n            cat  = meta[\"cat\"]\n            name = meta[\"name\"]\n            safe = meta[\"safe\"]\n            names.append(name)\n            if not safe:\n                block.append(f\"  \ud83d\udd34 {name} ({meta['dname']}) \u2014 CRITICAL, band NAHI karna chahiye!\")\n            elif cat == \"important\":\n                warn.append(f\"  \ud83d\udfe0 {name} ({meta['dname']}) \u2014 Important service, dhyan se!\")\n\n        if block:\n            messagebox.showerror(\"\u26d4 KHATARNAK SERVICE SELECTED!\",\n                \"Neeche di gayi services CRITICAL hain.\\n\"\n                \"Inhe band karne se system crash ho sakta hai!\\n\\n\"\n                + \"\\n\".join(block) +\n                \"\\n\\nIn services ko DESELECT karo aur dubara try karo.\")\n            return\n\n        confirm_msg = f\"{'Disable' if action=='disable' else 'Stop'} karne se ye services band ho jaayengi:\\n\\n\"\n        confirm_msg += \"\\n\".join(f\"  \u2022 {n}\" for n in names)\n        if warn:\n            confirm_msg += \"\\n\\n\u26a0\ufe0f SAWDHAN \u2014 Ye services Important hain:\\n\" + \"\\n\".join(warn)\n        # Dependency awareness: show dependents (services that rely on this one)\n        dep_warn = []\n        dep_block = []\n        for n in names:\n            deps = self._service_dependents(n)\n            if not deps:\n                continue\n            running = []\n            for dn in deps[:12]:\n                st, _ = self._service_state(dn)\n                if st and st != \"STOPPED\":\n                    running.append(dn)\n            if action == \"disable\":\n                dep_warn.append(f\"  \u26a0 {n} ke dependents: {', '.join(deps[:8])}\" + (\"...\" if len(deps) &gt; 8 else \"\"))\n            else:\n                if running:\n                    dep_block.append(f\"  \u26d4 {n} ke running dependents: {', '.join(running[:8])}\" + (\"...\" if len(running) &gt; 8 else \"\"))\n                else:\n                    dep_warn.append(f\"  \u26a0 {n} ke dependents: {', '.join(deps[:8])}\" + (\"...\" if len(deps) &gt; 8 else \"\"))\n        if dep_block:\n            messagebox.showerror(\n                \"\u26d4 Dependent Services Running\",\n                \"Selected service(s) par kuch services dependent hain aur abhi RUNNING hain.\\n\"\n                \"Pehle dependents stop karo (ya unko deselect karo), phir try karo.\\n\\n\"\n                + \"\\n\".join(dep_block)\n            )\n            return\n        if dep_warn:\n            confirm_msg += \"\\n\\n\ud83d\udd17 DEPENDENCY WARNING:\\n\" + \"\\n\".join(dep_warn)\n        confirm_msg += f\"\\n\\n{'Disable karne se ye restart pe nahi chalegi.' if action=='disable' else 'Stop karne se ye tab tak nahi chalegi jab tak restart nahi karte.'}\\n\\nAage badhein?\"\n\n        if not messagebox.askyesno(\n                \"\u26a0\ufe0f Confirm \u2014 Service \" + (\"Disable\" if action==\"disable\" else \"Stop\"),\n                confirm_msg):\n            return\n\n        results = []\n        if action == \"disable\":\n            self._svc_save_start_mode_snapshot(names)\n        for name in names:\n            if action == \"stop\":\n                results.append(self._service_stop_checked(name))\n            else:\n                results.append(self._service_config_checked(name, \"disabled\"))\n                results.append(self._service_stop_checked(name))\n        summary = self._action_summary(\"Service \" + (\"Disable\" if action == \"disable\" else \"Stop\"), results)\n        messagebox.showinfo(\"Already Done\" if summary[\"already_done\"] else \"Done\", summary[\"message\"])\n        self._scan_impacting_services()\n\n    def _get_visible_svc_rows(self):\n        cat = self._svc_cur_filter_cat\n        txt = self.svc_search.get().lower() if hasattr(self,'svc_search') else \"\"\n        rows = self._svc_all_rows\n        if cat != \"all\":\n            rows = [r for r in rows if cat in r[1]]\n        if txt:\n            rows = [r for r in rows if txt in r[2][\"name\"].lower()\n                    or txt in r[2][\"dname\"].lower()]\n        return rows\n\n    def _disable_all_optional(self):\n        optional = [r for r in self._svc_all_rows if \"optional\" in r[1]]\n        if not optional:\n            messagebox.showinfo(\"Koi Service Nahi\",\n                \"Pehle 'Scan All Services' karo.\")\n            return\n        names = [r[2][\"name\"] for r in optional]\n        msg = (f\"Neeche di gayi {len(names)} Optional services disable ho jaayengi:\\n\\n\"\n               + \"\\n\".join(f\"  \ud83d\udfe2 {n}\" for n in names[:15])\n               + (f\"\\n  ...aur {len(names)-15} aur\" if len(names)&gt;15 else \"\")\n               + \"\\n\\nYe sab safely disable ho sakti hain.\\nKya aage badhein?\")\n        if messagebox.askyesno(\"\u26a1 Disable All Optional\", msg):\n            results = []\n            self._svc_save_start_mode_snapshot(names)\n            for name in names:\n                results.append(self._service_config_checked(name, \"disabled\"))\n                results.append(self._service_stop_checked(name))\n            summary = self._action_summary(\"Optional Services\", results)\n            messagebox.showinfo(\"Already Done\" if summary[\"already_done\"] else \"Done!\", summary[\"message\"] + \"\\nRestart karo best results ke liye.\")\n            self._scan_impacting_services()\n\n    def _stop_services(self):\n        results = []\n        for iid in self.svc_tree.selection():\n            name = self.svc_tree.item(iid, \"values\")[1]\n            results.append(self._service_stop_checked(name))\n        if results:\n            summary = self._action_summary(\"Service Stop\", results)\n            messagebox.showinfo(\"Already Done\" if summary[\"already_done\"] else \"Done\", summary[\"message\"])\n        self._scan_impacting_services()\n\n    def _start_services(self):\n        results = []\n        for iid in self.svc_tree.selection():\n            name = self.svc_tree.item(iid, \"values\")[1]\n            results.append(self._service_start_checked(name))\n        if results:\n            summary = self._action_summary(\"Service Start\", results)\n            messagebox.showinfo(\"Already Done\" if summary[\"already_done\"] else \"Done\", summary[\"message\"])\n        self._scan_impacting_services()\n\n    def _disable_services(self):\n        results = []\n        for iid in self.svc_tree.selection():\n            name = self.svc_tree.item(iid, \"values\")[1]\n            results.append(self._service_config_checked(name, \"disabled\"))\n        if results:\n            summary = self._action_summary(\"Service Disable\", results)\n            messagebox.showinfo(\"Already Done\" if summary[\"already_done\"] else \"Done\", summary[\"message\"])\n        self._scan_impacting_services()\n\n    # ---------- RAM OPTIMIZER (with Before/After) ----------\n    def _build_memory(self, parent):\n        root = tk.Frame(parent, bg=C[\"bg\"])\n        canvas = tk.Canvas(root, bg=C[\"bg\"], highlightthickness=0)\n        scrollbar = ttk.Scrollbar(root, orient=\"vertical\", command=canvas.yview)\n        inner = tk.Frame(canvas, bg=C[\"bg\"])\n        inner.bind(\"\", lambda e: canvas.configure(scrollregion=canvas.bbox(\"all\")))\n        inner_window = canvas.create_window((0, 0), window=inner, anchor=\"nw\")\n        canvas.configure(yscrollcommand=scrollbar.set)\n        scrollbar.pack(side=\"right\", fill=\"y\")\n        canvas.pack(side=\"left\", fill=\"both\", expand=True)\n\n        def _resize_inner(event):\n            try:\n                canvas.itemconfigure(inner_window, width=event.width)\n                canvas.configure(scrollregion=canvas.bbox(\"all\"))\n            except Exception:\n                pass\n\n        canvas.bind(\"\", _resize_inner)\n        self._bind_scoped_mousewheel(inner, canvas)\n\n        frame = inner\n        self._section_header(frame, \"\ud83e\udde0 RAM Optimizer\", \"Free up RAM memory - WORKING\")\n        stats = tk.Frame(frame, bg=C[\"bg\"])\n        stats.pack(fill=\"x\", padx=16, pady=8)\n        self.ram_cards = {}\n        for i, (k, lbl, color) in enumerate([(\"total\",\"Total RAM\",C[\"text\"]), (\"used\",\"Used RAM\",C[\"error\"]), (\"free\",\"Free RAM\",C[\"success\"]), (\"cached\",\"Cache\",C[\"accent4\"])]):\n            card = self._stat_card(stats, lbl, \"--\", color)\n            card.grid(row=0, column=i, padx=6, sticky=\"ew\")\n            stats.columnconfigure(i, weight=1)\n            self.ram_cards[k] = card\n        monitor = tk.Frame(frame, bg=C[\"bg\"])\n        monitor.pack(fill=\"x\", padx=16, pady=(0,8))\n        self.ram_operation_progress_var = tk.DoubleVar(value=0.0)\n        self.ram_operation_progress_bar = ttk.Progressbar(monitor,\n                                                         variable=self.ram_operation_progress_var,\n                                                         maximum=100, mode=\"determinate\")\n        self.ram_operation_progress_bar.pack(fill=\"x\", padx=2, pady=(0,4))\n        self.ram_operation_status_lbl = tk.Label(monitor, text=\"Ready\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"])\n        self.ram_operation_status_lbl.pack(anchor=\"w\", pady=(0,4))\n        metrics = tk.Frame(monitor, bg=C[\"bg\"])\n        metrics.pack(fill=\"x\")\n        self.ram_predicted_free_var = tk.StringVar(value=\"--\")\n        self.ram_confidence_var = tk.StringVar(value=\"--\")\n        self.ram_delta_var = tk.StringVar(value=\"--\")\n        for label, var, fg in [\n            (\"Predicted Free\", self.ram_predicted_free_var, C[\"success\"]),\n            (\"Confidence\", self.ram_confidence_var, C[\"accent4\"]),\n            (\"Delta\", self.ram_delta_var, C[\"warning\"]),\n        ]:\n            card = tk.Frame(metrics, bg=C[\"card\"], padx=8, pady=8)\n            card.pack(side=\"left\", fill=\"x\", expand=True, padx=3)\n            tk.Label(card, text=label, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\")\n            tk.Label(card, textvariable=var, font=(\"Segoe UI\", 14, \"bold\"), fg=fg, bg=C[\"card\"]).pack(anchor=\"w\")\n        mid = tk.Frame(frame, bg=C[\"bg\"])\n        mid.pack(fill=\"both\", expand=True, padx=16, pady=8)\n        mid.columnconfigure(0, weight=1)\n        mid.columnconfigure(1, weight=1)\n        left = tk.Frame(mid, bg=C[\"card\"])\n        left.grid(row=0, column=0, sticky=\"nsew\", padx=(0,6))\n        tk.Label(left, text=\"  RAM Tools\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8,6), padx=8)\n        self._action_card_grid(left, [\n            (\"\ud83d\ude80\", \"Aggressive RAM Boost\",  \"Full RAM free karo\",            C[\"btn_info\"], self._ram_boost_with_confirm),\n            (\"\ud83d\udd04\", \"Empty Working Sets\",    \"Working sets clear karo\",       C[\"btn_info\"], self._ram_empty_with_confirm),\n            (\"\ud83d\udcbe\", \"Clear Standby Cache\",   \"Standby list flush karo\",       C[\"btn_info\"], self._clear_standby_with_confirm),\n            (\"\ud83d\udcca\", \"Show Heavy Processes\",  \"RAM zyada use karne wale show\", C[\"btn_info\"], self._ram_show_heavy),\n        ], cols=2)\n\n        advanced = tk.Frame(left, bg=C[\"card\"])\n        advanced.pack(fill=\"x\", padx=12, pady=(8,4))\n        tk.Label(advanced, text=\"  Advanced OS Controls\", font=FONTS[\"small\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(0,6), padx=2)\n        adv_grid = tk.Frame(advanced, bg=C[\"card\"])\n        adv_grid.pack(fill=\"x\")\n        adv_grid.columnconfigure(0, weight=1)\n        adv_grid.columnconfigure(1, weight=1)\n\n        self._kernel_trim_btn = self._btn(\n            adv_grid, \"\ud83d\udd25 Kernel Trim\", C[\"btn_info\"],\n            lambda: self._ram_service_action_submit(\"kernel_trim\", self._kernel_working_set_trim, self._kernel_trim_btn)\n        )\n        self._kernel_trim_btn.grid(row=0, column=0, sticky=\"ew\", padx=3, pady=2)\n\n        self._priority_demote_btn = self._btn(\n            adv_grid, \"\ud83d\udc22 Priority Demotion\", C[\"btn_warn\"],\n            lambda: self._ram_service_action_submit(\"priority_demotion\", self._background_priority_demotion, self._priority_demote_btn)\n        )\n        self._priority_demote_btn.grid(row=0, column=1, sticky=\"ew\", padx=3, pady=2)\n\n        self._standby_flush_btn = self._btn(\n            adv_grid, \"\ud83c\udf0a Standby Flusher\", C[\"btn_chip\"],\n            lambda: self._ram_service_action_submit(\"standby_flusher\", self._flush_standby_list, self._standby_flush_btn)\n        )\n        self._standby_flush_btn.grid(row=1, column=0, sticky=\"ew\", padx=3, pady=2)\n\n        self._sysmain_toggle_btn = self._btn(\n            adv_grid, \"\ud83d\udee1 SysMain Toggle\", C[\"btn_chip\"],\n            lambda: self._ram_service_action_submit(\"sysmain_toggle\", self._toggle_sysmain_service, self._sysmain_toggle_btn)\n        )\n        self._sysmain_toggle_btn.grid(row=1, column=1, sticky=\"ew\", padx=3, pady=2)\n\n        # Auto RAM Free (every 15 minutes) \u2014 requested feature\n        row = tk.Frame(left, bg=C[\"card\"])\n        row.pack(fill=\"x\", padx=12, pady=(6, 2))\n        tk.Label(row, text=\"Interval:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ram_auto_interval_var = tk.StringVar(value=\"15\")\n        ttk.Combobox(row, values=[\"15\", \"30\", \"60\"], textvariable=self._ram_auto_interval_var,\n                     width=6, font=FONTS[\"small\"], state=\"readonly\").pack(side=\"left\", padx=6)\n        tk.Label(row, text=\"min\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ram_auto_btn = self._btn(left, \"\u23f1 Auto RAM Free (15 min): OFF\", C[\"btn_warn\"], self._ram_auto_toggle)\n        self._ram_auto_btn.pack(fill=\"x\", padx=12, pady=3)\n        right = tk.Frame(mid, bg=C[\"card\"])\n        right.grid(row=0, column=1, sticky=\"nsew\", padx=(6,0))\n        tk.Label(right, text=\"  Memory Log\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8,4), padx=8)\n        self.ram_log = self._scrolled_text(right, height=18)\n        self.ram_execution_log = self.ram_log\n        if not hasattr(self, \"_ram_auto_enabled\"):\n            self._ram_auto_enabled = False\n        if not hasattr(self, \"_ram_auto_after_id\"):\n            self._ram_auto_after_id = None\n        self._ram_update_stats()\n        return root\n\n    def _ram_update_stats(self):\n        try:\n            vm = psutil.virtual_memory()\n            self.ram_cards[\"total\"]._value_lbl.config(text=self._fmt_size(vm.total))\n            self.ram_cards[\"used\"]._value_lbl.config(text=f\"{vm.percent:.1f}%\")\n            self.ram_cards[\"used\"]._bar.config(value=vm.percent)\n            self.ram_cards[\"free\"]._value_lbl.config(text=self._fmt_size(vm.available))\n            self.ram_cards[\"cached\"]._value_lbl.config(text=self._fmt_size(getattr(vm, 'cached', 0) or 0))\n        except:\n            pass\n        self.after(3000, self._ram_update_stats)\n\n    def _ram_boost_with_confirm(self):\n        def before():\n            return f\"Free RAM before: {self._fmt_size(psutil.virtual_memory().available)}\"\n        def action():\n            self._do_ram_optimize(aggressive=True)\n        def after():\n            return f\"Free RAM after: {self._fmt_size(psutil.virtual_memory().available)}\"\n        self._confirm_and_launch_job(\"Aggressive RAM Boost\", \"This will aggressively free up RAM by trimming working sets and clearing caches.\\nMay cause slight lag for a moment.\",\n                                    before, \"ram_boost\", self._do_ram_optimize, True)\n\n    def _ram_empty_with_confirm(self):\n        def before():\n            return f\"Free RAM before: {self._fmt_size(psutil.virtual_memory().available)}\"\n        def action():\n            self._do_ram_optimize(aggressive=False)\n        def after():\n            return f\"Free RAM after: {self._fmt_size(psutil.virtual_memory().available)}\"\n        self._confirm_and_launch_job(\"Empty Working Sets\", \"This will safely empty working sets of all processes.\\nTypically frees RAM without harming performance.\",\n                                    before, \"ram_empty\", self._do_ram_optimize, False)\n\n    def _clear_standby_with_confirm(self):\n        def before():\n            return f\"Standby cache size before: {self._fmt_size(psutil.virtual_memory().available)}\"\n        def action():\n            self._purge_memory_lists()\n        def after():\n            return f\"Standby cache size after: {self._fmt_size(psutil.virtual_memory().available)}\"\n        self._confirm_and_launch_job(\"Clear Standby Cache\", \"This clears the standby memory list (cached RAM).\\nIt can free up RAM that is being held unnecessarily.\",\n                                    before, \"ram_clear_standby\", self._purge_memory_lists)\n\n    def _do_ram_optimize(self, aggressive=False):\n        if not hasattr(self, \"_ram_opt_lock\"):\n            self._ram_opt_lock = threading.Lock()\n        with self._ram_opt_lock:\n            if getattr(self, \"_ram_opt_running\", False):\n                self._append_log(self.ram_log, \"\u26a0\ufe0f RAM optimize already running \u2014 skipping\", C[\"warning\"])\n                return\n            self._ram_opt_running = True\n        try:\n            before = psutil.virtual_memory()\n            gc.collect()\n            kernel32 = ctypes.windll.kernel32\n            psapi = ctypes.windll.psapi\n\n            batch = {\n                \"phase\": \"ram_optimize\",\n                \"status_text\": \"Optimizing RAM...\",\n                \"progress_pct\": 0.0,\n                \"processes_scanned\": 0,\n                \"errors\": 0,\n                \"freed_mb\": 0,\n                \"predicted_free_mb\": int(before.available / (1024**2) * 0.05),\n                \"confidence_score\": min(95, max(30, int((before.percent / 100.0) * 90 + 10))),\n                \"delta_mb\": 0,\n            }\n            last_dispatch = time.time()\n\n            def dispatch_metrics(force=False):\n                try:\n                    batch[\"progress_pct\"] = min(100.0, (batch[\"processes_scanned\"] / max(1, psutil.cpu_count(logical=False) * 10)) * 100.0)\n                    batch[\"status_text\"] = f\"Optimizing RAM... {batch['processes_scanned']} processes scanned\"\n                    self._ram_service_emit_metrics(batch.copy(), force=force)\n                except Exception:\n                    pass\n\n            for proc in psutil.process_iter(['pid']):\n                batch[\"processes_scanned\"] += 1\n                pid = proc.info.get('pid')\n                if not pid or pid in (0, 4):\n                    continue\n                try:\n                    handle = kernel32.OpenProcess(0x0400 | 0x0100 | 0x0010, False, int(pid))\n                    if handle:\n                        try:\n                            try:\n                                psapi.EmptyWorkingSet(handle)\n                            except (PermissionError, psutil.AccessDenied):\n                                batch[\"errors\"] += 1\n                            except Exception:\n                                batch[\"errors\"] += 1\n                        finally:\n                            kernel32.CloseHandle(handle)\n                except (PermissionError, psutil.AccessDenied):\n                    batch[\"errors\"] += 1\n                except Exception:\n                    batch[\"errors\"] += 1\n                if time.time() - last_dispatch &gt;= 0.12:\n                    dispatch_metrics()\n                    last_dispatch = time.time()\n\n            self._purge_memory_lists()\n            if aggressive:\n                try:\n                    ctypes.windll.kernel32.SetSystemFileCacheSize(-1, -1, 0)\n                except Exception:\n                    pass\n\n            after = psutil.virtual_memory()\n            freed = after.available - before.available\n            batch[\"freed_mb\"] = int(freed / (1024**2))\n            batch[\"delta_mb\"] = int((after.available - before.available) / (1024**2))\n            batch[\"status_text\"] = f\"RAM optimize complete \u2014 freed {self._fmt_size(freed)}\"\n            batch[\"progress_pct\"] = 100.0\n            self._ram_service_emit_metrics(batch.copy(), force=True)\n\n            if freed &gt;= 0:\n                self._append_log(self.ram_log, f\"\u2705 RAM Freed: {self._fmt_size(freed)}\", C[\"success\"])\n            else:\n                self._append_log(self.ram_log, f\"\u2139 RAM change: {self._fmt_size(freed)} (cache re-allocated)\", C[\"warning\"])\n        except Exception as e:\n            self._append_log(self.ram_log, f\"RAM optimize failed: {e}\", C[\"error\"])\n        finally:\n            with self._ram_opt_lock:\n                self._ram_opt_running = False\n\n    def _kernel_working_set_trim(self):\n        before = self._snapshot_resource_state() or {}\n        batch = {\n            \"phase\": \"kernel_trim\",\n            \"status_text\": \"Kernel working set trim running...\",\n            \"progress_pct\": 0.0,\n            \"trimmed_processes\": 0,\n            \"errors\": 0,\n            \"delta_mb\": 0,\n        }\n        self._ram_service_emit_metrics(batch)\n        try:\n            kernel32 = ctypes.windll.kernel32\n            psapi = ctypes.windll.psapi\n            last_dispatch = time.monotonic()\n            for proc in psutil.process_iter(['pid', 'name']):\n                try:\n                    pid = int(proc.info.get('pid') or 0)\n                    if pid &lt;= 0 or pid == os.getpid():\n                        continue\n                    handle = kernel32.OpenProcess(0x001F0FFF, False, pid)\n                    if not handle:\n                        continue\n                    try:\n                        if psapi.EmptyWorkingSet(handle):\n                            batch[\"trimmed_processes\"] += 1\n                        try:\n                            kernel32.SetProcessWorkingSetSize(handle, -1, -1)\n                        except Exception:\n                            pass\n                    finally:\n                        kernel32.CloseHandle(handle)\n                except (PermissionError, psutil.AccessDenied):\n                    batch[\"errors\"] += 1\n                except Exception:\n                    batch[\"errors\"] += 1\n                if time.monotonic() - last_dispatch &gt;= 0.120:\n                    batch[\"status_text\"] = f\"Kernel trim active \u2014 {batch['trimmed_processes']} trimmed\"\n                    batch[\"progress_pct\"] = min(100.0, (batch[\"trimmed_processes\"] / max(1, psutil.cpu_count(logical=False) * 2)) * 100.0)\n                    self._ram_service_emit_metrics(batch.copy())\n                    last_dispatch = time.monotonic()\n            after = psutil.virtual_memory()\n            batch[\"delta_mb\"] = int((after.available - before.get(\"available_mb\", 0)) / 1024**2)\n            batch[\"status_text\"] = f\"Kernel trim complete \u2014 freed {self._fmt_size(batch['delta_mb'] * 1024**2)}\"\n            batch[\"progress_pct\"] = 100.0\n            self._ram_service_emit_metrics(batch.copy(), force=True)\n            self._append_log(self.ram_log, f\"\u2705 Kernel working set trim complete \u2014 freed {self._fmt_size(batch['delta_mb'] * 1024**2)}\", C[\"success\"])\n        except Exception as e:\n            self._append_log(self.ram_log, f\"Kernel trim failed: {e}\", C[\"error\"])\n\n    def _background_priority_demotion(self):\n        before = psutil.virtual_memory()\n        batch = {\n            \"phase\": \"priority_demotion\",\n            \"status_text\": \"Background process priority demotion running...\",\n            \"progress_pct\": 0.0,\n            \"scanned\": 0,\n            \"demoted\": 0,\n            \"errors\": 0,\n            \"delta_mb\": 0,\n        }\n        self._ram_service_emit_metrics(batch)\n        idle_class = getattr(psutil, 'IDLE_PRIORITY_CLASS', getattr(psutil, 'BELOW_NORMAL_PRIORITY_CLASS', 64))\n        keep_names = {\n            'explorer.exe', 'taskmgr.exe', 'chrome.exe', 'firefox.exe', 'msedge.exe',\n            'dwm.exe', 'svchost.exe', 'services.exe', 'lsass.exe', 'wininit.exe',\n            'winlogon.exe', 'csrss.exe', 'system', 'idle', 'spoolsv.exe', 'steam.exe',\n        }\n        last_dispatch = time.monotonic()\n        for proc in psutil.process_iter(['pid', 'name', 'username', 'nice']):\n            batch[\"scanned\"] += 1\n            try:\n                pid = int(proc.info.get('pid') or 0)\n                if pid &lt;= 0 or pid == os.getpid():\n                    continue\n                name = str(proc.info.get('name') or '').lower()\n                username = str(proc.info.get('username') or '').lower()\n                if name in keep_names or any(term in name for term in ('microsoft', 'windows', 'service', 'system', 'sql', 'svchost')):\n                    continue\n                if username in ('nt authority\\\\system', 'local service', 'network service'):\n                    continue\n                current = proc.info.get('nice')\n                if current == idle_class:\n                    continue\n                try:\n                    proc.nice(idle_class)\n                    batch[\"demoted\"] += 1\n                except (PermissionError, psutil.AccessDenied):\n                    batch[\"errors\"] += 1\n                except Exception:\n                    batch[\"errors\"] += 1\n            except (PermissionError, psutil.AccessDenied):\n                batch[\"errors\"] += 1\n            except Exception:\n                batch[\"errors\"] += 1\n            if time.monotonic() - last_dispatch &gt;= 0.120:\n                batch[\"status_text\"] = f\"Demoting background apps... {batch['demoted']} demoted\"\n                batch[\"progress_pct\"] = min(100.0, (batch[\"scanned\"] / max(1, psutil.cpu_count(logical=False) * 10)) * 100.0)\n                self._ram_service_emit_metrics(batch.copy())\n                last_dispatch = time.monotonic()\n        after = psutil.virtual_memory()\n        batch[\"delta_mb\"] = int((after.available - before.available) / 1024**2)\n        batch[\"status_text\"] = f\"Priority demotion complete \u2014 {batch['demoted']} apps demoted\"\n        batch[\"progress_pct\"] = 100.0\n        self._ram_service_emit_metrics(batch.copy(), force=True)\n        self._append_log(self.ram_log, f\"\u2705 Background priority demotion complete \u2014 {batch['demoted']} processes\", C[\"success\"])\n\n    def _flush_standby_list(self):\n        before = psutil.virtual_memory()\n        batch = {\n            \"phase\": \"standby_flush\",\n            \"status_text\": \"Standby list flush running...\",\n            \"progress_pct\": 0.0,\n            \"errors\": 0,\n            \"delta_mb\": 0,\n        }\n        self._ram_service_emit_metrics(batch)\n        try:\n            self._purge_memory_lists()\n            try:\n                ctypes.windll.kernel32.SetSystemFileCacheSize(-1, -1, 0)\n            except (PermissionError, psutil.AccessDenied):\n                batch[\"errors\"] += 1\n            except Exception:\n                pass\n            try:\n                kernel32 = ctypes.windll.kernel32\n                psapi = ctypes.windll.psapi\n                handle = kernel32.GetCurrentProcess()\n                psapi.EmptyWorkingSet(handle)\n            except Exception:\n                pass\n            after = psutil.virtual_memory()\n            batch[\"delta_mb\"] = int((after.available - before.available) / 1024**2)\n            batch[\"status_text\"] = f\"Standby flush complete \u2014 freed {self._fmt_size(batch['delta_mb'] * 1024**2)}\"\n            batch[\"progress_pct\"] = 100.0\n            self._ram_service_emit_metrics(batch.copy(), force=True)\n            self._append_log(self.ram_log, f\"\u2705 Standby list flushed \u2014 freed {self._fmt_size(batch['delta_mb'] * 1024**2)}\", C[\"success\"])\n        except Exception as e:\n            self._append_log(self.ram_log, f\"Standby flush failed: {e}\", C[\"error\"])\n\n    def _toggle_sysmain_service(self):\n        batch = {\n            \"phase\": \"sysmain_toggle\",\n            \"status_text\": \"SysMain toggle running...\",\n            \"progress_pct\": 0.0,\n            \"action\": \"pending\",\n        }\n        self._ram_service_emit_metrics(batch)\n        try:\n            svc = psutil.win_service_get(\"SysMain\")\n            status = svc.status().lower()\n            if status == \"running\":\n                try:\n                    svc.stop()\n                    svc.wait(15)\n                    batch[\"action\"] = \"stopped\"\n                except (PermissionError, psutil.AccessDenied):\n                    batch[\"action\"] = \"permission_denied\"\n                    batch[\"status_text\"] = \"SysMain stop denied\"\n                    batch[\"progress_pct\"] = 100.0\n                    self._ram_service_emit_metrics(batch.copy(), force=True)\n                    self._append_log(self.ram_log, \"\u26a0\ufe0f SysMain stop denied by permissions\", C[\"warning\"])\n                    return\n                except Exception:\n                    batch[\"action\"] = \"stop_failed\"\n            else:\n                try:\n                    svc.start()\n                    svc.wait(15)\n                    batch[\"action\"] = \"started\"\n                except (PermissionError, psutil.AccessDenied):\n                    batch[\"action\"] = \"permission_denied\"\n                    batch[\"status_text\"] = \"SysMain start denied\"\n                    batch[\"progress_pct\"] = 100.0\n                    self._ram_service_emit_metrics(batch.copy(), force=True)\n                    self._append_log(self.ram_log, \"\u26a0\ufe0f SysMain start denied by permissions\", C[\"warning\"])\n                    return\n                except Exception:\n                    batch[\"action\"] = \"start_failed\"\n            batch[\"status_text\"] = f\"SysMain {batch['action']}\"\n            batch[\"progress_pct\"] = 100.0\n            self._ram_service_emit_metrics(batch.copy(), force=True)\n            self._append_log(self.ram_log, f\"\u2705 SysMain {batch['action']}\", C[\"success\"])\n        except Exception as e:\n            self._append_log(self.ram_log, f\"SysMain toggle failed: {e}\", C[\"error\"])\n\n    def _ram_auto_toggle(self):\n        enabled = not bool(getattr(self, \"_ram_auto_enabled\", False))\n        self._ram_auto_enabled = enabled\n        try:\n            if hasattr(self, \"_ram_auto_btn\") and self._ram_auto_btn:\n                self._ram_auto_btn.config(\n                    text=(\"\u23f1 Auto RAM Free (15 min): ON\" if enabled else \"\u23f1 Auto RAM Free (15 min): OFF\"),\n                    bg=(C[\"btn_info\"] if enabled else C[\"btn_warn\"])\n                )\n        except Exception:\n            pass\n        if enabled:\n            mins = self._ram_auto_interval_minutes()\n            self._append_log(self.ram_log, f\"\u23f1 Auto RAM Free enabled \u2014 every {mins} minutes\", C[\"accent4\"])\n            self._ram_auto_schedule(immediate=False)\n        else:\n            self._append_log(self.ram_log, \"\u23f1 Auto RAM Free disabled\", C[\"warning\"])\n            self._ram_auto_cancel()\n\n    def _ram_auto_cancel(self):\n        try:\n            aid = getattr(self, \"_ram_auto_after_id\", None)\n            if aid:\n                self.after_cancel(aid)\n        except Exception:\n            pass\n        self._ram_auto_after_id = None\n\n    def _ram_auto_schedule(self, immediate=False):\n        self._ram_auto_cancel()\n        if not getattr(self, \"_ram_auto_enabled\", False):\n            return\n        mins = self._ram_auto_interval_minutes()\n        delay = 1000 if immediate else (mins * 60 * 1000)\n        self._ram_auto_after_id = self.after(delay, self._ram_auto_tick)\n\n    def _ram_auto_interval_minutes(self):\n        try:\n            v = int((getattr(self, \"_ram_auto_interval_var\", None).get() if hasattr(self, \"_ram_auto_interval_var\") else \"15\") or \"15\")\n            if v in (15, 30, 60):\n                return v\n        except Exception:\n            pass\n        return 15\n\n    def _ram_auto_tick(self):\n        if not getattr(self, \"_ram_auto_enabled\", False):\n            return\n        # Avoid lag when system is busy\n        try:\n            if psutil.cpu_percent(interval=0.1) &gt; 75:\n                self._append_log(self.ram_log, \"\u23f1 Auto RAM Free skipped (CPU high)\", C[\"warning\"])\n                self._ram_auto_schedule(immediate=False)\n                return\n        except Exception:\n            pass\n        self._submit_ram_service_job(\"ram_auto_boost\", self._do_ram_optimize, True)\n        self._ram_auto_schedule(immediate=False)\n\n    def _purge_memory_lists(self):\n        try:\n            ntdll = ctypes.windll.ntdll\n            cleared = False\n            for val in (2, 3, 4, 5):\n                try:\n                    # NtSetSystemInformation returns an NTSTATUS; failure raises in some contexts\n                    ntdll.NtSetSystemInformation(80, ctypes.byref(ctypes.c_int(val)), 4)\n                    cleared = True\n                except Exception:\n                    continue\n            if cleared:\n                try:\n                    self._append_log(self.ram_log, \"\u2705 Standby cleared\", C[\"success\"])\n                except Exception:\n                    pass\n                return True\n\n            # Fallback: try to reduce system file cache size\n            try:\n                ctypes.windll.kernel32.SetSystemFileCacheSize(-1, -1, 0)\n                try:\n                    self._append_log(self.ram_log, \"\u2705 Standby cleared via SetSystemFileCacheSize\", C[\"success\"])\n                except Exception:\n                    pass\n                return True\n            except Exception:\n                try:\n                    self._append_log(self.ram_log, \"\u26a0 Could not clear standby lists (insufficient permissions?)\", C[\"warning\"])\n                except Exception:\n                    pass\n                return False\n\n        except Exception as e:\n            try:\n                self._append_log(self.ram_log, f\"Standby clear failed: {e}\", C[\"error\"])\n            except Exception:\n                pass\n            return False\n\n    def _ram_show_heavy(self):\n        \"\"\"RAM heavy processes ko popup window mein dikhao with Kill/Stop buttons\"\"\"\n        win = tk.Toplevel(self)\n        win.title(\"\ud83d\udd34 RAM Heavy Processes \u2014 Kill / Stop\")\n        win.geometry(\"820x500\")\n        win.configure(bg=C[\"bg\"])\n        win.resizable(True, True)\n\n        tk.Label(win, text=\"\ud83d\udd34  RAM Heavy Processes\", font=FONTS[\"subhead\"],\n                 fg=C[\"error\"], bg=C[\"bg\"]).pack(anchor=\"w\", padx=16, pady=(12, 4))\n        tk.Label(win, text=\"Process select karo \u2192 Kill (force) ya Terminate (graceful)\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"]).pack(anchor=\"w\", padx=16)\n\n        # --- treeview ---\n        cols = (\"PID\", \"Name\", \"RAM (MB)\", \"CPU %\", \"Status\")\n        tree_frame = tk.Frame(win, bg=C[\"bg\"])\n        tree_frame.pack(fill=\"both\", expand=True, padx=16, pady=8)\n        tree = ttk.Treeview(tree_frame, columns=cols, show=\"headings\",\n                            height=14, style=\"Custom.Treeview\", selectmode=\"extended\")\n        for col, w in zip(cols, [70, 260, 90, 70, 90]):\n            tree.heading(col, text=col)\n            tree.column(col, width=w, anchor=\"w\")\n        vsb = ttk.Scrollbar(tree_frame, orient=\"vertical\", command=tree.yview)\n        tree.configure(yscrollcommand=vsb.set)\n        tree.pack(side=\"left\", fill=\"both\", expand=True)\n        vsb.pack(side=\"right\", fill=\"y\")\n\n        status_lbl = tk.Label(win, text=\"Loading\u2026\", font=FONTS[\"small\"],\n                              fg=C[\"text_dim\"], bg=C[\"bg\"])\n        status_lbl.pack(anchor=\"w\", padx=16)\n\n        # --- buttons ---\n        btn_row = tk.Frame(win, bg=C[\"bg\"])\n        btn_row.pack(fill=\"x\", padx=16, pady=(4, 12))\n\n        def _refresh():\n            tree.delete(*tree.get_children())\n            status_lbl.config(text=\"Refreshing\u2026\", fg=C[\"text_dim\"])\n            try:\n                procs = sorted(\n                    psutil.process_iter(['pid', 'name', 'memory_info', 'cpu_percent', 'status']),\n                    key=lambda p: (p.info.get('memory_info') or type('', (), {'rss': 0})()).rss,\n                    reverse=True\n                )\n                count = 0\n                for p in procs[:30]:\n                    try:\n                        mem = p.info.get('memory_info')\n                        mb = round(mem.rss / (1024 ** 2), 1) if mem else 0\n                        cpu = p.info.get('cpu_percent', 0.0) or 0.0\n                        st = p.info.get('status', '?') or '?'\n                        tree.insert(\"\", \"end\", iid=str(p.info['pid']),\n                                    values=(p.info['pid'], p.info.get('name', '?'), mb, f\"{cpu:.1f}\", st))\n                        count += 1\n                    except Exception:\n                        pass\n                status_lbl.config(text=f\"\u2705 {count} processes loaded \u2014 multiple select ke liye Ctrl+Click\",\n                                  fg=C[\"success\"])\n            except Exception as ex:\n                status_lbl.config(text=f\"\u274c Error: {ex}\", fg=C[\"error\"])\n\n        def _kill_selected(graceful=False):\n            selected = tree.selection()\n            if not selected:\n                messagebox.showwarning(\"Select karo\", \"Pehle ek ya zyada processes select karo\", parent=win)\n                return\n            names = [tree.item(s)[\"values\"][1] for s in selected]\n            action = \"Terminate (graceful)\" if graceful else \"Kill (force)\"\n            if not messagebox.askyesno(\n                f\"Confirm \u2014 {action}\",\n                f\"{len(selected)} process(es) {action} karna hai?\\n\\n\" +\n                \"\\n\".join(str(n) for n in names[:10]) +\n                (\"\\n...\" if len(names) &gt; 10 else \"\") +\n                \"\\n\\nUnsaved data loss ho sakta hai!\",\n                parent=win\n            ):\n                return\n            done = 0\n            errs = []\n            for iid in selected:\n                try:\n                    pid = int(iid)\n                    proc = psutil.Process(pid)\n                    if graceful:\n                        proc.terminate()\n                    else:\n                        proc.kill()\n                    tree.delete(iid)\n                    done += 1\n                except psutil.NoSuchProcess:\n                    tree.delete(iid)\n                    done += 1\n                except Exception as ex:\n                    errs.append(f\"PID {iid}: {ex}\")\n            msg = f\"\u2705 {done} process(es) {action} kiye\"\n            if errs:\n                msg += f\"\\n\u26a0\ufe0f {len(errs)} errors: \" + \"; \".join(errs[:3])\n            status_lbl.config(text=msg, fg=C[\"success\"] if not errs else C[\"warning\"])\n            self._append_log(self.ram_log, msg, C[\"success\"] if not errs else C[\"warning\"])\n\n        tk.Button(btn_row, text=\"\ud83d\udd04 Refresh\", font=FONTS[\"body\"],\n                  bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=12, pady=6,\n                  cursor=\"hand2\", command=_refresh).pack(side=\"left\", padx=(0, 6))\n        tk.Button(btn_row, text=\"\u26a1 Terminate (Graceful)\", font=FONTS[\"body\"],\n                  bg=C[\"warning\"], fg=C[\"bg\"], bd=0, padx=12, pady=6,\n                  cursor=\"hand2\", command=lambda: _kill_selected(graceful=True)).pack(side=\"left\", padx=(0, 6))\n        tk.Button(btn_row, text=\"\ud83d\udc80 Kill (Force)\", font=FONTS[\"body\"],\n                  bg=C[\"error\"], fg=C[\"text\"], bd=0, padx=12, pady=6,\n                  cursor=\"hand2\", command=lambda: _kill_selected(graceful=False)).pack(side=\"left\", padx=(0, 6))\n        tk.Button(btn_row, text=\"\u2716 Close\", font=FONTS[\"body\"],\n                  bg=C[\"card\"], fg=C[\"text\"], bd=0, padx=12, pady=6,\n                  cursor=\"hand2\", command=win.destroy).pack(side=\"right\")\n\n        win.after(100, _refresh)  # auto load on open\n\n    def _do_ram_show_heavy(self):\n        try:\n            procs = sorted(psutil.process_iter(['pid','name','memory_info']),\n                           key=lambda p: (p.info.get('memory_info') or type('',(),{'rss':0})()).rss,\n                           reverse=True)\n            self._append_log(self.ram_log, \"\ud83d\udd34 Top 10 RAM-heavy processes:\", C[\"accent\"])\n            for p in procs[:10]:\n                try:\n                    mem = p.info.get('memory_info')\n                    mb = round(mem.rss/(1024**2),1) if mem else 0\n                    self._append_log(self.ram_log, f\"  PID {p.info['pid']:6d}  {p.info['name']:&lt;30s}  {mb} MB\", C[\"text\"])\n                except Exception:\n                    pass\n        except Exception:\n            self._append_log(self.ram_log, \"\u26a0\ufe0f Unable to enumerate RAM-heavy processes right now.\", C[\"warning\"])\n\n    # ---------- STARTUP MANAGER (unchanged except confirm) ----------\n    def _build_startup(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\ude80 Startup Manager\", \"Manage startup programs\")\n        self._action_card_grid(frame, [\n            (\"\ud83d\udd0d\", \"Refresh\",          \"Startup entries reload karo\",          C[\"btn_info\"], self._refresh_startup),\n            (\"\u26d4\", \"Disable Selected\", \"Selected entries boot pe nahi chalenge\",C[\"btn_warn\"], lambda: self._with_confirm(\"Disable Startup\", \"Disable selected startup entries? They won't run on boot.\", self._disable_startup)),\n            (\"\u2705\", \"Enable Selected\",  \"Selected entries wapas enable karo\",   C[\"btn\"],      lambda: self._with_confirm(\"Enable Startup\", \"Enable selected startup entries?\", self._enable_startup)),\n            (\"\ud83d\udce4\", \"Export List\",      \"Startup entries export karo\",        C[\"btn_chip\"], self._export_startup_list),\n            (\"\ud83d\udd0e\", \"Find Orphans\",     \"Missing target files ke startup entries\", C[\"btn_warn\"], self._find_orphan_startup_entries),\n        ], cols=5)\n        self.startup_tree = ttk.Treeview(frame, columns=(\"Name\", \"Command\", \"Location\", \"Status\"), show=\"headings\", height=20, style=\"Custom.Treeview\")\n        for col, w in zip((\"Name\", \"Command\", \"Location\", \"Status\"), [200,300,150,80]):\n            self.startup_tree.heading(col, text=col)\n            self.startup_tree.column(col, width=w, anchor=\"w\")\n        vsb = ttk.Scrollbar(frame, orient=\"vertical\", command=self.startup_tree.yview)\n        self.startup_tree.configure(yscrollcommand=vsb.set)\n        self.startup_tree.pack(side=\"left\", fill=\"both\", expand=True, padx=16, pady=8)\n        vsb.pack(side=\"right\", fill=\"y\", pady=8, padx=(0,8))\n        return frame\n\n    def _collect_startup_entries(self):\n        disabled_prefix = \"__GodawariDisabled__\"\n        seen = set()\n        entries = []\n        reg_locations = [\n            (\"HKCU\", winreg.HKEY_CURRENT_USER, r\"Software\\Microsoft\\Windows\\CurrentVersion\\Run\"),\n            (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"Software\\Microsoft\\Windows\\CurrentVersion\\Run\"),\n            (\"HKCU\", winreg.HKEY_CURRENT_USER, r\"Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce\"),\n            (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce\"),\n            (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"Software\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Run\"),\n            (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"Software\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\RunOnce\"),\n        ]\n        for hive_name, hive, reg_path in reg_locations:\n            try:\n                key = winreg.OpenKey(hive, reg_path, 0, winreg.KEY_READ)\n                i = 0\n                while True:\n                    try:\n                        name, value, _ = winreg.EnumValue(key, i)\n                        status = \"Disabled\" if name.startswith(disabled_prefix) else \"Enabled\"\n                        shown_name = name.replace(disabled_prefix, \"\", 1)\n                        dedupe_key = (shown_name.lower(), str(value).lower(), f\"{hive_name}|REG|{reg_path}\")\n                        if dedupe_key not in seen:\n                            seen.add(dedupe_key)\n                            entries.append({\n                                \"display_name\": shown_name,\n                                \"raw_name\": name,\n                                \"command\": str(value),\n                                \"location\": f\"{hive_name}|REG|{reg_path}\",\n                                \"status\": status,\n                                \"kind\": \"registry\",\n                                \"hive\": hive,\n                                \"reg_path\": reg_path,\n                                \"value\": value,\n                            })\n                        i += 1\n                    except OSError:\n                        break\n                winreg.CloseKey(key)\n            except Exception:\n                pass\n\n        startup_folders = [\n            (os.path.join(os.environ.get(\"APPDATA\", \"\"), r\"Microsoft\\Windows\\Start Menu\\Programs\\Startup\"), \"User Startup\"),\n            (os.path.join(os.environ.get(\"PROGRAMDATA\", \"\"), r\"Microsoft\\Windows\\Start Menu\\Programs\\StartUp\"), \"Common Startup\"),\n        ]\n        for folder, label in startup_folders:\n            if not folder or not os.path.exists(folder):\n                continue\n            try:\n                for f in Path(folder).glob(\"*\"):\n                    if not f.is_file():\n                        continue\n                    status = \"Disabled\" if f.name.endswith(\".disabled\") else \"Enabled\"\n                    shown_name = f.name[:-9] if status == \"Disabled\" else f.name\n                    dedupe_key = (shown_name.lower(), str(f).lower(), f\"{label}|FOLDER|{folder}\")\n                    if dedupe_key in seen:\n                        continue\n                    seen.add(dedupe_key)\n                    entries.append({\n                        \"display_name\": shown_name,\n                        \"raw_name\": f.name,\n                        \"command\": str(f),\n                        \"location\": f\"{label}|FOLDER|{folder}\",\n                        \"status\": status,\n                        \"kind\": \"folder\",\n                        \"path\": str(f),\n                    })\n            except Exception:\n                pass\n        return entries\n\n    def _refresh_startup(self):\n        self.startup_tree.delete(*self.startup_tree.get_children())\n        for entry in self._collect_startup_entries():\n            self.startup_tree.insert(\"\", \"end\", values=(entry[\"display_name\"], entry[\"command\"], entry[\"location\"], entry[\"status\"]))\n\n    def _refresh_registry_startup(self):\n        if not hasattr(self, \"registry_startup_tree\"):\n            return\n        self.registry_startup_tree.delete(*self.registry_startup_tree.get_children())\n        self._registry_startup_items = {}\n        for entry in self._collect_startup_entries():\n            uid = f\"startup-{len(self._registry_startup_items) + 1}\"\n            self._registry_startup_items[uid] = entry\n            self.registry_startup_tree.insert(\"\", \"end\", iid=uid, values=(entry[\"display_name\"], entry[\"command\"], entry[\"location\"], entry[\"status\"]))\n\n    def _delete_startup_entry(self, entry):\n        if not entry:\n            return False\n        try:\n            if entry[\"kind\"] == \"registry\":\n                key = winreg.OpenKey(entry[\"hive\"], entry[\"reg_path\"], 0, winreg.KEY_SET_VALUE | winreg.KEY_READ)\n                try:\n                    winreg.DeleteValue(key, entry[\"raw_name\"])\n                finally:\n                    winreg.CloseKey(key)\n                return True\n            path = Path(entry.get(\"path\") or entry.get(\"command\") or \"\")\n            if not path.exists():\n                return False\n            if path.is_dir():\n                shutil.rmtree(path, ignore_errors=True)\n            else:\n                path.unlink()\n            return True\n        except Exception:\n            return False\n\n    def _delete_registry_startup_selected(self):\n        if not hasattr(self, \"registry_startup_tree\"):\n            return\n        selected = self.registry_startup_tree.selection()\n        if not selected:\n            messagebox.showwarning(\"Nothing Selected\", \"Delete karne ke liye startup item select karo.\")\n            return\n        if not messagebox.askyesno(\"Delete Selected Startup Items\", f\"{len(selected)} selected startup item(s) delete karein? This affects boot behavior.\"):\n            return\n        deleted = 0\n        failed = 0\n        for iid in selected:\n            entry = self._registry_startup_items.get(iid)\n            if self._delete_startup_entry(entry):\n                deleted += 1\n                self.registry_startup_tree.delete(iid)\n                self._append_log(self.reg_log, f\"\ud83d\uddd1 Deleted startup item: {entry['display_name']}\", C[\"success\"])\n            else:\n                failed += 1\n                self._append_log(self.reg_log, f\"\u26a0 Could not delete startup item: {entry['display_name']}\", C[\"warning\"])\n        if deleted:\n            self._append_log(self.reg_log, f\"\u2705 Deleted {deleted} startup item(s).\", C[\"success\"])\n        if failed:\n            self._append_log(self.reg_log, f\"\u26a0 Failed to delete {failed} startup item(s).\", C[\"warning\"])\n\n    def _disable_startup(self):\n        for item in self.startup_tree.selection():\n            vals = self.startup_tree.item(item, \"values\")\n            if len(vals) &lt; 4 or vals[3] == \"Disabled\":\n                continue\n            name, command, loc = vals[0], vals[1], vals[2]\n            parts = loc.split(\"|\", 2)\n            if len(parts) &gt;= 3 and parts[1] == \"REG\":\n                hive = winreg.HKEY_CURRENT_USER if parts[0] == \"HKCU\" else winreg.HKEY_LOCAL_MACHINE\n                key = winreg.OpenKey(hive, parts[2], 0, winreg.KEY_SET_VALUE | winreg.KEY_READ)\n                value, vtype = winreg.QueryValueEx(key, name)\n                winreg.SetValueEx(key, \"__GodawariDisabled__\" + name, 0, vtype, value)\n                winreg.DeleteValue(key, name)\n                winreg.CloseKey(key)\n            elif len(parts) &gt;= 3 and parts[1] == \"FOLDER\":\n                src = Path(command)\n                dest = src.with_name(src.name + \".disabled\")\n                if src.exists():\n                    if dest.exists():\n                        dest.unlink()\n                    src.rename(dest)\n        self._refresh_startup()\n\n    def _enable_startup(self):\n        for item in self.startup_tree.selection():\n            vals = self.startup_tree.item(item, \"values\")\n            if len(vals) &lt; 4 or vals[3] == \"Enabled\":\n                continue\n            name, command, loc = vals[0], vals[1], vals[2]\n            parts = loc.split(\"|\", 2)\n            if len(parts) &gt;= 3 and parts[1] == \"REG\":\n                hive = winreg.HKEY_CURRENT_USER if parts[0] == \"HKCU\" else winreg.HKEY_LOCAL_MACHINE\n                key = winreg.OpenKey(hive, parts[2], 0, winreg.KEY_SET_VALUE | winreg.KEY_READ)\n                value, vtype = winreg.QueryValueEx(key, \"__GodawariDisabled__\" + name)\n                winreg.SetValueEx(key, name, 0, vtype, value)\n                winreg.DeleteValue(key, \"__GodawariDisabled__\" + name)\n                winreg.CloseKey(key)\n            elif len(parts) &gt;= 3 and parts[1] == \"FOLDER\":\n                src = Path(command)\n                if src.name.endswith(\".disabled\") and src.exists():\n                    dest = src.with_name(src.name[:-9])\n                    if dest.exists():\n                        dest.unlink()\n                    src.rename(dest)\n        self._refresh_startup()\n\n    def _startup_command_to_path(self, command):\n        if not command:\n            return \"\"\n        command = command.strip()\n        m = re.match(r'^\"([^\"]+)\"', command)\n        if m:\n            return m.group(1)\n        m = re.match(r'^([^\\s]+)', command)\n        return m.group(1) if m else \"\"\n\n    def _export_startup_list(self):\n        items = []\n        for item in self.startup_tree.get_children():\n            vals = self.startup_tree.item(item, \"values\")\n            if len(vals) &lt; 4:\n                continue\n            items.append(vals)\n        if not items:\n            messagebox.showinfo(\"No Startup Entries\", \"Koi startup entry export karne ko nahin mila.\")\n            return\n        path = filedialog.asksaveasfilename(defaultextension=\".csv\",\n                                            filetypes=[(\"CSV files\", \"*.csv\")],\n                                            initialfile=\"Startup_Entries.csv\",\n                                            title=\"Save Startup List\")\n        if not path:\n            return\n        try:\n            import csv\n            with open(path, \"w\", newline=\"\", encoding=\"utf-8\") as f:\n                writer = csv.writer(f)\n                writer.writerow([\"Name\", \"Command\", \"Location\", \"Status\"])\n                writer.writerows(items)\n            messagebox.showinfo(\"Exported\", f\"Startup list saved to:\\n{path}\")\n            self._append_log(self.clean_log, f\"\ud83d\udcbe Startup list exported: {path}\", C[\"success\"])\n        except Exception as e:\n            messagebox.showerror(\"Export Failed\", str(e))\n            self._append_log(self.clean_log, f\"\u274c Startup export failed: {e}\", C[\"error\"])\n\n    def _find_orphan_startup_entries(self):\n        orphaned = 0\n        for iid in self.startup_tree.get_children():\n            vals = self.startup_tree.item(iid, \"values\")\n            if len(vals) &lt; 3:\n                continue\n            path = self._startup_command_to_path(vals[1])\n            exists = os.path.exists(path) if path else False\n            if path and not exists:\n                orphaned += 1\n                self.startup_tree.item(iid, tags=(\"orphan\",))\n            else:\n                self.startup_tree.item(iid, tags=())\n        self.startup_tree.tag_configure(\"orphan\", background=\"#3D1D1D\")\n        if orphaned:\n            messagebox.showinfo(\"Orphaned Startup Entries\", f\"{orphaned} orphaned startup entries found. Check the list for missing targets.\")\n            self._append_log(self.clean_log, f\"\ud83d\udd0e Found {orphaned} orphaned startup entries.\", C[\"warning\"])\n        else:\n            messagebox.showinfo(\"No Orphans\", \"No missing startup targets detected.\")\n            self._append_log(self.clean_log, \"\u2705 No orphaned startup entries found.\", C[\"success\"])\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  TASK SCHEDULER \u2014 Knowledge Base\n    #  cat: \"danger\"   = Kabhi disable mat karo \u2014 system toot jayega\n    #       \"caution\"  = Soch ke karo \u2014 Windows feature affected hoga\n    #       \"safe\"     = Safely disable \u2014 performance badhegi\n    #       \"telemetry\"= Microsoft ko data bhejta hai \u2014 disable karo\n    #       \"thirdparty\"= Software ka auto-update/check task\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    TASK_DB = {\n        # \u2500\u2500 DANGER \u2014 kabhi mat chhuo \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        r\"\\Microsoft\\Windows\\UpdateOrchestrator\\Schedule Scan\":\n            (\"danger\", False, \"Windows Update scan \u2014 disable karne se security patches nahi aayenge. Bahut zaroori hai.\"),\n        r\"\\Microsoft\\Windows\\WindowsUpdate\\Scheduled Start\":\n            (\"danger\", False, \"Windows Update start task \u2014 disable = updates nahi hoge, security risk.\"),\n        r\"\\Microsoft\\Windows\\Defrag\\ScheduledDefrag\":\n            (\"caution\", True, \"HDD defragmentation \u2014 SSD pe disable karo (SSD ko defrag ki zarurat nahi). HDD pe rakho.\"),\n        r\"\\Microsoft\\Windows\\Diagnosis\\Scheduled\":\n            (\"caution\", True, \"Windows auto-diagnosis \u2014 system problems detect karta hai. Home pe safe to disable.\"),\n        r\"\\Microsoft\\Windows\\Chkdsk\\ProactiveScan\":\n            (\"caution\", True, \"Disk error check \u2014 SSD pe disable karo. HDD pe useful hai.\"),\n        r\"\\Microsoft\\Windows\\MemoryDiagnostic\\ProcessMemoryDiagnosticEvents\":\n            (\"caution\", True, \"RAM diagnostic events \u2014 home use pe disable kar sakte ho.\"),\n        r\"\\Microsoft\\Windows\\MemoryDiagnostic\\RunFullMemoryDiagnostic\":\n            (\"caution\", True, \"Full RAM scan \u2014 randomly chalta hai, system slow karta hai. Disable safe hai.\"),\n        # \u2500\u2500 TELEMETRY \u2014 Microsoft ko data bhejta hai \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        r\"\\Microsoft\\Windows\\Application Experience\\Microsoft Compatibility Appraiser\":\n            (\"telemetry\", True, \"CompatTelRunner.exe \u2014 CPU 100% kar deta hai! Microsoft ko compatibility data bhejta hai. DISABLE KARO.\"),\n        r\"\\Microsoft\\Windows\\Application Experience\\ProgramDataUpdater\":\n            (\"telemetry\", True, \"Application Experience data Microsoft ko bhejta hai. Disable karo.\"),\n        r\"\\Microsoft\\Windows\\Application Experience\\StartupAppTask\":\n            (\"telemetry\", True, \"Startup apps track karta hai \u2014 disable safe hai.\"),\n        r\"\\Microsoft\\Windows\\Application Experience\\AitAgent\":\n            (\"telemetry\", True, \"Application Impact Telemetry \u2014 Microsoft ko usage data bhejta hai. Disable karo.\"),\n        r\"\\Microsoft\\Windows\\Autochk\\Proxy\":\n            (\"telemetry\", True, \"AutoChk telemetry proxy \u2014 Microsoft ko data bhejta hai. Disable karo.\"),\n        r\"\\Microsoft\\Windows\\Customer Experience Improvement Program\\Consolidator\":\n            (\"telemetry\", True, \"CEIP data collector \u2014 Microsoft ko aapka usage data bhejta hai. Disable karo.\"),\n        r\"\\Microsoft\\Windows\\Customer Experience Improvement Program\\KernelCeipTask\":\n            (\"telemetry\", True, \"Kernel level CEIP \u2014 system ke andar se data collect karta hai. Disable karo.\"),\n        r\"\\Microsoft\\Windows\\Customer Experience Improvement Program\\UsbCeip\":\n            (\"telemetry\", True, \"USB devices ka usage data bhejta hai Microsoft ko. Disable karo.\"),\n        r\"\\Microsoft\\Windows\\Customer Experience Improvement Program\\Uploader\":\n            (\"telemetry\", True, \"CEIP data upload task \u2014 internet bandwidth use karta hai. Disable karo.\"),\n        r\"\\Microsoft\\Windows\\DiskFootprint\\Diagnostics\":\n            (\"telemetry\", True, \"Disk usage diagnostics data bhejta hai. Disable karo.\"),\n        r\"\\Microsoft\\Windows\\Feedback\\Siuf\\DmClient\":\n            (\"telemetry\", True, \"Windows Feedback \u2014 aapke opinions collect karta hai Microsoft ke liye. Disable karo.\"),\n        r\"\\Microsoft\\Windows\\Feedback\\Siuf\\DmClientOnScenarioDownload\":\n            (\"telemetry\", True, \"Feedback scenario download \u2014 disable karo.\"),\n        r\"\\Microsoft\\Windows\\NetTrace\\GatherNetworkInfo\":\n            (\"telemetry\", True, \"Network diagnostics data collect karta hai. Disable karo.\"),\n        r\"\\Microsoft\\Windows\\Power Efficiency Diagnostics\\AnalyzeSystem\":\n            (\"telemetry\", True, \"Power usage analysis \u2014 battery/power data bhejta hai. Disable karo.\"),\n        r\"\\Microsoft\\Windows\\Shell\\FamilySafetyMonitor\":\n            (\"telemetry\", True, \"Family Safety monitoring \u2014 use nahi karte to disable karo.\"),\n        r\"\\Microsoft\\Windows\\Shell\\FamilySafetyRefresh\":\n            (\"telemetry\", True, \"Family Safety data refresh \u2014 disable karo.\"),\n        r\"\\Microsoft\\Windows\\WS\\WSTask\":\n            (\"telemetry\", True, \"Windows Store telemetry \u2014 disable karo.\"),\n        # \u2500\u2500 SAFE TO DISABLE \u2014 performance badhegi \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        r\"\\Microsoft\\Windows\\DiskCleanup\\SilentCleanup\":\n            (\"safe\", True, \"Background disk cleanup \u2014 randomly disk scan karta hai, disk I/O badh jaati hai. Disable karo, manual cleanup use karo.\"),\n        r\"\\Microsoft\\Windows\\Maintenance\\WinSAT\":\n            (\"safe\", True, \"Windows System Assessment Tool \u2014 PC benchmark \u2014 randomly chalta hai, resources waste karta hai. Disable karo.\"),\n        r\"\\Microsoft\\Windows\\Maps\\MapsUpdateTask\":\n            (\"safe\", True, \"Windows Maps offline update \u2014 maps use nahi karte to disable karo.\"),\n        r\"\\Microsoft\\Windows\\Maps\\MapsToastTask\":\n            (\"safe\", True, \"Maps toast notification \u2014 disable karo.\"),\n        r\"\\Microsoft\\Windows\\Offline Files\\Background Synchronization\":\n            (\"safe\", True, \"Offline file sync \u2014 network shared files use nahi karte to disable karo.\"),\n        r\"\\Microsoft\\Windows\\Offline Files\\Logon Synchronization\":\n            (\"safe\", True, \"Offline files login sync \u2014 home PC pe disable karo.\"),\n        r\"\\Microsoft\\Windows\\RemoteAssistance\\RemoteAssistanceTask\":\n            (\"safe\", True, \"Remote Assistance \u2014 koi aapke PC par remotely connect nahi karta to disable karo.\"),\n        r\"\\Microsoft\\Windows\\RetailDemo\\CleanupOfflineContent\":\n            (\"safe\", True, \"Retail Demo cleanup \u2014 shop display ke liye hai. Home PC pe immediately disable karo.\"),\n        r\"\\Microsoft\\Windows\\SettingSync\\BackgroundUploadTask\":\n            (\"safe\", True, \"Settings cloud sync \u2014 OneDrive/Microsoft account sync. Privacy ke liye disable karo.\"),\n        r\"\\Microsoft\\Windows\\SettingSync\\NetworkStateChangeTask\":\n            (\"safe\", True, \"Settings sync on network change \u2014 disable karo.\"),\n        r\"\\Microsoft\\Windows\\FileHistory\\File History (maintenance mode)\":\n            (\"safe\", True, \"File History maintenance \u2014 use nahi karte to disable karo.\"),\n        r\"\\Microsoft\\Windows\\Ras\\MobilityManager\":\n            (\"safe\", True, \"Mobile broadband manager \u2014 WiFi/ethernet use karte ho to disable karo.\"),\n        r\"\\Microsoft\\Windows\\Location\\Notifications\":\n            (\"safe\", True, \"Location notifications \u2014 privacy ke liye disable karo.\"),\n        r\"\\Microsoft\\Windows\\Location\\WindowsActionDialog\":\n            (\"safe\", True, \"Location access dialog \u2014 disable karo.\"),\n        r\"\\Microsoft\\Windows\\.NET Framework\\.NET Framework NGEN v4.0.30319\":\n            (\"safe\", True, \".NET optimization \u2014 ek baar chalta hai, phir dobara nahi chahiye. Disable karo.\"),\n        r\"\\Microsoft\\Windows\\.NET Framework\\.NET Framework NGEN v4.0.30319 64\":\n            (\"safe\", True, \".NET 64-bit optimization \u2014 disable karo.\"),\n        r\"\\Microsoft\\Windows\\WDI\\ResolutionHost\":\n            (\"safe\", True, \"Windows Diagnostic Infrastructure \u2014 resource heavy. Disable karo.\"),\n    }\n\n    TASK_CAT_COLOR = {\n        \"danger\":     \"#FF4444\",\n        \"caution\":    \"#FF9800\",\n        \"safe\":       \"#4CAF50\",\n        \"telemetry\":  \"#CE93D8\",\n        \"thirdparty\": \"#64B5F6\",\n    }\n    TASK_CAT_ICON = {\n        \"danger\":\"\ud83d\udd34\",\"caution\":\"\ud83d\udfe0\",\"safe\":\"\ud83d\udfe2\",\"telemetry\":\"\ud83d\udfe3\",\"thirdparty\":\"\ud83d\udd35\"\n    }\n\n    # \u2500\u2500 Preset packs \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    TASK_PRESETS = {\n        \"\u26a1 Telemetry Pack (Privacy)\": {\n            \"desc\": \"Saari Microsoft telemetry tasks disable ho jaayengi \u2014 privacy behtar hogi, CPU spikes khatam.\",\n            \"cats\": {\"telemetry\"}\n        },\n        \"\ud83d\ude80 Performance Pack\": {\n            \"desc\": \"Performance wali tasks disable \u2014 DiskCleanup, WinSAT, .NET NGEN, offline sync sab band.\",\n            \"cats\": {\"safe\"}\n        },\n        \"\u2622\ufe0f Full Nuke (Telemetry + Safe)\": {\n            \"desc\": \"Sabse aggressive \u2014 telemetry + safe tasks dono disable. Maximum performance.\",\n            \"cats\": {\"telemetry\",\"safe\"}\n        },\n    }\n\n    def _build_scheduler(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udcc5 Smart Task Scheduler\",\n                             \"Color-coded \u2014 Danger / Caution / Safe / Telemetry / 3rd Party\")\n\n        # \u2500\u2500 Compact top toolbar (1 row: buttons + filter + legend inline) \u2500\u2500\n        toolbar = tk.Frame(frame, bg=C[\"card\"])\n        toolbar.pack(fill=\"x\", padx=0, pady=0)\n\n        # Action buttons \u2014 inline, compact\n        btn_row = tk.Frame(toolbar, bg=C[\"card\"])\n        btn_row.pack(fill=\"x\", padx=10, pady=4)\n\n        for txt, color, cmd in [\n            (\"\ud83d\udd0d Scan Tasks\",      C[\"btn_info\"],   self._scan_tasks),\n            (\"\u26d4 Disable\",         C[\"btn_warn\"],   self._task_disable_safe),\n            (\"\u2705 Enable\",          C[\"btn\"],        lambda: self._with_confirm(\"Enable Tasks\",\"Enable selected tasks?\", self._enable_task)),\n            (\"\ud83d\uddd1 Delete\",          C[\"btn_danger\"], self._task_delete_safe),\n            (\"\ud83d\udcbe Backup\",          C[\"btn_chip\"],   self._backup_tasks),\n            (\"\ud83d\udd12 Telemetry Pack\",  C[\"btn_hw\"],     lambda: self._apply_task_preset(self.TASK_PRESETS[\"\u26a1 Telemetry Pack (Privacy)\"])),\n            (\"\ud83d\ude80 Perf Pack\",       C[\"btn_hw\"],     lambda: self._apply_task_preset(self.TASK_PRESETS[\"\ud83d\ude80 Performance Pack\"])),\n            (\"\u2622 Full Nuke\",        C[\"btn_hw\"],     lambda: self._apply_task_preset(self.TASK_PRESETS[\"\u2622\ufe0f Full Nuke (Telemetry + Safe)\"])),\n        ]:\n            tk.Button(btn_row, text=txt, font=FONTS[\"small\"], bg=color,\n                      fg=C[\"text\"], bd=0, padx=9, pady=4, cursor=\"hand2\",\n                      command=cmd).pack(side=\"left\", padx=2)\n\n        # \u2500\u2500 Compact: filter + stat counts + legend \u2014 single row \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        mid = tk.Frame(frame, bg=C[\"bg\"])\n        mid.pack(fill=\"x\", padx=10, pady=(2,0))\n\n        # Filter\n        tk.Label(mid, text=\"\ud83d\udd0e\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"]).pack(side=\"left\", padx=(4,2))\n        self.task_search = tk.Entry(mid, width=16, font=FONTS[\"small\"],\n                                    bg=C[\"card\"], fg=C[\"text\"],\n                                    insertbackground=C[\"text\"], relief=\"flat\", bd=3)\n        self.task_search.pack(side=\"left\", padx=(0,4))\n        self.task_search.bind(\"\", self._filter_tasks)\n\n        for lbl, val in [(\"All\",\"all\"),(\"\ud83d\udd34\",\"danger\"),(\"\ud83d\udfe0\",\"caution\"),\n                         (\"\ud83d\udfe2\",\"safe\"),(\"\ud83d\udfe3\",\"telemetry\"),(\"\ud83d\udd35\",\"thirdparty\"),(\"\u26a0\",\"highcpu\")]:\n            tk.Button(mid, text=lbl, font=FONTS[\"small\"],\n                      bg=C[\"card\"], fg=C[\"text\"], bd=0, padx=5, pady=2,\n                      cursor=\"hand2\",\n                      command=lambda v=val: self._filter_task_cat(v)).pack(side=\"left\", padx=1)\n\n        # Stat counts inline\n        tk.Frame(mid, bg=C[\"border\"], width=1).pack(side=\"left\", fill=\"y\", padx=6)\n        self.task_stat_vars = {}\n        for k, lbl, col in [\n            (\"danger\",\"\ud83d\udd34 Danger\",\"#FF4444\"),(\"caution\",\"\ud83d\udfe0 Caution\",\"#FF9800\"),\n            (\"safe\",\"\ud83d\udfe2 Safe\",\"#4CAF50\"),(\"telemetry\",\"\ud83d\udfe3 Telem\",\"#CE93D8\"),\n            (\"thirdparty\",\"\ud83d\udd35 3rd\",\"#64B5F6\"),(\"total\",\"Total\",C[\"accent\"]),\n        ]:\n            v = tk.StringVar(value=\"--\")\n            self.task_stat_vars[k] = v\n            f = tk.Frame(mid, bg=C[\"card\"], padx=5, pady=2)\n            f.pack(side=\"left\", padx=2)\n            tk.Label(f, text=lbl, font=(FONTS[\"small\"][0], 7), fg=col, bg=C[\"card\"]).pack()\n            tk.Label(f, textvariable=v, font=(FONTS[\"small\"][0], 9, \"bold\"), fg=col, bg=C[\"card\"]).pack()\n\n        self.task_count_lbl = tk.Label(mid, text=\"\", font=FONTS[\"small\"],\n                                        fg=C[\"accent\"], bg=C[\"bg\"])\n        self.task_count_lbl.pack(side=\"right\", padx=8)\n\n        # \u2500\u2500 Full-width task list \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        list_frame = tk.Frame(frame, bg=C[\"card\"])\n        list_frame.pack(fill=\"both\", expand=True, padx=16, pady=(4,0))\n        list_frame.rowconfigure(0, weight=1)\n        list_frame.columnconfigure(0, weight=1)\n\n        cols = (\"Cat\",\"Task Name\",\"Path\",\"Status\",\"Last Run\",\"Safe?\")\n        self.task_tree = ttk.Treeview(list_frame, columns=cols, show=\"headings\",\n                                      height=28, style=\"Custom.Treeview\",\n                                      selectmode=\"extended\")\n        widths = [28, 280, 340, 80, 120, 65]\n        for col, w in zip(cols, widths):\n            self.task_tree.heading(col, text=col,\n                                   command=lambda c=col: self._sort_tasks(c))\n            self.task_tree.column(col, width=w,\n                                  anchor=\"center\" if col in (\"Cat\",\"Status\",\"Safe?\") else \"w\")\n        for cat, color in self.TASK_CAT_COLOR.items():\n            self.task_tree.tag_configure(cat, foreground=color)\n        self.task_tree.tag_configure(\"highcpu\", background=\"#2A1500\")\n        vsb = ttk.Scrollbar(list_frame, orient=\"vertical\", command=self.task_tree.yview)\n        hsb = ttk.Scrollbar(list_frame, orient=\"horizontal\", command=self.task_tree.xview)\n        self.task_tree.configure(yscrollcommand=vsb.set, xscrollcommand=hsb.set)\n        self.task_tree.grid(row=0, column=0, sticky=\"nsew\", padx=(4,0), pady=(4,0))\n        vsb.grid(row=0, column=1, sticky=\"ns\", pady=(4,0))\n        hsb.grid(row=1, column=0, sticky=\"ew\", padx=(4,0))\n        self.task_tree.bind(\"&lt;&gt;\", self._on_task_select)\n\n        # \u2500\u2500 Bottom collapsible detail + action log strip \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        bot = tk.Frame(frame, bg=C[\"panel\"])\n        bot.pack(fill=\"x\", padx=16, pady=(2,8))\n        bot.columnconfigure(0, weight=3)\n        bot.columnconfigure(1, weight=1)\n\n        # Detail box (left-bottom)\n        detail_wrap = tk.Frame(bot, bg=C[\"card\"])\n        detail_wrap.grid(row=0, column=0, sticky=\"nsew\", padx=(0,4), pady=4)\n        detail_wrap.rowconfigure(1, weight=1)\n        detail_wrap.columnconfigure(0, weight=1)\n\n        hdr_d = tk.Frame(detail_wrap, bg=C[\"card\"])\n        hdr_d.grid(row=0, column=0, sticky=\"ew\", padx=6, pady=(4,2))\n        tk.Label(hdr_d, text=\"  \ud83d\udccb Task Detail &amp; Risk Info\",\n                 font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\")\n        tk.Label(hdr_d, text=\"(koi bhi task click karo \u2014 detail yahan dikhe gi)\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\", padx=6)\n\n        self.task_detail = scrolledtext.ScrolledText(\n            detail_wrap, font=(\"Consolas\", 9), bg=\"#0D1117\", fg=C[\"text\"],\n            height=8, bd=0, relief=\"flat\", state=\"disabled\", wrap=\"word\")\n        self.task_detail.grid(row=1, column=0, sticky=\"nsew\", padx=6, pady=(0,4))\n\n        # Action log (right-bottom)\n        log_wrap = tk.Frame(bot, bg=C[\"card\"])\n        log_wrap.grid(row=0, column=1, sticky=\"nsew\", padx=(4,0), pady=4)\n        log_wrap.rowconfigure(1, weight=1)\n        log_wrap.columnconfigure(0, weight=1)\n        tk.Label(log_wrap, text=\"  \ud83d\udcdd Action Log\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).grid(\n                 row=0, column=0, sticky=\"w\", padx=6, pady=(4,2))\n        self.task_action_log = scrolledtext.ScrolledText(\n            log_wrap, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"],\n            insertbackground=C[\"text\"], height=8, bd=0, wrap=\"word\",\n            relief=\"flat\", state=\"disabled\")\n        self.task_action_log.grid(row=1, column=0, sticky=\"nsew\", padx=6, pady=(0,4))\n\n        # Internal state\n        self._task_all_rows = []\n        self._task_cur_cat = \"all\"\n        self._task_sort_col = \"\"\n        self._task_sort_rev = False\n        return frame\n\n    def _scan_tasks(self):\n        self._set_status(\"Scanning scheduled tasks...\", C[\"accent4\"])\n        if hasattr(self, \"_task_scan_status\"):\n            self._task_scan_status.config(text=\"  \u23f3 Scan chal rahi hai...\", fg=C[\"accent4\"])\n        self._launch_job(\"scan_tasks\", self._do_scan_tasks)\n\n    def _do_scan_tasks_legacy(self):\n        self.after(0, lambda: [self.task_tree.delete(i) for i in self.task_tree.get_children()])\n\n        # schtasks /query /fo CSV /v \u2014 fastest method\n        out, _ = self._run_cmd('schtasks /query /fo CSV /v', timeout=25)\n\n        # Third-party path indicators\n        THIRD_PARTY_ROOTS = {\n            \"google\",\"mozilla\",\"adobe\",\"java\",\"dropbox\",\"spotify\",\"discord\",\n            \"steam\",\"nvidia\",\"amd\",\"intel\",\"realtek\",\"logitech\",\"corsair\",\n            \"razer\",\"zoom\",\"teams\",\"skype\",\"ccleaner\",\"iobit\",\"malwarebytes\",\n            \"avast\",\"avg\",\"kaspersky\",\"mcafee\",\"norton\",\"bitdefender\",\n        }\n\n        counts = {k:0 for k in (\"danger\",\"caution\",\"safe\",\"telemetry\",\"thirdparty\",\"total\")}\n        seen   = set()\n        rows   = []\n\n        for line in out.splitlines():\n            line = line.strip().replace('\"','')\n            parts = line.split(',')\n            if len(parts) &lt; 7 or parts[0] == \"TaskName\":\n                continue\n            task_full = parts[0].strip()\n            status    = parts[3].strip() if len(parts) &gt; 3 else \"\"\n            last_run  = parts[5].strip() if len(parts) &gt; 5 else \"\"\n            if not task_full or task_full in seen:\n                continue\n            seen.add(task_full)\n\n            # Path split\n            if \"\\\\\" in task_full:\n                tpath = task_full.rsplit(\"\\\\\",1)[0] + \"\\\\\"\n                tname = task_full.rsplit(\"\\\\\",1)[1]\n            else:\n                tpath = \"\\\\\"\n                tname = task_full\n\n            if not tname:\n                continue\n\n            # Lookup DB\n            if task_full in self.TASK_DB:\n                cat, safe, desc = self.TASK_DB[task_full]\n            else:\n                tpath_low = tpath.lower()\n                tname_low = tname.lower()\n                full_low  = task_full.lower()\n                is_third = any(tp in full_low for tp in THIRD_PARTY_ROOTS)\n                if is_third:\n                    cat  = \"thirdparty\"\n                    safe = True\n                    desc = (f\"'{tname}' \u2014 Third-party software task.\\n\"\n                            \"Agar woh software use karte ho: disable mat karo.\\n\"\n                            \"Agar uninstall ho gaya: disable kar sakte ho.\")\n                elif \"\\\\microsoft\\\\windows\\\\\" in full_low:\n                    # Skip system tasks not in DB \u2014 they're likely safe/necessary\n                    if status.lower() == \"disabled\":\n                        continue\n                    cat  = \"caution\"\n                    safe = False\n                    desc = (f\"'{tname}' \u2014 Windows system task (hamare database mein nahi).\\n\"\n                            \"Google karo pehle, phir decide karo.\")\n                else:\n                    cat  = \"safe\"\n                    safe = True\n                    desc = (f\"'{tname}' \u2014 Unknown task, root folder mein hai.\\n\"\n                            \"Likely kisi software ka task hai. Safe to disable if unrecognized.\")\n\n            if status.lower() == \"disabled\":\n                continue\n\n            icon = self.TASK_CAT_ICON.get(cat,\"\u26aa\")\n            safe_txt = \"\u2705\" if safe else \"\u274c\"\n            row = (icon, tname, tpath, status, last_run[:16], safe_txt)\n            meta = {\"cat\":cat,\"safe\":safe,\"desc\":desc,\n                    \"full\":task_full,\"name\":tname,\"path\":tpath,\"status\":status,\n                    \"last_run\":last_run[:16] if last_run else \"N/A\"}\n            rows.append((row, (cat,), meta))\n            if cat in counts:\n                counts[cat] += 1\n            counts[\"total\"] += 1\n\n        self._task_all_rows = rows\n\n        def insert():\n            self._render_task_rows(rows)\n            for k,v in counts.items():\n                if k in self.task_stat_vars:\n                    self.task_stat_vars[k].set(str(v))\n            self._set_status(\n                f\"Scan done \u2014 {counts['total']} tasks | \"\n                f\"\ud83d\udfe3{counts['telemetry']} Telemetry | \"\n                f\"\ud83d\udfe2{counts['safe']} Safe | \"\n                f\"\ud83d\udfe0{counts['caution']} Caution | \"\n                f\"\ud83d\udd35{counts['thirdparty']} 3rd-Party\",\n                C[\"success\"])\n            if hasattr(self, \"_task_scan_status\"):\n                self._task_scan_status.config(\n                    text=f\"  \u2705 {counts['total']} tasks mile \u2014 task pe click karo detail dekhne ke liye\",\n                    fg=C[\"success\"])\n        self.after(0, insert)\n\n    def _do_scan_tasks(self):\n        self.after(0, lambda: [self.task_tree.delete(i) for i in self.task_tree.get_children()])\n        out, _ = self._run_cmd('schtasks /query /fo CSV /v', timeout=25)\n        third_party_roots = {\n            \"google\",\"mozilla\",\"adobe\",\"java\",\"dropbox\",\"spotify\",\"discord\",\n            \"steam\",\"nvidia\",\"amd\",\"intel\",\"realtek\",\"logitech\",\"corsair\",\n            \"razer\",\"zoom\",\"teams\",\"skype\",\"ccleaner\",\"iobit\",\"malwarebytes\",\n            \"avast\",\"avg\",\"kaspersky\",\"mcafee\",\"norton\",\"bitdefender\",\n        }\n        counts = {k: 0 for k in (\"danger\",\"caution\",\"safe\",\"telemetry\",\"thirdparty\",\"total\")}\n        seen = set()\n        rows = []\n        for record in self._task_records_from_schtasks(out):\n            task_full = (record.get(\"TaskName\") or record.get(\"Task Name\") or \"\").strip()\n            scheduled_state = (record.get(\"Scheduled Task State\") or \"\").strip()\n            status = (record.get(\"Status\") or scheduled_state or \"\").strip()\n            last_run = (record.get(\"Last Run Time\") or record.get(\"LastRunTime\") or \"\").strip()\n            run_cmd = (record.get(\"Task To Run\") or \"\").strip()\n            if not task_full or task_full in seen:\n                continue\n            seen.add(task_full)\n            if \"\\\\\" in task_full:\n                tpath = task_full.rsplit(\"\\\\\", 1)[0] + \"\\\\\"\n                tname = task_full.rsplit(\"\\\\\", 1)[1]\n            else:\n                tpath = \"\\\\\"\n                tname = task_full\n            if not tname:\n                continue\n            if task_full in self.TASK_DB:\n                cat, safe, desc = self.TASK_DB[task_full]\n            else:\n                full_low = task_full.lower()\n                is_third = any(tp in full_low for tp in third_party_roots)\n                if is_third:\n                    cat = \"thirdparty\"\n                    safe = True\n                    desc = (f\"'{tname}' - Third-party software task.\\n\"\n                            \"Agar woh software use karte ho: disable mat karo.\\n\"\n                            \"Agar uninstall ho gaya: disable kar sakte ho.\")\n                elif \"\\\\microsoft\\\\windows\\\\\" in full_low:\n                    if status.lower() == \"disabled\" or scheduled_state.lower() == \"disabled\":\n                        continue\n                    cat = \"caution\"\n                    safe = False\n                    desc = (f\"'{tname}' - Windows system task (database mein nahi).\\n\"\n                            \"Google karo pehle, phir decide karo.\")\n                else:\n                    cat = \"safe\"\n                    safe = True\n                    desc = (f\"'{tname}' - Unknown task, root folder mein hai.\\n\"\n                            \"Likely kisi software ka task hai. Safe to disable if unrecognized.\")\n            if status.lower() == \"disabled\" or scheduled_state.lower() == \"disabled\":\n                continue\n            icon = self.TASK_CAT_ICON.get(cat, \"*\")\n            safe_txt = \"\u2705\" if safe else \"\u274c\"\n            row = (icon, tname, tpath, status, last_run[:16], safe_txt)\n            meta = {\"cat\": cat, \"safe\": safe, \"desc\": desc,\n                    \"full\": task_full, \"name\": tname, \"path\": tpath, \"status\": status,\n                    \"last_run\": last_run[:16] if last_run else \"N/A\",\n                    \"run_cmd\": run_cmd or \"N/A\",\n                    \"scheduled_state\": scheduled_state or \"N/A\"}\n            rows.append((row, (cat,), meta))\n            if cat in counts:\n                counts[cat] += 1\n            counts[\"total\"] += 1\n        self._task_all_rows = rows\n\n        def insert():\n            self._render_task_rows(rows)\n            for k, v in counts.items():\n                if k in self.task_stat_vars:\n                    self.task_stat_vars[k].set(str(v))\n            self._set_status(\n                f\"Scan done - {counts['total']} tasks | \"\n                f\"{counts['telemetry']} Telemetry | \"\n                f\"{counts['safe']} Safe | \"\n                f\"{counts['caution']} Caution | \"\n                f\"{counts['thirdparty']} 3rd-Party\",\n                C[\"success\"])\n            if hasattr(self, \"_task_scan_status\"):\n                self._task_scan_status.config(\n                    text=f\"  {counts['total']} tasks mile - task pe click karo detail dekhne ke liye\",\n                    fg=C[\"success\"])\n        self.after(0, insert)\n\n    def _render_task_rows(self, rows):\n        for i in self.task_tree.get_children():\n            self.task_tree.delete(i)\n        for row, tags, _ in rows:\n            self.task_tree.insert(\"\",\"end\", values=row, tags=tags)\n        self.task_count_lbl.config(text=f\"{len(rows)} tasks\")\n\n    def _filter_tasks(self, event=None):\n        txt = self.task_search.get().lower() if hasattr(self,\"task_search\") else \"\"\n        cat = self._task_cur_cat\n        filtered = [r for r in self._task_all_rows\n                    if (cat==\"all\" or cat in r[1])\n                    and (not txt or txt in r[2][\"name\"].lower()\n                         or txt in r[2][\"path\"].lower())]\n        self._render_task_rows(filtered)\n\n    def _filter_task_cat(self, cat):\n        self._task_cur_cat = cat\n        self._filter_tasks()\n\n    def _sort_tasks(self, col):\n        col_map = {\"Cat\":0,\"Task Name\":1,\"Path\":2,\"Status\":3,\"Last Run\":4,\"Safe?\":5}\n        idx = col_map.get(col,1)\n        if self._task_sort_col == col:\n            self._task_sort_rev = not self._task_sort_rev\n        else:\n            self._task_sort_col = col\n            self._task_sort_rev = False\n        self._task_all_rows.sort(key=lambda r: r[0][idx], reverse=self._task_sort_rev)\n        self._filter_tasks()\n\n    def _on_task_select(self, event=None):\n        sel = self.task_tree.selection()\n        if not sel:\n            return\n        iid = sel[0]\n        idx = self.task_tree.index(iid)\n        visible = self._get_visible_task_rows()\n        if idx &gt;= len(visible):\n            return\n        meta = visible[idx][2]\n        cat  = meta[\"cat\"]\n        safe = meta[\"safe\"]\n        desc = meta[\"desc\"]\n        icon = self.TASK_CAT_ICON.get(cat,\"\u26aa\")\n        col  = self.TASK_CAT_COLOR.get(cat, C[\"text\"])\n\n        cat_label = {\n            \"danger\":    \"\ud83d\udd34 DANGER \u2014 Kabhi disable mat karo\",\n            \"caution\":   \"\ud83d\udfe0 CAUTION \u2014 Soch ke disable karo\",\n            \"safe\":      \"\ud83d\udfe2 SAFE \u2014 Disable karne se performance badhegi\",\n            \"telemetry\": \"\ud83d\udfe3 TELEMETRY \u2014 Microsoft ko data bhejta hai\",\n            \"thirdparty\":\"\ud83d\udd35 THIRD-PARTY \u2014 Software ka task\",\n        }.get(cat,\"\u26aa Unknown\")\n\n        risk_box = {\n            \"danger\":   (\"\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\\n\"\n                         \"\u2551 \u26d4 DISABLE MAT KARO \u2014 SYSTEM TOOTEGA \u2551\\n\"\n                         \"\u255a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255d\\n\"),\n            \"caution\":  \"\u26a0\ufe0f  SAWDHAN \u2014 Pehle Google karo, phir disable karo.\\n\",\n            \"safe\":     \"\u2705 DISABLE KARO \u2014 Safe hai, performance badhegi.\\n\",\n            \"telemetry\":(\"\ud83d\udfe3 DISABLE KARO \u2014 Ye task Microsoft ko aapka data bhejta hai.\\n\"\n                         \"   Privacy aur CPU ke liye disable karna better hai.\\n\"),\n            \"thirdparty\":(\"\ud83d\udd35 THIRD-PARTY \u2014 Agar software use karte ho: chhodo.\\n\"\n                          \"   Agar software remove ho gaya: Disable karo.\\n\"),\n        }.get(cat,\"\")\n\n        lines = [\n            f\"Task Name  : {meta['name']}\",\n            f\"Full Path  : {meta['full']}\",\n            f\"Category   : {cat_label}\",\n            f\"Status     : {meta['status']}\",\n            f\"Process    : {meta.get('run_cmd', 'N/A')}\",\n            f\"Last Run   : {meta.get('last_run', 'N/A')}\",\n            f\"Safe Disable: {'\u2705 Haan' if safe else '\u274c Nahi'}\",\n            \"\", \"\u2500\"*52, \"\",\n            \"\ud83d\udcd6 DESCRIPTION:\",\n            desc,\n            \"\", \"\u2500\"*52, \"\",\n            \"\u26a0\ufe0f  DISABLE KARNE SE KYA HOGA:\",\n            risk_box,\n            \"\ud83d\udca1 TIP:\",\n            {\n                \"danger\":    \"Isko chhod do \u2014 Windows ke kaam ka hai.\",\n                \"caution\":   \"SSD pe defrag/chkdsk disable karo \u2014 warna safe mat karo.\",\n                \"safe\":      f\"schtasks /Change /TN \\\"{meta['full']}\\\" /Disable\",\n                \"telemetry\": f\"schtasks /Change /TN \\\"{meta['full']}\\\" /Disable\",\n                \"thirdparty\":\"Software se hi manage karo ya uninstall karo.\",\n            }.get(cat,\"\"),\n        ]\n\n        self.task_detail.config(state=\"normal\")\n        self.task_detail.delete(\"1.0\",\"end\")\n        self.task_detail.tag_configure(\"red\",    foreground=\"#FF4444\")\n        self.task_detail.tag_configure(\"orange\", foreground=\"#FF9800\")\n        self.task_detail.tag_configure(\"green\",  foreground=\"#4CAF50\")\n        self.task_detail.tag_configure(\"purple\", foreground=\"#CE93D8\")\n        self.task_detail.tag_configure(\"blue\",   foreground=\"#64B5F6\")\n        self.task_detail.tag_configure(\"dim\",    foreground=\"#A0B0C8\")\n        for line in lines:\n            tag = \"dim\"\n            if \"DISABLE MAT\" in line or \"\u26d4\" in line: tag = \"red\"\n            elif \"SAWDHAN\" in line or \"\u26a0\ufe0f\" in line:   tag = \"orange\"\n            elif \"\u2705\" in line and \"DISABLE KARO\" in line: tag = \"green\"\n            elif \"\ud83d\udfe3\" in line:                         tag = \"purple\"\n            elif \"\ud83d\udd35\" in line:                         tag = \"blue\"\n            elif line.startswith(\"\u2500\"):                 tag = \"dim\"\n            elif line.startswith(\"Task\") or line.startswith(\"Full\") or line.startswith(\"Status\"): tag = \"dim\"\n            self.task_detail.insert(\"end\", line+\"\\n\", tag)\n        self.task_detail.config(state=\"disabled\")\n\n    def _get_visible_task_rows(self):\n        cat = self._task_cur_cat\n        txt = self.task_search.get().lower() if hasattr(self,\"task_search\") else \"\"\n        rows = self._task_all_rows\n        if cat != \"all\":\n            rows = [r for r in rows if cat in r[1]]\n        if txt:\n            rows = [r for r in rows\n                    if txt in r[2][\"name\"].lower() or txt in r[2][\"path\"].lower()]\n        return rows\n\n    def _task_disable_safe(self):\n        sel = self.task_tree.selection()\n        if not sel:\n            messagebox.showinfo(\"No Selection\",\"Pehle ek task select karo.\")\n            return\n        visible = self._get_visible_task_rows()\n        block, warn, targets = [], [], []\n        for iid in sel:\n            idx = self.task_tree.index(iid)\n            if idx &gt;= len(visible): continue\n            meta = visible[idx][2]\n            if meta[\"cat\"] == \"danger\" and not meta[\"safe\"]:\n                block.append(f\"  \ud83d\udd34 {meta['name']} \u2014 DANGER!\")\n            elif meta[\"cat\"] == \"caution\":\n                warn.append(f\"  \ud83d\udfe0 {meta['name']} \u2014 Caution task\")\n            targets.append(meta)\n\n        if block:\n            messagebox.showerror(\"\u26d4 KHATARNAK!\",\n                \"Ye tasks KABHI disable mat karo \u2014 system crash ho sakta hai!\\n\\n\"\n                + \"\\n\".join(block) + \"\\n\\nDeselect karo aur dubara try karo.\")\n            return\n        msg = f\"Disable karne se ye {len(targets)} tasks band ho jaayenge:\\n\\n\"\n        msg += \"\\n\".join(f\"  {self.TASK_CAT_ICON.get(t['cat'],'\u2022')} {t['name']}\" for t in targets[:15])\n        if len(targets) &gt; 15:\n            msg += f\"\\n  ...aur {len(targets)-15} aur\"\n        if warn:\n            msg += \"\\n\\n\u26a0\ufe0f CAUTION tasks included:\\n\" + \"\\n\".join(warn)\n        msg += \"\\n\\nAage badhein?\"\n        if not messagebox.askyesno(\"Confirm Disable\", msg):\n            return\n        disabled = 0\n        for meta in targets:\n            out, rc = self._run_cmd(f'schtasks /Change /TN \"{meta[\"full\"]}\" /Disable')\n            if rc == 0:\n                disabled += 1\n                self._append_log(self.task_action_log, f\"\u2705 Disabled: {meta['name']}\", C[\"success\"])\n            else:\n                self._append_log(self.task_action_log, f\"\u274c Failed: {meta['name']} \u2014 {out[:60]}\", C[\"error\"])\n        self._set_status(f\"Disabled {disabled}/{len(targets)} tasks\", C[\"success\"])\n        self._scan_tasks()\n\n    def _enable_task(self):\n        visible = self._get_visible_task_rows()\n        for iid in self.task_tree.selection():\n            idx = self.task_tree.index(iid)\n            if idx &gt;= len(visible): continue\n            meta = visible[idx][2]\n            self._run_cmd(f'schtasks /Change /TN \"{meta[\"full\"]}\" /Enable')\n            self._append_log(self.task_action_log, f\"\u2705 Enabled: {meta['name']}\", C[\"success\"])\n        self._scan_tasks()\n\n    def _task_delete_safe(self):\n        sel = self.task_tree.selection()\n        if not sel:\n            messagebox.showinfo(\"No Selection\",\"Pehle task select karo.\")\n            return\n        visible = self._get_visible_task_rows()\n        block, targets = [], []\n        for iid in sel:\n            idx = self.task_tree.index(iid)\n            if idx &gt;= len(visible): continue\n            meta = visible[idx][2]\n            if meta[\"cat\"] == \"danger\":\n                block.append(f\"  \ud83d\udd34 {meta['name']}\")\n            else:\n                targets.append(meta)\n        if block:\n            messagebox.showerror(\"\u26d4 KHATARNAK!\",\n                \"Ye tasks DELETE NAHI karne chahiye:\\n\\n\" + \"\\n\".join(block))\n            return\n        if not targets:\n            return\n        if not messagebox.askyesno(\"Confirm DELETE\",\n                f\"Permanently delete {len(targets)} tasks?\\n\"\n                \"\u26a0\ufe0f Delete ke baad wapas nahi aayenge!\\n\\n\"\n                \"Pehle Backup Tasks karo.\"):\n            return\n        for meta in targets:\n            self._run_cmd(f'schtasks /Delete /TN \"{meta[\"full\"]}\" /F')\n            self._append_log(self.task_action_log, f\"\ud83d\uddd1 Deleted: {meta['name']}\", C[\"warning\"])\n        self._scan_tasks()\n\n    def _disable_task(self):\n        visible = self._get_visible_task_rows()\n        for iid in self.task_tree.selection():\n            idx = self.task_tree.index(iid)\n            if idx &gt;= len(visible): continue\n            meta = visible[idx][2]\n            self._run_cmd(f'schtasks /Change /TN \"{meta[\"full\"]}\" /Disable')\n        self._scan_tasks()\n\n    def _delete_task(self):\n        visible = self._get_visible_task_rows()\n        for iid in self.task_tree.selection():\n            idx = self.task_tree.index(iid)\n            if idx &gt;= len(visible): continue\n            meta = visible[idx][2]\n            self._run_cmd(f'schtasks /Delete /TN \"{meta[\"full\"]}\" /F')\n        self._scan_tasks()\n\n    def _apply_task_preset(self, pack):\n        if not self._task_all_rows:\n            messagebox.showinfo(\"Pehle Scan Karo\",\"Pehle 'Scan All Tasks' click karo.\")\n            return\n        cats   = pack[\"cats\"]\n        desc   = pack[\"desc\"]\n        targets = [r[2] for r in self._task_all_rows if r[2][\"cat\"] in cats and r[2][\"safe\"]]\n        if not targets:\n            messagebox.showinfo(\"Koi Task Nahi\",f\"Is preset ke liye koi task nahi mila.\\nPehle Scan karo.\")\n            return\n        msg = (f\"{desc}\\n\\n\"\n               f\"{len(targets)} tasks disable ho jaayengi:\\n\\n\"\n               + \"\\n\".join(f\"  {self.TASK_CAT_ICON.get(t['cat'],'\u2022')} {t['name']}\"\n                            for t in targets[:20])\n               + (f\"\\n  ...aur {len(targets)-20} aur\" if len(targets)&gt;20 else \"\")\n               + \"\\n\\nAage badhein?\")\n        if not messagebox.askyesno(\"Confirm Preset\", msg):\n            return\n        done = 0\n        for meta in targets:\n            out, rc = self._run_cmd(f'schtasks /Change /TN \"{meta[\"full\"]}\" /Disable')\n            if rc == 0:\n                done += 1\n                self._append_log(self.task_action_log, f\"\u2705 {meta['name']}\", C[\"success\"])\n        messagebox.showinfo(\"Done!\",\n            f\"\u2705 {done}/{len(targets)} tasks disable ho gayi!\\nRestart karo best results ke liye.\")\n        self._scan_tasks()\n\n    def _backup_tasks(self):\n        dest = filedialog.asksaveasfilename(\n            title=\"Save Task Backup Script\",\n            defaultextension=\".bat\",\n            filetypes=[(\"Batch File\",\"*.bat\"),(\"All Files\",\"*.*\")],\n            initialfile=\"task_backup_restore.bat\")\n        if not dest:\n            return\n        lines = [\"@echo off\",\"echo Restoring disabled tasks...\",\"\"]\n        for row, tags, meta in self._task_all_rows:\n            lines.append(f'schtasks /Change /TN \"{meta[\"full\"]}\" /Enable')\n        lines += [\"\",\"echo Done! All tasks re-enabled.\",\"pause\"]\n        try:\n            with open(dest,\"w\") as f:\n                f.write(\"\\n\".join(lines))\n            messagebox.showinfo(\"Backup Saved\",\n                f\"\u2705 Restore script saved to:\\n{dest}\\n\\n\"\n                \"Agar kuch galat ho jaaye, is .bat file ko Run as Administrator se chalao.\")\n        except Exception as e:\n            messagebox.showerror(\"Error\", str(e))\n\n    # ---------- REGISTRY TWEAKS (with confirm) ----------\n    def _build_registry(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udccb Registry Tweaks\", \"Safe performance tweaks\")\n        content = tk.Frame(frame, bg=C[\"bg\"])\n        content.pack(fill=\"both\", expand=True, padx=16, pady=10)\n        content.columnconfigure(0, weight=1)\n        content.columnconfigure(1, weight=2)\n        left = tk.Frame(content, bg=C[\"card\"])\n        left.grid(row=0, column=0, sticky=\"nsew\", padx=(0,6))\n        tk.Label(left, text=\"  Tweaks\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8,4), padx=8)\n        for k, label in [\n            (\"visual_fx\", \"Disable Visual Effects\"),\n            (\"menu_delay\", \"Reduce Menu Delay\"),\n            (\"search_idx\", \"Disable Search Indexing\"),\n            (\"telemetry\", \"Minimize Telemetry\"),\n            (\"ntfs_last\", \"Disable Last Access Timestamp\"),\n            (\"autorun\", \"Disable Autorun\"),\n            (\"shutdown_fast\", \"Fast Shutdown Speed\"),\n            (\"extreme_visual\", \"Extreme Visual Effects Off (Aero, Shadows, Animations)\"),\n        ]:\n            var = tk.BooleanVar(value=True)\n            self.reg_vars[k] = var\n            tk.Checkbutton(left, text=f\"  {label}\", variable=var, font=FONTS[\"body\"], fg=C[\"text\"], bg=C[\"card\"], activebackground=C[\"card\"], selectcolor=C[\"panel\"], bd=0).pack(anchor=\"w\", padx=12, pady=2)\n        btn_row = tk.Frame(left, bg=C[\"card\"])\n        btn_row.pack(fill=\"x\", padx=12, pady=10)\n        self._btn(btn_row, \"\u2705 Apply Selected Tweaks\", C[\"btn\"], self._apply_registry).pack(fill=\"x\", pady=2)\n        self._btn(btn_row, \"\ud83d\udcbe Export Backup\", C[\"btn_chip\"], self._export_registry_backup).pack(fill=\"x\", pady=2)\n        self._btn(btn_row, \"\u267b\ufe0f Import .reg\", C[\"btn_warn\"], self._import_registry_backup).pack(fill=\"x\", pady=2)\n        right = tk.Frame(content, bg=C[\"card\"])\n        right.grid(row=0, column=1, sticky=\"nsew\", padx=(6,0))\n        tk.Label(right, text=\"  Registry Dashboard\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8,4), padx=8)\n        self.reg_progress_var = tk.DoubleVar(value=0.0)\n        self.reg_progress_bar = ttk.Progressbar(right, variable=self.reg_progress_var, maximum=100, mode=\"determinate\")\n        self.reg_progress_bar.pack(fill=\"x\", padx=12, pady=(0,6))\n        self.reg_status_lbl = tk.Label(right, text=\"Ready for registry optimization\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"])\n        self.reg_status_lbl.pack(anchor=\"w\", padx=12, pady=(0,8))\n        metrics = tk.Frame(right, bg=C[\"card\"])\n        metrics.pack(fill=\"x\", padx=12, pady=(0,6))\n        self.reg_keys_changed_var = tk.StringVar(value=\"0\")\n        self.reg_predicted_impact_var = tk.StringVar(value=\"--\")\n        self.reg_confidence_var = tk.StringVar(value=\"--\")\n        for label, var, fg in [\n            (\"Keys Changed\", self.reg_keys_changed_var, C[\"accent4\"]),\n            (\"Impact Score\", self.reg_predicted_impact_var, C[\"success\"]),\n            (\"Confidence\", self.reg_confidence_var, C[\"warning\"]),\n        ]:\n            card = tk.Frame(metrics, bg=C[\"bg\"], padx=8, pady=8)\n            card.pack(side=\"left\", fill=\"x\", expand=True, padx=3)\n            tk.Label(card, text=label, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"]).pack(anchor=\"w\")\n            tk.Label(card, textvariable=var, font=(\"Segoe UI\", 14, \"bold\"), fg=fg, bg=C[\"bg\"]).pack(anchor=\"w\")\n        tk.Label(right, text=\"  Startup Audit\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8,4), padx=8)\n        startup_btn_row = tk.Frame(right, bg=C[\"card\"])\n        startup_btn_row.pack(fill=\"x\", padx=12, pady=(0,6))\n        self._btn(startup_btn_row, \"\ud83d\udd04 Refresh Audit\", C[\"btn_info\"], self._refresh_registry_startup).pack(side=\"left\", padx=(0,4))\n        self._btn(startup_btn_row, \"\ud83d\uddd1 Delete Selected\", C[\"btn_danger\"], self._delete_registry_startup_selected).pack(side=\"left\")\n        self.registry_startup_tree = ttk.Treeview(right, columns=(\"Name\", \"Command\", \"Location\", \"Status\"), show=\"headings\", height=8, style=\"Custom.Treeview\")\n        for col, w in ((\"Name\", 180), (\"Command\", 280), (\"Location\", 160), (\"Status\", 80)):\n            self.registry_startup_tree.heading(col, text=col)\n            self.registry_startup_tree.column(col, width=w, anchor=\"w\")\n        vsb = ttk.Scrollbar(right, orient=\"vertical\", command=self.registry_startup_tree.yview)\n        self.registry_startup_tree.configure(yscrollcommand=vsb.set)\n        self.registry_startup_tree.pack(side=\"left\", fill=\"both\", expand=True, padx=(12, 0), pady=(0,8))\n        vsb.pack(side=\"right\", fill=\"y\", padx=(0, 12), pady=(0,8))\n        self._registry_startup_items = {}\n        self._refresh_registry_startup()\n        tk.Label(right, text=\"  Execution Log\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8,4), padx=8)\n        self.reg_log = self._scrolled_text(right, height=16)\n        self.reg_exec_log = self.reg_log\n        return frame\n\n    def _apply_registry(self):\n        def before():\n            return \"Registry changes will be applied. A restore point can be created.\"\n        self._confirm_and_launch_job(\"Registry Tweaks\", \"This will apply selected registry tweaks to improve performance.\\nIt is recommended to create a restore point first (will ask).\",\n                                      before, \"registry_tweaks\", self._do_registry)\n        # Note: _do_registry contains the actual registry changes and also creates restore point inside it.\n\n    def _export_registry_backup(self):\n        folder = filedialog.askdirectory(title=\"Select folder for registry backup\")\n        if not folder:\n            return\n        keys = [\n            r\"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\VisualEffects\",\n            r\"HKCU\\Control Panel\\Desktop\",\n            r\"HKLM\\SOFTWARE\\Policies\\Microsoft\\Windows\\DataCollection\",\n            r\"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer\",\n            r\"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Multimedia\\SystemProfile\",\n        ]\n        try:\n            paths = []\n            for key in keys:\n                safe_key = re.sub(r'[:\\\\]', '_', key)\n                export_path = os.path.join(folder, f\"Godawari_Registry_Backup_{safe_key}.reg\")\n                out, rc = self._run_cmd(f'reg export \"{key}\" \"{export_path}\" /y', timeout=20)\n                if rc != 0:\n                    raise RuntimeError(out.strip() or f\"reg export failed for {key}\")\n                paths.append(export_path)\n            messagebox.showinfo(\"Saved\", f\"Registry backup files exported to:\\n{folder}\")\n            self._append_log(self.reg_log, f\"\ud83d\udcbe Registry backup exported: {', '.join(paths)}\", C[\"success\"])\n        except Exception as e:\n            messagebox.showerror(\"Export Failed\", str(e))\n            self._append_log(self.reg_log, f\"\u274c Registry backup failed: {e}\", C[\"error\"])\n\n    def _import_registry_backup(self):\n        path = filedialog.askopenfilename(filetypes=[(\"Registry files\", \"*.reg\")], title=\"Open Registry Backup\")\n        if not path:\n            return\n        if not messagebox.askyesno(\"Import Registry Backup\", f\"Import registry file? This may change system settings.\\n{path}\"):\n            return\n        out, rc = self._run_cmd(f'reg import \"{path}\"', timeout=30)\n        if rc == 0:\n            messagebox.showinfo(\"Imported\", \"Registry backup imported successfully. Restart recommended.\")\n            self._append_log(self.reg_log, f\"\u2705 Imported registry backup: {path}\", C[\"success\"])\n        else:\n            messagebox.showerror(\"Import Failed\", out[:1000] or \"Unknown error\")\n            self._append_log(self.reg_log, f\"\u274c Registry import failed: {out[:200]}\", C[\"error\"])\n\n    def _do_registry_legacy(self):\n        v = self.reg_vars\n        if v[\"menu_delay\"].get():\n            self._reg_set(winreg.HKEY_CURRENT_USER, r\"Control Panel\\Desktop\", \"MenuShowDelay\", \"0\", winreg.REG_SZ)\n            self._append_log(self.reg_log, \"\u2705 Menu delay 0ms\", C[\"success\"])\n        if v[\"visual_fx\"].get():\n            self._reg_set(winreg.HKEY_CURRENT_USER, r\"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\VisualEffects\", \"VisualFXSetting\", 2, winreg.REG_DWORD)\n            self._append_log(self.reg_log, \"\u2705 Visual effects disabled\", C[\"success\"])\n        if v[\"search_idx\"].get():\n            self._run_cmd('sc config \"WSearch\" start= disabled')\n            self._run_cmd('sc stop \"WSearch\"')\n            self._append_log(self.reg_log, \"\u2705 Search indexing disabled\", C[\"success\"])\n        if v[\"telemetry\"].get():\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Policies\\Microsoft\\Windows\\DataCollection\", \"AllowTelemetry\", 0, winreg.REG_DWORD)\n            self._append_log(self.reg_log, \"\u2705 Telemetry minimized\", C[\"success\"])\n        if v[\"ntfs_last\"].get():\n            self._run_cmd(\"fsutil behavior set disablelastaccess 1\")\n            self._append_log(self.reg_log, \"\u2705 NTFS timestamp disabled\", C[\"success\"])\n        if v[\"autorun\"].get():\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer\", \"NoDriveTypeAutoRun\", 255, winreg.REG_DWORD)\n            self._append_log(self.reg_log, \"\u2705 Autorun disabled\", C[\"success\"])\n        if v.get(\"extreme_visual\") and v[\"extreme_visual\"].get():\n            self._reg_set(winreg.HKEY_CURRENT_USER, r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\VisualEffects\", \"VisualFXSetting\", 2, winreg.REG_DWORD)\n            try:\n                self._reg_set(winreg.HKEY_CURRENT_USER, r\"Control Panel\\Desktop\", \"UserPreferencesMask\", b'\\x9e\\x3e\\x07\\x80\\x12\\x00\\x00\\x00', winreg.REG_BINARY)\n                self._reg_set(winreg.HKEY_CURRENT_USER, r\"Control Panel\\Desktop\", \"MinAnimate\", \"0\", winreg.REG_SZ)\n            except:\n                pass\n            self._append_log(self.reg_log, \"\u2705 Extreme visual effects disabled (Aero, shadows, animations)\", C[\"success\"])\n        self._append_log(self.reg_log, \"\ud83c\udf89 Tweaks applied! Restart recommended.\", C[\"accent\"])\n\n    # ---------- GROUP POLICY (with confirm) ----------\n    def _build_grouppolicy(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udd12 Group Policy Optimizer\", \"Performance policies\")\n        content = tk.Frame(frame, bg=C[\"bg\"])\n        content.pack(fill=\"both\", expand=True, padx=16, pady=10)\n        content.columnconfigure(0, weight=1)\n        content.columnconfigure(1, weight=2)\n        left = tk.Frame(content, bg=C[\"card\"])\n        left.grid(row=0, column=0, sticky=\"nsew\", padx=(0,6))\n        tk.Label(left, text=\"  Policies\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8,4), padx=8)\n        for k, label in [(\"cortana\",\"Disable Cortana\"), (\"ads\",\"Disable Advertising ID\"), (\"consumer\",\"Disable Consumer Features\"), (\"remote\",\"Disable Remote Assistance\")]:\n            var = tk.BooleanVar(value=True)\n            self.gp_vars[k] = var\n            tk.Checkbutton(left, text=f\"  {label}\", variable=var, font=FONTS[\"body\"], fg=C[\"text\"], bg=C[\"card\"], activebackground=C[\"card\"], selectcolor=C[\"panel\"], bd=0).pack(anchor=\"w\", padx=12, pady=2)\n        profile_options = get_group_policy_profiles()\n        self.gp_profile_hint_var = tk.StringVar(value=profile_options[\"Balanced\"][\"summary\"])\n        tk.Label(left, text=\"Quick presets:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=12, pady=(4, 2))\n        profile_bar = tk.Frame(left, bg=C[\"card\"])\n        profile_bar.pack(fill=\"x\", padx=12, pady=(0, 2))\n        for profile_name in profile_options:\n            self._btn(profile_bar, profile_name, C[\"btn_chip\"], lambda name=profile_name: self._apply_gp_profile(name)).pack(fill=\"x\", pady=1)\n        tk.Label(left, textvariable=self.gp_profile_hint_var, font=FONTS[\"xsmall\"], fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=280, justify=\"left\").pack(anchor=\"w\", padx=12, pady=(0, 8))\n        self._btn(left, \"\u2705 Apply Selected Policies\", C[\"btn\"], self._apply_gp).pack(padx=12, pady=(4, 2), fill=\"x\")\n        self._btn(left, \"\ud83d\udcbe Backup GP\", C[\"btn_chip\"], self._gp_backup).pack(fill=\"x\", padx=12, pady=2)\n        self._btn(left, \"\u267b Restore GP\", C[\"btn_info\"], self._gp_restore).pack(fill=\"x\", padx=12, pady=(2, 10))\n        right = tk.Frame(content, bg=C[\"card\"])\n        right.grid(row=0, column=1, sticky=\"nsew\", padx=(6,0))\n        tk.Label(right, text=\"  Policy Dashboard\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8,4), padx=8)\n        self.gp_progress_var = tk.DoubleVar(value=0.0)\n        self.gp_progress_bar = ttk.Progressbar(right, variable=self.gp_progress_var, maximum=100, mode=\"determinate\")\n        self.gp_progress_bar.pack(fill=\"x\", padx=12, pady=(0,6))\n        self.gp_status_lbl = tk.Label(right, text=\"Ready for group policy optimization\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"])\n        self.gp_status_lbl.pack(anchor=\"w\", padx=12, pady=(0,8))\n        metrics = tk.Frame(right, bg=C[\"card\"])\n        metrics.pack(fill=\"x\", padx=12, pady=(0,6))\n        self.gp_action_count_var = tk.StringVar(value=\"0\")\n        self.gp_policy_score_var = tk.StringVar(value=\"--\")\n        self.gp_restart_risk_var = tk.StringVar(value=\"Low\")\n        for label, var, fg in [\n            (\"Actions\", self.gp_action_count_var, C[\"accent4\"]),\n            (\"Policy Score\", self.gp_policy_score_var, C[\"success\"]),\n            (\"Restart Risk\", self.gp_restart_risk_var, C[\"warning\"]),\n        ]:\n            card = tk.Frame(metrics, bg=C[\"bg\"], padx=8, pady=8)\n            card.pack(side=\"left\", fill=\"x\", expand=True, padx=3)\n            tk.Label(card, text=label, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"]).pack(anchor=\"w\")\n            tk.Label(card, textvariable=var, font=(\"Segoe UI\", 14, \"bold\"), fg=fg, bg=C[\"bg\"]).pack(anchor=\"w\")\n        tk.Label(right, text=\"  Execution Log\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8,4), padx=8)\n        self.gp_log = self._scrolled_text(right, height=16)\n        self.gp_action_log = self.gp_log\n        return frame\n\n    def _gp_backup(self):\n        path = filedialog.asksaveasfilename(defaultextension=\".json\", filetypes=[(\"JSON\",\"*.json\")],\n                                            initialfile=\"gp_backup.json\", title=\"Save GP Backup\")\n        if not path:\n            return\n        try:\n            data = {\n                \"ts\": datetime.datetime.now().isoformat(timespec=\"seconds\"),\n                \"values\": {\n                    \"cortana\": self._reg_get(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Policies\\Microsoft\\Windows\\Windows Search\", \"AllowCortana\"),\n                    \"ads\": self._reg_get(winreg.HKEY_CURRENT_USER, r\"Software\\Microsoft\\Windows\\CurrentVersion\\AdvertisingInfo\", \"Enabled\"),\n                    \"consumer\": self._reg_get(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Policies\\Microsoft\\Windows\\CloudContent\", \"DisableWindowsConsumerFeatures\"),\n                    \"remote\": self._reg_get(winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Control\\Remote Assistance\", \"fAllowToGetHelp\"),\n                },\n                \"gp_vars\": {k: bool(v.get()) for k, v in getattr(self, \"gp_vars\", {}).items()},\n            }\n            with open(path, \"w\", encoding=\"utf-8\") as f:\n                json.dump(data, f, ensure_ascii=False, indent=2, default=str)\n            self._append_log(self.gp_log, f\"\u2705 GP backup saved: {path}\", C[\"success\"])\n            messagebox.showinfo(\"Saved\", f\"\u2705 Backup saved:\\n{path}\")\n        except Exception as e:\n            messagebox.showerror(\"Backup Error\", str(e))\n\n    def _gp_restore(self):\n        path = filedialog.askopenfilename(filetypes=[(\"JSON\",\"*.json\")], title=\"Open GP Backup\")\n        if not path:\n            return\n        if not messagebox.askyesno(\"Restore GP\", \"Backup file se Group Policy values restore karein?\"):\n            return\n        try:\n            with open(path, \"r\", encoding=\"utf-8\") as f:\n                data = json.load(f)\n            vals = (data or {}).get(\"values\", {})\n        except Exception as e:\n            messagebox.showerror(\"Restore Error\", str(e))\n            return\n        results = []\n        try:\n            # Each stored value is tuple: (exists, current, type)\n            def apply_reg(key, hive, reg_path, name, default_val, vtype):\n                triple = vals.get(key)\n                if isinstance(triple, list) and len(triple) == 3:\n                    exists, cur, typ = triple\n                    if exists:\n                        return self._reg_set_checked(hive, reg_path, name, cur, typ, f\"Restore {key}\", self.gp_log)\n                return self._reg_set_checked(hive, reg_path, name, default_val, vtype, f\"Restore {key} default\", self.gp_log)\n            results.append(apply_reg(\"cortana\", winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Policies\\Microsoft\\Windows\\Windows Search\", \"AllowCortana\", 1, winreg.REG_DWORD))\n            results.append(apply_reg(\"ads\", winreg.HKEY_CURRENT_USER, r\"Software\\Microsoft\\Windows\\CurrentVersion\\AdvertisingInfo\", \"Enabled\", 1, winreg.REG_DWORD))\n            results.append(apply_reg(\"consumer\", winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Policies\\Microsoft\\Windows\\CloudContent\", \"DisableWindowsConsumerFeatures\", 0, winreg.REG_DWORD))\n            results.append(apply_reg(\"remote\", winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Control\\Remote Assistance\", \"fAllowToGetHelp\", 1, winreg.REG_DWORD))\n        except Exception as e:\n            self._append_log(self.gp_log, f\"\u26a0 Restore apply failed: {e}\", C[\"warning\"])\n        # Refresh policy\n        out, rc = self._run_cmd(\"gpupdate /force\")\n        results.append({\"state\": \"changed\" if rc == 0 else \"failed\", \"label\": \"Group Policy refresh\", \"error\": out[:300] if rc != 0 else \"\"})\n        summary = self._action_summary(\"GP Restore\", results)\n        self._append_log(self.gp_log, summary[\"message\"], C[\"accent\"])\n        messagebox.showinfo(\"Restore Result\", summary[\"message\"])\n\n    def _apply_gp_profile(self, profile_name):\n        profiles = get_group_policy_profiles()\n        profile = profiles.get(profile_name) or profiles.get(\"Balanced\")\n        for key in self.gp_vars:\n            self.gp_vars[key].set(key in profile[\"keys\"])\n        self.gp_profile_hint_var.set(profile[\"summary\"])\n        self._append_log(self.gp_log, f\"\ud83c\udfaf Group Policy preset applied: {profile_name} \u2014 {profile['summary']}\", C[\"success\"])\n\n    def _apply_gp(self):\n        def before():\n            return \"Group Policy changes will be applied.\"\n        self._confirm_and_launch_job(\"Group Policy Optimizer\", \"Apply selected group policy tweaks?\\nSome may require a restart.\",\n                                      before, \"group_policy_optimize\", self._do_gp)\n\n    def _do_gp_legacy(self):\n        v = self.gp_vars\n        if v[\"cortana\"].get():\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Policies\\Microsoft\\Windows\\Windows Search\", \"AllowCortana\", 0, winreg.REG_DWORD)\n            self._append_log(self.gp_log, \"\u2705 Cortana disabled\", C[\"success\"])\n        if v[\"ads\"].get():\n            self._reg_set(winreg.HKEY_CURRENT_USER, r\"Software\\Microsoft\\Windows\\CurrentVersion\\AdvertisingInfo\", \"Enabled\", 0, winreg.REG_DWORD)\n            self._append_log(self.gp_log, \"\u2705 Ad ID disabled\", C[\"success\"])\n        if v[\"consumer\"].get():\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Policies\\Microsoft\\Windows\\CloudContent\", \"DisableWindowsConsumerFeatures\", 1, winreg.REG_DWORD)\n            self._append_log(self.gp_log, \"\u2705 Consumer features disabled\", C[\"success\"])\n        if v[\"remote\"].get():\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Control\\Remote Assistance\", \"fAllowToGetHelp\", 0, winreg.REG_DWORD)\n            self._append_log(self.gp_log, \"\u2705 Remote Assistance disabled\", C[\"success\"])\n        self._run_cmd(\"gpupdate /force\")\n        self._append_log(self.gp_log, \"\u2705 GP Updated\", C[\"success\"])\n\n    def _do_registry(self):\n        v = self.reg_vars\n        selected_actions = [name for name, var in v.items() if var.get()]\n        total_actions = max(1, len(selected_actions))\n        batch = {\n            \"phase\": \"registry\",\n            \"status_text\": \"Initializing registry optimization...\",\n            \"progress_pct\": 0.0,\n            \"actions_total\": total_actions,\n            \"actions_done\": 0,\n            \"keys_changed\": 0,\n            \"errors\": 0,\n            \"predicted_impact\": min(95, 15 + total_actions * 12),\n            \"confidence_score\": min(98, max(30, 20 + total_actions * 10)),\n        }\n        last_dispatch = time.time()\n\n        def dispatch_metrics():\n            nonlocal last_dispatch\n            try:\n                batch[\"progress_pct\"] = min(100.0, (batch[\"actions_done\"] / batch[\"actions_total\"]) * 100.0)\n                batch[\"status_text\"] = f\"Applying registry tweaks ({batch['actions_done']}/{batch['actions_total']})\"\n                self._registry_gp_metrics_queue.put(batch.copy())\n            except Exception:\n                pass\n            last_dispatch = time.time()\n\n        def track(result):\n            try:\n                batch[\"actions_done\"] += 1\n                if isinstance(result, dict) and result.get(\"state\") == \"changed\":\n                    batch[\"keys_changed\"] += 1\n                if isinstance(result, dict) and result.get(\"state\") == \"failed\":\n                    batch[\"errors\"] += 1\n                if time.time() - last_dispatch &gt;= 0.12:\n                    dispatch_metrics()\n            except Exception:\n                pass\n            return result\n\n        results = []\n        try:\n            if v[\"menu_delay\"].get():\n                results.append(track(self._reg_set_checked(winreg.HKEY_CURRENT_USER, r\"Control Panel\\Desktop\", \"MenuShowDelay\", \"0\", winreg.REG_SZ, \"Menu delay 0ms\", self.reg_log)))\n            if v[\"visual_fx\"].get():\n                results.append(track(self._reg_set_checked(winreg.HKEY_CURRENT_USER, r\"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\VisualEffects\", \"VisualFXSetting\", 2, winreg.REG_DWORD, \"Visual effects disabled\", self.reg_log)))\n            if v[\"search_idx\"].get():\n                results.append(track(self._service_config_checked(\"WSearch\", \"disabled\", \"Search indexing service\", self.reg_log)))\n                results.append(track(self._service_stop_checked(\"WSearch\", \"Search indexing service\", self.reg_log)))\n            if v[\"telemetry\"].get():\n                results.append(track(self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Policies\\Microsoft\\Windows\\DataCollection\", \"AllowTelemetry\", 0, winreg.REG_DWORD, \"Telemetry minimized\", self.reg_log)))\n            if v[\"ntfs_last\"].get():\n                results.append(track(self._fsutil_last_access_checked(self.reg_log)))\n            if v[\"autorun\"].get():\n                results.append(track(self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer\", \"NoDriveTypeAutoRun\", 255, winreg.REG_DWORD, \"Autorun disabled\", self.reg_log)))\n            if v.get(\"shutdown_fast\") and v[\"shutdown_fast\"].get():\n                results.append(track(self._reg_set_checked(winreg.HKEY_CURRENT_USER, r\"Control Panel\\Desktop\", \"AutoEndTasks\", \"1\", winreg.REG_SZ, \"AutoEndTasks enabled\", self.reg_log)))\n                results.append(track(self._reg_set_checked(winreg.HKEY_CURRENT_USER, r\"Control Panel\\Desktop\", \"HungAppTimeout\", \"2000\", winreg.REG_SZ, \"HungAppTimeout 2s\", self.reg_log)))\n                results.append(track(self._reg_set_checked(winreg.HKEY_CURRENT_USER, r\"Control Panel\\Desktop\", \"WaitToKillAppTimeout\", \"2000\", winreg.REG_SZ, \"WaitToKillAppTimeout 2s\", self.reg_log)))\n                results.append(track(self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Control\", \"WaitToKillServiceTimeout\", \"2000\", winreg.REG_SZ, \"WaitToKillServiceTimeout 2s\", self.reg_log)))\n            if v.get(\"extreme_visual\") and v[\"extreme_visual\"].get():\n                results.append(track(self._reg_set_checked(winreg.HKEY_CURRENT_USER, r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\VisualEffects\", \"VisualFXSetting\", 2, winreg.REG_DWORD, \"Extreme visual effects base\", self.reg_log)))\n                results.append(track(self._reg_set_checked(winreg.HKEY_CURRENT_USER, r\"Control Panel\\Desktop\", \"UserPreferencesMask\", b'\\x9e\\x3e\\x07\\x80\\x12\\x00\\x00\\x00', winreg.REG_BINARY, \"Extreme visual effects mask\", self.reg_log)))\n                results.append(track(self._reg_set_checked(winreg.HKEY_CURRENT_USER, r\"Control Panel\\Desktop\", \"MinAnimate\", \"0\", winreg.REG_SZ, \"Window animation off\", self.reg_log)))\n        except Exception as e:\n            self._append_log(self.reg_log, f\"\u26a0 Registry optimization failed: {e}\", C[\"error\"])\n            batch[\"errors\"] += 1\n        dispatch_metrics()\n        try:\n            summary = self._action_summary(\"Registry Tweaks\", results)\n            self._append_log(self.reg_log, summary[\"message\"], C[\"accent\"])\n        except Exception as e:\n            self._append_log(self.reg_log, f\"\u26a0 Registry summary failed: {e}\", C[\"error\"])\n            summary = {\"message\": \"Registry completed with issues.\"}\n        batch[\"status_text\"] = \"Registry optimization complete\"\n        batch[\"progress_pct\"] = 100.0\n        batch[\"confidence_score\"] = min(100, batch[\"confidence_score\"] + (batch[\"actions_done\"] * 2))\n        self._registry_gp_metrics_queue.put(batch.copy())\n        return summary\n\n    def _do_gp(self):\n        v = self.gp_vars\n        selected_actions = [name for name, var in v.items() if var.get()]\n        total_actions = max(1, len(selected_actions))\n        batch = {\n            \"phase\": \"grouppolicy\",\n            \"status_text\": \"Initializing group policy optimizer...\",\n            \"progress_pct\": 0.0,\n            \"actions_total\": total_actions,\n            \"actions_done\": 0,\n            \"policy_score\": min(90, 10 + total_actions * 18),\n            \"restart_risk\": \"Low\",\n            \"errors\": 0,\n        }\n        last_dispatch = time.time()\n\n        def dispatch_metrics():\n            nonlocal last_dispatch\n            try:\n                batch[\"progress_pct\"] = min(100.0, (batch[\"actions_done\"] / batch[\"actions_total\"]) * 100.0)\n                batch[\"status_text\"] = f\"Applying group policy ({batch['actions_done']}/{batch['actions_total']})\"\n                self._registry_gp_metrics_queue.put(batch.copy())\n            except Exception:\n                pass\n            last_dispatch = time.time()\n\n        def track(result):\n            try:\n                batch[\"actions_done\"] += 1\n                if isinstance(result, dict) and result.get(\"state\") == \"changed\":\n                    batch[\"policy_score\"] = min(100, batch[\"policy_score\"] + 8)\n                if isinstance(result, dict) and result.get(\"state\") == \"failed\":\n                    batch[\"errors\"] += 1\n                    batch[\"restart_risk\"] = \"Medium\"\n                if time.time() - last_dispatch &gt;= 0.12:\n                    dispatch_metrics()\n            except Exception:\n                pass\n            return result\n\n        results = []\n        try:\n            if v[\"cortana\"].get():\n                results.append(track(self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Policies\\Microsoft\\Windows\\Windows Search\", \"AllowCortana\", 0, winreg.REG_DWORD, \"Cortana disabled\", self.gp_log)))\n            if v[\"ads\"].get():\n                results.append(track(self._reg_set_checked(winreg.HKEY_CURRENT_USER, r\"Software\\Microsoft\\Windows\\CurrentVersion\\AdvertisingInfo\", \"Enabled\", 0, winreg.REG_DWORD, \"Advertising ID disabled\", self.gp_log)))\n            if v[\"consumer\"].get():\n                results.append(track(self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Policies\\Microsoft\\Windows\\CloudContent\", \"DisableWindowsConsumerFeatures\", 1, winreg.REG_DWORD, \"Consumer features disabled\", self.gp_log)))\n            if v[\"remote\"].get():\n                results.append(track(self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Control\\Remote Assistance\", \"fAllowToGetHelp\", 0, winreg.REG_DWORD, \"Remote Assistance disabled\", self.gp_log)))\n            if any(r.get(\"state\") == \"changed\" for r in results):\n                out, rc = self._run_cmd(\"gpupdate /force\")\n                results.append(track({\"state\": \"changed\" if rc == 0 else \"failed\", \"label\": \"Group Policy refresh\", \"error\": out[:300] if rc != 0 else \"\"}))\n                self._append_log(self.gp_log, \"GP Updated\" if rc == 0 else f\"GP update failed: {out[:120]}\", C[\"success\"] if rc == 0 else C[\"error\"])\n                if rc != 0:\n                    batch[\"restart_risk\"] = \"High\"\n            else:\n                self._append_log(self.gp_log, \"Already done: GP update skipped\", C[\"warning\"])\n        except Exception as e:\n            self._append_log(self.gp_log, f\"\u26a0 Group Policy optimization failed: {e}\", C[\"error\"])\n            batch[\"errors\"] += 1\n            batch[\"restart_risk\"] = \"Medium\"\n        dispatch_metrics()\n        try:\n            summary = self._action_summary(\"Group Policy\", results)\n            self._append_log(self.gp_log, summary[\"message\"], C[\"accent\"])\n        except Exception as e:\n            self._append_log(self.gp_log, f\"\u26a0 Group Policy summary failed: {e}\", C[\"error\"])\n            summary = {\"message\": \"Group Policy completed with issues.\"}\n        batch[\"status_text\"] = \"Group Policy optimizer complete\"\n        batch[\"progress_pct\"] = 100.0\n        self._registry_gp_metrics_queue.put(batch.copy())\n        return summary\n\n    # ---------- NETWORK OPTIMIZER (with confirm) ----------\n    def _build_network(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"Network Optimizer\", \"TCP/IP, DNS, cache and bandwidth repair\")\n        self.network_health_status = tk.Label(\n            frame,\n            text=\"Connectivity status: idle\",\n            font=FONTS[\"small\"],\n            fg=C[\"text_dim\"],\n            bg=C[\"bg\"],\n            anchor=\"w\",\n        )\n        self.network_health_status.pack(fill=\"x\", padx=16, pady=(0, 4))\n        body = self._scrollable_section_body(frame)\n        self._action_card_grid(body, [\n            (\"TCP\", \"TCP Optimizations\",          \"TCP/IP tweaks apply karo\",            C[\"btn_info\"],   self._apply_tcp),\n            (\"DNS\", \"Flush DNS\",                  \"DNS cache saaf karo\",                 C[\"btn\"],        self._flush_dns),\n            (\"RST\", \"Reset TCP/IP\",               \"TCP/IP stack reset karo\",             C[\"btn_warn\"],   self._reset_tcpip),\n            (\"CLR\", \"Browser/Office Cache Clear\", \"Browser aur Office cache delete karo\",C[\"btn_danger\"], self._browser_office_cache_clear),\n            (\"NET\", \"Disable Net Throttling\",     \"Network speed limit hatao\",           C[\"btn_chip\"],   self._disable_network_throttling),\n            (\"P2P\", \"Disable Delivery Optim.\",    \"Windows Update bandwidth free karo\",  C[\"btn_warn\"],   self._disable_delivery_optimization),\n            (\"DNS+\", \"Optimize DNS\",              \"Cloudflare + Google DNS lagao\",       C[\"btn_info\"],   self._optimize_dns),\n            (\"ADPT\", \"Adapter-wise DNS\",          \"WiFi / Ethernet DNS alag set karo\",   C[\"btn_info\"],   self._dns_by_adapter_dialog),\n            (\"PING\", \"Ping Internet\",             \"Ping Cloudflare for latency\",        C[\"btn_chip\"],   self._network_ping_test),\n            (\"CHK\", \"Connectivity Audit\",         \"Ping + adapter summary report\",       C[\"btn_chip\"],   self._run_network_health_check),\n            (\"SPD\", \"Speedtest Hook\",             \"Run configured speedtest command\",   C[\"btn_info\"],   self._run_speedtest_hook),\n            (\"SAV\", \"Save Last Audit\",            \"Save latest audit as text\",           C[\"btn\"],        self._export_last_network_audit),\n            (\"RPT\", \"Export Net Report\",          \"Save network config + route report\",  C[\"btn\"],        self._export_network_report),\n        ], cols=4)\n        content = tk.Frame(body, bg=C[\"card\"])\n        content.pack(fill=\"both\", expand=True, padx=16, pady=(8, 12))\n        tk.Label(content, text=\"  Network log\", font=FONTS[\"subhead\"],\n                 fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8, 4), padx=8)\n        self.network_log = self._scrolled_text(content, height=14)\n        return frame\n\n    def _dns_by_adapter_dialog(self):\n        # Best-effort: list adapters and ask for adapter name\n        out, rc = self._run_cmd('powershell -Command \"Get-NetAdapter | Where-Object {$_.Status -eq \\'Up\\'} | Select-Object -ExpandProperty Name\"', timeout=10)\n        adapters = [a.strip() for a in out.splitlines() if a.strip()] if rc == 0 else []\n        if not adapters:\n            messagebox.showwarning(\"Adapters\", \"No active adapters found (or PowerShell blocked).\")\n            return\n        try:\n            import tkinter.simpledialog as simpledialog\n            choice = simpledialog.askstring(\"Adapter Name\",\n                                            \"Active adapters:\\n\" + \"\\n\".join(adapters[:10]) +\n                                            (\"\\n...\" if len(adapters) &gt; 10 else \"\") +\n                                            \"\\n\\nType exact adapter name (Wi-Fi/Ethernet):\")\n        except Exception:\n            choice = None\n        if not choice:\n            return\n        adapter = choice.strip()\n        if not adapter:\n            return\n        if not messagebox.askyesno(\"Set DNS\",\n                                   f\"Adapter: {adapter}\\nDNS: 1.1.1.1 + 8.8.8.8\\n\\nApply?\"):\n            return\n        # Use PowerShell for reliable adapter name handling\n        cmd = (\n            'powershell -Command \"'\n            f'Set-DnsClientServerAddress -InterfaceAlias \\'{adapter}\\' -ServerAddresses (\\'1.1.1.1\\',\\'8.8.8.8\\')\"'\n        )\n        out2, rc2 = self._run_cmd(cmd, timeout=20)\n        if rc2 == 0:\n            self._append_log(self.network_log, f\"\u2705 DNS applied on '{adapter}'\", C[\"success\"])\n        else:\n            self._append_log(self.network_log, f\"\u274c DNS set failed: {out2[:200]}\", C[\"error\"])\n\n    def _run_speedtest_hook(self):\n        \"\"\"\n        Optional hook: set env var GODAWARI_SPEEDTEST_CMD to a command that prints results.\n        Example: setx GODAWARI_SPEEDTEST_CMD \"speedtest --accept-license --accept-gdpr\"\n        \"\"\"\n        cmd = os.environ.get(\"GODAWARI_SPEEDTEST_CMD\", \"\").strip()\n        if not cmd:\n            messagebox.showinfo(\"Speedtest Hook\",\n                                \"Speedtest hook set nahi hai.\\n\\n\"\n                                \"Env var set karo:\\n\"\n                                \"GODAWARI_SPEEDTEST_CMD = \\n\\n\"\n                                \"Example:\\n\"\n                                \"speedtest --accept-license --accept-gdpr\")\n            return\n        self._append_log(self.network_log, f\"\u23f1 Speedtest running: {cmd}\", C[\"accent4\"])\n        out, rc = self._run_cmd(cmd, timeout=120)\n        if rc == 0:\n            self._append_log(self.network_log, out[:1200] if out else \"\u2705 Speedtest done\", C[\"success\"])\n        else:\n            self._append_log(self.network_log, f\"\u274c Speedtest failed (rc={rc}): {out[:300]}\", C[\"error\"])\n\n    def _apply_tcp(self):\n        if messagebox.askyesno(\"TCP Optimizations\", \"Apply TCP tuning for better network performance?\"):\n            for cmd in ['netsh int tcp set global autotuninglevel=normal', 'netsh int tcp set global rss=enabled']:\n                self._run_cmd(cmd)\n            self._append_log(self.network_log, \"\u2705 TCP optimizations applied\", C[\"success\"])\n\n    def _flush_dns(self):\n        if messagebox.askyesno(\"Flush DNS\", \"Flush DNS cache? This can resolve connectivity issues.\"):\n            self._run_cmd('ipconfig /flushdns')\n            self._append_log(self.network_log, \"\u2705 DNS flushed\", C[\"success\"])\n\n    def _reset_tcpip(self):\n        if messagebox.askyesno(\"Reset TCP/IP\", \"This will reset Winsock and TCP/IP stack. A restart will be needed.\"):\n            self._run_cmd('netsh int ip reset')\n            self._append_log(self.network_log, \"\u2705 TCP/IP reset. Restart required.\", C[\"warning\"])\n\n    def _browser_office_cache_clear(self):\n        if messagebox.askyesno(\"Clear Browser/Office Cache\", \"Clear caches for Chrome, Edge, and Office?\\nBrowsers will be closed.\"):\n            self._launch_job(\"browser_clear\", self._do_browser_clear)\n\n    def _do_browser_clear(self):\n        for exe in [\"chrome\",\"msedge\",\"firefox\"]:\n            self._run_cmd(f'taskkill /IM {exe}.exe /F')\n        total = 0\n        local = os.environ.get(\"LOCALAPPDATA\",\"\")\n        for p in [os.path.join(local,\"Google\\\\Chrome\\\\User Data\\\\Default\\\\Cache\"),\n                  os.path.join(local,\"Microsoft\\\\Edge\\\\User Data\\\\Default\\\\Cache\"),\n                  os.path.join(local,\"Microsoft\\\\Office\\\\16.0\\\\OfficeFileCache\")]:\n            if os.path.exists(p):\n                total += self._delete_folder_contents(p)\n        self._append_log(self.network_log, f\"\u2705 Cleared {self._fmt_size(total)} cache\", C[\"success\"])\n\n    def _disable_network_throttling(self):\n        if messagebox.askyesno(\"Disable Network Throttling\", \"This can improve network throughput for multimedia apps.\"):\n            result = self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Multimedia\\SystemProfile\", \"NetworkThrottlingIndex\", 0xffffffff, winreg.REG_DWORD, \"Network throttling disabled\", self.network_log)\n            if result[\"state\"] == \"already\":\n                messagebox.showinfo(\"Already Done\", \"Network throttling already disabled.\")\n\n    def _disable_delivery_optimization(self):\n        if messagebox.askyesno(\"Disable Delivery Optimization\", \"Disable Windows Update P2P sharing? Saves bandwidth.\"):\n            results = [\n                self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\DeliveryOptimization\\Config\", \"DODownloadMode\", 0, winreg.REG_DWORD, \"Delivery Optimization P2P off\", self.network_log),\n                self._service_stop_checked(\"DoSvc\", \"Delivery Optimization service\", self.network_log),\n                self._service_config_checked(\"DoSvc\", \"disabled\", \"Delivery Optimization service\", self.network_log),\n            ]\n            summary = self._action_summary(\"Delivery Optimization\", results)\n            if summary[\"already_done\"]:\n                messagebox.showinfo(\"Already Done\", \"Delivery Optimization already disabled.\")\n\n    def _network_ping_test(self):\n        if not messagebox.askyesno(\"Ping Test\", \"Ping 1.1.1.1 and 8.8.8.8 to check internet latency?\"):\n            return\n        targets = [\"1.1.1.1\", \"8.8.8.8\"]\n        for target in targets:\n            out, rc = self._run_cmd(f\"ping -n 4 {target}\", timeout=20)\n            if rc == 0:\n                self._append_log(self.network_log, f\"\u2705 Ping {target} OK:\\n{out.strip()[:400]}\", C[\"success\"])\n            else:\n                self._append_log(self.network_log, f\"\u274c Ping {target} failed (rc={rc}): {out.strip()[:400]}\", C[\"error\"])\n        self._set_status(\"Ping test complete\", C[\"success\"])\n\n    def _export_network_report(self):\n        path = filedialog.asksaveasfilename(defaultextension=\".txt\",\n                                            filetypes=[(\"Text files\",\"*.txt\")],\n                                            initialfile=\"Network_Report.txt\",\n                                            title=\"Save Network Report\")\n        if not path:\n            return\n        report = []\n        for cmd, label in [\n            (\"ipconfig /all\", \"IP Configuration\"),\n            (\"route print\", \"Route Table\"),\n            (\"netsh interface ipv4 show config\", \"IPv4 Adapter Config\"),\n            (\"netsh interface ipv6 show config\", \"IPv6 Adapter Config\"),\n            (\"netsh interface show interface\", \"Interface Status\"),\n        ]:\n            out, rc = self._run_cmd(cmd, timeout=30)\n            report.append(f\"=== {label} ===\\n\")\n            report.append(out if out else f\"[command failed rc={rc}]\\n\")\n        try:\n            with open(path, \"w\", encoding=\"utf-8\") as f:\n                f.write(\"\\n\".join(report))\n            messagebox.showinfo(\"Saved\", f\"Network report saved to:\\n{path}\")\n            self._append_log(self.network_log, f\"\ud83d\udcbe Network report saved: {path}\", C[\"success\"])\n        except Exception as e:\n            messagebox.showerror(\"Error\", str(e))\n            self._append_log(self.network_log, f\"\u274c Report save failed: {e}\", C[\"error\"])\n\n    def _run_network_health_check(self):\n        if not messagebox.askyesno(\"Connectivity Audit\", \"Run a quick ping + adapter audit now?\"):\n            return\n        self.network_health_status.config(text=\"Connectivity status: running audit\", fg=C[\"accent4\"])\n        self._append_log(self.network_log, \"\ud83d\udd0d Running connectivity audit...\", C[\"accent4\"])\n\n        ping_out, ping_rc = self._run_cmd(\"ping -n 2 1.1.1.1\", timeout=20)\n        ip_out, ip_rc = self._run_cmd(\"ipconfig /all\", timeout=20)\n        route_out, route_rc = self._run_cmd(\"route print\", timeout=20)\n\n        summary_lines = [\n            f\"Ping 1.1.1.1: {'OK' if ping_rc == 0 else 'FAIL'}\",\n            f\"ipconfig /all: {'OK' if ip_rc == 0 else 'FAIL'}\",\n            f\"route print: {'OK' if route_rc == 0 else 'FAIL'}\",\n        ]\n        if ping_rc == 0:\n            self._append_log(self.network_log, f\"\u2705 Ping check passed\\n{ping_out[:300]}\", C[\"success\"])\n        else:\n            self._append_log(self.network_log, f\"\u274c Ping check failed\\n{ping_out[:300]}\", C[\"error\"])\n\n        adapter_lines = [line for line in ip_out.splitlines() if \"DNS Servers\" in line or \"IPv4 Address\" in line or \"Description\" in line or \"Physical Address\" in line]\n        if adapter_lines:\n            self._append_log(self.network_log, \"\ud83d\udce1 Adapter summary:\\n\" + \"\\n\".join(adapter_lines[:20]), C[\"text\"])\n        else:\n            self._append_log(self.network_log, \"\ud83d\udce1 No adapter details captured from ipconfig output.\", C[\"warning\"])\n\n        self._append_log(self.network_log, \"\ud83d\udee3 Route summary:\\n\" + (route_out[:700] if route_out else \"route print unavailable\"), C[\"text\"])\n        self._append_log(self.network_log, \"\u2705 Connectivity audit complete. \" + \" | \".join(summary_lines), C[\"success\"])\n\n        self._last_network_audit = {\n            \"timestamp\": datetime.datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\"),\n            \"ping_rc\": ping_rc,\n            \"ip_rc\": ip_rc,\n            \"route_rc\": route_rc,\n            \"ping_output\": ping_out,\n            \"ip_output\": ip_out,\n            \"route_output\": route_out,\n        }\n        self.network_health_status.config(\n            text=f\"Connectivity status: audit complete at {self._last_network_audit['timestamp']}\",\n            fg=C[\"success\"],\n        )\n        self._set_status(\"Connectivity audit complete\", C[\"success\"])\n\n    def _export_last_network_audit(self):\n        audit = getattr(self, \"_last_network_audit\", None)\n        if not audit:\n            messagebox.showinfo(\"No Audit\", \"Pehle Connectivity Audit run karo.\")\n            return\n        path = filedialog.asksaveasfilename(\n            defaultextension=\".txt\",\n            filetypes=[(\"Text files\", \"*.txt\")],\n            initialfile=f\"Network_Audit_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.txt\",\n            title=\"Save Last Network Audit\",\n        )\n        if not path:\n            return\n        try:\n            lines = [\n                f\"Godawari Network Audit\",\n                f\"Timestamp: {audit['timestamp']}\",\n                f\"Ping rc: {audit['ping_rc']}\",\n                f\"ipconfig rc: {audit['ip_rc']}\",\n                f\"route print rc: {audit['route_rc']}\",\n                \"\",\n                \"--- Ping Output ---\",\n                audit.get(\"ping_output\", \"\"),\n                \"\",\n                \"--- ipconfig Output ---\",\n                audit.get(\"ip_output\", \"\"),\n                \"\",\n                \"--- route print Output ---\",\n                audit.get(\"route_output\", \"\"),\n            ]\n            with open(path, \"w\", encoding=\"utf-8\") as fh:\n                fh.write(\"\\n\".join(lines))\n            self._append_log(self.network_log, f\"\ud83d\udcbe Saved last audit: {path}\", C[\"success\"])\n            messagebox.showinfo(\"Saved\", f\"Last network audit saved to:\\n{path}\")\n        except Exception as e:\n            messagebox.showerror(\"Save Failed\", str(e))\n            self._append_log(self.network_log, f\"\u274c Failed to save audit: {e}\", C[\"error\"])\n\n    def _optimize_dns(self):\n        if messagebox.askyesno(\"Optimize DNS\", \"Set DNS to Cloudflare (1.1.1.1) and Google (8.8.8.8) for faster browsing?\"):\n            out, _ = self._run_cmd('wmic nic where \"NetEnabled=True\" get Index /format:csv')\n            lines = out.splitlines()\n            for line in lines[1:]:\n                if line.strip():\n                    idx = line.split(',')[1].strip()\n                    self._run_cmd(f'netsh interface ip set dns name={idx} static 1.1.1.1 primary')\n                    self._run_cmd(f'netsh interface ip add dns name={idx} 8.8.8.8 index=2')\n            self._append_log(self.network_log, \"\u2705 DNS set to Cloudflare (1.1.1.1) and Google (8.8.8.8)\", C[\"success\"])\n\n    # ---------- TROUBLESHOOTER &amp; POWER PLAN (shortened for length) ----------\n    # I'll include the essential parts. The rest methods are similar structure.\n\n    def _build_troubleshooter(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"System Repair\", \"Guided SFC, DISM, network, crash and driver diagnostics\")\n        body = self._scrollable_section_body(frame)\n\n        guide = tk.Frame(body, bg=C[\"card\"], highlightbackground=C[\"accent2\"], highlightthickness=1)\n        guide.pack(fill=\"x\", padx=16, pady=(10, 6))\n        tk.Label(guide, text=\"Recommended flow\", font=FONTS[\"subhead\"],\n                 fg=C[\"accent2\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=12, pady=(8, 2))\n        tk.Label(\n            guide,\n            text=\"Start with Repair Verification or Network Reset. Use advanced crash, boot, driver and security reports when the basic repair does not explain the issue.\",\n            font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], anchor=\"w\",\n            justify=\"left\", wraplength=self._dpi_px(980)\n        ).pack(fill=\"x\", padx=12, pady=(0, 8))\n\n        self._action_card_grid(body, [\n            (\"NET\", \"Network Reset\",            \"TCP/IP, Winsock and DNS reset\",       C[\"btn_info\"],   self._full_network_reset),\n            (\"SFC\", \"SFC /SCANNOW\",             \"System files scan and repair\",        C[\"btn\"],        self._run_sfc),\n            (\"DISM\", \"DISM RestoreHealth\",      \"Windows image repair\",                C[\"btn_warn\"],   self._run_dism),\n            (\"ALL\", \"Run All Repairs\",          \"Restore point, DISM, SFC and network\",C[\"accent4\"],    self._run_all_repairs),\n            (\"BSOD\", \"BSoD Deep Diagnose\",      \"Stop code, WHEA, driver and dump check\", C[\"accent3\"], self._bsod_deep_diagnose),\n            (\"DMP\", \"Enable Minidump\",          \"Capture future crash proof logs\",     C[\"btn_chip\"],   self._enable_bsod_minidump),\n            (\"DLL\", \"Kernel32/Rundll32 Check\",  \"WER, startup and DLL crash diagnose\", C[\"btn_info\"],   self._rundll32_error_diagnose),\n            (\"DBG\", \"WinDbg Dump Analyze\",      \"Minidump !analyze automation\",        C[\"accent4\"],    self._windbg_dump_analyze),\n            (\"EVT\", \"Event Correlation\",        \"Crash timeline root-cause summary\",   C[\"btn\"],        self._event_correlation_report),\n            (\"DRV\", \"Driver Diagnostics\",       \"Unsigned, recent and outdated drivers\", C[\"btn_warn\"], self._driver_diagnostics_report),\n            (\"HW\", \"Hardware Health\",           \"SMART, NVMe and RAM warning report\",  C[\"hw_accent\"],  self._hardware_health_report),\n            (\"CHK\", \"Repair Verification\",      \"SFC, DISM and event re-check report\", C[\"accent2\"],    self._repair_verification_report),\n            (\"BOOT\", \"Boot Status + BCD\",       \"EFI/BCD analysis and backup\",         C[\"btn_chip\"],   self._boot_status_bcd_backup),\n            (\"OFF\", \"Offline SFC/DISM\",         \"Mounted Windows repair commands\",     C[\"btn_info\"],   self._offline_repair_dialog),\n            (\"SEC\", \"Security Autoruns\",        \"AppInit, hosts and startup risk scan\", C[\"btn_warn\"],  self._security_startup_report),\n            (\"ZIP\", \"Diagnostic ZIP\",           \"HTML, JSON and TXT package export\",   C[\"accent\"],     self._diagnostic_zip_package),\n            (\"WU\", \"Disable Windows Update\",    \"Advanced blocker with warning\",       C[\"btn_danger\"], self._disable_windows_update),\n            (\"STOP\", \"Stop Repair\",             \"Stop the running repair command\",     C[\"btn_danger\"], self._stop_repairs),\n            (\"SAVE\", \"Export Repair Report\",    \"Save the current repair log\",         C[\"btn_chip\"],   self._export_repair_report),\n        ], cols=4)\n\n        content = tk.Frame(body, bg=C[\"card\"])\n        content.pack(fill=\"both\", expand=True, padx=16, pady=(8, 12))\n        tk.Label(content, text=\"  Live repair log\", font=FONTS[\"subhead\"],\n                 fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8, 4), padx=8)\n        self.trouble_log = self._scrolled_text(content, height=12)\n        return frame\n\n    def _stop_repairs(self):\n        self._repair_stop_flag = True\n        try:\n            p = getattr(self, \"_repair_proc\", None)\n            if p and p.poll() is None:\n                try:\n                    p.terminate()\n                except Exception:\n                    pass\n        except Exception:\n            pass\n        self._append_log(self.trouble_log, \"\u23f9 Stop requested for running repair command.\", C[\"warning\"])\n        self._set_status(\"Stop requested...\", C[\"warning\"])\n\n    def _export_repair_report(self):\n        path = filedialog.asksaveasfilename(defaultextension=\".txt\", filetypes=[(\"Text\",\"*.txt\")],\n                                            initialfile=\"SystemRepair_Report.txt\",\n                                            title=\"Save Repair Report\")\n        if not path:\n            return\n        try:\n            txt = \"\"\n            try:\n                txt = self.trouble_log.get(\"1.0\", \"end\")\n            except Exception:\n                txt = \"\"\n            with open(path, \"w\", encoding=\"utf-8\") as f:\n                f.write(txt)\n            messagebox.showinfo(\"Saved\", f\"\u2705 Report saved:\\n{path}\")\n        except Exception as e:\n            messagebox.showerror(\"Error\", str(e))\n\n    def _full_network_reset(self):\n        if messagebox.askyesno(\"Network Reset\", \"Reset Winsock and TCP/IP? Restart required.\"):\n            for cmd in ([\"netsh\", \"winsock\", \"reset\"], [\"netsh\", \"int\", \"ip\", \"reset\"], [\"ipconfig\", \"/flushdns\"]):\n                self._run_cmd(cmd)\n            self._append_log(self.trouble_log, \"\u2705 Network reset complete. Restart.\", C[\"success\"])\n\n    def _run_sfc(self):\n        if messagebox.askyesno(\"System File Checker\", \"Run SFC /SCANNOW? This may take a while.\"):\n            self._append_log(self.trouble_log, \"Running SFC...\", C[\"accent\"])\n            self._launch_job(\"sfc_scan\", self._run_cmd_cancelable, [\"sfc\", \"/scannow\"], 1200)\n\n    def _run_dism(self):\n        if messagebox.askyesno(\"DISM\", \"Run DISM RestoreHealth? This may take a while.\"):\n            self._append_log(self.trouble_log, \"Running DISM...\", C[\"accent\"])\n            self._launch_job(\"dism_restorehealth\", self._run_cmd_cancelable, [\"dism\", \"/online\", \"/cleanup-image\", \"/restorehealth\"], 2400)\n\n    def _run_cmd_cancelable(self, cmd, timeout_s=1800):\n        self._repair_stop_flag = False\n        try:\n            self._repair_proc = subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True,\n                                                 encoding=\"utf-8\", errors=\"replace\")\n            start = time.time()\n            out_lines = []\n            for line in self._repair_proc.stdout:\n                out_lines.append(line.rstrip(\"\\n\"))\n                if len(out_lines) % 25 == 0:\n                    tail = \"\\n\".join(out_lines[-10:])\n                    self.after(0, lambda t=tail: self._append_log(self.trouble_log, t, C[\"text_dim\"]))\n                if getattr(self, \"_repair_stop_flag\", False):\n                    try:\n                        self._repair_proc.terminate()\n                    except Exception:\n                        pass\n                    break\n                if timeout_s and (time.time() - start) &gt; timeout_s:\n                    try:\n                        self._repair_proc.terminate()\n                    except Exception:\n                        pass\n                    break\n            try:\n                rc = self._repair_proc.wait(timeout=5)\n            except Exception:\n                rc = -1\n            tail = \"\\n\".join(out_lines[-30:]) if out_lines else \"\"\n            if getattr(self, \"_repair_stop_flag\", False):\n                self.after(0, lambda: self._append_log(self.trouble_log, \"\u23f9 Repair stopped by user.\", C[\"warning\"]))\n                self.after(0, lambda: self._set_status(\"Repair stopped\", C[\"warning\"]))\n            elif timeout_s and (time.time() - start) &gt; timeout_s:\n                self.after(0, lambda: self._append_log(self.trouble_log, \"\u26a0 Repair timed out.\", C[\"warning\"]))\n                self.after(0, lambda: self._set_status(\"Repair timed out\", C[\"warning\"]))\n            else:\n                self.after(0, lambda: self._append_log(self.trouble_log, f\"\u2705 Command done (rc={rc}).\", C[\"success\"]))\n                if tail:\n                    self.after(0, lambda t=tail: self._append_log(self.trouble_log, t, C[\"text\"]))\n                self.after(0, lambda: self._set_status(\"Repair complete\", C[\"success\"]))\n        except Exception as e:\n            self.after(0, lambda: self._append_log(self.trouble_log, f\"\u274c Repair failed: {e}\", C[\"error\"]))\n        finally:\n            self._repair_proc = None\n\n    def _run_all_repairs(self):\n        if self._create_restore_point(\"Full Repair\"):\n            self._launch_job(\"full_repairs\", lambda: (self._run_dism(), self._run_sfc(), self._full_network_reset()))\n\n    def _disable_windows_update_legacy(self):\n        if messagebox.askyesno(\"Windows Update Blocker\", \"Disable Windows Update services? (Not recommended for security, but boosts performance)\"):\n            self._run_cmd('sc config \"wuauserv\" start= disabled')\n            self._run_cmd('sc stop \"wuauserv\"')\n            self._run_cmd('sc config \"UsoSvc\" start= disabled')\n            self._run_cmd('sc stop \"UsoSvc\"')\n            self._append_log(self.trouble_log, \"\u26a0\ufe0f Windows Update services disabled (Reboot required)\", C[\"warning\"])\n\n    def _disable_windows_update(self):\n        if messagebox.askyesno(\"Windows Update Blocker\", \"Disable Windows Update services? (Not recommended for security, but boosts performance)\"):\n            results = [\n                self._service_config_checked(\"wuauserv\", \"disabled\", \"Windows Update\", self.trouble_log),\n                self._service_stop_checked(\"wuauserv\", \"Windows Update\", self.trouble_log),\n                self._service_config_checked(\"UsoSvc\", \"disabled\", \"Update Orchestrator\", self.trouble_log),\n                self._service_stop_checked(\"UsoSvc\", \"Update Orchestrator\", self.trouble_log),\n            ]\n            summary = self._action_summary(\"Windows Update Blocker\", results)\n            self._append_log(self.trouble_log, summary[\"message\"], C[\"warning\"] if summary[\"already_done\"] else C[\"success\"])\n            messagebox.showinfo(\"Already Done\" if summary[\"already_done\"] else \"Done\", summary[\"message\"])\n\n    def _json_items_from_output(self, output):\n        raw = (output or \"\").strip()\n        if not raw:\n            return []\n        starts = [i for i in (raw.find(\"[\"), raw.find(\"{\")) if i &gt;= 0]\n        if starts:\n            raw = raw[min(starts):]\n        ends = [i for i in (raw.rfind(\"]\"), raw.rfind(\"}\")) if i &gt;= 0]\n        if ends:\n            raw = raw[:max(ends) + 1]\n        try:\n            data = json.loads(raw)\n            if isinstance(data, list):\n                return data\n            if isinstance(data, dict):\n                return [data]\n        except Exception:\n            pass\n        return []\n\n    def _crash_control_values(self):\n        names = [\n            \"CrashDumpEnabled\", \"MinidumpDir\", \"DumpFile\", \"LogEvent\",\n            \"AutoReboot\", \"Overwrite\", \"AlwaysKeepMemoryDump\",\n        ]\n        values = {}\n        for name in names:\n            exists, value, _ = self._reg_get(\n                winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\CrashControl\",\n                name\n            )\n            if exists:\n                values[name] = value\n        return values\n\n    def _bsod_dump_files(self):\n        files = []\n        targets = [\n            (r\"C:\\Windows\\Minidump\", \"*.dmp\", False),\n            (r\"C:\\Windows\\LiveKernelReports\", \"*.dmp\", True),\n        ]\n        for folder, pattern, recursive in targets:\n            try:\n                base = Path(folder)\n                if not base.exists():\n                    continue\n                iterator = base.rglob(pattern) if recursive else base.glob(pattern)\n                for path in iterator:\n                    try:\n                        st = path.stat()\n                        files.append({\n                            \"path\": str(path),\n                            \"name\": path.name,\n                            \"size_kb\": int(st.st_size / 1024),\n                            \"mtime\": datetime.datetime.fromtimestamp(st.st_mtime).strftime(\"%Y-%m-%d %H:%M\"),\n                        })\n                    except Exception:\n                        pass\n            except Exception:\n                pass\n        try:\n            memory_dump = Path(r\"C:\\Windows\\MEMORY.DMP\")\n            if memory_dump.exists():\n                st = memory_dump.stat()\n                files.append({\n                    \"path\": str(memory_dump),\n                    \"name\": memory_dump.name,\n                    \"size_kb\": int(st.st_size / 1024),\n                    \"mtime\": datetime.datetime.fromtimestamp(st.st_mtime).strftime(\"%Y-%m-%d %H:%M\"),\n                })\n        except Exception:\n            pass\n        files.sort(key=lambda item: item.get(\"mtime\", \"\"), reverse=True)\n        return files[:12]\n\n    def _bsod_stop_code_details(self, code):\n        try:\n            number = int(str(code).strip(), 16)\n            key = f\"0x{number:08X}\"\n        except Exception:\n            key = str(code).upper()\n        stop_map = {\n            \"0x0000000A\": (\"IRQL_NOT_LESS_OR_EQUAL\", \"Driver ne galat memory address access kiya.\", \"Recent driver rollback/update karo, RAM test chalao, overclock off rakho.\"),\n            \"0x0000001A\": (\"MEMORY_MANAGEMENT\", \"RAM, pagefile, driver memory leak ya memory corruption.\", \"Windows Memory Diagnostic/MemTest run karo, RAM reseat karo, SFC/DISM run karo.\"),\n            \"0x00000024\": (\"NTFS_FILE_SYSTEM\", \"File system, disk, bad sector ya storage driver issue.\", \"Important data backup karo, SMART check aur chkdsk /f /r run karo.\"),\n            \"0x0000003B\": (\"SYSTEM_SERVICE_EXCEPTION\", \"Driver/system service crash, aksar graphics/security software se.\", \"GPU/network/security driver clean reinstall karo, Windows update complete karo.\"),\n            \"0x00000050\": (\"PAGE_FAULT_IN_NONPAGED_AREA\", \"Bad RAM, bad driver, antivirus filter, ya disk/pagefile issue.\", \"RAM test, driver verifier status check, antivirus/storage driver update karo.\"),\n            \"0x0000007B\": (\"INACCESSIBLE_BOOT_DEVICE\", \"Windows boot disk/controller access nahi kar pa raha.\", \"BIOS SATA mode, storage driver, boot files, chkdsk aur startup repair check karo.\"),\n            \"0x0000007E\": (\"SYSTEM_THREAD_EXCEPTION_NOT_HANDLED\", \"Kernel driver exception handle nahi hui.\", \"Latest installed driver identify karke rollback/update karo; Safe Mode se test karo.\"),\n            \"0x0000007F\": (\"UNEXPECTED_KERNEL_MODE_TRAP\", \"CPU/RAM hardware fault, overheating, ya low-level driver issue.\", \"Temperature, RAM, CPU overclock, BIOS/chipset update check karo.\"),\n            \"0x0000009F\": (\"DRIVER_POWER_STATE_FAILURE\", \"Sleep/shutdown/resume me driver power state atak gaya.\", \"Power management, chipset, Wi-Fi, Bluetooth, GPU drivers update/rollback karo.\"),\n            \"0x000000C2\": (\"BAD_POOL_CALLER\", \"Driver ne memory pool galat tarah use kiya.\", \"Recent driver/app uninstall karo, Driver Verifier culprit ke liye use karo.\"),\n            \"0x000000D1\": (\"DRIVER_IRQL_NOT_LESS_OR_EQUAL\", \"Network/storage/GPU driver ne invalid memory access kiya.\", \"Culprit driver update/rollback karo; dump file WinDbg me analyze karo.\"),\n            \"0x000000EA\": (\"THREAD_STUCK_IN_DEVICE_DRIVER\", \"GPU/display driver loop me phans gaya.\", \"GPU driver clean reinstall, GPU temperature/power check, hardware acceleration test karo.\"),\n            \"0x000000ED\": (\"UNMOUNTABLE_BOOT_VOLUME\", \"Boot volume mount nahi hua; file system/disk problem.\", \"WinRE se chkdsk /f /r, boot repair, disk health check karo.\"),\n            \"0x000000EF\": (\"CRITICAL_PROCESS_DIED\", \"Important Windows process crash ho gaya.\", \"SFC/DISM, malware scan, recent update/driver rollback, disk health check karo.\"),\n            \"0x00000109\": (\"CRITICAL_STRUCTURE_CORRUPTION\", \"Kernel structure corrupt; driver, RAM, malware, overclock possible.\", \"Overclock off, RAM test, malware scan, unsigned drivers check karo.\"),\n            \"0x00000116\": (\"VIDEO_TDR_FAILURE\", \"GPU driver/hardware timeout.\", \"Display driver DDU se clean install, GPU temperature/PSU check, hardware acceleration off test karo.\"),\n            \"0x00000117\": (\"VIDEO_TDR_TIMEOUT_DETECTED\", \"GPU driver ne time par response nahi diya.\", \"Graphics driver update/rollback, temperature/power check karo.\"),\n            \"0x00000124\": (\"WHEA_UNCORRECTABLE_ERROR\", \"Hardware error: CPU, RAM, PCIe, GPU, SSD, PSU ya overheating.\", \"Temps, RAM, SMART, BIOS/chipset update, overclock off, hardware stress test karo.\"),\n            \"0x00000133\": (\"DPC_WATCHDOG_VIOLATION\", \"Driver/SSD controller ne response time exceed kiya.\", \"Storage/NVMe/chipset driver update, SSD firmware, external devices remove test karo.\"),\n            \"0x00000139\": (\"KERNEL_SECURITY_CHECK_FAILURE\", \"Driver/memory corruption ya incompatible software.\", \"Recent driver/app rollback, SFC/DISM, RAM test, malware scan karo.\"),\n        }\n        return key, stop_map.get(key, (\"Unknown stop code\", \"Exact cause dump analysis ke bina confirm nahi hota.\", \"Minidump ko WinDbg/WhoCrashed se analyze karo, phir culprit driver fix karo.\"))\n\n    def _collect_bsod_events(self):\n        script = r\"\"\"\n$ids = @(41,1001,161,6008,17,18,19,1,7,11,51,55,129,153,4101,1101,1102,1201,1202)\n$events = @()\ntry {\n    $events = Get-WinEvent -LogName System -MaxEvents 900 -ErrorAction SilentlyContinue |\n        Where-Object {\n            ($ids -contains $_.Id) -or\n            ($_.ProviderName -match 'BugCheck|Kernel-Power|WHEA|Display|Disk|Ntfs|volmgr|storahci|storport|iaStor|MemoryDiagnostics')\n        } |\n        Select-Object -First 35 `\n            @{n='TimeCreated';e={$_.TimeCreated.ToString('s')}},\n            ProviderName,Id,LevelDisplayName,\n            @{n='Message';e={$_.Message}}\n} catch {}\n$events | ConvertTo-Json -Depth 4\n\"\"\"\n        out, _ = self._run_powershell(script, timeout=60)\n        return self._json_items_from_output(out)\n\n    def _collect_recent_third_party_drivers(self):\n        script = r\"\"\"\n$drivers = @()\ntry {\n    $drivers = Get-CimInstance Win32_PnPSignedDriver -ErrorAction SilentlyContinue |\n        Where-Object { $_.DriverProviderName -and $_.DriverProviderName -notmatch '^Microsoft' } |\n        Sort-Object DriverDate -Descending |\n        Select-Object -First 12 DeviceName,DriverProviderName,DriverVersion,DriverDate\n} catch {}\n$drivers | ConvertTo-Json -Depth 4\n\"\"\"\n        out, _ = self._run_powershell(script, timeout=60)\n        return self._json_items_from_output(out)\n\n    def _build_bsod_deep_report(self):\n        dumps = self._bsod_dump_files()\n        crash_values = self._crash_control_values()\n        events = self._collect_bsod_events()\n        drivers = self._collect_recent_third_party_drivers()\n        verifier_out, _ = self._run_cmd(\"verifier /querysettings\", timeout=25)\n        pagefile_out, _ = self._run_cmd(\"wmic pagefileset get Name,InitialSize,MaximumSize /format:list\", timeout=20)\n\n        findings = []\n        solutions = []\n        stop_codes = []\n\n        for ev in events:\n            msg = str(ev.get(\"Message\", \"\") or \"\")\n            src = str(ev.get(\"ProviderName\", \"\") or \"\")\n            eid = str(ev.get(\"Id\", \"\") or \"\")\n            low = f\"{src} {eid} {msg}\".lower()\n\n            if \"bugcheck\" in low or eid == \"1001\":\n                for found in re.findall(r\"0x[0-9a-fA-F]{1,16}\", msg):\n                    key, (name, reason, solution) = self._bsod_stop_code_details(found)\n                    if key not in [x[0] for x in stop_codes]:\n                        stop_codes.append((key, name, reason, solution))\n                if not re.search(r\"0x[0-9a-fA-F]{1,16}\", msg):\n                    findings.append(\"BugCheck event mila, lekin stop code message me clear nahi tha.\")\n\n            if \"kernel-power\" in low and eid == \"41\":\n                findings.append(\"Kernel-Power 41 mila: PC clean shutdown ke bina restart hua.\")\n                solutions.append(\"Power loss/SMPS/overheating/BSOD path check karo. Agar saath me BugCheck code hai to driver/hardware cause follow karo.\")\n            if \"whea\" in low:\n                findings.append(\"WHEA hardware error event mila: CPU/RAM/PCIe/GPU/SSD side hardware warning possible.\")\n                solutions.append(\"Overclock off, temperature check, BIOS/chipset update, RAM test, SSD SMART, GPU/PCIe seating check karo.\")\n            if \"display\" in low or \"tdr\" in low or eid == \"4101\":\n                findings.append(\"Display/GPU driver reset event mila.\")\n                solutions.append(\"GPU driver clean reinstall/rollback, GPU temperature aur PSU power check karo.\")\n            if any(x in low for x in [\"disk\", \"ntfs\", \"storahci\", \"storport\", \"iastor\"]) or eid in {\"7\", \"11\", \"51\", \"55\", \"129\", \"153\"}:\n                findings.append(\"Disk/storage event mila: storage timeout, NTFS corruption ya bad sector possible.\")\n                solutions.append(\"Important data backup, SMART report, cable/port check, chkdsk /f /r, storage/NVMe driver update karo.\")\n            if \"volmgr\" in low and eid == \"161\":\n                findings.append(\"volmgr 161 mila: crash dump create nahi ho paya.\")\n                solutions.append(\"C: drive free space/pagefile/dump settings check karo; system managed pagefile aur minidump enable karo.\")\n            if \"memorydiagnostics\" in low and (\"hardware problems\" in low or \"detected\" in low):\n                findings.append(\"Memory Diagnostic ne memory problem indicate ki.\")\n                solutions.append(\"RAM sticks reseat karo, single-stick test, MemTest86 4-pass, faulty RAM replace karo.\")\n\n        for key, name, reason, solution in stop_codes:\n            findings.append(f\"Stop Code {key} ({name}): {reason}\")\n            solutions.append(solution)\n\n        dump_enabled = int(crash_values.get(\"CrashDumpEnabled\", -1) or -1)\n        if dump_enabled == 0:\n            findings.append(\"Crash dump disabled hai, isliye future BSOD proof file save nahi hogi.\")\n            solutions.append(\"Enable Minidump button run karo: CrashDumpEnabled=3, MinidumpDir set, AutoReboot off.\")\n        elif dump_enabled not in (1, 2, 3, 7):\n            findings.append(\"Crash dump setting unclear hai; dump capture verify karna chahiye.\")\n\n        if str(crash_values.get(\"AutoReboot\", \"\")).strip() == \"1\":\n            solutions.append(\"AutoReboot off rakhna useful hai, warna blue screen turant restart ho jati hai aur user stop code nahi dekh pata.\")\n\n        if verifier_out and \"No settings\" not in verifier_out and \"not currently enabled\" not in verifier_out:\n            findings.append(\"Driver Verifier active lag raha hai; ye intentionally bad drivers ko BSOD kara sakta hai.\")\n            solutions.append(\"Agar PC boot loop me hai to Safe Mode me `verifier /reset` run karke reboot karo.\")\n\n        lines = []\n        lines.append(\"BSoD Deep Troubleshooting Report (Hinglish)\")\n        lines.append(f\"Generated: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\")\n        lines.append(\"\")\n        lines.append(\"Troubleshoot kya kiya:\")\n        lines.append(\"- C:\\\\Windows\\\\Minidump aur LiveKernelReports me dump files check ki.\")\n        lines.append(\"- Event Viewer me BugCheck, Kernel-Power, WHEA, Display, Disk, NTFS, volmgr events check kiye.\")\n        lines.append(\"- Crash dump registry settings, pagefile setting, Driver Verifier status check kiya.\")\n        lines.append(\"- Recent third-party drivers list kiye, kyunki BSOD ka common cause driver hota hai.\")\n        lines.append(\"\")\n        lines.append(\"Dump files:\")\n        if dumps:\n            for item in dumps[:8]:\n                lines.append(f\"- {item['path']} | {item['mtime']} | {item['size_kb']} KB\")\n        else:\n            lines.append(\"- No dump file found. Ya to recent BSOD nahi hua, ya dump setting/pagefile issue hai.\")\n        lines.append(\"\")\n        lines.append(\"Crash dump settings:\")\n        if crash_values:\n            for key in sorted(crash_values):\n                lines.append(f\"- {key}: {crash_values.get(key)}\")\n        else:\n            lines.append(\"- CrashControl registry read nahi hua. Admin rights required ho sakte hain.\")\n        if pagefile_out.strip():\n            lines.append(\"\")\n            lines.append(\"Pagefile:\")\n            lines.append(pagefile_out.strip()[:900])\n        lines.append(\"\")\n        lines.append(\"Result / likely karan:\")\n        if findings:\n            for item in list(dict.fromkeys(findings))[:14]:\n                lines.append(f\"- {item}\")\n        else:\n            lines.append(\"- Strong BSOD root-cause event nahi mila. Agar issue repeat hota hai to minidump enable karke next crash capture karein.\")\n        lines.append(\"\")\n        lines.append(\"Solution:\")\n        if solutions:\n            for item in list(dict.fromkeys(solutions))[:14]:\n                lines.append(f\"- {item}\")\n        else:\n            lines.append(\"- Windows update complete karo, SFC/DISM run karo, RAM/disk health check karo, aur next dump ko WinDbg/WhoCrashed me analyze karo.\")\n        lines.append(\"\")\n        lines.append(\"Recent matching events:\")\n        if events:\n            for ev in events[:10]:\n                msg = \" \".join(str(ev.get(\"Message\", \"\") or \"\").split())[:240]\n                lines.append(f\"- {ev.get('TimeCreated','')} | {ev.get('ProviderName','')} | ID {ev.get('Id','')} | {msg}\")\n        else:\n            lines.append(\"- No matching Event Viewer data found.\")\n        lines.append(\"\")\n        lines.append(\"Recent non-Microsoft drivers:\")\n        if drivers:\n            for d in drivers[:10]:\n                lines.append(f\"- {d.get('DeviceName','')} | {d.get('DriverProviderName','')} | {d.get('DriverVersion','')} | {d.get('DriverDate','')}\")\n        else:\n            lines.append(\"- Third-party driver list empty/blocked.\")\n        lines.append(\"\")\n        lines.append(\"Customer ko simple explain:\")\n        lines.append(\"Blue screen ka matlab Windows kernel level par serious crash hua. Is report me humne stop code, crash dump, hardware WHEA, disk/NTFS, GPU/display aur driver clues check kiye. Jo clue mila hai uske hisaab se driver update/rollback, RAM/disk test, GPU/storage driver repair, ya minidump enable karna next best step hai.\")\n\n        severity = \"warning\" if findings or dumps else \"success\"\n        return \"\\n\".join(lines), severity, len(findings)\n\n    def _bsod_deep_diagnose(self):\n        if not messagebox.askyesno(\n            \"BSoD Deep Diagnose\",\n            \"Blue screen root-cause diagnosis run karein?\\n\\n\"\n            \"Ye sirf logs/settings check karega. Koi destructive change nahi karega.\"\n        ):\n            return\n        self._append_log(self.trouble_log, \"BSoD Deep Diagnose started...\", C[\"accent3\"])\n        self._set_status(\"BSoD diagnosis running...\", C[\"accent3\"])\n        self._launch_job(\"bsod_deep_diagnose\", self._do_bsod_deep_diagnose)\n\n    def _do_bsod_deep_diagnose(self):\n        try:\n            report, severity, count = self._build_bsod_deep_report()\n            color = C[\"warning\"] if severity == \"warning\" else C[\"success\"]\n            self._append_log(self.trouble_log, \"\\n\" + report + \"\\n\", color)\n            title = \"BSoD Clues Found\" if count else \"BSoD Diagnosis Complete\"\n            msg = (\n                f\"{count} clue(s) found. Full Hinglish report System Repair log me hai.\"\n                if count else\n                \"Strong BSOD clue nahi mila. Full report System Repair log me hai.\"\n            )\n            self.after(0, lambda: messagebox.showwarning(title, msg) if count else messagebox.showinfo(title, msg))\n            self.after(0, lambda: self._set_status(\"BSoD diagnosis complete\", color))\n        except Exception as e:\n            self._append_log(self.trouble_log, f\"BSoD diagnosis failed: {e}\", C[\"error\"])\n            self.after(0, lambda: self._set_status(\"BSoD diagnosis failed\", C[\"error\"]))\n\n    def _enable_bsod_minidump(self):\n        if not messagebox.askyesno(\n            \"Enable Minidump\",\n            \"Future Blue Screen ke proof logs enable karein?\\n\\n\"\n            \"Changes:\\n\"\n            \"- Small memory dump enable\\n\"\n            \"- C:\\\\Windows\\\\Minidump path set\\n\"\n            \"- Event log enable\\n\"\n            \"- Auto restart off, taaki stop code dikhe\\n\\n\"\n            \"Admin rights required.\"\n        ):\n            return\n        self._append_log(self.trouble_log, \"Enabling BSOD minidump settings...\", C[\"accent3\"])\n        try:\n            try:\n                os.makedirs(r\"C:\\Windows\\Minidump\", exist_ok=True)\n            except Exception as e:\n                self._append_log(self.trouble_log, f\"Minidump folder create warning: {e}\", C[\"warning\"])\n            results = [\n                self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Control\\CrashControl\", \"CrashDumpEnabled\", 3, winreg.REG_DWORD, \"Small memory dump enabled\", self.trouble_log),\n                self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Control\\CrashControl\", \"MinidumpDir\", r\"%SystemRoot%\\Minidump\", winreg.REG_EXPAND_SZ, \"Minidump directory set\", self.trouble_log),\n                self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Control\\CrashControl\", \"LogEvent\", 1, winreg.REG_DWORD, \"Crash event logging enabled\", self.trouble_log),\n                self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Control\\CrashControl\", \"AutoReboot\", 0, winreg.REG_DWORD, \"Auto restart after BSOD disabled\", self.trouble_log),\n                self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Control\\CrashControl\", \"Overwrite\", 1, winreg.REG_DWORD, \"Overwrite old dump enabled\", self.trouble_log),\n            ]\n            summary = self._action_summary(\"BSOD Minidump Setup\", results)\n            note = summary[\"message\"] + \"\\n\\nNote: Pagefile system managed hona chahiye, warna dump create fail ho sakta hai.\"\n            self._append_log(self.trouble_log, note, C[\"success\"] if not summary[\"failed\"] else C[\"warning\"])\n            messagebox.showinfo(\"Minidump Setup\", note)\n        except Exception as e:\n            self._append_log(self.trouble_log, f\"Minidump setup failed: {e}\", C[\"error\"])\n            messagebox.showerror(\"Error\", str(e))\n\n    def _collect_rundll32_details(self):\n        sig_script = r\"\"\"\n$paths = @(\"$env:windir\\System32\\rundll32.exe\", \"$env:windir\\SysWOW64\\rundll32.exe\")\n$items = foreach($p in $paths) {\n    $exists = Test-Path $p\n    $sig = $null\n    $file = $null\n    if($exists) {\n        $sig = Get-AuthenticodeSignature $p -ErrorAction SilentlyContinue\n        $file = Get-Item $p -ErrorAction SilentlyContinue\n    }\n    [pscustomobject]@{\n        Path=$p\n        Exists=$exists\n        Length=if($file){$file.Length}else{$null}\n        LastWriteTime=if($file){$file.LastWriteTime.ToString('s')}else{$null}\n        SignatureStatus=if($sig){[string]$sig.Status}else{\"Missing\"}\n        Signer=if($sig -and $sig.SignerCertificate){$sig.SignerCertificate.Subject}else{\"\"}\n    }\n}\n$items | ConvertTo-Json -Depth 4\n\"\"\"\n        startup_script = r\"\"\"\n$items = @()\n$keys = @(\n    'HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Run',\n    'HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce',\n    'HKLM:\\Software\\Microsoft\\Windows\\CurrentVersion\\Run',\n    'HKLM:\\Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce',\n    'HKLM:\\Software\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Run',\n    'HKLM:\\Software\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\RunOnce'\n)\nforeach($k in $keys) {\n    if(Test-Path $k) {\n        $props = Get-ItemProperty $k -ErrorAction SilentlyContinue\n        foreach($p in $props.PSObject.Properties) {\n            if($p.Name -match '^PS') { continue }\n            $v = [string]$p.Value\n            if($v -match 'rundll32|rundell32|rundll32\\.dll|rundell32\\.dll') {\n                $items += [pscustomobject]@{Location=$k;Name=$p.Name;Command=$v}\n            }\n        }\n    }\n}\n$items | ConvertTo-Json -Depth 4\n\"\"\"\n        task_script = r\"\"\"\n$items = @()\ntry {\n    $items = Get-ScheduledTask -ErrorAction SilentlyContinue |\n        Where-Object { ($_.Actions | Out-String) -match 'rundll32|rundell32|rundll32\\.dll|rundell32\\.dll' } |\n        Select-Object -First 30 TaskPath,TaskName,State,@{n='Action';e={($_.Actions | Out-String).Trim()}}\n} catch {}\n$items | ConvertTo-Json -Depth 4\n\"\"\"\n        event_script = r\"\"\"\n$items = @()\nforeach($log in @('Application','System')) {\n    try {\n        $items += Get-WinEvent -LogName $log -MaxEvents 900 -ErrorAction SilentlyContinue |\n            Where-Object {\n                ($_.Message -match 'rundll32|rundell32|rundll32\\.dll|rundell32\\.dll|kernel32\\.dll') -or\n                ($_.ProviderName -match 'SideBySide|Application Error' -and $_.Message -match '\\.dll|module|activation context|kernel32')\n            } |\n            Select-Object -First 25 @{n='Log';e={$log}},@{n='TimeCreated';e={$_.TimeCreated.ToString('s')}},ProviderName,Id,LevelDisplayName,@{n='Message';e={$_.Message}}\n    } catch {}\n}\n$items | Select-Object -First 35 | ConvertTo-Json -Depth 4\n\"\"\"\n        wer_script = r\"\"\"\n$roots = @(\"$env:ProgramData\\Microsoft\\Windows\\WER\\ReportArchive\", \"$env:ProgramData\\Microsoft\\Windows\\WER\\ReportQueue\", \"$env:LOCALAPPDATA\\Microsoft\\Windows\\WER\")\n$items = @()\nforeach($r in $roots) {\n    if(Test-Path $r) {\n        try {\n            $items += Get-ChildItem $r -Recurse -Filter Report.wer -ErrorAction SilentlyContinue |\n                Select-Object -First 80 |\n                ForEach-Object {\n                    $txt = Get-Content $_.FullName -Raw -ErrorAction SilentlyContinue\n                    if($txt -match 'rundll32|rundell32|kernel32\\.dll|Fault Module Name|AppName') {\n                        [pscustomobject]@{Path=$_.FullName;LastWriteTime=$_.LastWriteTime.ToString('s');Text=($txt.Substring(0, [Math]::Min($txt.Length, 2500)))}\n                    }\n                }\n        } catch {}\n    }\n}\n$items | Select-Object -First 30 | ConvertTo-Json -Depth 4\n\"\"\"\n        suspicious_file_script = r\"\"\"\n$paths = @(\n    \"$env:windir\\rundell32.dll\",\n    \"$env:windir\\rundll32.dll\",\n    \"$env:windir\\System32\\rundell32.dll\",\n    \"$env:windir\\System32\\rundll32.dll\",\n    \"$env:windir\\SysWOW64\\rundell32.dll\",\n    \"$env:windir\\SysWOW64\\rundll32.dll\"\n)\n$items = foreach($p in $paths) {\n    if(Test-Path $p) {\n        $f = Get-Item $p -ErrorAction SilentlyContinue\n        [pscustomobject]@{Path=$p;Length=$f.Length;LastWriteTime=$f.LastWriteTime.ToString('s')}\n    }\n}\n$items | ConvertTo-Json -Depth 4\n\"\"\"\n        sig_out, _ = self._run_powershell(sig_script, timeout=35)\n        startup_out, _ = self._run_powershell(startup_script, timeout=35)\n        task_out, _ = self._run_powershell(task_script, timeout=60)\n        event_out, _ = self._run_powershell(event_script, timeout=60)\n        suspicious_file_out, _ = self._run_powershell(suspicious_file_script, timeout=30)\n        wer_out, _ = self._run_powershell(wer_script, timeout=80)\n        where_out, _ = self._run_cmd(\"where rundll32\", timeout=15)\n        return {\n            \"files\": self._json_items_from_output(sig_out),\n            \"startup\": self._json_items_from_output(startup_out),\n            \"tasks\": self._json_items_from_output(task_out),\n            \"events\": self._json_items_from_output(event_out),\n            \"fake\": self._json_items_from_output(suspicious_file_out),\n            \"wer\": self._json_items_from_output(wer_out),\n            \"where\": where_out.strip(),\n        }\n\n    def _build_rundll32_report(self):\n        data = self._collect_rundll32_details()\n        findings = []\n        solutions = []\n\n        for item in data[\"files\"]:\n            path = str(item.get(\"Path\", \"\"))\n            exists = bool(item.get(\"Exists\"))\n            sig = str(item.get(\"SignatureStatus\", \"\"))\n            signer = str(item.get(\"Signer\", \"\"))\n            if not exists:\n                findings.append(f\"{path} missing hai.\")\n                solutions.append(\"System file missing/corrupt ho sakti hai: DISM RestoreHealth aur SFC /SCANNOW run karo.\")\n            elif sig.lower() != \"valid\" or \"microsoft\" not in signer.lower():\n                findings.append(f\"{path} signature suspicious hai: Status={sig}, Signer={signer}\")\n                solutions.append(\"Malware/tampering possible: Defender Offline Scan run karo, phir SFC/DISM se system file repair karo.\")\n\n        if data[\"fake\"]:\n            findings.append(\"rundll32.dll/rundell32.dll naam ki suspicious file mili. Windows ka real file rundll32.exe hota hai.\")\n            solutions.append(\"Suspicious DLL ko direct open/delete na karein. Pehle Defender Offline Scan, then autoruns/startup check karke source remove karein.\")\n\n        typo_hits = []\n        for group in (\"startup\", \"tasks\", \"events\"):\n            for item in data[group]:\n                text = \" \".join(str(v) for v in item.values()).lower()\n                if \"rundell32\" in text or \"rundll32.dll\" in text or \"rundell32.dll\" in text:\n                    typo_hits.append(item)\n        if typo_hits:\n            findings.append(\"rundell32/rundll32.dll typo reference mila. Ye aksar malware ya broken startup entry hoti hai.\")\n            solutions.append(\"Startup/Task Scheduler me us entry ko disable/remove karo, related unknown app uninstall karo, malware scan run karo.\")\n\n        if data[\"startup\"]:\n            findings.append(f\"{len(data['startup'])} startup Run entry rundll32 use kar rahi hai.\")\n            solutions.append(\"Agar error startup par aata hai to listed Run entry ka DLL path check karo; missing DLL ho to entry disable karo ya app reinstall/uninstall karo.\")\n        if data[\"tasks\"]:\n            findings.append(f\"{len(data['tasks'])} scheduled task rundll32 use kar raha hai.\")\n            solutions.append(\"Task Scheduler me listed task ka action verify karo; unknown/publisher-less task disable karke reboot test karo.\")\n\n        for ev in data[\"events\"]:\n            msg = str(ev.get(\"Message\", \"\") or \"\").lower()\n            src = str(ev.get(\"ProviderName\", \"\") or \"\").lower()\n            if \"kernel32.dll\" in msg:\n                findings.append(\"kernel32.dll faulting module event mila.\")\n                solutions.append(\"kernel32.dll aksar victim module hota hai. Real culprit app/plugin/runtime hota hai: affected app repair/reinstall, VC++ runtime repair, SFC/DISM run karo.\")\n            if \"specified module could not be found\" in msg or \"module could not be found\" in msg:\n                findings.append(\"Event log me 'specified module could not be found' mila.\")\n                solutions.append(\"Karan: Windows rundll32.exe se ek DLL load kar raha tha, par DLL missing hai. Solution: startup/task entry remove karo ya related app reinstall karo.\")\n            if \"sidebyside\" in src or \"activation context\" in msg:\n                findings.append(\"SideBySide/activation context DLL error mila.\")\n                solutions.append(\"Karan: app runtime/VC++ dependency mismatch. Solution: affected app reinstall karo aur Microsoft Visual C++ Redistributables repair/install karo.\")\n            if \"faulting application name: rundll32.exe\" in msg:\n                findings.append(\"rundll32.exe crash event mila.\")\n                solutions.append(\"Karan usually loaded DLL/plugin hota hai, rundll32.exe khud nahi. Event message me faulting module/app identify karke us app/driver ko repair karo.\")\n        for wer in data.get(\"wer\", []):\n            text = str(wer.get(\"Text\", \"\") or \"\").lower()\n            if \"kernel32.dll\" in text or \"rundll32\" in text or \"rundell32\" in text:\n                findings.append(\"WER crash report me kernel32/rundll32 related crash evidence mila.\")\n                solutions.append(\"WER report me AppName/Fault Module dekho; us affected app ko repair/reinstall karo aur dependency/runtime issue fix karo.\")\n\n        lines = []\n        lines.append(\"Kernel32 + Rundll32 / Rundell32 DLL Error Troubleshooting Report (Hinglish)\")\n        lines.append(f\"Generated: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\")\n        lines.append(\"\")\n        lines.append(\"Important clarification:\")\n        lines.append(\"- Windows ka real component rundll32.exe hota hai, rundell32.dll nahi.\")\n        lines.append(\"- Error usually tab aata hai jab startup/task/app rundll32.exe ke through ek DLL load karna chahta hai, par DLL missing/corrupt/incompatible hoti hai.\")\n        lines.append(\"\")\n        lines.append(\"Troubleshoot kya kiya:\")\n        lines.append(\"- System32 aur SysWOW64 me rundll32.exe file existence/signature check ki.\")\n        lines.append(\"- where rundll32 se PATH hijack check kiya.\")\n        lines.append(\"- Registry Run/RunOnce startup entries me rundll32/rundell32 references dhoonde.\")\n        lines.append(\"- Scheduled Tasks me rundll32 actions check kiye.\")\n        lines.append(\"- Event Viewer me rundll32, rundell32, kernel32, SideBySide, module/DLL errors check kiye.\")\n        lines.append(\"- WER ReportArchive/ReportQueue me faulting module crash reports check kiye.\")\n        lines.append(\"- Fake/suspicious rundll32.dll/rundell32.dll files common Windows folders me check ki.\")\n        lines.append(\"\")\n        lines.append(\"File status:\")\n        if data[\"files\"]:\n            for item in data[\"files\"]:\n                lines.append(f\"- {item.get('Path','')} | Exists={item.get('Exists')} | Signature={item.get('SignatureStatus')} | Signer={item.get('Signer','')}\")\n        else:\n            lines.append(\"- File signature data read nahi hua.\")\n        lines.append(\"\")\n        lines.append(\"where rundll32:\")\n        lines.append(data[\"where\"] or \"No PATH result.\")\n        lines.append(\"\")\n        lines.append(\"Result / likely karan:\")\n        if findings:\n            for item in list(dict.fromkeys(findings))[:14]:\n                lines.append(f\"- {item}\")\n        else:\n            lines.append(\"- rundll32 related strong problem nahi mila. Agar popup aa raha hai, exact popup text/DLL name note karke startup/task me search karein.\")\n        lines.append(\"\")\n        lines.append(\"Solution:\")\n        if solutions:\n            for item in list(dict.fromkeys(solutions))[:14]:\n                lines.append(f\"- {item}\")\n        else:\n            lines.append(\"- SFC/DISM run karo, unknown startup entries disable karo, affected app reinstall/uninstall karo, malware scan run karo.\")\n        lines.append(\"\")\n        lines.append(\"Startup entries:\")\n        if data[\"startup\"]:\n            for item in data[\"startup\"][:12]:\n                lines.append(f\"- {item.get('Location','')} | {item.get('Name','')} | {item.get('Command','')}\")\n        else:\n            lines.append(\"- No rundll32 startup entry found.\")\n        lines.append(\"\")\n        lines.append(\"Scheduled tasks:\")\n        if data[\"tasks\"]:\n            for item in data[\"tasks\"][:12]:\n                action = \" \".join(str(item.get(\"Action\", \"\")).split())[:260]\n                lines.append(f\"- {item.get('TaskPath','')}{item.get('TaskName','')} | {item.get('State','')} | {action}\")\n        else:\n            lines.append(\"- No rundll32 scheduled task found.\")\n        lines.append(\"\")\n        lines.append(\"Recent related events:\")\n        if data[\"events\"]:\n            for ev in data[\"events\"][:10]:\n                msg = \" \".join(str(ev.get(\"Message\", \"\") or \"\").split())[:260]\n                lines.append(f\"- {ev.get('TimeCreated','')} | {ev.get('ProviderName','')} | ID {ev.get('Id','')} | {msg}\")\n        else:\n            lines.append(\"- No recent related Event Viewer error found.\")\n        lines.append(\"\")\n        lines.append(\"WER reports:\")\n        if data.get(\"wer\"):\n            for wer in data[\"wer\"][:8]:\n                sample = \" \".join(str(wer.get(\"Text\", \"\") or \"\").split())[:260]\n                lines.append(f\"- {wer.get('LastWriteTime','')} | {wer.get('Path','')} | {sample}\")\n        else:\n            lines.append(\"- No related WER crash reports found.\")\n        lines.append(\"\")\n        lines.append(\"Customer ko simple explain:\")\n        lines.append(\"Rundll32.exe Windows ka loader hai aur kernel32.dll core Windows library hai. Popup/crash me inka naam aane ka matlab aksar ye hota hai ki koi app, startup entry, shell extension, driver, ya missing DLL inke through fail ho raha hai. Humne file signature, startup, scheduled task, Event Viewer aur WER crash reports check kiye. Jo entry/app/module culprit ho usko reinstall/uninstall/disable karein, malware scan plus SFC/DISM run karein.\")\n\n        return \"\\n\".join(lines), (\"warning\" if findings else \"success\"), len(findings)\n\n    def _rundll32_error_diagnose(self):\n        if not messagebox.askyesno(\n            \"Rundll32 Error Check\",\n            \"rundll32/rundell32 DLL error diagnosis run karein?\\n\\n\"\n            \"Ye logs, startup entries aur file signature check karega. Koi entry delete nahi karega.\"\n        ):\n            return\n        self._append_log(self.trouble_log, \"Rundll32 Error Check started...\", C[\"btn_info\"])\n        self._set_status(\"Rundll32 diagnosis running...\", C[\"btn_info\"])\n        self._launch_job(\"rundll32_error_diagnose\", self._do_rundll32_error_diagnose)\n\n    def _do_rundll32_error_diagnose(self):\n        try:\n            report, severity, count = self._build_rundll32_report()\n            color = C[\"warning\"] if severity == \"warning\" else C[\"success\"]\n            self._append_log(self.trouble_log, \"\\n\" + report + \"\\n\", color)\n            title = \"Rundll32 Clues Found\" if count else \"Rundll32 Check Complete\"\n            msg = (\n                f\"{count} clue(s) found. Full Hinglish report System Repair log me hai.\"\n                if count else\n                \"Strong rundll32 problem nahi mila. Full report System Repair log me hai.\"\n            )\n            self.after(0, lambda: messagebox.showwarning(title, msg) if count else messagebox.showinfo(title, msg))\n            self.after(0, lambda: self._set_status(\"Rundll32 diagnosis complete\", color))\n        except Exception as e:\n            self._append_log(self.trouble_log, f\"Rundll32 diagnosis failed: {e}\", C[\"error\"])\n            self.after(0, lambda: self._set_status(\"Rundll32 diagnosis failed\", C[\"error\"]))\n\n    def _show_text_report_window(self, title, text):\n        win = tk.Toplevel(self)\n        win.title(title)\n        win.geometry(\"1050x700\")\n        win.configure(bg=C[\"bg\"])\n        viewer = scrolledtext.ScrolledText(\n            win, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"],\n            insertbackground=C[\"text\"], wrap=\"word\"\n        )\n        viewer.pack(fill=\"both\", expand=True, padx=10, pady=10)\n        viewer.insert(\"1.0\", self._fix_text(text))\n        viewer.config(state=\"disabled\")\n\n    def _find_debugger_engine(self):\n        candidates = []\n        for exe in (\"cdb.exe\", \"kd.exe\", \"windbg.exe\"):\n            path = shutil.which(exe)\n            if path:\n                candidates.append(path)\n        roots = [\n            os.environ.get(\"ProgramFiles\", r\"C:\\Program Files\"),\n            os.environ.get(\"ProgramFiles(x86)\", r\"C:\\Program Files (x86)\"),\n        ]\n        rels = [\n            r\"Windows Kits\\10\\Debuggers\\x64\\cdb.exe\",\n            r\"Windows Kits\\10\\Debuggers\\x86\\cdb.exe\",\n            r\"Windows Kits\\10\\Debuggers\\x64\\kd.exe\",\n            r\"Windows Kits\\10\\Debuggers\\x64\\windbg.exe\",\n        ]\n        for root in roots:\n            if not root:\n                continue\n            for rel in rels:\n                p = os.path.join(root, rel)\n                if os.path.exists(p):\n                    candidates.append(p)\n        seen = set()\n        for p in candidates:\n            key = p.lower()\n            if key not in seen:\n                seen.add(key)\n                return p\n        return \"\"\n\n    def _parse_windbg_analysis(self, text):\n        data = {}\n        patterns = {\n            \"bugcheck\": r\"BUGCHECK_CODE:\\s+([^\\r\\n]+)\",\n            \"exception_code\": r\"EXCEPTION_CODE:\\s+\\(?([^\\s\\)]+)\",\n            \"probably_caused_by\": r\"Probably caused by\\s+:\\s+([^\\r\\n]+)\",\n            \"module_name\": r\"MODULE_NAME:\\s+([^\\r\\n]+)\",\n            \"image_name\": r\"IMAGE_NAME:\\s+([^\\r\\n]+)\",\n            \"failure_bucket\": r\"FAILURE_BUCKET_ID:\\s+([^\\r\\n]+)\",\n            \"process_name\": r\"PROCESS_NAME:\\s+([^\\r\\n]+)\",\n        }\n        for key, pat in patterns.items():\n            m = re.search(pat, text, re.I)\n            if m:\n                data[key] = m.group(1).strip()\n        stack = []\n        capture = False\n        for ln in text.splitlines():\n            if ln.strip().upper().startswith(\"STACK_TEXT\"):\n                capture = True\n                continue\n            if capture:\n                if not ln.strip():\n                    if stack:\n                        break\n                    continue\n                if len(stack) &lt; 18:\n                    stack.append(ln.rstrip())\n        data[\"stack\"] = stack\n        return data\n\n    def _build_windbg_report(self, dump_path):\n        dbg = self._find_debugger_engine()\n        if not dbg:\n            return (\n                \"WinDbg automation unavailable.\\n\\n\"\n                \"Debugging Tools for Windows/cdb.exe system me nahi mila.\\n\"\n                \"Install Windows SDK Debugging Tools, phir ye button !analyze -v automation run karega.\\n\\n\"\n                f\"Dump selected: {dump_path}\",\n                \"warning\"\n            )\n        cmd_script = \".symfix;.reload;!analyze -v;lm;k;q\"\n        cmd = f'\"{dbg}\" -z \"{dump_path}\" -c \"{cmd_script}\"'\n        out, rc = self._run_cmd(cmd, timeout=900)\n        parsed = self._parse_windbg_analysis(out)\n        lines = [\n            \"WinDbg Automated Crash Analysis\",\n            f\"Generated: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\",\n            f\"Debugger: {dbg}\",\n            f\"Dump: {dump_path}\",\n            f\"Return code: {rc}\",\n            \"\",\n            \"Commands executed:\",\n            \".symfix\",\n            \".reload\",\n            \"!analyze -v\",\n            \"lm\",\n            \"k\",\n            \"\",\n            \"Parsed result:\",\n        ]\n        if parsed:\n            for k in (\"bugcheck\", \"exception_code\", \"probably_caused_by\", \"module_name\", \"image_name\", \"failure_bucket\", \"process_name\"):\n                if parsed.get(k):\n                    lines.append(f\"- {k}: {parsed[k]}\")\n            if parsed.get(\"bugcheck\"):\n                key, detail = self._bsod_stop_code_details(parsed[\"bugcheck\"])\n                lines.append(f\"- stop code explain: {key} {detail[0]} | {detail[1]}\")\n                lines.append(f\"- solution: {detail[2]}\")\n            if parsed.get(\"probably_caused_by\"):\n                lines.append(\"\")\n                lines.append(\"Suspected driver/app:\")\n                lines.append(f\"- {parsed['probably_caused_by']}\")\n                lines.append(\"- Is driver/app ko update, rollback, ya clean reinstall karke retest karein.\")\n            if parsed.get(\"stack\"):\n                lines.append(\"\")\n                lines.append(\"Stack trace sample:\")\n                lines.extend(parsed[\"stack\"])\n        else:\n            lines.append(\"- WinDbg output parse nahi hua. Raw output neeche diya hai.\")\n        lines.append(\"\")\n        lines.append(\"Raw WinDbg output tail:\")\n        lines.append(out[-6000:] if out else \"No output\")\n        return \"\\n\".join(lines), (\"warning\" if parsed else \"success\")\n\n    def _windbg_dump_analyze(self):\n        dumps = self._bsod_dump_files()\n        if not dumps:\n            messagebox.showinfo(\"No Dump\", \"C:\\\\Windows\\\\Minidump ya MEMORY.DMP me dump file nahi mili.\")\n            return\n        latest = dumps[0][\"path\"]\n        if not messagebox.askyesno(\n            \"WinDbg Dump Analyze\",\n            f\"Latest dump analyze karein?\\n\\n{latest}\\n\\n\"\n            \"Ye WinDbg/cdb.exe available hone par symbols load karke !analyze -v run karega.\"\n        ):\n            return\n        self._append_log(self.trouble_log, f\"WinDbg analysis started: {latest}\", C[\"accent4\"])\n        self._set_status(\"WinDbg dump analysis running...\", C[\"accent4\"])\n        self._launch_job(\"windbg_dump_analyze\", self._do_windbg_dump_analyze, latest)\n\n    def _do_windbg_dump_analyze(self, dump_path):\n        try:\n            report, severity = self._build_windbg_report(dump_path)\n            color = C[\"warning\"] if severity == \"warning\" else C[\"success\"]\n            self._append_log(self.trouble_log, \"\\n\" + report + \"\\n\", color)\n            self.after(0, lambda: self._show_text_report_window(\"WinDbg Dump Analysis\", report))\n            self.after(0, lambda: self._set_status(\"WinDbg analysis complete\", color))\n        except Exception as e:\n            self._append_log(self.trouble_log, f\"WinDbg analysis failed: {e}\", C[\"error\"])\n            self.after(0, lambda: self._set_status(\"WinDbg analysis failed\", C[\"error\"]))\n\n    def _collect_correlation_events(self):\n        script = r\"\"\"\n$ids = @(41,1001,6008,7031,7034,7000,7001,7,11,51,55,129,153,161,17,18,19,4101,1000,1002)\n$all = @()\nforeach($log in @('System','Application')) {\n    try {\n        $all += Get-WinEvent -LogName $log -MaxEvents 700 -ErrorAction SilentlyContinue |\n            Where-Object { ($ids -contains $_.Id) -or $_.LevelDisplayName -match 'Critical|Error' } |\n            Select-Object @{n='Log';e={$log}},@{n='TimeCreated';e={$_.TimeCreated.ToString('s')}},\n                ProviderName,Id,LevelDisplayName,@{n='Message';e={$_.Message}}\n    } catch {}\n}\n$all | Sort-Object TimeCreated -Descending | Select-Object -First 120 | ConvertTo-Json -Depth 4\n\"\"\"\n        out, _ = self._run_powershell(script, timeout=80)\n        return self._json_items_from_output(out)\n\n    def _build_event_correlation_report(self):\n        events = self._collect_correlation_events()\n        categories = {\n            \"Kernel-Power / dirty shutdown\": [],\n            \"BugCheck / BSOD\": [],\n            \"Service crashes\": [],\n            \"Disk / NTFS / storage\": [],\n            \"WHEA hardware\": [],\n            \"Application crashes\": [],\n        }\n        for ev in events:\n            text = f\"{ev.get('ProviderName','')} {ev.get('Id','')} {ev.get('Message','')}\".lower()\n            eid = str(ev.get(\"Id\", \"\"))\n            if \"kernel-power\" in text or eid == \"6008\":\n                categories[\"Kernel-Power / dirty shutdown\"].append(ev)\n            if \"bugcheck\" in text or eid == \"1001\":\n                categories[\"BugCheck / BSOD\"].append(ev)\n            if \"service control manager\" in text or eid in {\"7031\", \"7034\", \"7000\", \"7001\"}:\n                categories[\"Service crashes\"].append(ev)\n            if any(x in text for x in (\"disk\", \"ntfs\", \"storahci\", \"storport\", \"volmgr\")) or eid in {\"7\", \"11\", \"51\", \"55\", \"129\", \"153\", \"161\"}:\n                categories[\"Disk / NTFS / storage\"].append(ev)\n            if \"whea\" in text or eid in {\"17\", \"18\", \"19\"}:\n                categories[\"WHEA hardware\"].append(ev)\n            if \"application error\" in text or eid in {\"1000\", \"1002\"}:\n                categories[\"Application crashes\"].append(ev)\n        lines = [\n            \"Event Correlation Report\",\n            f\"Generated: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\",\n            \"\",\n            \"Troubleshoot kya kiya:\",\n            \"- System/Application logs se critical/error events collect kiye.\",\n            \"- Kernel-Power, BugCheck, service crash, disk/NTFS, WHEA, application crash ko timeline me correlate kiya.\",\n            \"\",\n            \"Root-cause summary:\",\n        ]\n        for name, items in categories.items():\n            lines.append(f\"- {name}: {len(items)} event(s)\")\n        if categories[\"BugCheck / BSOD\"] and categories[\"Kernel-Power / dirty shutdown\"]:\n            lines.append(\"- Probable: dirty shutdown Kernel-Power ke peeche actual BugCheck/BSOD ho sakta hai.\")\n        if categories[\"WHEA hardware\"]:\n            lines.append(\"- Probable: hardware/thermal/PCIe/RAM/SSD issue BSOD ya restart ka source ho sakta hai.\")\n        if categories[\"Disk / NTFS / storage\"]:\n            lines.append(\"- Probable: disk/storage timeout ya NTFS corruption system freeze/BSOD trigger kar sakta hai.\")\n        if categories[\"Service crashes\"] and not categories[\"BugCheck / BSOD\"]:\n            lines.append(\"- Probable: Windows service/app instability hai; service dependencies aur recent updates check karo.\")\n        lines.append(\"\")\n        lines.append(\"Chronological events (latest first):\")\n        for ev in events[:35]:\n            msg = \" \".join(str(ev.get(\"Message\", \"\") or \"\").split())[:220]\n            lines.append(f\"- {ev.get('TimeCreated','')} | {ev.get('Log','')} | {ev.get('ProviderName','')} | ID {ev.get('Id','')} | {msg}\")\n        return \"\\n\".join(lines), (\"warning\" if events else \"success\")\n\n    def _event_correlation_report(self):\n        self._append_log(self.trouble_log, \"Event correlation started...\", C[\"btn\"])\n        self._set_status(\"Event correlation running...\", C[\"btn\"])\n        self._launch_job(\"event_correlation_report\", self._do_event_correlation_report)\n\n    def _do_event_correlation_report(self):\n        try:\n            report, severity = self._build_event_correlation_report()\n            color = C[\"warning\"] if severity == \"warning\" else C[\"success\"]\n            self._append_log(self.trouble_log, \"\\n\" + report + \"\\n\", color)\n            self.after(0, lambda: self._show_text_report_window(\"Event Correlation Report\", report))\n            self.after(0, lambda: self._set_status(\"Event correlation complete\", color))\n        except Exception as e:\n            self._append_log(self.trouble_log, f\"Event correlation failed: {e}\", C[\"error\"])\n\n    def _build_driver_diagnostics_report(self):\n        driverquery_out, _ = self._run_cmd(\"driverquery /v /fo csv\", timeout=80)\n        script = r\"\"\"\n$drivers = @()\ntry {\n    $drivers = Get-CimInstance Win32_PnPSignedDriver -ErrorAction SilentlyContinue |\n        Select-Object DeviceName,DriverProviderName,DriverVersion,DriverDate,InfName,IsSigned |\n        Sort-Object DriverDate -Descending\n} catch {}\n$sys = @()\ntry {\n    $sys = Get-ChildItem \"$env:windir\\System32\\drivers\\*.sys\" -ErrorAction SilentlyContinue |\n        Sort-Object LastWriteTime -Descending |\n        Select-Object -First 80 FullName,Length,LastWriteTime,@{n='Signature';e={(Get-AuthenticodeSignature $_.FullName -ErrorAction SilentlyContinue).Status}}\n} catch {}\n[pscustomobject]@{PnP=$drivers;SysFiles=$sys} | ConvertTo-Json -Depth 5\n\"\"\"\n        out, _ = self._run_powershell(script, timeout=120)\n        items = self._json_items_from_output(out)\n        payload = items[0] if items else {}\n        pnp = payload.get(\"PnP\", []) if isinstance(payload, dict) else []\n        sysfiles = payload.get(\"SysFiles\", []) if isinstance(payload, dict) else []\n        if isinstance(pnp, dict):\n            pnp = [pnp]\n        if isinstance(sysfiles, dict):\n            sysfiles = [sysfiles]\n\n        unsigned = []\n        old = []\n        recent = []\n        now = datetime.datetime.now()\n        for d in pnp:\n            signed = str(d.get(\"IsSigned\", \"\")).lower()\n            provider = str(d.get(\"DriverProviderName\", \"\") or \"\")\n            date_s = str(d.get(\"DriverDate\", \"\") or \"\")\n            if signed in {\"false\", \"0\"}:\n                unsigned.append(d)\n            if provider and \"microsoft\" not in provider.lower():\n                recent.append(d)\n            try:\n                dt = datetime.datetime.fromisoformat(date_s[:19])\n                if (now - dt).days &gt; 1460 and \"microsoft\" not in provider.lower():\n                    old.append(d)\n            except Exception:\n                pass\n        bad_sig = [x for x in sysfiles if str(x.get(\"Signature\", \"\")).lower() not in {\"valid\"}]\n\n        lines = [\n            \"Driver Diagnostics Report\",\n            f\"Generated: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\",\n            \"\",\n            \"Troubleshoot kya kiya:\",\n            \"- driverquery /v output collect kiya.\",\n            \"- Win32_PnPSignedDriver se provider/date/version check kiya.\",\n            \"- .sys driver file signatures check kiye.\",\n            \"\",\n            \"Summary:\",\n            f\"- PnP drivers read: {len(pnp)}\",\n            f\"- Unsigned PnP drivers: {len(unsigned)}\",\n            f\"- Old third-party drivers (&gt;4 years): {len(old)}\",\n            f\"- Suspicious/invalid .sys signatures: {len(bad_sig)}\",\n            \"\",\n            \"Likely BSOD driver clues:\",\n        ]\n        if unsigned:\n            lines.append(\"- Unsigned drivers kernel crash ka risk badhate hain.\")\n        if old:\n            lines.append(\"- Bahut purane third-party drivers Windows update ke baad BSOD de sakte hain.\")\n        if bad_sig:\n            lines.append(\"- Invalid signature .sys file malware/tampering/corruption ka clue ho sakta hai.\")\n        if not (unsigned or old or bad_sig):\n            lines.append(\"- Strong driver risk nahi mila; recent driver changes still verify karein.\")\n        lines.append(\"\")\n        lines.append(\"Unsigned drivers:\")\n        for d in unsigned[:20]:\n            lines.append(f\"- {d.get('DeviceName','')} | {d.get('DriverProviderName','')} | {d.get('DriverVersion','')} | {d.get('InfName','')}\")\n        if not unsigned:\n            lines.append(\"- None detected.\")\n        lines.append(\"\")\n        lines.append(\"Recent third-party drivers:\")\n        for d in recent[:20]:\n            lines.append(f\"- {d.get('DriverDate','')} | {d.get('DeviceName','')} | {d.get('DriverProviderName','')} | {d.get('DriverVersion','')}\")\n        lines.append(\"\")\n        lines.append(\"Driver file signature warnings:\")\n        for f in bad_sig[:20]:\n            lines.append(f\"- {f.get('Signature','')} | {f.get('LastWriteTime','')} | {f.get('FullName','')}\")\n        if not bad_sig:\n            lines.append(\"- None detected.\")\n        lines.append(\"\")\n        lines.append(\"driverquery sample:\")\n        lines.append(driverquery_out[:2500] if driverquery_out else \"driverquery output empty.\")\n        return \"\\n\".join(lines), (\"warning\" if unsigned or old or bad_sig else \"success\")\n\n    def _driver_diagnostics_report(self):\n        self._append_log(self.trouble_log, \"Driver diagnostics started...\", C[\"btn_warn\"])\n        self._launch_job(\"driver_diagnostics_report\", self._do_driver_diagnostics_report)\n\n    def _do_driver_diagnostics_report(self):\n        try:\n            report, severity = self._build_driver_diagnostics_report()\n            color = C[\"warning\"] if severity == \"warning\" else C[\"success\"]\n            self._append_log(self.trouble_log, \"\\n\" + report + \"\\n\", color)\n            self.after(0, lambda: self._show_text_report_window(\"Driver Diagnostics\", report))\n            self.after(0, lambda: self._set_status(\"Driver diagnostics complete\", color))\n        except Exception as e:\n            self._append_log(self.trouble_log, f\"Driver diagnostics failed: {e}\", C[\"error\"])\n\n    def _build_hardware_health_report(self):\n        script = r\"\"\"\n$phys = @()\n$reli = @()\n$disk = @()\n$mem = @()\ntry { $phys = Get-PhysicalDisk | Select FriendlyName,MediaType,HealthStatus,OperationalStatus,Size } catch {}\ntry { $reli = Get-PhysicalDisk | Get-StorageReliabilityCounter | Select DeviceId,Temperature,ReadErrorsTotal,WriteErrorsTotal,Wear,PowerOnHours } catch {}\ntry { $disk = Get-Disk | Select Number,FriendlyName,HealthStatus,OperationalStatus,PartitionStyle,Size } catch {}\ntry {\n    $mem = Get-WinEvent -LogName System -MaxEvents 300 -ErrorAction SilentlyContinue |\n        Where-Object { $_.ProviderName -match 'MemoryDiagnostics|WHEA' } |\n        Select-Object -First 25 @{n='TimeCreated';e={$_.TimeCreated.ToString('s')}},ProviderName,Id,LevelDisplayName,@{n='Message';e={$_.Message}}\n} catch {}\n[pscustomobject]@{PhysicalDisk=$phys;Reliability=$reli;Disk=$disk;HardwareEvents=$mem} | ConvertTo-Json -Depth 5\n\"\"\"\n        out, _ = self._run_powershell(script, timeout=90)\n        wmic_out, _ = self._run_cmd(\"wmic diskdrive get Caption,Model,Status,MediaType,Size /format:list\", timeout=25)\n        smartctl_path = shutil.which(\"smartctl.exe\") or shutil.which(\"smartctl\")\n        smartctl_out = \"\"\n        if smartctl_path:\n            scan, _ = self._run_cmd(f'\"{smartctl_path}\" --scan', timeout=20)\n            smartctl_out += scan + \"\\n\"\n            for ln in scan.splitlines()[:4]:\n                dev = ln.split()[0] if ln.strip() else \"\"\n                if dev:\n                    detail, _ = self._run_cmd(f'\"{smartctl_path}\" -H -A \"{dev}\"', timeout=45)\n                    smartctl_out += f\"\\n--- {dev} ---\\n{detail[:2500]}\\n\"\n        items = self._json_items_from_output(out)\n        payload = items[0] if items else {}\n        warnings = []\n        text_blob = json.dumps(payload, default=str).lower() + \"\\n\" + wmic_out.lower() + \"\\n\" + smartctl_out.lower()\n        for word, msg in [\n            (\"unhealthy\", \"Disk health unhealthy report hua.\"),\n            (\"warning\", \"Disk/hardware warning status mila.\"),\n            (\"pred fail\", \"SMART predicted failure ka clue mila.\"),\n            (\"readerror\", \"Read errors storage surface/controller issue dikha sakte hain.\"),\n            (\"writeerror\", \"Write errors storage media/controller issue dikha sakte hain.\"),\n            (\"whea\", \"WHEA hardware event mila.\"),\n            (\"memorydiagnostics\", \"Memory diagnostic event mila.\"),\n        ]:\n            if word in text_blob:\n                warnings.append(msg)\n        lines = [\n            \"SMART + Hardware Health Report\",\n            f\"Generated: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\",\n            \"\",\n            \"Troubleshoot kya kiya:\",\n            \"- Get-PhysicalDisk, Get-Disk, StorageReliabilityCounter check kiya.\",\n            \"- WMIC diskdrive status collect kiya.\",\n            \"- smartctl available ho to SMART health/attributes read kiye.\",\n            \"- WHEA/MemoryDiagnostics events check kiye.\",\n            \"\",\n            \"Result / warnings:\",\n        ]\n        if warnings:\n            for item in list(dict.fromkeys(warnings)):\n                lines.append(f\"- {item}\")\n        else:\n            lines.append(\"- Strong hardware warning nahi mila, lekin full SMART vendor attributes manually bhi verify karein.\")\n        lines.append(\"\")\n        lines.append(\"PowerShell hardware data:\")\n        lines.append(json.dumps(payload, ensure_ascii=False, indent=2, default=str)[:7000])\n        lines.append(\"\")\n        lines.append(\"WMIC disk status:\")\n        lines.append(wmic_out or \"WMIC output empty.\")\n        lines.append(\"\")\n        lines.append(\"smartctl:\")\n        lines.append(smartctl_out if smartctl_out else \"smartctl installed nahi mila. Install ho to detailed SMART attributes milenge.\")\n        return \"\\n\".join(lines), (\"warning\" if warnings else \"success\")\n\n    def _hardware_health_report(self):\n        self._append_log(self.trouble_log, \"Hardware health report started...\", C[\"hw_accent\"])\n        self._launch_job(\"hardware_health_report\", self._do_hardware_health_report)\n\n    def _do_hardware_health_report(self):\n        try:\n            report, severity = self._build_hardware_health_report()\n            color = C[\"warning\"] if severity == \"warning\" else C[\"success\"]\n            self._append_log(self.trouble_log, \"\\n\" + report + \"\\n\", color)\n            self.after(0, lambda: self._show_text_report_window(\"Hardware Health Report\", report))\n            self.after(0, lambda: self._set_status(\"Hardware health complete\", color))\n        except Exception as e:\n            self._append_log(self.trouble_log, f\"Hardware health failed: {e}\", C[\"error\"])\n\n    def _repair_verification_report(self):\n        if not messagebox.askyesno(\n            \"Repair Verification\",\n            \"Repair verification run karein?\\n\\n\"\n            \"Ye SFC /VERIFYONLY, DISM /ScanHealth aur recent error logs check karega. Time lag sakta hai.\"\n        ):\n            return\n        self._append_log(self.trouble_log, \"Repair verification started...\", C[\"accent2\"])\n        self._set_status(\"Repair verification running...\", C[\"accent2\"])\n        self._launch_job(\"repair_verification_report\", self._do_repair_verification_report)\n\n    def _do_repair_verification_report(self):\n        try:\n            lines = [\n                \"Repair Verification Report\",\n                f\"Generated: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\",\n                \"\",\n                \"Step 1: SFC /VERIFYONLY\",\n            ]\n            sfc, rc_sfc, to_sfc, stop_sfc = self._stream_cmd_to_log([\"sfc\", \"/verifyonly\"], self.trouble_log, timeout_s=1200)\n            lines.append(f\"SFC rc={rc_sfc}, timeout={to_sfc}, stopped={stop_sfc}\")\n            if \"no integrity violations\" in sfc.lower():\n                lines.append(\"SFC Result: Windows protected files clean.\")\n            elif \"integrity violations\" in sfc.lower():\n                lines.append(\"SFC Result: Corruption/violations detected. Run SFC /SCANNOW + DISM RestoreHealth.\")\n            else:\n                lines.append(\"SFC Result: Output manually review karein.\")\n            lines.append(\"\")\n            lines.append(\"Step 2: DISM /ScanHealth\")\n            dism, rc_dism, to_dism, stop_dism = self._stream_cmd_to_log(\n                [\"DISM\", \"/Online\", \"/Cleanup-Image\", \"/ScanHealth\"], self.trouble_log, timeout_s=1800\n            )\n            lines.append(f\"DISM rc={rc_dism}, timeout={to_dism}, stopped={stop_dism}\")\n            if \"no component store corruption detected\" in dism.lower():\n                lines.append(\"DISM Result: Component store clean.\")\n            elif \"repairable\" in dism.lower() or \"corruption\" in dism.lower():\n                lines.append(\"DISM Result: Component store issue detected. RestoreHealth run karein.\")\n            else:\n                lines.append(\"DISM Result: Output manually review karein.\")\n            lines.append(\"\")\n            lines.append(\"Step 3: Recent repair-related events\")\n            events = self._collect_correlation_events()\n            for ev in events[:20]:\n                msg = \" \".join(str(ev.get(\"Message\", \"\") or \"\").split())[:220]\n                lines.append(f\"- {ev.get('TimeCreated','')} | {ev.get('ProviderName','')} | ID {ev.get('Id','')} | {msg}\")\n            report = \"\\n\".join(lines)\n            color = C[\"warning\"] if (\"detected\" in report.lower() and \"clean\" not in report.lower()) else C[\"success\"]\n            self._append_log(self.trouble_log, \"\\n\" + report + \"\\n\", color)\n            self.after(0, lambda: self._show_text_report_window(\"Repair Verification\", report))\n            self.after(0, lambda: self._set_status(\"Repair verification complete\", color))\n        except Exception as e:\n            self._append_log(self.trouble_log, f\"Repair verification failed: {e}\", C[\"error\"])\n            self.after(0, lambda: self._set_status(\"Repair verification failed\", C[\"error\"]))\n\n    def _boot_status_bcd_backup(self):\n        if not messagebox.askyesno(\n            \"Boot Status + BCD Backup\",\n            \"Boot status analyze aur BCD backup create karein?\\n\\n\"\n            \"Ye destructive repair nahi karega. Sirf BCD export + EFI/boot info report banayega.\"\n        ):\n            return\n        self._append_log(self.trouble_log, \"Boot status + BCD backup started...\", C[\"btn_chip\"])\n        self._launch_job(\"boot_status_bcd_backup\", self._do_boot_status_bcd_backup)\n\n    def _do_boot_status_bcd_backup(self):\n        try:\n            os.makedirs(getattr(self, \"backup_dir\", os.getcwd()), exist_ok=True)\n            ts = datetime.datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n            bcd_path = os.path.join(self.backup_dir, f\"BCD_Backup_{ts}.bcd\")\n            enum_out, _ = self._run_cmd([\"bcdedit\", \"/enum\", \"all\"], timeout=40)\n            export_out, rc_export = self._run_cmd([\"bcdedit\", \"/export\", bcd_path], timeout=40)\n            ps = r\"\"\"\n$efi = @()\ntry { $efi = Get-Partition | Where-Object {$_.GptType -match 'c12a7328'} | Select DiskNumber,PartitionNumber,DriveLetter,Size,GptType } catch {}\n$firm = $env:firmware_type\n[pscustomobject]@{Firmware=$firm;EfiPartitions=$efi} | ConvertTo-Json -Depth 4\n\"\"\"\n            efi_out, _ = self._run_powershell(ps, timeout=30)\n            lines = [\n                \"Boot Status + BCD Backup Report\",\n                f\"Generated: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\",\n                f\"BCD backup: {bcd_path if rc_export == 0 else 'FAILED'}\",\n                f\"bcdedit export rc={rc_export}\",\n                \"\",\n                \"EFI / firmware info:\",\n                efi_out.strip() or \"EFI info unavailable.\",\n                \"\",\n                \"bcdedit /enum all:\",\n                enum_out[:9000] if enum_out else \"bcdedit output empty.\",\n                \"\",\n                \"Solution guidance:\",\n                \"- Agar boot fail hai aur BCD corrupt lag raha hai, WinRE me bootrec/bcdboot use karein.\",\n                \"- EFI system me bcdboot C:\\\\Windows /s : /f UEFI carefully use hota hai.\",\n                \"- Advanced boot repair se pehle backup aur exact Windows/EFI drive letters verify karein.\",\n            ]\n            report = \"\\n\".join(lines)\n            self._append_log(self.trouble_log, \"\\n\" + report + \"\\n\", C[\"success\"] if rc_export == 0 else C[\"warning\"])\n            self.after(0, lambda: self._show_text_report_window(\"Boot Status + BCD Backup\", report))\n            self.after(0, lambda: self._set_status(\"Boot status complete\", C[\"success\"] if rc_export == 0 else C[\"warning\"]))\n        except Exception as e:\n            self._append_log(self.trouble_log, f\"Boot status failed: {e}\", C[\"error\"])\n\n    def _offline_repair_dialog(self):\n        win_dir = filedialog.askdirectory(title=\"Offline Windows folder select karo (example: D:\\\\Windows)\")\n        if not win_dir:\n            return\n        if os.path.basename(win_dir).lower() != \"windows\":\n            if not messagebox.askyesno(\"Confirm Folder\", f\"Selected folder Windows naam ka nahi hai:\\n{win_dir}\\n\\nContinue?\"):\n                return\n        image_root = os.path.dirname(win_dir.rstrip(\"\\\\/\"))\n        boot_dir = os.path.splitdrive(image_root)[0] + \"\\\\\"\n        if not messagebox.askyesno(\n            \"Offline SFC/DISM\",\n            f\"Offline repair commands run karein?\\n\\n\"\n            f\"Offbootdir: {boot_dir}\\n\"\n            f\"Offwindir: {win_dir}\\n\"\n            f\"DISM Image: {image_root}\\n\\n\"\n            \"Mounted/offline Windows path galat hua to command fail ho sakti hai.\"\n        ):\n            return\n        self._append_log(self.trouble_log, f\"Offline repair started: {win_dir}\", C[\"btn_info\"])\n        self._launch_job(\"offline_repair\", self._do_offline_repair, boot_dir, win_dir, image_root)\n\n    def _do_offline_repair(self, boot_dir, win_dir, image_root):\n        try:\n            cmds = [\n                [\"sfc\", \"/scannow\", f\"/offbootdir={boot_dir}\", f\"/offwindir={win_dir}\"],\n                [\"DISM\", f\"/Image:{image_root}\", \"/Cleanup-Image\", \"/ScanHealth\"],\n                [\"DISM\", f\"/Image:{image_root}\", \"/Cleanup-Image\", \"/RestoreHealth\"],\n            ]\n            lines = [\"Offline Repair Report\", f\"Generated: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\"]\n            for cmd in cmds:\n                lines.append(\"\")\n                lines.append(f\"Command: {subprocess.list2cmdline(cmd)}\")\n                out, rc, timed_out, stopped = self._stream_cmd_to_log(cmd, self.trouble_log, timeout_s=3600)\n                lines.append(f\"rc={rc}, timeout={timed_out}, stopped={stopped}\")\n                lines.append(out[-1200:] if out else \"No output\")\n            report = \"\\n\".join(lines)\n            self._append_log(self.trouble_log, \"\\n\" + report + \"\\n\", C[\"success\"])\n            self.after(0, lambda: self._show_text_report_window(\"Offline Repair Report\", report))\n            self.after(0, lambda: self._set_status(\"Offline repair complete\", C[\"success\"]))\n        except Exception as e:\n            self._append_log(self.trouble_log, f\"Offline repair failed: {e}\", C[\"error\"])\n\n    def _build_security_startup_report(self):\n        script = r\"\"\"\n$items = @()\n$keys = @(\n 'HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Run',\n 'HKLM:\\Software\\Microsoft\\Windows\\CurrentVersion\\Run',\n 'HKLM:\\Software\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Run',\n 'HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows',\n 'HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon',\n 'HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\AppCertDlls',\n 'HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options'\n)\nforeach($k in $keys) {\n if(Test-Path $k) {\n   try {\n     $props = Get-ItemProperty $k -ErrorAction SilentlyContinue\n     foreach($p in $props.PSObject.Properties) {\n       if($p.Name -match '^PS') { continue }\n       $items += [pscustomobject]@{Location=$k;Name=$p.Name;Value=[string]$p.Value}\n     }\n   } catch {}\n }\n}\n$tasks = @()\ntry {\n $tasks = Get-ScheduledTask -ErrorAction SilentlyContinue |\n   Where-Object { ($_.TaskPath -notmatch '\\\\Microsoft\\\\Windows\\\\') -or (($_.Actions | Out-String) -match 'AppData|Temp|rundll32|powershell|wscript|cscript') } |\n   Select-Object -First 80 TaskPath,TaskName,State,@{n='Action';e={($_.Actions | Out-String).Trim()}}\n} catch {}\n[pscustomobject]@{Registry=$items;Tasks=$tasks} | ConvertTo-Json -Depth 5\n\"\"\"\n        out, _ = self._run_powershell(script, timeout=80)\n        hosts = \"\"\n        try:\n            hosts_path = r\"C:\\Windows\\System32\\drivers\\etc\\hosts\"\n            if os.path.exists(hosts_path):\n                with open(hosts_path, \"r\", encoding=\"utf-8\", errors=\"replace\") as f:\n                    hosts = f.read()[:6000]\n        except Exception as e:\n            hosts = f\"hosts read failed: {e}\"\n        items = self._json_items_from_output(out)\n        payload = items[0] if items else {}\n        reg = payload.get(\"Registry\", []) if isinstance(payload, dict) else []\n        tasks = payload.get(\"Tasks\", []) if isinstance(payload, dict) else []\n        if isinstance(reg, dict):\n            reg = [reg]\n        if isinstance(tasks, dict):\n            tasks = [tasks]\n        risky = []\n        for row in reg:\n            val = str(row.get(\"Value\", \"\"))\n            loc = str(row.get(\"Location\", \"\"))\n            name = str(row.get(\"Name\", \"\"))\n            low = f\"{loc} {name} {val}\".lower()\n            if any(x in low for x in [\"appinit_dlls\", \"debugger\", \"appdata\", \"\\\\temp\\\\\", \"rundll32\", \"powershell\", \"wscript\", \"cscript\", \".dll\"]):\n                risky.append(row)\n        lines = [\n            \"Security + Startup Analysis Report\",\n            f\"Generated: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\",\n            \"\",\n            \"Troubleshoot kya kiya:\",\n            \"- Run/RunOnce, AppInit_DLLs, Winlogon, IFEO Debugger keys inspect ki.\",\n            \"- Non-Microsoft/suspicious Scheduled Tasks check kiye.\",\n            \"- hosts file inspect kiya.\",\n            \"\",\n            \"Summary:\",\n            f\"- Registry autorun items: {len(reg)}\",\n            f\"- Risky autorun indicators: {len(risky)}\",\n            f\"- Scheduled task indicators: {len(tasks)}\",\n            \"\",\n            \"Risky registry indicators:\",\n        ]\n        for r in risky[:30]:\n            lines.append(f\"- {r.get('Location','')} | {r.get('Name','')} | {r.get('Value','')}\")\n        if not risky:\n            lines.append(\"- None detected.\")\n        lines.append(\"\")\n        lines.append(\"Scheduled task indicators:\")\n        for t in tasks[:25]:\n            action = \" \".join(str(t.get(\"Action\", \"\")).split())[:220]\n            lines.append(f\"- {t.get('TaskPath','')}{t.get('TaskName','')} | {t.get('State','')} | {action}\")\n        if not tasks:\n            lines.append(\"- None detected.\")\n        lines.append(\"\")\n        lines.append(\"hosts file sample:\")\n        lines.append(hosts if hosts else \"hosts empty/unavailable.\")\n        lines.append(\"\")\n        lines.append(\"Solution:\")\n        lines.append(\"- Unknown AppData/Temp/rundll32/powershell startup entries ko disable karke reboot test karo.\")\n        lines.append(\"- IFEO Debugger/AppInit_DLLs entries malware persistence ka strong clue ho sakte hain.\")\n        lines.append(\"- Defender Offline Scan + SFC/DISM run karo agar suspicious injection indicator mile.\")\n        return \"\\n\".join(lines), (\"warning\" if risky or tasks else \"success\")\n\n    def _security_startup_report(self):\n        self._append_log(self.trouble_log, \"Security autorun analysis started...\", C[\"btn_warn\"])\n        self._launch_job(\"security_startup_report\", self._do_security_startup_report)\n\n    def _do_security_startup_report(self):\n        try:\n            report, severity = self._build_security_startup_report()\n            color = C[\"warning\"] if severity == \"warning\" else C[\"success\"]\n            self._append_log(self.trouble_log, \"\\n\" + report + \"\\n\", color)\n            self.after(0, lambda: self._show_text_report_window(\"Security Startup Analysis\", report))\n            self.after(0, lambda: self._set_status(\"Security analysis complete\", color))\n        except Exception as e:\n            self._append_log(self.trouble_log, f\"Security analysis failed: {e}\", C[\"error\"])\n\n    def _diagnostic_zip_package(self):\n        path = filedialog.asksaveasfilename(\n            defaultextension=\".zip\",\n            filetypes=[(\"ZIP package\", \"*.zip\")],\n            initialfile=\"Godawari_Diagnostic_Package.zip\",\n            title=\"Save diagnostic package\"\n        )\n        if not path:\n            return\n        if not messagebox.askyesno(\"Diagnostic ZIP\", \"HTML/JSON/TXT diagnostic package generate karein? Kuch checks time le sakte hain.\"):\n            return\n        self._append_log(self.trouble_log, \"Diagnostic ZIP generation started...\", C[\"accent\"])\n        self._launch_job(\"diagnostic_zip_package\", self._do_diagnostic_zip_package, path)\n\n    def _do_diagnostic_zip_package(self, zip_path):\n        try:\n            reports = {}\n            builders = [\n                (\"bsod_report\", self._build_bsod_deep_report),\n                (\"rundll32_kernel32_report\", self._build_rundll32_report),\n                (\"event_correlation\", self._build_event_correlation_report),\n                (\"driver_diagnostics\", self._build_driver_diagnostics_report),\n                (\"hardware_health\", self._build_hardware_health_report),\n                (\"security_startup\", self._build_security_startup_report),\n            ]\n            for name, fn in builders:\n                try:\n                    result = fn()\n                    reports[name] = result[0] if isinstance(result, tuple) else str(result)\n                    self._append_log(self.trouble_log, f\"Report built: {name}\", C[\"text_dim\"])\n                except Exception as e:\n                    reports[name] = f\"FAILED: {e}\"\n            payload = {\n                \"generated\": datetime.datetime.now().isoformat(timespec=\"seconds\"),\n                \"computer\": platform.node(),\n                \"reports\": reports,\n            }\n            html_body = \"Godawari Diagnostic Package\"\n            html_body += \"\nGodawari Diagnostic Package\"\n            for name, text in reports.items():\n                html_body += f\"\n{html.escape(name)}\n{html.escape(text)}\"\n            html_body += \"\"\n            with zipfile.ZipFile(zip_path, \"w\", zipfile.ZIP_DEFLATED) as z:\n                z.writestr(\"diagnostics.json\", json.dumps(payload, ensure_ascii=False, indent=2, default=str))\n                z.writestr(\"diagnostics.html\", html_body)\n                for name, text in reports.items():\n                    z.writestr(f\"{name}.txt\", text)\n                try:\n                    z.writestr(\"current_repair_log.txt\", self.trouble_log.get(\"1.0\", \"end\"))\n                except Exception:\n                    pass\n            self._append_log(self.trouble_log, f\"Diagnostic ZIP saved: {zip_path}\", C[\"success\"])\n            self.after(0, lambda: messagebox.showinfo(\"Diagnostic ZIP\", f\"Saved:\\n{zip_path}\"))\n        except Exception as e:\n            self._append_log(self.trouble_log, f\"Diagnostic ZIP failed: {e}\", C[\"error\"])\n\n    def _build_power(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\u26a1 Power Plan\", \"Change power scheme + Hibernate\")\n        self._action_card_grid(frame, [\n            (\"\ud83d\udd0b\", \"High Performance\",           \"Max speed, zyada bijli\",              C[\"btn_danger\"], lambda: self._set_power(\"8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c\")),\n            (\"\u26a1\", \"Balanced\",                   \"Speed aur battery balance\",           C[\"btn_info\"],   lambda: self._set_power(\"381b4222-f694-41f0-9685-ff5bb260df2e\")),\n            (\"\ud83c\udf3f\", \"Power Saver\",                \"Battery bachao, speed kam\",           C[\"btn\"],        lambda: self._set_power(\"a1841308-3541-4fab-bc81-f71556f20b4a\")),\n            (\"\ud83c\udf19\", \"Disable Hibernate\",          \"Hibernate + Fast Startup band karo\",  C[\"btn_warn\"],   self._disable_hibernate),\n        ], cols=4)\n        content = tk.Frame(frame, bg=C[\"card\"])\n        content.pack(fill=\"x\", padx=16, pady=(4, 10))\n        self.power_status = tk.Label(content, text=\"\", font=FONTS[\"body\"], fg=C[\"accent2\"], bg=C[\"card\"])\n        self.power_status.pack(pady=10)\n        self._refresh_power_status()\n        return frame\n\n    def _refresh_power_status(self):\n        out, _ = self._run_cmd('powercfg /getactivescheme')\n        self.power_status.config(text=f\"Current: {out.strip() if out else 'Unknown'}\")\n        self.after(5000, self._refresh_power_status)\n\n    def _set_power(self, guid):\n        if messagebox.askyesno(\"Set Power Plan\", f\"Set active power plan to {guid}?\"):\n            self._run_cmd(f'powercfg /setactive {guid}')\n            self._refresh_power_status()\n\n    def _disable_hibernate(self):\n        if messagebox.askyesno(\"Disable Hibernate\", \"Turn off hibernate and fast startup? This frees disk space but makes boot slightly slower.\"):\n            self._run_cmd('powercfg -h off')\n            self._append_log(self.power_status.master, \"\u2705 Hibernate disabled + hiberfil.sys removed\", C[\"success\"])\n            self._run_cmd('REG ADD \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Session Manager\\\\Power\" /v HiberbootEnabled /t REG_DWORD /d 0 /f')\n            self._append_log(self.power_status.master, \"\u2705 Fast Startup disabled\", C[\"success\"])\n\n    # ---------- FILE RECOVERY ----------\n    def _build_recovery_safe(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n\n        # \u2500\u2500 Fixed header (outside scroll) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        self._section_header(\n            frame, \"\ud83d\udcc2 File Search &amp; Recovery\",\n            \"Zone A = maujood files dhundo | Zone B = deleted files sector se recover karo\")\n\n        # \u2500\u2500 Scrollable body \u2014 app ka built-in method use karo \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        # _scrollable_section_body returns an inner frame with canvas+scrollbar+\n        # scoped mousewheel already wired \u2014 no conflict with other menus.\n        frame_scroll = self._scrollable_section_body(frame)\n\n        zone_a = tk.Frame(frame_scroll, bg=C[\"card\"], highlightbackground=C[\"accent2\"], highlightthickness=2)\n        zone_a.pack(fill=\"x\", padx=16, pady=(4, 6))\n        tk.Label(zone_a, text=\"\ud83d\udd0d Zone A \u2014 Search Existing Files\",\n                 font=FONTS[\"subhead\"], fg=C[\"accent2\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=12, pady=(8, 2))\n        tk.Label(zone_a,\n                 text=\"Drive pe jo files abhi bhi maujood hain unhe dhundta hai (fast, no admin needed).\\n\"\n                      \"Deleted files ke liye Zone B use karo.\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\").pack(anchor=\"w\", padx=12, pady=(0, 6))\n\n        row_inputs = tk.Frame(zone_a, bg=C[\"card\"])\n        row_inputs.pack(fill=\"x\", padx=8, pady=4)\n        tk.Label(row_inputs, text=\"Drive:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\", padx=(0, 4))\n        drive_values = [f\"{d}\\\\\" for d in \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\" if os.path.exists(f\"{d}:\\\\\")]\n        drive_values += [\"Android\"]\n        self.rec_drive = ttk.Combobox(row_inputs, values=drive_values, width=10, font=FONTS[\"body\"], state=\"readonly\")\n        self.rec_drive.set(\"C:\\\\\")\n        self.rec_drive.pack(side=\"left\", padx=4)\n        tk.Label(row_inputs, text=\"File Types:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\", padx=(8, 4))\n        self.rec_ext = tk.Entry(row_inputs, width=30, font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"],\n                                insertbackground=C[\"text\"])\n        self.rec_ext.insert(0, \"jpg,png,pdf,docx\")\n        self.rec_ext.pack(side=\"left\", padx=4)\n        tk.Label(row_inputs, text=\"Quick:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\", padx=(8, 2))\n        for label, exts in [(\"Photos\", \"jpg,jpeg,png,bmp,gif\"), (\"Docs\", \"pdf,docx,xlsx,pptx,txt\"),\n                            (\"Videos\", \"mp4,avi,mkv,mov\"), (\"All\", \"jpg,png,pdf,docx,mp4,xlsx\")]:\n            tk.Button(row_inputs, text=label, font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text_dim\"],\n                      bd=0, padx=6, pady=2, cursor=\"hand2\",\n                      command=lambda e=exts: (self.rec_ext.delete(0, \"end\"), self.rec_ext.insert(0, e))).pack(side=\"left\", padx=2)\n\n        row_actions = tk.Frame(zone_a, bg=C[\"card\"])\n        row_actions.pack(fill=\"x\", padx=8, pady=(4, 4))\n        tk.Button(row_actions, text=\"\ud83d\udd0d Search Drive\",\n                  font=(\"Segoe UI\", 10, \"bold\"), bg=C[\"accent2\"], fg=\"#000\",\n                  bd=0, padx=16, pady=6, cursor=\"hand2\",\n                  command=self._start_file_recovery).pack(side=\"left\", padx=4)\n        self._rec_stop_btn = tk.Button(row_actions, text=\"\u23f9 Stop\", font=FONTS[\"body\"],\n            bg=C[\"btn_danger\"], fg=C[\"text\"], bd=0, padx=10, pady=5,\n            cursor=\"hand2\", state=\"disabled\", command=self._stop_file_recovery)\n        self._rec_stop_btn.pack(side=\"left\", padx=4)\n        self._rec_pause_btn = tk.Button(row_actions, text=\"\u23f8 Pause\", font=FONTS[\"body\"],\n            bg=C[\"btn_warn\"], fg=C[\"text\"], bd=0, padx=10, pady=5,\n            cursor=\"hand2\", state=\"disabled\", command=self._pause_resume_file_recovery)\n        self._rec_pause_btn.pack(side=\"left\", padx=4)\n\n        row_android = tk.Frame(zone_a, bg=C[\"card\"])\n        row_android.pack(fill=\"x\", padx=8, pady=(0, 8))\n        tk.Label(row_android, text=\"\ud83d\udcf1 Android:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\", padx=(0, 6))\n        tk.Button(row_android, text=\"DCIM Photos Backup\", font=FONTS[\"small\"],\n                  bg=C[\"btn_chip\"], fg=C[\"text\"], bd=0, padx=10, pady=4, cursor=\"hand2\",\n                  command=lambda: self._android_media_preset(\"dcim\")).pack(side=\"left\", padx=3)\n        tk.Button(row_android, text=\"WhatsApp Media\", font=FONTS[\"small\"],\n                  bg=C[\"btn_chip\"], fg=C[\"text\"], bd=0, padx=10, pady=4, cursor=\"hand2\",\n                  command=lambda: self._android_media_preset(\"whatsapp\")).pack(side=\"left\", padx=3)\n        self.adb_status_label = tk.Label(row_android, text=\"ADB Status: Checking...\",\n                                         font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"])\n        self.adb_status_label.pack(side=\"right\", padx=8)\n        tk.Button(row_android, text=\"ADB Refresh\", font=FONTS[\"small\"],\n                  bg=C[\"btn\"], fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=self._refresh_adb_status_label).pack(side=\"right\", padx=3)\n        self.after(150, self._refresh_adb_status_label)\n\n        zone_b = tk.Frame(frame_scroll, bg=C[\"card\"], highlightbackground=C[\"warning\"], highlightthickness=2)\n        zone_b.pack(fill=\"x\", padx=16, pady=(0, 6))\n        tk.Label(zone_b, text=\"\u26a1 Zone B \u2014 Recover Deleted Files (Admin Required)\",\n                 font=FONTS[\"subhead\"], fg=C[\"warning\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=12, pady=(8, 2))\n        tk.Label(zone_b,\n                 text=\"Disk ke sectors seedha scan karta hai. Formatted ya deleted files wapas la sakta hai.\\n\"\n                      \"Admin rights mandatory hain. Recovered data ALAG drive pe save karo.\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\").pack(anchor=\"w\", padx=12, pady=(0, 6))\n\n        row_source = tk.Frame(zone_b, bg=C[\"card\"])\n        row_source.pack(fill=\"x\", padx=8, pady=(0, 4))\n        tk.Label(row_source, text=\"Raw Source:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\", padx=4)\n        raw_values = [DEFAULT_RAW_DISK] + [\"\\\\\\\\.\\\\\" + d + \":\" for d in \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\" if os.path.exists(d + \":\\\\\")]\n        self.raw_disk_var = tk.StringVar(value=DEFAULT_RAW_DISK)\n        self.raw_disk_combo = ttk.Combobox(row_source, values=raw_values, textvariable=self.raw_disk_var, width=22, font=FONTS[\"body\"], state=\"readonly\")\n        self.raw_disk_combo.pack(side=\"left\", padx=4)\n        self.raw_source_badge = tk.Label(row_source, text=\"RAW DEVICE\", font=FONTS[\"small\"], fg=C[\"warning\"], bg=C[\"card\"])\n        self.raw_source_badge.pack(side=\"left\", padx=6)\n        self.raw_disk_combo.bind(\"&lt;&gt;\", lambda e: self._update_raw_source_badge())\n        self.raw_disk_combo.bind(\"\", lambda e: self._update_raw_source_badge())\n        tk.Label(row_source, text=\"Scan MB (0=Full):\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\", padx=(8, 2))\n        self.raw_scan_mb = tk.Entry(row_source, width=6, font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"])\n        self.raw_scan_mb.insert(0, \"0\")\n        self.raw_scan_mb.pack(side=\"left\", padx=2)\n        tk.Label(row_source, text=\"Start Sector:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\", padx=(8, 2))\n        self.raw_sector_num = tk.Entry(row_source, width=8, font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"])\n        self.raw_sector_num.insert(0, \"0\")\n        self.raw_sector_num.pack(side=\"left\", padx=2)\n\n        row_primary = tk.Frame(zone_b, bg=C[\"card\"])\n        row_primary.pack(fill=\"x\", padx=8, pady=(4, 2))\n        for label, color, cmd in [\n            (\"\u2705 AUTO Recovery (Recommended)\", C[\"accent2\"], self._start_auto_raw_recovery),\n            (\"\u26a1 Raw Signature Scan\", C[\"btn_danger\"], self._start_raw_signature_scan),\n            (\"\ud83d\udd0e PhotoRec Deep Scan\", C[\"btn_hw\"], self._start_photorec_deep_scan),\n        ]:\n            tk.Button(row_primary, text=label, font=FONTS[\"small\"], bg=color,\n                      fg=C[\"bg\"] if color == C[\"accent2\"] else C[\"text\"],\n                      bd=0, padx=12, pady=6, cursor=\"hand2\", command=cmd).pack(side=\"left\", padx=3, pady=2)\n\n        tk.Label(zone_b, text=\"Advanced forensic tools:\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=12, pady=(4, 0))\n        row_advanced = tk.Frame(zone_b, bg=C[\"card\"])\n        row_advanced.pack(fill=\"x\", padx=8, pady=(2, 8))\n        for label, color, cmd in [\n            (\"DMDE\", C[\"btn_info\"], self._start_dmde_recovery),\n            (\"Create IMG\", C[\"btn_warn\"], self._create_img_dialog),\n            (\"Import IMG\", C[\"btn_info\"], self._select_img_source),\n            (\"Hex Viewer\", C[\"btn_chip\"], self._show_raw_hex_dialog),\n            (\"Shadow Copies\", C[\"accent2\"], self._shadow_copy_recovery_report),\n            (\"Hash+Verify\", C[\"btn_warn\"], self._forensic_hash_verify_dialog),\n            (\"Session Save\", C[\"btn_chip\"], self._recovery_session_db_save),\n        ]:\n            tk.Button(row_advanced, text=label, font=FONTS[\"small\"], bg=color, fg=C[\"text\"],\n                      bd=0, padx=8, pady=4, cursor=\"hand2\", command=cmd).pack(side=\"left\", padx=3, pady=2)\n\n        prog = tk.Frame(frame_scroll, bg=C[\"card\"], highlightbackground=C[\"border\"], highlightthickness=1)\n        prog.pack(fill=\"x\", padx=16, pady=(0, 6))\n        self.scan_mode_label = tk.Label(prog, text=\"Mode: \u2014\",\n            font=FONTS[\"small\"], fg=C[\"accent4\"], bg=C[\"card\"])\n        self.scan_mode_label.pack(fill=\"x\", padx=12, pady=(10, 2))\n        self.raw_progress_label = tk.Label(prog, text=\"Ready \u2014 scan shuru karo\",\n                                           font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], anchor=\"w\")\n        self.raw_progress_label.pack(fill=\"x\", padx=12, pady=(0, 2))\n        self.hdd_resource_delta_lbl = tk.Label(prog, text=\"Memory Delta: --\",\n                                               font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], anchor=\"w\")\n        self.hdd_resource_delta_lbl.pack(fill=\"x\", padx=12, pady=(0, 2))\n        self.raw_progress_var = tk.DoubleVar(value=0)\n        self.raw_progress_bar = ttk.Progressbar(prog, variable=self.raw_progress_var, maximum=100, mode=\"determinate\")\n        self.raw_progress_bar.pack(fill=\"x\", padx=12, pady=(0, 4))\n        self.raw_progress_log = scrolledtext.ScrolledText(prog, height=5, font=FONTS[\"mono\"],\n                                                           bg=C[\"bg\"], fg=C[\"text\"],\n                                                           insertbackground=C[\"text\"], wrap=\"word\",\n                                                           state=\"disabled\", bd=0)\n        self.raw_progress_log.pack(fill=\"x\", padx=12, pady=(0, 4))\n        prog_btns = tk.Frame(prog, bg=C[\"card\"])\n        prog_btns.pack(fill=\"x\", padx=12, pady=(0, 10))\n        tk.Button(prog_btns, text=\"\ud83d\uddd1 Clear Log\", font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text_dim\"],\n                  bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=self._clear_recovery_progress_log).pack(side=\"left\")\n\n        results_outer = tk.Frame(frame_scroll, bg=C[\"card\"], highlightbackground=C[\"border\"], highlightthickness=1)\n        results_outer.pack(fill=\"x\", padx=16, pady=(0, 10))\n        results_hdr = tk.Frame(results_outer, bg=C[\"card\"])\n        results_hdr.pack(fill=\"x\", padx=12, pady=(10, 4))\n        tk.Label(results_hdr, text=\"\u2463 Milne wali / Recovered files:\",\n                 font=FONTS[\"small\"], fg=C[\"accent2\"], bg=C[\"card\"]).pack(side=\"left\")\n        self.rec_stats_label = tk.Label(results_hdr, text=\"0 files found | 0 selected\",\n            font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"])\n        self.rec_stats_label.pack(side=\"right\")\n\n        tree_wrap = tk.Frame(results_outer, bg=C[\"card\"])\n        tree_wrap.pack(fill=\"both\", expand=True, padx=12, pady=(0, 4))\n        rec_cols = (\"Filename\", \"Type\", \"Size\", \"Status\", \"Location\", \"Integrity\")\n        col_heads = (\"File Name\", \"Type\", \"Size\", \"Status\", \"Location / Sector\", \"Integrity\")\n        self.rec_tree = ttk.Treeview(tree_wrap, columns=rec_cols, show=\"headings\", height=14, style=\"Custom.Treeview\")\n        for col, head, w in zip(rec_cols, col_heads, (230, 55, 90, 145, 230, 75)):\n            self.rec_tree.heading(col, text=head)\n            self.rec_tree.column(col, width=w, anchor=\"w\")\n        self.rec_tree.tag_configure(\"recovered\", foreground=C[\"success\"])\n        self.rec_tree.tag_configure(\"partial\", foreground=C[\"warning\"])\n        self.rec_tree.tag_configure(\"found\", foreground=C[\"text\"])\n        yscroll = ttk.Scrollbar(tree_wrap, orient=\"vertical\", command=self.rec_tree.yview)\n        xscroll = ttk.Scrollbar(tree_wrap, orient=\"horizontal\", command=self.rec_tree.xview)\n        self.rec_tree.configure(yscrollcommand=yscroll.set, xscrollcommand=xscroll.set)\n        self.rec_tree.grid(row=0, column=0, sticky=\"nsew\")\n        yscroll.grid(row=0, column=1, sticky=\"ns\")\n        xscroll.grid(row=1, column=0, sticky=\"ew\")\n        tree_wrap.grid_rowconfigure(0, weight=1)\n        tree_wrap.grid_columnconfigure(0, weight=1)\n        self.rec_tree.bind(\"&lt;&gt;\", self._on_rec_select)\n\n        results_bar = tk.Frame(results_outer, bg=C[\"card\"])\n        results_bar.pack(fill=\"x\", padx=12, pady=(0, 10))\n        self._rec_recover_btn = tk.Button(results_bar, text=\"\ud83d\udcbe Recover Selected\",\n                  font=FONTS[\"body\"], bg=C[\"btn_info\"], fg=C[\"text\"],\n                  bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=self._recover_selected_files)\n        self._rec_recover_btn.pack(side=\"left\", padx=(0, 8))\n        tk.Button(results_bar, text=\"\ud83d\udccb Select All\", font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text\"],\n                  bd=0, padx=10, pady=5, cursor=\"hand2\",\n                  command=lambda: self.rec_tree.selection_set(self.rec_tree.get_children())).pack(side=\"left\", padx=(0, 8))\n        tk.Button(results_bar, text=\"\ud83d\uddd1 Clear List\", font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text_dim\"],\n                  bd=0, padx=10, pady=5, cursor=\"hand2\",\n                  command=self._clear_recovery_results).pack(side=\"left\")\n\n        self.rec_found_files = {}\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # \u2500\u2500 ZONE C \u2500\u2500 Batch Integrity Verifier (NEW FEATURE #1) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        # Real SHA256 hash computation on recovered/existing files.\n        # Runs fully in background thread, 0 fake logic, real OS file reads.\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        zone_c = tk.Frame(frame_scroll, bg=C[\"card\"],\n                          highlightbackground=C.get(\"accent4\", \"#9b59b6\"),\n                          highlightthickness=2)\n        zone_c.pack(fill=\"x\", padx=16, pady=(0, 6))\n        tk.Label(zone_c, text=\"\ud83d\udd10 Zone C \u2014 Batch Integrity Verifier  (SHA256 real-time)\",\n                 font=FONTS[\"subhead\"], fg=C.get(\"accent4\", \"#9b59b6\"), bg=C[\"card\"]\n                 ).pack(anchor=\"w\", padx=12, pady=(8, 2))\n        tk.Label(zone_c,\n                 text=\"Recovered ya kisi bhi folder ki files ko real SHA256 hash se verify karta hai.\\n\"\n                      \"Corrupt / 0-byte / truncated files automatically flag ho jaate hain.\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\"\n                 ).pack(anchor=\"w\", padx=12, pady=(0, 6))\n\n        zc_row1 = tk.Frame(zone_c, bg=C[\"card\"]); zc_row1.pack(fill=\"x\", padx=8, pady=4)\n        tk.Label(zc_row1, text=\"Folder:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(side=\"left\", padx=(0,4))\n        self._integ_dir_var = tk.StringVar()\n        tk.Entry(zc_row1, textvariable=self._integ_dir_var, width=42,\n                 font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"],\n                 insertbackground=C[\"text\"]).pack(side=\"left\", padx=4)\n        tk.Button(zc_row1, text=\"\ud83d\udcc1 Browse\", font=FONTS[\"small\"],\n                  bg=C[\"panel\"], fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=lambda: self._integ_dir_var.set(\n                      filedialog.askdirectory(title=\"Verify karne ka folder\")\n                  )).pack(side=\"left\", padx=4)\n        tk.Button(zc_row1, text=\"\ud83d\udcc2 Use Recovery Dest\", font=FONTS[\"small\"],\n                  bg=C[\"btn_chip\"], fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=lambda: self._integ_use_rec_dest()).pack(side=\"left\", padx=4)\n\n        zc_row2 = tk.Frame(zone_c, bg=C[\"card\"]); zc_row2.pack(fill=\"x\", padx=8, pady=(0,4))\n        self._integ_recurse_var = tk.BooleanVar(value=True)\n        tk.Checkbutton(zc_row2, text=\"Subfolders include\", variable=self._integ_recurse_var,\n                       font=FONTS[\"small\"], bg=C[\"card\"], fg=C[\"text\"],\n                       selectcolor=C[\"bg\"], activebackground=C[\"card\"]).pack(side=\"left\", padx=4)\n        self._integ_export_var = tk.BooleanVar(value=True)\n        tk.Checkbutton(zc_row2, text=\"CSV report export\", variable=self._integ_export_var,\n                       font=FONTS[\"small\"], bg=C[\"card\"], fg=C[\"text\"],\n                       selectcolor=C[\"bg\"], activebackground=C[\"card\"]).pack(side=\"left\", padx=4)\n\n        zc_stats_row = tk.Frame(zone_c, bg=C[\"card\"]); zc_stats_row.pack(fill=\"x\", padx=8)\n        self._integ_stat_lbl = tk.Label(zc_stats_row, text=\"\u2014 Ready \u2014\",\n                                        font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], anchor=\"w\")\n        self._integ_stat_lbl.pack(side=\"left\", fill=\"x\", expand=True)\n        self._integ_prog_var = tk.DoubleVar(value=0)\n        zc_pb = ttk.Progressbar(zone_c, variable=self._integ_prog_var, maximum=100, mode=\"determinate\")\n        zc_pb.pack(fill=\"x\", padx=12, pady=(2, 2))\n        self._integ_prog_bar = zc_pb\n\n        # Scrollable log sub-frame inside Zone C (Phase 2 requirement)\n        self._integ_log = scrolledtext.ScrolledText(zone_c, height=4, font=FONTS[\"mono\"],\n                                                    bg=C[\"bg\"], fg=C[\"text\"],\n                                                    insertbackground=C[\"text\"], wrap=\"word\",\n                                                    state=\"disabled\", bd=0)\n        self._integ_log.pack(fill=\"x\", padx=12, pady=(0, 4))\n\n        zc_btn_row = tk.Frame(zone_c, bg=C[\"card\"]); zc_btn_row.pack(fill=\"x\", padx=8, pady=(0,8))\n        self._integ_run_btn = tk.Button(\n            zc_btn_row, text=\"\ud83d\udd10 Run Integrity Check\",\n            font=(\"Segoe UI\", 10, \"bold\"),\n            bg=C.get(\"accent4\", \"#9b59b6\"), fg=C[\"text\"],\n            bd=0, padx=16, pady=6, cursor=\"hand2\",\n            command=self._start_integrity_verifier)\n        self._integ_run_btn.pack(side=\"left\", padx=4)\n        tk.Button(zc_btn_row, text=\"\ud83d\uddd1 Clear Log\", font=FONTS[\"small\"],\n                  bg=C[\"panel\"], fg=C[\"text_dim\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=lambda: (\n                      self._integ_log.config(state=\"normal\"),\n                      self._integ_log.delete(\"1.0\", \"end\"),\n                      self._integ_log.config(state=\"disabled\"),\n                      self._integ_stat_lbl.config(text=\"\u2014 Cleared \u2014\"),\n                      self._integ_prog_var.set(0),\n                  )).pack(side=\"left\", padx=4)\n\n        return frame\n\n    def _build_recovery_fixed(self, parent):\n        return self._build_recovery_safe(parent)\n\n    def _show_rescue_center(self):\n        try:\n            self._launch_job(\"refresh_rescue_status\", self._refresh_rescue_dashboard_status)\n        except Exception:\n            pass\n\n    def _build_rescue_recovery_center(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(\n            frame,\n            \"\ud83d\udea8 RESCUE &amp; RECOVERY CENTER\",\n            \"Technician-grade Windows rescue workspace with diagnostics, boot repair, media creation and restore safety.\",\n        )\n        tk.Label(frame, text=\"Designed for professional recovery workflows: WinRE checks, boot diagnostics, BitLocker visibility and restore point tracking.\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"], justify=\"left\").pack(fill=\"x\", padx=16, pady=(0, 6))\n\n        notebook = ttk.Notebook(frame)\n        notebook.pack(fill=\"both\", expand=True, padx=16, pady=(4, 12))\n        tabs = [\n            (\"Recovery Dashboard\", self._build_rescue_dashboard_tab),\n            (\"Windows Recovery\", self._build_windows_recovery_tab),\n            (\"Boot Repair\", self._build_boot_repair_tab),\n            (\"Rescue Media\", self._build_rescue_media_creator_tab),\n            (\"Offline Tools\", self._build_offline_recovery_tools_tab),\n            (\"Password Assistant\", self._build_password_recovery_assistant_tab),\n            (\"Recovery Console\", self._build_advanced_recovery_console_tab),\n            (\"Technician Toolkit\", self._build_technician_toolkit_tab),\n        ]\n        for title, builder in tabs:\n            tab = tk.Frame(notebook, bg=C[\"bg\"])\n            notebook.add(tab, text=title)\n            builder(tab)\n\n        self.after(200, self._show_rescue_center)\n        return frame\n\n    def _build_rescue_dashboard_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        status_frame = tk.Frame(body, bg=C[\"card\"])\n        status_frame.pack(fill=\"x\", padx=14, pady=10)\n\n        self.rescue_winre_status = tk.StringVar(value=\"Unknown\")\n        self.rescue_bitlocker_status = tk.StringVar(value=\"Unknown\")\n        self.rescue_restore_status = tk.StringVar(value=\"Unknown\")\n        self.rescue_readiness_status = tk.StringVar(value=\"Pending\")\n        self.rescue_last_sync = tk.StringVar(value=\"Never\")\n\n        for title, var, color in [\n            (\"WinRE Status\", self.rescue_winre_status, C[\"accent\"]),\n            (\"BitLocker Status\", self.rescue_bitlocker_status, C[\"warning\"]),\n            (\"Restore Point\", self.rescue_restore_status, C[\"success\"]),\n            (\"Recovery Readiness\", self.rescue_readiness_status, C[\"accent4\"]),\n            (\"Last Refresh\", self.rescue_last_sync, C[\"text_dim\"]),\n        ]:\n            card = tk.Frame(status_frame, bg=C[\"bg\"], bd=1, relief=\"solid\")\n            card.pack(side=\"left\", expand=True, fill=\"x\", padx=6, pady=6)\n            tk.Label(card, text=title, font=FONTS[\"small\"], fg=color, bg=C[\"bg\"]).pack(anchor=\"w\", padx=8, pady=(8, 2))\n            tk.Label(card, textvariable=var, font=FONTS[\"body\"], fg=C[\"text\"], bg=C[\"bg\"]).pack(anchor=\"w\", padx=8, pady=(0, 8))\n\n        tk.Label(body, text=\"Visible help: Refresh status and create a restore point before risky recovery actions.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=900, justify=\"left\").pack(fill=\"x\", padx=14, pady=(0, 8))\n        btn_row = tk.Frame(body, bg=C[\"bg\"])\n        btn_row.pack(fill=\"x\", padx=14, pady=(0, 10))\n        refresh_btn = tk.Button(btn_row, text=\"\ud83d\udd04 Refresh Dashboard\", font=FONTS[\"small\"], bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=12, pady=8, cursor=\"hand2\",\n              command=lambda: self._launch_job(\"refresh_rescue_status\", self._refresh_rescue_dashboard_status))\n        refresh_btn.pack(side=\"left\", padx=4)\n        self._create_tooltip(refresh_btn, \"Refresh Rescue Dashboard status, WinRE and restore point readiness before running recovery actions.\")\n        restore_btn = tk.Button(btn_row, text=\"\ud83d\udee1 Create Restore Point\", font=FONTS[\"small\"], bg=C[\"btn_hw\"], fg=C[\"text\"], bd=0, padx=12, pady=8, cursor=\"hand2\",\n              command=lambda: self._confirm_and_launch_job(\"Create Restore Point\", \"Create a verified restore point before critical recovery actions.\", None, \"restore_point_rescue\", self._collect_restore_point))\n        restore_btn.pack(side=\"left\", padx=4)\n        self._create_tooltip(restore_btn, \"Create a Windows restore point so you can roll back system changes if recovery actions cause issues.\")\n\n        history_frame = tk.LabelFrame(body, text=\"Recent Rescue Actions &amp; Restore Points\", font=FONTS[\"subhead\"], fg=C[\"accent2\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        history_frame.pack(fill=\"both\", expand=True, padx=14, pady=(0, 10))\n        self.rescue_history_tree = ttk.Treeview(history_frame, columns=(\"ts\", \"event\", \"detail\"), show=\"headings\", height=8, style=\"Custom.Treeview\")\n        for col, width in [(\"ts\", 160), (\"event\", 220), (\"detail\", 420)]:\n            self.rescue_history_tree.heading(col, text=col.title())\n            self.rescue_history_tree.column(col, width=width, anchor=\"w\")\n        self.rescue_history_tree.pack(fill=\"both\", expand=True, padx=8, pady=8)\n        return body\n\n    def _build_windows_recovery_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        lead = tk.Label(body, text=\"WinRE inspection, repair and readiness validation.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\")\n        lead.pack(fill=\"x\", padx=14, pady=(10, 8))\n        tk.Label(body, text=\"Visible help: Check WinRE first; repair only if WinRE is disabled or broken.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=900, justify=\"left\").pack(fill=\"x\", padx=14, pady=(0, 10))\n\n        self.winre_info_text = self._scrolled_text(body, height=14)\n        winre_check_btn = tk.Button(body, text=\"\ud83d\udd0d Check WinRE Status\", font=FONTS[\"small\"], bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=14, pady=8, cursor=\"hand2\",\n              command=lambda: self._confirm_and_launch_job(\"Check WinRE Status\", \"Inspect the Windows Recovery Environment.\", None, \"winre_status\", self._run_winre_status))\n        winre_check_btn.pack(pady=(0, 6), padx=14, anchor=\"w\")\n        self._create_tooltip(winre_check_btn, \"Check whether Windows Recovery Environment is enabled and correctly configured.\")\n        winre_repair_btn = tk.Button(body, text=\"\u2699 Repair WinRE\", font=FONTS[\"small\"], bg=C[\"btn_warn\"], fg=C[\"text\"], bd=0, padx=14, pady=8, cursor=\"hand2\",\n              command=lambda: self._confirm_and_launch_job(\"Repair WinRE\", \"Repair or enable Windows Recovery Environment.\", None, \"winre_repair\", self._run_winre_repair))\n        winre_repair_btn.pack(pady=(0, 14), padx=14, anchor=\"w\")\n        self._create_tooltip(winre_repair_btn, \"Repair or enable WinRE. Only use this if WinRE is missing or broken.\")\n        return body\n\n    def _build_boot_repair_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        desc = tk.Label(body, text=\"Boot diagnostics, BCD recovery and bootloader repair.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\")\n        desc.pack(fill=\"x\", padx=14, pady=(10, 8))\n        tk.Label(body, text=\"Visible help: Collect diagnostics first; repair MBR or rebuild BCD only if diagnostics indicate corruption.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=900, justify=\"left\").pack(fill=\"x\", padx=14, pady=(0, 10))\n        self.boot_repair_log = self._scrolled_text(body, height=16)\n\n        actions = tk.Frame(body, bg=C[\"card\"])\n        actions.pack(fill=\"x\", padx=14, pady=(10, 6))\n        for label, title, target, tip in [\n            (\"\ud83d\udd0d\", \"Collect Boot Diagnostics\", self._run_boot_diagnostics, \"Collect BCD and boot diagnostics to inspect startup configuration without making changes.\"),\n            (\"\ud83d\udee0\", \"Fix MBR\", self._run_boot_fix_mbr, \"Repair the Master Boot Record. Use only when diagnostics indicate MBR corruption.\"),\n            (\"\ud83e\udde9\", \"Rebuild BCD\", self._run_boot_rebuild_bcd, \"Rebuild the Boot Configuration Data store for Windows startup recovery.\"),\n        ]:\n            btn = tk.Button(actions, text=f\"{label} {title}\", font=FONTS[\"small\"], bg=C[\"btn_chip\"], fg=C[\"text\"], bd=0, padx=12, pady=8, cursor=\"hand2\",\n                      command=lambda t=target, n=title: self._confirm_and_launch_job(n, f\"{title} will perform safe boot diagnostics or repair.\", None, f\"boot_{title.replace(' ', '_').lower()}\", t))\n            btn.pack(side=\"left\", padx=4)\n            self._create_tooltip(btn, tip)\n        return body\n\n    def _build_rescue_media_creator_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        tk.Label(body, text=\"Rescue media readiness and removable drive validation.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\").pack(fill=\"x\", padx=14, pady=(10, 8))\n        tk.Label(body, text=\"Visible help: Probe removable drives and validate your target before building a rescue USB.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=900, justify=\"left\").pack(fill=\"x\", padx=14, pady=(0, 10))\n        self.rescue_media_status = self._scrolled_text(body, height=16)\n        probe_btn = tk.Button(body, text=\"\ud83d\udce6 Probe Rescue Media\", font=FONTS[\"small\"], bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=14, pady=8, cursor=\"hand2\",\n              command=lambda: self._confirm_and_launch_job(\"Probe Rescue Media\", \"Scan for removable rescue media targets.\", None, \"probe_rescue_media\", self._run_probe_rescue_media))\n        probe_btn.pack(pady=(0, 6), padx=14, anchor=\"w\")\n        self._create_tooltip(probe_btn, \"Scan removable drives and rescue media readiness before creating or using a bootable USB.\")\n        build_btn = tk.Button(body, text=\"\ud83d\udcbf Build Rescue USB\", font=FONTS[\"small\"], bg=C[\"btn_hw\"], fg=C[\"text\"], bd=0, padx=14, pady=8, cursor=\"hand2\",\n              command=lambda: self._confirm_and_launch_job(\"Build Rescue USB\", \"Create a rescue USB if WinPE tools are available.\", None, \"build_rescue_media\", self._run_build_rescue_media))\n        build_btn.pack(pady=(0, 14), padx=14, anchor=\"w\")\n        self._create_tooltip(build_btn, \"Create a rescue USB drive for offline repair when the system cannot boot.\")\n        return body\n\n    def _build_offline_recovery_tools_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        tk.Label(body, text=\"Offline recovery diagnostics without changing system state.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\").pack(fill=\"x\", padx=14, pady=(10, 8))\n        tk.Label(body, text=\"Visible help: Use offline captures to preserve evidence; avoid writing to the live system.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=900, justify=\"left\").pack(fill=\"x\", padx=14, pady=(0, 10))\n        self.offline_recovery_log = self._scrolled_text(body, height=16)\n        actions = tk.Frame(body, bg=C[\"card\"])\n        actions.pack(fill=\"x\", padx=14, pady=(0, 10))\n        for title, target, tip in [\n            (\"Capture Offline Snapshot\", self._run_offline_snapshot, \"Collect offline snapshot metadata for safe recovery investigations without changing live system state.\"),\n            (\"Collect Offline Registry\", self._run_offline_registry_collect, \"Export SYSTEM registry data for offline recovery analysis and evidence preservation.\"),\n        ]:\n            btn = tk.Button(actions, text=title, font=FONTS[\"small\"], bg=C[\"btn_chip\"], fg=C[\"text\"], bd=0, padx=12, pady=8, cursor=\"hand2\",\n                      command=lambda t=target, n=title: self._confirm_and_launch_job(n, f\"{title} will gather offline recovery artifacts.\", None, f\"offline_{title.replace(' ', '_').lower()}\", t))\n            btn.pack(side=\"left\", padx=4)\n            self._create_tooltip(btn, tip)\n        return body\n\n    def _build_password_recovery_assistant_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        tk.Label(body, text=\"Account diagnostics, SAM backup and BitLocker insight.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\").pack(fill=\"x\", padx=14, pady=(10, 8))\n        tk.Label(body, text=\"Visible help: Collect account and encryption diagnostics before performing password recovery.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=900, justify=\"left\").pack(fill=\"x\", padx=14, pady=(0, 10))\n        self.password_recovery_log = self._scrolled_text(body, height=16)\n        actions = tk.Frame(body, bg=C[\"card\"])\n        actions.pack(fill=\"x\", padx=14, pady=(0, 10))\n        for title, target, tip in [\n            (\"Account Diagnostics\", self._run_account_diagnostics, \"Inspect local user accounts and password recovery options for troubleshooting locked systems.\"),\n            (\"SAM + SYSTEM Backup\", self._run_sam_system_backup, \"Backup SAM and SYSTEM registry hives for password recovery and forensic analysis.\"),\n            (\"BitLocker Info\", self._run_bitlocker_info, \"View BitLocker encryption status for the system drive before recovery operations.\"),\n        ]:\n            btn = tk.Button(actions, text=title, font=FONTS[\"small\"], bg=C[\"btn_chip\"], fg=C[\"text\"], bd=0, padx=12, pady=8, cursor=\"hand2\",\n                      command=lambda t=target, n=title: self._confirm_and_launch_job(n, f\"{title} will gather recovery-sensitive diagnostics.\", None, f\"password_{title.replace(' ', '_').lower()}\", t))\n            btn.pack(side=\"left\", padx=4)\n            self._create_tooltip(btn, tip)\n        return body\n\n    def _build_advanced_recovery_console_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        tk.Label(body, text=\"Recovery console diagnostics, BCD dump and event correlation.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\").pack(fill=\"x\", padx=14, pady=(10, 8))\n        tk.Label(body, text=\"Visible help: Collect configuration and event diagnostics before making low-level recovery changes.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=900, justify=\"left\").pack(fill=\"x\", padx=14, pady=(0, 10))\n        self.recovery_console_log = self._scrolled_text(body, height=16)\n        actions = tk.Frame(body, bg=C[\"card\"])\n        actions.pack(fill=\"x\", padx=14, pady=(0, 10))\n        for title, target, tip in [\n            (\"Dump BCD Configuration\", self._run_bcd_dump, \"Export current BCD configuration for diagnostics before making boot repairs.\"),\n            (\"Collect Event Correlation\", self._run_event_correlation, \"Collect event logs to correlate boot and system errors during recovery.\"),\n            (\"Open Recovery Shell\", self._run_recovery_shell, \"Open a safe recovery shell capture for low-level troubleshooting.\"),\n        ]:\n            btn = tk.Button(actions, text=title, font=FONTS[\"small\"], bg=C[\"btn_chip\"], fg=C[\"text\"], bd=0, padx=12, pady=8, cursor=\"hand2\",\n                      command=lambda t=target, n=title: self._confirm_and_launch_job(n, f\"{title} will collect recovery console diagnostics.\", None, f\"console_{title.replace(' ', '_').lower()}\", t))\n            btn.pack(side=\"left\", padx=4)\n            self._create_tooltip(btn, tip)\n        return body\n\n    def _build_technician_toolkit_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        tk.Label(body, text=\"Technician tools for health checks, log capture and readiness validation.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\").pack(fill=\"x\", padx=14, pady=(10, 8))\n        tk.Label(body, text=\"Visible help: Run health checks and validate restore points before attempting repairs.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=900, justify=\"left\").pack(fill=\"x\", padx=14, pady=(0, 10))\n        self.technician_toolkit_log = self._scrolled_text(body, height=16)\n        actions = tk.Frame(body, bg=C[\"card\"])\n        actions.pack(fill=\"x\", padx=14, pady=(0, 10))\n        for title, target, tip in [\n            (\"Run Health Check\", self._run_technician_health_check, \"Run a system health check to gather recovery readiness diagnostics.\"),\n            (\"Collect System Logs\", self._run_collect_system_logs, \"Collect system event logs for technician troubleshooting.\"),\n            (\"Validate Recovery Readiness\", self._run_recovery_readiness_check, \"Check restore point and recovery safety readiness before repair actions.\"),\n        ]:\n            btn = tk.Button(actions, text=title, font=FONTS[\"small\"], bg=C[\"btn_chip\"], fg=C[\"text\"], bd=0, padx=12, pady=8, cursor=\"hand2\",\n                      command=lambda t=target, n=title: self._confirm_and_launch_job(n, f\"{title} will inspect recovery readiness and capture diagnostics.\", None, f\"tech_{title.replace(' ', '_').lower()}\", t))\n            btn.pack(side=\"left\", padx=4)\n            self._create_tooltip(btn, tip)\n        return body\n\n    def _refresh_rescue_dashboard_status(self):\n        data = {\"winre\": \"Unavailable\", \"bitlocker\": \"Unavailable\", \"restore\": \"Unavailable\", \"readiness\": \"Pending\", \"restore_points\": []}\n        try:\n            out, rc = self._run_cmd(\"reagentc /info\", timeout=18)\n            data[\"winre\"] = out.strip() if rc == 0 else f\"Error ({rc})\"\n        except Exception as e:\n            data[\"winre\"] = f\"Failed: {e}\"\n        try:\n            out, rc = self._run_cmd(\"manage-bde -status C:\", timeout=20)\n            data[\"bitlocker\"] = out.strip() if rc == 0 else f\"Error ({rc})\"\n        except Exception as e:\n            data[\"bitlocker\"] = f\"Failed: {e}\"\n        try:\n            if hasattr(self, \"restore_point_manager\"):\n                recent = self.restore_point_manager.list_recent(3) or []\n                data[\"restore_points\"] = recent\n                data[\"restore\"] = f\"{len(recent)} recent restore point(s)\"\n        except Exception:\n            data[\"restore\"] = \"Failed to enumerate\"\n        try:\n            if any(not v for v in (data[\"winre\"], data[\"bitlocker\"], data[\"restore\"])):\n                data[\"readiness\"] = \"Attention required\"\n            else:\n                data[\"readiness\"] = \"Ready\"\n        except Exception:\n            data[\"readiness\"] = \"Partial\"\n        data[\"ts\"] = datetime.datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\")\n        self.after(0, lambda: self._apply_rescue_dashboard_data(data))\n\n    def _apply_rescue_dashboard_data(self, data):\n        try:\n            self.rescue_winre_status.set(data.get(\"winre\", \"Unknown\"))\n            self.rescue_bitlocker_status.set(data.get(\"bitlocker\", \"Unknown\"))\n            self.rescue_restore_status.set(data.get(\"restore\", \"Unknown\"))\n            self.rescue_readiness_status.set(data.get(\"readiness\", \"Pending\"))\n            self.rescue_last_sync.set(data.get(\"ts\", \"Never\"))\n            if hasattr(self, \"rescue_history_tree\"):\n                self.rescue_history_tree.delete(*self.rescue_history_tree.get_children())\n                for item in data.get(\"restore_points\", []):\n                    self.rescue_history_tree.insert(\"\", \"end\", values=(item.get(\"Created\"), item.get(\"Description\"), item.get(\"SequenceNumber\")))\n        except Exception:\n            pass\n\n    def _collect_restore_point(self):\n        try:\n            if getattr(self, \"change_coordinator\", None):\n                info = self.change_coordinator.create_restore_point(\"Rescue Center checkpoint\")\n                return {\"ok\": bool(info.get(\"ok\")), \"message\": \"Restore point created.\" if info.get(\"ok\") else \"Restore point failed.\"}\n            if getattr(self, \"restore_point_manager\", None):\n                ok = self.restore_point_manager.create(\"Rescue Center checkpoint\", force=True)\n                return {\"ok\": ok, \"message\": \"Restore point created.\" if ok else \"Restore point failed.\"}\n        except Exception as e:\n            return {\"ok\": False, \"message\": str(e)}\n        return {\"ok\": False, \"message\": \"No restore manager available.\"}\n\n    def _run_winre_status(self):\n        out, rc = self._run_cmd(\"reagentc /info\", timeout=18)\n        self._append_log(self.winre_info_text, out or f\"Command failed ({rc})\", C[\"text\"])\n\n    def _run_winre_repair(self):\n        out, rc = self._run_cmd(\"reagentc /enable\", timeout=30)\n        self._append_log(self.winre_info_text, out or f\"Command failed ({rc})\", C[\"success\"] if rc == 0 else C[\"error\"])\n        if getattr(self, \"structured_logger\", None):\n            self.structured_logger.event(\"recovery_center\", \"winre_repair\", rc=rc)\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.winre_repair\", {\"rc\": rc})\n\n    def _run_boot_diagnostics(self):\n        self._append_log(self.boot_repair_log, \"Collecting BCD and boot diagnostics...\", C[\"accent4\"])\n        out, rc = self._run_cmd(\"bcdedit /enum all\", timeout=25)\n        self._append_log(self.boot_repair_log, out or f\"Command failed ({rc})\", C[\"text\"])\n        out2, rc2 = self._run_cmd(\"bootrec /scanos\", timeout=25)\n        self._append_log(self.boot_repair_log, out2 or f\"Command failed ({rc2})\", C[\"text\"])\n        if getattr(self, \"structured_logger\", None):\n            self.structured_logger.event(\"recovery_center\", \"boot_diagnostics\", rc1=rc, rc2=rc2)\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.boot_diagnostics\", {\"rc1\": rc, \"rc2\": rc2})\n\n    def _run_boot_fix_mbr(self):\n        out, rc = self._run_cmd(\"bootrec /fixmbr\", timeout=30)\n        self._append_log(self.boot_repair_log, out or f\"Command failed ({rc})\", C[\"success\"] if rc == 0 else C[\"error\"])\n        if getattr(self, \"structured_logger\", None):\n            self.structured_logger.event(\"recovery_center\", \"boot_fix_mbr\", rc=rc)\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.boot_fix_mbr\", {\"rc\": rc})\n\n    def _run_boot_rebuild_bcd(self):\n        out, rc = self._run_cmd(\"bootrec /rebuildbcd\", timeout=40)\n        self._append_log(self.boot_repair_log, out or f\"Command failed ({rc})\", C[\"success\"] if rc == 0 else C[\"error\"])\n        if getattr(self, \"structured_logger\", None):\n            self.structured_logger.event(\"recovery_center\", \"boot_rebuild_bcd\", rc=rc)\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.boot_rebuild_bcd\", {\"rc\": rc})\n\n    def _run_probe_rescue_media(self):\n        self._append_log(self.rescue_media_status, \"Probing removable drives and rescue media readiness...\", C[\"accent4\"])\n        out, rc = self._run_cmd(\"powershell -NoProfile -Command \\\"Get-Disk | Where-Object MediaType -eq 'Removable' | Select Number,FriendlyName,Size | ConvertTo-Json\\\"\", timeout=25)\n        self._append_log(self.rescue_media_status, out or f\"Command failed ({rc})\", C[\"text\"])\n        if getattr(self, \"structured_logger\", None):\n            self.structured_logger.event(\"recovery_center\", \"probe_rescue_media\", rc=rc)\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.probe_rescue_media\", {\"rc\": rc})\n\n    def _run_build_rescue_media(self):\n        self._append_log(self.rescue_media_status, \"Attempting rescue media build...\", C[\"accent4\"])\n        out, rc = self._run_cmd(\"powershell -NoProfile -Command \\\"if (Get-Command copype -ErrorAction SilentlyContinue) { Write-Output 'WinPE toolchain available' } else { Write-Error 'WinPE toolchain not found' }\\\"\", timeout=20)\n        self._append_log(self.rescue_media_status, out or f\"Command failed ({rc})\", C[\"text\"])\n        if getattr(self, \"structured_logger\", None):\n            self.structured_logger.event(\"recovery_center\", \"build_rescue_media\", rc=rc)\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.build_rescue_media\", {\"rc\": rc})\n\n    def _run_offline_snapshot(self):\n        self._append_log(self.offline_recovery_log, \"Collecting offline snapshot metadata...\", C[\"accent4\"])\n        out, rc = self._run_cmd(\"powershell -NoProfile -Command \\\"Get-ComputerInfo | Select CsName,WindowsVersion,OsBuildNumber,WindowsInstallationType | ConvertTo-Json\\\"\", timeout=25)\n        self._append_log(self.offline_recovery_log, out or f\"Command failed ({rc})\", C[\"text\"])\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.offline_snapshot\", {\"rc\": rc})\n\n    def _run_offline_registry_collect(self):\n        self._append_log(self.offline_recovery_log, \"Collecting offline registry artifacts...\", C[\"accent4\"])\n        out, rc = self._run_cmd(\"reg save HKLM\\\\SYSTEM %TEMP%\\\\SYSTEM_hive_backup /y\", timeout=30)\n        self._append_log(self.offline_recovery_log, out or f\"Command failed ({rc})\", C[\"success\"] if rc == 0 else C[\"error\"])\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.offline_registry_collect\", {\"rc\": rc})\n\n    def _run_account_diagnostics(self):\n        self._append_log(self.password_recovery_log, \"Gathering account diagnostics...\", C[\"accent4\"])\n        out, rc = self._run_cmd(\"net user\", timeout=20)\n        self._append_log(self.password_recovery_log, out or f\"Command failed ({rc})\", C[\"text\"])\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.account_diagnostics\", {\"rc\": rc})\n\n    def _run_sam_system_backup(self):\n        self._append_log(self.password_recovery_log, \"Backing up SAM and SYSTEM hives...\", C[\"accent4\"])\n        backup_dir = os.path.join(os.environ.get(\"TEMP\", \"C:\\\\Temp\"), \"sam_backup\")\n        try:\n            os.makedirs(backup_dir, exist_ok=True)\n        except Exception:\n            pass\n        for hive in [\"SAM\", \"SYSTEM\"]:\n            out, rc = self._run_cmd(f\"reg save HKLM\\\\{hive} {backup_dir}\\\\{hive}.hiv /y\", timeout=30)\n            self._append_log(self.password_recovery_log, out or f\"{hive} save failed ({rc})\", C[\"success\"] if rc == 0 else C[\"error\"])\n            if getattr(self, \"telemetry_store\", None):\n                self.telemetry_store.append(\"recovery.sam_backup\", {\"hive\": hive, \"rc\": rc})\n        if getattr(self, \"structured_logger\", None):\n            self.structured_logger.event(\"recovery_center\", \"sam_system_backup\", path=backup_dir)\n\n    def _run_bitlocker_info(self):\n        self._append_log(self.password_recovery_log, \"Collecting BitLocker status...\", C[\"accent4\"])\n        out, rc = self._run_cmd(\"manage-bde -status C:\", timeout=20)\n        self._append_log(self.password_recovery_log, out or f\"Command failed ({rc})\", C[\"text\"])\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.bitlocker_info\", {\"rc\": rc})\n\n    def _run_bcd_dump(self):\n        self._append_log(self.recovery_console_log, \"Dumping BCD configuration...\", C[\"accent4\"])\n        out, rc = self._run_cmd(\"bcdedit /enum all\", timeout=30)\n        self._append_log(self.recovery_console_log, out or f\"Command failed ({rc})\", C[\"text\"])\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.bcd_dump\", {\"rc\": rc})\n\n    def _run_event_correlation(self):\n        self._append_log(self.recovery_console_log, \"Collecting event correlation data...\", C[\"accent4\"])\n        out, rc = self._run_cmd(\"wevtutil qe System /c:50 /f:text\", timeout=25)\n        self._append_log(self.recovery_console_log, out or f\"Command failed ({rc})\", C[\"text\"])\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.event_correlation\", {\"rc\": rc})\n\n    def _run_recovery_shell(self):\n        self._append_log(self.recovery_console_log, \"Launching safe recovery shell capture...\", C[\"accent4\"])\n        out, rc = self._run_cmd(\"cmd /c echo Recovery shell initialized\", timeout=10)\n        self._append_log(self.recovery_console_log, out or f\"Command failed ({rc})\", C[\"text\"])\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.recovery_shell\", {\"rc\": rc})\n\n    def _run_technician_health_check(self):\n        self._append_log(self.technician_toolkit_log, \"Running technician health check...\", C[\"accent4\"])\n        out, rc = self._run_cmd(\"systeminfo\", timeout=40)\n        self._append_log(self.technician_toolkit_log, out or f\"Command failed ({rc})\", C[\"text\"])\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.health_check\", {\"rc\": rc})\n\n    def _run_collect_system_logs(self):\n        self._append_log(self.technician_toolkit_log, \"Collecting system logs...\", C[\"accent4\"])\n        out, rc = self._run_cmd(\"wevtutil qe System /c:30 /f:text\", timeout=25)\n        self._append_log(self.technician_toolkit_log, out or f\"Command failed ({rc})\", C[\"text\"])\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.collect_system_logs\", {\"rc\": rc})\n\n    def _run_recovery_readiness_check(self):\n        self._append_log(self.technician_toolkit_log, \"Validating recovery readiness...\", C[\"accent4\"])\n        out, rc = self._run_cmd(\"reagentc /info\", timeout=18)\n        self._append_log(self.technician_toolkit_log, out or f\"Command failed ({rc})\", C[\"text\"])\n        if getattr(self, \"telemetry_store\", None):\n            self.telemetry_store.append(\"recovery.readiness_check\", {\"rc\": rc})\n\n    def _build_recovery_modern(self, parent):\n        return self._build_recovery_safe(parent)\n\n    def _on_recovery_task_update(self, task):\n        self._ui_queue.put((\"recovery_queue\", None))\n        self._ui_queue.put((\"recovery_refresh\", None))\n        self._ui_queue.put((\"recovery_log\", f\"[{task.label}] {task.status.upper()} - {task.message or 'No details'}\"))\n        if task.status == \"running\":\n            self._ui_queue.put((\"status\", (f\"Recovery task running: {task.label}\", C[\"accent4\"])))\n        elif task.status == \"completed\":\n            self._ui_queue.put((\"status\", (f\"Recovery task completed: {task.label}\", C[\"success\"])))\n        elif task.status == \"failed\":\n            self._ui_queue.put((\"status\", (f\"Recovery task failed: {task.label}\", C[\"error\"])))\n        elif task.status == \"cancelled\":\n            self._ui_queue.put((\"status\", (f\"Recovery task cancelled: {task.label}\", C[\"warning\"])))\n\n    def _append_recovery_log(self, msg):\n        if not hasattr(self, \"recovery_log_text\"):\n            return\n        try:\n            self.recovery_log_text.config(state=\"normal\")\n            self.recovery_log_text.insert(\"end\", self._fix_text(str(msg)) + \"\\n\")\n            lines = float(self.recovery_log_text.index(\"end-1c\").split(\".\")[0])\n            if lines &gt; 500:\n                self.recovery_log_text.delete(\"1.0\", \"100.0\")\n            self.recovery_log_text.see(\"end\")\n            self.recovery_log_text.config(state=\"disabled\")\n        except Exception:\n            pass\n\n    def _refresh_recovery_tree(self, tree, category=None):\n        if tree is None:\n            return\n        try:\n            for iid in tree.get_children():\n                tree.delete(iid)\n            for item in self.recovery_results.all():\n                if category and item.category != category:\n                    continue\n                tag = \"recovered\" if item.recoverability_score &gt;= 75 else \"partial\" if item.recoverability_score &gt;= 40 else \"failed\"\n                tree.insert(\"\", \"end\", values=(\n                    item.file_name,\n                    item.file_type,\n                    self._fmt_size(item.size_bytes),\n                    item.status,\n                    item.path,\n                    f\"{item.recoverability_score}%\",\n                ), tags=(tag,))\n        except Exception:\n            pass\n\n    def _refresh_recovery_queue_tree(self):\n        tree = getattr(self, \"recovery_queue_tree\", None)\n        if tree is None:\n            return\n        try:\n            for iid in tree.get_children():\n                tree.delete(iid)\n            for task in self.recovery_manager.list_tasks():\n                tree.insert(\"\", \"end\", iid=task.task_id, values=(\n                    task.label,\n                    task.status,\n                    f\"{int(task.progress)}%\",\n                    task.message or \"\",\n                ))\n        except Exception:\n            pass\n\n    def _get_recovery_disk_values(self):\n        drives = [f\"{d}:\\\\\" for d in \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\" if os.path.exists(f\"{d}:\\\\\")]\n        raw_values = [DEFAULT_RAW_DISK] + [f\"\\\\\\\\.\\\\{d}:\" for d in \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\" if os.path.exists(f\"{d}:\\\\\")]\n        return raw_values + drives\n\n    def _resolve_disk_path(self, val):\n        \"\"\"Resolve a displayed combobox value to an actual device path.\n\n        If the value matches an entry in _recovery_disk_map, return the mapped path,\n        otherwise return the raw value or DEFAULT_RAW_DISK.\n        \"\"\"\n        try:\n            if not val:\n                return DEFAULT_RAW_DISK\n            if hasattr(self, \"_recovery_disk_map\") and isinstance(val, str) and val in self._recovery_disk_map:\n                return self._recovery_disk_map.get(val)\n            return val or DEFAULT_RAW_DISK\n        except Exception:\n            return DEFAULT_RAW_DISK\n\n    def _populate_recovery_disks(self):\n        \"\"\"Populate available physical disk display values and map them to device paths.\n\n        Uses PowerShell Get-Disk for friendly names; falls back to basic listing.\n        Updates any recovery combobox widgets if present.\n        \"\"\"\n        try:\n            script = \"Get-Disk | Select-Object Number,FriendlyName,Size,MediaType | ConvertTo-Json -Depth 2\"\n            out, rc = self._run_powershell(script, timeout=6)\n            disks = []\n            if out and out.strip() and out.strip() != \"[]\":\n                try:\n                    payload = json.loads(out)\n                    if isinstance(payload, dict):\n                        payload = [payload]\n                    for d in payload:\n                        num = d.get(\"Number\")\n                        name = d.get(\"FriendlyName\") or d.get(\"Model\") or \"Disk\"\n                        size = int(d.get(\"Size\") or 0)\n                        human = self._fmt_size(size)\n                        label = f\"PhysicalDrive{num} - {name} ({human})\"\n                        path = f\"\\\\\\\\.\\\\PhysicalDrive{num}\"\n                        disks.append((label, path))\n                except Exception:\n                    disks = []\n\n            if not disks:\n                # Fallback: use simple raw device list + letters\n                raw_vals = [DEFAULT_RAW_DISK]\n                for d in \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\":\n                    if os.path.exists(f\"{d}:\\\\\"):\n                        raw_vals.append(f\"\\\\\\\\.\\\\{d}:\")\n                disks = [(v, v) for v in raw_vals]\n\n            # Build map and display values\n            self._recovery_disk_map = {label: path for label, path in disks}\n            display_values = [label for label, _ in disks]\n\n            # Update known comboboxes if they exist\n            try:\n                if hasattr(self, \"partition_source_combo\"):\n                    self.partition_source_combo.configure(values=display_values)\n                if hasattr(self, \"deep_recovery_source_combo\"):\n                    self.deep_recovery_source_combo.configure(values=display_values)\n                if hasattr(self, \"raw_carve_source_combo\"):\n                    self.raw_carve_source_combo.configure(values=display_values)\n                if hasattr(self, \"nand_source_combo\"):\n                    self.nand_source_combo.configure(values=display_values)\n                if hasattr(self, \"dashboard_disk_combo\"):\n                    self.dashboard_disk_combo.configure(values=display_values)\n                if hasattr(self, \"photorec_source_combo\"):\n                    self.photorec_source_combo.configure(values=display_values)\n                if hasattr(self, \"mft_source_combo\"):\n                    self.mft_source_combo.configure(values=display_values)\n                if hasattr(self, \"raw_disk_combo\"):\n                    # raw_disk_combo expects raw/paths; extend with display labels too\n                    try:\n                        cur = list(self.raw_disk_combo.cget(\"values\"))\n                        combined = display_values + [v for v in cur if v not in display_values]\n                        self.raw_disk_combo.configure(values=combined)\n                    except Exception:\n                        pass\n                # Also populate detected disks tree if present\n                try:\n                    if hasattr(self, \"detected_disks_tree\") and self.detected_disks_tree is not None:\n                        try:\n                            for iid in self.detected_disks_tree.get_children():\n                                self.detected_disks_tree.delete(iid)\n                            for label, path in disks:\n                                # extract index from path if PhysicalDrive\n                                m = re.match(r\"\\\\\\\\.\\\\PhysicalDrive(\\d+)\", path)\n                                idx = int(m.group(1)) if m else -1\n                                size = \"\"\n                                try:\n                                    # try to get size by path\n                                    sz = _disk_source_size(path)\n                                    size = self._fmt_size(sz)\n                                except Exception:\n                                    size = \"N/A\"\n                                self.detected_disks_tree.insert(\"\", \"end\", iid=path, values=(idx if idx&gt;=0 else \"-\", label, size))\n                        except Exception:\n                            pass\n                except Exception:\n                    pass\n            except Exception:\n                pass\n        except Exception:\n            pass\n\n    def _emit_recovery_scan_stats(self, stats: dict):\n        try:\n            self._ui_queue.put((\"recovery_scan_stats\", stats))\n        except Exception:\n            pass\n\n    def _apply_recovery_scan_stats(self, stats):\n        if not isinstance(stats, dict):\n            return\n        tab = stats.get(\"tab\", \"global\")\n        pct = float(stats.get(\"pct\", 0) or 0)\n        files = int(stats.get(\"files_found\", 0) or 0)\n        folders = int(stats.get(\"folders_scanned\", 0) or 0)\n        msg = str(stats.get(\"message\", \"\") or \"\")\n        self._recovery_live_stats[tab] = stats\n        panel = self._recovery_progress_panels.get(tab) or self._recovery_progress_panels.get(\"global\")\n        if panel:\n            try:\n                panel[\"pct_var\"].set(max(0.0, min(100.0, pct)))\n                panel[\"bar\"].configure(mode=\"determinate\")\n            except Exception:\n                pass\n            try:\n                panel[\"stats_label\"].config(\n                    text=f\"\ud83d\udcc1 Files: {files:,}  |  \ud83d\udcc2 Folders: {folders:,}  |  {pct:.0f}%\"\n                )\n            except Exception:\n                pass\n            if msg and panel.get(\"status_label\"):\n                panel[\"status_label\"].config(text=msg[:220])\n        if tab == \"deep\" and hasattr(self, \"deep_recovery_status\"):\n            self.deep_recovery_status.config(text=f\"{pct:.0f}% \u2014 {files:,} signatures | {msg[:80]}\", fg=C[\"accent4\"])\n        if tab == \"photorec\" and hasattr(self, \"photorec_status_label\"):\n            rec = int(stats.get(\"files_recovered\", files) or 0)\n            self.photorec_status_label.config(\n                text=f\"PhotoRec: {pct:.0f}% | Recovered: {rec:,} | Found: {files:,}\", fg=C[\"accent2\"])\n        if tab == \"mft\" and hasattr(self, \"mft_status_label\"):\n            self.mft_status_label.config(\n                text=f\"MFT: {pct:.0f}% | Deleted: {files:,} | Recovered: {int(stats.get('files_recovered', 0)):,}\",\n                fg=C[\"accent2\"],\n            )\n        if hasattr(self, \"rec_stats_label\") and tab in (\"photorec\", \"deep\", \"mft\", \"raw\"):\n            self.rec_stats_label.config(text=f\"{files:,} items | Live scan {pct:.0f}%\")\n\n    def _build_recovery_progress_strip(self, parent, tab_key, title=\"Scan Progress\"):\n        strip = tk.LabelFrame(parent, text=title, font=FONTS[\"small\"], fg=C[\"accent2\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        strip.pack(fill=\"x\", padx=10, pady=(6, 8))\n        status_label = tk.Label(strip, text=\"\u0924\u0948\u092f\u093e\u0930 \u2014 scan \u0936\u0941\u0930\u0942 \u0915\u0930\u0947\u0902\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], anchor=\"w\")\n        status_label.pack(fill=\"x\", padx=10, pady=(8, 2))\n        stats_label = tk.Label(strip, text=\"\ud83d\udcc1 Files: 0  |  \ud83d\udcc2 Folders: 0  |  0%\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"], anchor=\"w\")\n        stats_label.pack(fill=\"x\", padx=10, pady=(0, 4))\n        pct_var = tk.DoubleVar(value=0.0)\n        bar = ttk.Progressbar(strip, variable=pct_var, maximum=100.0, mode=\"determinate\")\n        bar.pack(fill=\"x\", padx=10, pady=(0, 10))\n        self._recovery_progress_panels[tab_key] = {\n            \"pct_var\": pct_var,\n            \"bar\": bar,\n            \"stats_label\": stats_label,\n            \"status_label\": status_label,\n        }\n        return strip\n\n    def _reset_recovery_progress(self, tab_key, message=\"Scan \u0936\u0941\u0930\u0942 \u0939\u094b \u0930\u0939\u093e \u0939\u0948...\"):\n        panel = self._recovery_progress_panels.get(tab_key)\n        if panel:\n            panel[\"pct_var\"].set(0)\n            panel[\"status_label\"].config(text=message)\n            panel[\"stats_label\"].config(text=\"\ud83d\udcc1 Files: 0  |  \ud83d\udcc2 Folders: 0  |  0%\")\n\n    def _show_recovery_center(self):\n        if hasattr(self, \"recovery_queue_tree\"):\n            self._refresh_recovery_queue_tree()\n        try:\n            self._launch_job(\"populate_recovery_disks\", self._populate_recovery_disks)\n        except Exception:\n            pass\n\n    def _build_recovery_center(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(\n            frame,\n            \"\ud83d\udcc2 Professional File Recovery\",\n            \"Recuva / EaseUS style workflow \u2014 live progress, PhotoRec carving, NTFS MFT deleted recovery.\",\n        )\n\n        global_strip = tk.Frame(frame, bg=C[\"card\"], highlightbackground=C[\"accent2\"], highlightthickness=2)\n        global_strip.pack(fill=\"x\", padx=16, pady=(4, 8))\n        tk.Label(global_strip, text=\"\ud83d\udda5\ufe0f Live Recovery Status\", font=FONTS[\"subhead\"], fg=C[\"accent2\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=12, pady=(8, 2))\n        self._build_recovery_progress_strip(global_strip, \"global\", \"Overall Progress\")\n\n        notebook = ttk.Notebook(frame)\n        notebook.pack(fill=\"both\", expand=True, padx=16, pady=(4, 12))\n\n        tabs = [\n            (\"\ud83c\udfe0 Dashboard\", self._build_recovery_dashboard_tab),\n            (\"\u26a1 Quick Scan\", self._build_recovery_quick_tab),\n            (\"\ud83d\udd0e Deep / Raw Scan\", self._build_recovery_deep_tab),\n            (\"\ud83e\udde9 PhotoRec Pro\", self._build_recovery_photorec_tab),\n            (\"\ud83d\uddc2\ufe0f MFT Deleted Files\", self._build_recovery_mft_tab),\n            (\"\ud83d\udcbe Partition\", self._build_recovery_partitions_tab),\n            (\"\u26a1 NAND Flash\", self._build_recovery_nand_tab),\n            (\"\ud83d\udccc Queue\", self._build_recovery_queue_tab),\n            (\"\ud83d\udccb Logs\", self._build_recovery_logs_tab),\n            (\"\ud83d\udd58 History\", self._build_recovery_history_tab),\n        ]\n        for title, builder in tabs:\n            tab = tk.Frame(notebook, bg=C[\"bg\"])\n            notebook.add(tab, text=title)\n            builder(tab)\n\n        return frame\n\n    def _build_recovery_dashboard_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        card = tk.LabelFrame(body, text=\"Recovery Dashboard \u2014 Disk select karein\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        card.pack(fill=\"x\", padx=14, pady=10)\n\n        row = tk.Frame(card, bg=C[\"card\"])\n        row.pack(fill=\"x\", padx=10, pady=10)\n        tk.Label(row, text=\"Target Disk:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=0, column=0, sticky=\"w\")\n        self.dashboard_disk_var = tk.StringVar(value=\"\")\n        self.dashboard_disk_combo = ttk.Combobox(row, textvariable=self.dashboard_disk_var, width=42, state=\"readonly\")\n        self.dashboard_disk_combo.grid(row=0, column=1, padx=8, sticky=\"w\")\n        tk.Button(row, text=\"\ud83d\udd04 Refresh Disks\", font=FONTS[\"small\"], bg=C[\"btn\"], fg=C[\"text\"], bd=0, padx=10, pady=6, cursor=\"hand2\",\n              command=lambda: self._launch_job(\"populate_recovery_disks\", self._populate_recovery_disks)).grid(row=0, column=2, padx=4)\n\n        tk.Label(row, text=\"Output Folder:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=1, column=0, sticky=\"w\", pady=(10, 0))\n        self.dashboard_output_var = tk.StringVar(value=os.path.join(os.path.expanduser(\"~\"), \"Desktop\", \"Godawari_Recovery\"))\n        tk.Entry(row, textvariable=self.dashboard_output_var, width=48, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).grid(row=1, column=1, padx=8, pady=(10, 0), sticky=\"w\")\n        tk.Button(row, text=\"Browse\", font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text\"], bd=0, padx=10, pady=6, cursor=\"hand2\",\n                  command=lambda: self._browse_recovery_output(self.dashboard_output_var)).grid(row=1, column=2, padx=4, pady=(10, 0))\n\n        modes = tk.Frame(card, bg=C[\"card\"])\n        modes.pack(fill=\"x\", padx=10, pady=(8, 12))\n        tk.Label(modes, text=\"Scan Mode (professional tools jaisa):\", font=FONTS[\"body\"], fg=C[\"accent2\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(0, 6))\n        btn_row = tk.Frame(modes, bg=C[\"card\"])\n        btn_row.pack(fill=\"x\")\n        for label, color, cmd in [\n            (\"\ud83d\udd0d Quick Scan (Existing Files)\", C[\"accent2\"], self._dashboard_start_quick),\n            (\"\ud83d\udd0e Deep Signature Scan\", C[\"btn_warn\"], self._dashboard_start_deep),\n            (\"\ud83e\udde9 PhotoRec Multi-Pass\", C[\"btn_hw\"], self._dashboard_start_photorec),\n            (\"\ud83d\uddc2\ufe0f MFT Deleted Recovery\", C[\"btn_info\"], self._dashboard_start_mft),\n        ]:\n            tk.Button(btn_row, text=label, font=FONTS[\"small\"], bg=color, fg=C[\"text\"] if color != C[\"accent2\"] else \"#000\",\n                      bd=0, padx=12, pady=10, cursor=\"hand2\", command=cmd).pack(side=\"left\", padx=4, pady=4)\n\n        hint = tk.Label(card,\n            text=\"\ud83d\udca1 Tip: Deleted files ke liye MFT \u092f\u093e PhotoRec use \u0915\u0930\u0947\u0902\u0964 Live progress bar \u0928\u0940\u091a\u0947 \u0939\u0930 tab \u092e\u0947\u0902 \u0926\u093f\u0916\u0947\u0917\u093e\u0964 Output \u0939\u092e\u0947\u0936\u093e \u0905\u0932\u0917 drive \u092a\u0930 \u0930\u0916\u0947\u0902\u0964\",\n            font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\", wraplength=900)\n        hint.pack(fill=\"x\", padx=12, pady=(0, 10))\n        return body\n\n    def _browse_recovery_output(self, var):\n        path = filedialog.askdirectory(title=\"Recovery output folder\")\n        if path:\n            var.set(path)\n\n    def _sync_dashboard_disk_to_tabs(self):\n        disk = self.dashboard_disk_var.get().strip()\n        if not disk:\n            return\n        path = getattr(self, \"_recovery_disk_map\", {}).get(disk, disk)\n        for attr in (\n            \"deep_recovery_source_var\", \"photorec_source_var\", \"mft_source_var\",\n            \"raw_carve_source_var\", \"partition_source_var\", \"nand_source_var\",\n        ):\n            if hasattr(self, attr):\n                getattr(self, attr).set(path if path.startswith(\"\\\\\\\\.\\\\\") else disk)\n\n    def _dashboard_start_quick(self):\n        self._sync_dashboard_disk_to_tabs()\n        if hasattr(self, \"quick_recovery_drive_var\"):\n            d = self.dashboard_disk_var.get()\n            if d and \":\" in d:\n                self.quick_recovery_drive_var.set(d.split(\" - \")[0] if \" - \" in d else d[:3] + \"\\\\\")\n            if hasattr(self, \"quick_recovery_dest_var\"):\n                self.quick_recovery_dest_var.set(self.dashboard_output_var.get())\n        self._start_quick_recovery()\n\n    def _dashboard_start_deep(self):\n        self._sync_dashboard_disk_to_tabs()\n        if hasattr(self, \"deep_recovery_source_var\"):\n            self.deep_recovery_source_var.set(self.dashboard_disk_var.get())\n        self._start_deep_recovery()\n\n    def _dashboard_start_photorec(self):\n        self._sync_dashboard_disk_to_tabs()\n        if hasattr(self, \"photorec_source_var\"):\n            self.photorec_source_var.set(self.dashboard_disk_var.get())\n        if hasattr(self, \"photorec_output_var\"):\n            self.photorec_output_var.set(self.dashboard_output_var.get())\n        self._start_photorec_tab_scan()\n\n    def _dashboard_start_mft(self):\n        self._sync_dashboard_disk_to_tabs()\n        if hasattr(self, \"mft_source_var\"):\n            self.mft_source_var.set(self.dashboard_disk_var.get())\n        if hasattr(self, \"mft_output_var\"):\n            self.mft_output_var.set(os.path.join(self.dashboard_output_var.get(), \"MFT_Recovered\"))\n        self._start_mft_deleted_recovery()\n\n    def _build_recovery_quick_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        self._build_recovery_progress_strip(body, \"quick\", \"Quick Scan \u2014 Live Progress\")\n        card = tk.LabelFrame(body, text=\"\ud83d\udccb Quick Recovery (Existing Files)\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        card.pack(fill=\"x\", padx=14, pady=10)\n\n        drive_values = [f\"{d}:\\\\\" for d in \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\" if os.path.exists(f\"{d}:\\\\\")]\n        self.quick_recovery_drive_var = tk.StringVar(value=drive_values[0] if drive_values else \"C:\\\\\")\n        self.quick_recovery_types_var = tk.StringVar(value=\"jpg,png,pdf,docx,mp4\")\n        self.quick_recovery_dest_var = tk.StringVar(value=os.path.join(os.path.expanduser(\"~\"), \"Desktop\", \"Godawari_Quick_Recovery\"))\n\n        row = tk.Frame(card, bg=C[\"card\"])\n        row.pack(fill=\"x\", padx=10, pady=(10, 8))\n        tk.Label(row, text=\"Drive:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=0, column=0, sticky=\"w\")\n        ttk.Combobox(row, textvariable=self.quick_recovery_drive_var, values=drive_values, width=14, state=\"readonly\").grid(row=0, column=1, padx=6)\n        tk.Label(row, text=\"File Types:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=0, column=2, padx=(14, 4), sticky=\"w\")\n        tk.Entry(row, textvariable=self.quick_recovery_types_var, width=28, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).grid(row=0, column=3, padx=6)\n        tk.Label(row, text=\"Destination:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=1, column=0, pady=(8, 0), sticky=\"w\")\n        tk.Entry(row, textvariable=self.quick_recovery_dest_var, width=60, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).grid(row=1, column=1, columnspan=3, padx=6, pady=(8, 0), sticky=\"w\")\n\n        action_row = tk.Frame(card, bg=C[\"card\"])\n        action_row.pack(fill=\"x\", padx=10, pady=(0, 10))\n        tk.Button(action_row, text=\"\ud83d\udd0d Start Scan\", font=FONTS[\"small\"], bg=C[\"accent2\"], fg=\"#000\", bd=0, padx=14, pady=8, cursor=\"hand2\", command=self._start_quick_recovery).pack(side=\"left\")\n        tk.Button(action_row, text=\"\ud83e\uddf9 Clear Results\", font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text\"], bd=0, padx=14, pady=8, cursor=\"hand2\", command=lambda: (self.recovery_results.clear(), self._refresh_recovery_tree(self.quick_recovery_tree, category=\"Quick Recovery\"))).pack(side=\"left\", padx=8)\n\n        self.quick_recovery_status = tk.Label(card, text=\"Ready for quick recovery scan.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"])\n        self.quick_recovery_status.pack(fill=\"x\", padx=10, pady=(0, 6))\n\n        results_outer = tk.LabelFrame(body, text=\"\ud83d\udcc1 Quick Recovery Results\", font=FONTS[\"subhead\"], fg=C[\"accent2\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        results_outer.pack(fill=\"both\", expand=True, padx=14, pady=(0, 14))\n        cols = (\"Filename\", \"Type\", \"Size\", \"Status\", \"Location\", \"Integrity\")\n        self.quick_recovery_tree = ttk.Treeview(results_outer, columns=cols, show=\"headings\", height=12, style=\"Custom.Treeview\")\n        for col, width in zip(cols, (220, 70, 90, 120, 280, 90)):\n            self.quick_recovery_tree.heading(col, text=col)\n            self.quick_recovery_tree.column(col, width=width, anchor=\"w\")\n        self.quick_recovery_tree.tag_configure(\"recovered\", foreground=C[\"success\"])\n        self.quick_recovery_tree.tag_configure(\"partial\", foreground=C[\"warning\"])\n        self.quick_recovery_tree.tag_configure(\"failed\", foreground=C[\"error\"])\n        self.quick_recovery_tree.pack(fill=\"both\", expand=True, padx=8, pady=8)\n        self.quick_recovery_tree.bind(\"&lt;&gt;\", self._on_quick_recovery_select)\n\n        self.quick_recovery_preview = scrolledtext.ScrolledText(body, height=6, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], wrap=\"word\", bd=0, relief=\"flat\")\n        self.quick_recovery_preview.pack(fill=\"x\", padx=14, pady=(0, 10))\n        self.quick_recovery_preview.config(state=\"disabled\")\n\n        return body\n\n    def _start_quick_recovery(self):\n        drive = self.quick_recovery_drive_var.get().strip()\n        if not drive or not os.path.exists(drive):\n            messagebox.showwarning(\"Drive Missing\", \"Valid drive select karo.\")\n            return\n        exts = [e.strip().lstrip(\".\").lower() for e in self.quick_recovery_types_var.get().split(\",\") if e.strip()]\n        dest = self.quick_recovery_dest_var.get().strip() or os.path.join(os.path.expanduser(\"~\"), \"Desktop\", \"Godawari_Quick_Recovery\")\n        try:\n            dest = get_recovery_safety(getattr(self, \"app_config\", None)).validate_output_dir(dest, drive)\n        except Exception as exc:\n            messagebox.showerror(\"Recovery Safety\", str(exc))\n            return\n        self.recovery_results.clear()\n        self._refresh_recovery_tree(self.quick_recovery_tree, category=\"Quick Recovery\")\n        self.recovery_manager.submit_task(\"Quick Recovery\", self._task_quick_recovery, drive, exts, dest)\n        self.quick_recovery_status.config(text=\"Queued quick recovery task...\", fg=C[\"accent4\"])\n\n    def _task_quick_recovery(self, task, drive, exts, dest):\n        found = 0\n        folders = 0\n        self._ui_queue.put((\"recovery_log\", f\"[Quick Recovery] Scanning {drive} for {', '.join(exts) or 'all file types'}\"))\n        for root, _, files in os.walk(drive):\n            folders += 1\n            task.wait_if_paused()\n            if task.is_cancelled():\n                raise InterruptedError(\"Quick recovery cancelled\")\n            for name in files:\n                task.wait_if_paused()\n                if task.is_cancelled():\n                    raise InterruptedError(\"Quick recovery cancelled\")\n                ext = os.path.splitext(name)[1].lstrip(\".\").lower()\n                if exts and ext not in exts:\n                    continue\n                path = os.path.join(root, name)\n                try:\n                    size = os.path.getsize(path)\n                except Exception:\n                    size = 0\n                score = 90 if size &gt; 0 else 20\n                item = RecoveryResultItem(\n                    item_id=f\"quick-{uuid.uuid4()}\",\n                    source=drive,\n                    category=\"Quick Recovery\",\n                    file_name=name,\n                    file_type=ext or \"unknown\",\n                    size_bytes=size,\n                    recoverability_score=score,\n                    status=\"found\",\n                    path=path,\n                    metadata={\"root\": root},\n                )\n                self.recovery_results.add(item)\n                found += 1\n                if found % 20 == 0:\n                    self._emit_recovery_scan_stats({\n                        \"tab\": \"quick\",\n                        \"pct\": min(95, found // 15),\n                        \"files_found\": found,\n                        \"folders_scanned\": folders,\n                        \"message\": f\"Scanning... {found:,} files in {folders:,} folders\",\n                    })\n                if score &gt;= 75 and dest:\n                    try:\n                        safe_dest = get_recovery_safety(getattr(self, \"app_config\", None)).validate_output_dir(dest, drive)\n                        rel = os.path.relpath(path, drive)\n                        out_path = os.path.join(safe_dest, rel)\n                        os.makedirs(os.path.dirname(out_path), exist_ok=True)\n                        if not os.path.exists(out_path):\n                            shutil.copy2(path, out_path)\n                            item.metadata[\"exported_to\"] = out_path\n                    except Exception:\n                        pass\n                if found % 25 == 0:\n                    self._ui_queue.put((\"recovery_queue\", None))\n                    self._ui_queue.put((\"recovery_log\", f\"[Quick Recovery] {found} items found\"))\n                if found &gt;= 1500:\n                    self._ui_queue.put((\"recovery_log\", \"[Quick Recovery] Limit reached (1500 items)\"))\n                    return\n        self._emit_recovery_scan_stats({\n            \"tab\": \"quick\", \"pct\": 100, \"files_found\": found, \"folders_scanned\": folders,\n            \"message\": f\"Complete \u2014 {found:,} files\",\n        })\n        self._ui_queue.put((\"recovery_queue\", None))\n        self._ui_queue.put((\"recovery_refresh\", None))\n        self._ui_queue.put((\"recovery_log\", f\"[Quick Recovery] Completed, {found} items found.\"))\n\n    def _on_quick_recovery_select(self, event=None):\n        sel = self.quick_recovery_tree.selection()\n        if not sel:\n            return\n        values = self.quick_recovery_tree.item(sel[0], \"values\")\n        if not values or len(values) &lt; 6:\n            return\n        path = values[4]\n        preview = [f\"Path: {path}\", f\"Type: {values[1]}\", f\"Size: {values[2]}\", f\"Status: {values[3]}\", f\"Integrity: {values[5]}\", \"\"]\n        try:\n            if os.path.exists(path) and os.path.isfile(path):\n                with open(path, \"rb\") as fh:\n                    data = fh.read(512)\n                preview.append(data[:512].hex(\" \"))\n        except Exception as exc:\n            preview.append(f\"Preview failed: {exc}\")\n        self.quick_recovery_preview.config(state=\"normal\")\n        self.quick_recovery_preview.delete(\"1.0\", \"end\")\n        self.quick_recovery_preview.insert(\"end\", \"\\n\".join(preview))\n        self.quick_recovery_preview.config(state=\"disabled\")\n\n    def _build_recovery_deep_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        self._build_recovery_progress_strip(body, \"deep\", \"Deep / Raw Scan \u2014 Live Progress\")\n        card = tk.LabelFrame(body, text=\"\ud83d\udd0e Deep / Raw Signature Scan\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        card.pack(fill=\"x\", padx=14, pady=10)\n\n        self.deep_recovery_source_var = tk.StringVar(value=DEFAULT_RAW_DISK)\n        self.deep_recovery_types_var = tk.StringVar(value=\"jpg,png,pdf,zip,exe\")\n        self.deep_recovery_scan_mb_var = tk.StringVar(value=\"0\")\n        self.deep_recovery_start_var = tk.StringVar(value=\"0\")\n\n        row = tk.Frame(card, bg=C[\"card\"])\n        row.pack(fill=\"x\", padx=10, pady=10)\n        tk.Label(row, text=\"Source:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=0, column=0, sticky=\"w\")\n        self.deep_recovery_source_combo = ttk.Combobox(row, textvariable=self.deep_recovery_source_var, values=self._get_recovery_disk_values(), width=34, state=\"readonly\")\n        self.deep_recovery_source_combo.grid(row=0, column=1, padx=4)\n        tk.Label(row, text=\"Types:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=1, column=0, sticky=\"w\", pady=(8,0))\n        tk.Entry(row, textvariable=self.deep_recovery_types_var, width=34, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).grid(row=1, column=1, padx=4, pady=(8,0))\n        tk.Label(row, text=\"Scan MB:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=0, column=2, padx=(18,4), sticky=\"w\")\n        tk.Entry(row, textvariable=self.deep_recovery_scan_mb_var, width=8, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).grid(row=0, column=3, padx=4)\n        tk.Label(row, text=\"Start Sector:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=1, column=2, padx=(18,4), sticky=\"w\", pady=(8,0))\n        tk.Entry(row, textvariable=self.deep_recovery_start_var, width=10, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).grid(row=1, column=3, padx=4, pady=(8,0))\n\n        action_row = tk.Frame(card, bg=C[\"card\"])\n        action_row.pack(fill=\"x\", padx=10, pady=(0, 8))\n        tk.Button(action_row, text=\"\u26a1 Scan Raw Source\", font=FONTS[\"small\"], bg=C[\"btn_warn\"], fg=C[\"text\"], bd=0, padx=14, pady=8, cursor=\"hand2\", command=self._start_deep_recovery).pack(side=\"left\")\n        tk.Button(action_row, text=\"\ud83e\uddf9 Clear\", font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text\"], bd=0, padx=14, pady=8, cursor=\"hand2\", command=lambda: (self.recovery_results.clear(), self._refresh_recovery_tree(self.deep_recovery_tree, category=\"Deep Recovery\"))).pack(side=\"left\", padx=8)\n\n        self.deep_recovery_status = tk.Label(card, text=\"Raw signature scan ready.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"])\n        self.deep_recovery_status.pack(fill=\"x\", padx=10, pady=(0, 6))\n\n        results_outer = tk.LabelFrame(body, text=\"\ud83d\udce6 Deep Recovery Results\", font=FONTS[\"subhead\"], fg=C[\"accent2\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        results_outer.pack(fill=\"both\", expand=True, padx=14, pady=(0, 14))\n        cols = (\"Signature\", \"Type\", \"Sector\", \"Confidence\", \"Source\", \"Path\")\n        self.deep_recovery_tree = ttk.Treeview(results_outer, columns=cols, show=\"headings\", height=12, style=\"Custom.Treeview\")\n        for col, width in zip(cols, (180, 80, 120, 90, 220, 200)):\n            self.deep_recovery_tree.heading(col, text=col)\n            self.deep_recovery_tree.column(col, width=width, anchor=\"w\")\n        self.deep_recovery_tree.tag_configure(\"recovered\", foreground=C[\"success\"])\n        self.deep_recovery_tree.tag_configure(\"partial\", foreground=C[\"warning\"])\n        self.deep_recovery_tree.tag_configure(\"failed\", foreground=C[\"error\"])\n        self.deep_recovery_tree.pack(fill=\"both\", expand=True, padx=8, pady=8)\n\n        self.deep_recovery_preview = scrolledtext.ScrolledText(body, height=6, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], wrap=\"word\", bd=0, relief=\"flat\")\n        self.deep_recovery_preview.pack(fill=\"x\", padx=14, pady=(0, 10))\n        self.deep_recovery_preview.config(state=\"disabled\")\n\n        return body\n\n    def _start_deep_recovery(self):\n        source = self._resolve_disk_path(self.deep_recovery_source_var.get().strip() or DEFAULT_RAW_DISK)\n        if not source:\n            messagebox.showwarning(\"Source Missing\", \"Raw source disk/image select karein.\")\n            return\n        file_types = [e.strip().lstrip(\".\").upper() for e in self.deep_recovery_types_var.get().split(\",\") if e.strip()]\n        max_mb = self.deep_recovery_scan_mb_var.get().strip()\n        start_sector = self.deep_recovery_start_var.get().strip()\n        try:\n            max_bytes = int(max_mb) * 1024 * 1024 if max_mb and int(max_mb) &gt; 0 else None\n        except Exception:\n            max_bytes = None\n        try:\n            start_offset = int(start_sector) * SECTOR_SIZE if start_sector and int(start_sector) &gt; 0 else 0\n        except Exception:\n            start_offset = 0\n        self.recovery_results.clear()\n        self._refresh_recovery_tree(self.deep_recovery_tree, category=\"Deep Recovery\")\n        self._reset_recovery_progress(\"deep\", \"Deep scan queue \u092e\u0947\u0902 \u0939\u0948...\")\n        self.recovery_manager.submit_task(\"Deep Recovery\", self._task_deep_recovery, source, file_types, max_bytes, start_offset)\n        self.deep_recovery_status.config(text=\"Queued raw recovery scan...\", fg=C[\"accent4\"])\n\n    def _task_deep_recovery(self, task, source, file_types, max_bytes, start_offset):\n        self._ui_queue.put((\"recovery_log\", f\"[Deep Recovery] Scanning {source} from offset {start_offset} for {', '.join(file_types)}\"))\n        if _is_raw_device_path(source) and not is_admin():\n            raise PermissionError(\"Administrator rights required for raw disk scan.\")\n        def stats_cb(st):\n            st[\"tab\"] = \"deep\"\n            self._emit_recovery_scan_stats(st)\n        prog = make_progress_callback(lambda s: self._emit_recovery_scan_stats({**s, \"tab\": \"deep\"}), \"deep\")\n        def find_callback(msg):\n            self._ui_queue.put((\"recovery_log\", f\"[Deep Recovery] {msg}\"))\n            prog(msg)\n        hits = scan_disk_for_files(\n            source, max_bytes=max_bytes, start_offset=start_offset, file_types=file_types,\n            progress_callback=find_callback, stats_callback=stats_cb,\n        )\n        live_count = 0\n        for hit in hits:\n            score = 80 if hit.get(\"confidence\") == \"high\" else 55\n            try:\n                sample = self._forensic_read_at(source, int(hit.get(\"offset\", 0)), 4096)\n                conf = validate_recovered_file(sample, hit.get(\"file_type\", \"\"))\n                score = conf.score\n            except Exception:\n                pass\n            item = RecoveryResultItem(\n                item_id=f\"deep-{uuid.uuid4()}\",\n                source=source,\n                category=\"Deep Recovery\",\n                file_name=f\"{hit.get('file_type','UNKNOWN')} @ {hit.get('offset',0)}\",\n                file_type=hit.get(\"file_type\", \"RAW\"),\n                size_bytes=0,\n                recoverability_score=score,\n                status=\"signature\",\n                path=f\"{hit.get('disk_path', source)}:{hit.get('offset', 0)}\",\n                metadata=hit,\n            )\n            self.recovery_results.add(item)\n            live_count += 1\n            if live_count % 10 == 0:\n                self._emit_recovery_scan_stats({\n                    \"tab\": \"deep\", \"pct\": 90, \"files_found\": live_count,\n                    \"message\": f\"Indexing results... {live_count}/{len(hits)}\",\n                })\n        self._emit_recovery_scan_stats({\n            \"tab\": \"deep\", \"pct\": 100, \"files_found\": len(hits),\n            \"message\": f\"Complete \u2014 {len(hits)} signatures\",\n        })\n        self._ui_queue.put((\"recovery_queue\", None))\n        self._ui_queue.put((\"recovery_refresh\", None))\n        self._ui_queue.put((\"recovery_log\", f\"[Deep Recovery] Completed, {len(hits)} signatures discovered.\"))\n\n    def _build_recovery_photorec_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        self._build_recovery_progress_strip(body, \"photorec\", \"PhotoRec Pro \u2014 Live Carving Progress\")\n        card = tk.LabelFrame(body, text=\"\ud83e\udde9 PhotoRec Pro (Multi-Pass Carving)\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        card.pack(fill=\"x\", padx=14, pady=10)\n\n        self.photorec_source_var = tk.StringVar(value=\"\")\n        self.photorec_output_var = tk.StringVar(value=os.path.join(os.path.expanduser(\"~\"), \"Desktop\", \"Godawari_PhotoRec\"))\n        row = tk.Frame(card, bg=C[\"card\"])\n        row.pack(fill=\"x\", padx=10, pady=10)\n        tk.Label(row, text=\"Source Disk:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=0, column=0, sticky=\"w\")\n        self.photorec_source_combo = ttk.Combobox(row, textvariable=self.photorec_source_var, width=40, state=\"readonly\")\n        self.photorec_source_combo.grid(row=0, column=1, padx=6)\n        tk.Label(row, text=\"Output:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=1, column=0, sticky=\"w\", pady=(8, 0))\n        tk.Entry(row, textvariable=self.photorec_output_var, width=50, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).grid(row=1, column=1, padx=6, pady=(8, 0), sticky=\"w\")\n        tk.Button(row, text=\"Browse\", font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text\"], bd=0, padx=8, pady=6, cursor=\"hand2\",\n                  command=lambda: self._browse_recovery_output(self.photorec_output_var)).grid(row=1, column=2, pady=(8, 0))\n\n        info = tk.Label(card,\n            text=\"PhotoRec \u091c\u0948\u0938\u093e workflow:\\n\"\n                 \"\u2460 Auto block size  \u2461 Pass 1 aligned carving  \u2462 Pass 2 unaligned  \u2463 Validation\\n\"\n                 \"Har recovered file live list \u092e\u0947\u0902 \u0926\u093f\u0916\u0947\u0917\u0940 \u2014 progress bar real-time update \u0939\u094b\u0917\u093e\u0964\",\n            font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\")\n        info.pack(fill=\"x\", padx=12, pady=(0, 8))\n\n        action = tk.Frame(card, bg=C[\"card\"])\n        action.pack(fill=\"x\", padx=10, pady=(0, 10))\n        tk.Button(action, text=\"\u25b6 Start PhotoRec Scan\", font=(\"Segoe UI\", 10, \"bold\"), bg=C[\"btn_hw\"], fg=C[\"text\"],\n                  bd=0, padx=16, pady=10, cursor=\"hand2\", command=self._start_photorec_tab_scan).pack(side=\"left\")\n        tk.Button(action, text=\"\u23f9 Stop\", font=FONTS[\"small\"], bg=C[\"btn_danger\"], fg=C[\"text\"], bd=0, padx=12, pady=8, cursor=\"hand2\",\n                  command=self._stop_file_recovery).pack(side=\"left\", padx=8)\n\n        self.photorec_status_label = tk.Label(card, text=\"PhotoRec Pro ready.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"])\n        self.photorec_status_label.pack(fill=\"x\", padx=10, pady=(0, 8))\n\n        results = tk.LabelFrame(body, text=\"\ud83d\udce6 Live Recovered Files (PhotoRec)\", font=FONTS[\"subhead\"], fg=C[\"accent2\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        results.pack(fill=\"both\", expand=True, padx=14, pady=(0, 14))\n        cols = (\"File\", \"Type\", \"Size\", \"Pass\", \"Offset\", \"Path\")\n        self.photorec_tree = ttk.Treeview(results, columns=cols, show=\"headings\", height=14, style=\"Custom.Treeview\")\n        for col, w in zip(cols, (220, 60, 80, 50, 120, 280)):\n            self.photorec_tree.heading(col, text=col)\n            self.photorec_tree.column(col, width=w, anchor=\"w\")\n        self.photorec_tree.pack(fill=\"both\", expand=True, padx=8, pady=8)\n        return body\n\n    def _start_photorec_tab_scan(self):\n        label = self.photorec_source_var.get().strip()\n        source = self._resolve_disk_path(getattr(self, \"_recovery_disk_map\", {}).get(label, label))\n        if not source:\n            messagebox.showwarning(\"Source\", \"Disk/image select karein.\")\n            return\n        if not self._ensure_admin_for_raw_recovery(source):\n            return\n        output_dir = self.photorec_output_var.get().strip() or filedialog.askdirectory(title=\"PhotoRec output\")\n        if not output_dir:\n            return\n        try:\n            output_dir = get_recovery_safety(getattr(self, \"app_config\", None)).validate_output_dir(output_dir, source)\n        except Exception as exc:\n            messagebox.showerror(\"Safety\", str(exc))\n            return\n        if not messagebox.askyesno(\"PhotoRec Pro\", f\"Source: {source}\\nOutput: {output_dir}\\n\\nMulti-pass carving start?\"):\n            return\n        self.photorec_tree.delete(*self.photorec_tree.get_children())\n        self._reset_recovery_progress(\"photorec\", \"PhotoRec Pass 1 \u0936\u0941\u0930\u0942...\")\n        self._set_recovery_scan_mode(\"Mode: PhotoRec Pro Multi-Pass\", C[\"warning\"])\n        self.recovery_manager.submit_task(\"PhotoRec Pro\", self._task_photorec_tab_scan, source, output_dir)\n\n    def _task_photorec_tab_scan(self, task, source, output_dir):\n        files_live = [0]\n\n        def on_progress(msg):\n            prog = make_progress_callback(lambda s: self._emit_recovery_scan_stats({**s, \"tab\": \"photorec\"}), \"photorec\")\n            prog(msg)\n            self._ui_queue.put((\"recovery_log\", f\"[PhotoRec] {msg}\"))\n            m = re.search(r\"Pass\\s+\\d+:\\s+recovered\\s+(.+)\", str(msg), re.I)\n            if m:\n                fn = m.group(1).strip()\n                files_live[0] += 1\n                self._emit_recovery_scan_stats({\n                    \"tab\": \"photorec\", \"files_found\": files_live[0], \"files_recovered\": files_live[0],\n                    \"message\": f\"Recovered: {fn}\",\n                })\n                row = (fn, os.path.splitext(fn)[1].lstrip(\".\").upper() or \"?\", \"\u2014\", \"\u2014\", \"\u2014\", fn)\n                self._ui_queue.put((\"photorec_tree_row\", row))\n\n        result = multi_pass_recovery(source, output_dir, progress_callback=on_progress)\n        for item in result.get(\"files\", []):\n            row = (\n                os.path.basename(item[\"path\"]),\n                item.get(\"file_type\", \"?\"),\n                self._fmt_size(item.get(\"bytes\", 0)),\n                str(item.get(\"pass\", \"?\")),\n                f\"0x{item.get('offset', 0):X}\",\n                item[\"path\"],\n            )\n            self._ui_queue.put((\"photorec_tree_row\", row))\n        self._emit_recovery_scan_stats({\n            \"tab\": \"photorec\", \"pct\": 100,\n            \"files_found\": len(result.get(\"files\", [])),\n            \"files_recovered\": len(result.get(\"files\", [])),\n            \"message\": f\"Done \u2014 {result.get('recup_dir', output_dir)}\",\n        })\n        self._ui_queue.put((\"recovery_log\", f\"[PhotoRec] Complete: {len(result.get('files', []))} files\"))\n\n    def _build_recovery_mft_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        self._build_recovery_progress_strip(body, \"mft\", \"MFT Deleted Recovery \u2014 Live Progress\")\n        card = tk.LabelFrame(body, text=\"\ud83d\uddc2\ufe0f NTFS MFT Deleted File Recovery\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        card.pack(fill=\"x\", padx=14, pady=10)\n\n        self.mft_source_var = tk.StringVar(value=\"\")\n        self.mft_output_var = tk.StringVar(value=os.path.join(os.path.expanduser(\"~\"), \"Desktop\", \"Godawari_MFT_Recovery\"))\n        self.mft_max_records_var = tk.StringVar(value=\"8192\")\n        row = tk.Frame(card, bg=C[\"card\"])\n        row.pack(fill=\"x\", padx=10, pady=10)\n        tk.Label(row, text=\"NTFS Volume:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=0, column=0, sticky=\"w\")\n        self.mft_source_combo = ttk.Combobox(row, textvariable=self.mft_source_var, width=40, state=\"readonly\")\n        self.mft_source_combo.grid(row=0, column=1, padx=6)\n        tk.Label(row, text=\"Output:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=1, column=0, sticky=\"w\", pady=(8, 0))\n        tk.Entry(row, textvariable=self.mft_output_var, width=50, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).grid(row=1, column=1, padx=6, pady=(8, 0), sticky=\"w\")\n        tk.Button(row, text=\"Browse\", font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text\"], bd=0, padx=8, pady=6, cursor=\"hand2\",\n                  command=lambda: self._browse_recovery_output(self.mft_output_var)).grid(row=1, column=2, pady=(8, 0))\n        tk.Label(row, text=\"Max MFT Records:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=2, column=0, sticky=\"w\", pady=(8, 0))\n        tk.Entry(row, textvariable=self.mft_max_records_var, width=10, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).grid(row=2, column=1, padx=6, pady=(8, 0), sticky=\"w\")\n\n        tk.Label(card,\n                 text=\"\u092f\u0939 tab $MFT \u0938\u0947 deleted files \u0915\u0940 actual bytes recover \u0915\u0930\u0924\u0940 \u0939\u0948 (DATA runs \u2192 clusters).\\n\"\n                      \"Sirf NTFS volume \u092a\u0930 \u0915\u093e\u092e \u0915\u0930\u0947\u0917\u093e \u2014 partition/image source select \u0915\u0930\u0947\u0902\u0964\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\").pack(fill=\"x\", padx=12, pady=(0, 8))\n\n        action = tk.Frame(card, bg=C[\"card\"])\n        action.pack(fill=\"x\", padx=10, pady=(0, 10))\n        tk.Button(action, text=\"\u25b6 Recover Deleted (MFT)\", font=(\"Segoe UI\", 10, \"bold\"), bg=C[\"btn_info\"], fg=C[\"text\"],\n                  bd=0, padx=16, pady=10, cursor=\"hand2\", command=self._start_mft_deleted_recovery).pack(side=\"left\")\n\n        self.mft_status_label = tk.Label(card, text=\"MFT recovery ready.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"])\n        self.mft_status_label.pack(fill=\"x\", padx=10, pady=(0, 8))\n\n        results = tk.LabelFrame(body, text=\"\ud83d\udcc1 Recovered Deleted Files\", font=FONTS[\"subhead\"], fg=C[\"accent2\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        results.pack(fill=\"both\", expand=True, padx=14, pady=(0, 14))\n        cols = (\"File\", \"Size\", \"Status\", \"Fragmented\", \"Path\")\n        self.mft_tree = ttk.Treeview(results, columns=cols, show=\"headings\", height=14, style=\"Custom.Treeview\")\n        for col, w in zip(cols, (220, 90, 100, 80, 340)):\n            self.mft_tree.heading(col, text=col)\n            self.mft_tree.column(col, width=w, anchor=\"w\")\n        self.mft_tree.pack(fill=\"both\", expand=True, padx=8, pady=8)\n        return body\n\n    def _start_mft_deleted_recovery(self):\n        label = self.mft_source_var.get().strip()\n        source = self._resolve_disk_path(getattr(self, \"_recovery_disk_map\", {}).get(label, label))\n        if not source:\n            messagebox.showwarning(\"Source\", \"NTFS volume select karein (C: \u092f\u093e partition image).\")\n            return\n        if not self._ensure_admin_for_raw_recovery(source):\n            return\n        output_dir = self.mft_output_var.get().strip()\n        if not output_dir:\n            messagebox.showwarning(\"Output\", \"Output folder set karein.\")\n            return\n        try:\n            output_dir = get_recovery_safety(getattr(self, \"app_config\", None)).validate_output_dir(output_dir, source)\n        except Exception as exc:\n            messagebox.showerror(\"Safety\", str(exc))\n            return\n        try:\n            max_records = max(512, int(self.mft_max_records_var.get().strip()))\n        except Exception:\n            max_records = 8192\n        if not messagebox.askyesno(\"MFT Recovery\", f\"Deleted files recover karein?\\n\\nSource: {source}\\nOutput: {output_dir}\\nRecords: {max_records}\"):\n            return\n        self.mft_tree.delete(*self.mft_tree.get_children())\n        self._reset_recovery_progress(\"mft\", \"MFT scan \u0936\u0941\u0930\u0942...\")\n        self.recovery_manager.submit_task(\"MFT Deleted Recovery\", self._task_mft_deleted_recovery, source, output_dir, max_records)\n\n    def _task_mft_deleted_recovery(self, task, source, output_dir, max_records):\n        partition_offset = 0\n        if hasattr(self, \"_parse_mbr_partitions\"):\n            try:\n                sector = self._forensic_read_at(source, 0, 512)\n                parts = self._parse_mbr_partitions(sector)\n                if parts:\n                    partition_offset = int(parts[0].get(\"start_lba\", 0)) * SECTOR_SIZE\n            except Exception:\n                pass\n\n        def read_fn(offset, length):\n            task.wait_if_paused()\n            if task.is_cancelled():\n                raise InterruptedError(\"MFT recovery cancelled\")\n            return self._forensic_read_at(source, offset, length)\n\n        boot = read_fn(partition_offset, 512)\n\n        def progress_cb(st):\n            st[\"tab\"] = \"mft\"\n            self._emit_recovery_scan_stats(st)\n\n        result = recover_deleted_mft_files(\n            read_fn, partition_offset, boot, output_dir,\n            max_records=max_records, max_recover=500,\n            progress_callback=progress_cb,\n            cancel_check=task.is_cancelled,\n        )\n        for item in result.get(\"results\", []):\n            if not item.ok:\n                continue\n            row = (\n                item.file_name,\n                self._fmt_size(item.size_bytes),\n                \"\u2705 Recovered\" if item.ok else \"Failed\",\n                \"Yes\" if item.fragmented else \"No\",\n                item.output_path,\n            )\n            self._ui_queue.put((\"mft_tree_row\", row))\n            rec_item = RecoveryResultItem(\n                item_id=f\"mft-{uuid.uuid4()}\",\n                source=source,\n                category=\"MFT Deleted\",\n                file_name=item.file_name,\n                file_type=os.path.splitext(item.file_name)[1].lstrip(\".\") or \"file\",\n                size_bytes=item.size_bytes,\n                recoverability_score=85 if item.ok else 20,\n                status=\"recovered\" if item.ok else \"failed\",\n                path=item.output_path,\n                metadata={\"deleted\": item.deleted, \"fragmented\": item.fragmented},\n            )\n            self.recovery_results.add(rec_item)\n        self._emit_recovery_scan_stats({\n            \"tab\": \"mft\", \"pct\": 100,\n            \"files_found\": result.get(\"deleted_candidates\", 0),\n            \"files_recovered\": result.get(\"recovered_count\", 0),\n            \"message\": f\"MFT done \u2014 {result.get('recovered_count', 0)} files saved\",\n        })\n        self._ui_queue.put((\"recovery_queue\", None))\n        self._ui_queue.put((\"recovery_refresh\", None))\n        self._ui_queue.put((\"recovery_log\",\n            f\"[MFT] Deleted candidates: {result.get('deleted_candidates', 0)}, \"\n            f\"Recovered: {result.get('recovered_count', 0)} \u2192 {output_dir}\"))\n\n    def _build_recovery_raw_carve_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        card = tk.LabelFrame(body, text=\"\ud83e\udde9 RAW Carving\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        card.pack(fill=\"x\", padx=14, pady=10)\n\n        self.raw_carve_source_var = tk.StringVar(value=DEFAULT_RAW_DISK)\n        self.raw_carve_offset_var = tk.StringVar(value=\"0\")\n        self.raw_carve_length_var = tk.StringVar(value=\"65536\")\n\n        row = tk.Frame(card, bg=C[\"card\"])\n        row.pack(fill=\"x\", padx=10, pady=10)\n        tk.Label(row, text=\"Source:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=0, column=0, sticky=\"w\")\n        self.raw_carve_source_combo = ttk.Combobox(row, textvariable=self.raw_carve_source_var, values=self._get_recovery_disk_values(), width=36, state=\"readonly\")\n        self.raw_carve_source_combo.grid(row=0, column=1, padx=4)\n        tk.Label(row, text=\"Offset:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=1, column=0, pady=(8,0), sticky=\"w\")\n        tk.Entry(row, textvariable=self.raw_carve_offset_var, width=16, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).grid(row=1, column=1, padx=4, pady=(8,0), sticky=\"w\")\n        tk.Label(row, text=\"Length:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=1, column=2, padx=(18,4), pady=(8,0), sticky=\"w\")\n        tk.Entry(row, textvariable=self.raw_carve_length_var, width=12, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).grid(row=1, column=3, padx=4, pady=(8,0), sticky=\"w\")\n\n        action_row = tk.Frame(card, bg=C[\"card\"])\n        action_row.pack(fill=\"x\", padx=10, pady=(0, 6))\n        tk.Button(action_row, text=\"\ud83e\uddea Analyze Range\", font=FONTS[\"small\"], bg=C[\"btn_chip\"], fg=C[\"text\"], bd=0, padx=14, pady=8, cursor=\"hand2\", command=self._run_raw_carve).pack(side=\"left\")\n        tk.Button(action_row, text=\"\ud83e\uddf9 Clear\", font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text\"], bd=0, padx=14, pady=8, cursor=\"hand2\", command=lambda: self.raw_carve_output.config(state=\"normal\") or self.raw_carve_output.delete(\"1.0\",\"end\") or self.raw_carve_output.config(state=\"disabled\")).pack(side=\"left\", padx=8)\n\n        self.raw_carve_output = scrolledtext.ScrolledText(body, height=12, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], wrap=\"word\", bd=0, relief=\"flat\")\n        self.raw_carve_output.pack(fill=\"both\", expand=True, padx=14, pady=(0, 14))\n        self.raw_carve_output.config(state=\"disabled\")\n        return body\n\n    def _run_raw_carve(self):\n        source = self._resolve_disk_path(self.raw_carve_source_var.get().strip() or DEFAULT_RAW_DISK)\n        try:\n            offset = int(self.raw_carve_offset_var.get().strip())\n            length = max(4096, int(self.raw_carve_length_var.get().strip()))\n        except Exception:\n            messagebox.showwarning(\"Invalid Range\", \"Offset aur length numeric hone chahiye.\")\n            return\n        try:\n            data = self._forensic_read_at(source, offset, length)\n            if not data:\n                raise IOError(\"No data read from raw source\")\n            analysis = [f\"Source: {source}\", f\"Offset: {offset}\", f\"Length: {len(data)} bytes\", \"\"]\n            patterns = {\n                \"JPEG\": b\"\\xff\\xd8\\xff\",\n                \"PNG\": b\"\\x89PNG\\r\\n\\x1a\\n\",\n                \"PDF\": b\"%PDF\",\n                \"PE\": b\"MZ\",\n                \"ZIP\": b\"PK\",\n            }\n            for name, sig in patterns.items():\n                idx = data.find(sig)\n                if idx &gt;= 0:\n                    analysis.append(f\"Found {name} signature at offset {offset + idx}\")\n            if len(analysis) == 4:\n                analysis.append(\"No known signatures found in the selected region.\")\n            analysis.append(\"\\nPreview (first 256 bytes):\")\n            analysis.append(data[:256].hex(\" \"))\n            self.raw_carve_output.config(state=\"normal\")\n            self.raw_carve_output.delete(\"1.0\", \"end\")\n            self.raw_carve_output.insert(\"end\", \"\\n\".join(analysis))\n            self.raw_carve_output.config(state=\"disabled\")\n            self._ui_queue.put((\"recovery_log\", f\"[RAW Carving] Analyzed {length} bytes from {source}@{offset}\"))\n        except Exception as exc:\n            messagebox.showerror(\"Raw Carve Error\", str(exc))\n            self._ui_queue.put((\"recovery_log\", f\"[RAW Carving] Error: {exc}\"))\n\n    def _build_recovery_partitions_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        card = tk.LabelFrame(body, text=\"\ud83e\udded Partition Recovery\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        card.pack(fill=\"x\", padx=14, pady=10)\n        self.partition_source_var = tk.StringVar(value=DEFAULT_RAW_DISK)\n\n        top_row = tk.Frame(card, bg=C[\"card\"])\n        top_row.pack(fill=\"x\", padx=4, pady=(6,4))\n\n        # Left: Detected disks list\n        left = tk.Frame(top_row, bg=C[\"card\"])\n        left.pack(side=\"left\", fill=\"y\", padx=(6,8))\n        tk.Label(left, text=\"Detected Disks:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\")\n        cols = (\"#\", \"Name\", \"Size\")\n        self.detected_disks_tree = ttk.Treeview(left, columns=cols, show=\"headings\", height=6, style=\"Custom.Treeview\")\n        for col, w in zip(cols, (40, 320, 120)):\n            self.detected_disks_tree.heading(col, text=col)\n            self.detected_disks_tree.column(col, width=w, anchor=\"w\")\n        self.detected_disks_tree.pack(fill=\"both\", expand=False)\n        self.detected_disks_tree.bind(\"&lt;&gt;\", lambda e: None)\n        tk.Button(left, text=\"\ud83d\udd04 Refresh\", font=FONTS[\"small\"], bg=C[\"btn\"], fg=C[\"text\"], bd=0, padx=8, pady=6, cursor=\"hand2\", command=lambda: self._launch_job(\"recovery_populate_disks\", self._populate_recovery_disks)).pack(pady=6)\n\n        # Middle: actions\n        mid = tk.Frame(top_row, bg=C[\"card\"])\n        mid.pack(side=\"left\", fill=\"y\", padx=(4,8))\n        tk.Label(mid, text=\"Actions:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\")\n        tk.Button(mid, text=\"\ud83e\udde0 Scan Selected Disk\", font=FONTS[\"small\"], bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=10, pady=8, cursor=\"hand2\", command=self._start_scan_partitions).pack(fill=\"x\", pady=4)\n        tk.Button(mid, text=\"\ud83d\uddc2 Recover Selected Partition\", font=FONTS[\"small\"], bg=C[\"btn_warn\"], fg=C[\"text\"], bd=0, padx=10, pady=8, cursor=\"hand2\", command=self._start_recover_partition).pack(fill=\"x\", pady=4)\n\n        # Right: progress + partition details\n        right = tk.Frame(top_row, bg=C[\"card\"])\n        right.pack(side=\"left\", fill=\"both\", expand=True, padx=(4,6))\n        self.partition_progress_var = tk.DoubleVar(value=0.0)\n        self.partition_progress_bar = ttk.Progressbar(right, variable=self.partition_progress_var, maximum=100.0, mode=\"determinate\")\n        self.partition_progress_bar.pack(fill=\"x\", pady=(4,6))\n        self.partition_status_label = tk.Label(right, text=\"Ready\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"])\n        self.partition_status_label.pack(anchor=\"w\")\n\n        self.partition_info_text = scrolledtext.ScrolledText(right, height=12, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], wrap=\"word\", bd=0, relief=\"flat\")\n        self.partition_info_text.pack(fill=\"both\", expand=True, padx=4, pady=(6,4))\n        self.partition_info_text.config(state=\"disabled\")\n\n        # Partition results tree (below)\n        results_frame = tk.LabelFrame(body, text=\"Partitions / Results\", font=FONTS[\"subhead\"], fg=C[\"accent2\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        results_frame.pack(fill=\"both\", expand=True, padx=14, pady=(6, 12))\n        pcols = (\"Index\", \"Type\", \"Start LBA\", \"Sectors\", \"Size\")\n        self.partition_tree = ttk.Treeview(results_frame, columns=pcols, show=\"headings\", height=8, style=\"Custom.Treeview\")\n        for col, w in zip(pcols, (60, 120, 120, 120, 120)):\n            self.partition_tree.heading(col, text=col)\n            self.partition_tree.column(col, width=w, anchor=\"w\")\n        self.partition_tree.pack(fill=\"both\", expand=True, padx=8, pady=8)\n\n        # Ensure disks enumerated at build time\n        try:\n            self._launch_job(\"populate_recovery_disks\", self._populate_recovery_disks)\n        except Exception:\n            pass\n\n        return body\n\n    def _refresh_recovery_partitions(self):\n        source = self._resolve_disk_path(self.partition_source_var.get().strip() or DEFAULT_RAW_DISK)\n        try:\n            sector = self._forensic_read_at(source, 0, 512)\n            parts = self._parse_mbr_partitions(sector)\n            gpt = self._parse_gpt_entries(source)\n            lines = [f\"Source: {source}\", f\"MBR partitions: {len(parts)}\"]\n            for part in parts:\n                lines.append(f\"  #{part['index']} type={part['type']} start={part['start_lba']} sectors={part['sectors']} size={self._fmt_size(part['size'])}\")\n            if gpt:\n                lines.append(f\"GPT entries: {len(gpt.get('partitions', []))}\")\n                for part in gpt.get('partitions', []):\n                    lines.append(f\"  #{part['index']} name={part['name']} first={part['first_lba']} last={part['last_lba']} size={self._fmt_size(part['size'])}\")\n            if not parts and not gpt:\n                lines.append(\"No valid MBR/GPT partition table detected.\")\n        except Exception as exc:\n            lines = [f\"Partition parse failed: {exc}\"]\n        self.partition_info_text.config(state=\"normal\")\n        self.partition_info_text.delete(\"1.0\", \"end\")\n        self.partition_info_text.insert(\"end\", \"\\n\".join(lines))\n        self.partition_info_text.config(state=\"disabled\")\n        self._ui_queue.put((\"recovery_log\", f\"[Partition Recovery] Parsed partitions for {source}\"))\n\n    def _start_scan_partitions(self):\n        try:\n            sel = self.detected_disks_tree.selection()\n            if not sel:\n                messagebox.showwarning(\"Select Disk\", \"Koi disk select nahi hua. Pehle disk select karo.\")\n                return\n            disk_path = sel[0]\n            self.partition_source_var.set(disk_path)\n            self.partition_status_label.config(text=f\"Queued scan for {disk_path}\")\n            self.recovery_manager.submit_task(\"Scan Partitions\", self._task_scan_partitions, disk_path)\n        except Exception as e:\n            self._ui_queue.put((\"recovery_log\", f\"[Partition Recovery] Scan start failed: {e}\"))\n\n    def _task_scan_partitions(self, task, source):\n        try:\n            self._ui_queue.put((\"recovery_log\", f\"[Partition Recovery] Scanning partitions on {source}\"))\n            self._ui_queue.put((\"clone_progress\", (0, f\"Scanning {source}\", \"partition\")))\n            # Read and parse\n            sector = self._forensic_read_at(source, 0, 512)\n            parts = self._parse_mbr_partitions(sector)\n            gpt = self._parse_gpt_entries(source)\n            # Update partition tree in UI thread\n            def _update_tree():\n                try:\n                    self.partition_tree.delete(*self.partition_tree.get_children())\n                except Exception:\n                    pass\n                try:\n                    for part in parts:\n                        self.partition_tree.insert(\"\", \"end\", values=(part.get('index'), part.get('type'), part.get('start_lba'), part.get('sectors'), self._fmt_size(part.get('size'))))\n                    if gpt:\n                        for part in gpt.get('partitions', []):\n                            self.partition_tree.insert(\"\", \"end\", values=(part.get('index'), part.get('type','GPT'), part.get('first_lba'), part.get('last_lba') - part.get('first_lba') + 1, self._fmt_size(part.get('size'))))\n                except Exception:\n                    pass\n            self.after(0, _update_tree)\n            self._ui_queue.put((\"recovery_log\", f\"[Partition Recovery] Scan complete: {len(parts) + (len(gpt.get('partitions', [])) if gpt else 0)} partitions found\"))\n            self._ui_queue.put((\"clone_progress\", (100, \"Partition scan complete\", \"partition\")))\n        except Exception as exc:\n            self._ui_queue.put((\"recovery_log\", f\"[Partition Recovery] Scan failed: {exc}\"))\n            self._ui_queue.put((\"clone_progress\", (0, f\"Scan failed: {exc}\", \"partition\")))\n            raise\n\n    def _start_recover_partition(self):\n        try:\n            sel = self.partition_tree.selection()\n            if not sel:\n                messagebox.showwarning(\"Select Partition\", \"Koi partition select nahi hua. Pehle partition select karo.\")\n                return\n            vals = self.partition_tree.item(sel[0], 'values')\n            if not vals or len(vals) &lt; 4:\n                messagebox.showwarning(\"Invalid\", \"Selected partition data invalid.\")\n                return\n            start_lba = int(vals[2])\n            sectors = int(vals[3])\n            source = self.partition_source_var.get().strip() or DEFAULT_RAW_DISK\n            target = filedialog.asksaveasfilename(title=\"Save partition image as\", defaultextension=\".img\", filetypes=[(\"IMG\", \"*.img *.dd *.raw\"),(\"All\",\"*.*\")])\n            if not target:\n                return\n            if not messagebox.askyesno(\"Recover Partition\", f\"Recover partition start={start_lba} sectors={sectors} to:\\n{target}?\\nProceed?\"):\n                return\n            try:\n                get_recovery_safety(getattr(self, \"app_config\", None)).validate_write_path(target, source)\n            except Exception as exc:\n                messagebox.showerror(\"Recovery Safety\", str(exc))\n                return\n            max_bytes = sectors * SECTOR_SIZE\n            start_offset = start_lba * SECTOR_SIZE\n            self.recovery_manager.submit_task(\"Recover Partition\", self._task_recover_partition, source, start_offset, max_bytes, target)\n            self._ui_queue.put((\"recovery_log\", f\"[Partition Recovery] Queued partition recovery: {source} @ {start_lba}\"))\n        except Exception as e:\n            self._ui_queue.put((\"recovery_log\", f\"[Partition Recovery] Recover start failed: {e}\"))\n\n    def _task_recover_partition(self, task, source, start_offset, max_bytes, target_path):\n        try:\n            self._ui_queue.put((\"recovery_log\", f\"[Partition Recovery] Recovering {source}@{start_offset} -&gt; {target_path}\"))\n            def progress_cb(msg):\n                try:\n                    text = str(msg or \"\")\n                    m = re.search(r\"(\\d{1,3})%\", text)\n                    pct = int(m.group(1)) if m else 0\n                    self._ui_queue.put((\"clone_progress\", (pct, text, \"partition\")))\n                    self._ui_queue.put((\"recovery_log\", f\"[Partition Recovery] {text}\"))\n                except Exception:\n                    pass\n            copy_disk_range_to_img(source, target_path, start_offset=start_offset, max_bytes=max_bytes, progress_callback=progress_cb)\n            self._ui_queue.put((\"clone_progress\", (100, f\"Recovered: {target_path}\", \"partition\")))\n            self._ui_queue.put((\"recovery_log\", f\"[Partition Recovery] Recovery complete: {target_path}\"))\n        except Exception as e:\n            self._ui_queue.put((\"recovery_log\", f\"[Partition Recovery] Recovery failed: {e}\"))\n            self._ui_queue.put((\"clone_progress\", (0, f\"Recover failed: {e}\", \"partition\")))\n            raise\n\n    def _clone_selected_disk(self):\n        try:\n            source = self._resolve_disk_path(self.partition_source_var.get().strip() or DEFAULT_RAW_DISK)\n            path = filedialog.asksaveasfilename(\n                title=\"Save disk image as\",\n                defaultextension=\".img\",\n                filetypes=[(\"Disk image\", \"*.img *.dd *.raw\"), (\"All files\", \"*.*\")],\n                initialfile=f\"disk_clone_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.img\",\n            )\n            if not path:\n                return\n            if not messagebox.askyesno(\"Clone Disk\", f\"Clone {source} to:\\n{path}?\\n\\nProceed?\"):\n                return\n            if hasattr(self, \"clone_status_label\"):\n                self.clone_status_label.config(text=f\"\ud83d\udd04 Cloning {os.path.basename(source)} \u2192 {os.path.basename(path)}...\")\n            if hasattr(self, \"clone_progress_var\"):\n                try:\n                    self.clone_progress_var.set(0.0)\n                except Exception:\n                    pass\n            self.recovery_manager.submit_task(\"Clone Disk\", self._task_clone_disk, source, path)\n            self._ui_queue.put((\"recovery_log\", f\"[Clone Disk] Queued clone: {source} -&gt; {path}\"))\n        except Exception as e:\n            self._ui_queue.put((\"recovery_log\", f\"[Clone Disk] Error queuing clone: {e}\"))\n\n    def _task_clone_disk(self, task, source, img_path):\n        try:\n            self._ui_queue.put((\"recovery_log\", f\"[Clone Disk] Starting clone {source} -&gt; {img_path}\"))\n            def progress_cb(msg):\n                try:\n                    text = str(msg or \"\")\n                    # Send log line\n                    self._ui_queue.put((\"recovery_log\", f\"[Clone Disk] {text}\"))\n                    # Extract percentage if present\n                    m = re.search(r\"(\\d{1,3})%\", text)\n                    if m:\n                        try:\n                            pct = int(m.group(1))\n                        except Exception:\n                            pct = 0\n                        self._ui_queue.put((\"clone_progress\", (pct, text, \"clone\")))\n                    else:\n                        # If no percent, send text-only update\n                        self._ui_queue.put((\"clone_progress\", (0, text, \"clone\")))\n                except Exception:\n                    pass\n            # Use existing create_disk_image helper\n            # Reset UI\n            self._ui_queue.put((\"clone_progress\", (0, \"Starting clone...\", \"clone\")))\n            create_disk_image(source, img_path, max_bytes=None, progress_callback=progress_cb)\n            self._ui_queue.put((\"clone_progress\", (100, f\"Completed: {img_path}\", \"clone\")))\n            self._ui_queue.put((\"recovery_log\", f\"[Clone Disk] Completed: {img_path}\"))\n            self._ui_queue.put((\"recovery_queue\", None))\n        except Exception as e:\n            self._ui_queue.put((\"recovery_log\", f\"[Clone Disk] Failed: {e}\"))\n            try:\n                self._ui_queue.put((\"clone_progress\", (0, f\"Failed: {e}\", \"clone\")))\n            except Exception:\n                pass\n            raise\n\n    def _build_recovery_nand_tab(self, parent):\n        body = self._scrollable_section_body(parent)\n        card = tk.LabelFrame(body, text=\"\u26a1 NAND / Flash Analysis\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"], bd=1, relief=\"flat\")\n        card.pack(fill=\"x\", padx=14, pady=10)\n\n        self.nand_source_var = tk.StringVar(value=DEFAULT_RAW_DISK)\n        self.nand_sample_var = tk.StringVar(value=\"16\")\n\n        row = tk.Frame(card, bg=C[\"card\"])\n        row.pack(fill=\"x\", padx=10, pady=10)\n        tk.Label(row, text=\"Source:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=0, column=0, sticky=\"w\")\n        self.nand_source_combo = ttk.Combobox(row, textvariable=self.nand_source_var, values=self._get_recovery_disk_values(), width=40, state=\"readonly\")\n        self.nand_source_combo.grid(row=0, column=1, padx=4)\n        tk.Label(row, text=\"Sample MB:\", font=FONTS[\"body\"], fg=C[\"accent\"], bg=C[\"card\"]).grid(row=0, column=2, padx=(14,4), sticky=\"w\")\n        tk.Entry(row, textvariable=self.nand_sample_var, width=6, bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"]).grid(row=0, column=3, padx=4)\n        tk.Button(row, text=\"Analyze NAND\", font=FONTS[\"small\"], bg=C[\"btn_warn\"], fg=C[\"text\"], bd=0, padx=14, pady=8, cursor=\"hand2\", command=self._start_nand_analysis).grid(row=0, column=4, padx=(14,0))\n\n        self.nand_analysis_output = scrolledtext.ScrolledText(body, height=14, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], wrap=\"word\", bd=0, relief=\"flat\")\n        self.nand_analysis_output.pack(fill=\"both\", expand=True, padx=14, pady=(0, 14))\n        self.nand_analysis_output.config(state=\"disabled\")\n        return body\n\n    def _start_nand_analysis(self):\n        source = self._resolve_disk_path(self.nand_source_var.get().strip() or DEFAULT_RAW_DISK)\n        try:\n            sample_mb = max(1, int(self.nand_sample_var.get().strip()))\n        except Exception:\n            sample_mb = 16\n        self.recovery_manager.submit_task(\"NAND Analysis\", self._task_nand_analysis, source, sample_mb)\n        self._ui_queue.put((\"recovery_log\", f\"[NAND Analysis] Queued analysis for {source}\"))\n\n    def _task_nand_analysis(self, task, source, sample_mb):\n        self._ui_queue.put((\"recovery_log\", f\"[NAND Analysis] Sampling {sample_mb} MB from {source}\"))\n        try:\n            max_bytes = sample_mb * 1024 * 1024\n            sample_len = min(max_bytes, 4 * 1024 * 1024)\n            data = self._forensic_read_at(source, 0, sample_len)\n            if is_forensic_engine_available():\n                max_chunks = max(1, sample_mb // 4)\n                entropy_chunks = scan_disk_entropy(source, chunk_size=4 * 1024 * 1024, max_chunks=max_chunks)\n                erase_state = detect_nand_erase_state(data or b\"\")\n                headers = validate_media_headers(data or b\"\")\n                avg_entropy = (\n                    sum(e for _, e in entropy_chunks) / len(entropy_chunks) if entropy_chunks else 0.0\n                )\n                output = [\n                    f\"Source: {source}\",\n                    f\"Sample bytes: {len(data or b'')}\",\n                    f\"Avg entropy (chunks): {avg_entropy:.3f}\",\n                    f\"Entropy chunks: {len(entropy_chunks)}\",\n                    f\"Erase state: {erase_state}\",\n                    f\"Header validation: {headers}\",\n                ]\n            else:\n                entropy = self._shannon_entropy(data or b\"\")\n                erase_state = detect_nand_erase_state(data or b\"\")\n                output = [\n                    f\"Source: {source}\",\n                    f\"Forensic engine unavailable. Fallback entropy: {entropy:.2f}\",\n                    f\"Erase state: {erase_state}\",\n                ]\n            self.after(0, lambda out=\"\\n\".join(output): self._display_nand_output(out))\n            self._ui_queue.put((\"recovery_log\", f\"[NAND Analysis] Completed for {source}\"))\n        except Exception as exc:\n            self._ui_queue.put((\"recovery_log\", f\"[NAND Analysis] Error: {exc}\"))\n            raise\n\n    def _display_nand_output(self, text):\n        if not hasattr(self, \"nand_analysis_output\"):\n            return\n        self.nand_analysis_output.config(state=\"normal\")\n        self.nand_analysis_output.delete(\"1.0\", \"end\")\n        self.nand_analysis_output.insert(\"end\", text)\n        self.nand_analysis_output.config(state=\"disabled\")\n\n    def _build_recovery_queue_tab(self, parent):\n        body = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(body, \"\ud83d\udccc Recovery Queue\", \"Queued forensic and recovery tasks with cancel/pause control.\")\n        control_row = tk.Frame(body, bg=C[\"bg\"])\n        control_row.pack(fill=\"x\", padx=16, pady=(8, 2))\n        tk.Button(control_row, text=\"\u26d4 Cancel Selected\", font=FONTS[\"small\"], bg=C[\"btn_danger\"], fg=C[\"text\"], bd=0, padx=12, pady=6, cursor=\"hand2\", command=self._recovery_cancel_selected).pack(side=\"left\", padx=4)\n        tk.Button(control_row, text=\"\u23f8 Pause Selected\", font=FONTS[\"small\"], bg=C[\"btn_warn\"], fg=C[\"text\"], bd=0, padx=12, pady=6, cursor=\"hand2\", command=self._recovery_pause_selected).pack(side=\"left\", padx=4)\n        tk.Button(control_row, text=\"\u25b6 Resume Selected\", font=FONTS[\"small\"], bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=12, pady=6, cursor=\"hand2\", command=self._recovery_resume_selected).pack(side=\"left\", padx=4)\n\n        tree_frame = tk.Frame(body, bg=C[\"card\"])\n        tree_frame.pack(fill=\"both\", expand=True, padx=16, pady=10)\n        cols = (\"Task\", \"Status\", \"Progress\", \"Message\")\n        self.recovery_queue_tree = ttk.Treeview(tree_frame, columns=cols, show=\"headings\", style=\"Custom.Treeview\")\n        for col, width in zip(cols, (260, 120, 100, 420)):\n            self.recovery_queue_tree.heading(col, text=col)\n            self.recovery_queue_tree.column(col, width=width, anchor=\"w\")\n        self.recovery_queue_tree.pack(fill=\"both\", expand=True, side=\"left\")\n        yscroll = ttk.Scrollbar(tree_frame, orient=\"vertical\", command=self.recovery_queue_tree.yview)\n        yscroll.pack(side=\"right\", fill=\"y\")\n        self.recovery_queue_tree.configure(yscrollcommand=yscroll.set)\n        return body\n\n    def _recovery_cancel_selected(self):\n        sel = self.recovery_queue_tree.selection()\n        if not sel:\n            messagebox.showinfo(\"Select Task\", \"Ek task select karo.\")\n            return\n        for iid in sel:\n            self.recovery_manager.cancel_task(iid)\n        self._refresh_recovery_queue_tree()\n\n    def _recovery_pause_selected(self):\n        sel = self.recovery_queue_tree.selection()\n        if not sel:\n            messagebox.showinfo(\"Select Task\", \"Ek task select karo.\")\n            return\n        for iid in sel:\n            self.recovery_manager.pause_task(iid)\n        self._refresh_recovery_queue_tree()\n\n    def _recovery_resume_selected(self):\n        sel = self.recovery_queue_tree.selection()\n        if not sel:\n            messagebox.showinfo(\"Select Task\", \"Ek task select karo.\")\n            return\n        for iid in sel:\n            self.recovery_manager.resume_task(iid)\n        self._refresh_recovery_queue_tree()\n\n    def _build_recovery_logs_tab(self, parent):\n        body = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(body, \"\ud83d\udcda Recovery Logs\", \"Centralized log stream for recovery operations.\")\n        self.recovery_log_text = scrolledtext.ScrolledText(body, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], wrap=\"word\", bd=0, relief=\"flat\")\n        self.recovery_log_text.pack(fill=\"both\", expand=True, padx=16, pady=(10, 10))\n        self.recovery_log_text.config(state=\"disabled\")\n        btn_row = tk.Frame(body, bg=C[\"bg\"])\n        btn_row.pack(fill=\"x\", padx=16, pady=(0, 10))\n        tk.Button(btn_row, text=\"\ud83d\uddd1 Clear Log\", font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text\"], bd=0, padx=12, pady=6, cursor=\"hand2\", command=lambda: (self.recovery_log_text.config(state=\"normal\"), self.recovery_log_text.delete(\"1.0\",\"end\"), self.recovery_log_text.config(state=\"disabled\"))).pack(side=\"left\", padx=4)\n        tk.Button(btn_row, text=\"\ud83d\udcbe Save Log\", font=FONTS[\"small\"], bg=C[\"accent2\"], fg=\"#000\", bd=0, padx=12, pady=6, cursor=\"hand2\", command=self._save_recovery_log).pack(side=\"left\", padx=4)\n        return body\n\n    def _save_recovery_log(self):\n        try:\n            data = self.recovery_log_text.get(\"1.0\", \"end\").strip()\n            if not data:\n                messagebox.showinfo(\"No Log\", \"Recovery log empty hai.\")\n                return\n            path = os.path.join(os.path.expanduser(\"~\"), \"Desktop\", f\"Godawari_Recovery_Log_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.txt\")\n            with open(path, \"w\", encoding=\"utf-8\") as f:\n                f.write(data)\n            messagebox.showinfo(\"Saved\", f\"Log saved to Desktop:\\n{path}\")\n        except Exception as exc:\n            messagebox.showerror(\"Save Failed\", str(exc))\n\n    def _build_recovery_history_tab(self, parent):\n        body = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(body, \"\ud83d\uddc4\ufe0f Recovery History\", \"Session history and recovered object timeline.\")\n        btn_row = tk.Frame(body, bg=C[\"bg\"])\n        btn_row.pack(fill=\"x\", padx=16, pady=(8, 4))\n        tk.Button(btn_row, text=\"\ud83d\udd04 Refresh\", font=FONTS[\"small\"], bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=12, pady=6, cursor=\"hand2\", command=self._refresh_recovery_history).pack(side=\"left\")\n        self.recovery_history_tree = ttk.Treeview(body, columns=(\"Session\", \"Date\", \"Files\", \"Location\"), show=\"headings\", style=\"Custom.Treeview\")\n        for col, width in zip((\"Session\", \"Date\", \"Files\", \"Location\"), (220, 140, 90, 420)):\n            self.recovery_history_tree.heading(col, text=col)\n            self.recovery_history_tree.column(col, width=width, anchor=\"w\")\n        self.recovery_history_tree.pack(fill=\"both\", expand=True, padx=16, pady=(8, 12))\n        self._refresh_recovery_history()\n        return body\n\n    def _refresh_recovery_history(self):\n        tree = getattr(self, \"recovery_history_tree\", None)\n        if tree is None:\n            return\n        try:\n            for iid in tree.get_children():\n                tree.delete(iid)\n            base = getattr(self, \"recovery_sessions_dir\", os.path.join(os.path.expanduser(\"~\"), \"Desktop\"))\n            if not os.path.exists(base):\n                os.makedirs(base, exist_ok=True)\n            entries = []\n            for root, _, files in os.walk(base):\n                for fn in files:\n                    if fn.lower().endswith(\".json\") or fn.lower().endswith(\".log\"):\n                        path = os.path.join(root, fn)\n                        entries.append((fn, datetime.datetime.fromtimestamp(os.path.getmtime(path)).strftime(\"%Y-%m-%d %H:%M:%S\"), \"1\", root))\n            for row in sorted(entries, key=lambda x: x[1], reverse=True)[:80]:\n                tree.insert(\"\", \"end\", values=row)\n        except Exception:\n            pass\n\n    def _shannon_entropy(self, data: bytes) -&gt; float:\n        if not data:\n            return 0.0\n        freq = {}\n        for byte in data:\n            freq[byte] = freq.get(byte, 0) + 1\n        entropy = 0.0\n        length = len(data)\n        for count in freq.values():\n            p = count / length\n            entropy -= p * (0 if p &lt;= 0 else math.log2(p))\n        return entropy\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # ZONE C BACKEND \u2014 Batch Integrity Verifier\n    # Real SHA256 file hashing, fully threaded, queue-throttled UI updates\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _integ_log_write(self, msg):\n        \"\"\"Thread-safe write into Zone C log via after().\"\"\"\n        def _w():\n            try:\n                self._integ_log.config(state=\"normal\")\n                self._integ_log.insert(\"end\", msg + \"\\n\")\n                self._integ_log.see(\"end\")\n                self._integ_log.config(state=\"disabled\")\n            except Exception:\n                pass\n        self.after(0, _w)\n\n    def _integ_use_rec_dest(self):\n        \"\"\"Populate integrity folder from last known recovery destination.\"\"\"\n        d = getattr(self, \"_last_recovery_dest\", \"\")\n        if d and os.path.isdir(d):\n            self._integ_dir_var.set(d)\n        else:\n            messagebox.showinfo(\"No Dest\", \"Pehle Zone A/B se files recover karo, folder auto-fill ho jayega.\")\n\n    def _start_integrity_verifier(self):\n        \"\"\"Atomic-guarded launcher for Zone C background thread.\"\"\"\n        with self._rec_integrity_lock:\n            if self._recovery_is_processing:\n                messagebox.showwarning(\"Busy\", \"Ek operation pehle se chal raha hai. Wait karo.\")\n                return\n            folder = self._integ_dir_var.get().strip()\n            if not folder or not os.path.isdir(folder):\n                messagebox.showwarning(\"Folder\", \"Valid folder select karo.\")\n                return\n            self._recovery_is_processing = True\n            self._integ_run_btn.config(state=\"disabled\")\n\n        self._launch_job(\n            \"integrity_verify\",\n            self._do_integrity_verify,\n            folder,\n            self._integ_recurse_var.get(),\n            self._integ_export_var.get()\n        )\n\n    def _do_integrity_verify(self, folder, recurse, export_csv):\n        \"\"\"\n        Background worker \u2014 Zone C.\n        Walks folder, computes real SHA256 of every file, checks size / readability.\n        UI updates throttled to once per 120 ms via time.monotonic() guard.\n        No time.sleep() fakes. Every byte read is real OS I/O.\n        \"\"\"\n        results = []          # (path, size_bytes, sha256, status)\n        total_files  = 0\n        ok_files     = 0\n        corrupt_files = 0\n        zero_files   = 0\n        last_ui      = time.monotonic()\n\n        try:\n            # \u2500\u2500 collect files \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            all_files = []\n            if recurse:\n                for root_d, _, fnames in os.walk(folder):\n                    for fn in fnames:\n                        all_files.append(os.path.join(root_d, fn))\n            else:\n                for fn in os.listdir(folder):\n                    fp = os.path.join(folder, fn)\n                    if os.path.isfile(fp):\n                        all_files.append(fp)\n\n            total_files = len(all_files)\n            self._integ_log_write(f\"\u25b6 {total_files} files mili \u2014 SHA256 verification shuru\u2026\")\n\n            def _ui_update(idx, msg, pct):\n                now = time.monotonic()\n                if now - last_ui &gt;= 0.120:\n                    def _upd(m=msg, p=pct):\n                        try:\n                            self._integ_stat_lbl.config(text=m)\n                            self._integ_prog_var.set(p)\n                        except Exception:\n                            pass\n                    self.after(0, _upd)\n                    return now\n                return last_ui\n\n            for idx, fp in enumerate(all_files):\n                try:\n                    fsize = os.path.getsize(fp)\n                    if fsize == 0:\n                        status = \"ZERO_BYTE\"\n                        sha = \"\u2014\"\n                        zero_files += 1\n                    else:\n                        h = hashlib.sha256()\n                        try:\n                            with open(fp, \"rb\") as fh:\n                                for chunk in iter(lambda: fh.read(65536), b\"\"):\n                                    h.update(chunk)\n                            sha = h.hexdigest()\n                            status = \"OK\"\n                            ok_files += 1\n                        except (PermissionError, OSError) as read_err:\n                            sha = \"READ_ERROR\"\n                            status = f\"CORRUPT ({read_err.__class__.__name__})\"\n                            corrupt_files += 1\n                    results.append((fp, fsize, sha, status))\n                    pct = round((idx + 1) / max(total_files, 1) * 100, 1)\n                    msg_txt = (f\"\ud83d\udd10 Verifying {idx+1}/{total_files} | \u2705{ok_files} OK \"\n                               f\"| \u26a0{corrupt_files} Corrupt | 0\ufe0f\u20e3{zero_files} Zero\")\n                    last_ui = _ui_update(idx, msg_txt, pct)\n\n                    if status != \"OK\":\n                        self._integ_log_write(f\"  [{status}] {os.path.basename(fp)}\")\n\n                except Exception as file_err:\n                    results.append((fp, 0, \"ERROR\", str(file_err)))\n                    corrupt_files += 1\n                    self._integ_log_write(f\"  \u274c {os.path.basename(fp)}: {file_err}\")\n\n            # \u2500\u2500 final UI \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            final_msg = (f\"\u2705 Verification complete \u2014 {ok_files} OK | \"\n                         f\"{corrupt_files} Corrupt/Unreadable | {zero_files} Zero-byte\")\n            self.after(0, lambda: self._integ_stat_lbl.config(text=final_msg))\n            self.after(0, lambda: self._integ_prog_var.set(100))\n            self._integ_log_write(final_msg)\n\n            # \u2500\u2500 CSV export \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            if export_csv and results:\n                out_path = os.path.join(folder, f\"integrity_report_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.csv\")\n                try:\n                    with open(out_path, \"w\", newline=\"\", encoding=\"utf-8-sig\") as cf:\n                        w = csv.writer(cf)\n                        w.writerow([\"Path\", \"Size_Bytes\", \"SHA256\", \"Status\"])\n                        w.writerows(results)\n                    self._integ_log_write(f\"\ud83d\udce5 CSV saved: {out_path}\")\n                    self.after(0, lambda p=out_path: messagebox.showinfo(\n                        \"Report Saved\", f\"\u2705 Integrity CSV saved:\\n{p}\"))\n                except Exception as csv_err:\n                    self._integ_log_write(f\"\u274c CSV export failed: {csv_err}\")\n\n        except Exception as ex:\n            self._integ_log_write(f\"\u274c Fatal error: {ex}\")\n            self.after(0, lambda: self._integ_stat_lbl.config(text=f\"\u274c Error: {ex}\"))\n        finally:\n            # \u2500\u2500 strict resource cleanup \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            results.clear()\n            gc.collect()\n            with self._rec_integrity_lock:\n                self._recovery_is_processing = False\n            self.after(0, lambda: self._integ_run_btn.config(state=\"normal\"))\n\n    def _ensure_admin_for_raw_recovery(self, disk_path=None):\n        if disk_path and not _is_raw_device_path(disk_path):\n            return True\n        if is_admin():\n            return True\n        if messagebox.askyesno(\n            \"Admin Required\",\n            \"Raw disk recovery ke liye Administrator rights mandatory hain.\\n\\n\"\n            \"App ko admin mode me restart karein?\"\n        ):\n            run_as_admin()\n        return False\n\n    def _raw_disk_path(self):\n        return (self.raw_disk_var.get() if hasattr(self, \"raw_disk_var\") else DEFAULT_RAW_DISK).strip() or DEFAULT_RAW_DISK\n\n    def _forensic_read_at(self, source, offset, length):\n        if source and os.path.exists(source) and not _is_raw_device_path(source):\n            with open(source, \"rb\") as f:\n                f.seek(offset)\n                return f.read(length)\n        return _read_raw_at(source, offset, length)\n\n    def _parse_mbr_partitions(self, sector):\n        parts = []\n        if len(sector) &lt; 512 or sector[510:512] != b\"\\x55\\xAA\":\n            return parts\n        for idx in range(4):\n            off = 446 + idx * 16\n            ent = sector[off:off + 16]\n            if len(ent) &lt; 16:\n                continue\n            ptype = ent[4]\n            start = struct.unpack_from(\" 512:\n                    tail = self._forensic_read_at(source, max(0, size - 512), 512)\n            except Exception:\n                pass\n            if head.startswith(b\"vhdxfile\"):\n                return \"VHDX\"\n            if tail[0:8] == b\"conectix\":\n                return \"VHD\"\n            if head.startswith(b\"EVF\\x09\") or head.startswith(b\"LVF\\x09\"):\n                return \"E01\"\n            return ext.lstrip(\".\").upper() or \"RAW_FILE\"\n        except Exception:\n            return \"UNKNOWN\"\n\n    def _parse_gpt_entries(self, source):\n        try:\n            header = self._forensic_read_at(source, 512, 512)\n            if len(header) &lt; 92 or header[:8] != b\"EFI PART\":\n                return None\n            entry_lba = struct.unpack_from(\"= first_lba else 0,\n                    \"size\": ((last_lba - first_lba + 1) * SECTOR_SIZE) if last_lba &gt;= first_lba else 0,\n                    \"name\": name or \"(no name)\",\n                    \"attrs\": attrs,\n                    \"type_guid\": str(uuid.UUID(bytes_le=ent[:16])),\n                    \"part_guid\": str(uuid.UUID(bytes_le=ent[16:32])),\n                })\n            return {\n                \"disk_guid\": str(uuid.UUID(bytes_le=disk_guid_raw)),\n                \"entry_lba\": entry_lba,\n                \"entry_count\": entry_count,\n                \"entry_size\": entry_size,\n                \"partitions\": parts,\n            }\n        except Exception:\n            return None\n\n    def _parse_ntfs_runlist(self, data):\n        runs = []\n        i = 0\n        current_lcn = 0\n        while i &lt; len(data):\n            header = data[i]\n            i += 1\n            if header == 0:\n                break\n            len_size = header &amp; 0x0F\n            off_size = (header &gt;&gt; 4) &amp; 0x0F\n            if i + len_size + off_size &gt; len(data):\n                break\n            run_len = int.from_bytes(data[i:i + len_size], \"little\", signed=False)\n            i += len_size\n            run_off = int.from_bytes(data[i:i + off_size], \"little\", signed=True)\n            i += off_size\n            current_lcn += run_off\n            runs.append((current_lcn, run_len))\n        return runs\n\n    def _parse_ntfs_data_runs(self, rec):\n        if len(rec) &lt; 64 or rec[:4] != b\"FILE\":\n            return []\n        used = struct.unpack_from(\" len(rec):\n                break\n            nonresident = rec[pos + 8]\n            name_len = rec[pos + 9]\n            name_off = struct.unpack_from(\" len(rec):\n                    break\n                nonresident = rec[pos + 8]\n                if atype == 0x30 and not nonresident:\n                    vlen = struct.unpack_from(\"= 66:\n                        parent = struct.unpack_from(\" 1 else (\"contiguous\" if run_count == 1 else \"resident/unknown\")\n                lines.append(\n                    f\"- #{item.get('record')} [{state}/{kind}] {item.get('name')} | path={path_text} | \"\n                    f\"size={item.get('real_size','')} | modified={item.get('modified','')} | parent={item.get('parent_ref','')} | runs={run_count} {frag}\"\n                )\n            lines.append(\"\")\n            lines.append(\"Special NTFS metadata records:\")\n            for key in [\"$mft\", \"$mftmirr\", \"$bitmap\", \"$logfile\", \"$usnjrnl\"]:\n                if key in special:\n                    item = special[key]\n                    lines.append(f\"- {key}: record #{item.get('record')} path={self._reconstruct_ntfs_path(item, name_map)}\")\n                else:\n                    lines.append(f\"- {key}: sample range me not observed\")\n            lines.append(\"\")\n            lines.append(\"Professional note:\")\n            lines.append(\"- Ye sample parser original filename, deleted flag, timestamps, parent references aur best-effort path reconstruction prove karta hai.\")\n            lines.append(\"- Non-resident DATA runs parse kiye gaye hain; multiple runs fragmented file ka strong clue dete hain.\")\n            lines.append(\"- $Bitmap / $LogFile / $UsnJrnl presence recovery confidence aur filesystem timeline analysis me useful hoti hai.\")\n            report = \"\\n\".join(lines)\n            self._raw_recovery_progress(\"NTFS MFT sample complete.\")\n            self.after(0, lambda: self._open_raw_hex_window(0, report))\n        except Exception as e:\n            err = str(e)\n            self._raw_recovery_progress(f\"MFT sample failed: {err}\")\n            self.after(0, lambda err=err: messagebox.showerror(\"MFT Parser Error\", err))\n\n    def _shadow_copy_recovery_report(self):\n        self._reset_raw_progress(\"Shadow Copy enumeration...\")\n        self._launch_job(\"shadow_copy_report\", self._do_shadow_copy_recovery_report)\n\n    def _do_shadow_copy_recovery_report(self):\n        try:\n            out1, _ = self._run_cmd(\"vssadmin list shadows\", timeout=60)\n            out2, _ = self._run_cmd(\"wmic shadowcopy get ID,InstallDate,OriginatingMachine,VolumeName /format:list\", timeout=60)\n            report = (\n                \"Shadow Copy Recovery Report\\n\"\n                f\"Generated: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\\n\\n\"\n                \"Troubleshoot kya kiya:\\n\"\n                \"- vssadmin list shadows run kiya.\\n\"\n                \"- WMIC shadowcopy inventory collect ki.\\n\\n\"\n                \"Recovery guidance:\\n\"\n                \"- Shadow copy available ho to deleted files previous snapshot se copy kiye ja sakte hain.\\n\"\n                \"- Evidence-safe workflow: source snapshot read-only mount/copy, original disk par write mat karo.\\n\\n\"\n                f\"vssadmin output:\\n{out1 or 'No shadows or access denied.'}\\n\\n\"\n                f\"WMIC output:\\n{out2 or 'No WMIC shadow data.'}\\n\"\n            )\n            self._raw_recovery_progress(\"Shadow Copy report complete.\")\n            self.after(0, lambda: self._open_raw_hex_window(0, report))\n        except Exception as e:\n            err = str(e)\n            self._raw_recovery_progress(f\"Shadow Copy report failed: {err}\")\n\n    def _score_recovered_file(self, path):\n        try:\n            size = os.path.getsize(path)\n            with open(path, \"rb\") as f:\n                head = f.read(4096)\n                if size &gt; 4096:\n                    f.seek(max(0, size - 4096))\n                    tail = f.read(4096)\n                else:\n                    tail = head\n            ext = Path(path).suffix.lower().lstrip(\".\")\n            score = \"Partial (55)\"\n            reason = \"Header/footer unknown.\"\n            checks = {\n                \"jpg\": (head.startswith(b\"\\xff\\xd8\\xff\"), tail.rstrip().endswith(b\"\\xff\\xd9\")),\n                \"jpeg\": (head.startswith(b\"\\xff\\xd8\\xff\"), tail.rstrip().endswith(b\"\\xff\\xd9\")),\n                \"png\": (head.startswith(b\"\\x89PNG\\r\\n\\x1a\\n\"), b\"IEND\" in tail),\n                \"pdf\": (head.startswith(b\"%PDF\"), b\"%%EOF\" in tail),\n                \"zip\": (head.startswith(b\"PK\\x03\\x04\"), b\"PK\\x05\\x06\" in tail or b\"PK\\x06\\x06\" in tail),\n                \"docx\": (head.startswith(b\"PK\\x03\\x04\"), b\"PK\\x05\\x06\" in tail or b\"PK\\x06\\x06\" in tail),\n                \"xlsx\": (head.startswith(b\"PK\\x03\\x04\"), b\"PK\\x05\\x06\" in tail or b\"PK\\x06\\x06\" in tail),\n                \"pptx\": (head.startswith(b\"PK\\x03\\x04\"), b\"PK\\x05\\x06\" in tail or b\"PK\\x06\\x06\" in tail),\n            }\n            if ext in checks:\n                h_ok, f_ok = checks[ext]\n                if h_ok and f_ok:\n                    score, reason = \"Excellent (95)\", \"Header aur footer dono valid.\"\n                elif h_ok:\n                    score, reason = \"Partial (65)\", \"Header valid, footer missing/fragmented.\"\n                else:\n                    score, reason = \"Corrupted (20)\", \"Expected header missing.\"\n            if size == 0:\n                score, reason = \"Corrupted (0)\", \"Zero-byte recovered file.\"\n            return score, reason\n        except Exception as e:\n            return \"Unknown\", str(e)\n\n    def _forensic_hash_verify_dialog(self):\n        folder = filedialog.askdirectory(title=\"Recovered files folder select karo\")\n        if not folder:\n            return\n        self._reset_raw_progress(\"Hash + forensic verification running...\")\n        self._launch_job(\"forensic_hash_verify\", self._do_forensic_hash_verify, folder)\n\n    def _do_forensic_hash_verify(self, folder):\n        try:\n            rows = []\n            by_sha256 = {}\n            count = 0\n            for root, dirs, files in os.walk(folder):\n                for name in files:\n                    if getattr(self, \"_recovery_stop_flag\", False):\n                        break\n                    path = os.path.join(root, name)\n                    try:\n                        md5 = hashlib.md5()\n                        sha1 = hashlib.sha1()\n                        sha256 = hashlib.sha256()\n                        with open(path, \"rb\") as f:\n                            for chunk in iter(lambda: f.read(1024 * 1024), b\"\"):\n                                md5.update(chunk); sha1.update(chunk); sha256.update(chunk)\n                        score, reason = self._score_recovered_file(path)\n                        item = {\n                            \"path\": path,\n                            \"size\": os.path.getsize(path),\n                            \"md5\": md5.hexdigest(),\n                            \"sha1\": sha1.hexdigest(),\n                            \"sha256\": sha256.hexdigest(),\n                            \"score\": score,\n                            \"reason\": reason,\n                        }\n                        rows.append(item)\n                        by_sha256.setdefault(item[\"sha256\"], []).append(path)\n                        count += 1\n                        if count % 50 == 0:\n                            self._raw_recovery_progress(f\"Hashed {count} files...\")\n                    except Exception as e:\n                        rows.append({\"path\": path, \"error\": str(e)})\n            dups = {h: ps for h, ps in by_sha256.items() if len(ps) &gt; 1}\n            report_path = os.path.join(folder, \"Godawari_Forensic_Hash_Report.csv\")\n            with open(report_path, \"w\", newline=\"\", encoding=\"utf-8\") as f:\n                writer = csv.DictWriter(f, fieldnames=[\"path\", \"size\", \"md5\", \"sha1\", \"sha256\", \"score\", \"reason\", \"error\"])\n                writer.writeheader()\n                for row in rows:\n                    writer.writerow({k: row.get(k, \"\") for k in writer.fieldnames})\n            lines = [\n                \"Hash + Forensic Verification Report\",\n                f\"Folder: {folder}\",\n                f\"Files processed: {len(rows)}\",\n                f\"Duplicate SHA256 groups: {len(dups)}\",\n                f\"CSV report: {report_path}\",\n                \"\",\n                \"Recoverability scoring:\",\n                \"- Excellent: header/footer valid\",\n                \"- Partial: header valid but footer missing/fragmented\",\n                \"- Corrupted: expected header missing\",\n                \"\",\n                \"Duplicate groups:\",\n            ]\n            for h, ps in list(dups.items())[:20]:\n                lines.append(f\"- {h}: {len(ps)} files\")\n                lines.extend(f\"  {p}\" for p in ps[:5])\n            report = \"\\n\".join(lines)\n            self._raw_recovery_progress(\"Hash verification complete.\")\n            self.after(0, lambda: self._open_raw_hex_window(0, report))\n        except Exception as e:\n            err = str(e)\n            self._raw_recovery_progress(f\"Hash verification failed: {err}\")\n\n    def _recovery_session_db_path(self):\n        return os.path.join(getattr(self, \"backup_dir\", os.getcwd()), \"recovery_sessions.sqlite3\")\n\n    def _recovery_session_db_save(self):\n        try:\n            items = []\n            if hasattr(self, \"rec_tree\"):\n                for iid in self.rec_tree.get_children():\n                    vals = self.rec_tree.item(iid, \"values\")\n                    items.append(tuple(vals))\n            if not items and hasattr(self, \"rec_found_files\"):\n                for entry in self.rec_found_files.values():\n                    if isinstance(entry, str):\n                        p = entry\n                    elif isinstance(entry, dict):\n                        p = entry.get(\"path\") or \"\"\n                    else:\n                        continue\n                    if p:\n                        items.append((os.path.basename(str(p)), Path(str(p)).suffix.lstrip(\".\"), \"\", str(p)))\n            if not items:\n                messagebox.showinfo(\"No Session\", \"Recovery result list empty hai.\")\n                return\n            db_path = self._recovery_session_db_path()\n            os.makedirs(os.path.dirname(db_path), exist_ok=True)\n            con = sqlite3.connect(db_path)\n            try:\n                cur = con.cursor()\n                cur.execute(\"CREATE TABLE IF NOT EXISTS sessions(id INTEGER PRIMARY KEY, ts TEXT, source TEXT, note TEXT)\")\n                cur.execute(\"CREATE TABLE IF NOT EXISTS files(session_id INTEGER, filename TEXT, ext TEXT, size TEXT, path TEXT)\")\n                source = self._raw_disk_path() if hasattr(self, \"raw_disk_var\") else \"\"\n                cur.execute(\"INSERT INTO sessions(ts, source, note) VALUES(?,?,?)\", (datetime.datetime.now().isoformat(timespec=\"seconds\"), source, \"GUI recovery session\"))\n                sid = cur.lastrowid\n                cur.executemany(\"INSERT INTO files(session_id, filename, ext, size, path) VALUES(?,?,?,?,?)\", [(sid,) + tuple(x[:4]) for x in items])\n                con.commit()\n            finally:\n                con.close()\n            msg = f\"Recovery session saved: {db_path}\\nSession items: {len(items)}\"\n            self._raw_recovery_progress(msg)\n            messagebox.showinfo(\"Session Saved\", msg)\n        except Exception as e:\n            messagebox.showerror(\"Session DB Error\", str(e))\n\n    def _begin_recovery_operation(self, label):\n        if getattr(self, \"_recovery_active\", False):\n            raise RuntimeError(\"Ek recovery task already chal raha hai. Pehle usko complete/stop hone dein.\")\n        self._recovery_stop_flag = False\n        self._recovery_pause_flag = False\n        self._recovery_active = True\n        self._active_recovery_session_id = None\n        try:\n            mgr = getattr(self, \"recovery_session_manager\", None)\n            if mgr:\n                self._active_recovery_session_id = mgr.start(\n                    \"file_recovery\", {\"label\": str(label)})\n        except Exception:\n            pass\n        if hasattr(self, \"_rec_stop_btn\"):\n            self._rec_stop_btn.config(state=\"normal\")\n        if hasattr(self, \"_rec_pause_btn\"):\n            self._rec_pause_btn.config(state=\"normal\", text=\"\u23f8 Pause\")\n        self._set_status(label, C[\"warning\"])\n\n    def _finish_recovery_operation(self):\n        sid = getattr(self, \"_active_recovery_session_id\", None)\n        if sid:\n            try:\n                status = \"stopped\" if getattr(self, \"_recovery_stop_flag\", False) else \"completed\"\n                self.recovery_session_manager.complete(sid, status=status)\n            except Exception:\n                pass\n            self._active_recovery_session_id = None\n        self._recovery_active = False\n        self._recovery_pause_flag = False\n        if hasattr(self, \"_rec_stop_btn\"):\n            self._rec_stop_btn.config(state=\"disabled\")\n        if hasattr(self, \"_rec_pause_btn\"):\n            self._rec_pause_btn.config(state=\"disabled\", text=\"\u23f8 Pause\")\n\n    def _is_mobile_source(self, drive_text):\n        d = (drive_text or \"\").strip().lower()\n        return d in {\"mobile\", \"android\", \"phone\", \"mobile_deep\", \"android_deep\"} or d.startswith(\"android\")\n\n    def _android_media_preset(self, preset):\n        # Force Android mode + set exts presets; roots override used by mobile finder\n        try:\n            self.rec_drive.set(\"Android\")\n        except Exception:\n            pass\n        if preset == \"whatsapp\":\n            self.rec_ext.delete(0, \"end\")\n            self.rec_ext.insert(0, \"jpg,jpeg,png,mp4\")\n            self._mobile_roots_override = [\"/sdcard/WhatsApp/Media\", \"/sdcard/Android/media\"]\n        else:\n            self.rec_ext.delete(0, \"end\")\n            self.rec_ext.insert(0, \"jpg,jpeg,png,mp4\")\n            self._mobile_roots_override = [\"/sdcard/DCIM\", \"/sdcard/Pictures\", \"/sdcard/Movies\"]\n        self._start_file_recovery()\n\n    def _mobile_bridge_help(self):\n        cmd = os.environ.get(\"GODAWARI_MOBILE_BRIDGE_CMD\", \"\").strip()\n        messagebox.showinfo(\n            \"Mobile Bridge\",\n            \"Advanced mobile recovery ke liye optional bridge available hai.\\n\\n\"\n            \"Env var set karo:\\n\"\n            \"GODAWARI_MOBILE_BRIDGE_CMD = \\n\\n\"\n            \"Bridge command JSON list output kare:\\n\"\n            \"[\\\"/sdcard/path/file1.jpg\\\", \\\"...\\\" ]\\n\\n\"\n            f\"Current: {cmd if cmd else '(not set)'}\"\n        )\n\n    def _mobile_bridge_candidates(self, exts):\n        \"\"\"\n        Optional external bridge for advanced mobile recovery.\n        Set env var GODAWARI_MOBILE_BRIDGE_CMD to a command that outputs JSON list of paths.\n        \"\"\"\n        cmd = os.environ.get(\"GODAWARI_MOBILE_BRIDGE_CMD\", \"\").strip()\n        if not cmd:\n            return []\n        exts_arg = \",\".join(sorted({e.lower().strip(\".\") for e in exts if e.strip()}))\n        out, rc = self._run_cmd(f'{cmd} --ext \"{exts_arg}\"', timeout=180)\n        if rc != 0 or not out.strip():\n            return []\n        try:\n            data = json.loads(out)\n            if isinstance(data, list):\n                return [str(x) for x in data if str(x).strip()]\n        except Exception:\n            return []\n        return []\n\n    def _mobile_adb_available(self):\n        out, rc = self._run_cmd(self._adb_args(\"version\"), timeout=10)\n        return rc == 0 and \"android debug bridge\" in out.lower()\n\n    def _mobile_device_ready(self):\n        out, rc = self._run_cmd(self._adb_args(\"devices\"), timeout=10)\n        if rc != 0:\n            return False\n        for ln in out.splitlines()[1:]:\n            parts = ln.strip().split()\n            if len(parts) &gt;= 2 and parts[1].strip().lower() == \"device\":\n                return True\n        return False\n\n    def _find_adb_exe(self):\n        cached = getattr(self, \"_adb_exe_cache\", None)\n        if cached and os.path.isfile(cached):\n            return cached\n        candidates = []\n        env_direct = os.environ.get(\"ADB_PATH\", \"\").strip().strip('\"')\n        if env_direct:\n            candidates.append(env_direct)\n        for name in (\"adb.exe\", \"adb\"):\n            found = shutil.which(name)\n            if found:\n                candidates.append(found)\n        local_appdata = os.environ.get(\"LOCALAPPDATA\", \"\")\n        user_profile = os.environ.get(\"USERPROFILE\", \"\")\n        common_roots = [\n            os.getcwd(),\n            os.path.dirname(os.path.abspath(sys.argv[0])),\n            local_appdata,\n            user_profile,\n            os.path.join(local_appdata, \"Android\"),\n            os.path.join(local_appdata, \"Android\", \"Sdk\"),\n            os.path.join(user_profile, \"AppData\", \"Local\", \"Android\", \"Sdk\"),\n            os.path.join(user_profile, \"Downloads\"),\n            os.path.join(user_profile, \"Desktop\"),\n        ]\n        rels = [\n            \"platform-tools\\\\adb.exe\",\n            \"Android\\\\Sdk\\\\platform-tools\\\\adb.exe\",\n            \"sdk\\\\platform-tools\\\\adb.exe\",\n            \"tools\\\\platform-tools\\\\adb.exe\",\n        ]\n        for root in common_roots:\n            if not root:\n                continue\n            for rel in rels:\n                candidates.append(os.path.join(root, rel))\n        seen = set()\n        for path in candidates:\n            try:\n                norm = os.path.normcase(os.path.abspath(path))\n            except Exception:\n                norm = os.path.normcase(str(path))\n            if norm in seen:\n                continue\n            seen.add(norm)\n            if os.path.isfile(path):\n                self._adb_exe_cache = path\n                return path\n        return \"\"\n\n    def _adb_cmd(self, args):\n        adb_exe = self._find_adb_exe() or \"adb\"\n        return f'\"{adb_exe}\" {args}'.strip()\n\n    def _adb_args(self, *args):\n        adb_exe = self._find_adb_exe() or \"adb\"\n        return [adb_exe, *[str(a) for a in args]]\n\n    def _show_adb_help(self):\n        detected = self._find_adb_exe()\n        hint = detected if detected else \"Not detected\"\n        messagebox.showinfo(\n            \"ADB Required\",\n            \"Mobile recovery ke liye Android Platform Tools required hain.\\n\\n\"\n            f\"Detected ADB: {hint}\\n\\n\"\n            \"Setup:\\n\"\n            \"1. Android phone me USB debugging ON karo\\n\"\n            \"2. Platform Tools install/unzip karo\\n\"\n            \"3. adb.exe ko PATH me add karo ya ADB_PATH env var set karo\\n\"\n            \"4. Phone ko authorize karke retry karo\"\n        )\n\n    def _refresh_adb_status_label(self):\n        if not hasattr(self, \"adb_status_label\"):\n            return\n        adb_exe = self._find_adb_exe()\n        if not adb_exe:\n            text = \"ADB Status: Not Found\"\n            color = C[\"error\"]\n        elif self._mobile_device_ready():\n            text = \"ADB Status: Device Authorized\"\n            color = C[\"success\"]\n        else:\n            text = \"ADB Status: Found, device not authorized\"\n            color = C[\"warning\"]\n        self.adb_status_label.config(text=text, fg=color)\n\n    def _mobile_find_candidates(self, exts):\n        exts = [e.lower().strip(\".\") for e in exts if e.strip()]\n        roots = getattr(self, \"_mobile_roots_override\", None) or [\n            \"/sdcard/DCIM\", \"/sdcard/Download\", \"/sdcard/Pictures\", \"/sdcard/Movies\",\n            \"/sdcard/WhatsApp/Media\", \"/sdcard/Android/media\", \"/storage/emulated/0\",\n        ]\n        found = []\n        seen = set()\n        # Build a filtered find expression to reduce output volume\n        patterns = []\n        for ext in sorted({e for e in exts if e}):\n            # Use -iname for case-insensitive match\n            patterns.append(f\"-iname '*.{ext}'\")\n        expr = \"\"\n        if patterns:\n            expr = \"\\\\( \" + \" -o \".join(patterns[:20]) + \" \\\\)\"\n        for root in roots:\n            if getattr(self, \"_recovery_stop_flag\", False):\n                break\n            while getattr(self, \"_recovery_pause_flag\", False):\n                if getattr(self, \"_recovery_stop_flag\", False):\n                    break\n                time.sleep(0.2)\n            shell_script = \"if [ -d '\" + root + \"' ]; then find '\" + root + \"' -type f \"\n            if expr:\n                shell_script += expr + \" \"\n            shell_script += \"2&gt;/dev/null; fi\"\n            proc = subprocess.Popen(self._adb_args(\"shell\", shell_script), shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, encoding=\"utf-8\", errors=\"replace\")\n            try:\n                for line in proc.stdout:\n                    if getattr(self, \"_recovery_stop_flag\", False):\n                        proc.terminate()\n                        break\n                    while getattr(self, \"_recovery_pause_flag\", False):\n                        if getattr(self, \"_recovery_stop_flag\", False):\n                            proc.terminate()\n                            break\n                        time.sleep(0.2)\n                    p = line.strip()\n                    if not p:\n                        continue\n                    low = p.lower()\n                    if (not exts or any(low.endswith(\".\" + ext) for ext in exts)) and low not in seen:\n                        seen.add(low)\n                        found.append(p)\n                        if len(found) % 100 == 0:\n                            self._raw_recovery_progress(f\"MOBILE scan: {len(found)} files matched...\")\n            finally:\n                try:\n                    proc.wait(timeout=2)\n                except Exception:\n                    pass\n        # Extra recovery hint: media scanner cache can include recently indexed files.\n        try:\n            cmd = self._adb_args(\"shell\", \"find /sdcard -name .thumbnails -o -name LOST.DIR 2&gt;/dev/null\")\n            out, rc = self._run_cmd(cmd, timeout=25)\n            if rc == 0 and out.strip():\n                self._raw_recovery_progress(\"MOBILE hint: thumbnail/LOST.DIR folders bhi detect hui hain.\")\n        except Exception:\n            pass\n        bridge_items = self._mobile_bridge_candidates(exts)\n        if bridge_items:\n            for p in bridge_items:\n                low = p.lower()\n                if low not in seen:\n                    seen.add(low)\n                    found.append(p)\n            self._raw_recovery_progress(f\"MOBILE bridge added {len(bridge_items)} candidate(s)\")\n        return found\n\n    def _recovery_checkpoint_path(self, mode):\n        safe = re.sub(r\"[^a-zA-Z0-9_.-]+\", \"_\", str(mode or \"default\"))\n        return os.path.join(getattr(self, \"backup_dir\", os.getcwd()), f\"recovery_checkpoint_{safe}.json\")\n\n    def _save_recovery_checkpoint(self, mode, data):\n        try:\n            path = self._recovery_checkpoint_path(mode)\n            payload = {\n                \"ts\": datetime.datetime.now().isoformat(timespec=\"seconds\"),\n                \"mode\": mode,\n                \"data\": data,\n            }\n            with open(path, \"w\", encoding=\"utf-8\") as f:\n                json.dump(payload, f, ensure_ascii=False)\n        except Exception:\n            pass\n\n    def _load_recovery_checkpoint(self, mode):\n        try:\n            path = self._recovery_checkpoint_path(mode)\n            if not os.path.exists(path):\n                return None\n            with open(path, \"r\", encoding=\"utf-8\") as f:\n                payload = json.load(f)\n            if payload.get(\"mode\") != mode:\n                return None\n            return payload.get(\"data\")\n        except Exception:\n            return None\n\n    def _clear_recovery_checkpoint(self, mode):\n        try:\n            path = self._recovery_checkpoint_path(mode)\n            if os.path.exists(path):\n                os.remove(path)\n        except Exception:\n            pass\n\n    def _sha256_file(self, path):\n        h = hashlib.sha256()\n        with open(path, \"rb\") as f:\n            while True:\n                chunk = f.read(1024 * 1024)\n                if not chunk:\n                    break\n                h.update(chunk)\n        return h.hexdigest()\n\n    def _mobile_pull_with_retry(self, src, dst):\n        out = \"\"\n        for _ in range(3):\n            out, rc = self._run_cmd(self._adb_args(\"pull\", src, dst), timeout=300)\n            if rc == 0 and os.path.exists(dst):\n                return True, out\n            time.sleep(0.4)\n        return False, out\n\n    def _integrity_score(self, path, file_type_hint=\"\"):\n        try:\n            size = os.path.getsize(path)\n            if size &lt;= 0:\n                return 0, \"empty file\"\n            score = 40\n            reason = [\"file exists\"]\n            ext = (file_type_hint or os.path.splitext(path)[1].lstrip(\".\")).lower()\n            if size &gt; 1024:\n                score += 20\n                reason.append(\"size&gt;1KB\")\n            if size &gt; 1024 * 1024:\n                score += 10\n                reason.append(\"size&gt;1MB\")\n            if ext in (\"jpg\", \"jpeg\", \"png\", \"pdf\", \"zip\", \"mp4\", \"exe\"):\n                with open(path, \"rb\") as f:\n                    data = f.read(min(size, 8 * 1024 * 1024))\n                if ext in (\"jpg\", \"jpeg\") and data.startswith(b\"\\xFF\\xD8\"):\n                    score += 15\n                    reason.append(\"jpeg header ok\")\n                elif ext == \"png\" and data.startswith(b\"\\x89PNG\\r\\n\\x1A\\n\"):\n                    score += 15\n                    reason.append(\"png header ok\")\n                elif ext == \"pdf\" and data.startswith(b\"%PDF\"):\n                    score += 15\n                    reason.append(\"pdf header ok\")\n                elif ext == \"zip\" and data.startswith(b\"PK\\x03\\x04\"):\n                    score += 15\n                    reason.append(\"zip header ok\")\n                elif ext == \"mp4\" and b\"ftyp\" in data[:128]:\n                    score += 15\n                    reason.append(\"mp4 ftyp ok\")\n                elif ext == \"exe\" and data.startswith(b\"MZ\"):\n                    score += 15\n                    reason.append(\"mz header ok\")\n            return max(0, min(100, score)), \", \".join(reason)\n        except Exception as e:\n            return 20, f\"basic only ({e})\"\n\n    def _check_recovery_control(self):\n        if getattr(self, \"_recovery_stop_flag\", False):\n            raise InterruptedError(\"Recovery stopped by user.\")\n        paused_notice = False\n        while getattr(self, \"_recovery_pause_flag\", False):\n            if not paused_notice:\n                paused_notice = True\n                self.after(0, lambda: self._set_status(\"Recovery paused - Resume dabao\", C[\"warning\"]))\n            time.sleep(0.25)\n            if getattr(self, \"_recovery_stop_flag\", False):\n                raise InterruptedError(\"Recovery stopped by user.\")\n\n    def _update_raw_source_badge(self):\n        if not hasattr(self, \"raw_source_badge\"):\n            return\n        src = self._raw_disk_path()\n        if _is_raw_device_path(src):\n            self.raw_source_badge.config(text=\"RAW DEVICE - admin required\", fg=C[\"warning\"])\n        elif os.path.isfile(src):\n            self.raw_source_badge.config(text=\"IMG FILE - scan without admin\", fg=C[\"success\"])\n        else:\n            self.raw_source_badge.config(text=\"SOURCE NOT FOUND\", fg=C[\"error\"])\n\n    def _reset_raw_progress(self, message=\"Ready\"):\n        if hasattr(self, \"raw_progress_var\"):\n            self.raw_progress_var.set(0)\n        if hasattr(self, \"raw_progress_bar\"):\n            try:\n                self.raw_progress_bar.stop()\n            except Exception:\n                pass\n            self.raw_progress_bar.config(mode=\"determinate\")\n        if hasattr(self, \"raw_progress_label\"):\n            self.raw_progress_label.config(text=message)\n        if hasattr(self, \"raw_progress_log\"):\n            try:\n                self.raw_progress_log.config(state=\"normal\")\n                self.raw_progress_log.delete(\"1.0\", \"end\")\n                self.raw_progress_log.insert(\"end\", message + \"\\n\")\n                self.raw_progress_log.config(state=\"disabled\")\n            except Exception:\n                pass\n\n    def _append_log_line(self, text):\n        if hasattr(self, \"raw_progress_log\"):\n            try:\n                self.raw_progress_log.config(state=\"normal\")\n                self.raw_progress_log.insert(\"end\", text + \"\\n\")\n                self.raw_progress_log.see(\"end\")\n                self.raw_progress_log.config(state=\"disabled\")\n            except Exception:\n                pass\n\n    def _recovery_reset_ui_batch(self):\n        self._rec_pending_rows = []\n        self._rec_pending_progress = None\n        self._rec_pending_log = None\n        self._rec_flush_scheduled = False\n        if not hasattr(self, \"_rec_batch_lock\"):\n            self._rec_batch_lock = threading.Lock()\n\n    def _recovery_schedule_flush(self):\n        with self._rec_batch_lock:\n            if self._rec_flush_scheduled:\n                return\n            self._rec_flush_scheduled = True\n        self.after(80, self._recovery_flush_ui_batch)\n\n    def _recovery_queue_row(self, row, entry):\n        \"\"\"\n        Thread-safe row enqueue. Routes through _ui_queue so the main thread\n        can batch-insert rows without any direct widget access from threads.\n        \"\"\"\n        self._q_tree_row(row, entry)\n\n    def _recovery_set_drive_progress(self, scanned, file_count, dirpath):\n        \"\"\"\n        Thread-safe progress update. Enqueues label+log via _ui_queue.\n        Can be called from any thread.\n        \"\"\"\n        folder_tail = dirpath[-65:] if len(dirpath) &gt; 65 else dirpath\n        label_text = (\n            f\"\ud83d\udd0d Scanning...  {scanned:,} folders  |  {file_count:,} files mili  |  ...{folder_tail}\")\n        self._q(\"progress_label\", label_text)\n        self._q_log(dirpath)\n\n    def _recovery_flush_ui_batch(self):\n        \"\"\"\n        Drain any tree-row messages still sitting in the UI queue (main-thread only).\n        Called at the end of a scan to ensure no rows are left unrendered.\n        The heavy lifting is now done by _poll_ui_queue() every 50 ms.\n        \"\"\"\n        # Drain up to 500 pending tree_row messages from the queue\n        MAX_FLUSH = 500\n        processed = 0\n        try:\n            while processed &lt; MAX_FLUSH:\n                msg_type, payload = self._ui_queue.get_nowait()\n                processed += 1\n                if msg_type == \"tree_row\" and hasattr(self, \"rec_tree\"):\n                    row, entry = payload\n                    try:\n                        iid = self.rec_tree.insert(\"\", \"end\", values=row, tags=(\"found\",))\n                        if not isinstance(getattr(self, \"rec_found_files\", None), dict):\n                            self.rec_found_files = {}\n                        self.rec_found_files[iid] = entry\n                    except Exception:\n                        pass\n                elif msg_type == \"progress_label\" and hasattr(self, \"raw_progress_label\"):\n                    self.raw_progress_label.config(text=str(payload)[:200])\n                elif msg_type == \"log_line\":\n                    self._append_log_line(str(payload))\n        except _queue_module.Empty:\n            pass\n        self._on_rec_select()\n    def _prep_drive_scan_progress_ui(self):\n        self._recovery_reset_ui_batch()\n        if hasattr(self, \"raw_progress_bar\"):\n            try:\n                self.raw_progress_bar.stop()\n            except Exception:\n                pass\n            self.raw_progress_bar.config(mode=\"indeterminate\")\n            self.raw_progress_bar.start(10)\n        if hasattr(self, \"raw_progress_var\"):\n            self.raw_progress_var.set(0)\n\n    def _prep_raw_scan_progress_ui(self):\n        if hasattr(self, \"raw_progress_bar\"):\n            try:\n                self.raw_progress_bar.stop()\n            except Exception:\n                pass\n            self.raw_progress_bar.config(mode=\"indeterminate\")\n            try:\n                self.raw_progress_bar.start(5)\n            except Exception:\n                pass\n        if hasattr(self, \"raw_progress_var\"):\n            self.raw_progress_var.set(0)\n\n    def _on_rec_select(self, event=None):\n        total = len(self.rec_tree.get_children()) if hasattr(self, \"rec_tree\") else 0\n        sel = len(self.rec_tree.selection()) if hasattr(self, \"rec_tree\") else 0\n        if hasattr(self, \"rec_stats_label\"):\n            self.rec_stats_label.config(text=f\"{total:,} files | {sel} selected\")\n\n    def _make_recovery_progress_callback(self):\n        def cb(msg):\n            self._raw_recovery_progress(msg)\n            m = re.match(r\"Pass \\d+: recovered (.+)\", msg, re.I)\n            if m and hasattr(self, \"rec_tree\"):\n                filename = m.group(1).strip()\n                ext = os.path.splitext(filename)[1].lstrip(\".\").upper() or \"?\"\n                row = (filename, ext, \"\u2014\", \"Recovered \u2014 verifying...\", \"Raw Scan\", \"--\")\n\n                def _ins(r=row, fn=filename):\n                    iid = self.rec_tree.insert(\"\", \"end\", values=r, tags=(\"found\",))\n                    self.rec_found_files[iid] = {\"kind\": \"photorec_live\", \"path\": fn, \"filename\": fn}\n\n                self.after(0, _ins)\n        return cb\n\n    def _clear_recovery_progress_log(self):\n        if hasattr(self, \"raw_progress_log\"):\n            try:\n                self.raw_progress_log.config(state=\"normal\")\n                self.raw_progress_log.delete(\"1.0\", \"end\")\n                self.raw_progress_log.config(state=\"disabled\")\n            except Exception:\n                pass\n\n    def _set_recovery_scan_mode(self, text, fg=None):\n        if hasattr(self, \"scan_mode_label\"):\n            self.scan_mode_label.config(text=text, fg=fg or C[\"accent4\"])\n\n    def _update_rec_stats(self):\n        if not hasattr(self, \"rec_stats_label\"):\n            return\n        n = len(self.rec_tree.get_children()) if hasattr(self, \"rec_tree\") else 0\n        sel = len(self.rec_tree.selection()) if hasattr(self, \"rec_tree\") else 0\n        self.rec_stats_label.config(text=f\"{n:,} files | {sel:,} selected\")\n\n    def _clear_recovery_results(self):\n        if hasattr(self, \"rec_tree\"):\n            self.rec_tree.delete(*self.rec_tree.get_children())\n        self.rec_found_files = {}\n        if hasattr(self, \"raw_progress_var\"):\n            self.raw_progress_var.set(0)\n        if hasattr(self, \"raw_progress_label\"):\n            self.raw_progress_label.config(text=\"List saaf kar di gayi.\")\n        self._update_rec_stats()\n\n    def _raw_limit_bytes(self):\n        try:\n            raw_value = (self.raw_scan_mb.get() or \"\").strip()\n            if not raw_value:\n                return None\n            mb = int(raw_value)\n            if mb &lt;= 0:\n                return None\n            return mb * 1024 * 1024\n        except Exception:\n            return None\n\n    def _raw_file_types_from_entry(self):\n        mapping = {\n            \"JPG\": \"JPG\", \"JPEG\": \"JPG\",\n            \"PDF\": \"PDF\",\n            \"MP4\": \"MP4\", \"M4V\": \"MP4\", \"MOV\": \"MP4\",\n            \"ZIP\": \"ZIP\", \"DOCX\": \"ZIP\", \"XLSX\": \"ZIP\", \"PPTX\": \"ZIP\",\n            \"EXE\": \"EXE\",\n        }\n        types = []\n        for part in self.rec_ext.get().split(\",\"):\n            key = part.strip().strip(\".\").upper()\n            if key in mapping and mapping[key] not in types:\n                types.append(mapping[key])\n        return types or list(SIGNATURES.keys())\n\n    def _insert_raw_results(self, disk_path, results):\n        self.rec_tree.delete(*self.rec_tree.get_children())\n        self.rec_found_files = {}\n        for counter, item in enumerate(results, start=1):\n            file_type = item[\"file_type\"]\n            ext = item.get(\"extension\") or SIGNATURES.get(file_type, {}).get(\"ext\", \"\")\n            offset = item[\"offset\"]\n            display_name = f\"{file_type}_{counter:04d}{ext}\"\n            max_sz = SIGNATURES.get(file_type, {}).get(\"max_size\", 0)\n            est_size = f\"~{_human_size(max(max_sz // 8, SECTOR_SIZE))} est.\" if max_sz else \"\u2014\"\n            conf = str(item.get(\"confidence\", \"medium\"))\n            location = f\"Sector {item['sector']:,}  |  {conf.title()}\"\n            iid = self.rec_tree.insert(\"\", \"end\", values=(\n                display_name, file_type, est_size,\n                \"Found \u2014 Recover dabao \u25b6\", location, \"--\"), tags=(\"found\",))\n            self.rec_found_files[iid] = {\n                \"kind\": \"raw\",\n                \"disk_path\": disk_path,\n                \"offset\": offset,\n                \"file_type\": file_type,\n                \"display_name\": display_name,\n            }\n        self.after(0, self._on_rec_select)\n\n    def _raw_recovery_progress(self, msg):\n        self._check_recovery_control()\n        def _do(m=msg):\n            display = m if len(m) &lt;= 140 else (m[:137] + \"...\")\n            if hasattr(self, \"raw_progress_label\"):\n                self.raw_progress_label.config(text=display)\n            if hasattr(self, \"raw_progress_log\"):\n                try:\n                    self.raw_progress_log.config(state=\"normal\")\n                    self.raw_progress_log.insert(\"end\", self._fix_text(m) + \"\\n\")\n                    if float(self.raw_progress_log.index(\"end-1c\").split(\".\")[0]) &gt; 200:\n                        self.raw_progress_log.delete(\"1.0\", \"50.0\")\n                    self.raw_progress_log.see(\"end\")\n                    self.raw_progress_log.config(state=\"disabled\")\n                except Exception:\n                    pass\n            if hasattr(self, \"raw_progress_var\"):\n                pct = None\n                match = re.search(r\"Pass\\s+([12])\\s*:\\s*(\\d{1,3})%\", m, re.I)\n                if match:\n                    pass_num = int(match.group(1))\n                    pass_pct = max(0, min(100, int(match.group(2))))\n                    pct = (pass_pct * 0.45) if pass_num == 1 else 45 + (pass_pct * 0.45)\n                else:\n                    generic = re.search(r\"(\\d{1,3})%\\s*complete\", m, re.I)\n                    if generic:\n                        pct = max(0, min(100, int(generic.group(1))))\n                if pct is None:\n                    m2 = re.search(r\"(\\d{1,3})%\\s*complete\", m, re.I)\n                    if m2:\n                        pct = max(0, min(100, int(m2.group(1))))\n                if pct is None and \"AUTO 1/4\" in m:\n                    pct = 5\n                elif pct is None and \"AUTO 2/4\" in m:\n                    pct = 20\n                elif pct is None and \"AUTO 3/4\" in m:\n                    pct = max(float(self.raw_progress_var.get()), 25)\n                elif pct is None and \"AUTO 4/4\" in m:\n                    pct = 95\n                elif pct is None and (\"complete\" in m.lower() or \"done\" in m.lower()):\n                    pct = 100\n                elif pct is None and (\"start\" in m.lower() or \"start ho\" in m.lower()):\n                    pct = 1\n                if pct is not None and hasattr(self, \"raw_progress_bar\"):\n                    try:\n                        self.raw_progress_bar.stop()\n                    except Exception:\n                        pass\n                    self.raw_progress_bar.config(mode=\"determinate\")\n                    self.raw_progress_var.set(max(0, min(100, pct)))\n                elif hasattr(self, \"raw_progress_bar\"):\n                    try:\n                        self.raw_progress_bar.config(mode=\"indeterminate\")\n                        self.raw_progress_bar.start(5)\n                    except Exception:\n                        pass\n        self.after(0, _do)\n\n    def _start_raw_signature_scan(self):\n        disk_path = self._raw_disk_path()\n        self._update_raw_source_badge()\n        if not self._ensure_admin_for_raw_recovery(disk_path):\n            return\n        limit = self._raw_limit_bytes()\n        file_types = self._raw_file_types_from_entry()\n        limit_text = \"FULL DISK\" if limit is None else self._fmt_size(limit)\n        if not messagebox.askyesno(\n            \"Raw Signature Scan\",\n            f\"Raw disk scan start karein?\\n\\n\"\n            f\"Disk: {disk_path}\\n\"\n            f\"Limit: {limit_text}\\n\"\n            f\"Types: {', '.join(file_types)}\\n\\n\"\n            \"Yeh read-only scan hai, lekin time lag sakta hai.\"\n        ):\n            return\n        self.rec_tree.delete(*self.rec_tree.get_children())\n        self.rec_found_files = {}\n        self._set_recovery_scan_mode(\"Mode: Zone B \u2014 Raw Sector Recovery (Admin)\", C[\"warning\"])\n        self._clear_recovery_progress_log()\n        self._prep_raw_scan_progress_ui()\n        self._reset_raw_progress(\"Raw signature scan start ho raha hai...\")\n        try:\n            self._begin_recovery_operation(\"Raw signature scan start ho raha hai...\")\n        except Exception as e:\n            messagebox.showwarning(\"Recovery Busy\", str(e))\n            return\n        if not self._hdd_action_submit(\"raw_signature_scan\", self._do_raw_signature_scan, disk_path, limit, file_types):\n            self._set_status(\"Recovery action already running; wait for completion.\", C[\"warning\"])\n\n    def _do_raw_signature_scan(self, disk_path, limit, file_types):\n        try:\n            results = scan_disk_for_files(\n                disk_path,\n                max_bytes=limit,\n                file_types=file_types,\n                progress_callback=self._make_recovery_progress_callback(),\n            )\n\n            def _populate():\n                self._insert_raw_results(disk_path, results)\n                self._set_status(f\"Raw scan complete: {len(results)} signatures mile\", C[\"success\"])\n\n            self.after(0, _populate)\n        except InterruptedError as e:\n            msg = str(e)\n            self.after(0, lambda msg=msg: self._set_status(msg, C[\"warning\"]))\n        except Exception as e:\n            err = str(e)\n            self.after(0, lambda err=err: self._set_status(\"Raw scan failed: \" + err, C[\"error\"]))\n            self.after(0, lambda err=err: messagebox.showerror(\"Raw Scan Error\", err))\n        finally:\n            self.after(0, self._finish_recovery_operation)\n\n    def _create_img_dialog(self):\n        disk_path = self._raw_disk_path()\n        self._update_raw_source_badge()\n        if not self._ensure_admin_for_raw_recovery(disk_path):\n            return\n        limit = self._raw_limit_bytes()\n        img_path = filedialog.asksaveasfilename(\n            title=\"IMG file save location\",\n            defaultextension=\".img\",\n            filetypes=[(\"Disk image\", \"*.img\"), (\"All files\", \"*.*\")]\n        )\n        if not img_path:\n            return\n        limit_text = \"FULL DISK\" if limit is None else self._fmt_size(limit)\n        if not messagebox.askyesno(\n            \"Create Disk Image\",\n            f\"IMG backup banani hai?\\n\\nDisk: {disk_path}\\nOutput: {img_path}\\nSize: {limit_text}\\n\\n\"\n            \"Note: Full disk image bahut badi ho sakti hai.\"\n        ):\n            return\n        self._reset_raw_progress(\"IMG creation start ho rahi hai...\")\n        try:\n            self._begin_recovery_operation(\"IMG creation start ho rahi hai...\")\n        except Exception as e:\n            messagebox.showwarning(\"Recovery Busy\", str(e))\n            return\n        if not self._hdd_action_submit(\"raw_create_img\", self._do_create_img, disk_path, img_path, limit):\n            self._set_status(\"Recovery action already running; wait for completion.\", C[\"warning\"])\n\n    def _do_create_img(self, disk_path, img_path, limit):\n        try:\n            result = create_disk_image(disk_path, img_path, max_bytes=limit, progress_callback=self._raw_recovery_progress)\n            self.after(0, lambda: self._set_status(f\"IMG complete: {self._fmt_size(result['bytes'])}\", C[\"success\"]))\n            self.after(0, lambda: messagebox.showinfo(\"IMG Complete\", f\"IMG ban gayi:\\n{result['img_path']}\\n\\nSize: {self._fmt_size(result['bytes'])}\"))\n        except InterruptedError as e:\n            msg = str(e)\n            self.after(0, lambda msg=msg: self._set_status(msg, C[\"warning\"]))\n        except Exception as e:\n            err = str(e)\n            self.after(0, lambda err=err: self._set_status(\"IMG failed: \" + err, C[\"error\"]))\n            self.after(0, lambda err=err: messagebox.showerror(\"IMG Error\", err))\n        finally:\n            self.after(0, self._finish_recovery_operation)\n\n    def _start_auto_raw_recovery(self):\n        disk_path = self._raw_disk_path()\n        self._update_raw_source_badge()\n        if not self._ensure_admin_for_raw_recovery(disk_path):\n            return\n        limit = self._raw_limit_bytes()\n        file_types = self._raw_file_types_from_entry()\n        output_dir = filedialog.askdirectory(title=\"Recovered data save karne ke liye folder select karo\")\n        if not output_dir:\n            return\n        limit_text = \"FULL DISK\" if limit is None else self._fmt_size(limit)\n        if not messagebox.askyesno(\n            \"AUTO All Process\",\n            f\"Auto recovery workflow start karein?\\n\\n\"\n            f\"1. IMG backup banegi\\n\"\n            f\"2. Raw signature scan hoga\\n\"\n            f\"3. Found files auto extract hongi\\n\"\n            f\"4. Real hex preview show hoga\\n\\n\"\n            f\"Disk: {disk_path}\\n\"\n            f\"Scan/Image Size: {limit_text}\\n\"\n            f\"Types: {', '.join(file_types)}\\n\"\n            f\"Output: {output_dir}\\n\\n\"\n            \"Note: Large scan size se time aur storage dono lagenge.\"\n        ):\n            return\n        self.rec_tree.delete(*self.rec_tree.get_children())\n        self.rec_found_files = {}\n        self._set_recovery_scan_mode(\"Mode: Zone B \u2014 Raw Sector Recovery (Admin)\", C[\"warning\"])\n        self._clear_recovery_progress_log()\n        self._reset_raw_progress(\"AUTO recovery start ho rahi hai...\")\n        try:\n            self._begin_recovery_operation(\"AUTO recovery start ho rahi hai...\")\n        except Exception as e:\n            messagebox.showwarning(\"Recovery Busy\", str(e))\n            return\n        if not self._hdd_action_submit(\"auto_raw_recovery\", self._do_auto_raw_recovery, disk_path, limit, file_types, output_dir):\n            self._set_status(\"Recovery action already running; wait for completion.\", C[\"warning\"])\n\n    def _do_auto_raw_recovery(self, disk_path, limit, file_types, output_dir):\n        recovered = []\n        warnings = []\n        img_result = None\n        try:\n            stamp = datetime.datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n            img_path = os.path.join(output_dir, f\"raw_backup_{stamp}.img\")\n            self._raw_recovery_progress(\"AUTO 1/4: IMG backup ban rahi hai...\")\n            img_result = create_disk_image(disk_path, img_path, max_bytes=limit, progress_callback=self._raw_recovery_progress)\n\n            source_for_scan = img_result[\"img_path\"] if img_result and img_result.get(\"bytes\", 0) &gt; 0 else disk_path\n            self._raw_recovery_progress(\"AUTO 2/4: IMG import/source ready ho gaya...\")\n            self.after(0, lambda src=source_for_scan: self.raw_disk_var.set(src))\n\n            self._raw_recovery_progress(\"AUTO 3/4: PhotoRec multi-pass recovery chal rahi hai...\")\n            photo_result = multi_pass_recovery(\n                source_for_scan, output_dir,\n                progress_callback=self._make_recovery_progress_callback())\n            recovered = photo_result[\"files\"]\n\n            self._raw_recovery_progress(\"AUTO 4/4: Real hex preview read ho raha hai...\")\n            first_sector = recovered[0][\"offset\"] // SECTOR_SIZE if recovered else 0\n            hex_text = raw_hex_viewer(first_sector, disk_path=source_for_scan)\n\n            def _finish():\n                self._set_status(f\"AUTO complete: {len(recovered)} files recovered\", C[\"success\"])\n                file_map = {os.path.basename(f[\"path\"]): f for f in recovered}\n                seen_basenames = set()\n                for iid in list(self.rec_tree.get_children()):\n                    vals = list(self.rec_tree.item(iid, \"values\"))\n                    if not vals:\n                        continue\n                    bn = vals[0]\n                    seen_basenames.add(bn)\n                    if bn in file_map:\n                        item = file_map[bn]\n                        loc = item[\"path\"][-60:] if len(item[\"path\"]) &gt; 60 else item[\"path\"]\n                        self.rec_tree.item(iid, values=(\n                            bn, item[\"file_type\"], self._fmt_size(item[\"bytes\"]),\n                            \"\u2705 Recovered\", loc, \"--\"), tags=(\"recovered\",))\n                        self.rec_found_files[iid] = item[\"path\"]\n                for item in recovered:\n                    bn = os.path.basename(item[\"path\"])\n                    if bn in seen_basenames:\n                        continue\n                    loc = item[\"path\"][-60:] if len(item[\"path\"]) &gt; 60 else item[\"path\"]\n                    iid = self.rec_tree.insert(\"\", \"end\", values=(\n                        bn, item[\"file_type\"], self._fmt_size(item[\"bytes\"]),\n                        \"\u2705 Recovered\", loc, \"--\"), tags=(\"recovered\",))\n                    self.rec_found_files[iid] = item[\"path\"]\n                self._on_rec_select()\n                self._show_auto_recovery_result(output_dir, img_result, photo_result, recovered, warnings, hex_text)\n\n            self.after(0, _finish)\n        except InterruptedError as e:\n            msg = str(e)\n            self.after(0, lambda msg=msg: self._set_status(msg, C[\"warning\"]))\n        except Exception as e:\n            err = str(e)\n            self.after(0, lambda err=err: self._set_status(\"AUTO recovery failed: \" + err, C[\"error\"]))\n            self.after(0, lambda err=err: messagebox.showerror(\"AUTO Recovery Error\", err))\n        finally:\n            self.after(0, self._finish_recovery_operation)\n\n    def _show_auto_recovery_result(self, output_dir, img_result, results, recovered, warnings, hex_text):\n        win = tk.Toplevel(self)\n        win.title(\"AUTO Recovery Result\")\n        win.geometry(\"1100x720\")\n        win.configure(bg=C[\"bg\"])\n        if isinstance(results, dict):\n            found_count = len(results.get(\"files\", []))\n            recup_dir = results.get(\"recup_dir\", output_dir)\n            block_size = results.get(\"block_size\", \"N/A\")\n        else:\n            found_count = len(results)\n            recup_dir = output_dir\n            block_size = \"N/A\"\n        summary = (\n            f\"AUTO RECOVERY COMPLETE\\n\"\n            f\"Output Folder: {output_dir}\\n\"\n            f\"recup_dir: {recup_dir}\\n\"\n            f\"Block size: {block_size}\\n\"\n            f\"IMG: {(img_result or {}).get('img_path', 'N/A')}\\n\"\n            f\"IMG Size: {self._fmt_size((img_result or {}).get('bytes', 0))}\\n\"\n            f\"Signatures/Files Found: {found_count}\\n\"\n            f\"Files Recovered: {len(recovered)}\\n\"\n            f\"Warnings: {len(warnings)}\\n\"\n            f\"\\nRecovered Files:\\n\"\n        )\n        if recovered:\n            summary += \"\\n\".join(f\"- {item['path']} ({self._fmt_size(item['bytes'])})\" for item in recovered[:80])\n            if len(recovered) &gt; 80:\n                summary += f\"\\n... aur {len(recovered) - 80} files\"\n        else:\n            summary += \"Koi file extract nahi hui.\"\n        if warnings:\n            summary += \"\\n\\nWarnings:\\n\" + \"\\n\".join(warnings[:40])\n        summary += \"\\n\\nREAL HEX PREVIEW:\\n\" + hex_text\n        viewer = scrolledtext.ScrolledText(win, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], wrap=\"none\")\n        viewer.pack(fill=\"both\", expand=True, padx=10, pady=10)\n        viewer.insert(\"1.0\", summary)\n        viewer.config(state=\"disabled\")\n        messagebox.showinfo(\n            \"AUTO Recovery Complete\",\n            f\"{len(recovered)} files recover hui.\\n\\nOutput folder:\\n{output_dir}\\n\\nDetails result window me show ho rahe hain.\"\n        )\n\n    def _select_img_source(self):\n        img_path = filedialog.askopenfilename(\n            title=\"IMG/DD/raw disk image import karo\",\n            filetypes=[(\"Disk images\", \"*.img *.dd *.raw *.bin\"), (\"All files\", \"*.*\")]\n        )\n        if not img_path:\n            return\n        self.raw_disk_var.set(img_path)\n        try:\n            values = list(self.raw_disk_combo.cget(\"values\"))\n            if img_path not in values:\n                values.insert(0, img_path)\n                self.raw_disk_combo.configure(values=values)\n        except Exception:\n            pass\n        self._update_raw_source_badge()\n        self._set_status(f\"IMG source selected: {img_path}\", C[\"success\"])\n\n    def _export_hex_sector_img(self):\n        try:\n            sector = int((self.raw_sector_num.get() or \"0\").strip())\n            start_offset = sector * SECTOR_SIZE\n            limit = self._raw_limit_bytes()\n            disk_path = self._raw_disk_path()\n            self._update_raw_source_badge()\n            if not self._ensure_admin_for_raw_recovery(disk_path):\n                return\n        except Exception as e:\n            messagebox.showerror(\"Sector IMG Error\", str(e))\n            return\n        img_path = filedialog.asksaveasfilename(\n            title=\"Sector range ko IMG me save karo\",\n            defaultextension=\".img\",\n            filetypes=[(\"Disk image\", \"*.img\"), (\"All files\", \"*.*\")]\n        )\n        if not img_path:\n            return\n        size_text = \"source ke end tak\" if limit is None else self._fmt_size(limit)\n        if not messagebox.askyesno(\n            \"Sector to IMG\",\n            f\"Hex/Sector range ko IMG me export karein?\\n\\n\"\n            f\"Source: {disk_path}\\n\"\n            f\"Start sector: {sector}\\n\"\n            f\"Start offset: 0x{start_offset:X}\\n\"\n            f\"Size: {size_text}\\n\"\n            f\"Output: {img_path}\\n\\n\"\n            \"Is IMG ko Import IMG button se scan kar sakte hain.\"\n        ):\n            return\n        self._reset_raw_progress(\"Sector IMG export start ho raha hai...\")\n        try:\n            self._begin_recovery_operation(\"Sector IMG export start ho raha hai...\")\n        except Exception as e:\n            messagebox.showwarning(\"Recovery Busy\", str(e))\n            return\n        if not self._hdd_action_submit(\"sector_img_export\", self._do_export_hex_sector_img, disk_path, img_path, start_offset, limit):\n            self._set_status(\"Recovery action already running; wait for completion.\", C[\"warning\"])\n\n    def _do_export_hex_sector_img(self, disk_path, img_path, start_offset, limit):\n        try:\n            result = copy_disk_range_to_img(disk_path, img_path, start_offset=start_offset, max_bytes=limit, progress_callback=self._raw_recovery_progress)\n            def _finish():\n                self._set_status(f\"Sector IMG complete: {self._fmt_size(result['bytes'])}\", C[\"success\"])\n                self.raw_disk_var.set(result[\"img_path\"])\n                messagebox.showinfo(\n                    \"Sector IMG Complete\",\n                    f\"IMG ban gayi:\\n{result['img_path']}\\n\\n\"\n                    f\"Size: {self._fmt_size(result['bytes'])}\\n\\n\"\n                    \"Ab yahi IMG source select ho gayi hai; PhotoRec Deep Scan/AUTO se scan kar sakte hain.\"\n                )\n            self.after(0, _finish)\n        except InterruptedError as e:\n            msg = str(e)\n            self.after(0, lambda msg=msg: self._set_status(msg, C[\"warning\"]))\n        except Exception as e:\n            err = str(e)\n            self.after(0, lambda err=err: self._set_status(\"Sector IMG failed: \" + err, C[\"error\"]))\n            self.after(0, lambda err=err: messagebox.showerror(\"Sector IMG Error\", err))\n        finally:\n            self.after(0, self._finish_recovery_operation)\n\n    def _candidate_dmde_paths(self):\n        candidates = []\n        env_path = os.environ.get(\"GODAWARI_DMDE_PATH\", \"\").strip().strip('\"')\n        if env_path:\n            candidates.append(env_path)\n        for exe_name in (\"dmde.exe\", \"dmde64.exe\", \"dmde32.exe\"):\n            found = shutil.which(exe_name)\n            if found:\n                candidates.append(found)\n        base_dirs = [\n            os.getcwd(),\n            os.path.dirname(os.path.abspath(sys.argv[0])),\n            os.environ.get(\"ProgramFiles\", \"\"),\n            os.environ.get(\"ProgramFiles(x86)\", \"\"),\n            os.environ.get(\"LOCALAPPDATA\", \"\"),\n        ]\n        rels = [\n            \"DMDE\\\\dmde.exe\",\n            \"DMDE\\\\dmde64.exe\",\n            \"dmde\\\\dmde.exe\",\n            \"tools\\\\dmde\\\\dmde.exe\",\n            \"assets\\\\tools\\\\dmde\\\\dmde.exe\",\n        ]\n        for base in base_dirs:\n            if not base:\n                continue\n            for rel in rels:\n                candidates.append(os.path.join(base, rel))\n        seen = set()\n        result = []\n        for path in candidates:\n            norm = os.path.normcase(os.path.abspath(path))\n            if norm in seen:\n                continue\n            seen.add(norm)\n            if os.path.isfile(path):\n                result.append(path)\n        return result\n\n    def _find_dmde_exe(self):\n        candidates = self._candidate_dmde_paths()\n        if candidates:\n            return candidates[0]\n        return \"\"\n\n    def _ask_dmde_exe(self):\n        exe = filedialog.askopenfilename(\n            title=\"DMDE executable select karo (dmde.exe)\",\n            filetypes=[(\"DMDE executable\", \"dmde*.exe\"), (\"Executable\", \"*.exe\"), (\"All files\", \"*.*\")]\n        )\n        if exe and os.path.isfile(exe):\n            os.environ[\"GODAWARI_DMDE_PATH\"] = exe\n            return exe\n        return \"\"\n\n    def _start_dmde_recovery(self):\n        disk_path = self._raw_disk_path()\n        self._update_raw_source_badge()\n        if not self._ensure_admin_for_raw_recovery(disk_path):\n            return\n\n        dmde_exe = self._find_dmde_exe()\n        if not dmde_exe:\n            self._set_status(\"DMDE available nahi mila. Auto-detect only mode active hai.\", C[\"warning\"])\n            messagebox.showinfo(\n                \"DMDE Not Available\",\n                \"DMDE executable auto-detect nahi hua.\\n\\n\"\n                \"Ab yeh tool manual .exe browse nahi maangega.\\n\"\n                \"Agar DMDE use karna ho to usse standard location me install/put karo,\\n\"\n                \"ya GODAWARI_DMDE_PATH env var set karo.\"\n            )\n            return\n\n        source_kind = \"IMG/file source\" if os.path.isfile(disk_path) else \"raw disk/device\"\n        if not messagebox.askyesno(\n            \"DMDE Recovery\",\n            f\"DMDE recovery console launch karein?\\n\\n\"\n            f\"DMDE: {dmde_exe}\\n\"\n            f\"Source: {disk_path}\\n\"\n            f\"Type: {source_kind}\\n\\n\"\n            \"Forensic safety:\\n\"\n            \"- Source disk par kuch write mat karein.\\n\"\n            \"- Recovered data hamesha dusre drive/folder me save karein.\\n\"\n            \"- DMDE ke write/repair options sirf verified clone/IMG par use karein.\"\n        ):\n            return\n\n        self._reset_raw_progress(\"DMDE Recovery launch ho raha hai...\")\n        try:\n            self._begin_recovery_operation(\"DMDE Recovery launch ho raha hai...\")\n        except Exception as e:\n            messagebox.showwarning(\"Recovery Busy\", str(e))\n            return\n        if not self._hdd_action_submit(\"dmde_recovery\", self._do_dmde_recovery, dmde_exe, disk_path):\n            self._set_status(\"Recovery action already running; wait for completion.\", C[\"warning\"])\n\n    def _do_dmde_recovery(self, dmde_exe, disk_path):\n        proc = None\n        try:\n            report_dir = getattr(self, \"backup_dir\", os.getcwd())\n            os.makedirs(report_dir, exist_ok=True)\n            report_path = os.path.join(report_dir, \"dmde_recovery_launch.log\")\n            cmd = [dmde_exe, disk_path]\n            self._raw_recovery_progress(\"DMDE subprocess start: \" + subprocess.list2cmdline(cmd))\n            proc = subprocess.Popen(\n                cmd,\n                cwd=os.path.dirname(dmde_exe) or None,\n                stdout=subprocess.PIPE,\n                stderr=subprocess.STDOUT,\n                text=True,\n                encoding=\"utf-8\",\n                errors=\"replace\",\n            )\n            self._dmde_proc = proc\n            started = datetime.datetime.now().isoformat(timespec=\"seconds\")\n            with open(report_path, \"a\", encoding=\"utf-8\") as f:\n                f.write(f\"[{started}] DMDE launched\\n\")\n                f.write(\"Command: \" + subprocess.list2cmdline(cmd) + \"\\n\")\n                f.write(\"Source: \" + disk_path + \"\\n\")\n            self._audit_event(\"dmde_recovery_started\", {\n                \"dmde\": dmde_exe,\n                \"source\": disk_path,\n                \"pid\": proc.pid,\n                \"report\": report_path,\n            })\n            self.after(0, lambda: self._set_status(f\"DMDE running (PID {proc.pid})\", C[\"success\"]))\n\n            output_tail = []\n            if proc.stdout:\n                while proc.poll() is None:\n                    line = proc.stdout.readline()\n                    if line:\n                        clean = line.strip()\n                        if clean:\n                            output_tail.append(clean)\n                            output_tail = output_tail[-40:]\n                            self._raw_recovery_progress(\"DMDE: \" + clean[:180])\n                    else:\n                        time.sleep(0.25)\n                for line in proc.stdout.readlines():\n                    clean = line.strip()\n                    if clean:\n                        output_tail.append(clean)\n            rc = proc.wait(timeout=5)\n            ended = datetime.datetime.now().isoformat(timespec=\"seconds\")\n            with open(report_path, \"a\", encoding=\"utf-8\") as f:\n                f.write(f\"[{ended}] DMDE exited rc={rc}\\n\")\n                if output_tail:\n                    f.write(\"Output tail:\\n\" + \"\\n\".join(output_tail[-40:]) + \"\\n\")\n                f.write(\"\\n\")\n            self._audit_event(\"dmde_recovery_finished\", {\"rc\": rc, \"report\": report_path})\n            self.after(0, lambda rc=rc, report_path=report_path: self._set_status(f\"DMDE closed (rc={rc}) - log saved\", C[\"success\"] if rc == 0 else C[\"warning\"]))\n            self.after(0, lambda report_path=report_path: messagebox.showinfo(\"DMDE Recovery\", f\"DMDE session closed.\\n\\nLog:\\n{report_path}\"))\n        except FileNotFoundError:\n            self.after(0, lambda: messagebox.showerror(\"DMDE Missing\", \"DMDE executable nahi mila. dmde.exe path dobara select karein.\"))\n        except InterruptedError as e:\n            msg = str(e)\n            self.after(0, lambda msg=msg: self._set_status(msg, C[\"warning\"]))\n        except Exception as e:\n            err = str(e)\n            self.after(0, lambda err=err: self._set_status(\"DMDE launch failed: \" + err, C[\"error\"]))\n            self.after(0, lambda err=err: messagebox.showerror(\"DMDE Recovery Error\", err))\n        finally:\n            if getattr(self, \"_dmde_proc\", None) is proc:\n                self._dmde_proc = None\n            self.after(0, self._finish_recovery_operation)\n\n    def _start_photorec_deep_scan(self):\n        disk_path = self._raw_disk_path()\n        self._update_raw_source_badge()\n        if not self._ensure_admin_for_raw_recovery(disk_path):\n            return\n        output_dir = filedialog.askdirectory(title=\"PhotoRec recovered output folder select karo\")\n        if not output_dir:\n            return\n        if not messagebox.askyesno(\n            \"PhotoRec Deep Scan\",\n            f\"PhotoRec-style deep scan start karein?\\n\\n\"\n            f\"Source: {disk_path}\\n\"\n            f\"Output: {output_dir}\\\\recup_dir.N\\n\\n\"\n            \"Process:\\n\"\n            \"1. Auto block/cluster size detect\\n\"\n            \"2. Pass 1 block-aligned carving\\n\"\n            \"3. Pass 2 unaligned signature scan\\n\"\n            \"4. Validation + best-effort fragment reassembly\\n\\n\"\n            \"No size limit rakha gaya hai, isliye full disk scan bahut time le sakta hai.\"\n        ):\n            return\n        self.rec_tree.delete(*self.rec_tree.get_children())\n        self.rec_found_files = {}\n        self._set_recovery_scan_mode(\"Mode: Zone B \u2014 Raw Sector Recovery (Admin)\", C[\"warning\"])\n        self._clear_recovery_progress_log()\n        self._prep_raw_scan_progress_ui()\n        self._reset_raw_progress(\"PhotoRec Deep Scan start ho rahi hai...\")\n        try:\n            self._begin_recovery_operation(\"PhotoRec Deep Scan start ho rahi hai...\")\n        except Exception as e:\n            messagebox.showwarning(\"Recovery Busy\", str(e))\n            return\n        if not self._hdd_action_submit(\"photorec_deep_scan\", self._do_photorec_deep_scan, disk_path, output_dir):\n            self._set_status(\"Recovery action already running; wait for completion.\", C[\"warning\"])\n\n    def _do_photorec_deep_scan(self, disk_path, output_dir):\n        try:\n            result = multi_pass_recovery(\n                disk_path, output_dir,\n                progress_callback=self._make_recovery_progress_callback())\n            def _finish():\n                file_map = {os.path.basename(f[\"path\"]): f for f in result.get(\"files\", [])}\n                seen_basenames = set()\n                for iid in list(self.rec_tree.get_children()):\n                    vals = list(self.rec_tree.item(iid, \"values\"))\n                    if not vals:\n                        continue\n                    bn = vals[0]\n                    seen_basenames.add(bn)\n                    if bn in file_map:\n                        item = file_map[bn]\n                        loc = item[\"path\"][-60:] if len(item[\"path\"]) &gt; 60 else item[\"path\"]\n                        self.rec_tree.item(iid, values=(\n                            bn, item[\"file_type\"], self._fmt_size(item[\"bytes\"]),\n                            \"\u2705 Recovered\", loc, \"--\"), tags=(\"recovered\",))\n                        self.rec_found_files[iid] = item[\"path\"]\n                for item in result.get(\"files\", []):\n                    bn = os.path.basename(item[\"path\"])\n                    if bn in seen_basenames:\n                        continue\n                    loc = item[\"path\"][-60:] if len(item[\"path\"]) &gt; 60 else item[\"path\"]\n                    iid = self.rec_tree.insert(\"\", \"end\", values=(\n                        bn, item[\"file_type\"], self._fmt_size(item[\"bytes\"]),\n                        \"\u2705 Recovered\", loc, \"--\"), tags=(\"recovered\",))\n                    self.rec_found_files[iid] = item[\"path\"]\n                self._on_rec_select()\n                self._set_status(f\"PhotoRec scan complete: {len(result.get('files', []))} files\", C[\"success\"])\n                self._show_photorec_result(result)\n            self.after(0, _finish)\n        except InterruptedError as e:\n            msg = str(e)\n            self.after(0, lambda msg=msg: self._set_status(msg, C[\"warning\"]))\n        except Exception as e:\n            err = str(e)\n            self.after(0, lambda err=err: self._set_status(\"PhotoRec scan failed: \" + err, C[\"error\"]))\n            self.after(0, lambda err=err: messagebox.showerror(\"PhotoRec Deep Scan Error\", err))\n        finally:\n            self.after(0, self._finish_recovery_operation)\n\n    def _show_photorec_result(self, result):\n        win = tk.Toplevel(self)\n        win.title(\"PhotoRec Deep Scan Result\")\n        win.geometry(\"980x620\")\n        win.configure(bg=C[\"bg\"])\n        text = (\n            f\"PHOTOREC-STYLE DEEP SCAN COMPLETE\\n\"\n            f\"recup_dir: {result['recup_dir']}\\n\"\n            f\"Block size: {result['block_size']} bytes\\n\"\n            f\"Recovered files: {len(result['files'])}\\n\\n\"\n        )\n        for item in result[\"files\"][:300]:\n            text += f\"Pass {item['pass']} | 0x{item['offset']:X} | {item['file_type']} | {self._fmt_size(item['bytes'])} | {item['path']}\\n\"\n        if len(result[\"files\"]) &gt; 300:\n            text += f\"\\n... aur {len(result['files']) - 300} files tree me available hain.\"\n        viewer = scrolledtext.ScrolledText(win, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], wrap=\"none\")\n        viewer.pack(fill=\"both\", expand=True, padx=10, pady=10)\n        viewer.insert(\"1.0\", text)\n        viewer.config(state=\"disabled\")\n        messagebox.showinfo(\"PhotoRec Deep Scan\", f\"{len(result['files'])} files recover hui.\\n\\nFolder:\\n{result['recup_dir']}\")\n\n    def _show_raw_hex_dialog(self):\n        try:\n            sector = int((self.raw_sector_num.get() or \"0\").strip())\n            disk_path = self._raw_disk_path()\n            self._update_raw_source_badge()\n            if not self._ensure_admin_for_raw_recovery(disk_path):\n                return\n        except Exception as e:\n            messagebox.showerror(\"Hex Viewer Error\", str(e))\n            return\n        self._reset_raw_progress(f\"Hex viewer sector {sector} read ho raha hai...\")\n        try:\n            self._begin_recovery_operation(f\"Hex viewer sector {sector} read ho raha hai...\")\n        except Exception as e:\n            messagebox.showwarning(\"Recovery Busy\", str(e))\n            return\n        if not self._hdd_action_submit(\"raw_hex_view\", self._do_show_raw_hex_dialog, disk_path, sector):\n            self._set_status(\"Recovery action already running; wait for completion.\", C[\"warning\"])\n\n    def _do_show_raw_hex_dialog(self, disk_path, sector):\n        try:\n            self._raw_recovery_progress(f\"Hex viewer: reading {disk_path} sector {sector}\")\n            text = raw_hex_viewer(sector, disk_path=disk_path)\n            self.after(0, lambda: self._open_raw_hex_window(sector, text))\n            self.after(0, lambda: self._set_status(f\"Hex viewer ready: sector {sector}\", C[\"success\"]))\n        except InterruptedError as e:\n            msg = str(e)\n            self.after(0, lambda msg=msg: self._set_status(msg, C[\"warning\"]))\n        except Exception as e:\n            err = str(e)\n            self.after(0, lambda err=err: self._set_status(\"Hex viewer failed: \" + err, C[\"error\"]))\n            self.after(0, lambda err=err: messagebox.showerror(\"Hex Viewer Error\", err))\n        finally:\n            self.after(0, self._finish_recovery_operation)\n\n    def _open_raw_hex_window(self, sector, text):\n        win = tk.Toplevel(self)\n        win.title(f\"Raw Hex Viewer - Sector {sector}\")\n        win.geometry(\"980x620\")\n        win.configure(bg=C[\"bg\"])\n        viewer = scrolledtext.ScrolledText(win, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], wrap=\"none\")\n        viewer.pack(fill=\"both\", expand=True, padx=10, pady=10)\n        viewer.insert(\"1.0\", text)\n        viewer.config(state=\"disabled\")\n\n    def _start_file_recovery(self):\n        drive = self.rec_drive.get().replace(\"\\\\\", \"\").rstrip(\"\\\\\")\n        exts = [e.strip().lstrip(\".\") for e in self.rec_ext.get().split(\",\") if e.strip()]\n        if not drive or not exts:\n            messagebox.showwarning(\"Input\", \"Drive aur extensions fill karo.\")\n            return\n        if self._is_mobile_source(drive):\n            if not self._mobile_adb_available():\n                self._show_adb_help()\n                return\n            if not self._mobile_device_ready():\n                messagebox.showerror(\"Device Not Ready\", \"ADB mila, lekin phone connected/authorized nahi hai.\\nUSB debugging enable karke phone par Allow dabao, phir retry karo.\")\n                return\n        ext_str = \", \".join(exts)\n        if not messagebox.askyesno(\"File Search\",\n            f\"{'Mobile (ADB)' if self._is_mobile_source(drive) else f'Drive {drive}:'} pe yeh files dhundega:\\n{ext_str}\\n\\n\"\n            f\"Note: Yeh ZONE A scan hai \u2014 drive pe maujood accessible files dhundta hai.\\n\"\n            f\"Deleted files ke liye ZONE B \u2192 Raw Signature Scan use karo (Admin required).\\n\\nProceed?\"):\n            return\n        # Reset control flags\n        try:\n            self._begin_recovery_operation(f\"Searching {drive} for {ext_str}...\")\n        except Exception as e:\n            messagebox.showwarning(\"Recovery Busy\", str(e))\n            return\n        self._set_recovery_scan_mode(\"Mode: Zone A \u2014 File Search (Drive Scan)\", C[\"accent2\"])\n        self._clear_recovery_progress_log()\n        self._prep_drive_scan_progress_ui()\n        if hasattr(self, \"raw_progress_label\"):\n            self.raw_progress_label.config(text=f\"Searching {drive}: for {ext_str}...\")\n        if hasattr(self, \"raw_progress_var\"):\n            self.raw_progress_var.set(0)\n        # Update control buttons\n        if hasattr(self, \"_rec_stop_btn\"):\n            self._rec_stop_btn.config(state=\"normal\")\n        if hasattr(self, \"_rec_pause_btn\"):\n            self._rec_pause_btn.config(state=\"normal\", text=\"\u23f8 Pause\")\n        if not self._hdd_action_submit(\"file_search\", self._do_file_recovery, drive, exts):\n            self._set_status(\"Recovery action already running; wait for completion.\", C[\"warning\"])\n\n    def _stop_file_recovery(self):\n        # Set BOTH the legacy flag and the threading.Event so the background\n        # scan loop detects the stop signal at its very next check (&lt; 50 ms).\n        self._recovery_stop_flag = True\n        self._recovery_pause_flag = False\n        if hasattr(self, \"_scan_stop_event\"):\n            self._scan_stop_event.set()  # unblocks any time.sleep() pause too\n        self._set_status(\"\u23f9 Recovery roka ja raha hai...\", C[\"warning\"])\n        if hasattr(self, \"_rec_stop_btn\"):\n            self._rec_stop_btn.config(state=\"disabled\")\n        if hasattr(self, \"_rec_pause_btn\"):\n            self._rec_pause_btn.config(state=\"disabled\", text=\"\u23f8 Pause\")\n\n    def _pause_resume_file_recovery(self):\n        if not hasattr(self, \"_recovery_pause_flag\"):\n            return\n        self._recovery_pause_flag = not self._recovery_pause_flag\n        if self._recovery_pause_flag:\n            self._set_status(\"\u23f8 Recovery paused \u2014 Resume dabao jab taiyar ho\", C[\"warning\"])\n            if hasattr(self, \"_rec_pause_btn\"):\n                self._rec_pause_btn.config(text=\"\u25b6 Resume\")\n        else:\n            self._set_status(\"\u25b6 Recovery resume ho gayi...\", C[\"accent4\"])\n            if hasattr(self, \"_rec_pause_btn\"):\n                self._rec_pause_btn.config(text=\"\u23f8 Pause\")\n\n    def _do_file_recovery(self, drive, exts):\n        \"\"\"\n        Background thread worker for Zone-A file search.\n\n        ALL GUI updates go through self._ui_queue (via self._q*() helpers).\n        The main thread drains the queue every 50 ms in _poll_ui_queue().\n        This keeps the GUI fully responsive and the progress bar smooth.\n        \"\"\"\n        # \u2500\u2500 1. Reset UI on main thread \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        def _scan_start_ui():\n            try:\n                for i in self.rec_tree.get_children():\n                    self.rec_tree.delete(i)\n                self.rec_found_files = {}\n                self._recovery_reset_ui_batch()\n                self._on_rec_select()\n                if hasattr(self, \"raw_progress_log\"):\n                    self.raw_progress_log.config(state=\"normal\")\n                    self.raw_progress_log.delete(\"1.0\", \"end\")\n                    self.raw_progress_log.config(state=\"disabled\")\n                # Switch progress bar to indeterminate (animated bounce)\n                if hasattr(self, \"raw_progress_bar\"):\n                    try:\n                        self.raw_progress_bar.stop()\n                    except Exception:\n                        pass\n                    self.raw_progress_bar.config(mode=\"indeterminate\")\n                    self.raw_progress_bar.start(12)\n                if hasattr(self, \"raw_progress_label\"):\n                    self.raw_progress_label.config(text=f\"Scan shuru ho raha hai \u2014 {drive}:\\\\ ...\")\n            except Exception:\n                pass\n        self.after(0, _scan_start_ui)\n\n        # Clear the stop event so a previous stop does not block a fresh scan\n        self._scan_stop_event.clear()\n        self._recovery_stop_flag = False   # also reset the legacy flag\n        before_state = self._snapshot_resource_state() or {}\n\n        file_count   = 0\n        scanned      = 0\n        local_matches = []   # accumulate for checkpoint saves\n\n        try:\n            ext_set  = {(\".\" + e.lower().strip(\".\")) for e in exts if e.strip()}\n            mode_key = f\"search_{drive.lower()}\"\n\n            # \u2500\u2500 2. Resume checkpoint \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            cp = self._load_recovery_checkpoint(mode_key) or {}\n            cp_exts = set(cp.get(\"exts\", [])) if isinstance(cp, dict) else set()\n            resume_ok = (\n                bool(cp)\n                and cp.get(\"drive\", \"\").lower() == drive.lower()\n                and cp_exts == {e.lower().strip(\".\") for e in exts}\n            )\n            processed_dirs = set(cp.get(\"processed_dirs\", [])) if resume_ok else set()\n            saved_matches  = cp.get(\"matches\", []) if resume_ok else []\n\n            if resume_ok and saved_matches:\n                for p in saved_matches:\n                    if self._scan_stop_event.is_set():\n                        break\n                    try:\n                        nm  = os.path.basename(p)\n                        ex  = os.path.splitext(nm)[1].lstrip(\".\") or \"?\"\n                        sz  = self._fmt_size(os.path.getsize(p)) if os.path.exists(p) else \"?\"\n                        loc = p[-60:] if len(p) &gt; 60 else p\n                        row = (nm, ex, sz, \"Found \u2014 Recover dabao \u25b6\", loc, \"--\")\n                        # \u25b6 Queue the tree row \u2014 do NOT touch rec_tree from background thread\n                        self._q_tree_row(row, p)\n                        file_count += 1\n                        local_matches.append(p)\n                    except Exception:\n                        pass\n                self._q_log(f\"Resume checkpoint: {len(saved_matches)} previous matches loaded\")\n\n            # \u2500\u2500 3. Mobile or local drive scan \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            if self._is_mobile_source(drive):\n                mobile_paths = self._mobile_find_candidates(exts)\n                for p in mobile_paths:\n                    if self._scan_stop_event.is_set():\n                        break\n                    name = os.path.basename(p)\n                    ext  = os.path.splitext(name)[1].lstrip(\".\") or \"?\"\n                    loc  = p[-60:] if len(p) &gt; 60 else p\n                    row  = (name, ext, \"Mobile\", \"Found \u2014 Recover dabao \u25b6\", loc, \"--\")\n                    entry = {\"kind\": \"mobile\", \"path\": p}\n                    self._q_tree_row(row, entry)\n                    file_count += 1\n                    local_matches.append(p)\n\n                self._save_recovery_checkpoint(mode_key, {\n                    \"drive\": drive,\n                    \"exts\": [e.lower().strip(\".\") for e in exts],\n                    \"matches\": [m for m in local_matches][-3000:],\n                    \"processed_dirs\": [],\n                })\n\n            else:\n                # \u2500\u2500 Local drive walk \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n                root_path = drive + \":\\\\\"\n                _PROGRESS_INTERVAL   = 5    # update label every N dirs\n                _LOG_INTERVAL        = 25   # log path every N dirs\n                _CHECKPOINT_INTERVAL = 250  # save checkpoint every N dirs\n                last_progress_time = time.monotonic()\n\n                for dirpath, _, filenames in os.walk(root_path):\n                    # \u2500\u2500 Instant stop check \u2014 no Tk access, thread-safe \u2500\u2500\u2500\n                    if self._scan_stop_event.is_set() or getattr(self, \"_recovery_stop_flag\", False):\n                        self._scan_stop_event.set()\n                        break\n\n                    if dirpath in processed_dirs:\n                        continue\n\n                    # \u2500\u2500 Pause: tight sleep loop \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n                    while getattr(self, \"_recovery_pause_flag\", False):\n                        if self._scan_stop_event.is_set() or getattr(self, \"_recovery_stop_flag\", False):\n                            self._scan_stop_event.set()\n                            break\n                        time.sleep(0.15)\n\n                    # \u2500\u2500 Scan files in this directory \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n                    for fn in filenames:\n                        if self._scan_stop_event.is_set():\n                            break\n                        low_ext = os.path.splitext(fn)[1].lower()\n                        if low_ext not in ext_set:\n                            continue\n                        full = os.path.join(dirpath, fn)\n                        try:\n                            sz = self._fmt_size(os.path.getsize(full))\n                        except Exception:\n                            sz = \"?\"\n                        type_lbl = low_ext.lstrip(\".\") or \"?\"\n                        loc = dirpath[-60:] if len(dirpath) &gt; 60 else dirpath\n                        row = (fn, type_lbl, sz, \"Found \u2014 Recover dabao \u25b6\", loc, \"--\")\n                        # \u25b6 Thread-safe: put into queue, NOT self.after(0,...)\n                        self._q_tree_row(row, full)\n                        file_count += 1\n                        local_matches.append(full)\n\n                    scanned += 1\n                    processed_dirs.add(dirpath)\n\n                    # \u2500\u2500 Yield briefly so the UI thread can run often \u2500\u2500\u2500\u2500\u2500\n                    time.sleep(0.001)\n\n                    # \u2500\u2500 Real-time progress label update (via queue) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\n                    now = time.monotonic()\n                    if scanned == 1 or now - last_progress_time &gt;= 0.100:\n                        folder_tail = dirpath[-65:] if len(dirpath) &gt; 65 else dirpath\n                        label_text  = (\n                            f\"\ud83d\udd0d Scanning...  {scanned:,} folders scanned  |  \"\n                            f\"{file_count:,} files mili  |  ...{folder_tail}\"\n                        )\n                        self._q(\"progress_label\", label_text)\n                        self._hdd_recovery_emit_metrics({\n                            \"phase\": \"file_search\",\n                            \"status_text\": label_text,\n                            \"scan_mode\": \"Mode: Zone A \u2014 File Search (Drive Scan)\",\n                            \"progress_pct\": None,\n                            \"files_found\": file_count,\n                            \"scanned_dirs\": scanned,\n                            \"resource_before_mb\": before_state.get(\"available_mb\", 0),\n                            \"resource_after_mb\": int(psutil.virtual_memory().available / 1024**2) if psutil else 0,\n                            \"delta_mb\": int(psutil.virtual_memory().available / 1024**2) - int(before_state.get(\"available_mb\", 0)),\n                        })\n                        if scanned % _LOG_INTERVAL == 0 or file_count % 10 == 0:\n                            self._q_log(dirpath)\n                        last_progress_time = now\n\n                    # \u2500\u2500 Periodic checkpoint save \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n                    if scanned % _CHECKPOINT_INTERVAL == 0:\n                        self._save_recovery_checkpoint(mode_key, {\n                            \"drive\": drive,\n                            \"exts\": [e.lower().strip(\".\") for e in exts],\n                            \"matches\": local_matches[-3000:],\n                            \"processed_dirs\": list(processed_dirs)[-15000:],\n                        })\n\n            # \u2500\u2500 4. Scan done \u2014 final UI update via after() \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            stopped       = self._scan_stop_event.is_set() or getattr(self, \"_recovery_stop_flag\", False)\n            n             = file_count\n            folders_final = scanned\n\n            def _done():\n                \"\"\"Runs on main thread via self.after(0, ...).\"\"\"\n                # Stop indeterminate animation and switch to determinate\n                if hasattr(self, \"raw_progress_bar\"):\n                    try:\n                        self.raw_progress_bar.stop()\n                    except Exception:\n                        pass\n                    self.raw_progress_bar.config(mode=\"determinate\")\n\n                # Flush any leftover queued tree rows\n                self._recovery_flush_ui_batch()\n                self._on_rec_select()\n\n                color      = C[\"success\"] if n &gt; 0 else C[\"warning\"]\n                status_msg = f\"{'\u23f9 Stopped \u2014 ' if stopped else ''}Search complete: {n} files found on {drive}\"\n                self._set_status(status_msg, color)\n\n                if hasattr(self, \"raw_progress_var\"):\n                    self.raw_progress_var.set(100 if not stopped else 50)\n                if hasattr(self, \"raw_progress_label\"):\n                    if stopped:\n                        self.raw_progress_label.config(\n                            text=f\"\u23f9 Stopped | {n:,} files found | Drive {drive}\")\n                    else:\n                        self.raw_progress_label.config(\n                            text=(f\"\u2705 Scan complete \u2014 {n:,} files found on {drive}: | \"\n                                  f\"{folders_final:,} folders scanned\"))\n\n                if hasattr(self, \"_rec_stop_btn\"):\n                    self._rec_stop_btn.config(state=\"disabled\")\n                if hasattr(self, \"_rec_pause_btn\"):\n                    self._rec_pause_btn.config(state=\"disabled\", text=\"\u23f8 Pause\")\n                self._recovery_active = False\n\n                if not stopped:\n                    self._clear_recovery_checkpoint(mode_key)\n                if n == 0 and not stopped:\n                    messagebox.showinfo(\n                        \"No Files Found\",\n                        f\"Drive {drive}: pe koi file nahi mili.\\n\\n\"\n                        \"Deleted files ke liye Zone B \u2192 Raw Signature Scan use karo (admin required).\")\n                elif stopped and n &gt; 0:\n                    messagebox.showinfo(\n                        \"Search Stopped\",\n                        f\"\u23f9 Search rok di gayi.\\n{n} files abhi tak mili hain.\\n\\n\"\n                        \"In files ko select karke recover kar sakte ho.\")\n\n            self.after(0, _done)\n\n        except Exception as e:\n            err = str(e)\n            self.after(0, lambda err=err: self._set_status(\"Search failed: \" + err, C[\"error\"]))\n        finally:\n            self.after(0, self._finish_recovery_operation)\n\n    def _recover_selected_files(self):\n        dest = filedialog.askdirectory(title=\"Recovered files save karne ke liye folder choose karo\")\n        if not dest:\n            return\n        selected = self.rec_tree.selection()\n        if not selected:\n            messagebox.showwarning(\"Select Files\", \"Pehle list mein files select karo.\")\n            return\n        try:\n            self._begin_recovery_operation(\"Extracting selected files...\")\n        except Exception as e:\n            messagebox.showwarning(\"Busy\", str(e))\n            return\n        if hasattr(self, \"_rec_recover_btn\"):\n            self._rec_recover_btn.config(state=\"disabled\")\n        if not self._hdd_action_submit(\"recover_selected_files\", self._do_recover_selected_files, dest, list(selected)):\n            self._set_status(\"Recovery action already running; wait for completion.\", C[\"warning\"])\n\n    def _do_recover_selected_files(self, dest, selected_iids):\n        before_state = self._snapshot_resource_state() or {}\n        count = 0\n        errors = []\n        seen_hashes = set()\n        try:\n            for iid in selected_iids:\n                entry = self.rec_found_files.get(iid)\n                if entry is None:\n                    continue\n                if isinstance(entry, dict) and entry.get(\"kind\") == \"raw\":\n                    try:\n                        extract_limit = SIGNATURES[entry[\"file_type\"]][\"max_size\"]\n                        ui_limit = self._raw_limit_bytes()\n                        if ui_limit is not None and entry[\"offset\"] &lt; ui_limit:\n                            extract_limit = max(SECTOR_SIZE, min(extract_limit, ui_limit - entry[\"offset\"]))\n                        result = extract_file_at_offset(\n                            entry[\"disk_path\"],\n                            entry[\"offset\"],\n                            entry[\"file_type\"],\n                            output_dir=dest,\n                            max_bytes=extract_limit,\n                            progress_callback=self._raw_recovery_progress,\n                        )\n                        complete = result.get(\"complete_boundary\", True)\n                        if not complete:\n                            errors.append(f\"{os.path.basename(result['path'])}: boundary incomplete, file fragmented/truncated ho sakti hai\")\n                        try:\n                            h = self._sha256_file(result[\"path\"])\n                            if h in seen_hashes:\n                                os.remove(result[\"path\"])\n                                errors.append(f\"Duplicate removed: {os.path.basename(result['path'])}\")\n                            else:\n                                seen_hashes.add(h)\n                                score, _reason = self._integrity_score(result[\"path\"], entry.get(\"file_type\", \"\"))\n                                actual_size = self._fmt_size(result.get(\"bytes\") or os.path.getsize(result[\"path\"]))\n                                score_text = f\"{score}/100 {'\u2705' if score &gt;= 60 else '\u26a0 check'}\"\n                                status_txt = \"\u2705 Recovered\" if complete else \"\u26a0 May be corrupt\"\n                                tag = \"recovered\" if complete else \"partial\"\n                                def _upd_row(i=iid, s=actual_size, st=status_txt, sc=score_text, tg=tag):\n                                    vals = list(self.rec_tree.item(i, \"values\"))\n                                    if len(vals) &gt;= 6:\n                                        self.rec_tree.item(i, values=(vals[0], vals[1], s, st, vals[4], sc), tags=(tg,))\n                                    self._on_rec_select()\n                                self.after(0, _upd_row)\n                                count += 1\n                        except Exception as e:\n                            errors.append(f\"Hash/score failed: {e}\")\n                            count += 1\n                    except Exception as e:\n                        errors.append(str(e))\n                elif isinstance(entry, dict) and entry.get(\"kind\") == \"mobile\":\n                    try:\n                        src = entry.get(\"path\", \"\")\n                        if not src:\n                            continue\n                        dst = os.path.join(dest, os.path.basename(src))\n                        ok, out = self._mobile_pull_with_retry(src, dst)\n                        if ok:\n                            try:\n                                h = self._sha256_file(dst)\n                                if h in seen_hashes:\n                                    os.remove(dst)\n                                    errors.append(f\"Duplicate mobile file skipped: {os.path.basename(dst)}\")\n                                    continue\n                                seen_hashes.add(h)\n                                score, _reason = self._integrity_score(dst, os.path.splitext(dst)[1].lstrip(\".\"))\n                                actual_size = self._fmt_size(os.path.getsize(dst))\n                                score_text = f\"{score}/100 {'\u2705' if score &gt;= 60 else '\u26a0 check'}\"\n                                def _upd_mob(i=iid, s=actual_size, sc=score_text):\n                                    vals = list(self.rec_tree.item(i, \"values\"))\n                                    if len(vals) &gt;= 6:\n                                        self.rec_tree.item(i, values=(vals[0], vals[1], s, \"\u2705 Recovered\", vals[4], sc), tags=(\"recovered\",))\n                                    self._on_rec_select()\n                                self.after(0, _upd_mob)\n                            except Exception as e:\n                                errors.append(f\"Mobile hash/score failed: {e}\")\n                            count += 1\n                        else:\n                            errors.append(f\"Mobile pull failed: {src} | {out[:140]}\")\n                    except Exception as e:\n                        errors.append(str(e))\n                else:\n                    path = entry if isinstance(entry, str) else entry.get(\"path\", \"\")\n                    if path and os.path.exists(path):\n                        try:\n                            dst = os.path.join(dest, os.path.basename(path))\n                            shutil.copy2(path, dst)\n                            try:\n                                h = self._sha256_file(dst)\n                                if h in seen_hashes:\n                                    os.remove(dst)\n                                    errors.append(f\"Duplicate local file skipped: {os.path.basename(dst)}\")\n                                    continue\n                                seen_hashes.add(h)\n                                score, _reason = self._integrity_score(dst, os.path.splitext(dst)[1].lstrip(\".\"))\n                                actual_size = self._fmt_size(os.path.getsize(dst))\n                                score_text = f\"{score}/100 {'\u2705' if score &gt;= 60 else '\u26a0 check'}\"\n                                def _upd_loc(i=iid, s=actual_size, sc=score_text):\n                                    vals = list(self.rec_tree.item(i, \"values\"))\n                                    if len(vals) &gt;= 6:\n                                        self.rec_tree.item(i, values=(vals[0], vals[1], s, \"\u2705 Recovered\", vals[4], sc), tags=(\"recovered\",))\n                                    self._on_rec_select()\n                                self.after(0, _upd_loc)\n                            except Exception as e:\n                                errors.append(f\"Local hash/score failed: {e}\")\n                            count += 1\n                        except Exception as e:\n                            errors.append(str(e))\n        finally:\n            def _finish():\n                if hasattr(self, \"_rec_recover_btn\"):\n                    self._rec_recover_btn.config(state=\"normal\")\n                summary = f\"\u2705 {count} files recovered to {dest}\"\n                if errors:\n                    summary += f\" | \u26a0 {len(errors)} errors\"\n                self._set_status(summary, C[\"success\"] if not errors else C[\"warning\"])\n                after_state = self._snapshot_resource_state() or {}\n                self._hdd_recovery_emit_metrics({\n                    \"phase\": \"recovery_extract\",\n                    \"status_text\": summary,\n                    \"progress_pct\": 100.0,\n                    \"files_found\": count,\n                    \"resource_before_mb\": before_state.get(\"available_mb\", 0),\n                    \"resource_after_mb\": after_state.get(\"available_mb\", 0),\n                    \"delta_mb\": after_state.get(\"available_mb\", 0) - before_state.get(\"available_mb\", 0),\n                })\n            self.after(0, _finish)\n            self.after(0, self._finish_recovery_operation)\n            gc.collect()\n\n    # ---------- LIVE TEMPERATURE (unchanged) ----------\n    def _build_live_temps(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83c\udf21\ufe0f Live Temperature Monitor\", \"Real CPU/GPU thermal readings\", hw=True)\n        self._action_card_grid(frame, [\n            (\"\ud83c\udf21\", \"Refresh Temps\", \"CPU + GPU temperature readings\", C[\"btn_chip\"], self._scan_temps),\n        ], cols=1)\n        stats = tk.Frame(frame, bg=C[\"bg\"])\n        stats.pack(fill=\"x\", padx=16, pady=8)\n        self.temp_cards = {}\n        for i, (k, lbl, color) in enumerate([(\"cpu_t\",\"CPU Temp\",C[\"error\"]), (\"gpu_t\",\"GPU Temp\",C[\"accent4\"])]):\n            card = self._stat_card(stats, lbl, \"--\", color)\n            card.grid(row=0, column=i, padx=6, sticky=\"ew\")\n            stats.columnconfigure(i, weight=1)\n            self.temp_cards[k] = card\n        self.temp_log = self._scrolled_text(frame, 18)\n        return frame\n\n    def _scan_temps(self):\n        self._launch_job(\"scan_temps\", self._do_scan_temps)\n\n    def _do_scan_temps(self):\n        self._append_log(self.temp_log, \"Querying WMI thermal zones...\", C[\"text\"])\n        out, _ = self._run_powershell(\n            \"Get-WmiObject -Namespace root\\\\wmi \"\n            \"-Class MSAcpi_ThermalZoneTemperature | \"\n            \"Select-Object -ExpandProperty CurrentTemperature\", timeout=15)\n        temps = []\n        for line in out.splitlines():\n            stripped = line.strip()\n            if stripped.replace('.', '').isdigit():\n                try:\n                    temps.append(float(stripped))\n                except:\n                    pass\n        if temps:\n            cpu_c = (temps[0] / 10.0) - 273.15\n            self.temp_cards[\"cpu_t\"]._value_lbl.config(text=f\"{cpu_c:.1f} \u00b0C\")\n            self.temp_cards[\"cpu_t\"]._bar.config(value=min(cpu_c, 100))\n            self._append_log(self.temp_log, f\"CPU Temp: {cpu_c:.1f} \u00b0C\", C[\"success\"] if cpu_c &lt; 75 else C[\"error\"])\n            if len(temps) &gt; 1:\n                gpu_c = (temps[1] / 10.0) - 273.15\n                self.temp_cards[\"gpu_t\"]._value_lbl.config(text=f\"{gpu_c:.1f} \u00b0C\")\n                self.temp_cards[\"gpu_t\"]._bar.config(value=min(gpu_c, 100))\n                self._append_log(self.temp_log, f\"GPU Temp: {gpu_c:.1f} \u00b0C\", C[\"success\"] if gpu_c &lt; 85 else C[\"error\"])\n        else:\n            self._append_log(self.temp_log, \"\u26a0 Native WMI thermal probes not found on this hardware.\", C[\"warning\"])\n            self._append_log(self.temp_log, \"Note: Requires laptop sensors or specific desktop motherboards.\", C[\"text_dim\"])\n        self._append_log(self.temp_log, \"\u2705 Temp scan complete.\", C[\"success\"])\n        self._set_status(\"Temp scan complete\", C[\"success\"])\n\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  REVO-STYLE BATCH UNINSTALLER  v2.0  \u2014  Deep Forced Removal\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _build_uninstaller(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"Professional Uninstall Center\",\n                             \"Safe uninstall, force removal, leftover scan and audit-ready cleanup\")\n\n        guide = tk.Frame(frame, bg=C[\"card\"], highlightbackground=C[\"accent2\"], highlightthickness=1)\n        guide.pack(fill=\"x\", padx=16, pady=(8, 4))\n        tk.Label(guide, text=\"Beginner-safe workflow\", font=FONTS[\"subhead\"],\n                 fg=C[\"accent2\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=12, pady=(8, 2))\n        tk.Label(\n            guide,\n            text=\"1. Scan Programs.  2. Select an app.  3. Use Safe Uninstall first.  4. Scan Leftovers.  5. Clean only reviewed items. Force Uninstall is for broken uninstallers only.\",\n            font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], anchor=\"w\",\n            justify=\"left\", wraplength=self._dpi_px(1040)\n        ).pack(fill=\"x\", padx=12, pady=(0, 8))\n\n        uninst_actions = [\n            (\"Scan Programs\", C[\"btn_info\"], self._scan_installed),\n            (\"Safe Uninstall\", C[\"btn_warn\"], self._uninst_standard),\n            (\"Force Uninstall\", C[\"btn_danger\"], self._uninst_force),\n            (\"Deep Leftover Scan\", C[\"btn_info\"], self._scan_leftovers),\n            (\"Clean Reviewed\", C[\"btn_danger\"], self._clean_leftovers),\n            (\"Unlock Locked File\", C[\"btn_chip\"], self._unlock_file_dialog),\n            (\"Deep Folder Cleanup\", C[\"btn_danger\"], self._deep_cleanup_folder_dialog),\n        ]\n\n        sf = tk.Frame(frame, bg=C[\"bg\"])\n        sf.pack(fill=\"x\", padx=16, pady=(6,2))\n        tk.Label(sf, text=\"\ud83d\udd0d Search:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"]).pack(side=\"left\")\n        self.uninst_search = tk.Entry(sf, width=30, font=FONTS[\"body\"], bg=C[\"card\"],\n                                      fg=C[\"text\"], insertbackground=C[\"text\"], relief=\"flat\", bd=4)\n        self.uninst_search.pack(side=\"left\", padx=8)\n        self.uninst_search.bind(\"\", self._filter_uninst)\n        self.uninst_count_lbl = tk.Label(sf, text=\"\", font=FONTS[\"small\"], fg=C[\"accent\"], bg=C[\"bg\"])\n        self.uninst_count_lbl.pack(side=\"left\", padx=12)\n        self.uninst_pause_btn = self._btn(sf, \"Pause Scan\", C[\"btn_chip\"], self._pause_resume_uninst_scan)\n        self.uninst_pause_btn.pack(side=\"right\", padx=4)\n        self._btn(sf, \"Stop Scan\", C[\"btn_danger\"], self._stop_uninst_scan).pack(side=\"right\", padx=4)\n\n        self.uninst_progress_var = tk.DoubleVar(value=0)\n        ttk.Progressbar(frame, variable=self.uninst_progress_var, maximum=100, mode=\"determinate\").pack(\n            fill=\"x\", padx=16, pady=(2, 4)\n        )\n        self.uninst_timing_lbl = tk.Label(frame, text=\"Elapsed: 00:00 | Left: -- | Total: --\",\n                                          font=FONTS[\"small\"], fg=C[\"text_dim\"],\n                                          bg=C[\"bg\"], anchor=\"w\")\n        self.uninst_timing_lbl.pack(fill=\"x\", padx=16, pady=(0, 4))\n\n        summary = tk.Frame(frame, bg=C[\"bg\"])\n        summary.pack(fill=\"x\", padx=16, pady=(0, 4))\n        self.uninst_summary_vars = {}\n        for key, label, color in [\n            (\"programs\", \"Programs\", C[\"accent\"]),\n            (\"leftovers\", \"Leftovers\", C[\"warning\"]),\n            (\"risky\", \"Risky\", C[\"accent3\"]),\n            (\"safe\", \"Safe\", C[\"accent2\"]),\n        ]:\n            box = tk.Frame(summary, bg=C[\"card\"], highlightbackground=C[\"border\"], highlightthickness=1)\n            box.pack(side=\"left\", padx=(0, 6), fill=\"x\", expand=True)\n            tk.Label(box, text=label, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=8, pady=(5, 0))\n            var = tk.StringVar(value=\"0\")\n            self.uninst_summary_vars[key] = var\n            tk.Label(box, textvariable=var, font=FONTS[\"heading\"], fg=color, bg=C[\"card\"]).pack(anchor=\"w\", padx=8, pady=(0, 5))\n\n        # \u2500\u2500 Paned layout \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        paned = tk.Frame(frame, bg=C[\"bg\"])\n        paned.pack(fill=\"both\", expand=True, padx=16, pady=6)\n        paned.columnconfigure(0, weight=5)\n        paned.columnconfigure(1, weight=3)\n        paned.rowconfigure(0, weight=1)\n\n        # Left: program list\n        left = tk.Frame(paned, bg=C[\"card\"])\n        left.grid(row=0, column=0, sticky=\"nsew\", padx=(0,6))\n        left.rowconfigure(1, weight=1)\n        left.columnconfigure(0, weight=1)\n        tk.Label(left, text=\"  Installed Programs\", font=FONTS[\"subhead\"],\n                 fg=C[\"accent\"], bg=C[\"card\"]).grid(row=0, column=0, columnspan=3, sticky=\"w\", pady=(8,4), padx=8)\n        cols = (\"Software\",\"Version\",\"Size\",\"Date\",\"Publisher\")\n        self.uninst_tree = ttk.Treeview(left, columns=cols, show=\"headings\",\n                                        height=24, style=\"Custom.Treeview\")\n        for col, w in zip(cols, [260, 90, 80, 90, 170]):\n            self.uninst_tree.heading(col, text=col,\n                                     command=lambda c=col: self._sort_uninst(c))\n            self.uninst_tree.column(col, width=w, anchor=\"w\")\n        vsb = ttk.Scrollbar(left, orient=\"vertical\", command=self.uninst_tree.yview)\n        hsb = ttk.Scrollbar(left, orient=\"horizontal\", command=self.uninst_tree.xview)\n        self.uninst_tree.configure(yscrollcommand=vsb.set, xscrollcommand=hsb.set)\n        self.uninst_tree.grid(row=1, column=0, sticky=\"nsew\", padx=(8,0), pady=(0,0))\n        vsb.grid(row=1, column=1, sticky=\"ns\", pady=(0,0), padx=(0,8))\n        hsb.grid(row=2, column=0, sticky=\"ew\", padx=(8,0), pady=(0,8))\n        self._bind_tree_responsive_columns(self.uninst_tree, [\n            (\"Software\", 280, 5), (\"Version\", 90, 1), (\"Size\", 80, 1), (\"Date\", 90, 1), (\"Publisher\", 180, 3)\n        ])\n        self.uninst_tree.bind(\"&lt;&gt;\", self._on_uninst_select)\n\n        # Right: detail + leftover panel\n        right = tk.Frame(paned, bg=C[\"card\"])\n        right.grid(row=0, column=1, sticky=\"nsew\", padx=(6,0))\n        right.rowconfigure(3, weight=1)\n        right.rowconfigure(5, weight=2)\n        right.columnconfigure(0, weight=1)\n\n        tk.Label(right, text=\"  Actions\", font=FONTS[\"subhead\"],\n                 fg=C[\"accent\"], bg=C[\"card\"]).grid(row=0, column=0, columnspan=2,\n                 sticky=\"w\", padx=8, pady=(8,2))\n        action_box = tk.Frame(right, bg=C[\"card\"])\n        action_box.grid(row=1, column=0, columnspan=2, sticky=\"ew\", padx=4, pady=(0,4))\n        self._compact_action_grid(action_box, uninst_actions, cols=2)\n\n        tk.Label(right, text=\"  App Details\", font=FONTS[\"subhead\"],\n                 fg=C[\"accent\"], bg=C[\"card\"]).grid(row=2, column=0, columnspan=2,\n                 sticky=\"w\", padx=8, pady=(8,4))\n        self.uninst_detail = scrolledtext.ScrolledText(\n            right, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"],\n            height=5, bd=0, relief=\"flat\", state=\"disabled\", wrap=\"word\")\n        self.uninst_detail.grid(row=3, column=0, columnspan=2,\n                                sticky=\"nsew\", padx=8, pady=(0,4))\n\n        tk.Label(right, text=\"  Leftover Files / Registry / Folders\",\n                 font=FONTS[\"subhead\"], fg=C[\"warning\"], bg=C[\"card\"]).grid(\n                 row=4, column=0, sticky=\"w\", padx=8, pady=(4,4))\n        self.leftover_tree = ttk.Treeview(right, columns=(\"Type\",\"Risk\",\"Confidence\",\"Path\"),\n                                          show=\"headings\", height=10,\n                                          style=\"Custom.Treeview\")\n        self.leftover_tree.heading(\"Type\", text=\"Type\")\n        self.leftover_tree.column(\"Type\", width=80, anchor=\"center\")\n        self.leftover_tree.heading(\"Risk\", text=\"Risk\")\n        self.leftover_tree.column(\"Risk\", width=70, anchor=\"center\")\n        self.leftover_tree.heading(\"Confidence\", text=\"Score\")\n        self.leftover_tree.column(\"Confidence\", width=70, anchor=\"center\")\n        self.leftover_tree.heading(\"Path\", text=\"Path / Registry Key\")\n        self.leftover_tree.column(\"Path\", width=330, anchor=\"w\")\n        self.leftover_tree.tag_configure(\"file\", foreground=C[\"warning\"])\n        self.leftover_tree.tag_configure(\"reg\",  foreground=C[\"accent3\"])\n        self.leftover_tree.tag_configure(\"safe\", foreground=C[\"success\"])\n        self.leftover_tree.tag_configure(\"risky\", foreground=C[\"accent3\"])\n        lvsb = ttk.Scrollbar(right, orient=\"vertical\", command=self.leftover_tree.yview)\n        self.leftover_tree.configure(yscrollcommand=lvsb.set)\n        self.leftover_tree.grid(row=5, column=0, sticky=\"nsew\", padx=(8,0), pady=(0,8))\n        lvsb.grid(row=5, column=1, sticky=\"ns\", pady=(0,8), padx=(0,4))\n        self._bind_tree_responsive_columns(self.leftover_tree, [\n            (\"Type\", 80, 0), (\"Risk\", 70, 0), (\"Confidence\", 70, 0), (\"Path\", 330, 4)\n        ])\n\n        self.uninst_status = tk.Label(frame, text=\"  Ready \u2014 Scan programs to begin\",\n                                      font=FONTS[\"small\"], fg=C[\"accent2\"],\n                                      bg=C[\"bg\"], anchor=\"w\")\n        self.uninst_status.pack(fill=\"x\", padx=16, pady=(0,6))\n\n        # Internal state\n        self.uninst_data     = []\n        self.uninst_filtered = []\n        self.leftover_items  = []\n        self.uninst_sort_col = \"\"\n        self.uninst_sort_rev = False\n        self._uninst_cancel_flag = False\n        self._uninst_pause_flag = False\n        self._set_uninst_progress(0, \"Ready - Scan Programs to begin\", C[\"accent2\"])\n        return frame\n\n    def _build_event_viewer(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udcdc Event Viewer (Simple Explain)\",\n                             \"System/Application errors ka simple reason + solution\")\n\n        top = tk.Frame(frame, bg=C[\"panel\"])\n        top.pack(fill=\"x\", padx=16, pady=(8, 6))\n\n        tk.Label(top, text=\"Log:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"left\", padx=(8, 4))\n        self.ev_log_var = tk.StringVar(value=\"System\")\n        self.ev_log_combo = ttk.Combobox(top, textvariable=self.ev_log_var, values=[\"System\", \"Application\"], width=12, state=\"readonly\")\n        self.ev_log_combo.pack(side=\"left\", padx=4, pady=8)\n\n        tk.Label(top, text=\"Level:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"left\", padx=(10, 4))\n        self.ev_level_var = tk.StringVar(value=\"Error,Critical\")\n        self.ev_level_combo = ttk.Combobox(top, textvariable=self.ev_level_var, values=[\"Error,Critical\", \"Error\", \"Warning,Error,Critical\"], width=20, state=\"readonly\")\n        self.ev_level_combo.pack(side=\"left\", padx=4, pady=8)\n\n        tk.Label(top, text=\"Count:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"left\", padx=(10, 4))\n        self.ev_count_entry = tk.Entry(top, width=6, font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"])\n        self.ev_count_entry.insert(0, \"80\")\n        self.ev_count_entry.pack(side=\"left\", padx=4, pady=8)\n\n        self._btn(top, \"\ud83d\udd04 Fetch Events\", C[\"btn_info\"], self._eventviewer_fetch).pack(side=\"left\", padx=(12, 4), pady=8)\n        self._btn(top, \"\ud83e\udde0 Explain Selected\", C[\"btn_warn\"], self._eventviewer_explain_selected).pack(side=\"left\", padx=4, pady=8)\n\n        body = tk.Frame(frame, bg=C[\"bg\"])\n        body.pack(fill=\"both\", expand=True, padx=16, pady=(0, 8))\n        body.columnconfigure(0, weight=3)\n        body.columnconfigure(1, weight=2)\n        body.rowconfigure(0, weight=1)\n\n        left = tk.Frame(body, bg=C[\"card\"])\n        left.grid(row=0, column=0, sticky=\"nsew\", padx=(0, 6))\n        tk.Label(left, text=\"  Recent Windows Events\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8, 4), padx=8)\n\n        cols = (\"Time\", \"Source\", \"EventID\", \"Level\", \"Message\")\n        self.ev_tree = ttk.Treeview(left, columns=cols, show=\"headings\", height=18, style=\"Custom.Treeview\")\n        widths = [160, 180, 80, 90, 600]\n        for col, w in zip(cols, widths):\n            self.ev_tree.heading(col, text=col)\n            self.ev_tree.column(col, width=w, anchor=\"w\")\n        evsb = ttk.Scrollbar(left, orient=\"vertical\", command=self.ev_tree.yview)\n        self.ev_tree.configure(yscrollcommand=evsb.set)\n        self.ev_tree.pack(side=\"left\", fill=\"both\", expand=True, padx=(8, 0), pady=(0, 8))\n        evsb.pack(side=\"right\", fill=\"y\", pady=(0, 8), padx=(0, 4))\n        self.ev_tree.bind(\"&lt;&gt;\", self._eventviewer_explain_selected)\n\n        right = tk.Frame(body, bg=C[\"card\"])\n        right.grid(row=0, column=1, sticky=\"nsew\", padx=(6, 0))\n        tk.Label(right, text=\"  Simple Explanation\", font=FONTS[\"subhead\"], fg=C[\"warning\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(8, 4), padx=8)\n        self.ev_explain = scrolledtext.ScrolledText(\n            right, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"],\n            height=22, bd=0, relief=\"flat\", state=\"disabled\", wrap=\"word\"\n        )\n        self.ev_explain.pack(fill=\"both\", expand=True, padx=8, pady=(0, 8))\n\n        self.ev_status = tk.Label(frame, text=\"  Ready - Fetch Events dabao\", font=FONTS[\"small\"],\n                                  fg=C[\"accent2\"], bg=C[\"bg\"], anchor=\"w\")\n        self.ev_status.pack(fill=\"x\", padx=16, pady=(0, 6))\n        self.ev_items = []\n        return frame\n\n    def _eventviewer_fetch(self):\n        log_name = (self.ev_log_var.get() if hasattr(self, \"ev_log_var\") else \"System\").strip() or \"System\"\n        level_csv = (self.ev_level_var.get() if hasattr(self, \"ev_level_var\") else \"Error,Critical\").strip()\n        count = 80\n        try:\n            count = max(10, min(300, int((self.ev_count_entry.get() or \"80\").strip())))\n        except Exception:\n            count = 80\n        self.ev_status.config(text=f\"  Fetching {log_name} events...\", fg=C[\"accent4\"])\n        self._launch_job(\"eventviewer_fetch\", self._do_eventviewer_fetch, log_name, level_csv, count)\n\n    def _do_eventviewer_fetch(self, log_name, level_csv, count):\n        levels = [x.strip().lower() for x in str(level_csv).split(\",\") if x.strip()]\n        level_map = {\"critical\": 1, \"error\": 2, \"warning\": 3, \"information\": 4, \"verbose\": 5}\n        lvl_ids = [str(level_map[x]) for x in levels if x in level_map]\n        if not lvl_ids:\n            lvl_ids = [\"1\", \"2\"]\n        level_expr = \",\".join(lvl_ids)\n\n        ps_script = (\n            f\"$f=@{{LogName='{log_name}'; Level={level_expr}}}; \"\n            f\"Get-WinEvent -FilterHashtable $f -MaxEvents {int(count)} -ErrorAction SilentlyContinue | \"\n            f\"Select-Object TimeCreated,ProviderName,Id,LevelDisplayName,Message | ConvertTo-Json -Depth 4\"\n        )\n        cmd = f'powershell -NoProfile -ExecutionPolicy Bypass -Command \"{ps_script}\"'\n        out, rc = self._run_cmd(cmd, timeout=60)\n        if rc != 0 or not out.strip():\n            self.after(0, lambda: self.ev_status.config(text=\"  Event fetch failed. Run as Admin and retry.\", fg=C[\"error\"]))\n            return\n        try:\n            data = json.loads(out)\n            if isinstance(data, dict):\n                data = [data]\n            if not isinstance(data, list):\n                data = []\n        except Exception:\n            data = []\n        self.ev_items = data\n        self.after(0, self._populate_eventviewer_tree)\n\n    def _populate_eventviewer_tree(self):\n        self.ev_tree.delete(*self.ev_tree.get_children())\n        for ev in self.ev_items:\n            try:\n                t = str(ev.get(\"TimeCreated\", \"\"))[:19].replace(\"T\", \" \")\n                src = str(ev.get(\"ProviderName\", \"\") or \"\")\n                eid = str(ev.get(\"Id\", \"\") or \"\")\n                lvl = str(ev.get(\"LevelDisplayName\", \"\") or \"\")\n                msg = \" \".join(str(ev.get(\"Message\", \"\") or \"\").split())\n                if len(msg) &gt; 220:\n                    msg = msg[:220] + \"...\"\n                self.ev_tree.insert(\"\", \"end\", values=(t, src, eid, lvl, msg))\n            except Exception:\n                pass\n        c = len(self.ev_items)\n        color = C[\"warning\"] if c else C[\"success\"]\n        self.ev_status.config(text=f\"  Loaded {c} event(s). Select one for simple explanation.\", fg=color)\n        if c:\n            first = self.ev_tree.get_children()\n            if first:\n                self.ev_tree.selection_set(first[0])\n                self._eventviewer_explain_selected()\n\n    def _eventviewer_explain_selected(self, event=None):\n        if not hasattr(self, \"ev_tree\"):\n            return\n        sel = self.ev_tree.selection()\n        if not sel:\n            return\n        idx = self.ev_tree.index(sel[0])\n        if idx &lt; 0 or idx &gt;= len(self.ev_items):\n            return\n        ev = self.ev_items[idx]\n        text = self._eventviewer_make_simple_explain(ev)\n        self.ev_explain.config(state=\"normal\")\n        self.ev_explain.delete(\"1.0\", \"end\")\n        self.ev_explain.insert(\"1.0\", text)\n        self.ev_explain.config(state=\"disabled\")\n\n    def _eventviewer_make_simple_explain(self, ev):\n        eid = str(ev.get(\"Id\", \"\") or \"\")\n        source = str(ev.get(\"ProviderName\", \"\") or \"Unknown\")\n        level = str(ev.get(\"LevelDisplayName\", \"\") or \"Unknown\")\n        t = str(ev.get(\"TimeCreated\", \"\") or \"\").replace(\"T\", \" \")\n        msg_full = str(ev.get(\"Message\", \"\") or \"\").strip()\n        msg_low = msg_full.lower()\n\n        reason = \"System me operation fail hua ya expected service response nahi mili.\"\n        solution = \"System restart karo, latest updates lagao, phir issue ko dubara reproduce karke check karo.\"\n\n        known = {\n            (\"Kernel-Power\", \"41\"): (\n                \"PC proper shutdown ke bina restart hua (power cut, crash, force restart).\",\n                \"Power cable/SMPS check karo, overheating test karo, RAM test chalao, aur sudden power loss avoid karo.\"\n            ),\n            (\"Microsoft-Windows-Kernel-Power\", \"41\"): (\n                \"PC proper shutdown ke bina restart hua. Ye BSOD, power cut, overheating ya force shutdown se aa sakta hai.\",\n                \"BugCheck/WHEA/Disk events ke saath compare karo. PSU, temperature, RAM, driver aur disk health check karo.\"\n            ),\n            (\"Microsoft-Windows-WER-SystemErrorReporting\", \"1001\"): (\n                \"Windows ne BugCheck/Blue Screen report log kiya.\",\n                \"Stop code note karo, C:\\\\Windows\\\\Minidump file analyze karo, phir culprit driver/hardware fix karo.\"\n            ),\n            (\"Microsoft-Windows-WHEA-Logger\", \"17\"): (\n                \"Corrected hardware error detect hua; system bach gaya par hardware path warning de raha hai.\",\n                \"BIOS/chipset update, overclock off, RAM/SSD/GPU/PCIe health aur temperature check karo.\"\n            ),\n            (\"Microsoft-Windows-WHEA-Logger\", \"18\"): (\n                \"Fatal hardware error detect hua; ye BSOD ka strong hardware clue hai.\",\n                \"RAM test, CPU/GPU temperature, PSU, SSD SMART, BIOS/chipset update aur overclock reset karo.\"\n            ),\n            (\"Microsoft-Windows-WHEA-Logger\", \"19\"): (\n                \"Corrected hardware error repeat ho sakta hai.\",\n                \"Event details me component dekho, phir related driver/firmware/hardware check karo.\"\n            ),\n            (\"volmgr\", \"161\"): (\n                \"Crash dump create nahi ho paya, isliye BSOD proof file missing ho sakti hai.\",\n                \"C: drive free space, pagefile aur CrashControl minidump settings enable karo.\"\n            ),\n            (\"Display\", \"4101\"): (\n                \"Display/GPU driver ne respond karna band kiya aur recover hua.\",\n                \"GPU driver clean reinstall/rollback, GPU temperature, power cable/PSU aur hardware acceleration test karo.\"\n            ),\n            (\"Application Error\", \"1000\"): (\n                \"Kisi application/module ne crash kiya.\",\n                \"Faulting application/module name dekho. Agar rundll32.exe hai to loaded DLL/app culprit hota hai; us app/driver ko repair karo.\"\n            ),\n            (\"SideBySide\", \"33\"): (\n                \"App runtime/VC++ dependency mismatch ya missing manifest issue.\",\n                \"Affected app reinstall/repair karo aur Microsoft Visual C++ Redistributables repair/install karo.\"\n            ),\n            (\"Service Control Manager\", \"7000\"): (\n                \"Koi service startup pe start nahi ho payi.\",\n                \"Services menu me jaake service dependencies check karo, startup type sahi set karo, phir reboot karo.\"\n            ),\n            (\"Service Control Manager\", \"7001\"): (\n                \"Service dependency chain me issue hai, required service pehle start nahi hui.\",\n                \"Related dependent services ko Automatic pe set karo aur start order verify karo.\"\n            ),\n            (\"Disk\", \"7\"): (\n                \"Disk read/write hardware level problem detect hui.\",\n                \"SMART scan chalao, cable/port check karo, data backup lo, aur disk health verify karo.\"\n            ),\n            (\"Ntfs\", \"55\"): (\n                \"File system me corruption detect hua.\",\n                \"Admin CMD me `chkdsk /f` run karo (boot drive ke liye restart required).\"\n            ),\n            (\"DistributedCOM\", \"10016\"): (\n                \"DCOM permission mismatch log hua; mostly harmless hota hai.\",\n                \"Agar app crash nahi ho rahi to ignore kar sakte ho; otherwise specific app permissions tune karo.\"\n            ),\n        }\n        if (source, eid) in known:\n            reason, solution = known[(source, eid)]\n        else:\n            if \"access is denied\" in msg_low or \"access denied\" in msg_low:\n                reason = \"Permission issue ki wajah se operation block hua.\"\n                solution = \"Tool/Admin rights ke saath run karo, folder/service permissions verify karo.\"\n            elif \"bugcheck\" in msg_low or \"blue screen\" in msg_low:\n                reason = \"Windows kernel crash/BSOD report log hua.\"\n                solution = \"BSoD Deep Diagnose run karo, stop code aur minidump check karo, phir driver/RAM/disk/GPU cause fix karo.\"\n            elif \"rundll32\" in msg_low or \"rundell32\" in msg_low:\n                reason = \"rundll32.exe se DLL load/crash issue lag raha hai. Real Windows file rundll32.exe hota hai, rundell32.dll nahi.\"\n                solution = \"Rundll32 Error Check run karo; startup/task me missing DLL entry disable karo, affected app reinstall/uninstall karo, SFC/DISM aur malware scan chalao.\"\n            elif \"specified module could not be found\" in msg_low or \"module could not be found\" in msg_low:\n                reason = \"Koi startup/app ek DLL load kar raha tha jo ab missing hai.\"\n                solution = \"Startup Apps, Task Scheduler aur registry Run entries me missing DLL reference dhoondh kar disable/remove karo ya related app reinstall karo.\"\n            elif \"side-by-side\" in msg_low or \"activation context\" in msg_low:\n                reason = \"App runtime/VC++ dependency mismatch detect hua.\"\n                solution = \"Affected app repair/reinstall karo aur Microsoft Visual C++ Redistributables repair/install karo.\"\n            elif \"whea\" in msg_low or \"hardware error\" in msg_low:\n                reason = \"Hardware layer se error signal mila.\"\n                solution = \"Temperature, RAM, SSD SMART, GPU/PCIe, PSU, BIOS/chipset driver aur overclock settings check karo.\"\n            elif \"timeout\" in msg_low or \"timed out\" in msg_low:\n                reason = \"Operation ko required response time me reply nahi mila.\"\n                solution = \"Heavy load kam karo, related service restart karo, network/disk responsiveness check karo.\"\n            elif \"driver\" in msg_low:\n                reason = \"Driver related compatibility ya corruption issue lag raha hai.\"\n                solution = \"Driver Checker se current driver version check karke stable version reinstall/update karo.\"\n            elif \"dns\" in msg_low or \"network\" in msg_low:\n                reason = \"Network stack ya DNS resolution me issue detect hua.\"\n                solution = \"Network Optimizer me DNS flush + TCP reset chalao, phir reconnect test karo.\"\n\n        if len(msg_full) &gt; 1200:\n            msg_full = msg_full[:1200] + \"\\n... (message truncated)\"\n\n        return (\n            f\"Event Time: {t}\\n\"\n            f\"Source: {source}\\n\"\n            f\"Error Code / Event ID: {eid}\\n\"\n            f\"Level: {level}\\n\\n\"\n            f\"1) Ye error code kya hai?\\n\"\n            f\"   Event ID {eid} ({source}) system ka diagnostic code hai jo issue category batata hai.\\n\\n\"\n            f\"2) Ye kyun aaya?\\n\"\n            f\"   {reason}\\n\\n\"\n            f\"3) Iska solution kya ho sakta hai?\\n\"\n            f\"   {solution}\\n\\n\"\n            f\"Original Windows Message:\\n{msg_full or 'N/A'}\\n\"\n        )\n\n    # \u2500\u2500 Scan all installed programs \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _threadsafe_confirm(self, title, message):\n        text = str(message)\n        if len(text) &gt; 5000:\n            text = text[:5000] + \"\\n\\n...list lambi hai, baaki items log me dekhein.\"\n        if threading.current_thread() is threading.main_thread():\n            return messagebox.askyesno(title, text)\n        done = threading.Event()\n        result = {\"yes\": False}\n\n        def _ask():\n            try:\n                result[\"yes\"] = messagebox.askyesno(title, text)\n            finally:\n                done.set()\n\n        self.after(0, _ask)\n        done.wait()\n        return result[\"yes\"]\n\n    def _tool_log(self, msg, level=\"INFO\"):\n        self.after(0, lambda: self._log(msg, level))\n\n    def _unlock_file_dialog(self):\n        path = filedialog.askopenfilename(title=\"Locked file select karo\")\n        if not path:\n            return\n        self.uninst_status.config(text=\"Locked file scan chal raha hai...\", fg=C[\"accent4\"])\n\n        def _run():\n            result = unlock_file_if_locked(\n                path,\n                confirm_callback=self._threadsafe_confirm,\n                log_callback=lambda msg: self._tool_log(msg, \"INFO\"),\n            )\n\n            def _finish():\n                color = C[\"success\"] if result.get(\"ok\") else C[\"warning\"]\n                self.uninst_status.config(text=result.get(\"message\", \"Unlock complete\"), fg=color)\n                details = result.get(\"message\", \"\")\n                if result.get(\"terminated\"):\n                    details += \"\\n\\nTerminated PID(s): \" + \", \".join(map(str, result[\"terminated\"]))\n                if result.get(\"errors\"):\n                    details += \"\\n\\nErrors:\\n\" + \"\\n\".join(result[\"errors\"])\n                if result.get(\"ok\"):\n                    messagebox.showinfo(\"Unlock Result\", details)\n                else:\n                    messagebox.showwarning(\"Unlock Result\", details)\n\n            self.after(0, _finish)\n\n        self._launch_job(\"unlock_app\", _run)\n\n    def _deep_cleanup_folder_dialog(self):\n        folder = filedialog.askdirectory(title=\"Program folder select karo\")\n        if not folder:\n            return\n        self.uninst_status.config(text=\"Deep cleanup scan chal raha hai...\", fg=C[\"accent4\"])\n\n        def _run():\n            result = deep_cleanup_program(\n                folder,\n                confirm_callback=self._threadsafe_confirm,\n                log_callback=lambda msg: self._tool_log(msg, \"INFO\"),\n            )\n\n            def _finish():\n                color = C[\"success\"] if result.get(\"ok\") else C[\"warning\"]\n                self.uninst_status.config(text=result.get(\"message\", \"Deep cleanup complete\"), fg=color)\n                details = result.get(\"message\", \"\")\n                if result.get(\"ok\"):\n                    details += (\n                        f\"\\n\\nFiles: {result.get('files', 0)}\"\n                        f\"\\nFolders: {result.get('dirs', 0)}\"\n                        f\"\\nRegistry clues listed: {len(result.get('registry_entries', []))}\"\n                    )\n                    messagebox.showinfo(\"Deep Cleanup Result\", details)\n                    self._scan_installed()\n                else:\n                    if result.get(\"errors\"):\n                        details += \"\\n\\nErrors:\\n\" + \"\\n\".join(result[\"errors\"])\n                    messagebox.showwarning(\"Deep Cleanup Result\", details)\n\n            self.after(0, _finish)\n\n        self._launch_job(\"deep_cleanup\", _run)\n\n    def _scan_installed(self):\n        self.uninst_tree.delete(*self.uninst_tree.get_children())\n        self.uninst_data = []\n        self.uninst_filtered = []\n        self._uninst_cancel_flag = False\n        self._uninst_pause_flag = False\n        if hasattr(self, \"uninst_pause_btn\"):\n            self.uninst_pause_btn.config(text=\"Pause Scan\")\n        self._set_uninst_progress(5, \"Scanning installed programs...\", C[\"accent4\"])\n        self._audit_event(\"uninstall_scan_started\", {\"scope\": \"installed_programs\"})\n        self._launch_job(\"scan_installed_programs\", self._do_scan_installed)\n\n    def _do_scan_installed(self):\n        regs = [\n            (winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\"),\n            (winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\"),\n            (winreg.HKEY_CURRENT_USER,  r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\"),\n        ]\n        found = []\n        try:\n            for reg_idx, (hive, path) in enumerate(regs, start=1):\n                self._check_uninst_control()\n                self._set_uninst_progress(10 + reg_idx * 18, f\"Reading uninstall registry hive {reg_idx}/{len(regs)}...\", C[\"accent4\"])\n                try:\n                    key = winreg.OpenKey(hive, path, 0, winreg.KEY_READ)\n                    i = 0\n                    while True:\n                        self._check_uninst_control()\n                        try:\n                            sub_name = winreg.EnumKey(key, i); i += 1\n                            subkey = winreg.OpenKey(key, sub_name, 0, winreg.KEY_READ)\n                            name      = self._reg_read_str(subkey, \"DisplayName\")\n                            version   = self._reg_read_str(subkey, \"DisplayVersion\")\n                            size_kb   = self._reg_read_str(subkey, \"EstimatedSize\")\n                            date      = self._reg_read_str(subkey, \"InstallDate\")\n                            uninst_s  = self._reg_read_str(subkey, \"UninstallString\")\n                            quiet_s   = self._reg_read_str(subkey, \"QuietUninstallString\")\n                            publisher = self._reg_read_str(subkey, \"Publisher\")\n                            inst_loc  = self._reg_read_str(subkey, \"InstallLocation\")\n                            winreg.CloseKey(subkey)\n                            if not name: continue\n                            skip_words = [\"KB\",\"Security Update\",\"Hotfix\",\"Service Pack\",\"Update for\"]\n                            if any(x in name for x in skip_words): continue\n                            try: sz = int(size_kb)*1024 if size_kb and size_kb.isdigit() else 0\n                            except: sz = 0\n                            found.append({\n                                \"name\": name, \"version\": version, \"size\": sz,\n                                \"date\": date[:8] if date and len(date) &gt;= 8 else \"--\",\n                                \"publisher\": publisher, \"uninst\": uninst_s,\n                                \"quiet\": quiet_s, \"install_loc\": inst_loc,\n                                \"has_uninstall\": bool(uninst_s or quiet_s),\n                                \"reg_key\": path + \"\\\\\" + sub_name,\n                                \"reg_hive\": \"HKLM\" if hive == winreg.HKEY_LOCAL_MACHINE else \"HKCU\",\n                            })\n                        except OSError: break\n                    winreg.CloseKey(key)\n                except Exception:\n                    pass\n        except InterruptedError:\n            self._audit_event(\"uninstall_scan_cancelled\", {\"scope\": \"installed_programs\", \"found\": len(found)})\n            self._set_uninst_progress(0, \"Installed-program scan cancelled.\", C[\"warning\"])\n            return\n        found.sort(key=lambda x: x[\"name\"].lower())\n        self.uninst_data     = found\n        self.uninst_filtered = found[:]\n        self.after(0, self._populate_uninst_tree)\n        self._set_uninst_progress(100, f\"Found {len(found)} programs\", C[\"success\"])\n        self._audit_event(\"uninstall_scan_finished\", {\"scope\": \"installed_programs\", \"count\": len(found)})\n        self.after(0, lambda: self._set_status(f\"Found {len(found)} installed programs\", C[\"success\"]))\n\n    def _populate_uninst_tree(self):\n        self.uninst_tree.delete(*self.uninst_tree.get_children())\n        for item in self.uninst_filtered:\n            self.uninst_tree.insert(\"\", \"end\", values=(\n                item[\"name\"], item[\"version\"],\n                self._fmt_size(item[\"size\"]), item[\"date\"], item[\"publisher\"]))\n        self.uninst_count_lbl.config(text=f\"{len(self.uninst_filtered)} programs\")\n        if hasattr(self, \"uninst_summary_vars\"):\n            self.uninst_summary_vars[\"programs\"].set(str(len(self.uninst_filtered)))\n\n    def _filter_uninst(self, event=None):\n        q = self.uninst_search.get().strip().lower()\n        self.uninst_filtered = (\n            self.uninst_data[:] if not q else\n            [x for x in self.uninst_data\n             if q in x[\"name\"].lower() or q in x[\"publisher\"].lower()])\n        self._populate_uninst_tree()\n\n    def _sort_uninst(self, col):\n        col_map = {\"Software\":\"name\",\"Version\":\"version\",\"Size\":\"size\",\"Date\":\"date\",\"Publisher\":\"publisher\"}\n        key = col_map.get(col, \"name\")\n        self.uninst_sort_rev = (not self.uninst_sort_rev) if self.uninst_sort_col == col else False\n        self.uninst_sort_col = col\n        self.uninst_filtered.sort(key=lambda x: str(x.get(key,\"\")), reverse=self.uninst_sort_rev)\n        self._populate_uninst_tree()\n\n    def _on_uninst_select(self, event=None):\n        sel = self.uninst_tree.selection()\n        if not sel: return\n        idx = self.uninst_tree.index(sel[0])\n        if idx &gt;= len(self.uninst_filtered): return\n        it = self.uninst_filtered[idx]\n        if not it.get(\"has_uninstall\"):\n            self.uninst_status.config(\n                text=\"Is program ka uninstall command nahi mila. \"\n                     \"Force Uninstall ya manual removal use karo.\",\n                fg=C[\"warning\"])\n        detail = (\n            f\"Name         : {it['name']}\\n\"\n            f\"Version      : {it['version'] or 'N/A'}\\n\"\n            f\"Publisher    : {it['publisher'] or 'N/A'}\\n\"\n            f\"Size         : {self._fmt_size(it['size'])}\\n\"\n            f\"Install Date : {it['date']}\\n\"\n            f\"Install Path : {it['install_loc'] or 'N/A'}\\n\"\n            f\"Registry Key : {it['reg_hive']}\\\\{it['reg_key']}\\n\"\n            f\"Has Uninstall: {'Yes' if it.get('has_uninstall') else 'No \u2014 use Force/manual'}\\n\"\n            f\"Uninstall    : {(it['uninst'] or 'N/A')[:100]}\\n\"\n            f\"Quiet Uninst : {(it['quiet'] or 'N/A')[:100]}\"\n        )\n        self.uninst_detail.config(state=\"normal\")\n        self.uninst_detail.delete(\"1.0\",\"end\")\n        self.uninst_detail.insert(\"1.0\", detail)\n        self.uninst_detail.config(state=\"disabled\")\n\n    def _get_sel_uninst(self):\n        items = []\n        for iid in self.uninst_tree.selection():\n            idx = self.uninst_tree.index(iid)\n            if idx &lt; len(self.uninst_filtered):\n                items.append(self.uninst_filtered[idx])\n        return items\n\n    def _uninst_is_protected(self, item):\n        \"\"\"\n        Publisher allowlist / protection guard.\n        Blocks uninstall for drivers/security/OS components by default.\n        \"\"\"\n        pub = (item.get(\"publisher\") or \"\").strip().lower()\n        name = (item.get(\"name\") or \"\").strip().lower()\n        protected_publishers = {\n            \"microsoft\", \"intel\", \"nvidia\", \"advanced micro devices\", \"amd\", \"realtek\",\n            \"qualcomm\", \"broadcom\", \"hewlett-packard\", \"hp\", \"dell\", \"lenovo\", \"asus\",\n            \"acer\", \"canon\", \"epson\", \"brother\", \"samsung\",\n        }\n        protected_keywords = {\n            \"driver\", \"chipset\", \"bluetooth\", \"wifi\", \"wireless\", \"lan\", \"ethernet\",\n            \"graphics\", \"display\", \"audio\", \"realtek\", \"nvidia\", \"intel\", \"amd\",\n            \"security update\", \"visual c++\", \"redistributable\", \"runtime\",\n        }\n        if any(p in pub for p in protected_publishers) or any(k in name for k in protected_keywords):\n            return True, f\"Protected publisher/app: {item.get('publisher') or 'N/A'}\"\n        return False, \"\"\n\n    def _uninst_verify_removed(self, item):\n        try:\n            hive = item.get(\"reg_hive\")\n            key_path = item.get(\"reg_key\")\n            if not hive or not key_path:\n                return True\n            # reg_hive stored as string in item; map it\n            hive_obj = winreg.HKEY_LOCAL_MACHINE if \"HKEY_LOCAL_MACHINE\" in hive or hive == \"HKLM\" else winreg.HKEY_CURRENT_USER\n            try:\n                k = winreg.OpenKey(hive_obj, key_path, 0, winreg.KEY_READ)\n                winreg.CloseKey(k)\n                return False\n            except Exception:\n                return True\n        except Exception:\n            return True\n\n    # \u2500\u2500 Standard Uninstall \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _uninst_standard(self):\n        items = self._get_sel_uninst()\n        if not items:\n            messagebox.showinfo(\"No Selection\",\"Select programs to uninstall.\"); return\n        no_cmd = [it for it in items if not it.get(\"has_uninstall\")]\n        if no_cmd:\n            self.uninst_status.config(\n                text=\"Is program ka uninstall command nahi mila. \"\n                     \"Force Uninstall ya manual removal use karo.\",\n                fg=C[\"warning\"])\n            messagebox.showwarning(\n                \"No Uninstall Command\",\n                \"In programs ke paas official uninstall command nahi hai:\\n\\n\"\n                + \"\\n\".join(x[\"name\"] for x in no_cmd[:12])\n                + (\"\\n...\" if len(no_cmd) &gt; 12 else \"\")\n                + \"\\n\\nSafe Uninstall skip hoga. Force Uninstall ya manual removal try karo.\")\n            items = [it for it in items if it.get(\"has_uninstall\")]\n            if not items:\n                return\n        protected = []\n        safe_items = []\n        for it in items:\n            ok, reason = self._uninst_is_protected(it)\n            if ok:\n                protected.append(f\"{it['name']} ({reason})\")\n            else:\n                safe_items.append(it)\n        if protected:\n            messagebox.showwarning(\"Protected Apps Skipped\",\n                                   \"Ye programs protected hain (drivers/system/security).\\n\"\n                                   \"Inko uninstall skip kiya ja raha hai:\\n\\n\" + \"\\n\".join(protected[:12]) +\n                                   (\"\\n...\" if len(protected) &gt; 12 else \"\"))\n        if not safe_items:\n            return\n        names = \"\\n\".join(it[\"name\"] for it in safe_items)\n        if not messagebox.askyesno(\"Safe Uninstall\",\n            f\"Run the official uninstaller for:\\n\\n{names}\\n\\n\"\n            \"A restore point is recommended. Silent mode is used only when the app provides it.\"): return\n        if not self._create_restore_point(\"Before Safe Uninstall\"):\n            return\n        self._audit_event(\"safe_uninstall_requested\", {\"items\": [x.get(\"name\") for x in safe_items]})\n        self._set_uninst_progress(10, f\"Safe uninstall queued for {len(safe_items)} program(s)\", C[\"accent4\"])\n        self._launch_job(\"safe_uninstall_batch\", self._run_uninst_batch_standard, safe_items)\n\n    def _run_uninst_batch_standard(self, items):\n        batch_leftovers = {}\n        total = len(items)\n        for idx, item in enumerate(items, start=1):\n            name = item[\"name\"]\n            self.after(0, lambda i=idx, t=total, n=name: self.uninst_status.config(\n                text=f\"[{i}/{t}] Uninstalling: {n}...\", fg=C[\"accent4\"]))\n            # Uninstall karo\n            cmd  = self._normalize_uninstall_command(item, quiet=True)\n            if cmd:\n                self._audit_event(\"safe_uninstall_command\", {\"name\": name, \"cmd\": cmd[:300]})\n                out, rc = self._run_cmd(cmd, timeout=300)\n                if rc == 0:\n                    self._log(f\"Uninstalled OK: {name}\", \"OK\")\n                else:\n                    self._log(f\"Uninstall issue: {name} (rc={rc})\", \"WARN\")\n            # \u2500\u2500 REVO STYLE: Uninstall ke turant baad leftover scan \u2500\u2500\u2500\u2500\u2500\n            self.after(0, lambda i=idx, t=total, n=name: self.uninst_status.config(\n                text=f\"[{i}/{t}] Scanning leftovers: {n}...\", fg=C[\"warning\"]))\n            try:\n                leftovers = self._scan_leftovers_for_item(item)\n            except InterruptedError:\n                self._set_uninst_progress(0, \"Safe uninstall leftover scan cancelled.\", C[\"warning\"])\n                self._audit_event(\"safe_uninstall_cancelled\", {\"completed\": idx - 1, \"total\": total})\n                break\n            batch_leftovers[name] = leftovers\n            # Leftover tree mein live update karo\n            if leftovers:\n                self.after(0, lambda n=name, lft=leftovers: self._append_batch_leftovers_to_tree(n, lft))\n            self.after(0, lambda i=idx, t=total, n=name, lc=len(leftovers): self.uninst_status.config(\n                text=f\"[{i}/{t}] Done: {n} | Leftovers: {lc}\",\n                fg=C[\"warning\"] if lc else C[\"success\"]))\n            self._set_uninst_progress(20 + (idx / max(total, 1)) * 75, f\"[{idx}/{total}] Safe uninstall scan complete: {name}\", C[\"warning\"] if leftovers else C[\"success\"])\n        self.after(500, self._scan_installed)\n        self.after(0, lambda: self._show_batch_leftover_preview(batch_leftovers))\n\n    def _append_batch_leftovers_to_tree(self, app_name, leftovers):\n        \"\"\"Batch uninstall ke baad leftovers turant right panel mein dikhao.\"\"\"\n        try:\n            # Section header\n            self.leftover_tree.insert(\"\", \"end\", values=(\"APP\", \"Info\", \"\", f\"--- {app_name} ---\"),\n                                      tags=(\"reg\",))\n            for item in leftovers:\n                ftype, path, risk, confidence, _meta = self._leftover_parts(item)\n                tag = \"risky\" if risk.lower() == \"risky\" else \"safe\"\n                self.leftover_tree.insert(\"\", \"end\", values=(ftype, risk, confidence, path), tags=(tag,))\n            # Auto-scroll\n            children = self.leftover_tree.get_children()\n            if children:\n                self.leftover_tree.see(children[-1])\n        except Exception:\n            pass\n\n    def _show_batch_leftover_preview(self, batch_leftovers):\n        apps_with_leftovers = {k: v for k, v in (batch_leftovers or {}).items() if v}\n        if not apps_with_leftovers:\n            self.uninst_status.config(text=\"Batch uninstall complete. No leftovers detected.\", fg=C[\"success\"])\n            messagebox.showinfo(\"Batch Uninstall Complete\",\n                                \"Selected programs uninstall ho gaye.\\n\\nNo obvious leftovers detected.\")\n            return\n\n        lines = []\n        for app_name, items in apps_with_leftovers.items():\n            risky = sum(1 for x in items if self._leftover_parts(x)[2].lower() == \"risky\")\n            lines.append(f\"* {app_name}  -&gt;  {len(items)} leftover(s), {risky} risky\")\n            for item in items[:8]:\n                ftype, path, risk, confidence, _meta = self._leftover_parts(item)\n                lines.append(f\"    [{ftype} | {risk} | {confidence}%] {path}\")\n            if len(items) &gt; 8:\n                lines.append(f\"    ... +{len(items)-8} more\")\n        preview = \"\\n\".join(lines)\n        if len(preview) &gt; 4500:\n            preview = preview[:4500] + \"\\n\\n...list truncated.\"\n\n        messagebox.showinfo(\n            \"Revo-style Leftovers Found\",\n            \"Uninstall ke baad ye leftovers detect hue:\\n\\n\"\n            f\"{preview}\\n\\n\"\n            \"Tip: Program select karke 'Scan Leftovers' aur phir 'Clean Leftovers' use karein.\"\n        )\n        self.uninst_status.config(\n            text=f\"Batch uninstall complete. Leftovers found in {len(apps_with_leftovers)} app(s).\",\n            fg=C[\"warning\"]\n        )\n\n    def _run_uninst_cmd(self, item, batch_leftovers=None):\n        name = item[\"name\"]\n        cmd  = self._normalize_uninstall_command(item, quiet=True)\n        if not cmd: return\n        self.after(0, lambda: self.uninst_status.config(\n            text=f\"Uninstalling: {name}...\", fg=C[\"accent4\"]))\n        self._log(f\"Uninstalling: {name}\", \"INFO\")\n        self._audit_event(\"safe_uninstall_command\", {\"name\": name, \"cmd\": cmd[:300]})\n        out, rc = self._run_cmd(cmd, timeout=300)\n        if rc == 0:\n            self._log(f\"Uninstalled OK: {name}\", \"OK\")\n            if not self._uninst_verify_removed(item):\n                self._log(f\"Verify WARN: {name} still present in registry list\", \"WARN\")\n            leftovers = self._scan_leftovers_for_item(item)\n            if batch_leftovers is not None:\n                batch_leftovers[name] = leftovers\n            self.after(0, lambda: self.uninst_status.config(\n                text=(f\"Uninstalled: {name} | Leftovers: {len(leftovers)}\"),\n                fg=(C[\"warning\"] if leftovers else C[\"success\"])))\n            if leftovers and batch_leftovers is None:\n                self.leftover_items = leftovers\n                self.after(0, self._populate_leftover_tree)\n                self.after(0, lambda: messagebox.showinfo(\n                    \"Leftovers Detected\",\n                    f\"{name} uninstall complete.\\n\\n\"\n                    f\"{len(leftovers)} leftover(s) detect hue.\\n\"\n                    \"Preview right panel me show ho raha hai.\"\n                ))\n            if batch_leftovers is None:\n                self.after(2000, self._scan_installed)\n        else:\n            self._log(f\"Uninstall issue: {name} (rc={rc})\", \"WARN\")\n            def ask_force():\n                if messagebox.askyesno(\"Uninstall Issue\",\n                    f\"Standard uninstall may have failed for:\\n{name}\\n\\n\"\n                    \"Run Force Remove to clean all leftovers?\"):\n                    self._launch_job(\"force_remove_item\", self._force_remove_item, item)\n            self.after(0, ask_force)\n\n    # \u2500\u2500 Force Remove (Revo-style deep clean) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _uninst_force(self):\n        items = self._get_sel_uninst()\n        if not items:\n            messagebox.showinfo(\"No Selection\",\"Select programs to force remove.\"); return\n        no_cmd = [it for it in items if not it.get(\"has_uninstall\")]\n        if no_cmd:\n            self.uninst_status.config(\n                text=\"Kuch programs mein uninstall command nahi \u2014 Force mode install path/registry se hataega.\",\n                fg=C[\"warning\"])\n            if not messagebox.askyesno(\n                \"No Uninstall Command\",\n                \"Ye programs mein official uninstall string nahi hai \u2014 Force mode registry/folders se hataega:\\n\\n\"\n                + \"\\n\".join(x[\"name\"] for x in no_cmd[:12])\n                + (\"\\n...\" if len(no_cmd) &gt; 12 else \"\")\n                + \"\\n\\nContinue with Force Uninstall?\"\n            ):\n                return\n        protected = []\n        safe_items = []\n        for it in items:\n            ok, reason = self._uninst_is_protected(it)\n            if ok:\n                protected.append(f\"{it['name']} ({reason})\")\n            else:\n                safe_items.append(it)\n        if protected:\n            messagebox.showwarning(\"Protected Apps Skipped\",\n                                   \"Force remove me bhi drivers/system apps skip kiye ja rahe hain:\\n\\n\" +\n                                   \"\\n\".join(protected[:12]) + (\"\\n...\" if len(protected) &gt; 12 else \"\"))\n        if not safe_items:\n            return\n        names = \"\\n\".join(it[\"name\"] for it in safe_items)\n        if not messagebox.askyesno(\"Force Uninstall\",\n            f\"Use Force Uninstall only for broken uninstallers or partially deleted apps.\\n\\n\"\n            f\"It will:\\n\"\n            f\" 1. Try the official uninstaller first\\n\"\n            f\" 2. Stop matching app processes\\n\"\n            f\" 3. Scan install folders, AppData, shortcuts, startup, services and registry\\n\"\n            f\" 4. Remove only matched leftovers after restore-point confirmation\\n\\n\"\n            f\"Programs:\\n{names}\\n\\nThis is permanent. Continue?\"\n        ): return\n        if not self._create_restore_point(f\"Force Remove: {safe_items[0]['name']}\"):\n            return\n        self._audit_event(\"force_uninstall_requested\", {\"items\": [x.get(\"name\") for x in safe_items]})\n        self._set_uninst_progress(5, f\"Force uninstall queued for {len(safe_items)} program(s)\", C[\"warning\"])\n        self._launch_job(\"force_uninstall\", self._run_force_remove_batch, safe_items)\n\n    def _run_force_remove_batch(self, items):\n        total = len(items)\n        try:\n            for idx, item in enumerate(items, start=1):\n                self._check_uninst_control()\n                self._set_uninst_progress(10 + ((idx - 1) / max(total, 1)) * 85, f\"[{idx}/{total}] Force uninstall: {item.get('name','')}\", C[\"warning\"])\n                self._force_remove_item(item, show_message=False)\n        except InterruptedError:\n            self._set_uninst_progress(0, \"Force uninstall cancelled at a safe checkpoint.\", C[\"warning\"])\n            self._audit_event(\"force_uninstall_cancelled\", {\"total\": total})\n            return\n        self._set_uninst_progress(100, \"Force uninstall batch complete. Restart is recommended.\", C[\"success\"])\n        self.after(0, lambda: messagebox.showinfo(\"Force Uninstall Complete\", \"Force uninstall batch complete.\\n\\nRestart is recommended to finish locked-file cleanup.\"))\n        self.after(2000, self._scan_installed)\n\n    def _app_keywords(self, name):\n        import re\n        words = re.split(r\"[ _\\-]+\", name.lower())\n        return [w for w in words if len(w) &gt; 3 and w not in\n                {\"microsoft\",\"windows\",\"update\",\"version\",\"setup\",\"install\",\n                 \"corp\",\"inc\",\"ltd\",\"llc\",\"software\",\"system\",\"service\"}]\n\n    def _force_remove_item(self, item, show_message=True):\n        name   = item[\"name\"]\n        words  = self._app_keywords(name)\n        removed = []\n        self.after(0, lambda: self.uninst_status.config(\n            text=f\"Force removing: {name}...\", fg=C[\"warning\"]))\n        self._log(f\"=== Force Remove START: {name} ===\", \"WARN\")\n\n        # 1. Run uninstaller silently\n        cmd = self._normalize_uninstall_command(item, quiet=True)\n        if cmd:\n            self._log(f\"[1] Uninstall cmd: {cmd[:100]}\", \"INFO\")\n            self._audit_event(\"force_uninstall_command\", {\"name\": name, \"cmd\": cmd[:300]})\n            self._run_cmd(cmd, timeout=180)\n            removed.append(\"Ran uninstaller\")\n        time.sleep(1)\n\n        # 2. Kill running processes\n        for proc in psutil.process_iter([\"pid\",\"name\",\"exe\"]):\n            try:\n                pname = (proc.info.get(\"name\") or \"\").lower()\n                pexe  = (proc.info.get(\"exe\")  or \"\").lower()\n                if any(w in pname or w in pexe for w in words):\n                    proc.kill()\n                    removed.append(f\"Killed process: {pname}\")\n                    self._log(f\"[2] Killed: {pname}\", \"OK\")\n            except: pass\n        time.sleep(1)\n\n        # 3. Delete install folder\n        inst_loc = item.get(\"install_loc\",\"\").strip()\n        candidate_dirs = []\n        if inst_loc and os.path.isdir(inst_loc):\n            candidate_dirs.append(inst_loc)\n        for base in [os.environ.get(\"ProgramFiles\",\"\"),\n                     os.environ.get(\"ProgramFiles(x86)\",\"\"),\n                     os.environ.get(\"LOCALAPPDATA\",\"\"),\n                     os.environ.get(\"APPDATA\",\"\")]:\n            if not base: continue\n            try:\n                for entry in Path(base).iterdir():\n                    if entry.is_dir() and any(w in entry.name.lower() for w in words):\n                        if str(entry) not in candidate_dirs:\n                            candidate_dirs.append(str(entry))\n            except: pass\n        for d in candidate_dirs:\n            try:\n                self._delete_leftover_path(d, \"FOLDER\")\n                removed.append(f\"Deleted folder: {d}\")\n                self._log(f\"[3] Deleted folder: {d}\", \"OK\")\n            except Exception as e:\n                self._log(f\"[3] Folder skipped: {d} ({e})\", \"WARN\")\n\n        # 4. Registry cleanup\n        reg_roots = [\n            (winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\"),\n            (winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\WOW6432Node\"),\n            (winreg.HKEY_CURRENT_USER,  r\"SOFTWARE\"),\n            (winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Services\"),\n            (winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\"),\n            (winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\"),\n            (winreg.HKEY_CURRENT_USER,  r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\"),\n        ]\n        for hive, root_path in reg_roots:\n            try:\n                root = winreg.OpenKey(hive, root_path, 0, winreg.KEY_READ)\n                to_del = []\n                i = 0\n                while True:\n                    try: sub = winreg.EnumKey(root, i); i += 1\n                    except OSError: break\n                    if any(w in sub.lower() for w in words):\n                        to_del.append(sub)\n                winreg.CloseKey(root)\n                for sub in to_del:\n                    full = root_path + \"\\\\\" + sub\n                    if root_path.lower().endswith(r\"currentcontrolset\\services\"):\n                        ok, err = self._native_delete_service(sub)\n                        if not ok:\n                            self._log(f\"[4] DeleteService fallback for {sub}: {err}\", \"WARN\")\n                            self._reg_delete_tree(hive, full)\n                    else:\n                        self._reg_delete_tree(hive, full)\n                    removed.append(f\"Reg: {full}\")\n                    self._log(f\"[4] Deleted reg: {full}\", \"OK\")\n            except: pass\n        # Also delete the specific stored key\n        try:\n            hive_map = {\"HKLM\": winreg.HKEY_LOCAL_MACHINE,\n                        \"HKCU\": winreg.HKEY_CURRENT_USER}\n            h = hive_map.get(item.get(\"reg_hive\",\"HKLM\"), winreg.HKEY_LOCAL_MACHINE)\n            self._reg_delete_tree(h, item.get(\"reg_key\",\"\"))\n        except: pass\n\n        # 5. AppData leftovers\n        for base in [os.environ.get(\"APPDATA\",\"\"), os.environ.get(\"LOCALAPPDATA\",\"\")]:\n            if not base: continue\n            try:\n                for entry in Path(base).iterdir():\n                    try:\n                        if any(w in entry.name.lower() for w in words):\n                            if entry.is_dir():\n                                self._delete_leftover_path(str(entry), \"FOLDER\")\n                            else:\n                                self._delete_leftover_path(str(entry), \"FILE\")\n                            removed.append(f\"AppData: {entry.name}\")\n                            self._log(f\"[5] AppData removed: {entry.name}\", \"OK\")\n                    except: pass\n            except: pass\n\n        # 6. Start Menu + Desktop shortcuts\n        for sm_base in [os.environ.get(\"APPDATA\",\"\"), os.environ.get(\"ProgramData\",\"\")]:\n            sm = Path(sm_base) / \"Microsoft\" / \"Windows\" / \"Start Menu\" / \"Programs\"\n            if sm.exists():\n                for entry in sm.rglob(\"*\"):\n                    try:\n                        if any(w in str(entry).lower() for w in words):\n                            if entry.is_file():\n                                self._delete_leftover_path(str(entry), \"SHORTCUT\")\n                            elif entry.is_dir():\n                                self._delete_leftover_path(str(entry), \"FOLDER\")\n                            removed.append(f\"StartMenu: {entry.name}\")\n                            self._log(f\"[6] StartMenu removed: {entry.name}\", \"OK\")\n                    except: pass\n        desktop = Path(os.path.expanduser(\"~\")) / \"Desktop\"\n        if desktop.exists():\n            for lnk in desktop.glob(\"*.lnk\"):\n                try:\n                    if any(w in lnk.stem.lower() for w in words):\n                        self._delete_leftover_path(str(lnk), \"SHORTCUT\")\n                        removed.append(f\"Desktop shortcut: {lnk.name}\")\n                        self._log(f\"[6] Desktop shortcut: {lnk.name}\", \"OK\")\n                except: pass\n\n        # 7. Temp folder\n        temp = os.environ.get(\"TEMP\",\"\")\n        if temp:\n            try:\n                for entry in Path(temp).iterdir():\n                    try:\n                        if any(w in str(entry).lower() for w in words):\n                            if entry.is_dir():\n                                self._delete_leftover_path(str(entry), \"FOLDER\")\n                            else:\n                                self._delete_leftover_path(str(entry), \"FILE\")\n                            removed.append(f\"Temp: {entry.name}\")\n                    except: pass\n            except: pass\n\n        # Done\n        summary = f\"Force remove complete: {name} \u2014 {len(removed)} items removed\"\n        self._log(f\"=== Force Remove DONE: {name} ({len(removed)} items) ===\", \"OK\")\n        self._audit_event(\"force_uninstall_finished\", {\"name\": name, \"removed_count\": len(removed)})\n        self.after(0, lambda: self.uninst_status.config(text=summary, fg=C[\"success\"]))\n        if show_message:\n            self.after(0, lambda: messagebox.showinfo(\n                \"Force Remove Complete\",\n                f\"Removed {len(removed)} items for:\\n{name}\\n\\n\"\n                \"Restart recommended to complete cleanup.\"))\n            self.after(2000, self._scan_installed)\n\n    def _reg_delete_tree(self, hive, path):\n        if not path: return\n        try:\n            key = winreg.OpenKey(hive, path, 0, winreg.KEY_READ)\n            subkeys = []\n            i = 0\n            while True:\n                try: subkeys.append(winreg.EnumKey(key, i)); i += 1\n                except OSError: break\n            winreg.CloseKey(key)\n            for sub in subkeys:\n                self._reg_delete_tree(hive, path + \"\\\\\" + sub)\n            winreg.DeleteKey(hive, path)\n        except: pass\n\n    # \u2500\u2500 Scan Leftovers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _scan_leftovers(self):\n        items = self._get_sel_uninst()\n        if not items:\n            messagebox.showinfo(\"No Selection\",\"Select a program to scan leftovers.\"); return\n        item = items[0]\n        self.leftover_tree.delete(*self.leftover_tree.get_children())\n        self.leftover_items = []\n        self._uninst_cancel_flag = False\n        self._uninst_pause_flag = False\n        if hasattr(self, \"uninst_pause_btn\"):\n            self.uninst_pause_btn.config(text=\"Pause Scan\")\n        self._set_uninst_progress(5, f\"Deep leftover scan for: {item['name']}...\", C[\"accent4\"])\n        self._audit_event(\"leftover_scan_started\", {\"name\": item.get(\"name\"), \"publisher\": item.get(\"publisher\")})\n        self._launch_job(\"scan_leftovers\", self._do_scan_leftovers, item)\n\n    def _do_scan_leftovers(self, item):\n        name = item[\"name\"]\n        try:\n            found = self._scan_leftovers_for_item(item, progress=True)\n        except InterruptedError:\n            self._audit_event(\"leftover_scan_cancelled\", {\"name\": name})\n            self._set_uninst_progress(0, f\"Leftover scan cancelled for: {name}\", C[\"warning\"])\n            return\n        self.leftover_items = found\n        self.after(0, self._populate_leftover_tree)\n        count = len(found)\n        risky = sum(1 for x in found if self._leftover_parts(x)[2].lower() == \"risky\")\n        safe = max(0, count - risky)\n        color = C[\"warning\"] if count else C[\"success\"]\n        self._set_uninst_progress(100, f\"{count} leftover(s) found for: {name}\", color)\n        if hasattr(self, \"uninst_summary_vars\"):\n            self.after(0, lambda: self.uninst_summary_vars[\"leftovers\"].set(str(count)))\n            self.after(0, lambda: self.uninst_summary_vars[\"risky\"].set(str(risky)))\n            self.after(0, lambda: self.uninst_summary_vars[\"safe\"].set(str(safe)))\n        self._audit_event(\"leftover_scan_finished\", {\"name\": name, \"count\": count, \"risky\": risky, \"safe\": safe})\n\n    def _scan_leftovers_for_item(self, item, progress=False):\n        name = item.get(\"name\", \"\")\n        words = self._app_keywords(name)\n        if not words:\n            fallback = re.sub(r\"[^a-z0-9]+\", \" \", name.lower()).strip().split()\n            words = [w for w in fallback if len(w) &gt;= 3][:3]\n        if not words:\n            return []\n\n        found = []\n        seen = set()\n\n        def add_item(ftype, path, confidence=70, risk=None, source=\"\", action=\"delete\", meta=None):\n            self._add_leftover_item(found, seen, ftype, path, confidence, risk, source, action, meta)\n\n        def word_hit(text):\n            low = str(text or \"\").lower()\n            return any(w in low for w in words)\n\n        def progress_step(pct, text):\n            if progress:\n                self._set_uninst_progress(pct, text, C[\"accent4\"])\n\n        install_loc = (item.get(\"install_loc\") or \"\").strip().strip('\"')\n        if install_loc and os.path.exists(install_loc):\n            add_item(\"FOLDER\", install_loc, 95, \"Risky\", \"InstallLocation\")\n\n        progress_step(12, \"Scanning registry residue...\")\n        reg_roots = [\n            (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\", 2),\n            (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\WOW6432Node\", 2),\n            (\"HKCU\", winreg.HKEY_CURRENT_USER,  r\"SOFTWARE\", 2),\n            (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Services\", 1),\n            (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\", 1),\n            (\"HKCU\", winreg.HKEY_CURRENT_USER,  r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\", 1),\n        ]\n        scanned = [0]\n        deadline = time.time() + 25\n\n        def scan_reg_level(hive_name, hive, root_path, depth):\n            self._check_uninst_control()\n            if scanned[0] &gt; 5000 or time.time() &gt; deadline:\n                return\n            try:\n                root = winreg.OpenKey(hive, root_path, 0, winreg.KEY_READ)\n            except Exception:\n                return\n            try:\n                try:\n                    value_text = _registry_value_text(root)\n                    if word_hit(root_path) or word_hit(value_text):\n                        add_item(\"REG\", f\"{hive_name}\\\\{root_path}\", 78, \"Risky\", \"Registry values\")\n                except Exception:\n                    pass\n                i = 0\n                while True:\n                    self._check_uninst_control()\n                    try:\n                        sub = winreg.EnumKey(root, i)\n                        i += 1\n                    except OSError:\n                        break\n                    scanned[0] += 1\n                    child_path = root_path + \"\\\\\" + sub\n                    if word_hit(sub):\n                        add_item(\"REG\", f\"{hive_name}\\\\{child_path}\", 88 if \"uninstall\" in root_path.lower() else 74, \"Risky\", \"Registry key\")\n                    if depth &gt; 0 and scanned[0] &lt; 5000 and time.time() &lt;= deadline:\n                        scan_reg_level(hive_name, hive, child_path, depth - 1)\n            finally:\n                try:\n                    winreg.CloseKey(root)\n                except Exception:\n                    pass\n\n        for hive_name, hive, root_path, depth in reg_roots:\n            scan_reg_level(hive_name, hive, root_path, depth)\n\n        progress_step(38, \"Scanning install folders, AppData and shortcuts...\")\n        search_bases = [\n            os.environ.get(\"ProgramFiles\",\"\"),\n            os.environ.get(\"ProgramFiles(x86)\",\"\"),\n            os.environ.get(\"ProgramData\",\"\"),\n            os.environ.get(\"APPDATA\",\"\"),\n            os.environ.get(\"LOCALAPPDATA\",\"\"),\n            os.environ.get(\"TEMP\",\"\"),\n            str(Path(os.path.expanduser(\"~\")) / \"Desktop\"),\n        ]\n        for base in search_bases:\n            self._check_uninst_control()\n            if not base:\n                continue\n            try:\n                for entry in Path(base).iterdir():\n                    self._check_uninst_control()\n                    try:\n                        if word_hit(entry.name):\n                            add_item(\"FOLDER\" if entry.is_dir() else \"FILE\", str(entry), 72, None, \"Filesystem\")\n                    except Exception:\n                        pass\n            except Exception:\n                pass\n\n        for sm_base in [os.environ.get(\"APPDATA\",\"\"), os.environ.get(\"ProgramData\",\"\")]:\n            self._check_uninst_control()\n            sm = Path(sm_base) / \"Microsoft\" / \"Windows\" / \"Start Menu\" / \"Programs\"\n            if sm.exists():\n                try:\n                    for idx, entry in enumerate(sm.rglob(\"*.lnk\")):\n                        if idx % 50 == 0:\n                            self._check_uninst_control()\n                        if word_hit(str(entry)):\n                            add_item(\"SHORTCUT\", str(entry), 68, \"Safe\", \"Start Menu shortcut\")\n                except Exception:\n                    pass\n\n        progress_step(58, \"Scanning startup entries...\")\n        run_roots = [\n            (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\"),\n            (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Run\"),\n            (\"HKCU\", winreg.HKEY_CURRENT_USER,  r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\"),\n            (\"HKLM\", winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce\"),\n            (\"HKCU\", winreg.HKEY_CURRENT_USER,  r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce\"),\n        ]\n        for hive_name, hive, run_path in run_roots:\n            self._check_uninst_control()\n            try:\n                key = winreg.OpenKey(hive, run_path, 0, winreg.KEY_READ)\n                i = 0\n                while True:\n                    try:\n                        value_name, value, _vtype = winreg.EnumValue(key, i)\n                        i += 1\n                    except OSError:\n                        break\n                    if word_hit(value_name) or word_hit(value):\n                        display = f\"{hive_name}\\\\{run_path}\\\\{value_name}\"\n                        add_item(\"STARTUP\", display, 76, \"Risky\", \"Registry startup\",\n                                 meta={\"hive\": hive_name, \"path\": run_path, \"value\": value_name})\n                winreg.CloseKey(key)\n            except Exception:\n                pass\n\n        progress_step(70, \"Scanning Windows services...\")\n        try:\n            for svc in psutil.win_service_iter():\n                self._check_uninst_control()\n                try:\n                    info = svc.as_dict()\n                    svc_name = info.get(\"name\", \"\") or \"\"\n                    disp = info.get(\"display_name\", \"\") or \"\"\n                    bin_path = info.get(\"binpath\", \"\") or \"\"\n                    if word_hit(svc_name) or word_hit(disp) or word_hit(bin_path):\n                        add_item(\"SERVICE\", svc_name, 72, \"Risky\", \"Windows service\",\n                                 meta={\"service\": svc_name, \"display\": disp, \"binpath\": bin_path})\n                except Exception:\n                    pass\n        except Exception:\n            pass\n\n        progress_step(82, \"Scanning scheduled tasks...\")\n        try:\n            ps_terms = \"@(\" + \",\".join(_ps_single_quote(w) for w in words[:6]) + \")\"\n            script = f\"\"\"\n$terms = {ps_terms}\n$items = @()\ntry {{\n    $items = Get-ScheduledTask -ErrorAction SilentlyContinue | Where-Object {{\n        $txt = ($_.TaskName + ' ' + $_.TaskPath + ' ' + $_.URI).ToLower()\n        foreach($t in $terms) {{ if($txt.Contains($t.ToLower())) {{ return $true }} }}\n        return $false\n    }} | Select-Object -First 80 TaskName,TaskPath,State\n}} catch {{}}\n$items | ConvertTo-Json -Depth 3\n\"\"\"\n            out, _ = self._run_powershell(script, timeout=35)\n            for task in self._json_items_from_output(out):\n                self._check_uninst_control()\n                task_name = str(task.get(\"TaskName\", \"\") or \"\")\n                task_path = str(task.get(\"TaskPath\", \"\\\\\") or \"\\\\\")\n                full = (task_path.rstrip(\"\\\\\") + \"\\\\\" + task_name).replace(\"\\\\\\\\\", \"\\\\\")\n                add_item(\"TASK\", full, 66, \"Risky\", \"Scheduled Task\",\n                         meta={\"task\": full, \"state\": task.get(\"State\", \"\")})\n        except Exception:\n            pass\n\n        found.sort(key=lambda rec: (self._leftover_parts(rec)[0], -self._leftover_parts(rec)[3], self._leftover_parts(rec)[1].lower()))\n        return found[:2000]\n\n    def _populate_leftover_tree(self):\n        self.leftover_tree.delete(*self.leftover_tree.get_children())\n        risky = 0\n        safe = 0\n        for item in self.leftover_items:\n            ftype, path, risk, confidence, _meta = self._leftover_parts(item)\n            if risk.lower() == \"risky\":\n                risky += 1\n                tag = \"risky\"\n            else:\n                safe += 1\n                tag = \"safe\"\n            self.leftover_tree.insert(\"\", \"end\", tags=(tag,),\n                                      values=(ftype, risk, confidence, path))\n        if hasattr(self, \"uninst_summary_vars\"):\n            self.uninst_summary_vars[\"leftovers\"].set(str(len(self.leftover_items)))\n            self.uninst_summary_vars[\"risky\"].set(str(risky))\n            self.uninst_summary_vars[\"safe\"].set(str(safe))\n\n    # \u2500\u2500 Clean Leftovers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _clean_leftovers(self):\n        if not self.leftover_items:\n            messagebox.showinfo(\"Nothing\",\"Scan leftovers first.\"); return\n        n = len(self.leftover_items)\n        risky = sum(1 for x in self.leftover_items if self._leftover_parts(x)[2].lower() == \"risky\")\n        if not messagebox.askyesno(\"Clean Reviewed Leftovers\",\n            f\"Permanently clean {n} reviewed leftover item(s)?\\n\\n\"\n            f\"Risky items: {risky}\\n\"\n            \"This can remove files, folders, registry keys, services, startup entries and scheduled tasks.\\n\\n\"\n            \"Create/allow a restore point before continuing.\"): return\n        if not self._create_restore_point(\"Before Leftover Cleanup\"):\n            return\n        self._audit_event(\"leftover_cleanup_requested\", {\"count\": n, \"risky\": risky})\n        self._set_uninst_progress(5, f\"Cleaning {n} reviewed leftover item(s)...\", C[\"warning\"])\n        self._launch_job(\"clean_leftovers\", self._do_clean_leftovers)\n\n    def _do_clean_leftovers(self):\n        cleaned = 0; errors = 0\n        total = len(self.leftover_items)\n        for idx, item in enumerate(list(self.leftover_items), start=1):\n            ftype, path, _risk, _confidence, meta = self._leftover_parts(item)\n            try:\n                self._check_uninst_control()\n                if ftype == \"REG\":\n                    parts = path.split(\"\\\\\", 2)\n                    if len(parts) &lt; 3: continue\n                    hmap = {\"HKLM\": winreg.HKEY_LOCAL_MACHINE,\n                            \"HKCU\": winreg.HKEY_CURRENT_USER}\n                    h = hmap.get(parts[0])\n                    if not h: continue\n                    self._reg_delete_tree(h, parts[1] + \"\\\\\" + parts[2])\n                    cleaned += 1\n                elif ftype in (\"FOLDER\", \"FILE\", \"SHORTCUT\"):\n                    if os.path.exists(path):\n                        self._delete_leftover_path(path, ftype); cleaned += 1\n                elif ftype == \"SERVICE\":\n                    svc = meta.get(\"service\") or path\n                    ok, err = self._native_delete_service(svc)\n                    if not ok:\n                        raise RuntimeError(err or \"DeleteService failed\")\n                    cleaned += 1\n                elif ftype == \"STARTUP\":\n                    hive_name = meta.get(\"hive\", \"\")\n                    run_path = meta.get(\"path\", \"\")\n                    value_name = meta.get(\"value\", \"\")\n                    hmap = {\"HKLM\": winreg.HKEY_LOCAL_MACHINE,\n                            \"HKCU\": winreg.HKEY_CURRENT_USER}\n                    h = hmap.get(hive_name)\n                    if h and run_path and value_name:\n                        key = winreg.OpenKey(h, run_path, 0, winreg.KEY_SET_VALUE)\n                        try:\n                            winreg.DeleteValue(key, value_name)\n                        finally:\n                            winreg.CloseKey(key)\n                        cleaned += 1\n                elif ftype == \"TASK\":\n                    task_name = meta.get(\"task\") or path\n                    out, rc = self._run_cmd(f'schtasks /Delete /TN \"{task_name}\" /F', timeout=45)\n                    if rc != 0:\n                        raise RuntimeError(out[-300:] if out else \"schtasks delete failed\")\n                    cleaned += 1\n                self._set_uninst_progress(5 + (idx / max(total, 1)) * 90, f\"Cleaning leftovers [{idx}/{total}]...\", C[\"warning\"])\n            except InterruptedError:\n                self._set_uninst_progress(0, \"Leftover cleanup cancelled.\", C[\"warning\"])\n                self._audit_event(\"leftover_cleanup_cancelled\", {\"cleaned\": cleaned, \"errors\": errors})\n                return\n            except Exception as e:\n                errors += 1\n                self._audit_event(\"leftover_cleanup_error\", {\"type\": ftype, \"path\": path, \"error\": str(e)})\n        summary = f\"Cleaned {cleaned} leftover(s). Errors: {errors}\"\n        self._set_uninst_progress(100, summary, C[\"success\"] if errors == 0 else C[\"warning\"])\n        self._log(summary, \"OK\")\n        self._audit_event(\"leftover_cleanup_finished\", {\"cleaned\": cleaned, \"errors\": errors})\n        self.leftover_items = []\n        self.after(0, self._populate_leftover_tree)\n\n    def _reg_read_str(self, key, value_name):\n        try:\n            val, _ = winreg.QueryValueEx(key, value_name)\n            return str(val)\n        except:\n            return \"\"\n\n    def _uninstall_selected_with_confirm(self):\n        \"\"\"Legacy compatibility \u2014 calls standard uninstall\"\"\"\n        self._uninst_standard()\n\n\n        # ---------- HARDWARE, PRINTER, DRIVER, BACKUP, REPORT, LOG (unchanged, but confirm added where needed) ----------\n    def _build_hardware(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udda5\ufe0f Hardware Health\", \"Real stats\", hw=True)\n        self._action_card_grid(frame, [\n            (\"\ud83d\udd0d\", \"Scan Hardware\", \"CPU, GPU, RAM, Disk info scan karo\", C[\"btn_hw\"], self._scan_hw),\n        ], cols=1)\n        content = tk.Frame(frame, bg=C[\"card\"])\n        content.pack(fill=\"both\", expand=True, padx=16, pady=10)\n        self.hw_log = self._scrolled_text(content, height=22)\n        return frame\n\n    def _scan_hw(self):\n        self._launch_job(\"scan_hw\", self._do_scan_hw)\n\n    def _do_scan_hw(self):\n        self._append_log(self.hw_log, \"\u2550\"*50, C[\"border\"])\n        out, _ = self._run_cmd(\"wmic cpu get Name,LoadPercentage /format:list\")\n        self._append_log(self.hw_log, \"-- CPU --\", C[\"hw_accent\"])\n        for l in out.splitlines():\n            if \"=\" in l:\n                self._append_log(self.hw_log, l, C[\"text\"])\n        out, _ = self._run_cmd(\"wmic path win32_VideoController get Name,AdapterRAM,DriverVersion /format:list\")\n        self._append_log(self.hw_log, \"-- GPU --\", C[\"hw_accent\"])\n        for l in out.splitlines():\n            if \"=\" in l and l.split(\"=\")[1].strip():\n                if \"AdapterRAM\" in l:\n                    try:\n                        l = f\"VRAM={self._fmt_size(int(l.split('=')[1]))}\"\n                    except:\n                        pass\n                self._append_log(self.hw_log, l, C[\"text\"])\n        self._append_log(self.hw_log, \"\u2705 Hardware scan complete\", C[\"success\"])\n\n    def _build_printer(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udda8\ufe0f Advanced Printer Fixer\",\n                             \"Spooler reset, stuck jobs, driver repair, network printer \u2014 sab kuch\")\n\n        self._printer_action_buttons = []\n        printer_actions = [\n            (\"\ud83d\udd0d\", \"Detect Printers\",       \"System pe printers dhundho\",           C[\"btn_info\"],   self._printer_detect),\n            (\"\ud83d\udd01\", \"Reset Spooler\",         \"Print Spooler service restart karo\",   C[\"btn_warn\"],   self._printer_reset_spooler),\n            (\"\ud83d\uddd1\",  \"Clear Stuck Jobs\",     \"Atkaye hue print jobs saaf karo\",       C[\"btn_danger\"], self._printer_clear_jobs),\n            (\"\ud83d\udd27\", \"Full Auto-Repair\",      \"Spooler + jobs + driver full fix\",     C[\"btn_hw\"],     self._printer_full_repair),\n            (\"\ud83e\uddf9\", \"Driver Purge/Reinstall\",\"Printer driver saaf karo + reinstall\", C[\"btn_danger\"], self._printer_driver_purge_flow),\n            (\"\ud83d\udda5\",  \"Set as Default\",       \"Selected printer default set karo\",    C[\"btn_chip\"],   self._printer_set_default),\n            (\"\u274c\", \"Remove Printer\",        \"Selected printer hata do\",             C[\"btn_danger\"], self._printer_remove),\n            (\"\ud83c\udf10\", \"Network Printer Setup\", \"Network printer add karo\",             C[\"btn_info\"],   self._printer_network_setup),\n        ]\n        printer_toolbar = tk.Frame(frame, bg=C[\"bg\"])\n        printer_toolbar.pack(fill=\"x\", padx=12, pady=(4, 2))\n        for col in range(4):\n            printer_toolbar.columnconfigure(col, weight=1)\n        for idx, (_icon, title, _subtitle, color, cmd_func) in enumerate(printer_actions):\n            btn = tk.Button(printer_toolbar, text=title, font=FONTS[\"small\"],\n                            bg=color, fg=C[\"text\"], bd=0, padx=8, pady=4,\n                            cursor=\"hand2\", command=cmd_func)\n            btn.grid(row=idx // 4, column=idx % 4, sticky=\"ew\", padx=3, pady=2)\n            self._printer_action_buttons.append(btn)\n\n        # \u2500\u2500 Tab Notebook \u2014 Tab1: Printer Fixer, Tab2: Sharing Center \u2500\u2500\n        nb = ttk.Notebook(frame)\n        nb.pack(fill=\"both\", expand=True, padx=8, pady=(4,8))\n\n        # Tab 1 \u2014 Printer Fixer\n        tab1 = tk.Frame(nb, bg=C[\"bg\"])\n        nb.add(tab1, text=\"  \ud83d\udda8  Printer Fixer  \")\n\n        paned = tk.Frame(tab1, bg=C[\"bg\"])\n        paned.pack(fill=\"both\", expand=True, padx=8, pady=(4,8))\n        paned.columnconfigure(0, weight=2)\n        paned.columnconfigure(1, weight=3)\n        paned.rowconfigure(0, weight=1)\n\n        # Left \u2014 printer list + status cards\n        left = tk.Frame(paned, bg=C[\"card\"])\n        left.grid(row=0, column=0, sticky=\"nsew\", padx=(0,6))\n        left.rowconfigure(1, weight=1)\n\n        # Status cards\n        cards = tk.Frame(left, bg=C[\"card\"])\n        cards.pack(fill=\"x\", pady=(8,4), padx=8)\n        self.printer_stat_vars = {}\n        for i,(k,lbl,col) in enumerate([\n            (\"total\",   \"Total Printers\", C[\"accent\"]),\n            (\"online\",  \"Online\",         C[\"success\"]),\n            (\"offline\", \"Offline\",        C[\"error\"]),\n            (\"default\", \"Default\",        C[\"accent2\"]),\n        ]):\n            cards.columnconfigure(i, weight=1)\n            c = tk.Frame(cards, bg=C[\"bg\"], padx=8, pady=6)\n            c.grid(row=0, column=i, padx=3, sticky=\"ew\")\n            tk.Label(c, text=lbl, font=FONTS[\"small\"], fg=col, bg=C[\"bg\"]).pack(anchor=\"w\")\n            v = tk.StringVar(value=\"--\")\n            self.printer_stat_vars[k] = v\n            tk.Label(c, textvariable=v, font=(\"Segoe UI\",14,\"bold\"),\n                     fg=col, bg=C[\"bg\"]).pack(anchor=\"w\")\n\n        # Printer list\n        tk.Label(left, text=\"  Detected Printers\", font=FONTS[\"subhead\"],\n                 fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=8, pady=(4,2))\n        cols = (\"Name\",\"Status\",\"Default\",\"Jobs\")\n        self.printer_tree = ttk.Treeview(left, columns=cols, show=\"headings\",\n                                          height=12, style=\"Custom.Treeview\",\n                                          selectmode=\"browse\")\n        for col, w in zip(cols, [200,90,70,50]):\n            self.printer_tree.heading(col, text=col)\n            self.printer_tree.column(col, width=w, anchor=\"center\")\n        self.printer_tree.tag_configure(\"online\",  foreground=C[\"success\"])\n        self.printer_tree.tag_configure(\"offline\", foreground=C[\"error\"])\n        self.printer_tree.tag_configure(\"default\", foreground=C[\"warning\"])\n        psb = ttk.Scrollbar(left, orient=\"vertical\", command=self.printer_tree.yview)\n        self.printer_tree.configure(yscrollcommand=psb.set)\n        self.printer_tree.pack(side=\"left\", fill=\"both\", expand=True, padx=(8,0), pady=(0,8))\n        psb.pack(side=\"right\", fill=\"y\", pady=(0,8), padx=(0,4))\n        self.printer_tree.bind(\"&lt;&gt;\", self._on_printer_select)\n        self._printer_data = []\n\n        # Right \u2014 action log + diagnostics\n        right = tk.Frame(paned, bg=C[\"card\"])\n        right.grid(row=0, column=1, sticky=\"nsew\")\n        right.rowconfigure(1, weight=1)\n\n        # Quick action buttons\n        qa = tk.Frame(right, bg=C[\"card\"])\n        qa.pack(fill=\"x\", padx=8, pady=(8,4))\n        tk.Label(qa, text=\"Quick Fixes:\", font=FONTS[\"small\"],\n                 fg=C[\"text_dim\"], bg=C[\"card\"]).grid(row=0, column=0, sticky=\"w\", padx=(0,6), pady=(0,3))\n        quick_grid = tk.Frame(qa, bg=C[\"card\"])\n        quick_grid.grid(row=1, column=0, sticky=\"ew\")\n        qa.columnconfigure(0, weight=1)\n        for idx, (lbl, fn) in enumerate([\n            (\"Restart Spooler\",       self._printer_reset_spooler),\n            (\"SFC /scannow\",          self._printer_sfc),\n            (\"PrintNightmare Fix\",    self._printer_printnightmare),\n            (\"Run Troubleshooter\",    self._printer_troubleshooter),\n            (\"Open Print Queue\",      self._printer_open_queue),\n            (\"Driver Audit\",          self._printer_driver_signature_audit),\n            (\"Spooler Snapshot\",      self._printer_spooler_snapshot),\n        ]):\n            row, col = divmod(idx, 3)\n            quick_grid.columnconfigure(col, weight=1)\n            btn = tk.Button(quick_grid, text=lbl, font=FONTS[\"small\"],\n                            bg=C[\"btn_info\"], fg=\"white\", bd=0, padx=8, pady=3,\n                            cursor=\"hand2\", command=fn)\n            btn.grid(row=row, column=col, sticky=\"ew\", padx=3, pady=2)\n            self._printer_action_buttons.append(btn)\n\n        status_panel = tk.Frame(right, bg=C[\"card\"])\n        status_panel.pack(fill=\"x\", padx=8, pady=(0,4))\n        tk.Label(status_panel, text=\"Execution:\", font=FONTS[\"small\"],\n                 fg=C[\"text_dim\"], bg=C[\"card\"]).grid(row=0, column=0, sticky=\"w\", padx=(0,6))\n        self.printer_exec_status_lbl = tk.Label(status_panel, text=\"Ready\",\n                                                font=FONTS[\"small\"], fg=C[\"text_dim\"],\n                                                bg=C[\"card\"])\n        self.printer_exec_status_lbl.grid(row=0, column=1, sticky=\"w\")\n        self.printer_exec_time_lbl = tk.Label(status_panel, text=\"Elapsed: 00:00 | ETA: --\",\n                                              font=FONTS[\"small\"], fg=C[\"text_dim\"],\n                                              bg=C[\"card\"])\n        self.printer_exec_time_lbl.grid(row=1, column=0, columnspan=2, sticky=\"w\", pady=(2, 0))\n        status_panel.columnconfigure(1, weight=1)\n\n        tk.Label(right, text=\"  \ud83d\udcdd Repair Log\",\n                 font=FONTS[\"subhead\"], fg=C[\"accent2\"], bg=C[\"card\"]).pack(\n                 anchor=\"w\", padx=8, pady=(4,2))\n        self.printer_log = self._scrolled_text(right, height=12)\n        tk.Label(right, text=\"  \ud83d\udd0e Execution Trace\",\n                 font=FONTS[\"subhead\"], fg=C[\"accent2\"], bg=C[\"card\"]).pack(\n                 anchor=\"w\", padx=8, pady=(4,2))\n        self.printer_trace_log = self._scrolled_text(right, height=4)\n\n        # Spooler status indicator\n        bot = tk.Frame(right, bg=C[\"card\"])\n        bot.pack(fill=\"x\", padx=8, pady=(4,8))\n        tk.Label(bot, text=\"Spooler:\", font=FONTS[\"small\"],\n                 fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self.spooler_status_lbl = tk.Label(bot, text=\"Unknown\",\n                                            font=FONTS[\"small\"], fg=C[\"warning\"],\n                                            bg=C[\"card\"])\n        self.spooler_status_lbl.pack(side=\"left\", padx=6)\n        self._btn(bot, \"\u21bb Refresh Status\", C[\"btn_chip\"],\n                  self._refresh_spooler_status).pack(side=\"left\", padx=6)\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # \ud83d\udd17 TAB 2 \u2014 PRINTER SHARING CENTER\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        tab2 = tk.Frame(nb, bg=C[\"bg\"])\n        nb.add(tab2, text=\"  \ud83d\udd17  Sharing Center (Host &amp; Client)  \")\n\n        # Header inside tab2\n        share_hdr = tk.Frame(tab2, bg=C[\"panel\"])\n        share_hdr.pack(fill=\"x\")\n        tk.Label(share_hdr, text=\"  \ud83d\udd17 Printer Sharing Center\",\n                 font=FONTS[\"heading\"], fg=C[\"accent4\"], bg=C[\"panel\"]).pack(side=\"left\", pady=8, padx=8)\n        tk.Label(share_hdr,\n                 text=\"Har port, service, security alag-alag kholo \u2014 Host &amp; Client dono ke liye\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"left\", pady=8)\n        self._btn(share_hdr, \"\ud83d\udd0e Check Sharing Status\", C[\"btn_chip\"],\n                  self._check_sharing_status).pack(side=\"right\", padx=10, pady=6)\n\n        # Scrollable area inside tab2\n        sc_outer = tk.Frame(tab2, bg=C[\"bg\"])\n        sc_outer.pack(fill=\"both\", expand=True, padx=0, pady=0)\n        sc_canvas = tk.Canvas(sc_outer, bg=C[\"bg\"], highlightthickness=0)\n        sc_sb = ttk.Scrollbar(sc_outer, orient=\"vertical\", command=sc_canvas.yview)\n        sc_canvas.configure(yscrollcommand=sc_sb.set)\n        sc_sb.pack(side=\"right\", fill=\"y\")\n        sc_canvas.pack(side=\"left\", fill=\"both\", expand=True)\n        share_body = tk.Frame(sc_canvas, bg=C[\"bg\"])\n        sc_win = sc_canvas.create_window((0,0), window=share_body, anchor=\"nw\")\n        def _sc_resize(e):\n            sc_canvas.configure(scrollregion=sc_canvas.bbox(\"all\"))\n            sc_canvas.itemconfig(sc_win, width=sc_canvas.winfo_width())\n        share_body.bind(\"\", _sc_resize)\n        def _sc_canvas_configure(e):\n            sc_canvas.itemconfig(sc_win, width=e.width)\n            sc_canvas.configure(scrollregion=sc_canvas.bbox(\"all\"))\n        sc_canvas.bind(\"\", _sc_canvas_configure)\n        self._bind_scoped_mousewheel(share_body, sc_canvas)\n\n        share_body.columnconfigure(0, weight=1)\n        share_body.columnconfigure(1, weight=1)\n\n        def _section_card(parent, title, subtitle, bg_hdr, fg_title, col):\n            \"\"\"Card with header for HOST or CLIENT sections.\"\"\"\n            frm = tk.Frame(parent, bg=C[\"card\"], bd=0)\n            hdr = tk.Frame(frm, bg=bg_hdr)\n            hdr.pack(fill=\"x\")\n            tk.Label(hdr, text=title, font=FONTS[\"subhead\"], fg=fg_title, bg=bg_hdr).pack(anchor=\"w\", padx=10, pady=6)\n            tk.Label(hdr, text=subtitle, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=bg_hdr).pack(anchor=\"w\", padx=10, pady=(0,6))\n            return frm\n\n        def _grp_label(parent, text, bg=None):\n            bg = bg or C[\"card\"]\n            tk.Label(parent, text=text, font=FONTS[\"small\"],\n                     fg=C[\"accent4\"], bg=bg, anchor=\"w\").pack(fill=\"x\", padx=10, pady=(8,2))\n            tk.Frame(parent, bg=C[\"border\"], height=1).pack(fill=\"x\", padx=10)\n\n        def _ibtn(parent, text, color, cmd, desc=\"\"):\n            row = tk.Frame(parent, bg=C[\"card\"])\n            row.pack(fill=\"x\", padx=8, pady=2)\n            tk.Button(row, text=text, font=FONTS[\"body\"],\n                      bg=color, fg=C[\"bg\"] if color in (C[\"accent\"],C[\"success\"]) else C[\"text\"],\n                      bd=0, padx=10, pady=6, cursor=\"hand2\", anchor=\"w\",\n                      command=cmd).pack(side=\"left\", fill=\"x\", expand=True)\n            if desc:\n                tk.Label(row, text=desc, font=(\"Consolas\",8),\n                         fg=C[\"text_dim\"], bg=C[\"card\"], anchor=\"w\", wraplength=260).pack(side=\"left\", padx=(6,4))\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # \ud83d\udda5 HOST COMPUTER COLUMN\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        host_frame = _section_card(share_body,\n            \"\ud83d\udda5  HOST COMPUTER  \u2014  Jis PC pe printer laga hai\",\n            \"Yahan printer physically connected hai (USB/LPT)\",\n            \"#1A3A2A\", C[\"accent\"], 0)\n        host_frame.grid(row=0, column=0, sticky=\"nsew\", padx=(8,4), pady=6)\n\n        # \u2500\u2500 HOST: PORTS \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(host_frame, \"\ud83d\udd0c  PORTS \u2014 Firewall mein open karo (IN + OUT)\")\n        _ibtn(host_frame, \"\u25b6 Port 445 TCP+UDP  \u2014  SMB File &amp; Printer Sharing\",\n              C[\"btn_chip\"], lambda: self._open_single_port_host(445,\"TCP+UDP\",\"SMB-Printer-Sharing\"),\n              \"Printer sharing ka main port\")\n        _ibtn(host_frame, \"\u25b6 Port 139 TCP  \u2014  NetBIOS Session Service\",\n              C[\"btn_chip\"], lambda: self._open_single_port_host(139,\"TCP\",\"NetBIOS-Session\"),\n              \"Purane Windows me sharing ke liye\")\n        _ibtn(host_frame, \"\u25b6 Port 137 UDP  \u2014  NetBIOS Name Service\",\n              C[\"btn_chip\"], lambda: self._open_single_port_host(137,\"UDP\",\"NetBIOS-Name\"),\n              \"Network name resolution\")\n        _ibtn(host_frame, \"\u25b6 Port 138 UDP  \u2014  NetBIOS Datagram Service\",\n              C[\"btn_chip\"], lambda: self._open_single_port_host(138,\"UDP\",\"NetBIOS-Datagram\"),\n              \"NetBIOS broadcast messages\")\n        _ibtn(host_frame, \"\u25b6 Port 135 TCP  \u2014  RPC Endpoint Mapper\",\n              C[\"btn_chip\"], lambda: self._open_single_port_host(135,\"TCP\",\"RPC-Endpoint\"),\n              \"Windows Remote Procedure Call\")\n        _ibtn(host_frame, \"\u25b6 Port 9100 TCP  \u2014  RAW Print / JetDirect\",\n              C[\"btn_chip\"], lambda: self._open_single_port_host(9100,\"TCP\",\"RAW-Print-JetDirect\"),\n              \"Network printer direct print port\")\n        _ibtn(host_frame, \"\u25b6 Port 631 TCP  \u2014  IPP Internet Printing Protocol\",\n              C[\"btn_chip\"], lambda: self._open_single_port_host(631,\"TCP\",\"IPP-Printing\"),\n              \"Internet Printing Protocol (IPP)\")\n        _ibtn(host_frame, \"\u25b6 Port 515 TCP  \u2014  LPD/LPR Line Printer Daemon\",\n              C[\"btn_chip\"], lambda: self._open_single_port_host(515,\"TCP\",\"LPD-LPR-Printer\"),\n              \"Legacy Unix/Linux print protocol\")\n        _ibtn(host_frame, \"\u2705 Sabhi Printer Ports Ek Saath Kholo  (445+139+137+138+135+9100+631+515)\",\n              C[\"btn_warn\"], self._host_open_ports,\n              \"Saare ports ek click mein\")\n\n        # \u2500\u2500 HOST: SECURITY / FIREWALL \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(host_frame, \"\ud83d\udd12  SECURITY &amp; FIREWALL SETTINGS\")\n        _ibtn(host_frame, \"\u25b6 Network Discovery  \u2192  Enable (Private)\",\n              C[\"btn_info\"], lambda: self._host_single_security(\"network_discovery\"),\n              \"Doosre computers network mein dikh sakein\")\n        _ibtn(host_frame, \"\u25b6 File &amp; Printer Sharing Rules  \u2192  ON (All Profiles)\",\n              C[\"btn_info\"], lambda: self._host_single_security(\"fp_sharing_rules\"),\n              \"Windows Firewall built-in sharing rules\")\n        _ibtn(host_frame, \"\u25b6 Network Profile  \u2192  Private\",\n              C[\"btn_info\"], lambda: self._host_single_security(\"network_private\"),\n              \"Public profile pe sharing band hoti hai\")\n        _ibtn(host_frame, \"\u25b6 Password Protected Sharing  \u2192  OFF\",\n              C[\"btn_info\"], lambda: self._host_single_security(\"pwd_sharing_off\"),\n              \"Bina password ke client connect kar sake\")\n        _ibtn(host_frame, \"\u25b6 SMB Signing  \u2192  Optional (Not Required)\",\n              C[\"btn_info\"], lambda: self._host_single_security(\"smb_sign_optional\"),\n              \"HKLM/.../LanmanServer: RequireSecuritySignature=0\")\n        _ibtn(host_frame, \"\u25b6 Windows Defender Firewall  \u2192  Private Network OFF\",\n              C[\"btn_info\"], lambda: self._host_single_security(\"fw_private_off\"),\n              \"Private profile firewall band karo (trusted LAN)\")\n        _ibtn(host_frame, \"\u25b6 ICMPv4 Ping  \u2192  Allow (Firewall)\",\n              C[\"btn_info\"], lambda: self._host_single_security(\"allow_ping\"),\n              \"Client se ping ka jawab aaye\")\n        _ibtn(host_frame, \"\u2705 Saari Security Settings Ek Saath\",\n              C[\"btn_warn\"], self._host_security_fix,\n              \"Network Discovery + F&amp;P Rules + Private + SMB\")\n\n        # \u2500\u2500 HOST: REGISTRY \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(host_frame, \"\ud83d\udddd  REGISTRY CHANGES\")\n        _ibtn(host_frame, \"\u25b6 AutoShareServer = 1  (Admin shares C$, D$ enable)\",\n              C[\"btn_hw\"], lambda: self._host_single_reg(\"AutoShareServer\"),\n              \"HKLM/.../LanmanServer/Parameters\")\n        _ibtn(host_frame, \"\u25b6 AutoShareWks = 1  (Workstation shares enable)\",\n              C[\"btn_hw\"], lambda: self._host_single_reg(\"AutoShareWks\"),\n              \"HKLM/.../LanmanServer/Parameters\")\n        _ibtn(host_frame, \"\u25b6 IRPStackSize = 20  (Large network packets fix)\",\n              C[\"btn_hw\"], lambda: self._host_single_reg(\"IRPStackSize\"),\n              \"HKLM/.../LanmanServer/Parameters\")\n        _ibtn(host_frame, \"\u25b6 LimitBlankPasswordUse = 0  (Blank password allow)\",\n              C[\"btn_hw\"], lambda: self._host_single_reg(\"LimitBlankPasswordUse\"),\n              \"HKLM/.../Control/Lsa\")\n        _ibtn(host_frame, \"\u25b6 DisableWebPrinting = 0  (Web printing enable)\",\n              C[\"btn_hw\"], lambda: self._host_single_reg(\"DisableWebPrinting\"),\n              \"HKLM/.../Control/Print\")\n        _ibtn(host_frame, \"\u25b6 SMB1 Protocol  \u2192  Enable  (XP/Win7 clients ke liye)\",\n              C[\"btn_hw\"], lambda: self._host_single_reg(\"EnableSMB1\"),\n              \"\u26a0 Security risk \u2014 sirf trusted LAN pe karo\")\n        _ibtn(host_frame, \"\u2705 Saare Registry Changes Ek Saath\",\n              C[\"btn_warn\"], self._host_registry_fix,\n              \"AutoShare + IRPStack + LimitBlank + DisableWeb\")\n\n        # \u2500\u2500 HOST: SERVICES \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(host_frame, \"\u2699\ufe0f  SERVICES \u2014 Start/Enable karo\")\n        _ibtn(host_frame, \"\u25b6 Print Spooler  \u2192  Auto + Start\",\n              C[\"accent2\"], lambda: self._host_single_svc(\"Spooler\"),\n              \"Printer ka main service \u2014 shuruaat yahan se\")\n        _ibtn(host_frame, \"\u25b6 Server (LanmanServer)  \u2192  Auto + Start\",\n              C[\"accent2\"], lambda: self._host_single_svc(\"LanmanServer\"),\n              \"File &amp; Printer Sharing ka core service\")\n        _ibtn(host_frame, \"\u25b6 Workstation (LanmanWorkstation)  \u2192  Auto + Start\",\n              C[\"accent2\"], lambda: self._host_single_svc(\"LanmanWorkstation\"),\n              \"Network client redirector service\")\n        _ibtn(host_frame, \"\u25b6 TCP/IP NetBIOS Helper  \u2192  Auto + Start\",\n              C[\"accent2\"], lambda: self._host_single_svc(\"lmhosts\"),\n              \"NetBIOS over TCP/IP naam resolution\")\n        _ibtn(host_frame, \"\u25b6 Function Discovery Provider Host  \u2192  Auto + Start\",\n              C[\"accent2\"], lambda: self._host_single_svc(\"fdPHost\"),\n              \"Network discovery ke liye zaroori\")\n        _ibtn(host_frame, \"\u25b6 Function Discovery Resource Publication  \u2192  Auto + Start\",\n              C[\"accent2\"], lambda: self._host_single_svc(\"FDResPub\"),\n              \"Computer ko network mein publish karta hai\")\n        _ibtn(host_frame, \"\u25b6 SSDP Discovery  \u2192  Auto + Start\",\n              C[\"accent2\"], lambda: self._host_single_svc(\"SSDPSRV\"),\n              \"UPnP devices discovery\")\n        _ibtn(host_frame, \"\u2705 Saari Services Ek Saath Enable karo\",\n              C[\"btn_warn\"], self._host_enable_services,\n              \"Spooler + Server + Workstation + NetBIOS + FD\")\n\n        # \u2500\u2500 HOST: PRINTER SHARE \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(host_frame, \"\ud83d\udce4  PRINTER SHARE KARO\")\n        _ibtn(host_frame, \"\ud83d\udce4  Selected Printer Share Karo  (Auto Confirm)\",\n              C[\"accent\"], self._host_auto_share,\n              \"Upar list mein printer select karo, phir click\")\n\n        # \u2500\u2500 HOST: ERROR 0x0000709 FIX \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(host_frame, \"\ud83d\udd34  ERROR 0x0000709 \u2014 Default Printer Cannot Be Set\")\n        _ibtn(host_frame, \"\ud83d\udd27 Auto-Fix Error 0x0000709  (HOST \u2014 Ek Click Mein)\",\n              C[\"error\"], self._fix_error_709_host,\n              \"Default printer set nahi ho raha \u2014 registry + spooler + RPC fix\")\n\n        # \u2500\u2500 HOST: ERROR 0x0000011b FIX \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(host_frame, \"\ud83d\udd34  ERROR 0x0000011b \u2014 Network Printer Connect Fail\")\n        _ibtn(host_frame, \"\ud83d\udd27 Auto-Fix Error 0x0000011b  (HOST \u2014 Ek Click Mein)\",\n              C[\"error\"], self._fix_error_11b_host,\n              \"Windows Update KB5005565+ ke baad network printer connect nahi \u2014 CVE-2021-1678 patch rollback\")\n\n        # \u2500\u2500 HOST: ONE-CLICK MEGA FIX \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(host_frame, \"\u26a1  MEGA AUTO-FIX \u2014 HOST KI SAARI SETTINGS EK SAATH\")\n        _ibtn(host_frame, \"\ud83d\ude80  HOST: SABKUCH AUTO-FIX  (Ports + Security + Registry + Services + Share + 709 + 11b)\",\n              \"#FF6600\", self._host_mega_auto_fix,\n              \"Ek click mein HOST ka poora printer sharing setup complete \u2014 seedha ready to share\")\n        tk.Frame(host_frame, bg=C[\"bg\"], height=8).pack()\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # \ud83d\udcbb CLIENT COMPUTER COLUMN\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        client_frame = _section_card(share_body,\n            \"\ud83d\udcbb  CLIENT COMPUTER  \u2014  Jo shared printer use karega\",\n            \"Yahan printer nahi laga, network se use karna hai\",\n            \"#1A2A3A\", C[\"accent2\"], 1)\n        client_frame.grid(row=0, column=1, sticky=\"nsew\", padx=(4,8), pady=6)\n\n        # \u2500\u2500 CLIENT: PORTS \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(client_frame, \"\ud83d\udd0c  PORTS \u2014 Firewall mein open karo (IN + OUT)\")\n        _ibtn(client_frame, \"\u25b6 Port 445 TCP+UDP  \u2014  SMB Client Access\",\n              C[\"btn_chip\"], lambda: self._open_single_port_client(445,\"TCP+UDP\",\"SMB-Client-Access\"),\n              \"Host se SMB connection ke liye\")\n        _ibtn(client_frame, \"\u25b6 Port 139 TCP  \u2014  NetBIOS Session (Client)\",\n              C[\"btn_chip\"], lambda: self._open_single_port_client(139,\"TCP\",\"NetBIOS-Session-Client\"),\n              \"NetBIOS session connect karne ke liye\")\n        _ibtn(client_frame, \"\u25b6 Port 137 UDP  \u2014  NetBIOS Name (Client)\",\n              C[\"btn_chip\"], lambda: self._open_single_port_client(137,\"UDP\",\"NetBIOS-Name-Client\"),\n              \"Naam se IP resolve karne ke liye\")\n        _ibtn(client_frame, \"\u25b6 Port 138 UDP  \u2014  NetBIOS Datagram (Client)\",\n              C[\"btn_chip\"], lambda: self._open_single_port_client(138,\"UDP\",\"NetBIOS-Datagram-Client\"),\n              \"NetBIOS broadcast receive karne ke liye\")\n        _ibtn(client_frame, \"\u25b6 Port 135 TCP  \u2014  RPC Client\",\n              C[\"btn_chip\"], lambda: self._open_single_port_client(135,\"TCP\",\"RPC-Client\"),\n              \"Remote Procedure Call \u2014 Windows core\")\n        _ibtn(client_frame, \"\u25b6 Port 9100 TCP  \u2014  RAW Print (Client Side)\",\n              C[\"btn_chip\"], lambda: self._open_single_port_client(9100,\"TCP\",\"RAW-Print-Client\"),\n              \"Direct raw print access client pe\")\n        _ibtn(client_frame, \"\u25b6 Port 631 TCP  \u2014  IPP Client\",\n              C[\"btn_chip\"], lambda: self._open_single_port_client(631,\"TCP\",\"IPP-Client\"),\n              \"Internet Printing Protocol client\")\n        _ibtn(client_frame, \"\u25b6 Port 515 TCP  \u2014  LPD/LPR Client\",\n              C[\"btn_chip\"], lambda: self._open_single_port_client(515,\"TCP\",\"LPD-LPR-Client\"),\n              \"Legacy print protocol client\")\n        _ibtn(client_frame, \"\u2705 Sabhi Client Ports Ek Saath  (445+139+137+138+135+9100+631+515)\",\n              C[\"btn_warn\"], self._client_open_ports,\n              \"Saare ports ek click mein\")\n\n        # \u2500\u2500 CLIENT: SECURITY \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(client_frame, \"\ud83d\udd12  SECURITY &amp; FIREWALL SETTINGS\")\n        _ibtn(client_frame, \"\u25b6 Network Discovery  \u2192  Enable (Client)\",\n              C[\"btn_info\"], lambda: self._client_single_security(\"network_discovery\"),\n              \"Host PC ko network mein dhundh sake\")\n        _ibtn(client_frame, \"\u25b6 File &amp; Printer Sharing Rules  \u2192  ON (Client)\",\n              C[\"btn_info\"], lambda: self._client_single_security(\"fp_sharing_rules\"),\n              \"Windows Firewall F&amp;P rules enable\")\n        _ibtn(client_frame, \"\u25b6 Network Profile  \u2192  Private (Client)\",\n              C[\"btn_info\"], lambda: self._client_single_security(\"network_private\"),\n              \"Public profile pe sharing accessible nahi hoti\")\n        _ibtn(client_frame, \"\u25b6 SMB Client Signing  \u2192  Optional\",\n              C[\"btn_info\"], lambda: self._client_single_security(\"smb_sign_optional\"),\n              \"HKLM/.../LanmanWorkstation: RequireSecuritySignature=0\")\n        _ibtn(client_frame, \"\u25b6 Point &amp; Print  \u2192  No Warning / No Elevation\",\n              C[\"btn_info\"], lambda: self._client_single_security(\"point_print\"),\n              \"Driver install bina UAC prompt ke\")\n        _ibtn(client_frame, \"\u25b6 Windows Defender Firewall  \u2192  Private Network OFF\",\n              C[\"btn_info\"], lambda: self._client_single_security(\"fw_private_off\"),\n              \"Client pe private firewall temporarily off\")\n        _ibtn(client_frame, \"\u25b6 ICMPv4 Ping  \u2192  Allow (Client Firewall)\",\n              C[\"btn_info\"], lambda: self._client_single_security(\"allow_ping\"),\n              \"Host ko ping se dhundh sake\")\n        _ibtn(client_frame, \"\u2705 Saari Client Security Settings Ek Saath\",\n              C[\"btn_warn\"], self._client_security_fix,\n              \"Discovery + F&amp;P Rules + Private + SMB + PnP\")\n\n        # \u2500\u2500 CLIENT: REGISTRY \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(client_frame, \"\ud83d\udddd  REGISTRY CHANGES\")\n        _ibtn(client_frame, \"\u25b6 AllowInsecureGuestAuth = 1  (Guest share access)\",\n              C[\"btn_hw\"], lambda: self._client_single_reg(\"AllowInsecureGuestAuth\"),\n              \"HKLM/.../LanmanWorkstation/Parameters\")\n        _ibtn(client_frame, \"\u25b6 LimitBlankPasswordUse = 0  (Blank password connect)\",\n              C[\"btn_hw\"], lambda: self._client_single_reg(\"LimitBlankPasswordUse\"),\n              \"HKLM/.../Control/Lsa\")\n        _ibtn(client_frame, \"\u25b6 RequireSecuritySignature = 0  (SMB signing optional)\",\n              C[\"btn_hw\"], lambda: self._client_single_reg(\"RequireSecuritySignature\"),\n              \"HKLM/.../LanmanWorkstation/Parameters\")\n        _ibtn(client_frame, \"\u25b6 Point &amp; Print: NoWarningNoElevationOnInstall = 1\",\n              C[\"btn_hw\"], lambda: self._client_single_reg(\"PnP_NoWarning\"),\n              \"HKLM/SOFTWARE/Policies/.../PointAndPrint\")\n        _ibtn(client_frame, \"\u25b6 Point &amp; Print: UpdatePromptSettings = 2\",\n              C[\"btn_hw\"], lambda: self._client_single_reg(\"PnP_UpdatePrompt\"),\n              \"HKLM/SOFTWARE/Policies/.../PointAndPrint\")\n        _ibtn(client_frame, \"\u25b6 Point &amp; Print: RestrictDriverInstall = 0\",\n              C[\"btn_hw\"], lambda: self._client_single_reg(\"PnP_RestrictDriver\"),\n              \"HKLM/SOFTWARE/Policies/.../PointAndPrint\")\n        _ibtn(client_frame, \"\u2705 Saare Client Registry Changes Ek Saath\",\n              C[\"btn_warn\"], self._client_registry_fix,\n              \"GuestAuth + LimitBlank + SMB + Point&amp;Print\")\n\n        # \u2500\u2500 CLIENT: SERVICES \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(client_frame, \"\u2699\ufe0f  SERVICES \u2014 Start/Enable karo (Client)\")\n        _ibtn(client_frame, \"\u25b6 Print Spooler  \u2192  Auto + Start\",\n              C[\"accent2\"], lambda: self._host_single_svc(\"Spooler\"),\n              \"Client pe bhi spooler chahiye\")\n        _ibtn(client_frame, \"\u25b6 Workstation (LanmanWorkstation)  \u2192  Auto + Start\",\n              C[\"accent2\"], lambda: self._host_single_svc(\"LanmanWorkstation\"),\n              \"Network redirector \u2014 sharing ke liye zaroori\")\n        _ibtn(client_frame, \"\u25b6 TCP/IP NetBIOS Helper  \u2192  Auto + Start\",\n              C[\"accent2\"], lambda: self._host_single_svc(\"lmhosts\"),\n              \"NetBIOS naam resolution client side\")\n        _ibtn(client_frame, \"\u25b6 Function Discovery Provider Host  \u2192  Auto + Start\",\n              C[\"accent2\"], lambda: self._host_single_svc(\"fdPHost\"),\n              \"Network mein host PC dhundh sake\")\n        _ibtn(client_frame, \"\u25b6 SSDP Discovery  \u2192  Auto + Start\",\n              C[\"accent2\"], lambda: self._host_single_svc(\"SSDPSRV\"),\n              \"UPnP / network device discovery\")\n\n        # \u2500\u2500 CLIENT: CONNECT \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(client_frame, \"\ud83d\udda8  HOST SE CONNECT KARO\")\n        _ibtn(client_frame, \"\ud83d\udda8  Host ke Shared Printer se Connect Karo\",\n              C[\"accent\"], self._client_connect_printer,\n              \"Host IP + Share Name daal ke connect\")\n\n        # \u2500\u2500 CLIENT: ERROR 0x0000709 FIX \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(client_frame, \"\ud83d\udd34  ERROR 0x0000709 \u2014 Default Printer Cannot Be Set\")\n        _ibtn(client_frame, \"\ud83d\udd27 Auto-Fix Error 0x0000709  (CLIENT \u2014 Ek Click Mein)\",\n              C[\"error\"], self._fix_error_709_client,\n              \"Default printer set nahi ho raha \u2014 registry + spooler + UserSelectedDefault fix\")\n\n        # \u2500\u2500 CLIENT: ERROR 0x0000011b FIX \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(client_frame, \"\ud83d\udd34  ERROR 0x0000011b \u2014 Network Printer Connect Fail\")\n        _ibtn(client_frame, \"\ud83d\udd27 Auto-Fix Error 0x0000011b  (CLIENT \u2014 Ek Click Mein)\",\n              C[\"error\"], self._fix_error_11b_client,\n              \"Network printer connect nahi \u2014 RPC encryption + LanmanWorkstation fix\")\n\n        # \u2500\u2500 CLIENT: ONE-CLICK MEGA FIX \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _grp_label(client_frame, \"\u26a1  MEGA AUTO-FIX \u2014 CLIENT KI SAARI SETTINGS EK SAATH\")\n        _ibtn(client_frame, \"\ud83d\ude80  CLIENT: SABKUCH AUTO-FIX  (Ports + Security + Registry + Services + 709 + 11b + Connect)\",\n              \"#FF6600\", self._client_mega_auto_fix,\n              \"Ek click mein CLIENT ka poora printer connect setup \u2014 seedha print karo\")\n        tk.Frame(client_frame, bg=C[\"bg\"], height=8).pack()\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # \ud83d\udcdd SHARING LOG \u2014 tab2 ke andar\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        share_log_outer = tk.Frame(tab2, bg=C[\"card\"])\n        share_log_outer.pack(fill=\"x\", padx=8, pady=(2,8))\n        tk.Label(share_log_outer, text=\"  \ud83d\udcdd Sharing Center Log\",\n                 font=FONTS[\"subhead\"], fg=C[\"accent4\"], bg=C[\"card\"]).pack(\n                 anchor=\"w\", padx=8, pady=(6,2))\n        self.sharing_log = self._scrolled_text(share_log_outer, height=6)\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # \ud83d\udd27 TAB 3 \u2014 ADVANCED ERROR FIX GUIDE (0x0000709 + 0x0000011b)\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        tab3 = tk.Frame(nb, bg=C[\"bg\"])\n        nb.add(tab3, text=\"  \ud83d\udd34  Error Fix Guide (709 &amp; 11b)  \")\n\n        # \u2500\u2500 Tab3 Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        t3_hdr = tk.Frame(tab3, bg=C[\"panel\"])\n        t3_hdr.pack(fill=\"x\")\n        tk.Label(t3_hdr, text=\"  \ud83d\udd34 Printer Error Fix Guide \u2014 0x0000709 &amp; 0x0000011b\",\n                 font=FONTS[\"heading\"], fg=C[\"error\"], bg=C[\"panel\"]).pack(side=\"left\", pady=8, padx=8)\n        tk.Label(t3_hdr,\n                 text=\"In-app auto-fix buttons + manual steps \u2014 dono tarike ek jagah\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"left\")\n\n        # \u2500\u2500 Tab3 Scrollable Canvas \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        t3_outer = tk.Frame(tab3, bg=C[\"bg\"])\n        t3_outer.pack(fill=\"both\", expand=True)\n        t3_canvas = tk.Canvas(t3_outer, bg=C[\"bg\"], highlightthickness=0)\n        t3_sb = ttk.Scrollbar(t3_outer, orient=\"vertical\", command=t3_canvas.yview)\n        t3_canvas.configure(yscrollcommand=t3_sb.set)\n        t3_sb.pack(side=\"right\", fill=\"y\")\n        t3_canvas.pack(side=\"left\", fill=\"both\", expand=True)\n        t3_body = tk.Frame(t3_canvas, bg=C[\"bg\"])\n        t3_win = t3_canvas.create_window((0,0), window=t3_body, anchor=\"nw\")\n        def _t3_resize(e):\n            t3_canvas.configure(scrollregion=t3_canvas.bbox(\"all\"))\n            t3_canvas.itemconfig(t3_win, width=t3_canvas.winfo_width())\n        t3_body.bind(\"\", _t3_resize)\n        def _t3_canvas_configure(e):\n            t3_canvas.itemconfig(t3_win, width=e.width)\n            t3_canvas.configure(scrollregion=t3_canvas.bbox(\"all\"))\n        t3_canvas.bind(\"\", _t3_canvas_configure)\n        self._bind_scoped_mousewheel(t3_body, t3_canvas)\n\n        # \u2500\u2500 Helper functions for Tab3 layout \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        def _t3_section(title, subtitle, color):\n            frm = tk.Frame(t3_body, bg=C[\"card\"], bd=0)\n            frm.pack(fill=\"x\", padx=12, pady=(8,0))\n            hdr = tk.Frame(frm, bg=color)\n            hdr.pack(fill=\"x\")\n            tk.Label(hdr, text=title, font=FONTS[\"subhead\"], fg=C[\"text\"],\n                     bg=color, anchor=\"w\").pack(anchor=\"w\", padx=12, pady=(8,2))\n            tk.Label(hdr, text=subtitle, font=FONTS[\"small\"], fg=C[\"text_dim\"],\n                     bg=color, anchor=\"w\").pack(anchor=\"w\", padx=12, pady=(0,6))\n            return frm\n\n        def _t3_step(parent, num, title, detail, cmd_text=\"\"):\n            \"\"\"Numbered step row with optional command display.\"\"\"\n            row = tk.Frame(parent, bg=C[\"card\"])\n            row.pack(fill=\"x\", padx=8, pady=3)\n            # Step number badge\n            badge = tk.Label(row, text=f\" {num} \", font=(\"Consolas\",10,\"bold\"),\n                             fg=C[\"bg\"], bg=C[\"accent4\"], padx=4, pady=2)\n            badge.pack(side=\"left\", padx=(6,8), pady=4, anchor=\"n\")\n            # Content\n            content = tk.Frame(row, bg=C[\"card\"])\n            content.pack(side=\"left\", fill=\"x\", expand=True, pady=4)\n            tk.Label(content, text=title, font=FONTS[\"body\"], fg=C[\"text\"],\n                     bg=C[\"card\"], anchor=\"w\").pack(anchor=\"w\")\n            if detail:\n                tk.Label(content, text=detail, font=FONTS[\"small\"], fg=C[\"text_dim\"],\n                         bg=C[\"card\"], anchor=\"w\", wraplength=700, justify=\"left\").pack(anchor=\"w\")\n            if cmd_text:\n                cmd_row = tk.Frame(content, bg=\"#0D0D1A\")\n                cmd_row.pack(fill=\"x\", pady=(3,0))\n                tk.Label(cmd_row, text=f\"  {cmd_text}\", font=(\"Consolas\",9),\n                         fg=C[\"accent2\"], bg=\"#0D0D1A\", anchor=\"w\").pack(side=\"left\", padx=4, pady=3)\n                def _copy(t=cmd_text):\n                    self.clipboard_clear()\n                    self.clipboard_append(t)\n                    messagebox.showinfo(\"Copied!\", f\"Copied:\\n{t}\", parent=self)\n                tk.Button(cmd_row, text=\"\ud83d\udccb Copy\", font=(\"Consolas\",8),\n                          bg=C[\"btn_chip\"], fg=C[\"text\"], bd=0, padx=6, pady=2,\n                          cursor=\"hand2\", command=_copy).pack(side=\"right\", padx=4)\n\n        def _t3_auto_btn(parent, text, color, cmd, note=\"\"):\n            row = tk.Frame(parent, bg=C[\"card\"])\n            row.pack(fill=\"x\", padx=8, pady=(4,2))\n            tk.Button(row, text=text, font=FONTS[\"body\"], bg=color, fg=C[\"text\"],\n                      bd=0, padx=14, pady=8, cursor=\"hand2\", anchor=\"w\",\n                      command=cmd).pack(side=\"left\")\n            if note:\n                tk.Label(row, text=note, font=FONTS[\"small\"], fg=C[\"text_dim\"],\n                         bg=C[\"card\"], anchor=\"w\").pack(side=\"left\", padx=10)\n\n        def _t3_divider(parent):\n            tk.Frame(parent, bg=C[\"border\"], height=1).pack(fill=\"x\", padx=12, pady=4)\n\n        def _t3_info_box(parent, text, bg=\"#1A1A2A\", fg=None):\n            fg = fg or C[\"accent4\"]\n            bx = tk.Frame(parent, bg=bg, bd=0)\n            bx.pack(fill=\"x\", padx=20, pady=(4,0))\n            tk.Label(bx, text=text, font=FONTS[\"small\"], fg=fg, bg=bg,\n                     anchor=\"w\", wraplength=820, justify=\"left\",\n                     padx=10, pady=8).pack(fill=\"x\")\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # SECTION 1 \u2014 QUICK DECISION (Kaunsa error hai?)\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        s0 = _t3_section(\"\ud83e\udd14  Pehle Pehchano \u2014 Kaunsa Error Hai?\",\n                         \"Error code dekho aur us section mein jaao\", \"#1A2A1A\")\n        _t3_info_box(s0,\n            \"0x0000709  \u2192  'Operation could not be completed. Cannot set default printer.'\\n\"\n            \"              Matlab: Windows ko default printer set karna nahi aa raha \u2014 mostly registry/spooler issue.\\n\\n\"\n            \"0x0000011b \u2192  'Windows cannot connect to the printer. Operation failed with error 0x0000011b.'\\n\"\n            \"              Matlab: Network/shared printer se connection nahi ho raha \u2014 mostly Windows Update (KB5005565) ne RPC strict kar diya.\",\n            bg=\"#0D1A0D\", fg=C[\"text\"])\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # SECTION 2 \u2014 ERROR 0x0000709 FULL GUIDE\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        s1 = _t3_section(\"\ud83d\udd34  Error 0x0000709 \u2014 Default Printer Cannot Be Set\",\n                         \"HOST aur CLIENT dono pe ye steps karo\", \"#2A1A1A\")\n\n        _t3_info_box(s1,\n            \"\u26a1 SABSE PEHLE \u2014 Neeche ka Auto-Fix button dabaao. Manually karne ki zaroorat nahi padegi.\",\n            bg=\"#1A0D0D\", fg=C[\"warning\"])\n\n        _t3_auto_btn(s1, \"\ud83d\udd27 AUTO-FIX 0x0000709 \u2014 HOST (Ek Click)\",  C[\"error\"],\n                     self._fix_error_709_host, \"\u2190 HOST PC pe run karo (jisme printer laga hai)\")\n        _t3_auto_btn(s1, \"\ud83d\udd27 AUTO-FIX 0x0000709 \u2014 CLIENT (Ek Click)\", C[\"error\"],\n                     self._fix_error_709_client, \"\u2190 CLIENT PC pe run karo (jo print karna chahta hai)\")\n\n        _t3_divider(s1)\n        tk.Label(s1, text=\"  \ud83d\udccb Manual Steps (agar auto-fix kaam na kare):\",\n                 font=FONTS[\"body\"], fg=C[\"accent4\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=10, pady=(6,2))\n\n        _t3_step(s1, \"1\", \"Group Policy se RPC Settings fix karo  (Windows Pro/Enterprise only)\",\n                 \"Windows Key + R \u2192 gpedit.msc \u2192 Computer Configuration \u2192 Administrative Templates \u2192 Printers\\n\"\n                 \"\u2192 'Configure RPC connection settings' \u2192 Enabled \u2192 Dropdown: 'RPC over named pipes' \u2192 Apply \u2192 OK\",\n                 \"gpedit.msc\")\n        _t3_auto_btn(s1,\n            \"\u2699 Auto-Fix: gpedit.msc Setting  \u2014 Configure RPC \u2192 Named Pipes (Windows Pro/Enterprise)\",\n            C[\"btn_hw\"], self._auto_gpedit_rpc_709,\n            \"\u2190 Ek click: Group Policy RPC setting auto set\")\n\n        _t3_step(s1, \"2\", \"Registry se RpcAuthnLevelPrivacyEnabled = 0 set karo  (Windows Home ke liye bhi kaam karta hai)\",\n                 \"Windows Key + R \u2192 regedit \u2192 HKEY_LOCAL_MACHINE\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\\n\"\n                 \"\u2192 Right-click \u2192 New \u2192 DWORD (32-bit) \u2192 Name: RpcAuthnLevelPrivacyEnabled \u2192 Value: 0\",\n                 r\"HKLM\\SYSTEM\\CurrentControlSet\\Control\\Print  \u2192  RpcAuthnLevelPrivacyEnabled = 0\")\n        _t3_auto_btn(s1,\n            \"\ud83d\udddd Auto-Fix: Registry Setting  \u2014 RpcAuthnLevelPrivacyEnabled = 0  (Home + Pro dono)\",\n            C[\"btn_hw\"], self._auto_reg_rpcauth_0,\n            \"\u2190 Ek click: Registry me value seedha set ho jaayegi\")\n\n        _t3_step(s1, \"3\", \"LegacyDefaultPrinterMode = 1 set karo  (Windows auto printer manage feature band karo)\",\n                 \"HKEY_CURRENT_USER\\\\SOFTWARE\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\Windows\\n\"\n                 \"\u2192 New DWORD \u2192 LegacyDefaultPrinterMode \u2192 Value: 1\",\n                 r\"HKCU\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows  \u2192  LegacyDefaultPrinterMode = 1\")\n        _t3_auto_btn(s1,\n            \"\ud83d\udddd Auto-Fix: Registry Setting  \u2014 LegacyDefaultPrinterMode = 1  (Windows auto-manage OFF)\",\n            C[\"btn_hw\"], self._auto_reg_legacy_default,\n            \"\u2190 Ek click: HKCU registry value auto set\")\n\n        _t3_step(s1, \"4\", \"Print Spooler Service Restart karo\",\n                 \"Windows Key + R \u2192 services.msc \u2192 Print Spooler \u2192 Right-click \u2192 Restart\",\n                 \"services.msc\")\n        _t3_auto_btn(s1,\n            \"\ud83d\udd01 Auto-Fix: Print Spooler Restart\",\n            C[\"btn_chip\"], self._printer_reset_spooler,\n            \"\u2190 Ek click: Spooler stop + start\")\n\n        _t3_step(s1, \"5\", \"UserSelectedDefault registry value delete karo  (stale default clear)\",\n                 \"HKEY_CURRENT_USER\\\\SOFTWARE\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\Windows\\n\"\n                 \"\u2192 'UserSelectedDefault' value ko delete karo (agar hai to)\", \"\")\n        _t3_auto_btn(s1,\n            \"\ud83d\udddd Auto-Fix: Registry Setting  \u2014 UserSelectedDefault Delete  (stale default clear)\",\n            C[\"btn_hw\"], self._auto_reg_delete_userselected,\n            \"\u2190 Ek click: Purana default printer entry hata do\")\n\n        _t3_step(s1, \"6\", \"Reboot karo\",\n                 \"Saari changes ke baad computer restart karo \u2014 registry changes tabhi full effect mein aati hain.\", \"\")\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # SECTION 3 \u2014 ERROR 0x0000011b FULL GUIDE\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        s2 = _t3_section(\"\ud83d\udd34  Error 0x0000011b \u2014 Network Printer Cannot Connect\",\n                         \"Ye error Windows Update KB5005565/KB5005566 ke baad aata hai \u2014 HOST + CLIENT dono fix karo\",\n                         \"#2A1A2A\")\n\n        _t3_info_box(s2,\n            \"Root Cause: Microsoft ne October 2021 update (KB5005565) mein RPC encryption strict kar di.\\n\"\n            \"Fix: RpcAuthnLevelPrivacyEnabled = 0 dono PCs pe \u2014 HOST aur CLIENT dono pe karna ZAROORI hai.\",\n            bg=\"#1A0D1A\", fg=C[\"warning\"])\n\n        _t3_auto_btn(s2, \"\ud83d\udd27 AUTO-FIX 0x0000011b \u2014 HOST (Ek Click)\",  C[\"error\"],\n                     self._fix_error_11b_host, \"\u2190 HOST PC pe pehle run karo\")\n        _t3_auto_btn(s2, \"\ud83d\udd27 AUTO-FIX 0x0000011b \u2014 CLIENT (Ek Click)\", C[\"error\"],\n                     self._fix_error_11b_client, \"\u2190 CLIENT PC pe run karo\")\n\n        _t3_divider(s2)\n        tk.Label(s2, text=\"  \ud83d\udccb Manual Steps (agar auto-fix kaam na kare):\",\n                 font=FONTS[\"body\"], fg=C[\"accent4\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=10, pady=(6,2))\n\n        _t3_step(s2, \"1\", \"Group Policy se RPC Settings fix karo \u2014 DONO PCs pe  (Windows Pro/Enterprise)\",\n                 \"Windows Key + R \u2192 gpedit.msc \u2192 Computer Configuration \u2192 Administrative Templates \u2192 Printers\\n\"\n                 \"\u2192 'Configure RPC connection settings' \u2192 Enabled \u2192 'RPC over named pipes' \u2192 Apply \u2192 OK\\n\"\n                 \"\u26a0 DONO COMPUTERS pe \u2014 HOST aur CLIENT dono pe ye setting karo\",\n                 \"gpedit.msc\")\n        _t3_auto_btn(s2,\n            \"\u2699 Auto-Fix: gpedit.msc Setting  \u2014 Configure RPC \u2192 Named Pipes  (Windows Pro/Enterprise)\",\n            C[\"btn_hw\"], self._auto_gpedit_rpc_11b,\n            \"\u2190 Ek click: Group Policy RPC + Printer settings auto set (dono computers pe alag-alag chalao)\")\n\n        _t3_step(s2, \"2\", \"Registry mein RpcAuthnLevelPrivacyEnabled = 0 set karo \u2014 DONO PCs pe\",\n                 \"Ye Windows Home ke liye bhi kaam karta hai (jahan gpedit nahi hota)\\n\"\n                 \"Path: HKEY_LOCAL_MACHINE\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\\n\"\n                 \"\u2192 New DWORD (32-bit) \u2192 Name: RpcAuthnLevelPrivacyEnabled \u2192 Value data: 0 \u2192 OK\",\n                 r\"reg add HKLM\\SYSTEM\\CurrentControlSet\\Control\\Print /v RpcAuthnLevelPrivacyEnabled /t REG_DWORD /d 0 /f\")\n        _t3_auto_btn(s2,\n            \"\ud83d\udddd Auto-Fix: Registry Setting  \u2014 RpcAuthnLevelPrivacyEnabled = 0  (Home + Pro dono)\",\n            C[\"btn_hw\"], self._auto_reg_rpcauth_0,\n            \"\u2190 Ek click: Registry me value seedha set \u2014 DONO PCs pe alag-alag chalao\")\n\n        _t3_step(s2, \"3\", \"Windows Credentials mein Password save karo  (Client PC pe)\",\n                 \"Client PC pe: Windows Search \u2192 Credential Manager \u2192 Windows Credentials\\n\"\n                 \"\u2192 'Add a Windows credential'\\n\"\n                 \"\u2192 Internet/network address: HOST PC ka naam ya IP (jaise: \\\\\\\\Main-PC ya 192.168.1.15)\\n\"\n                 \"\u2192 Username + Password: HOST PC ka login credentials \u2192 OK\",\n                 \"control /name Microsoft.CredentialManager\")\n        _t3_step(s2, \"4\", \"Print Spooler Restart karo \u2014 DONO PCs pe\",\n                 \"Windows Key + R \u2192 services.msc \u2192 Print Spooler \u2192 Right-click \u2192 Restart\\n\"\n                 \"Ya neeche ka button dabaao:\",\n                 \"net stop spooler &amp;&amp; net start spooler\")\n        _t3_auto_btn(s2,\n            \"\ud83d\udd01 Auto-Fix: Print Spooler Restart\",\n            C[\"btn_chip\"], self._printer_reset_spooler,\n            \"\u2190 Ek click: Spooler stop + start\")\n\n        _t3_step(s2, \"5\", \"DONO Computers Restart karo\",\n                 \"Registry changes full effect tab aati hain \u2014 restart zaroori hai.\", \"\")\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # SECTION 4 \u2014 CREDENTIAL MANAGER (Windows Credentials Save)\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        s3 = _t3_section(\"\ud83d\udd11  Windows Credentials Manager \u2014 Auto Save / Open\",\n                         \"PC-to-PC sharing mein authentication fail hoti hai \u2014 yahan credentials save karo\",\n                         \"#1A1A2A\")\n\n        _t3_info_box(s3,\n            \"Jab HOST PC password-protected ho aur CLIENT bina password ke connect karne ki koshish kare\\n\"\n            \"to error aata hai. Solution: CLIENT pe HOST ke credentials Credential Manager mein save karo.\",\n            bg=\"#0D0D1A\", fg=C[\"text_dim\"])\n\n        cred_frame = tk.Frame(s3, bg=C[\"card\"])\n        cred_frame.pack(fill=\"x\", padx=8, pady=8)\n        cred_cols = tk.Frame(cred_frame, bg=C[\"card\"])\n        cred_cols.pack(fill=\"x\", padx=4)\n\n        # Input fields for credential manager\n        tk.Label(cred_cols, text=\"  HOST PC ka IP / Name:\", font=FONTS[\"body\"],\n                 fg=C[\"text\"], bg=C[\"card\"]).grid(row=0, column=0, sticky=\"w\", padx=6, pady=4)\n        self._cred_host_var = tk.StringVar(value=\"192.168.1.x  ya  PC-Name\")\n        cred_host_e = tk.Entry(cred_cols, textvariable=self._cred_host_var,\n                               font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"],\n                               insertbackground=C[\"text\"], relief=\"flat\", bd=4, width=30)\n        cred_host_e.grid(row=0, column=1, padx=6, pady=4)\n        cred_host_e.bind(\"\",\n            lambda e: cred_host_e.delete(0,\"end\") if \"ya\" in cred_host_e.get() or \"x\" in cred_host_e.get() else None)\n\n        tk.Label(cred_cols, text=\"  Username:\", font=FONTS[\"body\"],\n                 fg=C[\"text\"], bg=C[\"card\"]).grid(row=1, column=0, sticky=\"w\", padx=6, pady=4)\n        self._cred_user_var = tk.StringVar(value=\"\")\n        tk.Entry(cred_cols, textvariable=self._cred_user_var, font=FONTS[\"body\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"],\n                 relief=\"flat\", bd=4, width=30).grid(row=1, column=1, padx=6, pady=4)\n\n        tk.Label(cred_cols, text=\"  Password:\", font=FONTS[\"body\"],\n                 fg=C[\"text\"], bg=C[\"card\"]).grid(row=2, column=0, sticky=\"w\", padx=6, pady=4)\n        self._cred_pwd_var = tk.StringVar(value=\"\")\n        tk.Entry(cred_cols, textvariable=self._cred_pwd_var, font=FONTS[\"body\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"],\n                 relief=\"flat\", bd=4, width=30, show=\"*\").grid(row=2, column=1, padx=6, pady=4)\n\n        cred_btn_row = tk.Frame(cred_frame, bg=C[\"card\"])\n        cred_btn_row.pack(fill=\"x\", padx=8, pady=(4,8))\n\n        def _auto_save_cred():\n            host = self._cred_host_var.get().strip()\n            user = self._cred_user_var.get().strip()\n            pwd  = self._cred_pwd_var.get().strip()\n            if not host or \"ya\" in host or \"x\" in host:\n                messagebox.showwarning(\"Host Missing\", \"HOST PC ka naam ya IP dalo.\")\n                return\n            if not user:\n                messagebox.showwarning(\"Username Missing\", \"Username dalo.\")\n                return\n            # Build cmdkey command\n            unc = host if host.startswith(\"\\\\\\\\\") else f\"\\\\\\\\{host}\"\n            cmd = f'cmdkey /add:{unc} /user:{user} /pass:{pwd if pwd else \"\"}'\n            out, rc = self._run_cmd(cmd, timeout=10)\n            if rc == 0:\n                self._sharing_log(f\"\u2705 Credential saved for {unc} (user: {user})\", C[\"success\"])\n                messagebox.showinfo(\"\u2705 Done!\", f\"Credential saved!\\nHost: {unc}\\nUser: {user}\\n\\nAb printer connect karo.\")\n            else:\n                self._sharing_log(f\"\u26a0 cmdkey failed rc={rc}: {out}\", C[\"warning\"])\n                messagebox.showerror(\"Error\", f\"Credential save nahi hua:\\n{out}\")\n\n        def _open_cred_manager():\n            self._run_cmd(\"control /name Microsoft.CredentialManager\")\n            self._sharing_log(\"\u2705 Credential Manager khola gaya.\", C[\"success\"])\n\n        def _list_creds():\n            out, _ = self._run_cmd(\"cmdkey /list\", timeout=10)\n            messagebox.showinfo(\"Saved Credentials\", out or \"Koi saved credential nahi mila.\")\n\n        def _delete_cred():\n            host = self._cred_host_var.get().strip()\n            if not host or \"ya\" in host:\n                messagebox.showwarning(\"\", \"Pehle HOST ka naam/IP dalo.\")\n                return\n            unc = host if host.startswith(\"\\\\\\\\\") else f\"\\\\\\\\{host}\"\n            out, rc = self._run_cmd(f'cmdkey /delete:{unc}', timeout=10)\n            msg = f\"\u2705 Credential deleted: {unc}\" if rc == 0 else f\"\u26a0 Delete failed: {out}\"\n            self._sharing_log(msg, C[\"success\"] if rc == 0 else C[\"warning\"])\n            messagebox.showinfo(\"Result\", msg)\n\n        tk.Button(cred_btn_row, text=\"\ud83d\udcbe Auto-Save Credential (cmdkey)\", font=FONTS[\"body\"],\n                  bg=C[\"accent\"], fg=C[\"bg\"], bd=0, padx=12, pady=7, cursor=\"hand2\",\n                  command=_auto_save_cred).pack(side=\"left\", padx=(0,6))\n        tk.Button(cred_btn_row, text=\"\ud83d\udcc2 Open Credential Manager\", font=FONTS[\"body\"],\n                  bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=10, pady=7, cursor=\"hand2\",\n                  command=_open_cred_manager).pack(side=\"left\", padx=(0,6))\n        tk.Button(cred_btn_row, text=\"\ud83d\udccb List Credentials\", font=FONTS[\"body\"],\n                  bg=C[\"btn_chip\"], fg=C[\"text\"], bd=0, padx=10, pady=7, cursor=\"hand2\",\n                  command=_list_creds).pack(side=\"left\", padx=(0,6))\n        tk.Button(cred_btn_row, text=\"\ud83d\uddd1 Delete Credential\", font=FONTS[\"body\"],\n                  bg=C[\"error\"], fg=C[\"text\"], bd=0, padx=10, pady=7, cursor=\"hand2\",\n                  command=_delete_cred).pack(side=\"left\")\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # SECTION 5 \u2014 QUICK ACTIONS (all-in-one shortcuts)\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        s4 = _t3_section(\"\u26a1  Quick Actions \u2014 Ek Click Tools\",\n                         \"Frequently needed tools seedha yahan se\",\n                         \"#1A2A2A\")\n\n        def _t3_quick(parent, label, cmd_str, note=\"\"):\n            row = tk.Frame(parent, bg=C[\"card\"])\n            row.pack(fill=\"x\", padx=8, pady=2)\n            def _run():\n                self._run_cmd(cmd_str, timeout=10)\n                self._sharing_log(f\"\u25b6 Ran: {cmd_str}\", C[\"text_dim\"])\n            tk.Button(row, text=label, font=FONTS[\"body\"],\n                      bg=C[\"btn_hw\"], fg=C[\"text\"], bd=0, padx=12, pady=6,\n                      cursor=\"hand2\", anchor=\"w\", command=_run).pack(side=\"left\", fill=\"x\", expand=True)\n            if note:\n                tk.Label(row, text=note, font=(\"Consolas\",8), fg=C[\"text_dim\"],\n                         bg=C[\"card\"]).pack(side=\"left\", padx=6)\n\n        _t3_quick(s4, \"\ud83d\udd01 Spooler Restart\",\n                  \"net stop spooler /y &amp; net start spooler\",\n                  \"Print queue hang fix\")\n        _t3_quick(s4, \"\ud83d\uddc2 Open Printers &amp; Scanners\",\n                  \"control printers\",\n                  \"Windows printers settings\")\n        _t3_quick(s4, \"\ud83d\udd11 Open Credential Manager\",\n                  \"control /name Microsoft.CredentialManager\",\n                  \"Saved network passwords\")\n        _t3_quick(s4, \"\u2699 Open Group Policy Editor\",\n                  \"gpedit.msc\",\n                  \"RPC settings (Pro/Enterprise only)\")\n        _t3_quick(s4, \"\ud83d\udcdd Open Registry Editor\",\n                  \"regedit\",\n                  \"Manual registry changes\")\n        _t3_quick(s4, \"\ud83d\udd27 Open Services\",\n                  \"services.msc\",\n                  \"Start/Stop/Restart services\")\n        _t3_quick(s4, \"\ud83c\udf10 Open Network &amp; Sharing Center\",\n                  \"control.exe /name Microsoft.NetworkAndSharingCenter\",\n                  \"Network profile + sharing settings\")\n        _t3_quick(s4, \"\ud83d\udda5 Open Computer Name / Workgroup Settings\",\n                  \"SystemPropertiesComputerName.exe\",\n                  \"Workgroup mismatch fix\")\n        _t3_quick(s4, \"\ud83d\udce1 IPConfig \u2014 IP Address Check\",\n                  \"cmd /k ipconfig /all\",\n                  \"Apna IP janno\")\n        _t3_quick(s4, \"\ud83d\udd0d SFC Scannow \u2014 System File Check\",\n                  \"cmd /k sfc /scannow\",\n                  \"Corrupted Windows files repair\")\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # SECTION 6 \u2014 DECISION TREE (Home vs Pro, IP vs Name)\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        s5 = _t3_section(\"\ud83d\uddfa  Windows Edition &amp; Connection Type \u2014 Kya Use Karo?\",\n                         \"Aapka Windows version aur connection method fix decide karta hai\",\n                         \"#1A2A3A\")\n\n        _t3_info_box(s5,\n            \"Windows HOME (jaise HP/Dell pe usually hota hai)\\n\"\n            \"  \u2192 gpedit.msc NAHI khulega\\n\"\n            \"  \u2192 Registry method use karo: RpcAuthnLevelPrivacyEnabled = 0\\n\"\n            \"  \u2192 Ya neeche Auto-Fix button seedha kaam karega\\n\\n\"\n            \"Windows PRO / ENTERPRISE (office machines usually)\\n\"\n            \"  \u2192 gpedit.msc bhi use kar sakte ho (Group Policy method)\\n\"\n            \"  \u2192 Registry method bhi kaam karta hai\\n\\n\"\n            \"IP Address se connect karna  (jaise \\\\\\\\192.168.1.15\\\\ShareName)\\n\"\n            \"  \u2192 Zyada reliable \u2014 naam resolution ki zaroorat nahi\\n\"\n            \"  \u2192 Credential Manager mein IP save karo\\n\\n\"\n            \"PC Name se connect karna  (jaise \\\\\\\\OFFICPC\\\\ShareName)\\n\"\n            \"  \u2192 NetBIOS naam resolution chahiye (lmhosts service)\\n\"\n            \"  \u2192 Agar naam se nahi ho raha to IP se try karo\",\n            bg=\"#0D1A2A\", fg=C[\"text\"])\n\n        # Windows Edition Check Button\n        def _check_win_edition():\n            out, _ = self._run_cmd(\n                'powershell -Command \"(Get-WmiObject -Class Win32_OperatingSystem).Caption\"',\n                timeout=10)\n            edition = out.strip() or \"Unknown\"\n            is_home = \"home\" in edition.lower()\n            msg = (\n                f\"Windows Edition: {edition}\\n\\n\"\n                + (\"\u26a0 HOME edition hai \u2014 gpedit.msc nahi khulega.\\n\"\n                   \"   Registry method ya Auto-Fix button use karo.\"\n                   if is_home else\n                   \"\u2705 Pro/Enterprise edition hai \u2014 gpedit.msc available hai.\\n\"\n                   \"   Group Policy ya Registry dono methods kaam karenge.\")\n            )\n            messagebox.showinfo(\"Windows Edition Check\", msg)\n            self._sharing_log(f\"\u2139 Windows: {edition}\", C[\"text_dim\"])\n\n        btn_row_s5 = tk.Frame(s5, bg=C[\"card\"])\n        btn_row_s5.pack(fill=\"x\", padx=8, pady=6)\n        tk.Button(btn_row_s5, text=\"\ud83d\udd0d Check Windows Edition\", font=FONTS[\"body\"],\n                  bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=14, pady=7, cursor=\"hand2\",\n                  command=_check_win_edition).pack(side=\"left\", padx=(0,8))\n        tk.Button(btn_row_s5, text=\"\ud83d\ude80 HOST Mega Auto-Fix\", font=FONTS[\"body\"],\n                  bg=\"#FF6600\", fg=C[\"text\"], bd=0, padx=14, pady=7, cursor=\"hand2\",\n                  command=self._host_mega_auto_fix).pack(side=\"left\", padx=(0,8))\n        tk.Button(btn_row_s5, text=\"\ud83d\ude80 CLIENT Mega Auto-Fix\", font=FONTS[\"body\"],\n                  bg=\"#FF6600\", fg=C[\"text\"], bd=0, padx=14, pady=7, cursor=\"hand2\",\n                  command=self._client_mega_auto_fix).pack(side=\"left\")\n\n        tk.Frame(t3_body, bg=C[\"bg\"], height=20).pack()  # bottom padding\n\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # \ud83d\udd34 TAB 4 \u2014 ENTERPRISE PRINTER RECOVERY CENTER\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        tab4 = tk.Frame(nb, bg=C[\"bg\"])\n        nb.add(tab4, text=\"  \ud83d\udd34  Network Printer Recovery  \")\n\n        # \u2500\u2500 Tab4 Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        t4_hdr = tk.Frame(tab4, bg=\"#1A0A0A\")\n        t4_hdr.pack(fill=\"x\")\n        tk.Label(t4_hdr, text=\"  \ud83d\udd34 Enterprise Network Printer Recovery Center\",\n                 font=FONTS[\"subhead\"], fg=\"#FF4444\", bg=\"#1A0A0A\").pack(side=\"left\", pady=4, padx=8)\n        tk.Label(t4_hdr,\n                 text=\"\\\"Windows Couldn't connect to the printer\\\" \u2014 Auto Diagnose &amp; Repair\",\n                 font=FONTS[\"xsmall\"], fg=C[\"text_dim\"], bg=\"#1A0A0A\").pack(side=\"left\", pady=4)\n\n        # \u2500\u2500 FULL AUTO FIX MEGA BUTTON \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        mega_frame = tk.Frame(tab4, bg=\"#2A0A0A\", pady=2)\n        mega_frame.pack(fill=\"x\", padx=8, pady=(3, 2))\n        tk.Label(mega_frame,\n                 text=\"  \u26a1 ONE-CLICK ENTERPRISE RECOVERY \u2014 Diagnose + Repair Everything Automatically\",\n                 font=FONTS[\"xsmall\"], fg=\"#FF9800\", bg=\"#2A0A0A\").pack(anchor=\"w\", padx=8, pady=(2,1))\n        self._epr_full_auto_btn = tk.Button(\n            mega_frame,\n            text=\"\ud83d\ude80  FULL AUTO FIX  \u2014  \\\"Windows Couldn't Connect to Printer\\\"  (All 18 Steps)\",\n            font=(\"Segoe UI\", 10, \"bold\"),\n            bg=\"#C62828\", fg=\"#FFFFFF\",\n            bd=0, padx=12, pady=6,\n            cursor=\"hand2\",\n            command=self._epr_full_auto_fix,\n            activebackground=\"#B71C1C\",\n            activeforeground=\"#FFFFFF\",\n            relief=\"flat\"\n        )\n        self._epr_full_auto_btn.pack(fill=\"x\", padx=8, pady=(1, 3))\n\n        # \u2500\u2500 Progress &amp; Status Bar \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        prog_frame = tk.Frame(tab4, bg=C[\"card\"])\n        prog_frame.pack(fill=\"x\", padx=8, pady=(0, 2))\n        prog_inner = tk.Frame(prog_frame, bg=C[\"card\"])\n        prog_inner.pack(fill=\"x\", padx=8, pady=2)\n        tk.Label(prog_inner, text=\"Status:\", font=FONTS[\"small\"],\n                 fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self.epr_status_lbl = tk.Label(prog_inner, text=\"Ready \u2014 Click FULL AUTO FIX to begin\",\n                                        font=FONTS[\"small\"], fg=C[\"accent4\"], bg=C[\"card\"])\n        self.epr_status_lbl.pack(side=\"left\", padx=6)\n        self.epr_progress = ttk.Progressbar(prog_frame, mode=\"indeterminate\", length=200)\n        self.epr_progress.pack(fill=\"x\", padx=8, pady=(0, 3))\n\n        # \u2500\u2500 Main body: 3-column layout \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        t4_body_outer = tk.Frame(tab4, bg=C[\"bg\"])\n        t4_body_outer.pack(fill=\"both\", expand=True, padx=8, pady=(0, 8))\n        t4_canvas = tk.Canvas(t4_body_outer, bg=C[\"bg\"], highlightthickness=0)\n        t4_vsb = ttk.Scrollbar(t4_body_outer, orient=\"vertical\", command=t4_canvas.yview)\n        t4_canvas.configure(yscrollcommand=t4_vsb.set)\n        t4_vsb.pack(side=\"right\", fill=\"y\")\n        t4_canvas.pack(side=\"left\", fill=\"both\", expand=True)\n        t4_body = tk.Frame(t4_canvas, bg=C[\"bg\"])\n        t4_win = t4_canvas.create_window((0, 0), window=t4_body, anchor=\"nw\")\n\n        def _t4_sc_resize(e):\n            t4_canvas.configure(scrollregion=t4_canvas.bbox(\"all\"))\n            t4_canvas.itemconfig(t4_win, width=t4_canvas.winfo_width())\n        t4_body.bind(\"\", _t4_sc_resize)\n        def _t4_canvas_configure(e):\n            t4_canvas.itemconfig(t4_win, width=e.width)\n            t4_canvas.configure(scrollregion=t4_canvas.bbox(\"all\"))\n        t4_canvas.bind(\"\", _t4_canvas_configure)\n        self._bind_scoped_mousewheel(t4_body, t4_canvas)\n\n        t4_body.columnconfigure(0, weight=1)\n        t4_body.columnconfigure(1, weight=1)\n        t4_body.columnconfigure(2, weight=1)\n\n        # \u2500\u2500 Helper functions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        def _t4_card(parent, title, color_hdr=\"#1A1A2E\"):\n            f = tk.Frame(parent, bg=C[\"card\"], bd=0)\n            h = tk.Frame(f, bg=color_hdr)\n            h.pack(fill=\"x\")\n            tk.Label(h, text=title, font=FONTS[\"subhead\"],\n                     fg=C[\"accent4\"], bg=color_hdr).pack(anchor=\"w\", padx=10, pady=6)\n            return f\n\n        def _t4_btn(parent, text, color, cmd, desc=\"\"):\n            row = tk.Frame(parent, bg=C[\"card\"])\n            row.pack(fill=\"x\", padx=6, pady=2)\n            tk.Button(row, text=text, font=FONTS[\"small\"],\n                      bg=color, fg=C[\"text\"], bd=0, padx=8, pady=5,\n                      cursor=\"hand2\", anchor=\"w\",\n                      command=cmd).pack(side=\"left\", fill=\"x\", expand=True)\n            if desc:\n                tk.Label(row, text=desc, font=(\"Consolas\", 8),\n                         fg=C[\"text_dim\"], bg=C[\"card\"],\n                         anchor=\"w\", wraplength=150).pack(side=\"left\", padx=(4, 2))\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # LEFT COLUMN \u2014 Connectivity &amp; Network\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        left_col = tk.Frame(t4_body, bg=C[\"bg\"])\n        left_col.grid(row=0, column=0, sticky=\"nsew\", padx=(0, 4), pady=4)\n\n        # \u2014 Tester / Validator Card \u2014\n        tester_card = _t4_card(left_col, \"\ud83d\udd0d  Printer Connection Tester\", \"#0D1B2A\")\n        tester_card.pack(fill=\"x\", pady=(0, 6))\n        tester_inner = tk.Frame(tester_card, bg=C[\"card\"])\n        tester_inner.pack(fill=\"x\", padx=8, pady=(4, 2))\n        tk.Label(tester_inner, text=\"Host IP / Name:\", font=FONTS[\"small\"],\n                 fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\")\n        self.epr_host_var = tk.StringVar(value=\"\")\n        tk.Entry(tester_inner, textvariable=self.epr_host_var,\n                 font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"],\n                 insertbackground=C[\"text\"], width=28).pack(fill=\"x\", pady=2)\n        tk.Label(tester_inner, text=\"Share Name:\", font=FONTS[\"small\"],\n                 fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\", pady=(4, 0))\n        self.epr_share_var = tk.StringVar(value=\"\")\n        tk.Entry(tester_inner, textvariable=self.epr_share_var,\n                 font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"],\n                 insertbackground=C[\"text\"], width=28).pack(fill=\"x\", pady=2)\n        tk.Frame(tester_card, bg=C[\"border\"], height=1).pack(fill=\"x\", padx=8, pady=4)\n        _t4_btn(tester_card, \"\ud83d\udd0c  Ping Host PC\",           C[\"btn_chip\"], self._epr_ping_host,        \"ICMP ping test\")\n        _t4_btn(tester_card, \"\ud83d\uddc2  Test SMB Share Access\",  C[\"btn_chip\"], self._epr_test_smb,         \"\\\\\\\\host\\\\share reachability\")\n        _t4_btn(tester_card, \"\ud83d\udda8  Validate Printer Path\",  C[\"btn_chip\"], self._epr_validate_printer, \"UNC printer reachability\")\n        _t4_btn(tester_card, \"\ud83d\udd0c  Reconnect Shared Printer\", C[\"btn_info\"], self._epr_reconnect_shared, \"Auto reconnect + re-install\")\n        tk.Frame(tester_card, bg=C[\"bg\"], height=6).pack()\n\n        # \u2014 Network Share Validator \u2014\n        ns_card = _t4_card(left_col, \"\ud83c\udf10  Network Share Validator\", \"#0A1A1A\")\n        ns_card.pack(fill=\"x\", pady=(0, 6))\n        _t4_btn(ns_card, \"\ud83c\udf10  Network Share Validator\",    C[\"btn_info\"],  self._epr_net_share_validator, \"Validate share existence\")\n        _t4_btn(ns_card, \"\ud83d\udce1  Network Discovery Enable\",   C[\"btn_info\"],  self._epr_enable_netdiscovery, \"Private profile + FD services\")\n        _t4_btn(ns_card, \"\ud83d\udd25  Firewall Sharing Rules Fix\", C[\"btn_warn\"],  self._epr_firewall_fix,        \"F&amp;P sharing rules ON\")\n        tk.Frame(ns_card, bg=C[\"bg\"], height=6).pack()\n\n        # \u2014 Auto-Detection Status Area \u2014\n        det_card = _t4_card(left_col, \"\ud83d\udcca  Auto-Detection Status\", \"#1A2A0A\")\n        det_card.pack(fill=\"x\", pady=(0, 6))\n        self.epr_detect_log = self._scrolled_text(det_card, height=7)\n        _t4_btn(det_card, \"\ud83d\udd0d  Run Auto-Detection\",        C[\"btn_info\"],  self._epr_auto_detect, \"Diagnose root cause\")\n        tk.Frame(det_card, bg=C[\"bg\"], height=6).pack()\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # MIDDLE COLUMN \u2014 Repair Buttons\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        mid_col = tk.Frame(t4_body, bg=C[\"bg\"])\n        mid_col.grid(row=0, column=1, sticky=\"nsew\", padx=(4, 4), pady=4)\n\n        # \u2014 Spooler &amp; RPC \u2014\n        spool_card = _t4_card(mid_col, \"\u2699\ufe0f  Spooler &amp; RPC Repair\", \"#1A0A2E\")\n        spool_card.pack(fill=\"x\", pady=(0, 6))\n        _t4_btn(spool_card, \"\u26a1  Smart Spooler Recovery\",    C[\"btn_hw\"],    self._epr_smart_spooler,    \"Deep spooler + DLL repair\")\n        _t4_btn(spool_card, \"\ud83d\udd27  RPC + SMB Repair\",          C[\"btn_hw\"],    self._epr_rpc_smb_repair,   \"RpcAuthnLevel + SMB fix\")\n        _t4_btn(spool_card, \"\ud83d\uddd1  Printer Cache Cleaner\",      C[\"btn_danger\"], self._epr_cache_cleaner,   \"Corrupted mappings removal\")\n        _t4_btn(spool_card, \"\ud83d\udd04  Full Printer Reset\",         C[\"btn_danger\"], self._epr_full_reset,      \"Nuclear reset + reinstall\")\n        tk.Frame(spool_card, bg=C[\"bg\"], height=6).pack()\n\n        # \u2014 Permissions &amp; Drivers \u2014\n        perm_card = _t4_card(mid_col, \"\ud83d\udd11  Permissions &amp; Drivers\", \"#1A1A0A\")\n        perm_card.pack(fill=\"x\", pady=(0, 6))\n        _t4_btn(perm_card, \"\ud83d\udd11  Shared Printer Permission Repair\", C[\"btn_warn\"], self._epr_permission_repair, \"ACL + GPO permissions\")\n        _t4_btn(perm_card, \"\ud83d\udda8  Point &amp; Print Repair\",             C[\"btn_warn\"], self._epr_point_print_repair, \"NoWarning + restriction fix\")\n        _t4_btn(perm_card, \"\ud83d\udd27  Driver Compatibility Repair\",      C[\"btn_chip\"], self._epr_driver_compat,     \"x86/x64 mismatch fix\")\n        _t4_btn(perm_card, \"\ud83d\udce1  Canon Printer Compatibility Fix\",  C[\"btn_chip\"], self._epr_canon_fix,         \"CNUSB + Canon-specific fix\")\n        tk.Frame(perm_card, bg=C[\"bg\"], height=6).pack()\n\n        # \u2014 Error-Specific Fixes \u2014\n        err_card = _t4_card(mid_col, \"\ud83d\udd34  Error-Specific Repairs\", \"#2A0A0A\")\n        err_card.pack(fill=\"x\", pady=(0, 6))\n        for err_code, err_desc, err_fn in [\n            (\"0x0000011b\", \"RPC Encryption / KB5005565\",   self._epr_fix_11b),\n            (\"0x0000007c\", \"Printer Driver Corrupt\",        self._epr_fix_7c),\n            (\"0x00000709\", \"Default Printer Cannot Set\",    self._epr_fix_709),\n            (\"Access Denied\", \"Printer ACL / Auth Fail\",   self._epr_fix_access_denied),\n            (\"RPC Unavailable\", \"RPC Server Unavailable\",  self._epr_fix_rpc_unavail),\n            (\"Driver Missing\", \"Driver Not Found / Bad\",   self._epr_fix_driver_missing),\n            (\"Path Not Found\", \"Network Path Not Found\",   self._epr_fix_path_not_found),\n        ]:\n            row = tk.Frame(err_card, bg=C[\"card\"])\n            row.pack(fill=\"x\", padx=6, pady=2)\n            tk.Label(row, text=err_code, font=(\"Consolas\", 9, \"bold\"),\n                     fg=C[\"error\"], bg=C[\"card\"], width=14, anchor=\"w\").pack(side=\"left\", padx=(4, 0))\n            tk.Label(row, text=err_desc, font=FONTS[\"small\"],\n                     fg=C[\"text_dim\"], bg=C[\"card\"], anchor=\"w\").pack(side=\"left\", padx=(4, 4))\n            tk.Button(row, text=\"Fix\", font=FONTS[\"small\"],\n                      bg=C[\"btn_danger\"], fg=C[\"text\"], bd=0, padx=10, pady=3,\n                      cursor=\"hand2\", command=err_fn).pack(side=\"right\", padx=4)\n        tk.Frame(err_card, bg=C[\"bg\"], height=6).pack()\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # RIGHT COLUMN \u2014 Live Diagnostics + Repair Log + Summary\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        right_col = tk.Frame(t4_body, bg=C[\"bg\"])\n        right_col.grid(row=0, column=2, sticky=\"nsew\", padx=(4, 0), pady=4)\n\n        # \u2014 Live Diagnostics Panel \u2014\n        diag_card = _t4_card(right_col, \"\ud83d\udce1  Live Diagnostics Panel\", \"#0D2A1A\")\n        diag_card.pack(fill=\"x\", pady=(0, 4))\n        self.epr_diag_log = self._scrolled_text(diag_card, height=8)\n\n        # \u2014 Repair Log Viewer \u2014\n        replog_card = _t4_card(right_col, \"\ud83d\udcdd  Repair Log\", \"#2A1A0A\")\n        replog_card.pack(fill=\"x\", pady=(0, 4))\n        self.epr_repair_log = self._scrolled_text(replog_card, height=6)\n\n        # \u2014 Recovery Summary Viewer \u2014\n        summ_card = _t4_card(right_col, \"\ud83d\udccb  Recovery Summary\", \"#0A1A2A\")\n        summ_card.pack(fill=\"x\", pady=(0, 4))\n        self.epr_summary_log = self._scrolled_text(summ_card, height=4)\n\n        # \u2014 RPC Smart Switcher Panel \u2014\n        rpc_panel = tk.Frame(right_col, bg=\"#1E1A00\")\n        rpc_panel.pack(fill=\"x\", padx=0, pady=(0, 4))\n        hdr_rpc = tk.Frame(rpc_panel, bg=\"#2A2200\")\n        hdr_rpc.pack(fill=\"x\")\n        tk.Label(hdr_rpc, text=\"  \u26a1 Smart RPC Privacy Switcher\",\n                 font=FONTS[\"subhead\"], fg=\"#FFCC00\", bg=\"#2A2200\").pack(side=\"left\", padx=8, pady=6)\n        rpc_info = tk.Frame(rpc_panel, bg=\"#1E1A00\")\n        rpc_info.pack(fill=\"x\", padx=8, pady=4)\n        self.epr_rpc_status_lbl = tk.Label(rpc_info,\n            text=\"RpcAuthnLevelPrivacyEnabled: Checking...\",\n            font=FONTS[\"small\"], fg=C[\"warning\"], bg=\"#1E1A00\")\n        self.epr_rpc_status_lbl.pack(anchor=\"w\")\n        btn_rpc_row = tk.Frame(rpc_panel, bg=\"#1E1A00\")\n        btn_rpc_row.pack(fill=\"x\", padx=8, pady=(0, 6))\n        tk.Button(btn_rpc_row, text=\"\ud83d\udd0d Check RPC Setting\",\n                  font=FONTS[\"small\"], bg=C[\"btn_chip\"], fg=C[\"text\"],\n                  bd=0, padx=10, pady=5, cursor=\"hand2\",\n                  command=self._epr_check_rpc_setting).pack(side=\"left\", padx=(0, 6))\n        tk.Button(btn_rpc_row, text=\"\ud83d\udd27 Smart RPC Fix (Auto Validate + Rollback)\",\n                  font=FONTS[\"small\"], bg=C[\"btn_warn\"], fg=C[\"text\"],\n                  bd=0, padx=10, pady=5, cursor=\"hand2\",\n                  command=self._epr_smart_rpc_fix).pack(side=\"left\")\n        tk.Frame(right_col, bg=C[\"bg\"], height=90).pack(fill=\"x\")\n        self.after(250, lambda c=t4_canvas: c.configure(scrollregion=c.bbox(\"all\")))\n\n\n        return frame\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \u2699 AUTO-FIX: gpedit.msc RPC Setting \u2014 Error 709\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _auto_gpedit_rpc_709(self):\n        \"\"\"Group Policy: Configure RPC \u2192 Named Pipes (for 709 fix).\"\"\"\n        if not messagebox.askyesno(\"\u2699 Auto-Fix: gpedit RPC Setting (Error 709)\",\n                \"Ye setting Group Policy mein auto set hogi:\\n\\n\"\n                \"Path: Computer Config \u2192 Admin Templates \u2192 Printers\\n\"\n                \"Setting: Configure RPC connection settings\\n\"\n                \"Value: Enabled, Protocol: RPC over named pipes\\n\\n\"\n                \"\u26a0 Windows Pro/Enterprise pe hi kaam karta hai.\\n\"\n                \"Windows Home me bhi try karega \u2014 Registry fallback bhi chalega.\\n\\n\"\n                \"Continue karein?\"):\n            return\n        self._sharing_log(\"\u2699 [gpedit] RPC setting fix chal raha hai (Error 709)...\", C[\"accent4\"])\n        self._launch_job(\"gpedit_rpc_fix\", self._do_auto_gpedit_rpc)\n\n    def _auto_gpedit_rpc_11b(self):\n        \"\"\"Group Policy: Configure RPC \u2192 Named Pipes (for 11b fix).\"\"\"\n        if not messagebox.askyesno(\"\u2699 Auto-Fix: gpedit RPC Setting (Error 0x0000011b)\",\n                \"Ye setting Group Policy mein auto set hogi:\\n\\n\"\n                \"Path: Computer Config \u2192 Admin Templates \u2192 Printers\\n\"\n                \"Setting: Configure RPC connection settings\\n\"\n                \"Value: Enabled, Protocol: RPC over named pipes\\n\\n\"\n                \"\u26a0 DONO PCs pe alag-alag run karo \u2014 HOST aur CLIENT dono pe!\\n\"\n                \"Windows Home me bhi try karega \u2014 Registry fallback bhi chalega.\\n\\n\"\n                \"Continue karein?\"):\n            return\n        self._sharing_log(\"\u2699 [gpedit] RPC setting fix chal raha hai (Error 11b)...\", C[\"accent4\"])\n        self._launch_job(\"gpedit_rpc_fix\", self._do_auto_gpedit_rpc)\n\n    def _do_auto_gpedit_rpc(self):\n        \"\"\"\n        Internally Group Policy ki 'Configure RPC connection settings' wali setting\n        Registry ke through set karta hai \u2014 gpedit.msc open kiye bina.\n        HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Printers\\\\RPC\n        RpcUseNamedPipeProtocol = 1  (Named Pipes force karo)\n        ForceKerberosForRpc     = 0  (Kerberos RPC strict band)\n        RpcTcpPort              = 0  (TCP port: 0 = any)\n        AllowEncryptedPrinterRPC= 0  (Encrypted RPC: off)\n        \"\"\"\n        log = self._sharing_log\n        L = C\n        reg_path = r\"SOFTWARE\\Policies\\Microsoft\\Windows NT\\Printers\\RPC\"\n\n        log(\"  [gpedit-auto 1/4] RpcUseNamedPipeProtocol = 1 (Named Pipes)...\", L[\"accent4\"])\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE, reg_path,\n                          \"RpcUseNamedPipeProtocol\", 1, winreg.REG_DWORD)\n            log(\"  \u2705 RpcUseNamedPipeProtocol = 1\", L[\"success\"])\n        except Exception as e:\n            self._run_cmd(f'reg add \"HKLM\\\\{reg_path}\" /v RpcUseNamedPipeProtocol /t REG_DWORD /d 1 /f')\n            log(f\"  \u2705 RpcUseNamedPipeProtocol = 1 (reg cmd, {e})\", L[\"success\"])\n\n        log(\"  [gpedit-auto 2/4] ForceKerberosForRpc = 0 (Kerberos strict band)...\", L[\"accent4\"])\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE, reg_path,\n                          \"ForceKerberosForRpc\", 0, winreg.REG_DWORD)\n            log(\"  \u2705 ForceKerberosForRpc = 0\", L[\"success\"])\n        except Exception as e:\n            self._run_cmd(f'reg add \"HKLM\\\\{reg_path}\" /v ForceKerberosForRpc /t REG_DWORD /d 0 /f')\n            log(f\"  \u2705 ForceKerberosForRpc = 0 (reg cmd)\", L[\"success\"])\n\n        log(\"  [gpedit-auto 3/4] AllowEncryptedPrinterRPC = 0 (Encrypted RPC off)...\", L[\"accent4\"])\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE, reg_path,\n                          \"AllowEncryptedPrinterRPC\", 0, winreg.REG_DWORD)\n            log(\"  \u2705 AllowEncryptedPrinterRPC = 0\", L[\"success\"])\n        except Exception as e:\n            self._run_cmd(f'reg add \"HKLM\\\\{reg_path}\" /v AllowEncryptedPrinterRPC /t REG_DWORD /d 0 /f')\n            log(f\"  \u2705 AllowEncryptedPrinterRPC = 0 (reg cmd)\", L[\"success\"])\n\n        log(\"  [gpedit-auto 4/4] RpcAuthnLevelPrivacyEnabled = 0 (main fix)...\", L[\"accent4\"])\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                          r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                          \"RpcAuthnLevelPrivacyEnabled\", 0, winreg.REG_DWORD)\n            log(\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0\", L[\"success\"])\n        except Exception as e:\n            self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\" /v RpcAuthnLevelPrivacyEnabled /t REG_DWORD /d 0 /f')\n            log(f\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0 (reg cmd)\", L[\"success\"])\n\n        log(\"\u2705 gpedit RPC settings \u2014 auto apply ho gayi!\", L[\"success\"])\n        log(\"   \u25ba Computer restart karo for Group Policy to take full effect.\", L[\"text_dim\"])\n        self.after(0, lambda: messagebox.showinfo(\n            \"\u2705 gpedit Auto-Fix Done!\",\n            \"Group Policy RPC settings apply ho gayi:\\n\\n\"\n            \"  \u2705 RpcUseNamedPipeProtocol = 1  (Named Pipes)\\n\"\n            \"  \u2705 ForceKerberosForRpc     = 0\\n\"\n            \"  \u2705 AllowEncryptedPrinterRPC = 0\\n\"\n            \"  \u2705 RpcAuthnLevelPrivacyEnabled = 0\\n\\n\"\n            \"\u26a0 Agar dono PCs hain to DONO pe run karo.\\n\"\n            \"Computer restart karo for full effect.\"))\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \ud83d\udddd AUTO-FIX: Registry \u2014 RpcAuthnLevelPrivacyEnabled = 0\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _auto_reg_rpcauth_0(self):\n        \"\"\"Registry: HKLM\\\\...\\\\Control\\\\Print \u2192 RpcAuthnLevelPrivacyEnabled = 0\"\"\"\n        self._sharing_log(\"\ud83d\udddd [Registry] RpcAuthnLevelPrivacyEnabled = 0 set kar raha hoon...\", C[\"accent4\"])\n        def _r():\n            try:\n                self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                              r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                              \"RpcAuthnLevelPrivacyEnabled\", 0, winreg.REG_DWORD)\n                self._sharing_log(\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0  \u2190 DONE\", C[\"success\"])\n                self.after(0, lambda: messagebox.showinfo(\n                    \"\u2705 Registry Fix Done!\",\n                    \"Registry set ho gayi:\\n\\n\"\n                    \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\\n\"\n                    \"  RpcAuthnLevelPrivacyEnabled = 0\\n\\n\"\n                    \"\u26a0 DONO PCs pe alag-alag run karo (HOST + CLIENT).\\n\"\n                    \"Phir Spooler restart karo \u2014 button neeche hai.\"))\n            except Exception as e:\n                # cmd fallback\n                out, rc = self._run_cmd(\n                    'reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\" '\n                    '/v RpcAuthnLevelPrivacyEnabled /t REG_DWORD /d 0 /f')\n                if rc == 0:\n                    self._sharing_log(\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0 (reg cmd fallback)\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"\u2705 Done!\", \"Registry fix ho gayi!\\nSpooler restart karo.\"))\n                else:\n                    self._sharing_log(f\"  \u274c Registry set failed: {e} | rc={rc}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", f\"Registry set nahi hua:\\n{e}\\n\\nAdmin mode mein run karo.\"))\n        self._launch_job(\"auto_reg_rpcauth\", _r)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \ud83d\udddd AUTO-FIX: Registry \u2014 LegacyDefaultPrinterMode = 1\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _auto_reg_legacy_default(self):\n        \"\"\"Registry: HKCU\\\\...\\\\Windows \u2192 LegacyDefaultPrinterMode = 1\"\"\"\n        self._sharing_log(\"\ud83d\udddd [Registry] LegacyDefaultPrinterMode = 1 set kar raha hoon...\", C[\"accent4\"])\n        def _r():\n            try:\n                key = winreg.OpenKey(\n                    winreg.HKEY_CURRENT_USER,\n                    r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows\",\n                    0, winreg.KEY_SET_VALUE)\n                winreg.SetValueEx(key, \"LegacyDefaultPrinterMode\", 0, winreg.REG_DWORD, 1)\n                winreg.CloseKey(key)\n                self._sharing_log(\"  \u2705 LegacyDefaultPrinterMode = 1  \u2190 DONE\", C[\"success\"])\n                self.after(0, lambda: messagebox.showinfo(\n                    \"\u2705 Registry Fix Done!\",\n                    \"Registry set ho gayi:\\n\\n\"\n                    \"HKCU\\\\SOFTWARE\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\Windows\\n\"\n                    \"  LegacyDefaultPrinterMode = 1\\n\\n\"\n                    \"Windows ab printer default automatically change nahi karega.\\n\"\n                    \"Spooler restart karo \u2014 button neeche hai.\"))\n            except Exception as e:\n                out, rc = self._run_cmd(\n                    'reg add \"HKCU\\\\SOFTWARE\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\Windows\" '\n                    '/v LegacyDefaultPrinterMode /t REG_DWORD /d 1 /f')\n                if rc == 0:\n                    self._sharing_log(\"  \u2705 LegacyDefaultPrinterMode = 1 (reg cmd fallback)\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"\u2705 Done!\", \"Registry fix ho gayi!\"))\n                else:\n                    self._sharing_log(f\"  \u274c Failed: {e}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", f\"Registry set nahi hua:\\n{e}\"))\n        self._launch_job(\"auto_reg_legacy_default\", _r)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \ud83d\udddd AUTO-FIX: Registry \u2014 UserSelectedDefault DELETE\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _auto_reg_delete_userselected(self):\n        \"\"\"Registry: HKCU\\\\...\\\\Windows \u2192 Delete UserSelectedDefault\"\"\"\n        self._sharing_log(\"\ud83d\udddd [Registry] UserSelectedDefault delete kar raha hoon...\", C[\"accent4\"])\n        def _r():\n            try:\n                key = winreg.OpenKey(\n                    winreg.HKEY_CURRENT_USER,\n                    r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows\",\n                    0, winreg.KEY_SET_VALUE | winreg.KEY_READ)\n                try:\n                    winreg.DeleteValue(key, \"UserSelectedDefault\")\n                    self._sharing_log(\"  \u2705 UserSelectedDefault deleted \u2014 Windows fresh default set karega\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\n                        \"\u2705 Done!\",\n                        \"UserSelectedDefault registry value delete ho gayi!\\n\\n\"\n                        \"Windows ab apne aap fresh default printer set karega.\\n\"\n                        \"Spooler restart karo ya reboot karo.\"))\n                except FileNotFoundError:\n                    self._sharing_log(\"  \u2139 UserSelectedDefault nahi mili \u2014 already clean hai\", C[\"text_dim\"])\n                    self.after(0, lambda: messagebox.showinfo(\"\u2139 Info\",\n                        \"UserSelectedDefault value nahi mili.\\n\"\n                        \"Already clean hai \u2014 koi action zaruri nahi.\"))\n                winreg.CloseKey(key)\n            except Exception as e:\n                self._sharing_log(f\"  \u274c Delete failed: {e}\", C[\"error\"])\n                self.after(0, lambda: messagebox.showerror(\"Error\", f\"Delete nahi hua:\\n{e}\"))\n        self._launch_job(\"auto_reg_delete_userselected\", _r)\n\n    def _printer_detect(self):\n        self._set_status(\"Detecting printers...\", C[\"accent4\"])\n        self._printer_action_submit(\"printer_detect\", self._do_printer_detect)\n\n    def _do_printer_detect(self):\n        out, _ = self._run_cmd(\n            'powershell -Command \"Get-Printer | Select-Object Name,PrinterStatus,Default,JobCount | ConvertTo-Csv -NoTypeInformation\"',\n            timeout=15)\n        rows = []\n        counts = {\"total\":0,\"online\":0,\"offline\":0,\"default\":\"\u2014\"}\n        for line in out.splitlines()[1:]:\n            line = line.strip().replace('\"','')\n            parts = line.split(',')\n            if len(parts) &lt; 4:\n                continue\n            name    = parts[0].strip()\n            status  = parts[1].strip()\n            default = parts[2].strip()\n            jobs    = parts[3].strip()\n            if not name:\n                continue\n            is_online  = status.lower() in (\"normal\",\"0\",\"idle\")\n            is_default = default.lower() == \"true\"\n            status_txt = \"\ud83d\udfe2 Online\" if is_online else \"\ud83d\udd34 Offline\"\n            def_txt    = \"\u2705 Yes\" if is_default else \"\"\n            tag = \"default\" if is_default else (\"online\" if is_online else \"offline\")\n            rows.append(((name, status_txt, def_txt, jobs or \"0\"), tag,\n                         {\"name\":name,\"online\":is_online,\"default\":is_default}))\n            counts[\"total\"] += 1\n            if is_online:\n                counts[\"online\"] += 1\n            else:\n                counts[\"offline\"] += 1\n            if is_default:\n                counts[\"default\"] = name[:18]\n\n        self._printer_data = rows\n\n        def insert():\n            for i in self.printer_tree.get_children():\n                self.printer_tree.delete(i)\n            for row, tag, _ in rows:\n                self.printer_tree.insert(\"\",\"end\", values=row, tags=(tag,))\n            for k,v in counts.items():\n                if k in self.printer_stat_vars:\n                    self.printer_stat_vars[k].set(str(v))\n            self._set_status(f\"Found {counts['total']} printers \u2014 {counts['online']} online, {counts['offline']} offline\", C[\"success\"])\n            self._refresh_spooler_status()\n            self._append_log(self.printer_log, f\"\u2705 Scan complete \u2014 {counts['total']} printers detected\", C[\"success\"])\n        self.after(0, insert)\n\n    def _on_printer_select(self, event=None):\n        sel = self.printer_tree.selection()\n        if not sel or not self._printer_data:\n            return\n        idx = self.printer_tree.index(sel[0])\n        if idx &gt;= len(self._printer_data):\n            return\n        meta = self._printer_data[idx][2]\n        self._append_log(self.printer_log,\n            f\"\u2139 Selected: {meta['name']} \u2014 {'Online' if meta['online'] else 'OFFLINE'}{'  [DEFAULT]' if meta['default'] else ''}\",\n            C[\"accent2\"])\n\n    def _refresh_spooler_status(self):\n        out, _ = self._run_cmd('sc query Spooler', timeout=5)\n        if \"RUNNING\" in out:\n            self.spooler_status_lbl.config(text=\"\u2705 Running\", fg=C[\"success\"])\n        elif \"STOPPED\" in out:\n            self.spooler_status_lbl.config(text=\"\u274c STOPPED\", fg=C[\"error\"])\n        else:\n            self.spooler_status_lbl.config(text=\"\u26a0 Unknown\", fg=C[\"warning\"])\n\n    def _printer_reset_spooler(self):\n        self._printer_action_submit(\"printer_reset_spooler\", self._do_reset_spooler)\n\n    def _do_reset_spooler(self):\n        self._printer_log(\"\u2501\"*50, C[\"border\"])\n        self._printer_log(\"\ud83d\udd01 Spooler restart ho raha hai...\", C[\"accent4\"])\n        # Stop spooler\n        self._run_cmd('net stop spooler /y')\n        self._printer_log(\"  \u23f9 Spooler stopped\", C[\"warning\"])\n        # Also stop dependent services\n        self._run_cmd('net stop \"Print Spooler\" /y')\n        time.sleep(1)\n        # Start spooler\n        self._run_cmd('net start spooler')\n        self._printer_log(\"  \u25b6 Spooler started\", C[\"success\"])\n        # Verify\n        out, _ = self._run_cmd('sc query Spooler')\n        if \"RUNNING\" in out:\n            self._printer_log(\"\u2705 Spooler successfully restarted!\", C[\"success\"])\n        else:\n            self._printer_log(\"\u274c Spooler start nahi hua \u2014 Full Repair try karo.\", C[\"error\"])\n        self.after(0, self._refresh_spooler_status)\n\n    def _printer_clear_jobs(self):\n        if not messagebox.askyesno(\"Clear Print Jobs\",\n                \"Saare stuck print jobs delete ho jaayenge.\\n\"\n                \"Spooler restart hoga.\\nAage badhein?\"):\n            return\n        self._printer_action_submit(\"printer_clear_jobs\", self._do_clear_jobs)\n\n    def _do_clear_jobs(self):\n        self._printer_log(\"\u2501\"*50, C[\"border\"])\n        self._printer_log(\"\ud83d\uddd1 Print jobs clear ho rahe hain...\", C[\"accent4\"])\n        # Stop spooler\n        self._run_cmd('net stop spooler /y')\n        self._printer_log(\"  \u23f9 Spooler stopped\", C[\"warning\"])\n        time.sleep(1)\n        # Delete spool files\n        spool_dir = os.path.join(os.environ.get(\"SYSTEMROOT\",\"C:\\\\Windows\"),\n                                  \"System32\",\"spool\",\"PRINTERS\")\n        deleted = 0\n        if os.path.exists(spool_dir):\n            for f in Path(spool_dir).glob(\"*\"):\n                try:\n                    f.unlink()\n                    deleted += 1\n                except: pass\n        self._printer_log(f\"  \ud83d\uddd1 {deleted} spool files deleted from {spool_dir}\", C[\"warning\"])\n        # Restart spooler\n        self._run_cmd('net start spooler')\n        self._printer_log(\"  \u25b6 Spooler restarted\", C[\"success\"])\n        self._printer_log(\"\u2705 Print queue cleared! Ab print karo.\", C[\"success\"])\n        self.after(0, self._refresh_spooler_status)\n\n    def _printer_full_repair(self):\n        if not messagebox.askyesno(\"\ud83d\udd27 Full Printer Auto-Repair\",\n                \"Ye steps perform hoge:\\n\"\n                \"1. Spooler stop + restart\\n\"\n                \"2. Stuck jobs delete\\n\"\n                \"3. Spooler DLL re-register\\n\"\n                \"4. Firewall rules check\\n\"\n                \"5. Registry default path verify\\n\"\n                \"6. Spooler auto startup set\\n\\n\"\n                \"Aage badhein?\"):\n            return\n        self._printer_action_submit(\"printer_full_repair\", self._do_full_repair)\n\n    def _printer_driver_purge_flow(self):\n        sel = self.printer_tree.selection()\n        if not sel or not self._printer_data:\n            messagebox.showinfo(\"Select Printer\", \"Pehle printer select karo.\")\n            return\n        idx = self.printer_tree.index(sel[0])\n        if idx &gt;= len(self._printer_data):\n            return\n        name = self._printer_data[idx][2][\"name\"]\n        if not messagebox.askyesno(\"Driver Purge/Reinstall\",\n                                   f\"Selected printer:\\n{name}\\n\\n\"\n                                   \"Steps:\\n\"\n                                   \"1) Remove printer\\n\"\n                                   \"2) Remove printer driver\\n\"\n                                   \"3) pnputil cleanup (best-effort)\\n\\n\"\n                                   \"Proceed? (Admin recommended)\"):\n            return\n        self._printer_action_submit(\"printer_driver_purge\", self._do_printer_driver_purge, name)\n\n    def _do_printer_driver_purge(self, printer_name):\n        self._printer_log(\"\u2550\"*52, C[\"border\"])\n        self._printer_log(f\"\ud83e\uddf9 Driver purge starting for: {printer_name}\", C[\"accent4\"])\n        # Detect driver name\n        drv = \"\"\n        out, rc = self._run_cmd(\n            f'powershell -Command \"(Get-Printer -Name \\'{printer_name}\\' -ErrorAction SilentlyContinue).DriverName\"',\n            timeout=15\n        )\n        if rc == 0:\n            drv = (out or \"\").strip().splitlines()[-1].strip()\n        self._printer_log(f\"Driver detected: {drv if drv else 'Unknown'}\", C[\"text_dim\"])\n        # Remove printer\n        out2, rc2 = self._run_cmd(\n            f'powershell -Command \"Remove-Printer -Name \\'{printer_name}\\' -ErrorAction SilentlyContinue\"',\n            timeout=20\n        )\n        self._printer_log(\"\u2705 Printer removed\" if rc2 == 0 else f\"\u26a0 Remove printer rc={rc2}: {out2[:200]}\", C[\"success\"] if rc2 == 0 else C[\"warning\"])\n        # Remove driver\n        if drv:\n            out3, rc3 = self._run_cmd(\n                f'powershell -Command \"Remove-PrinterDriver -Name \\'{drv}\\' -ErrorAction SilentlyContinue\"',\n                timeout=25\n            )\n            self._printer_log(\"\u2705 Driver removed\" if rc3 == 0 else f\"\u26a0 Remove driver rc={rc3}: {out3[:200]}\", C[\"success\"] if rc3 == 0 else C[\"warning\"])\n        # pnputil cleanup (best-effort)\n        out4, rc4 = self._run_cmd('pnputil /enum-drivers', timeout=25)\n        if rc4 == 0 and drv:\n            self._printer_log(\"\u2139 pnputil listed drivers (manual cleanup if needed).\", C[\"text_dim\"])\n        self._printer_log(\"\u2705 Driver purge flow complete. Now reinstall printer driver and add printer again.\", C[\"success\"])\n        self.after(0, self._printer_detect)\n\n    def _do_full_repair(self):\n        self._printer_log(\"\u2550\"*52, C[\"border\"])\n        self._printer_log(\"  \ud83d\udd27 FULL PRINTER AUTO-REPAIR STARTING\", C[\"hw_accent\"])\n        self._printer_log(\"\u2550\"*52, C[\"border\"])\n\n        # Step 1 \u2014 Stop spooler\n        self._printer_log(\"\\n[1/6] Spooler band kar raha hoon...\", C[\"accent4\"])\n        try:\n            self._service_config_checked(\"Spooler\", \"auto\", \"Spooler startup=auto\", self.printer_log)\n        except Exception:\n            pass\n        try:\n            self._service_stop_checked(\"Spooler\", \"Print Spooler\", self.printer_log)\n        except Exception:\n            self._run_cmd('net stop spooler /y')\n        self._printer_log(\"  \u2705 Spooler stopped, startup=auto set\", C[\"success\"])\n\n        # Step 2 \u2014 Clear spool folder\n        self._printer_log(\"\\n[2/6] Stuck print jobs delete kar raha hoon...\", C[\"accent4\"])\n        spool_dir = os.path.join(os.environ.get(\"SYSTEMROOT\",\"C:\\\\Windows\"),\n                                  \"System32\",\"spool\",\"PRINTERS\")\n        deleted = 0\n        for f in Path(spool_dir).glob(\"*\"):\n            try: f.unlink(); deleted += 1\n            except: pass\n        self._printer_log(f\"  \u2705 {deleted} stuck jobs deleted\", C[\"success\"])\n\n        # Step 3 \u2014 Re-register spooler DLLs\n        self._printer_log(\"\\n[3/6] Spooler DLLs re-register kar raha hoon...\", C[\"accent4\"])\n        sys32 = os.path.join(os.environ.get(\"SYSTEMROOT\",\"C:\\\\Windows\"), \"System32\")\n        for dll in [\"spoolsv.exe\",\"localspl.dll\",\"spoolss.dll\",\"win32spl.dll\"]:\n            path = os.path.join(sys32, dll)\n            if os.path.exists(path) and dll.endswith(\".dll\"):\n                self._run_cmd(f'regsvr32 /s \"{path}\"')\n                self._printer_log(f\"  \u2705 Registered: {dll}\", C[\"success\"])\n            elif os.path.exists(path):\n                self._printer_log(f\"  \u2705 Found: {dll}\", C[\"success\"])\n            else:\n                self._printer_log(f\"  \u274c Missing: {dll} \u2014 SFC /scannow try karo\", C[\"error\"])\n\n        # Step 4 \u2014 Firewall rules for printing\n        self._printer_log(\"\\n[4/6] Printer firewall rules check kar raha hoon...\", C[\"accent4\"])\n        for port, proto, name in [\n            (135,\"TCP\",\"RPC\"),\n            (445,\"TCP\",\"SMB\"),\n            (9100,\"TCP\",\"RAW Print\"),\n            (631,\"TCP\",\"IPP Print\"),\n        ]:\n            self._run_cmd(f'netsh advfirewall firewall add rule name=\"GodawariPrint_{name}\" '\n                          f'dir=in action=allow protocol={proto} localport={port} '\n                          f'profile=private,domain')\n            self._printer_log(f\"  \u2705 Port {port}/{proto} ({name}) open\", C[\"success\"])\n\n        # Step 5 \u2014 Registry spool path verify\n        self._printer_log(\"\\n[5/6] Registry spool path verify kar raha hoon...\", C[\"accent4\"])\n        default_spool = spool_dir\n        try:\n            key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,\n                                  r\"SYSTEM\\CurrentControlSet\\Control\\Print\\Printers\",\n                                  0, winreg.KEY_SET_VALUE | winreg.KEY_READ)\n            try:\n                current, _ = winreg.QueryValueEx(key, \"DefaultSpoolDirectory\")\n                if not os.path.exists(current):\n                    winreg.SetValueEx(key, \"DefaultSpoolDirectory\", 0,\n                                      winreg.REG_SZ, default_spool)\n                    self._printer_log(f\"  \u2705 Spool path fixed: {default_spool}\", C[\"success\"])\n                else:\n                    self._printer_log(f\"  \u2705 Spool path OK: {current}\", C[\"success\"])\n            except:\n                self._printer_log(\"  \u2139 Spool path entry not found \u2014 using default\", C[\"text_dim\"])\n            winreg.CloseKey(key)\n        except Exception as e:\n            self._printer_log(f\"  \u26a0 Registry check failed: {e}\", C[\"warning\"])\n\n        # Step 6 \u2014 PrintNightmare mitigation\n        self._printer_log(\"\\n[6/6] PrintNightmare security fix kar raha hoon...\", C[\"accent4\"])\n        self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                      r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                      \"RpcAuthnLevelPrivacyEnabled\", 1, winreg.REG_DWORD)\n        self._printer_log(\"  \u2705 RPC auth level hardened\", C[\"success\"])\n\n        # Start spooler\n        try:\n            self._service_start_checked(\"Spooler\", \"Print Spooler\", self.printer_log)\n        except Exception:\n            self._run_cmd('net start spooler')\n        self._printer_log(\"\\n\u2550\"*52, C[\"border\"])\n        self._printer_log(\"\u2705 FULL REPAIR COMPLETE! Ab printer test karo.\", C[\"success\"])\n        self._printer_log(\"   Agar abhi bhi problem hai \u2014 Driver reinstall karo.\", C[\"text_dim\"])\n        self.after(0, self._refresh_spooler_status)\n\n    def _printer_sfc(self):\n        if not messagebox.askyesno(\"SFC Scan\",\n                \"System File Checker chalega \u2014 Windows files repair karega.\\n\"\n                \"10-15 minute lag sakte hain.\\nAage badhein?\"):\n            return\n        self._printer_log(\"\ud83d\udd0d SFC /scannow chal raha hai...\", C[\"accent4\"])\n        self._printer_action_submit(\"printer_sfc\", self._do_printer_sfc)\n\n    def _do_printer_sfc(self):\n        out, _ = self._run_cmd('sfc /scannow', timeout=900)\n        self._printer_log(out[-300:] if isinstance(out, str) else \"SFC completed.\", C[\"text\"])\n        self._printer_log(\"\u2705 SFC complete\", C[\"success\"])\n\n    def _printer_printnightmare(self):\n        if not messagebox.askyesno(\"PrintNightmare Fix\",\n                \"PrintNightmare vulnerability fix karega:\\n\"\n                \"\u2022 Remote access restrict karega\\n\"\n                \"\u2022 Point and Print disable karega\\n\"\n                \"\u2022 RPC auth harden karega\\nAage badhein?\"):\n            return\n        self._printer_action_submit(\"printer_printnightmare\", self._do_printer_printnightmare)\n\n    def _do_printer_printnightmare(self):\n        self._printer_log(\"\ud83d\udd12 Applying PrintNightmare mitigations...\", C[\"accent4\"])\n        self._run_cmd('reg add \"HKLM/SOFTWARE/Policies/Microsoft/Windows NT/Printers/PointAndPrint\" /v RestrictDriverInstallationToAdministrators /t REG_DWORD /d 1 /f')\n        self._run_cmd('reg add \"HKLM/SOFTWARE/Policies/Microsoft/Windows NT/Printers/PointAndPrint\" /v NoWarningNoElevationOnInstall /t REG_DWORD /d 0 /f')\n        self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                      r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                      \"RpcAuthnLevelPrivacyEnabled\", 1, winreg.REG_DWORD)\n        self._printer_log(\"\u2705 PrintNightmare vulnerability patched!\", C[\"success\"])\n\n    def _printer_troubleshooter(self):\n        self._printer_log(\"\ud83d\udd0d Windows Printer Troubleshooter chal raha hai...\", C[\"accent4\"])\n        self._printer_action_submit(\"printer_troubleshooter\", self._do_printer_troubleshooter)\n\n    def _do_printer_troubleshooter(self):\n        self._run_cmd('msdt.exe /id PrinterDiagnostic')\n        self._printer_log(\"\u2139 Troubleshooter window open hua.\", C[\"text_dim\"])\n\n    def _printer_open_queue(self):\n        sel = self.printer_tree.selection()\n        if sel and self._printer_data:\n            idx = self.printer_tree.index(sel[0])\n            if idx &lt; len(self._printer_data):\n                name = self._printer_data[idx][2][\"name\"]\n                self._run_cmd(f'rundll32 printui.dll,PrintUIEntry /o /n \"{name}\"')\n                return\n        # Open printers &amp; scanners settings\n        self._run_cmd('control printers')\n\n    def _printer_set_default(self):\n        sel = self.printer_tree.selection()\n        if not sel or not self._printer_data:\n            messagebox.showinfo(\"Select Printer\",\"Pehle printer select karo.\")\n            return\n        idx = self.printer_tree.index(sel[0])\n        if idx &gt;= len(self._printer_data):\n            return\n        name = self._printer_data[idx][2][\"name\"]\n        self._printer_action_submit(\"printer_set_default\", self._do_printer_set_default, printer_name=name)\n\n    def _do_printer_set_default(self, printer_name):\n        out, rc = self._run_cmd(\n            f'powershell -Command \"Set-Printer -Name \\'{printer_name}\\' -IsDefault $true\"',\n            timeout=10)\n        if rc == 0:\n            self._printer_log(f\"\u2705 '{printer_name}' default printer set ho gaya!\", C[\"success\"])\n        else:\n            self._run_cmd(f'rundll32 printui.dll,PrintUIEntry /y /n \"{printer_name}\"')\n            self._printer_log(f\"\u2705 '{printer_name}' default set (legacy method)\", C[\"success\"])\n        self._printer_detect()\n\n    def _printer_remove(self):\n        sel = self.printer_tree.selection()\n        if not sel or not self._printer_data:\n            messagebox.showinfo(\"Select Printer\",\"Pehle printer select karo.\")\n            return\n        idx = self.printer_tree.index(sel[0])\n        if idx &gt;= len(self._printer_data):\n            return\n        name = self._printer_data[idx][2][\"name\"]\n        if not messagebox.askyesno(\"Remove Printer\",\n                f\"'{name}' printer remove ho jaayega.\\nAage badhein?\"):\n            return\n        self._printer_action_submit(\"printer_remove\", self._do_printer_remove, printer_name=name)\n\n    def _do_printer_remove(self, printer_name):\n        out, rc = self._run_cmd(\n            f'powershell -Command \"Remove-Printer -Name \\'{printer_name}\\'\"', timeout=10)\n        if rc == 0:\n            self._printer_log(f\"\u2705 '{printer_name}' removed!\", C[\"success\"])\n        else:\n            self._run_cmd(f'rundll32 printui.dll,PrintUIEntry /dl /n \"{printer_name}\"')\n            self._printer_log(f\"\u2705 '{printer_name}' removed (legacy method)\", C[\"success\"])\n        self._printer_detect()\n\n    def _printer_driver_signature_audit(self):\n        self._printer_action_submit(\"printer_driver_signature_audit\", self._do_printer_driver_signature_audit)\n\n    def _do_printer_driver_signature_audit(self):\n        self._printer_log(\"\ud83d\udd0d Collecting printer driver metadata...\", C[\"accent4\"])\n        output, rc = self._run_cmd(\n            'powershell -Command \"Get-PrinterDriver | Select-Object Name,Manufacturer,InfName,Version | ConvertTo-Csv -NoTypeInformation\"',\n            timeout=12)\n        if rc != 0 or not output:\n            self._printer_log(\"\u26a0 Driver audit failed or returned no data.\", C[\"warning\"])\n            return\n        lines = [line.strip() for line in output.splitlines() if line.strip()]\n        self._printer_log(f\"\u2705 {len(lines)-1} driver entries found\", C[\"success\"]) if len(lines) &gt; 1 else self._printer_log(\"\u26a0 No drivers discovered.\", C[\"warning\"])\n        for row in lines[:12]:\n            self._printer_trace(row, C[\"text_dim\"])\n        if len(lines) &gt; 12:\n            self._printer_trace(f\"... and {len(lines)-1-11} more driver records\", C[\"text_dim\"])\n\n    def _printer_spooler_snapshot(self):\n        self._printer_action_submit(\"printer_spooler_snapshot\", self._do_printer_spooler_snapshot)\n\n    def _do_printer_spooler_snapshot(self):\n        self._printer_log(\"\ud83d\udcf8 Capturing spooler and driver snapshot...\", C[\"accent4\"])\n        cfg, rc1 = self._run_cmd('sc qc spooler', timeout=10)\n        self._printer_trace(cfg or \"Unable to read spooler service config.\", C[\"text\"]) \n        driver_info, rc2 = self._run_cmd('pnputil /enum-drivers', timeout=20)\n        drivers = [line for line in (driver_info or \"\").splitlines() if line.strip()]\n        self._printer_log(f\"\u2705 Spooler snapshot captured \u2014 {len(drivers)} driver lines\", C[\"success\"])\n        for line in drivers[:8]:\n            self._printer_trace(line, C[\"text_dim\"])\n        if len(drivers) &gt; 8:\n            self._printer_trace(f\"... and {len(drivers)-8} more lines\", C[\"text_dim\"])\n\n    def _printer_network_setup(self):\n        dlg = tk.Toplevel(self)\n        dlg.title(\"Network Printer Setup\")\n        dlg.geometry(\"480x340\")\n        dlg.configure(bg=C[\"bg\"])\n        dlg.grab_set()\n\n        tk.Label(dlg, text=\"\ud83c\udf10 Network / Shared Printer Setup\",\n                 font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"bg\"]).pack(pady=(16,4))\n\n        info = tk.Frame(dlg, bg=C[\"card\"])\n        info.pack(fill=\"x\", padx=20, pady=6)\n\n        fields = {}\n        for lbl, key, placeholder in [\n            (\"Printer IP / Hostname:\", \"ip\",   \"e.g. 192.168.1.100\"),\n            (\"Share Name (optional):\", \"share\",\"e.g. HP_LaserJet\"),\n            (\"Port Name:\",             \"port\", \"e.g. IP_192.168.1.100\"),\n        ]:\n            row = tk.Frame(info, bg=C[\"card\"])\n            row.pack(fill=\"x\", pady=4)\n            tk.Label(row, text=lbl, font=FONTS[\"body\"], fg=C[\"text\"],\n                     bg=C[\"card\"], width=22, anchor=\"w\").pack(side=\"left\")\n            e = tk.Entry(row, font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"],\n                         insertbackground=C[\"text\"], relief=\"flat\", bd=4, width=24)\n            e.insert(0, placeholder)\n            e.bind(\"\",  lambda ev,p=placeholder,en=e: en.delete(0,\"end\") if en.get()==p else None)\n            e.bind(\"\", lambda ev,p=placeholder,en=e: en.insert(0,p) if not en.get() else None)\n            e.pack(side=\"left\", padx=4)\n            fields[key] = e\n\n        log = scrolledtext.ScrolledText(dlg, height=6, font=FONTS[\"mono\"],\n                                         bg=C[\"bg\"], fg=C[\"text\"], bd=0, state=\"disabled\")\n        log.pack(fill=\"both\", expand=True, padx=20, pady=4)\n\n        def _do_add():\n            ip    = fields[\"ip\"].get().strip()\n            share = fields[\"share\"].get().strip()\n            port  = fields[\"port\"].get().strip() or f\"IP_{ip}\"\n            if not ip or ip.startswith(\"e.g\"):\n                messagebox.showwarning(\"IP Missing\",\"Printer IP enter karo.\", parent=dlg)\n                return\n\n            def _run():\n                def _log(msg, col=C[\"text\"]):\n                    log.config(state=\"normal\")\n                    log.insert(\"end\", msg+\"\\n\")\n                    log.see(\"end\")\n                    log.config(state=\"disabled\")\n\n                _log(f\"Connecting to {ip}...\")\n                # Add TCP/IP port\n                self._run_cmd(\n                    f'powershell -Command \"Add-PrinterPort -Name \\'{port}\\' -PrinterHostAddress \\'{ip}\\'\"',\n                    timeout=10)\n                _log(f\"\u2705 Port {port} added\")\n                # Add printer\n                if share:\n                    cmd = (f'powershell -Command \"Add-Printer -Name \\'Network_{ip}\\' '\n                           f'-DriverName \\'Microsoft Print To PDF\\' -PortName \\'{port}\\'\"')\n                else:\n                    cmd = (f'net use LPT1: \\\\\\\\{ip}\\\\{share} /persistent:yes')\n                out, rc = self._run_cmd(cmd, timeout=15)\n                if rc == 0:\n                    _log(f\"\u2705 Printer added! IP: {ip}\")\n                else:\n                    _log(f\"\u26a0 Auto-add failed. Manually karo:\\n  Control Panel \u2192 Devices \u2192 Add Printer \u2192 Manual \u2192 TCP/IP \u2192 {ip}\")\n                _log(\"Done!\")\n                self.after(0, self._printer_detect)\n\n            self._launch_job(\"printer_add\", _run)\n\n        btn_frame = tk.Frame(dlg, bg=C[\"bg\"])\n        btn_frame.pack(pady=8)\n        self._btn(btn_frame, \"\ud83c\udf10 Add Network Printer\", C[\"btn_info\"], _do_add).pack(side=\"left\", padx=6)\n        self._btn(btn_frame, \"\ud83d\udd0d Ping Printer IP\",     C[\"btn_chip\"],\n                  lambda ip=fields[\"ip\"].get(): self._launch_job(\"printer_ping\", lambda: self._append_log(log, self._run_cmd(f'ping -n 2 {ip}')[0], C[\"text\"])) ).pack(side=\"left\", padx=6)\n        self._btn(btn_frame, \"Close\", C[\"btn_warn\"], dlg.destroy).pack(side=\"left\", padx=6)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \ud83d\udd17 PRINTER SHARING CENTER \u2014 HELPER &amp; STATUS\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _get_hostname(self):\n        try:\n            return platform.node()\n        except:\n            return \"YourHostPC\"\n\n    def _sharing_log(self, msg, col=None):\n        \"\"\"Safe append to sharing_log widget.\"\"\"\n        if col is None:\n            col = C[\"text\"]\n        try:\n            self._append_log(self.sharing_log, msg, col)\n        except Exception:\n            pass\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # INDIVIDUAL PORT OPENERS \u2014 HOST\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _open_single_port_host(self, port, proto_str, name):\n        \"\"\"Open a single port on HOST firewall (IN + OUT).\"\"\"\n        self._sharing_log(f\"\ud83d\udd0c [HOST] Port {port}/{proto_str} ({name}) khol raha hoon...\", C[\"accent4\"])\n        def _r():\n            protos = [\"TCP\",\"UDP\"] if proto_str == \"TCP+UDP\" else [proto_str]\n            for proto in protos:\n                for dirn in [\"in\",\"out\"]:\n                    rule = f\"GodawariHost_{name}_{dirn.upper()}\"\n                    cmd = (f'netsh advfirewall firewall add rule '\n                           f'name=\"{rule}\" dir={dirn} action=allow '\n                           f'protocol={proto} localport={port} profile=any')\n                    _, rc = self._run_cmd(cmd)\n                    self._sharing_log(\n                        f\"  {'\u2705' if rc==0 else '\u26a0'} {port}/{proto} {dirn.upper()} \u2192 {'OK' if rc==0 else 'Already exists / Error'}\",\n                        C[\"success\"] if rc==0 else C[\"warning\"])\n            self._sharing_log(f\"\u2705 Port {port}/{proto_str} ({name}) \u2192 Done!\", C[\"success\"])\n        self._launch_job(f\"open_port_host_{port}_{name}\", _r)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # INDIVIDUAL PORT OPENERS \u2014 CLIENT\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _open_single_port_client(self, port, proto_str, name):\n        \"\"\"Open a single port on CLIENT firewall (IN + OUT).\"\"\"\n        self._sharing_log(f\"\ud83d\udd0c [CLIENT] Port {port}/{proto_str} ({name}) khol raha hoon...\", C[\"accent2\"])\n        def _r():\n            protos = [\"TCP\",\"UDP\"] if proto_str == \"TCP+UDP\" else [proto_str]\n            for proto in protos:\n                for dirn in [\"in\",\"out\"]:\n                    rule = f\"GodawariClient_{name}_{dirn.upper()}\"\n                    cmd = (f'netsh advfirewall firewall add rule '\n                           f'name=\"{rule}\" dir={dirn} action=allow '\n                           f'protocol={proto} localport={port} profile=any')\n                    _, rc = self._run_cmd(cmd)\n                    self._sharing_log(\n                        f\"  {'\u2705' if rc==0 else '\u26a0'} {port}/{proto} {dirn.upper()} \u2192 {'OK' if rc==0 else 'Already exists / Error'}\",\n                        C[\"success\"] if rc==0 else C[\"warning\"])\n            self._sharing_log(f\"\u2705 Port {port}/{proto_str} ({name}) \u2192 Done!\", C[\"success\"])\n        self._launch_job(f\"open_port_client_{port}_{name}\", _r)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # INDIVIDUAL SECURITY ACTIONS \u2014 HOST\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _host_single_security(self, key):\n        \"\"\"Apply one specific HOST security setting.\"\"\"\n        self._sharing_log(f\"\ud83d\udd12 [HOST] Security setting apply kar raha hoon: {key}\", C[\"accent4\"])\n        def _r():\n            if key == \"network_discovery\":\n                self._run_cmd('netsh advfirewall firewall set rule group=\"Network Discovery\" new enable=Yes profile=private')\n                self._sharing_log(\"  \u2705 Network Discovery \u2192 ON (Private profile)\", C[\"success\"])\n            elif key == \"fp_sharing_rules\":\n                self._run_cmd('netsh advfirewall firewall set rule group=\"File and Printer Sharing\" new enable=Yes profile=any')\n                self._sharing_log(\"  \u2705 File &amp; Printer Sharing Rules \u2192 ON (All profiles)\", C[\"success\"])\n            elif key == \"network_private\":\n                self._run_cmd('powershell -Command \"Set-NetConnectionProfile -NetworkCategory Private\"')\n                self._sharing_log(\"  \u2705 Network Profile \u2192 Private\", C[\"success\"])\n            elif key == \"pwd_sharing_off\":\n                self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Lsa\" /v LimitBlankPasswordUse /t REG_DWORD /d 0 /f')\n                self._sharing_log(\"  \u2705 Password Protected Sharing \u2192 OFF (LimitBlankPasswordUse=0)\", C[\"success\"])\n            elif key == \"smb_sign_optional\":\n                self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanServer\\\\Parameters\" /v RequireSecuritySignature /t REG_DWORD /d 0 /f')\n                self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanServer\\\\Parameters\" /v EnableSecuritySignature /t REG_DWORD /d 1 /f')\n                self._sharing_log(\"  \u2705 SMB Server Signing \u2192 Optional (RequireSecuritySignature=0, Enable=1)\", C[\"success\"])\n            elif key == \"fw_private_off\":\n                self._run_cmd('netsh advfirewall set privateprofile state off')\n                self._sharing_log(\"  \u2705 Windows Defender Firewall \u2192 Private profile OFF\", C[\"success\"])\n                self._sharing_log(\"  \u26a0 Sirf trusted/local LAN pe karo!\", C[\"warning\"])\n            elif key == \"allow_ping\":\n                self._run_cmd('netsh advfirewall firewall add rule name=\"GodawariAllowPing_IN\" protocol=ICMPv4 dir=in action=allow')\n                self._run_cmd('netsh advfirewall firewall add rule name=\"GodawariAllowPing_OUT\" protocol=ICMPv4 dir=out action=allow')\n                self._sharing_log(\"  \u2705 ICMPv4 Ping \u2192 Allowed (IN + OUT)\", C[\"success\"])\n            self._sharing_log(f\"\u2705 [HOST] {key} \u2192 Complete!\", C[\"success\"])\n        self._launch_job(f\"host_security_{key}\", _r)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # INDIVIDUAL SECURITY ACTIONS \u2014 CLIENT\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _client_single_security(self, key):\n        \"\"\"Apply one specific CLIENT security setting.\"\"\"\n        self._sharing_log(f\"\ud83d\udd12 [CLIENT] Security setting: {key}\", C[\"accent2\"])\n        def _r():\n            if key == \"network_discovery\":\n                self._run_cmd('netsh advfirewall firewall set rule group=\"Network Discovery\" new enable=Yes profile=private')\n                self._sharing_log(\"  \u2705 Network Discovery \u2192 ON (Private profile)\", C[\"success\"])\n            elif key == \"fp_sharing_rules\":\n                self._run_cmd('netsh advfirewall firewall set rule group=\"File and Printer Sharing\" new enable=Yes profile=any')\n                self._sharing_log(\"  \u2705 File &amp; Printer Sharing Rules \u2192 ON (All profiles)\", C[\"success\"])\n            elif key == \"network_private\":\n                self._run_cmd('powershell -Command \"Set-NetConnectionProfile -NetworkCategory Private\"')\n                self._sharing_log(\"  \u2705 Network Profile \u2192 Private\", C[\"success\"])\n            elif key == \"smb_sign_optional\":\n                self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanWorkstation\\\\Parameters\" /v RequireSecuritySignature /t REG_DWORD /d 0 /f')\n                self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanWorkstation\\\\Parameters\" /v EnableSecuritySignature /t REG_DWORD /d 1 /f')\n                self._sharing_log(\"  \u2705 SMB Client Signing \u2192 Optional (RequireSecuritySignature=0)\", C[\"success\"])\n            elif key == \"point_print\":\n                self._run_cmd('reg add \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Printers\\\\PointAndPrint\" /v NoWarningNoElevationOnInstall /t REG_DWORD /d 1 /f')\n                self._run_cmd('reg add \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Printers\\\\PointAndPrint\" /v UpdatePromptSettings /t REG_DWORD /d 2 /f')\n                self._sharing_log(\"  \u2705 Point &amp; Print \u2192 No Warning, No Elevation on Install\", C[\"success\"])\n            elif key == \"fw_private_off\":\n                self._run_cmd('netsh advfirewall set privateprofile state off')\n                self._sharing_log(\"  \u2705 Windows Defender Firewall \u2192 Private profile OFF (Client)\", C[\"success\"])\n                self._sharing_log(\"  \u26a0 Sirf trusted/local LAN pe karo!\", C[\"warning\"])\n            elif key == \"allow_ping\":\n                self._run_cmd('netsh advfirewall firewall add rule name=\"GodawariClientPing_IN\" protocol=ICMPv4 dir=in action=allow')\n                self._run_cmd('netsh advfirewall firewall add rule name=\"GodawariClientPing_OUT\" protocol=ICMPv4 dir=out action=allow')\n                self._sharing_log(\"  \u2705 ICMPv4 Ping \u2192 Allowed on Client (IN + OUT)\", C[\"success\"])\n            self._sharing_log(f\"\u2705 [CLIENT] {key} \u2192 Complete!\", C[\"success\"])\n        self._launch_job(f\"client_single_reg_{key}\", _r)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # INDIVIDUAL REGISTRY CHANGES \u2014 HOST\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _host_single_reg(self, key):\n        \"\"\"Apply one specific HOST registry change.\"\"\"\n        self._sharing_log(f\"\ud83d\udddd [HOST] Registry: {key}\", C[\"accent4\"])\n        def _r():\n            try:\n                if key == \"AutoShareServer\":\n                    self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                        r\"SYSTEM\\CurrentControlSet\\Services\\LanmanServer\\Parameters\",\n                        \"AutoShareServer\", 1, winreg.REG_DWORD)\n                    self._sharing_log(\"  \u2705 AutoShareServer = 1  (Admin C$,D$ shares ON)\", C[\"success\"])\n                elif key == \"AutoShareWks\":\n                    self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                        r\"SYSTEM\\CurrentControlSet\\Services\\LanmanServer\\Parameters\",\n                        \"AutoShareWks\", 1, winreg.REG_DWORD)\n                    self._sharing_log(\"  \u2705 AutoShareWks = 1  (Workstation shares ON)\", C[\"success\"])\n                elif key == \"IRPStackSize\":\n                    self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                        r\"SYSTEM\\CurrentControlSet\\Services\\LanmanServer\\Parameters\",\n                        \"IRPStackSize\", 20, winreg.REG_DWORD)\n                    self._sharing_log(\"  \u2705 IRPStackSize = 20  (Large network packets fix)\", C[\"success\"])\n                elif key == \"LimitBlankPasswordUse\":\n                    self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                        r\"SYSTEM\\CurrentControlSet\\Control\\Lsa\",\n                        \"LimitBlankPasswordUse\", 0, winreg.REG_DWORD)\n                    self._sharing_log(\"  \u2705 LimitBlankPasswordUse = 0  (Blank password allowed)\", C[\"success\"])\n                elif key == \"DisableWebPrinting\":\n                    self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                        r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                        \"DisableWebPrinting\", 0, winreg.REG_DWORD)\n                    self._sharing_log(\"  \u2705 DisableWebPrinting = 0  (Web printing enabled)\", C[\"success\"])\n                elif key == \"EnableSMB1\":\n                    if messagebox.askyesno(\"SMB1 Enable\",\n                            \"SMB1 enable karna chahte hain?\\n\\n\"\n                            \"\u26a0 Security risk \u2014 sirf XP/Win7 clients ke liye!\\nContinue?\"):\n                        self._run_cmd('powershell -Command \"Set-SmbServerConfiguration -EnableSMB1Protocol $true -Force\"')\n                        self._sharing_log(\"  \u2705 SMB1 Protocol \u2192 Enabled\", C[\"warning\"])\n                self._sharing_log(f\"\u2705 [HOST] {key} \u2192 Done!\", C[\"success\"])\n            except Exception as ex:\n                self._sharing_log(f\"  \u274c {key}: {ex}\", C[\"error\"])\n        self._launch_job(f\"host_single_reg_{key}\", _r)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # INDIVIDUAL REGISTRY CHANGES \u2014 CLIENT\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _client_single_reg(self, key):\n        \"\"\"Apply one specific CLIENT registry change.\"\"\"\n        self._sharing_log(f\"\ud83d\udddd [CLIENT] Registry: {key}\", C[\"accent2\"])\n        def _r():\n            try:\n                if key == \"AllowInsecureGuestAuth\":\n                    self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                        r\"SYSTEM\\CurrentControlSet\\Services\\LanmanWorkstation\\Parameters\",\n                        \"AllowInsecureGuestAuth\", 1, winreg.REG_DWORD)\n                    self._sharing_log(\"  \u2705 AllowInsecureGuestAuth = 1  (Guest share access)\", C[\"success\"])\n                elif key == \"LimitBlankPasswordUse\":\n                    self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                        r\"SYSTEM\\CurrentControlSet\\Control\\Lsa\",\n                        \"LimitBlankPasswordUse\", 0, winreg.REG_DWORD)\n                    self._sharing_log(\"  \u2705 LimitBlankPasswordUse = 0  (Blank password connect)\", C[\"success\"])\n                elif key == \"RequireSecuritySignature\":\n                    self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                        r\"SYSTEM\\CurrentControlSet\\Services\\LanmanWorkstation\\Parameters\",\n                        \"RequireSecuritySignature\", 0, winreg.REG_DWORD)\n                    self._sharing_log(\"  \u2705 RequireSecuritySignature = 0  (SMB signing optional)\", C[\"success\"])\n                elif key == \"PnP_NoWarning\":\n                    self._run_cmd('reg add \"HKLM/SOFTWARE/Policies/Microsoft/Windows NT/Printers/PointAndPrint\" /v NoWarningNoElevationOnInstall /t REG_DWORD /d 1 /f')\n                    self._sharing_log(\"  \u2705 PnP NoWarningNoElevationOnInstall = 1\", C[\"success\"])\n                elif key == \"PnP_UpdatePrompt\":\n                    self._run_cmd('reg add \"HKLM/SOFTWARE/Policies/Microsoft/Windows NT/Printers/PointAndPrint\" /v UpdatePromptSettings /t REG_DWORD /d 2 /f')\n                    self._sharing_log(\"  \u2705 PnP UpdatePromptSettings = 2\", C[\"success\"])\n                elif key == \"PnP_RestrictDriver\":\n                    self._run_cmd('reg add \"HKLM/SOFTWARE/Policies/Microsoft/Windows NT/Printers/PointAndPrint\" /v RestrictDriverInstallationToAdministrators /t REG_DWORD /d 0 /f')\n                    self._sharing_log(\"  \u2705 PnP RestrictDriverInstallationToAdministrators = 0\", C[\"success\"])\n                self._sharing_log(f\"\u2705 [CLIENT] {key} \u2192 Done!\", C[\"success\"])\n            except Exception as ex:\n                self._sharing_log(f\"  \u274c {key}: {ex}\", C[\"error\"])\n        self._launch_job(\"apply_sharing_client_changes\", _r)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # INDIVIDUAL SERVICE STARTER \u2014 HOST/CLIENT SHARED\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _host_single_svc(self, svc_name):\n        \"\"\"Start and set a single service to Auto.\"\"\"\n        svc_display = {\n            \"Spooler\": \"Print Spooler\",\n            \"LanmanServer\": \"Server (File &amp; Printer Sharing)\",\n            \"LanmanWorkstation\": \"Workstation (Network Redirector)\",\n            \"lmhosts\": \"TCP/IP NetBIOS Helper\",\n            \"fdPHost\": \"Function Discovery Provider Host\",\n            \"FDResPub\": \"Function Discovery Resource Publication\",\n            \"SSDPSRV\": \"SSDP Discovery\",\n        }.get(svc_name, svc_name)\n        self._sharing_log(f\"\u2699\ufe0f Service: {svc_display} \u2192 Auto + Start\", C[\"accent4\"])\n        def _r():\n            _, r1 = self._run_cmd(f'sc config \"{svc_name}\" start= auto')\n            _, r2 = self._run_cmd(f'sc start \"{svc_name}\"')\n            ok = r1 == 0 or r2 == 0\n            self._sharing_log(\n                f\"  {'\u2705' if ok else '\u26a0'} {svc_display} \u2192 {'Auto+Started' if ok else 'Check manually'}\",\n                C[\"success\"] if ok else C[\"warning\"])\n        threading.Thread(target=_r, daemon=True).start()\n\n    def _check_sharing_status(self):\n        \"\"\"Quick check: Network Discovery, File Sharing, Spooler, Workgroup.\"\"\"\n        self._sharing_log(\"\u2550\"*56, C[\"border\"])\n        self._sharing_log(\"\ud83d\udd0e Sharing Status Check chal raha hai...\", C[\"accent4\"])\n        self._launch_job(\"check_sharing_status\", self._do_check_sharing_status)\n\n    def _do_check_sharing_status(self):\n        # Spooler\n        out, _ = self._run_cmd('sc query spooler')\n        running = \"running\" in out.lower()\n        self._sharing_log(f\"  {'\u2705' if running else '\u274c'} Print Spooler: {'Running' if running else 'Stopped'}\",\n                          C[\"success\"] if running else C[\"error\"])\n\n        # Server / LanmanServer\n        out2, _ = self._run_cmd('sc query lanmanserver')\n        srv = \"running\" in out2.lower()\n        self._sharing_log(f\"  {'\u2705' if srv else '\u274c'} LanmanServer (File Sharing): {'Running' if srv else 'Stopped'}\",\n                          C[\"success\"] if srv else C[\"error\"])\n\n        # Workgroup\n        out3, _ = self._run_cmd('wmic computersystem get Workgroup /value')\n        wg = out3.strip().replace(\"Workgroup=\",\"\").strip()\n        self._sharing_log(f\"  \u2139 Workgroup: {wg if wg else 'Unknown'}\", C[\"text_dim\"])\n\n        # Computer Name + IP\n        out4, _ = self._run_cmd('ipconfig')\n        for line in out4.splitlines():\n            if \"IPv4\" in line and \"169.\" not in line:\n                self._sharing_log(f\"  \u2139 {line.strip()}\", C[\"text_dim\"])\n                break\n\n        # Firewall File &amp; Printer Sharing state\n        out5, _ = self._run_cmd('netsh advfirewall firewall show rule name=\"File and Printer Sharing (SMB-In)\"')\n        enabled_fw = \"enabled\" in out5.lower()\n        self._sharing_log(\n            f\"  {'\u2705' if enabled_fw else '\u26a0'} Firewall F&amp;P Rule: {'Enabled' if enabled_fw else 'Disabled/Missing'}\",\n            C[\"success\"] if enabled_fw else C[\"warning\"])\n\n        # Printer sharing via PowerShell\n        out6, _ = self._run_cmd(\n            'powershell -Command \"Get-Printer | Select-Object Name,Shared,ShareName | ConvertTo-Csv -NoTypeInformation\"',\n            timeout=10)\n        any_shared = False\n        for line in out6.splitlines()[1:]:\n            parts = line.strip().replace('\"','').split(',')\n            if len(parts) &gt;= 2 and parts[1].strip().lower() == \"true\":\n                any_shared = True\n                self._sharing_log(\n                    f\"  \u2705 Shared Printer: {parts[0].strip()}  \u2192  ShareName: {parts[2].strip() if len(parts)&gt;2 else '\u2014'}\",\n                    C[\"success\"])\n        if not any_shared:\n            self._sharing_log(\"  \u26a0 Koi printer shared nahi hai! Host pe Auto-Share button chalao.\", C[\"warning\"])\n\n        self._sharing_log(\"\u2705 Status check complete!\", C[\"success\"])\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \ud83d\udda5 HOST COMPUTER \u2014 PRINTER SHARING METHODS\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _host_open_ports(self):\n        if not messagebox.askyesno(\"Host: Port Fix\",\n                \"HOST computer pe ye ports open honge:\\n\\n\"\n                \"\u2022 445 TCP/UDP  \u2014 SMB File &amp; Printer Sharing\\n\"\n                \"\u2022 139 TCP      \u2014 NetBIOS Session Service\\n\"\n                \"\u2022 137 UDP      \u2014 NetBIOS Name Service\\n\"\n                \"\u2022 138 UDP      \u2014 NetBIOS Datagram Service\\n\"\n                \"\u2022 135 TCP      \u2014 RPC Endpoint Mapper\\n\"\n                \"\u2022 9100 TCP     \u2014 RAW Print Port\\n\"\n                \"\u2022 631  TCP     \u2014 IPP Print\\n\\n\"\n                \"\u26a0 Sirf private/trusted network pe karo!\\nContinue karein?\"):\n            return\n        self._sharing_log(\"\u2550\"*56, C[\"border\"])\n        self._sharing_log(\"\ud83d\udd0c [HOST] Printer ports khol raha hoon...\", C[\"accent4\"])\n        self._launch_job(\"host_open_ports\", self._do_host_open_ports)\n\n    def _do_host_open_ports(self):\n        ports = [\n            (445,  \"TCP\", \"SMB-Print-TCP\"),\n            (445,  \"UDP\", \"SMB-Print-UDP\"),\n            (139,  \"TCP\", \"NetBIOS-Session\"),\n            (137,  \"UDP\", \"NetBIOS-Name\"),\n            (138,  \"UDP\", \"NetBIOS-Datagram\"),\n            (135,  \"TCP\", \"RPC-Endpoint\"),\n            (9100, \"TCP\", \"RAW-Print\"),\n            (631,  \"TCP\", \"IPP-Print\"),\n        ]\n        for port, proto, name in ports:\n            cmd_in = (f'netsh advfirewall firewall add rule '\n                      f'name=\"GodawariShare_{name}_IN\" '\n                      f'dir=in action=allow protocol={proto} '\n                      f'localport={port} profile=any')\n            _, rc = self._run_cmd(cmd_in)\n            cmd_out = (f'netsh advfirewall firewall add rule '\n                       f'name=\"GodawariShare_{name}_OUT\" '\n                       f'dir=out action=allow protocol={proto} '\n                       f'localport={port} profile=any')\n            self._run_cmd(cmd_out)\n            sym = \"\u2705\" if rc == 0 else \"\u26a0\"\n            self._sharing_log(\n                f\"  {sym} Port {port}/{proto} ({name}) \u2192 IN+OUT opened\",\n                C[\"success\"] if rc == 0 else C[\"warning\"])\n\n        # Enable predefined Windows rule group\n        self._run_cmd(\n            'netsh advfirewall firewall set rule '\n            'group=\"File and Printer Sharing\" new enable=Yes profile=any')\n        self._sharing_log(\"  \u2705 Windows 'File and Printer Sharing' rule group \u2192 ON\", C[\"success\"])\n        self._sharing_log(\"\u2705 [HOST] All printer sharing ports opened!\", C[\"success\"])\n\n    def _host_security_fix(self):\n        if not messagebox.askyesno(\"Host: Security &amp; Firewall Fix\",\n                \"HOST security changes honge:\\n\\n\"\n                \"\u2022 Network Discovery \u2192 Enable (Private profile)\\n\"\n                \"\u2022 File &amp; Printer Sharing firewall rules \u2192 ON\\n\"\n                \"\u2022 Network profile \u2192 Private\\n\"\n                \"\u2022 SMB security signature \u2192 Optional\\n\"\n                \"\u2022 Password Protected Sharing \u2192 aapki choice\\n\\n\"\n                \"Continue karein?\"):\n            return\n        pwd_off = messagebox.askyesno(\"Password Protected Sharing\",\n            \"Password Protected Sharing BAND karna chahte hain?\\n\\n\"\n            \"\u2705 YES = Band karo (Client bina password connect kar sake)\\n\"\n            \"\u274c NO  = On rehne do (Zyada secure)\")\n        self._sharing_log(\"\u2550\"*56, C[\"border\"])\n        self._sharing_log(\"\ud83d\udd12 [HOST] Security &amp; Firewall fix chal raha hai...\", C[\"accent4\"])\n        self._launch_job(\"host_security_fix\", lambda: self._do_host_security_fix(pwd_off))\n\n    def _do_host_security_fix(self, disable_pwd_sharing):\n        # Network Discovery \u2014 private\n        self._run_cmd('netsh advfirewall firewall set rule group=\"Network Discovery\" new enable=Yes profile=private')\n        self._sharing_log(\"  \u2705 Network Discovery \u2192 ON (Private)\", C[\"success\"])\n\n        # File &amp; Printer Sharing \u2014 all profiles\n        self._run_cmd('netsh advfirewall firewall set rule group=\"File and Printer Sharing\" new enable=Yes profile=any')\n        self._sharing_log(\"  \u2705 File &amp; Printer Sharing rules \u2192 ON (All profiles)\", C[\"success\"])\n\n        # Network profile \u2192 Private\n        self._run_cmd('powershell -Command \"Set-NetConnectionProfile -NetworkCategory Private\"')\n        self._sharing_log(\"  \u2705 Network profile \u2192 Private\", C[\"success\"])\n\n        # Password protected sharing\n        val = 0 if disable_pwd_sharing else 1\n        self._run_cmd(\n            f'reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Lsa\" '\n            f'/v LimitBlankPasswordUse /t REG_DWORD /d {val} /f')\n        self._sharing_log(\n            f\"  \u2705 Password Protected Sharing \u2192 {'OFF' if disable_pwd_sharing else 'ON (unchanged)'}\",\n            C[\"success\"])\n\n        # SMB server signature \u2014 optional (not required)\n        self._run_cmd(\n            'reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanServer\\\\Parameters\" '\n            '/v RequireSecuritySignature /t REG_DWORD /d 0 /f')\n        self._run_cmd(\n            'reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanServer\\\\Parameters\" '\n            '/v EnableSecuritySignature /t REG_DWORD /d 1 /f')\n        self._sharing_log(\"  \u2705 SMB signature \u2192 Optional (not required)\", C[\"success\"])\n\n        self._sharing_log(\"\u2705 [HOST] Security fix complete!\", C[\"success\"])\n\n    def _host_registry_fix(self):\n        if not messagebox.askyesno(\"Host: Registry Changes\",\n                \"HOST ke liye ye registry changes honge:\\n\\n\"\n                \"\u2022 AutoShareServer = 1 (admin shares enable)\\n\"\n                \"\u2022 AutoShareWks   = 1 (workstation shares)\\n\"\n                \"\u2022 IRPStackSize   = 20 (large network packets)\\n\"\n                \"\u2022 LimitBlankPasswordUse = 0\\n\"\n                \"\u2022 DisableWebPrinting    = 0\\n\"\n                \"\u2022 SMB1 status check (aapki marzi)\\n\\n\"\n                \"\u26a0 Registry badlega \u2014 seedha asar padega!\\nContinue karein?\"):\n            return\n        self._sharing_log(\"\u2550\"*56, C[\"border\"])\n        self._sharing_log(\"\ud83d\udddd [HOST] Registry changes apply kar raha hoon...\", C[\"accent4\"])\n        self._launch_job(\"host_registry_fix\", self._do_host_registry_fix)\n\n    def _do_host_registry_fix(self):\n        changes = [\n            (winreg.HKEY_LOCAL_MACHINE,\n             r\"SYSTEM\\CurrentControlSet\\Services\\LanmanServer\\Parameters\",\n             \"AutoShareServer\", 1, winreg.REG_DWORD),\n            (winreg.HKEY_LOCAL_MACHINE,\n             r\"SYSTEM\\CurrentControlSet\\Services\\LanmanServer\\Parameters\",\n             \"AutoShareWks\", 1, winreg.REG_DWORD),\n            (winreg.HKEY_LOCAL_MACHINE,\n             r\"SYSTEM\\CurrentControlSet\\Services\\LanmanServer\\Parameters\",\n             \"IRPStackSize\", 20, winreg.REG_DWORD),\n            (winreg.HKEY_LOCAL_MACHINE,\n             r\"SYSTEM\\CurrentControlSet\\Control\\Lsa\",\n             \"LimitBlankPasswordUse\", 0, winreg.REG_DWORD),\n            (winreg.HKEY_LOCAL_MACHINE,\n             r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n             \"DisableWebPrinting\", 0, winreg.REG_DWORD),\n        ]\n        for hive, path, name, val, typ in changes:\n            try:\n                self._reg_set(hive, path, name, val, typ)\n                self._sharing_log(f\"  \u2705 {name} = {val}\", C[\"success\"])\n            except Exception as e:\n                self._sharing_log(f\"  \u26a0 {name}: {e}\", C[\"warning\"])\n\n        # SMB1 check\n        out, _ = self._run_cmd(\n            'powershell -Command \"(Get-SmbServerConfiguration).EnableSMB1Protocol\"',\n            timeout=10)\n        smb1_on = out.strip().lower() == \"true\"\n        self._sharing_log(\n            f\"  \u2139 SMB1 currently: {'Enabled' if smb1_on else 'Disabled'}\",\n            C[\"text_dim\"])\n        if not smb1_on:\n            def ask_smb1():\n                if messagebox.askyesno(\"SMB1 Protocol\",\n                        \"SMB1 abhi BAND hai.\\n\\n\"\n                        \"Purane clients (Windows XP/7) ke liye SMB1 chahiye.\\n\"\n                        \"Enable karein?\\n\\n\"\n                        \"\u26a0 Security risk \u2014 sirf trusted/local network pe karo!\"):\n                    self._run_cmd(\n                        'powershell -Command \"Set-SmbServerConfiguration -EnableSMB1Protocol $true -Force\"')\n                    self._sharing_log(\"  \u2705 SMB1 \u2192 Enabled\", C[\"success\"])\n                else:\n                    self._sharing_log(\"  \u2139 SMB1 \u2192 Unchanged (Disabled)\", C[\"text_dim\"])\n            self.after(0, ask_smb1)\n\n        self._sharing_log(\"\u2705 [HOST] Registry changes complete!\", C[\"success\"])\n        self._sharing_log(\"   \u26a0 Restart karna recommended hai.\", C[\"warning\"])\n\n    def _host_enable_services(self):\n        if not messagebox.askyesno(\"Host: Enable Sharing Services\",\n                \"Ye services start + Auto hogi HOST pe:\\n\\n\"\n                \"\u2022 Spooler          \u2014 Print queue manager\\n\"\n                \"\u2022 LanmanServer     \u2014 Network shares provide karta hai\\n\"\n                \"\u2022 LanmanWorkstation \u2014 SMB client\\n\"\n                \"\u2022 lmhosts          \u2014 TCP/IP NetBIOS Helper\\n\"\n                \"\u2022 fdPHost          \u2014 Function Discovery Host\\n\"\n                \"\u2022 FDResPub         \u2014 Network resource publishing\\n\"\n                \"\u2022 SSDPSRV          \u2014 SSDP Discovery\\n\"\n                \"\u2022 upnphost         \u2014 UPnP\\n\"\n                \"\u2022 Dnscache         \u2014 DNS Client\\n\\n\"\n                \"Continue karein?\"):\n            return\n        self._sharing_log(\"\u2550\"*56, C[\"border\"])\n        self._sharing_log(\"\ud83c\udfe0 [HOST] Sharing services enable kar raha hoon...\", C[\"accent4\"])\n        self._launch_job(\"host_enable_services\", self._do_host_enable_services)\n\n    def _do_host_enable_services(self):\n        services = [\n            (\"Spooler\",            \"Print Spooler\"),\n            (\"LanmanServer\",       \"Server (File Sharing)\"),\n            (\"LanmanWorkstation\",  \"Workstation\"),\n            (\"lmhosts\",            \"TCP/IP NetBIOS Helper\"),\n            (\"fdPHost\",            \"Function Discovery Host\"),\n            (\"FDResPub\",           \"Function Discovery Resource Publication\"),\n            (\"SSDPSRV\",            \"SSDP Discovery\"),\n            (\"upnphost\",           \"UPnP Device Host\"),\n            (\"Dnscache\",           \"DNS Client\"),\n        ]\n        for svc, display in services:\n            self._run_cmd(f'sc config {svc} start= auto')\n            out, rc = self._run_cmd(f'net start {svc}')\n            ok = rc == 0 or \"already\" in out.lower() or \"started\" in out.lower()\n            self._sharing_log(\n                f\"  {'\u2705' if ok else '\u26a0'} {display} ({svc}) \u2192 Auto + Started\",\n                C[\"success\"] if ok else C[\"warning\"])\n        self._sharing_log(\"\u2705 [HOST] All sharing services enabled!\", C[\"success\"])\n\n    def _host_auto_share(self):\n        \"\"\"Auto-share selected printer from HOST + open Windows confirmation.\"\"\"\n        sel = self.printer_tree.selection()\n        if not sel or not self._printer_data:\n            messagebox.showinfo(\"Printer Select Karo\",\n                \"Pehle printer list mein se printer click karke select karo,\\n\"\n                \"phir 'Auto-Share' button dabao.\")\n            return\n        idx = self.printer_tree.index(sel[0])\n        if idx &gt;= len(self._printer_data):\n            return\n        printer_name = self._printer_data[idx][2][\"name\"]\n        share_name   = printer_name.replace(\" \", \"_\")[:20]\n\n        if not messagebox.askyesno(\"Host: Auto-Share Printer\",\n                f\"Printer:    {printer_name}\\n\"\n                f\"Share Name: {share_name}\\n\\n\"\n                \"Ye automatically share ho jaayega.\\n\"\n                \"Firewall rules bhi enable honge.\\n\"\n                \"Sharing hone ke baad Windows confirmation window\\n\"\n                \"aur Printer Properties khud khul jaayengi.\\n\\n\"\n                \"Continue karein?\"):\n            return\n        self._sharing_log(\"\u2550\"*56, C[\"border\"])\n        self._sharing_log(\n            f\"\ud83d\udce4 [HOST] '{printer_name}' ko share kar raha hoon \u2192 ShareName: '{share_name}'\",\n            C[\"accent4\"])\n        self._launch_job(\"host_auto_share\", lambda: self._do_host_auto_share(printer_name, share_name))\n\n    def _do_host_auto_share(self, printer_name, share_name):\n        # 1) Ensure spooler running\n        self._run_cmd('net start spooler')\n        self._sharing_log(\"  \u2705 Spooler started\", C[\"success\"])\n\n        # 2) Enable firewall rules\n        self._run_cmd(\n            'netsh advfirewall firewall set rule '\n            'group=\"File and Printer Sharing\" new enable=Yes profile=any')\n        self._sharing_log(\"  \u2705 File &amp; Printer Sharing firewall \u2192 ON\", C[\"success\"])\n\n        # 3) Share via PowerShell (primary)\n        out, rc = self._run_cmd(\n            f'powershell -Command \"Set-Printer -Name \\'{printer_name}\\' '\n            f'-Shared $true -ShareName \\'{share_name}\\'\"',\n            timeout=15)\n        if rc == 0:\n            self._sharing_log(\n                f\"  \u2705 '{printer_name}' shared as '{share_name}' (PowerShell)\", C[\"success\"])\n        else:\n            # Fallback: rundll32\n            self._run_cmd(\n                f'rundll32 printui.dll,PrintUIEntry /Xs /n \"{printer_name}\" '\n                f'attributes +shared sharename \"{share_name}\"',\n                timeout=10)\n            self._sharing_log(\n                f\"  \u2705 Shared via legacy method (rundll32)\", C[\"success\"])\n\n        # 4) Restart spooler to apply\n        self._run_cmd('net stop spooler /y')\n        time.sleep(1)\n        self._run_cmd('net start spooler')\n        self._sharing_log(\"  \u2705 Spooler restarted \u2014 sharing active\", C[\"success\"])\n\n        # 5) Open Windows confirmation automatically\n        hostname = self._get_hostname()\n        unc_path = f\"\\\\\\\\{hostname}\\\\{share_name}\"\n\n        def _open_confirmation():\n            # Open Printers &amp; Scanners control panel\n            subprocess.Popen([\"control.exe\", \"printers\"], shell=False)\n            time.sleep(1)\n            # Open Printer Properties (sharing tab visible)\n            try:\n                subprocess.Popen(\n                    [\"rundll32.exe\", \"printui.dll,PrintUIEntry\", \"/p\", \"/n\", printer_name],\n                    shell=False)\n            except Exception:\n                pass\n            # Final confirmation dialog\n            messagebox.showinfo(\n                \"\ud83c\udf89 Printer Sharing Complete!\",\n                f\"\u2705 Printer successfully shared!\\n\\n\"\n                f\"Printer Name : {printer_name}\\n\"\n                f\"Share Name   : {share_name}\\n\"\n                f\"UNC Path     : {unc_path}\\n\"\n                f\"Host PC      : {hostname}\\n\\n\"\n                f\"Client computers isko iss address se connect kar sakte hain:\\n\"\n                f\"  {unc_path}\\n\\n\"\n                \"Printers window aur Printer Properties\\n\"\n                \"ab khul gaye hain \u2014 Sharing tab check karo. \u2705\")\n            self._sharing_log(\n                f\"\u2705 [HOST] SHARING CONFIRMED!  UNC: {unc_path}\", C[\"success\"])\n\n        self.after(0, _open_confirmation)\n        self.after(500, self._printer_detect)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \ud83d\udd34 ERROR 0x0000709 \u2014 AUTO-FIX  (HOST)\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _fix_error_709_host(self):\n        \"\"\"Error 0x0000709 fix: HOST side \u2014 default printer registry + spooler + RPC.\"\"\"\n        if not messagebox.askyesno(\"Fix Error 0x0000709 \u2014 HOST\",\n                \"Error 0x0000709 matlab:\\n\"\n                \"  'Operation could not be completed \u2014 default printer cannot be set'\\n\\n\"\n                \"HOST pe ye fixes honge:\\n\"\n                \"  1. Spooler stop \u2192 spool folder clean \u2192 restart\\n\"\n                \"  2. UserSelectedDefault registry fix\\n\"\n                \"  3. DefaultSpoolDirectory path verify\\n\"\n                \"  4. Spooler DLLs re-register (localspl, spoolss, win32spl)\\n\"\n                \"  5. RPC service verify\\n\"\n                \"  6. Windows 'Manage my default printer' feature disable\\n\"\n                \"  7. Spooler startup = Auto forced\\n\\n\"\n                \"Continue karein?\"):\n            return\n        self._sharing_log(\"\u2550\"*56, C[\"border\"])\n        self._sharing_log(\"\ud83d\udd34 [HOST] Error 0x0000709 fix chal raha hai...\", C[\"error\"])\n        self._launch_job(\"fix_error_709_host\", self._do_fix_error_709_host)\n\n    def _do_fix_error_709_host(self):\n        log = self._sharing_log\n        L = C\n\n        # Step 1 \u2014 Spooler stop + spool clean + restart\n        log(\"  [1/7] Spooler stop + spool clean...\", L[\"accent4\"])\n        self._run_cmd('net stop spooler /y')\n        time.sleep(1)\n        spool_dir = os.path.join(os.environ.get(\"SYSTEMROOT\",\"C:\\\\Windows\"),\n                                  \"System32\",\"spool\",\"PRINTERS\")\n        deleted = 0\n        for f in Path(spool_dir).glob(\"*\"):\n            try: f.unlink(); deleted += 1\n            except: pass\n        log(f\"  \u2705 {deleted} spool files deleted\", L[\"success\"])\n\n        # Step 2 \u2014 UserSelectedDefault registry\n        log(\"  [2/7] UserSelectedDefault registry fix...\", L[\"accent4\"])\n        try:\n            key = winreg.OpenKey(\n                winreg.HKEY_CURRENT_USER,\n                r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows\",\n                0, winreg.KEY_SET_VALUE | winreg.KEY_READ)\n            try:\n                winreg.DeleteValue(key, \"UserSelectedDefault\")\n                log(\"  \u2705 UserSelectedDefault removed (will auto-rebuild)\", L[\"success\"])\n            except FileNotFoundError:\n                log(\"  \u2139 UserSelectedDefault not found \u2014 OK\", L[\"text_dim\"])\n            winreg.CloseKey(key)\n        except Exception as e:\n            log(f\"  \u26a0 UserSelectedDefault: {e}\", L[\"warning\"])\n\n        # Also clear Device registry stale default\n        try:\n            key2 = winreg.OpenKey(\n                winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\\Printers\",\n                0, winreg.KEY_SET_VALUE | winreg.KEY_READ)\n            try:\n                winreg.DeleteValue(key2, \"DefaultSpoolDirectory\")\n            except: pass\n            winreg.CloseKey(key2)\n        except: pass\n\n        # Step 3 \u2014 DefaultSpoolDirectory path set correct\n        log(\"  [3/7] DefaultSpoolDirectory path verify + fix...\", L[\"accent4\"])\n        try:\n            key3 = winreg.OpenKey(\n                winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\\Printers\",\n                0, winreg.KEY_SET_VALUE)\n            winreg.SetValueEx(key3, \"DefaultSpoolDirectory\", 0,\n                              winreg.REG_SZ, spool_dir)\n            winreg.CloseKey(key3)\n            log(f\"  \u2705 DefaultSpoolDirectory = {spool_dir}\", L[\"success\"])\n        except Exception as e:\n            log(f\"  \u26a0 Spool dir registry: {e}\", L[\"warning\"])\n\n        # Step 4 \u2014 Re-register spooler DLLs\n        log(\"  [4/7] Spooler DLLs re-register...\", L[\"accent4\"])\n        sys32 = os.path.join(os.environ.get(\"SYSTEMROOT\",\"C:\\\\Windows\"), \"System32\")\n        for dll in [\"localspl.dll\",\"spoolss.dll\",\"win32spl.dll\",\"inetpp.dll\"]:\n            path = os.path.join(sys32, dll)\n            if os.path.exists(path):\n                self._run_cmd(f'regsvr32 /s \"{path}\"')\n                log(f\"  \u2705 Registered: {dll}\", L[\"success\"])\n\n        # Step 5 \u2014 RPC service running\n        log(\"  [5/7] RPC service verify...\", L[\"accent4\"])\n        self._run_cmd('sc config RpcSs start= auto')\n        self._run_cmd('sc start RpcSs')\n        out, _ = self._run_cmd('sc query RpcSs')\n        log(\"  \u2705 RPC: Running\" if \"RUNNING\" in out else \"  \u26a0 RPC: Check manually\", L[\"success\"] if \"RUNNING\" in out else L[\"warning\"])\n\n        # Step 6 \u2014 \"Let Windows manage my default printer\" OFF\n        log(\"  [6/7] Windows auto-default printer feature \u2192 OFF...\", L[\"accent4\"])\n        try:\n            key4 = winreg.OpenKey(\n                winreg.HKEY_CURRENT_USER,\n                r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows\",\n                0, winreg.KEY_SET_VALUE)\n            winreg.SetValueEx(key4, \"LegacyDefaultPrinterMode\", 0, winreg.REG_DWORD, 1)\n            winreg.CloseKey(key4)\n            log(\"  \u2705 LegacyDefaultPrinterMode = 1 (Windows auto-manage OFF)\", L[\"success\"])\n        except Exception as e:\n            log(f\"  \u26a0 LegacyDefaultPrinterMode: {e}\", L[\"warning\"])\n\n        # Step 7 \u2014 Spooler auto + restart\n        log(\"  [7/7] Spooler startup = Auto + Start...\", L[\"accent4\"])\n        self._run_cmd('sc config Spooler start= auto')\n        self._run_cmd('net start spooler')\n        time.sleep(1)\n        out2, _ = self._run_cmd('sc query Spooler')\n        if \"RUNNING\" in out2:\n            log(\"  \u2705 Spooler: Running!\", L[\"success\"])\n        else:\n            log(\"  \u26a0 Spooler start nahi hua \u2014 Full Repair try karo\", L[\"warning\"])\n\n        log(\"\", L[\"text\"])\n        log(\"\u2705 [HOST] Error 0x0000709 FIX COMPLETE!\", L[\"success\"])\n        log(\"   \u25ba Ab printer detect karo aur default set karo.\", L[\"text_dim\"])\n        self.after(0, self._refresh_spooler_status)\n        self.after(500, self._printer_detect)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \ud83d\udd34 ERROR 0x0000011b \u2014 AUTO-FIX  (HOST)\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _fix_error_11b_host(self):\n        \"\"\"Error 0x0000011b fix: HOST side \u2014 RpcAuthnLevelPrivacyEnabled rollback + SMB.\"\"\"\n        if not messagebox.askyesno(\"Fix Error 0x0000011b \u2014 HOST\",\n                \"Error 0x0000011b matlab:\\n\"\n                \"'Windows cannot connect to the printer \u2014 Operation failed with error 0x0000011b'\\n\\n\"\n                \"Ye Microsoft ke Windows Update (KB5005565/KB5005566) ke baad\\n\"\n                \"aata hai \u2014 RPC encryption policy strict ho gayi hai.\\n\\n\"\n                \"HOST pe ye fixes honge:\\n\"\n                \"  1. RpcAuthnLevelPrivacyEnabled = 0  (KB5005565 rollback)\\n\"\n                \"  2. RestrictRemoteClients = 0  (RPC remote access allow)\\n\"\n                \"  3. EnableAuthEpResolution = 1\\n\"\n                \"  4. LanmanServer security relax\\n\"\n                \"  5. Spooler restart\\n\"\n                \"  6. Firewall rules verify\\n\\n\"\n                \"\u26a0 Sirf trusted/private LAN pe karo!\\nContinue karein?\"):\n            return\n        self._sharing_log(\"\u2550\"*56, C[\"border\"])\n        self._sharing_log(\"\ud83d\udd34 [HOST] Error 0x0000011b fix chal raha hai...\", C[\"error\"])\n        self._launch_job(\"fix_error_11b_host\", self._do_fix_error_11b_host)\n\n    def _do_fix_error_11b_host(self):\n        log = self._sharing_log\n        L = C\n\n        # Step 1 \u2014 RpcAuthnLevelPrivacyEnabled = 0 (THE main fix for 11b)\n        log(\"  [1/6] RpcAuthnLevelPrivacyEnabled = 0 (KB5005565 fix)...\", L[\"accent4\"])\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                \"RpcAuthnLevelPrivacyEnabled\", 0, winreg.REG_DWORD)\n            log(\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0  (HOST \u2014 RPC encryption relaxed)\", L[\"success\"])\n        except Exception as e:\n            # Fallback via reg command\n            self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\" /v RpcAuthnLevelPrivacyEnabled /t REG_DWORD /d 0 /f')\n            log(f\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0 (via reg cmd, {e})\", L[\"success\"])\n\n        # Step 2 \u2014 RestrictRemoteClients = 0\n        log(\"  [2/6] RPC RestrictRemoteClients = 0...\", L[\"accent4\"])\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SOFTWARE\\Policies\\Microsoft\\Windows NT\\Rpc\",\n                \"RestrictRemoteClients\", 0, winreg.REG_DWORD)\n            log(\"  \u2705 RestrictRemoteClients = 0\", L[\"success\"])\n        except Exception as e:\n            self._run_cmd('reg add \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Rpc\" /v RestrictRemoteClients /t REG_DWORD /d 0 /f')\n            log(f\"  \u2705 RestrictRemoteClients = 0 (reg cmd)\", L[\"success\"])\n\n        # Step 3 \u2014 EnableAuthEpResolution = 1\n        log(\"  [3/6] EnableAuthEpResolution = 1...\", L[\"accent4\"])\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SOFTWARE\\Policies\\Microsoft\\Windows NT\\Rpc\",\n                \"EnableAuthEpResolution\", 1, winreg.REG_DWORD)\n            log(\"  \u2705 EnableAuthEpResolution = 1\", L[\"success\"])\n        except Exception as e:\n            self._run_cmd('reg add \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Rpc\" /v EnableAuthEpResolution /t REG_DWORD /d 1 /f')\n            log(f\"  \u2705 EnableAuthEpResolution = 1 (reg cmd)\", L[\"success\"])\n\n        # Step 4 \u2014 LanmanServer security relax\n        log(\"  [4/6] LanmanServer security relax...\", L[\"accent4\"])\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanServer\\\\Parameters\" /v RequireSecuritySignature /t REG_DWORD /d 0 /f')\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanServer\\\\Parameters\" /v EnableSecuritySignature /t REG_DWORD /d 1 /f')\n        log(\"  \u2705 LanmanServer SMB signing: optional\", L[\"success\"])\n\n        # Step 5 \u2014 Spooler restart\n        log(\"  [5/6] Spooler restart...\", L[\"accent4\"])\n        self._run_cmd('net stop spooler /y')\n        time.sleep(1)\n        self._run_cmd('net start spooler')\n        out, _ = self._run_cmd('sc query Spooler')\n        log(\"  \u2705 Spooler: Running\" if \"RUNNING\" in out else \"  \u26a0 Spooler check karo\", L[\"success\"] if \"RUNNING\" in out else L[\"warning\"])\n\n        # Step 6 \u2014 Firewall printer rules\n        log(\"  [6/6] Firewall rules verify...\", L[\"accent4\"])\n        self._run_cmd('netsh advfirewall firewall set rule group=\"File and Printer Sharing\" new enable=Yes profile=any')\n        for port, proto, name in [(445,\"TCP\",\"SMB\"),(135,\"TCP\",\"RPC\"),(9100,\"TCP\",\"RAW\")]:\n            self._run_cmd(f'netsh advfirewall firewall add rule name=\"Godawari11b_{name}\" dir=in action=allow protocol={proto} localport={port} profile=any')\n        log(\"  \u2705 Firewall rules: set\", L[\"success\"])\n\n        log(\"\", L[\"text\"])\n        log(\"\u2705 [HOST] Error 0x0000011b FIX COMPLETE!\", L[\"success\"])\n        log(\"   \u25ba IMPORTANT: HOST + CLIENT dono pe ye fix karo!\", L[\"warning\"])\n        log(\"   \u25ba Phir HOST restart karo for registry to take effect.\", L[\"text_dim\"])\n        self.after(0, self._refresh_spooler_status)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \ud83d\udd34 ERROR 0x0000709 \u2014 AUTO-FIX  (CLIENT)\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _fix_error_709_client(self):\n        if not messagebox.askyesno(\"Fix Error 0x0000709 \u2014 CLIENT\",\n                \"CLIENT pe Error 0x0000709 fix:\\n\\n\"\n                \"  1. Spooler stop + clean + restart\\n\"\n                \"  2. UserSelectedDefault registry clear\\n\"\n                \"  3. LegacyDefaultPrinterMode = 1\\n\"\n                \"  4. AllowInsecureGuestAuth = 1\\n\"\n                \"  5. LimitBlankPasswordUse = 0\\n\"\n                \"  6. Spooler DLLs re-register\\n\"\n                \"  7. Spooler Auto + Start\\n\\n\"\n                \"Continue karein?\"):\n            return\n        self._sharing_log(\"\u2550\"*56, C[\"border\"])\n        self._sharing_log(\"\ud83d\udd34 [CLIENT] Error 0x0000709 fix chal raha hai...\", C[\"error\"])\n        self._launch_job(\"fix_error_709_client\", self._do_fix_error_709_client)\n\n    def _do_fix_error_709_client(self):\n        log = self._sharing_log\n        L = C\n\n        log(\"  [1/7] Spooler stop + spool clean...\", L[\"accent4\"])\n        self._run_cmd('net stop spooler /y')\n        time.sleep(1)\n        spool_dir = os.path.join(os.environ.get(\"SYSTEMROOT\",\"C:\\\\Windows\"),\"System32\",\"spool\",\"PRINTERS\")\n        deleted = 0\n        for f in Path(spool_dir).glob(\"*\"):\n            try: f.unlink(); deleted += 1\n            except: pass\n        log(f\"  \u2705 {deleted} spool files deleted\", L[\"success\"])\n\n        log(\"  [2/7] UserSelectedDefault registry clear...\", L[\"accent4\"])\n        try:\n            key = winreg.OpenKey(winreg.HKEY_CURRENT_USER,\n                r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows\",\n                0, winreg.KEY_SET_VALUE | winreg.KEY_READ)\n            try:\n                winreg.DeleteValue(key, \"UserSelectedDefault\")\n                log(\"  \u2705 UserSelectedDefault removed\", L[\"success\"])\n            except FileNotFoundError:\n                log(\"  \u2139 UserSelectedDefault not found \u2014 OK\", L[\"text_dim\"])\n            winreg.CloseKey(key)\n        except Exception as e:\n            log(f\"  \u26a0 {e}\", L[\"warning\"])\n\n        log(\"  [3/7] LegacyDefaultPrinterMode = 1 (Windows auto-manage OFF)...\", L[\"accent4\"])\n        try:\n            key2 = winreg.OpenKey(winreg.HKEY_CURRENT_USER,\n                r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows\",\n                0, winreg.KEY_SET_VALUE)\n            winreg.SetValueEx(key2, \"LegacyDefaultPrinterMode\", 0, winreg.REG_DWORD, 1)\n            winreg.CloseKey(key2)\n            log(\"  \u2705 LegacyDefaultPrinterMode = 1\", L[\"success\"])\n        except Exception as e:\n            log(f\"  \u26a0 {e}\", L[\"warning\"])\n\n        log(\"  [4/7] AllowInsecureGuestAuth = 1...\", L[\"accent4\"])\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Services\\LanmanWorkstation\\Parameters\",\n                \"AllowInsecureGuestAuth\", 1, winreg.REG_DWORD)\n            log(\"  \u2705 AllowInsecureGuestAuth = 1\", L[\"success\"])\n        except Exception as e:\n            log(f\"  \u26a0 {e}\", L[\"warning\"])\n\n        log(\"  [5/7] LimitBlankPasswordUse = 0...\", L[\"accent4\"])\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Lsa\" /v LimitBlankPasswordUse /t REG_DWORD /d 0 /f')\n        log(\"  \u2705 LimitBlankPasswordUse = 0\", L[\"success\"])\n\n        log(\"  [6/7] Spooler DLLs re-register...\", L[\"accent4\"])\n        sys32 = os.path.join(os.environ.get(\"SYSTEMROOT\",\"C:\\\\Windows\"), \"System32\")\n        for dll in [\"localspl.dll\",\"spoolss.dll\",\"win32spl.dll\"]:\n            path = os.path.join(sys32, dll)\n            if os.path.exists(path):\n                self._run_cmd(f'regsvr32 /s \"{path}\"')\n                log(f\"  \u2705 Registered: {dll}\", L[\"success\"])\n\n        log(\"  [7/7] Spooler Auto + Start...\", L[\"accent4\"])\n        self._run_cmd('sc config Spooler start= auto')\n        self._run_cmd('net start spooler')\n        time.sleep(1)\n        out, _ = self._run_cmd('sc query Spooler')\n        log(\"  \u2705 Spooler: Running!\" if \"RUNNING\" in out else \"  \u26a0 Spooler check karo\", L[\"success\"] if \"RUNNING\" in out else L[\"warning\"])\n\n        log(\"\", L[\"text\"])\n        log(\"\u2705 [CLIENT] Error 0x0000709 FIX COMPLETE!\", L[\"success\"])\n        log(\"   \u25ba Ab 'Detect Printers' karo aur default printer set karo.\", L[\"text_dim\"])\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \ud83d\udd34 ERROR 0x0000011b \u2014 AUTO-FIX  (CLIENT)\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _fix_error_11b_client(self):\n        if not messagebox.askyesno(\"Fix Error 0x0000011b \u2014 CLIENT\",\n                \"CLIENT pe Error 0x0000011b fix:\\n\\n\"\n                \"'Windows cannot connect to the printer \u2014 0x0000011b'\\n\"\n                \"Ye Windows Update KB5005565 ke baad aata hai.\\n\\n\"\n                \"  1. RpcAuthnLevelPrivacyEnabled = 0  \u2190 MAIN FIX\\n\"\n                \"  2. RestrictRemoteClients = 0\\n\"\n                \"  3. EnableAuthEpResolution = 1\\n\"\n                \"  4. LanmanWorkstation SMB signing relax\\n\"\n                \"  5. AllowInsecureGuestAuth = 1\\n\"\n                \"  6. Point &amp; Print restrictions relax\\n\"\n                \"  7. Firewall rules + Spooler restart\\n\\n\"\n                \"\u26a0 Sirf trusted LAN pe karo!\\nContinue karein?\"):\n            return\n        self._sharing_log(\"\u2550\"*56, C[\"border\"])\n        self._sharing_log(\"\ud83d\udd34 [CLIENT] Error 0x0000011b fix chal raha hai...\", C[\"error\"])\n        self._launch_job(\"fix_error_11b_client\", self._do_fix_error_11b_client)\n\n    def _do_fix_error_11b_client(self):\n        log = self._sharing_log\n        L = C\n\n        # Step 1 \u2014 THE main fix\n        log(\"  [1/7] RpcAuthnLevelPrivacyEnabled = 0  \u2190 MAIN FIX...\", L[\"accent4\"])\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                \"RpcAuthnLevelPrivacyEnabled\", 0, winreg.REG_DWORD)\n            log(\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0  (CLIENT)\", L[\"success\"])\n        except Exception as e:\n            self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\" /v RpcAuthnLevelPrivacyEnabled /t REG_DWORD /d 0 /f')\n            log(f\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0 (reg cmd, {e})\", L[\"success\"])\n\n        # Step 2 \u2014 RestrictRemoteClients\n        log(\"  [2/7] RestrictRemoteClients = 0...\", L[\"accent4\"])\n        self._run_cmd('reg add \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Rpc\" /v RestrictRemoteClients /t REG_DWORD /d 0 /f')\n        log(\"  \u2705 RestrictRemoteClients = 0\", L[\"success\"])\n\n        # Step 3 \u2014 EnableAuthEpResolution\n        log(\"  [3/7] EnableAuthEpResolution = 1...\", L[\"accent4\"])\n        self._run_cmd('reg add \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Rpc\" /v EnableAuthEpResolution /t REG_DWORD /d 1 /f')\n        log(\"  \u2705 EnableAuthEpResolution = 1\", L[\"success\"])\n\n        # Step 4 \u2014 LanmanWorkstation signing relax\n        log(\"  [4/7] LanmanWorkstation SMB signing relax...\", L[\"accent4\"])\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanWorkstation\\\\Parameters\" /v RequireSecuritySignature /t REG_DWORD /d 0 /f')\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanWorkstation\\\\Parameters\" /v EnableSecuritySignature /t REG_DWORD /d 1 /f')\n        log(\"  \u2705 LanmanWorkstation SMB signing: optional\", L[\"success\"])\n\n        # Step 5 \u2014 AllowInsecureGuestAuth\n        log(\"  [5/7] AllowInsecureGuestAuth = 1...\", L[\"accent4\"])\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Services\\LanmanWorkstation\\Parameters\",\n                \"AllowInsecureGuestAuth\", 1, winreg.REG_DWORD)\n            log(\"  \u2705 AllowInsecureGuestAuth = 1\", L[\"success\"])\n        except Exception as e:\n            log(f\"  \u26a0 {e}\", L[\"warning\"])\n\n        # Step 6 \u2014 Point &amp; Print relax\n        log(\"  [6/7] Point &amp; Print restrictions relax...\", L[\"accent4\"])\n        for cmd in [\n            'reg add \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Printers\\\\PointAndPrint\" /v NoWarningNoElevationOnInstall /t REG_DWORD /d 1 /f',\n            'reg add \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Printers\\\\PointAndPrint\" /v UpdatePromptSettings /t REG_DWORD /d 2 /f',\n            'reg add \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Printers\\\\PointAndPrint\" /v RestrictDriverInstallationToAdministrators /t REG_DWORD /d 0 /f',\n        ]:\n            self._run_cmd(cmd)\n        log(\"  \u2705 Point &amp; Print: relaxed\", L[\"success\"])\n\n        # Step 7 \u2014 Firewall + Spooler\n        log(\"  [7/7] Firewall + Spooler restart...\", L[\"accent4\"])\n        self._run_cmd('netsh advfirewall firewall set rule group=\"File and Printer Sharing\" new enable=Yes profile=any')\n        self._run_cmd('net stop spooler /y')\n        time.sleep(1)\n        self._run_cmd('net start spooler')\n        out, _ = self._run_cmd('sc query Spooler')\n        log(\"  \u2705 Spooler: Running\" if \"RUNNING\" in out else \"  \u26a0 Spooler check karo\", L[\"success\"] if \"RUNNING\" in out else L[\"warning\"])\n\n        log(\"\", L[\"text\"])\n        log(\"\u2705 [CLIENT] Error 0x0000011b FIX COMPLETE!\", L[\"success\"])\n        log(\"   \u25ba HOST pe bhi yahi fix karo!\", L[\"warning\"])\n        log(\"   \u25ba Phir computer restart karo \u2014 printer connect hoga.\", L[\"text_dim\"])\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \ud83d\ude80 MEGA AUTO-FIX \u2014 HOST (Sabkuch ek saath)\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \ud83d\udd34 ENTERPRISE PRINTER RECOVERY CENTER \u2014 Backend Methods\n    #  Tab 4: Network Printer Recovery \u2014 All repair logic\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    # \u2500\u2500 Internal logging helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_log(self, msg, color=None):\n        \"\"\"Log to repair log panel.\"\"\"\n        color = color or C[\"text\"]\n        self._append_log(getattr(self, \"epr_repair_log\", None) or\n                         getattr(self, \"printer_log\", None), msg, color)\n\n    def _epr_diag(self, msg, color=None):\n        \"\"\"Log to live diagnostics panel.\"\"\"\n        color = color or C[\"text\"]\n        self._append_log(getattr(self, \"epr_diag_log\", None) or\n                         getattr(self, \"printer_log\", None), msg, color)\n\n    def _epr_summary(self, msg, color=None):\n        \"\"\"Log to recovery summary panel.\"\"\"\n        color = color or C[\"text\"]\n        self._append_log(getattr(self, \"epr_summary_log\", None) or\n                         getattr(self, \"printer_log\", None), msg, color)\n\n    def _epr_detect_log(self, msg, color=None):\n        \"\"\"Log to auto-detection panel.\"\"\"\n        color = color or C[\"text\"]\n        self._append_log(getattr(self, \"epr_detect_log\", None) or\n                         getattr(self, \"printer_log\", None), msg, color)\n\n    def _epr_set_status(self, msg, color=None):\n        \"\"\"Update status label on the EPR tab.\"\"\"\n        color = color or C[\"accent4\"]\n        def _do():\n            try:\n                lbl = getattr(self, \"epr_status_lbl\", None)\n                if lbl:\n                    lbl.config(text=msg, fg=color)\n            except Exception:\n                pass\n        self.after(0, _do)\n\n    def _epr_progress_start(self):\n        def _do():\n            try:\n                p = getattr(self, \"epr_progress\", None)\n                if p:\n                    p.start(12)\n            except Exception:\n                pass\n        self.after(0, _do)\n\n    def _epr_progress_stop(self):\n        def _do():\n            try:\n                p = getattr(self, \"epr_progress\", None)\n                if p:\n                    p.stop()\n            except Exception:\n                pass\n        self.after(0, _do)\n\n    def _epr_submit(self, name, fn, *args, **kwargs):\n        \"\"\"Submit an EPR task to worker manager.\"\"\"\n        mgr = getattr(self, \"worker_manager\", None)\n        if mgr:\n            try:\n                mgr.submit(name, fn, *args, **kwargs)\n                return\n            except Exception:\n                pass\n        self._launch_job(\"bg_task\", fn, *args, **kwargs)\n\n    def _epr_reg_backup(self, hive, path, backup_name):\n        \"\"\"Backup a registry key before modifying it.\"\"\"\n        try:\n            backup_dir = Path(os.environ.get(\"TEMP\", \"C:\\\\Temp\")) / \"GodawariEPR_Backup\"\n            backup_dir.mkdir(parents=True, exist_ok=True)\n            ts = datetime.datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n            backup_file = str(backup_dir / f\"{backup_name}_{ts}.reg\")\n            hive_str = {\n                winreg.HKEY_LOCAL_MACHINE:  \"HKLM\",\n                winreg.HKEY_CURRENT_USER:   \"HKCU\",\n                winreg.HKEY_USERS:          \"HKU\",\n            }.get(hive, \"HKLM\")\n            self._run_cmd(f'reg export \"{hive_str}\\\\{path}\" \"{backup_file}\" /y', timeout=10)\n            return backup_file\n        except Exception:\n            return None\n\n    # \u2500\u2500 Auto Detection \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_auto_detect(self):\n        self._epr_submit(\"epr_auto_detect\", self._do_epr_auto_detect)\n\n    def _do_epr_auto_detect(self):\n        log = self._epr_detect_log\n        self._epr_progress_start()\n        self._epr_set_status(\"Running auto-detection...\", C[\"accent4\"])\n        log(\"\u2550\" * 54, C[\"border\"])\n        log(\"\ud83d\udd0d AUTO-DETECTION STARTING...\", C[\"accent\"])\n        issues = []\n\n        # 1. Spooler check\n        log(\"  [1/8] Checking Print Spooler...\", C[\"text_dim\"])\n        out, _ = self._run_cmd(\"sc query Spooler\", timeout=8)\n        if \"RUNNING\" not in out:\n            log(\"  \u274c Spooler NOT running\", C[\"error\"])\n            issues.append(\"Spooler stopped\")\n        else:\n            log(\"  \u2705 Spooler: Running\", C[\"success\"])\n\n        # 2. RPC setting check\n        log(\"  [2/8] Checking RpcAuthnLevelPrivacyEnabled...\", C[\"text_dim\"])\n        try:\n            key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                0, winreg.KEY_READ)\n            val, _ = winreg.QueryValueEx(key, \"RpcAuthnLevelPrivacyEnabled\")\n            winreg.CloseKey(key)\n            if val == 1:\n                log(\"  \u26a0 RpcAuthnLevelPrivacyEnabled = 1 (may block printer sharing)\", C[\"warning\"])\n                issues.append(\"RPC Privacy = 1 (error 0x0000011b risk)\")\n            else:\n                log(\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0 (OK)\", C[\"success\"])\n        except FileNotFoundError:\n            log(\"  \u2139 RpcAuthnLevelPrivacyEnabled not set (default=1 on patched Win11)\", C[\"warning\"])\n            issues.append(\"RPC Privacy key missing \u2014 may default to 1\")\n        except Exception as e:\n            log(f\"  \u26a0 RPC check failed: {e}\", C[\"warning\"])\n\n        # 3. Firewall check\n        log(\"  [3/8] Checking Firewall sharing rules...\", C[\"text_dim\"])\n        out2, _ = self._run_cmd(\n            'netsh advfirewall firewall show rule name=\"File and Printer Sharing (SMB-In)\" verbose',\n            timeout=10)\n        if \"Enabled\" not in out2 and \"Yes\" not in out2:\n            log(\"  \u274c File &amp; Printer Sharing firewall rules may be OFF\", C[\"error\"])\n            issues.append(\"Firewall sharing rules disabled\")\n        else:\n            log(\"  \u2705 Firewall: F&amp;P Sharing rules OK\", C[\"success\"])\n\n        # 4. Network discovery\n        log(\"  [4/8] Checking Network Discovery...\", C[\"text_dim\"])\n        out3, _ = self._run_cmd(\n            \"netsh advfirewall firewall show rule name=\\\"Network Discovery (NB-Datagram-In)\\\" verbose\",\n            timeout=10)\n        if \"Enabled\" not in out3 and \"Yes\" not in out3:\n            log(\"  \u26a0 Network Discovery may be disabled\", C[\"warning\"])\n            issues.append(\"Network Discovery disabled\")\n        else:\n            log(\"  \u2705 Network Discovery: OK\", C[\"success\"])\n\n        # 5. SMB1 check\n        log(\"  [5/8] Checking SMB services...\", C[\"text_dim\"])\n        out4, _ = self._run_cmd(\"sc query LanmanServer\", timeout=8)\n        if \"RUNNING\" not in out4:\n            log(\"  \u274c LanmanServer (Server service) NOT running\", C[\"error\"])\n            issues.append(\"LanmanServer stopped\")\n        else:\n            log(\"  \u2705 LanmanServer: Running\", C[\"success\"])\n\n        # 6. Point &amp; Print check\n        log(\"  [6/8] Checking Point &amp; Print restrictions...\", C[\"text_dim\"])\n        try:\n            key2 = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,\n                r\"SOFTWARE\\Policies\\Microsoft\\Windows NT\\Printers\\PointAndPrint\",\n                0, winreg.KEY_READ)\n            try:\n                restrict, _ = winreg.QueryValueEx(key2, \"Restricted\")\n                if restrict == 1:\n                    log(\"  \u26a0 Point &amp; Print Restricted = 1 (may block driver install)\", C[\"warning\"])\n                    issues.append(\"Point &amp; Print restriction active\")\n                else:\n                    log(\"  \u2705 Point &amp; Print: Not restricted\", C[\"success\"])\n            except FileNotFoundError:\n                log(\"  \u2705 Point &amp; Print: Default (OK)\", C[\"success\"])\n            winreg.CloseKey(key2)\n        except Exception:\n            log(\"  \u2139 Point &amp; Print GPO key not found (OK)\", C[\"text_dim\"])\n\n        # 7. Printer port reachability (if host/share entered)\n        host = getattr(self, \"epr_host_var\", tk.StringVar()).get().strip()\n        if host:\n            log(f\"  [7/8] Pinging host: {host}...\", C[\"text_dim\"])\n            out5, rc5 = self._run_cmd(f\"ping -n 2 -w 1000 {host}\", timeout=10)\n            if rc5 == 0 and \"TTL=\" in out5:\n                log(f\"  \u2705 Host reachable: {host}\", C[\"success\"])\n            else:\n                log(f\"  \u274c Host NOT reachable: {host}\", C[\"error\"])\n                issues.append(f\"Host unreachable: {host}\")\n        else:\n            log(\"  [7/8] Host not entered \u2014 skip ping\", C[\"text_dim\"])\n\n        # 8. Spool directory check\n        log(\"  [8/8] Checking spool directory...\", C[\"text_dim\"])\n        spool_dir = os.path.join(os.environ.get(\"SYSTEMROOT\", \"C:\\\\Windows\"),\n                                  \"System32\", \"spool\", \"PRINTERS\")\n        try:\n            stuck = list(Path(spool_dir).glob(\"*.SPL\")) + list(Path(spool_dir).glob(\"*.SHD\"))\n            if stuck:\n                log(f\"  \u26a0 {len(stuck)} stuck spool files found\", C[\"warning\"])\n                issues.append(f\"{len(stuck)} stuck spool files\")\n            else:\n                log(\"  \u2705 Spool directory: Clean\", C[\"success\"])\n        except Exception:\n            log(\"  \u2139 Spool check skipped (access issue)\", C[\"text_dim\"])\n\n        # Summary\n        log(\"\", C[\"text\"])\n        if issues:\n            log(f\"\u26a0 ISSUES DETECTED ({len(issues)}):\", C[\"warning\"])\n            for iss in issues:\n                log(f\"  \u2022 {iss}\", C[\"error\"])\n            log(\"\", C[\"text\"])\n            log(\"\u2192 Click FULL AUTO FIX to repair all detected issues.\", C[\"accent4\"])\n        else:\n            log(\"\u2705 No major issues detected! Network printer should work.\", C[\"success\"])\n\n        self._epr_progress_stop()\n        self._epr_set_status(\n            f\"Detection complete \u2014 {len(issues)} issue(s) found\",\n            C[\"error\"] if issues else C[\"success\"])\n\n    # \u2500\u2500 Full Auto Fix \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_full_auto_fix(self):\n        if not messagebox.askyesno(\n            \"\ud83d\ude80 FULL AUTO FIX \u2014 Enterprise Printer Recovery\",\n            \"This will automatically perform 18 repair steps:\\n\\n\"\n            \"  1.  Diagnose printer sharing problems\\n\"\n            \"  2.  Detect root cause\\n\"\n            \"  3.  Repair Print Spooler\\n\"\n            \"  4.  Repair RPC + SMB issues\\n\"\n            \"  5.  Repair Point &amp; Print restrictions\\n\"\n            \"  6.  Repair firewall sharing rules\\n\"\n            \"  7.  Repair network discovery\\n\"\n            \"  8.  Repair printer sharing settings\\n\"\n            \"  9.  Repair broken printer cache\\n\"\n            \" 10. Remove corrupted printer mappings\\n\"\n            \" 11. Repair Canon printer compatibility\\n\"\n            \" 12. Detect x86/x64 driver mismatch\\n\"\n            \" 13. Repair driver installation issues\\n\"\n            \" 14. Validate printer reachability\\n\"\n            \" 15. Reconnect shared printer\\n\"\n            \" 16. Validate successful printer installation\\n\"\n            \" 17. Generate repair summary\\n\"\n            \" 18. Log all actions safely\\n\\n\"\n            \"\u26a0 Run as Administrator for full effect.\\n\"\n            \"Continue?\"):\n            return\n        self._epr_submit(\"epr_full_auto_fix\", self._do_epr_full_auto_fix)\n\n    def _do_epr_full_auto_fix(self):\n        log  = self._epr_log\n        diag = self._epr_diag\n        summ = self._epr_summary\n        self._epr_progress_start()\n        results = []\n\n        def step(n, total, msg):\n            self._epr_set_status(f\"[{n}/{total}] {msg}\", C[\"accent4\"])\n            log(f\"\\n[{n:02d}/{total}] {msg}\", C[\"accent4\"])\n            diag(f\"  \u25ba {msg}\", C[\"text_dim\"])\n\n        log(\"\u2550\" * 56, C[\"border\"])\n        log(\"\ud83d\ude80 FULL AUTO FIX \u2014 Enterprise Network Printer Recovery\", C[\"error\"])\n        log(\"\u2550\" * 56, C[\"border\"])\n\n        TOTAL = 18\n\n        # \u2500\u2500 Step 1: Diagnose \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(1, TOTAL, \"Diagnosing printer sharing problems\")\n        self._do_epr_auto_detect()\n        results.append(\"\u2705 Diagnosis complete\")\n\n        # \u2500\u2500 Step 2: Detect root cause \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(2, TOTAL, \"Detecting root cause (RPC, spooler, firewall)\")\n        rpc_broken = False\n        spooler_broken = False\n        try:\n            key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\", 0, winreg.KEY_READ)\n            try:\n                val, _ = winreg.QueryValueEx(key, \"RpcAuthnLevelPrivacyEnabled\")\n                rpc_broken = (val == 1)\n            except FileNotFoundError:\n                rpc_broken = True   # missing = system default may be 1 on patched Win11\n            winreg.CloseKey(key)\n        except Exception:\n            rpc_broken = True\n\n        out_sp, _ = self._run_cmd(\"sc query Spooler\", timeout=8)\n        spooler_broken = \"RUNNING\" not in out_sp\n        log(f\"  RPC broken: {rpc_broken}  |  Spooler broken: {spooler_broken}\", C[\"text_dim\"])\n        results.append(f\"\u2705 Root cause: RPC={rpc_broken}, Spooler={spooler_broken}\")\n\n        # \u2500\u2500 Step 3: Repair Spooler \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(3, TOTAL, \"Repairing Print Spooler\")\n        self._run_cmd(\"net stop spooler /y\", timeout=8)\n        time.sleep(1)\n        spool_dir = os.path.join(os.environ.get(\"SYSTEMROOT\", \"C:\\\\Windows\"),\n                                  \"System32\", \"spool\", \"PRINTERS\")\n        cleared = 0\n        try:\n            for f in Path(spool_dir).glob(\"*\"):\n                try:\n                    f.unlink(); cleared += 1\n                except Exception:\n                    pass\n        except Exception:\n            pass\n        self._run_cmd(\"sc config Spooler start= auto\")\n        self._run_cmd(\"net start spooler\", timeout=8)\n        time.sleep(1)\n        out_sp2, _ = self._run_cmd(\"sc query Spooler\", timeout=8)\n        ok = \"RUNNING\" in out_sp2\n        log(f\"  {'\u2705' if ok else '\u274c'} Spooler: {'Running' if ok else 'FAILED'} | {cleared} spool files cleared\",\n            C[\"success\"] if ok else C[\"error\"])\n        results.append(f\"{'\u2705' if ok else '\u274c'} Spooler repair\")\n\n        # \u2500\u2500 Step 4: RPC + SMB repair \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(4, TOTAL, \"Repairing RPC + SMB issues\")\n        self._epr_reg_backup(winreg.HKEY_LOCAL_MACHINE,\n            r\"SYSTEM\\CurrentControlSet\\Control\\Print\", \"RpcPrint_backup\")\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                \"RpcAuthnLevelPrivacyEnabled\", 0, winreg.REG_DWORD)\n            log(\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0\", C[\"success\"])\n        except Exception:\n            self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\" /v RpcAuthnLevelPrivacyEnabled /t REG_DWORD /d 0 /f')\n            log(\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0 (via reg cmd)\", C[\"success\"])\n\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SOFTWARE\\Policies\\Microsoft\\Windows NT\\Rpc\",\n                \"RestrictRemoteClients\", 0, winreg.REG_DWORD)\n            log(\"  \u2705 RestrictRemoteClients = 0\", C[\"success\"])\n        except Exception:\n            self._run_cmd('reg add \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Rpc\" /v RestrictRemoteClients /t REG_DWORD /d 0 /f')\n\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanServer\\\\Parameters\" /v RequireSecuritySignature /t REG_DWORD /d 0 /f')\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanWorkstation\\\\Parameters\" /v RequireSecuritySignature /t REG_DWORD /d 0 /f')\n        log(\"  \u2705 SMB signing: optional on both sides\", C[\"success\"])\n        results.append(\"\u2705 RPC + SMB repaired\")\n\n        # \u2500\u2500 Step 5: Point &amp; Print \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(5, TOTAL, \"Repairing Point &amp; Print restrictions\")\n        self._do_epr_point_print_repair_silent()\n        results.append(\"\u2705 Point &amp; Print repaired\")\n\n        # \u2500\u2500 Step 6: Firewall \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(6, TOTAL, \"Repairing firewall sharing rules\")\n        self._do_epr_firewall_fix_silent()\n        results.append(\"\u2705 Firewall rules applied\")\n\n        # \u2500\u2500 Step 7: Network discovery \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(7, TOTAL, \"Repairing network discovery\")\n        self._do_epr_enable_netdiscovery_silent()\n        results.append(\"\u2705 Network discovery enabled\")\n\n        # \u2500\u2500 Step 8: Printer sharing settings \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(8, TOTAL, \"Repairing printer sharing settings\")\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanServer\\\\Parameters\" /v AutoShareServer /t REG_DWORD /d 1 /f')\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanServer\\\\Parameters\" /v AutoShareWks /t REG_DWORD /d 1 /f')\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Lsa\" /v LimitBlankPasswordUse /t REG_DWORD /d 0 /f')\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanWorkstation\\\\Parameters\" /v AllowInsecureGuestAuth /t REG_DWORD /d 1 /f')\n        log(\"  \u2705 Sharing settings: AutoShare + LimitBlank + GuestAuth\", C[\"success\"])\n        results.append(\"\u2705 Sharing settings repaired\")\n\n        # \u2500\u2500 Step 9: Printer cache \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(9, TOTAL, \"Repairing broken printer cache\")\n        self._do_epr_cache_cleaner_silent()\n        results.append(\"\u2705 Printer cache cleaned\")\n\n        # \u2500\u2500 Step 10: Remove corrupted mappings \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(10, TOTAL, \"Removing corrupted printer mappings\")\n        removed = 0\n        try:\n            ps_script = (\n                \"$printers = Get-Printer -ErrorAction SilentlyContinue | \"\n                \"Where-Object {$_.PrinterStatus -eq 'Error' -or $_.PrinterStatus -eq 'Offline'};\"\n                \"foreach ($p in $printers) { Remove-Printer -Name $p.Name -ErrorAction SilentlyContinue; \"\n                \"Write-Output \\\"REMOVED:$($p.Name)\\\" }\"\n            )\n            out_rm = self._run_cmd(\n                f'powershell -NoProfile -Command \"{ps_script}\"', timeout=30)\n            out_str = out_rm[0] if isinstance(out_rm, tuple) else str(out_rm)\n            removed = out_str.count(\"REMOVED:\")\n            log(f\"  \u2705 {removed} corrupted printer mapping(s) removed\", C[\"success\"])\n        except Exception as e:\n            log(f\"  \u26a0 Mapping removal: {e}\", C[\"warning\"])\n        results.append(f\"\u2705 Removed {removed} corrupted mapping(s)\")\n\n        # \u2500\u2500 Step 11: Canon compatibility \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(11, TOTAL, \"Repairing Canon printer compatibility\")\n        self._do_epr_canon_fix_silent()\n        results.append(\"\u2705 Canon compatibility applied\")\n\n        # \u2500\u2500 Step 12: Driver mismatch detection \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(12, TOTAL, \"Detecting x86/x64 driver mismatch\")\n        arch_ok = self._do_epr_check_driver_arch()\n        results.append(f\"{'\u2705' if arch_ok else '\u26a0'} Driver arch: {'OK' if arch_ok else 'Mismatch detected'}\")\n\n        # \u2500\u2500 Step 13: Driver repair \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(13, TOTAL, \"Repairing driver installation issues\")\n        sys32 = os.path.join(os.environ.get(\"SYSTEMROOT\", \"C:\\\\Windows\"), \"System32\")\n        for dll in [\"localspl.dll\", \"spoolss.dll\", \"win32spl.dll\", \"winspool.drv\"]:\n            path = os.path.join(sys32, dll)\n            if os.path.exists(path):\n                self._run_cmd(f'regsvr32 /s \"{path}\"')\n        log(\"  \u2705 Spooler DLLs re-registered\", C[\"success\"])\n        results.append(\"\u2705 Driver DLLs re-registered\")\n\n        # \u2500\u2500 Step 14: Validate reachability \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(14, TOTAL, \"Validating printer reachability\")\n        host = getattr(self, \"epr_host_var\", tk.StringVar()).get().strip()\n        if host:\n            safe_host = re.sub(r\"[^A-Za-z0-9_.:-]\", \"\", host)\n            out_ping, rc_ping = self._run_cmd(f\"ping -n 1 -w 1000 {safe_host}\", timeout=5)\n            reachable = rc_ping == 0 and \"TTL=\" in out_ping.upper()\n            log(f\"  {'\u2705' if reachable else '\u274c'} Host {host}: {'reachable' if reachable else 'unreachable'}\", C[\"success\"] if reachable else C[\"error\"])\n            results.append(f\"{'\u2705' if reachable else '\u274c'} Host reachability: {host}\")\n        else:\n            log(\"  \u2139 Host not specified \u2014 skip ping test\", C[\"text_dim\"])\n            results.append(\"\u2139 Host reachability: skipped (no host entered)\")\n\n        # \u2500\u2500 Step 15: Reconnect shared printer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(15, TOTAL, \"Reconnecting shared printer\")\n        share = getattr(self, \"epr_share_var\", tk.StringVar()).get().strip()\n        if host and share:\n            safe_host = re.sub(r\"[^A-Za-z0-9_.:-]\", \"\", host)\n            safe_share = re.sub(r\"[^A-Za-z0-9_.$ -]\", \"\", share).strip()\n            unc = f\"\\\\\\\\{safe_host}\\\\{safe_share}\"\n            out_nu, rc_nu = self._run_cmd(f'net use \"{unc}\" /persistent:yes', timeout=8)\n            if rc_nu == 0 or \"completed\" in out_nu.lower():\n                log(f\"  \u2705 Connected to: {unc}\", C[\"success\"])\n                results.append(f\"\u2705 Reconnected: {unc}\")\n            else:\n                log(f\"  \u26a0 net use result: {out_nu[:100]}\", C[\"warning\"])\n                results.append(f\"\u26a0 Reconnect attempted: {unc}\")\n        else:\n            log(\"  \u2139 Host/Share not specified \u2014 skip reconnect\", C[\"text_dim\"])\n            results.append(\"\u2139 Reconnect: skipped (enter Host IP and Share Name above)\")\n\n        # \u2500\u2500 Step 16: Validate installation \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(16, TOTAL, \"Validating successful printer installation\")\n        out_list, _ = self._run_cmd(\n            'powershell -NoProfile -Command \"Get-Printer | Select-Object Name,PrinterStatus | ConvertTo-Csv -NoTypeInformation\"',\n            timeout=12)\n        printer_count = max(0, out_list.count(\"\\n\") - 1)\n        log(f\"  \u2705 {printer_count} printer(s) found after repair\", C[\"success\"])\n        results.append(f\"\u2705 Validation: {printer_count} printer(s) visible\")\n\n        # \u2500\u2500 Step 17: Spooler final restart \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(17, TOTAL, \"Final spooler restart + service validation\")\n        self._run_cmd(\"net stop spooler /y\", timeout=8)\n        time.sleep(1)\n        self._run_cmd(\"net start spooler\", timeout=8)\n        out_final, _ = self._run_cmd(\"sc query Spooler\", timeout=8)\n        spooler_ok = \"RUNNING\" in out_final\n        log(f\"  {'\u2705' if spooler_ok else '\u274c'} Final spooler state: {'Running' if spooler_ok else 'STOPPED'}\", C[\"success\"] if spooler_ok else C[\"error\"])\n        self.after(0, self._refresh_spooler_status)\n\n        # \u2500\u2500 Step 18: Generate summary \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        step(18, TOTAL, \"Generating repair summary + logging\")\n        ts = datetime.datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\")\n        summ(\"\u2550\" * 50, C[\"border\"])\n        summ(f\"\ud83d\udd34 ENTERPRISE PRINTER RECOVERY \u2014 SUMMARY\", C[\"accent\"])\n        summ(f\"   Completed at: {ts}\", C[\"text_dim\"])\n        summ(\"\", C[\"text\"])\n        for r in results:\n            color = C[\"success\"] if r.startswith(\"\u2705\") else (C[\"error\"] if r.startswith(\"\u274c\") else C[\"warning\"])\n            summ(f\"  {r}\", color)\n        summ(\"\", C[\"text\"])\n        passed = sum(1 for r in results if r.startswith(\"\u2705\"))\n        failed = sum(1 for r in results if r.startswith(\"\u274c\"))\n        summ(f\"  Total: {passed} passed / {failed} failed / {len(results)} steps\", C[\"accent4\"])\n        if failed == 0:\n            summ(\"  \u25ba REPAIR SUCCESSFUL \u2014 Try your printer now!\", C[\"success\"])\n            summ(\"  \u25ba Restart this PC if printer still not working.\", C[\"text_dim\"])\n        else:\n            summ(\"  \u25ba Some steps had issues \u2014 check Repair Log for details.\", C[\"warning\"])\n            summ(\"  \u25ba Try individual repair buttons for failed steps.\", C[\"text_dim\"])\n        summ(\"\u2550\" * 50, C[\"border\"])\n\n        self._epr_progress_stop()\n        self._epr_set_status(\n            f\"COMPLETE \u2014 {passed}/{len(results)} steps passed\",\n            C[\"success\"] if failed == 0 else C[\"warning\"])\n\n        # Structured log\n        try:\n            lg = getattr(self, \"structured_logger\", None)\n            if lg:\n                lg.log(\"epr_full_auto_fix\", \"Full Auto Fix completed\", {\n                    \"passed\": passed, \"failed\": failed, \"steps\": len(results)})\n        except Exception:\n            pass\n\n    # \u2500\u2500 Connection Tester Methods \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_ping_host(self):\n        host = getattr(self, \"epr_host_var\", tk.StringVar()).get().strip()\n        if not host:\n            messagebox.showinfo(\"Host IP\", \"Host IP ya naam enter karo upar.\")\n            return\n        self._epr_submit(\"epr_ping\", self._do_epr_ping, host)\n\n    def _do_epr_ping(self, host):\n        self._epr_set_status(f\"Pinging {host}...\")\n        self._epr_diag(f\"\ud83d\udd0c Pinging {host}...\", C[\"text_dim\"])\n        out, rc = self._run_cmd(f\"ping -n 4 -w 1000 {host}\", timeout=12)\n        if rc == 0 and \"TTL=\" in out:\n            self._epr_diag(f\"  \u2705 Host reachable: {host}\", C[\"success\"])\n            self._epr_set_status(f\"\u2705 {host} is reachable\", C[\"success\"])\n        else:\n            self._epr_diag(f\"  \u274c Host NOT reachable: {host}\", C[\"error\"])\n            self._epr_set_status(f\"\u274c {host} unreachable \u2014 check IP/network\", C[\"error\"])\n\n    def _epr_test_smb(self):\n        host  = getattr(self, \"epr_host_var\",  tk.StringVar()).get().strip()\n        share = getattr(self, \"epr_share_var\", tk.StringVar()).get().strip()\n        if not host:\n            messagebox.showinfo(\"Host\", \"Host IP enter karo.\")\n            return\n        self._epr_submit(\"epr_smb_test\", self._do_epr_test_smb, host, share)\n\n    def _do_epr_test_smb(self, host, share):\n        self._epr_set_status(f\"Testing SMB: \\\\\\\\{host}...\")\n        self._epr_diag(f\"\ud83d\uddc2 Testing SMB share: \\\\\\\\{host}\\\\{share or '*'}\", C[\"text_dim\"])\n        unc = f\"\\\\\\\\{host}\" if not share else f\"\\\\\\\\{host}\\\\{share}\"\n        out, rc = self._run_cmd(f'net use \"{unc}\" /persistent:no', timeout=12)\n        if rc == 0 or \"completed\" in out.lower():\n            self._epr_diag(f\"  \u2705 SMB accessible: {unc}\", C[\"success\"])\n            self._epr_set_status(f\"\u2705 SMB OK: {unc}\", C[\"success\"])\n        else:\n            # Try listing\n            out2, rc2 = self._run_cmd(f'dir \"{unc}\"', timeout=8)\n            if rc2 == 0:\n                self._epr_diag(f\"  \u2705 SMB share visible: {unc}\", C[\"success\"])\n                self._epr_set_status(f\"\u2705 SMB OK\", C[\"success\"])\n            else:\n                self._epr_diag(f\"  \u274c SMB not accessible: {unc}\", C[\"error\"])\n                self._epr_diag(f\"     Result: {out[:120]}\", C[\"text_dim\"])\n                self._epr_set_status(f\"\u274c SMB failed \u2014 check sharing settings\", C[\"error\"])\n\n    def _epr_validate_printer(self):\n        host  = getattr(self, \"epr_host_var\",  tk.StringVar()).get().strip()\n        share = getattr(self, \"epr_share_var\", tk.StringVar()).get().strip()\n        if not host or not share:\n            messagebox.showinfo(\"Input\", \"Host IP aur Share Name dono enter karo.\")\n            return\n        self._epr_submit(\"epr_validate\", self._do_epr_validate_printer, host, share)\n\n    def _do_epr_validate_printer(self, host, share):\n        unc = f\"\\\\\\\\{host}\\\\{share}\"\n        self._epr_set_status(f\"Validating: {unc}...\")\n        self._epr_diag(f\"\ud83d\udda8 Validating printer path: {unc}\", C[\"text_dim\"])\n        out, rc = self._run_cmd(f'rundll32 printui.dll,PrintUIEntry /ga /n\"{unc}\"', timeout=15)\n        if rc == 0:\n            self._epr_diag(f\"  \u2705 Printer connection validated: {unc}\", C[\"success\"])\n            self._epr_set_status(f\"\u2705 Printer reachable: {unc}\", C[\"success\"])\n        else:\n            # Fallback: add printer via PowerShell\n            ps = f'Add-Printer -ConnectionName \"{unc}\" -ErrorAction SilentlyContinue; if ($?) {{ \"OK\" }} else {{ \"FAIL\" }}'\n            out2, _ = self._run_cmd(f'powershell -NoProfile -Command \"{ps}\"', timeout=20)\n            if \"OK\" in out2:\n                self._epr_diag(f\"  \u2705 Printer added via PowerShell: {unc}\", C[\"success\"])\n                self._epr_set_status(f\"\u2705 Printer added\", C[\"success\"])\n            else:\n                self._epr_diag(f\"  \u274c Could not connect to printer: {unc}\", C[\"error\"])\n                self._epr_set_status(f\"\u274c Printer not reachable \u2014 run FULL AUTO FIX\", C[\"error\"])\n\n    def _epr_reconnect_shared(self):\n        host  = getattr(self, \"epr_host_var\",  tk.StringVar()).get().strip()\n        share = getattr(self, \"epr_share_var\", tk.StringVar()).get().strip()\n        if not host or not share:\n            messagebox.showinfo(\"Input\", \"Host IP aur Share Name dono enter karo.\")\n            return\n        if not messagebox.askyesno(\"Reconnect Shared Printer\",\n                f\"Printer reconnect hoga:\\n\\\\\\\\{host}\\\\{share}\\n\\nContinue?\"):\n            return\n        self._epr_submit(\"epr_reconnect\", self._do_epr_reconnect_shared, host, share)\n\n    def _do_epr_reconnect_shared(self, host, share):\n        log = self._epr_log\n        unc = f\"\\\\\\\\{host}\\\\{share}\"\n        self._epr_set_status(f\"Reconnecting: {unc}...\")\n        log(f\"\ud83d\udd17 Reconnecting shared printer: {unc}\", C[\"accent4\"])\n\n        # Remove old connection\n        self._run_cmd(f'net use \"{unc}\" /delete /y', timeout=10)\n        log(\"  \u2139 Old connection removed\", C[\"text_dim\"])\n\n        # Firewall\n        self._run_cmd('netsh advfirewall firewall set rule group=\"File and Printer Sharing\" new enable=Yes profile=any')\n        log(\"  \u2705 Firewall rules: ON\", C[\"success\"])\n\n        # RPC fix\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                \"RpcAuthnLevelPrivacyEnabled\", 0, winreg.REG_DWORD)\n        except Exception:\n            self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\" /v RpcAuthnLevelPrivacyEnabled /t REG_DWORD /d 0 /f')\n        log(\"  \u2705 RPC setting: OK\", C[\"success\"])\n\n        # Reconnect\n        out, rc = self._run_cmd(f'net use \"{unc}\" /persistent:yes', timeout=15)\n        if rc == 0 or \"completed\" in out.lower():\n            log(f\"  \u2705 Connected: {unc}\", C[\"success\"])\n        else:\n            log(f\"  \u26a0 net use: {out[:120]}\", C[\"warning\"])\n\n        # Add as printer\n        ps = f'Add-Printer -ConnectionName \"{unc}\" -ErrorAction SilentlyContinue'\n        self._run_cmd(f'powershell -NoProfile -Command \"{ps}\"', timeout=20)\n        log(f\"  \u2705 Printer install attempted: {unc}\", C[\"success\"])\n\n        # Spooler restart\n        self._run_cmd(\"net stop spooler /y\"); time.sleep(1)\n        self._run_cmd(\"net start spooler\")\n        log(\"  \u2705 Spooler restarted\", C[\"success\"])\n        log(\"\u2705 Shared printer reconnect complete!\", C[\"success\"])\n        self._epr_set_status(\"\u2705 Reconnect complete\", C[\"success\"])\n\n    # \u2500\u2500 Firewall &amp; Network Discovery \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_firewall_fix(self):\n        self._epr_submit(\"epr_fw_fix\", self._do_epr_firewall_fix_silent)\n\n    def _do_epr_firewall_fix_silent(self):\n        self._epr_set_status(\"Applying firewall rules...\")\n        cmds = [\n            'netsh advfirewall firewall set rule group=\"File and Printer Sharing\" new enable=Yes profile=any',\n            'netsh advfirewall firewall set rule group=\"Network Discovery\" new enable=Yes profile=Private',\n            'netsh advfirewall firewall add rule name=\"EPR_SMB_In\" dir=in action=allow protocol=TCP localport=445 profile=any',\n            'netsh advfirewall firewall add rule name=\"EPR_SMB_Out\" dir=out action=allow protocol=TCP localport=445 profile=any',\n            'netsh advfirewall firewall add rule name=\"EPR_RPC_In\" dir=in action=allow protocol=TCP localport=135 profile=any',\n            'netsh advfirewall firewall add rule name=\"EPR_RAW_In\" dir=in action=allow protocol=TCP localport=9100 profile=any',\n            'netsh advfirewall firewall add rule name=\"EPR_NetBIOS_In\" dir=in action=allow protocol=TCP localport=139 profile=any',\n        ]\n        for cmd in cmds:\n            self._run_cmd(cmd, timeout=10)\n        self._epr_log(\"  \u2705 Firewall sharing rules applied\", C[\"success\"])\n        self._epr_set_status(\"\u2705 Firewall rules applied\", C[\"success\"])\n\n    def _epr_enable_netdiscovery(self):\n        self._epr_submit(\"epr_netdisc\", self._do_epr_enable_netdiscovery_silent)\n\n    def _do_epr_enable_netdiscovery_silent(self):\n        self._epr_set_status(\"Enabling network discovery...\")\n        self._run_cmd('netsh advfirewall firewall set rule group=\"Network Discovery\" new enable=Yes profile=Private')\n        # FD services\n        for svc in [\"FDResPub\", \"fdPHost\", \"SSDPSRV\", \"upnphost\"]:\n            self._run_cmd(f\"sc config {svc} start= auto\")\n            self._run_cmd(f\"net start {svc}\")\n        self._epr_log(\"  \u2705 Network discovery enabled + FD services started\", C[\"success\"])\n        self._epr_set_status(\"\u2705 Network discovery: ON\", C[\"success\"])\n\n    # \u2500\u2500 Network Share Validator \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_net_share_validator(self):\n        host  = getattr(self, \"epr_host_var\",  tk.StringVar()).get().strip()\n        share = getattr(self, \"epr_share_var\", tk.StringVar()).get().strip()\n        if not host:\n            messagebox.showinfo(\"Host\", \"Host IP enter karo.\")\n            return\n        self._epr_submit(\"epr_nsv\", self._do_epr_net_share_validator, host, share)\n\n    def _do_epr_net_share_validator(self, host, share):\n        log = self._epr_diag\n        self._epr_set_status(f\"Validating share: \\\\\\\\{host}...\")\n        log(f\"\ud83c\udf10 Network Share Validator: \\\\\\\\{host}\\\\{share or ''}\", C[\"accent4\"])\n\n        # Ping\n        out, rc = self._run_cmd(f\"ping -n 2 -w 1000 {host}\", timeout=8)\n        log(f\"  Ping: {'\u2705 OK' if (rc==0 and 'TTL=' in out) else '\u274c FAIL'}\", C[\"success\"] if (rc==0 and \"TTL=\" in out) else C[\"error\"])\n\n        # Port 445\n        ps445 = f\"Test-NetConnection -ComputerName {host} -Port 445 -InformationLevel Quiet 2&gt;$null\"\n        out445, _ = self._run_cmd(f'powershell -NoProfile -Command \"{ps445}\"', timeout=10)\n        log(f\"  Port 445: {'\u2705 Open' if 'True' in out445 else '\u274c Closed/Filtered'}\", C[\"success\"] if \"True\" in out445 else C[\"error\"])\n\n        # Port 139\n        ps139 = f\"Test-NetConnection -ComputerName {host} -Port 139 -InformationLevel Quiet 2&gt;$null\"\n        out139, _ = self._run_cmd(f'powershell -NoProfile -Command \"{ps139}\"', timeout=10)\n        log(f\"  Port 139: {'\u2705 Open' if 'True' in out139 else '\u26a0 Closed'}\", C[\"success\"] if \"True\" in out139 else C[\"warning\"])\n\n        # Share list\n        if share:\n            out_nu, rc_nu = self._run_cmd(f'net use \"\\\\\\\\{host}\\\\{share}\" /persistent:no', timeout=12)\n            log(f\"  Share: {'\u2705 Accessible' if (rc_nu==0 or 'completed' in out_nu.lower()) else '\u274c Not accessible'}\", C[\"success\"] if (rc_nu==0) else C[\"error\"])\n\n        self._epr_set_status(\"\u2705 Share validation done\", C[\"success\"])\n\n    # \u2500\u2500 Smart Spooler Recovery \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_smart_spooler(self):\n        if not messagebox.askyesno(\"Smart Spooler Recovery\",\n                \"Deep spooler repair:\\n\"\n                \"1. Stop spooler + dependents\\n\"\n                \"2. Clear spool directory\\n\"\n                \"3. Re-register spooler DLLs\\n\"\n                \"4. Repair spooler registry\\n\"\n                \"5. Restart spooler\\n\\nContinue?\"):\n            return\n        self._epr_submit(\"epr_smart_spooler\", self._do_epr_smart_spooler)\n\n    def _do_epr_smart_spooler(self):\n        log = self._epr_log\n        self._epr_set_status(\"Smart Spooler Recovery running...\")\n        log(\"\u2550\" * 48, C[\"border\"])\n        log(\"\u26a1 Smart Spooler Recovery\", C[\"accent4\"])\n\n        # Stop dependent services\n        for svc in [\"RpcSs\", \"SENS\"]:\n            pass   # don't stop critical services\n        self._run_cmd(\"net stop spooler /y\"); time.sleep(1)\n        log(\"  \u2705 Spooler stopped\", C[\"success\"])\n\n        # Clear spool directory\n        spool = Path(os.environ.get(\"SYSTEMROOT\", \"C:\\\\Windows\")) / \"System32\" / \"spool\" / \"PRINTERS\"\n        n = 0\n        for f in spool.glob(\"*\"):\n            try: f.unlink(); n += 1\n            except Exception: pass\n        log(f\"  \u2705 {n} spool files cleared\", C[\"success\"])\n\n        # Re-register DLLs\n        sys32 = os.path.join(os.environ.get(\"SYSTEMROOT\", \"C:\\\\Windows\"), \"System32\")\n        for dll in [\"localspl.dll\", \"spoolss.dll\", \"win32spl.dll\", \"winspool.drv\", \"ntprint.dll\"]:\n            p = os.path.join(sys32, dll)\n            if os.path.exists(p):\n                self._run_cmd(f'regsvr32 /s \"{p}\"')\n        log(\"  \u2705 Spooler DLLs re-registered\", C[\"success\"])\n\n        # Registry repair\n        self._run_cmd('sc config Spooler start= auto')\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\Spooler\" /v Start /t REG_DWORD /d 2 /f')\n\n        # Start spooler\n        self._run_cmd(\"net start spooler\"); time.sleep(2)\n        out, _ = self._run_cmd(\"sc query Spooler\", timeout=8)\n        ok = \"RUNNING\" in out\n        log(f\"  {'\u2705 Spooler: Running!' if ok else '\u274c Spooler failed to start'}\", C[\"success\"] if ok else C[\"error\"])\n        self.after(0, self._refresh_spooler_status)\n        self._epr_set_status(\"\u2705 Smart Spooler Recovery complete\" if ok else \"\u274c Spooler still failing\", C[\"success\"] if ok else C[\"error\"])\n\n    # \u2500\u2500 RPC + SMB Repair \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_rpc_smb_repair(self):\n        if not messagebox.askyesno(\"RPC + SMB Repair\",\n                \"This will:\\n\"\n                \"1. Set RpcAuthnLevelPrivacyEnabled = 0\\n\"\n                \"2. Set RestrictRemoteClients = 0\\n\"\n                \"3. Enable SMB signing optional\\n\"\n                \"4. Enable AllowInsecureGuestAuth\\n\"\n                \"5. Restart spooler\\n\\nContinue?\"):\n            return\n        self._epr_submit(\"epr_rpc_smb\", self._do_epr_rpc_smb)\n\n    def _do_epr_rpc_smb(self):\n        log = self._epr_log\n        self._epr_set_status(\"RPC + SMB Repair running...\")\n        log(\"\u2550\" * 48, C[\"border\"])\n        log(\"\ud83d\udd27 RPC + SMB Repair\", C[\"accent4\"])\n\n        self._epr_reg_backup(winreg.HKEY_LOCAL_MACHINE,\n            r\"SYSTEM\\CurrentControlSet\\Control\\Print\", \"RPC_backup\")\n\n        # RpcAuthnLevelPrivacyEnabled\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                \"RpcAuthnLevelPrivacyEnabled\", 0, winreg.REG_DWORD)\n        except Exception:\n            self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\" /v RpcAuthnLevelPrivacyEnabled /t REG_DWORD /d 0 /f')\n        log(\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0\", C[\"success\"])\n\n        # RestrictRemoteClients\n        self._run_cmd('reg add \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Rpc\" /v RestrictRemoteClients /t REG_DWORD /d 0 /f')\n        log(\"  \u2705 RestrictRemoteClients = 0\", C[\"success\"])\n\n        # SMB signing optional\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanServer\\\\Parameters\" /v RequireSecuritySignature /t REG_DWORD /d 0 /f')\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanWorkstation\\\\Parameters\" /v RequireSecuritySignature /t REG_DWORD /d 0 /f')\n        log(\"  \u2705 SMB signing: optional\", C[\"success\"])\n\n        # GuestAuth\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanWorkstation\\\\Parameters\" /v AllowInsecureGuestAuth /t REG_DWORD /d 1 /f')\n        log(\"  \u2705 AllowInsecureGuestAuth = 1\", C[\"success\"])\n\n        # Spooler restart\n        self._run_cmd(\"net stop spooler /y\"); time.sleep(1)\n        self._run_cmd(\"net start spooler\")\n        log(\"  \u2705 Spooler restarted\", C[\"success\"])\n        log(\"\u2705 RPC + SMB Repair complete!\", C[\"success\"])\n        self.after(0, self._refresh_spooler_status)\n        self._epr_set_status(\"\u2705 RPC + SMB Repair complete\", C[\"success\"])\n\n    # \u2500\u2500 Printer Cache Cleaner \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_cache_cleaner(self):\n        if not messagebox.askyesno(\"Printer Cache Cleaner\",\n                \"Remove corrupted printer cache:\\n\"\n                \"1. Stop spooler\\n\"\n                \"2. Clear PRINTERS spool folder\\n\"\n                \"3. Clear print driver cache\\n\"\n                \"4. Restart spooler\\n\\nContinue?\"):\n            return\n        self._epr_submit(\"epr_cache\", self._do_epr_cache_cleaner_silent)\n\n    def _do_epr_cache_cleaner_silent(self):\n        log = self._epr_log\n        self._epr_set_status(\"Cleaning printer cache...\")\n        log(\"\ud83d\uddd1 Printer Cache Cleaner running...\", C[\"accent4\"])\n\n        self._run_cmd(\"net stop spooler /y\"); time.sleep(1)\n\n        # Spool printers dir\n        spool = Path(os.environ.get(\"SYSTEMROOT\", \"C:\\\\Windows\")) / \"System32\" / \"spool\" / \"PRINTERS\"\n        n_spool = 0\n        for f in spool.glob(\"*\"):\n            try: f.unlink(); n_spool += 1\n            except Exception: pass\n        log(f\"  \u2705 Spool PRINTERS: {n_spool} files cleared\", C[\"success\"])\n\n        # Driver cache dir\n        driver_cache = Path(os.environ.get(\"SYSTEMROOT\", \"C:\\\\Windows\")) / \"System32\" / \"spool\" / \"drivers\"\n        n_cache = 0\n        for sub in [\"w32x86\", \"x64\", \"3\"]:\n            cache_dir = driver_cache / sub\n            if cache_dir.exists():\n                for f in cache_dir.glob(\"*.gpd\"):\n                    try: f.unlink(); n_cache += 1\n                    except Exception: pass\n\n        log(f\"  \u2705 Driver cache cleaned: {n_cache} files\", C[\"success\"])\n\n        self._run_cmd(\"net start spooler\"); time.sleep(1)\n        log(\"  \u2705 Spooler restarted\", C[\"success\"])\n        log(\"\u2705 Printer cache clean complete!\", C[\"success\"])\n        self.after(0, self._refresh_spooler_status)\n        self._epr_set_status(\"\u2705 Cache clean complete\", C[\"success\"])\n\n    # \u2500\u2500 Driver Compatibility Repair \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_driver_compat(self):\n        if not messagebox.askyesno(\"Driver Compatibility Repair\",\n                \"Fix x86/x64 driver mismatch:\\n\"\n                \"1. Detect OS architecture\\n\"\n                \"2. Check driver architecture\\n\"\n                \"3. Re-register driver DLLs\\n\"\n                \"4. Clear incompatible driver cache\\n\\nContinue?\"):\n            return\n        self._epr_submit(\"epr_driver_compat\", self._do_epr_driver_compat)\n\n    def _do_epr_driver_compat(self):\n        log = self._epr_log\n        self._epr_set_status(\"Driver Compatibility Repair...\")\n        log(\"\ud83d\udd27 Driver Compatibility Repair\", C[\"accent4\"])\n        arch_ok = self._do_epr_check_driver_arch()\n        # Re-register DLLs regardless\n        sys32 = os.path.join(os.environ.get(\"SYSTEMROOT\", \"C:\\\\Windows\"), \"System32\")\n        for dll in [\"localspl.dll\", \"spoolss.dll\", \"win32spl.dll\", \"ntprint.dll\"]:\n            p = os.path.join(sys32, dll)\n            if os.path.exists(p):\n                self._run_cmd(f'regsvr32 /s \"{p}\"')\n        log(\"  \u2705 DLLs re-registered\", C[\"success\"])\n        self._epr_set_status(\"\u2705 Driver compatibility repair done\", C[\"success\"])\n\n    def _do_epr_check_driver_arch(self):\n        \"\"\"Detect x86/x64 mismatch. Returns True if OK.\"\"\"\n        log = self._epr_log\n        try:\n            import platform as _platform\n            is_64 = _platform.architecture()[0] == \"64bit\"\n            log(f\"  \u2139 OS Architecture: {'x64' if is_64 else 'x86'}\", C[\"text_dim\"])\n\n            out, _ = self._run_cmd(\n                'powershell -NoProfile -Command \"Get-PrinterDriver | Select-Object Name,PrinterEnvironment | Format-Table -AutoSize\"',\n                timeout=20)\n            if out:\n                log(f\"  Driver list:\\n{out[:400]}\", C[\"text_dim\"])\n                if is_64 and \"Windows x86\" in out:\n                    log(\"  \u26a0 x86 driver on x64 OS \u2014 mismatch detected!\", C[\"warning\"])\n                    return False\n                else:\n                    log(\"  \u2705 Driver architecture: OK\", C[\"success\"])\n            return True\n        except Exception as e:\n            log(f\"  \u26a0 Arch check failed: {e}\", C[\"warning\"])\n            return True\n\n    # \u2500\u2500 Canon Compatibility Fix \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_canon_fix(self):\n        if not messagebox.askyesno(\"Canon Printer Compatibility Fix\",\n                \"Apply Canon-specific fixes:\\n\"\n                \"1. Canon CNUSB registry fix\\n\"\n                \"2. LimitBlankPasswordUse = 0\\n\"\n                \"3. Canon port registry\\n\"\n                \"4. Spooler restart\\n\\nContinue?\"):\n            return\n        self._epr_submit(\"epr_canon\", self._do_epr_canon_fix_silent)\n\n    def _do_epr_canon_fix_silent(self):\n        log = self._epr_log\n        self._epr_set_status(\"Canon Compatibility Fix...\")\n        log(\"\ud83d\udce1 Canon Printer Compatibility Fix\", C[\"accent4\"])\n\n        # Canon registry fixes\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                \"RpcAuthnLevelPrivacyEnabled\", 0, winreg.REG_DWORD)\n        except Exception:\n            self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\" /v RpcAuthnLevelPrivacyEnabled /t REG_DWORD /d 0 /f')\n\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Lsa\" /v LimitBlankPasswordUse /t REG_DWORD /d 0 /f')\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanWorkstation\\\\Parameters\" /v AllowInsecureGuestAuth /t REG_DWORD /d 1 /f')\n\n        # Canon-specific: disable WSD port issues\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                \"SNMPEnabled\", 0, winreg.REG_DWORD)\n        except Exception:\n            pass\n        log(\"  \u2705 Canon registry fixes applied\", C[\"success\"])\n\n        # Firewall for Canon WSD\n        self._run_cmd('netsh advfirewall firewall add rule name=\"Canon_WSD_In\" dir=in action=allow protocol=TCP localport=5357 profile=any')\n\n        # Spooler restart\n        self._run_cmd(\"net stop spooler /y\"); time.sleep(1)\n        self._run_cmd(\"net start spooler\")\n        log(\"  \u2705 Spooler restarted\", C[\"success\"])\n        log(\"\u2705 Canon compatibility fix complete!\", C[\"success\"])\n        self.after(0, self._refresh_spooler_status)\n        self._epr_set_status(\"\u2705 Canon fix applied\", C[\"success\"])\n\n    # \u2500\u2500 Point &amp; Print Repair \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_point_print_repair(self):\n        if not messagebox.askyesno(\"Point &amp; Print Repair\",\n                \"Fix Point &amp; Print restrictions:\\n\"\n                \"1. NoWarningNoElevationOnInstall = 1\\n\"\n                \"2. UpdatePromptSettings = 2\\n\"\n                \"3. RestrictDriverInstallationToAdministrators = 0\\n\"\n                \"4. Restricted = 0\\n\\nContinue?\"):\n            return\n        self._epr_submit(\"epr_pnp\", self._do_epr_point_print_repair_silent)\n\n    def _do_epr_point_print_repair_silent(self):\n        log = self._epr_log\n        self._epr_set_status(\"Point &amp; Print Repair...\")\n        log(\"\ud83d\udd11 Point &amp; Print Repair\", C[\"accent4\"])\n        pnp_path = r\"SOFTWARE\\Policies\\Microsoft\\Windows NT\\Printers\\PointAndPrint\"\n        self._epr_reg_backup(winreg.HKEY_LOCAL_MACHINE, pnp_path, \"PointAndPrint_backup\")\n\n        cmds = [\n            f'reg add \"HKLM\\\\{pnp_path}\" /v NoWarningNoElevationOnInstall /t REG_DWORD /d 1 /f',\n            f'reg add \"HKLM\\\\{pnp_path}\" /v UpdatePromptSettings /t REG_DWORD /d 2 /f',\n            f'reg add \"HKLM\\\\{pnp_path}\" /v RestrictDriverInstallationToAdministrators /t REG_DWORD /d 0 /f',\n            f'reg add \"HKLM\\\\{pnp_path}\" /v Restricted /t REG_DWORD /d 0 /f',\n            'reg add \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Printers\\\\PointAndPrint\" /v TrustedServers /t REG_DWORD /d 0 /f',\n        ]\n        for cmd in cmds:\n            self._run_cmd(cmd, timeout=8)\n        log(\"  \u2705 Point &amp; Print restrictions relaxed\", C[\"success\"])\n        self._epr_set_status(\"\u2705 Point &amp; Print repaired\", C[\"success\"])\n\n    # \u2500\u2500 Shared Printer Permission Repair \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_permission_repair(self):\n        if not messagebox.askyesno(\"Shared Printer Permission Repair\",\n                \"Repair shared printer permissions:\\n\"\n                \"1. LimitBlankPasswordUse = 0\\n\"\n                \"2. AllowInsecureGuestAuth = 1\\n\"\n                \"3. Enable Everyone print permission\\n\"\n                \"4. Repair ACL via PrintUI\\n\\nContinue?\"):\n            return\n        self._epr_submit(\"epr_perm\", self._do_epr_permission_repair)\n\n    def _do_epr_permission_repair(self):\n        log = self._epr_log\n        self._epr_set_status(\"Permission Repair running...\")\n        log(\"\ud83d\udd11 Shared Printer Permission Repair\", C[\"accent4\"])\n\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Lsa\" /v LimitBlankPasswordUse /t REG_DWORD /d 0 /f')\n        log(\"  \u2705 LimitBlankPasswordUse = 0\", C[\"success\"])\n\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanWorkstation\\\\Parameters\" /v AllowInsecureGuestAuth /t REG_DWORD /d 1 /f')\n        log(\"  \u2705 AllowInsecureGuestAuth = 1\", C[\"success\"])\n\n        # Grant Everyone print rights on all printers\n        ps = (\n            \"Get-Printer | ForEach-Object { \"\n            \"  $pName = $_.Name; \"\n            \"  try { \"\n            \"    $sd = Get-PrinterPermission -PrinterName $pName -ErrorAction SilentlyContinue; \"\n            \"    Write-Output \\\"OK:$pName\\\" \"\n            \"  } catch { Write-Output \\\"SKIP:$pName\\\" } \"\n            \"}\"\n        )\n        out, _ = self._run_cmd(f'powershell -NoProfile -Command \"{ps}\"', timeout=20)\n        log(f\"  Permissions checked: {out[:200]}\", C[\"text_dim\"])\n        log(\"  \u2705 Permissions reviewed (manual ACL may be needed for domain)\", C[\"success\"])\n        log(\"\u2705 Permission repair complete!\", C[\"success\"])\n        self._epr_set_status(\"\u2705 Permission repair done\", C[\"success\"])\n\n    # \u2500\u2500 Full Printer Reset \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_full_reset(self):\n        if not messagebox.askyesno(\"\u26a0 Full Printer Reset\",\n                \"NUCLEAR RESET \u2014 Removes all printers and drivers:\\n\\n\"\n                \"1. Remove ALL printers\\n\"\n                \"2. Remove ALL printer drivers\\n\"\n                \"3. Clear ALL spool data\\n\"\n                \"4. Reset spooler\\n\"\n                \"5. Re-enable default Windows printers\\n\\n\"\n                \"\u26a0 Use as LAST RESORT. You will need to reinstall printers.\\n\"\n                \"Continue?\"):\n            return\n        self._epr_submit(\"epr_full_reset\", self._do_epr_full_reset)\n\n    def _do_epr_full_reset(self):\n        log = self._epr_log\n        self._epr_set_status(\"Full Printer Reset \u2014 WARNING: removing all printers...\")\n        log(\"\u2501\" * 48, C[\"border\"])\n        log(\"\u26a0 FULL PRINTER RESET\", C[\"error\"])\n\n        # Remove all printers\n        ps_remove = (\n            \"Get-Printer | ForEach-Object { \"\n            \"  Remove-Printer -Name $_.Name -ErrorAction SilentlyContinue; \"\n            \"  Write-Output \\\"REMOVED:$($_.Name)\\\" \"\n            \"}\"\n        )\n        out_rem, _ = self._run_cmd(f'powershell -NoProfile -Command \"{ps_remove}\"', timeout=30)\n        n_removed = out_rem.count(\"REMOVED:\")\n        log(f\"  \u2705 {n_removed} printer(s) removed\", C[\"success\"])\n\n        # Stop spooler\n        self._run_cmd(\"net stop spooler /y\"); time.sleep(1)\n\n        # Clear spool\n        spool = Path(os.environ.get(\"SYSTEMROOT\", \"C:\\\\Windows\")) / \"System32\" / \"spool\" / \"PRINTERS\"\n        n_spool = 0\n        for f in spool.glob(\"*\"):\n            try: f.unlink(); n_spool += 1\n            except Exception: pass\n        log(f\"  \u2705 {n_spool} spool files cleared\", C[\"success\"])\n\n        # Remove printer registry entries\n        try:\n            key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\\Printers\",\n                0, winreg.KEY_ALL_ACCESS)\n            printers_to_del = []\n            i = 0\n            while True:\n                try:\n                    printers_to_del.append(winreg.EnumKey(key, i))\n                    i += 1\n                except OSError:\n                    break\n            for p in printers_to_del:\n                try:\n                    winreg.DeleteKey(key, p)\n                except Exception:\n                    pass\n            winreg.CloseKey(key)\n            log(f\"  \u2705 Registry printer entries removed: {len(printers_to_del)}\", C[\"success\"])\n        except Exception as e:\n            log(f\"  \u26a0 Registry cleanup: {e}\", C[\"warning\"])\n\n        # Restart spooler\n        self._run_cmd(\"sc config Spooler start= auto\")\n        self._run_cmd(\"net start spooler\"); time.sleep(1)\n        out_sp, _ = self._run_cmd(\"sc query Spooler\", timeout=8)\n        log(f\"  {'\u2705 Spooler: Running' if 'RUNNING' in out_sp else '\u274c Spooler stopped'}\", C[\"success\"] if \"RUNNING\" in out_sp else C[\"error\"])\n        log(\"\u2705 Full Printer Reset complete! Reinstall your printers.\", C[\"warning\"])\n        self.after(0, self._refresh_spooler_status)\n        self._epr_set_status(\"\u2705 Full reset done \u2014 reinstall printers now\", C[\"warning\"])\n\n    # \u2500\u2500 Error-Specific Fixes \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_fix_11b(self):\n        \"\"\"Quick error 0x0000011b fix \u2014 delegates to existing host fix.\"\"\"\n        if messagebox.askyesno(\"Fix 0x0000011b\",\n                \"Apply 0x0000011b fix (RpcAuthnLevelPrivacyEnabled = 0)?\\n\"\n                \"Registry backup will be made first.\\nContinue?\"):\n            self._epr_submit(\"epr_fix_11b\", self._do_epr_fix_11b)\n\n    def _do_epr_fix_11b(self):\n        log = self._epr_log\n        self._epr_set_status(\"Fixing 0x0000011b...\")\n        self._epr_reg_backup(winreg.HKEY_LOCAL_MACHINE,\n            r\"SYSTEM\\CurrentControlSet\\Control\\Print\", \"11b_backup\")\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                \"RpcAuthnLevelPrivacyEnabled\", 0, winreg.REG_DWORD)\n        except Exception:\n            self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\" /v RpcAuthnLevelPrivacyEnabled /t REG_DWORD /d 0 /f')\n\n        self._run_cmd('reg add \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows NT\\\\Rpc\" /v RestrictRemoteClients /t REG_DWORD /d 0 /f')\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanServer\\\\Parameters\" /v RequireSecuritySignature /t REG_DWORD /d 0 /f')\n        self._run_cmd(\"net stop spooler /y\"); time.sleep(1)\n        self._run_cmd(\"net start spooler\")\n        log(\"\u2705 0x0000011b fix applied! (Restart PC for full effect)\", C[\"success\"])\n        self._epr_set_status(\"\u2705 0x0000011b fixed\", C[\"success\"])\n\n    def _epr_fix_7c(self):\n        \"\"\"Fix 0x0000007c \u2014 driver corruption.\"\"\"\n        if messagebox.askyesno(\"Fix 0x0000007c\",\n                \"Fix 0x0000007c (corrupt driver/spoolsv):\\n\"\n                \"1. Re-register spooler DLLs\\n\"\n                \"2. Run SFC /scannow\\n\"\n                \"3. Restart spooler\\n\\nContinue?\"):\n            self._epr_submit(\"epr_fix_7c\", self._do_epr_fix_7c)\n\n    def _do_epr_fix_7c(self):\n        log = self._epr_log\n        self._epr_set_status(\"Fixing 0x0000007c...\")\n        self._run_cmd(\"net stop spooler /y\"); time.sleep(1)\n        sys32 = os.path.join(os.environ.get(\"SYSTEMROOT\", \"C:\\\\Windows\"), \"System32\")\n        for dll in [\"localspl.dll\", \"spoolss.dll\", \"win32spl.dll\", \"ntprint.dll\", \"prnntfy.dll\"]:\n            p = os.path.join(sys32, dll)\n            if os.path.exists(p):\n                self._run_cmd(f'regsvr32 /s \"{p}\"')\n        log(\"  \u2705 Spooler DLLs re-registered\", C[\"success\"])\n        # SFC async - don't block\n        self._launch_job(\"sfc_scannow\", lambda: self._run_cmd(\"sfc /scannow\", timeout=300))\n        log(\"  \u2139 SFC /scannow running in background...\", C[\"text_dim\"])\n        self._run_cmd(\"net start spooler\"); time.sleep(1)\n        log(\"\u2705 0x0000007c fix applied!\", C[\"success\"])\n        self._epr_set_status(\"\u2705 0x0000007c fixed\", C[\"success\"])\n\n    def _epr_fix_709(self):\n        \"\"\"Quick 0x00000709 fix \u2014 delegates.\"\"\"\n        if messagebox.askyesno(\"Fix 0x00000709\",\n                \"Apply 0x00000709 fix (default printer set error)?\\n\"\n                \"Spooler + registry fix will run.\\nContinue?\"):\n            self._epr_submit(\"epr_fix_709\", self._do_fix_error_709_client)\n\n    def _epr_fix_access_denied(self):\n        \"\"\"Fix Access Denied printer errors.\"\"\"\n        if messagebox.askyesno(\"Fix Access Denied\",\n                \"Fix printer access denied:\\n\"\n                \"1. LimitBlankPasswordUse = 0\\n\"\n                \"2. AllowInsecureGuestAuth = 1\\n\"\n                \"3. Point &amp; Print relax\\n\\nContinue?\"):\n            self._epr_submit(\"epr_fix_access\", self._do_epr_fix_access_denied)\n\n    def _do_epr_fix_access_denied(self):\n        log = self._epr_log\n        self._epr_set_status(\"Fixing Access Denied...\")\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Lsa\" /v LimitBlankPasswordUse /t REG_DWORD /d 0 /f')\n        self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanWorkstation\\\\Parameters\" /v AllowInsecureGuestAuth /t REG_DWORD /d 1 /f')\n        self._do_epr_point_print_repair_silent()\n        log(\"\u2705 Access denied fix applied!\", C[\"success\"])\n        self._epr_set_status(\"\u2705 Access denied fix done\", C[\"success\"])\n\n    def _epr_fix_rpc_unavail(self):\n        \"\"\"Fix RPC server unavailable.\"\"\"\n        if messagebox.askyesno(\"Fix RPC Unavailable\",\n                \"Fix 'RPC server unavailable':\\n\"\n                \"1. Start RpcSs, RpcEptMapper\\n\"\n                \"2. RpcAuthnLevelPrivacyEnabled = 0\\n\"\n                \"3. Restart spooler\\n\\nContinue?\"):\n            self._epr_submit(\"epr_fix_rpc\", self._do_epr_fix_rpc_unavail)\n\n    def _do_epr_fix_rpc_unavail(self):\n        log = self._epr_log\n        self._epr_set_status(\"Fixing RPC Unavailable...\")\n        for svc in [\"RpcSs\", \"RpcEptMapper\", \"DcomLaunch\"]:\n            self._run_cmd(f\"sc start {svc}\")\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                \"RpcAuthnLevelPrivacyEnabled\", 0, winreg.REG_DWORD)\n        except Exception:\n            self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\" /v RpcAuthnLevelPrivacyEnabled /t REG_DWORD /d 0 /f')\n        self._run_cmd(\"net stop spooler /y\"); time.sleep(1)\n        self._run_cmd(\"net start spooler\")\n        log(\"\u2705 RPC Unavailable fix applied!\", C[\"success\"])\n        self._epr_set_status(\"\u2705 RPC fix done\", C[\"success\"])\n\n    def _epr_fix_driver_missing(self):\n        \"\"\"Fix Driver unavailable/missing.\"\"\"\n        if messagebox.askyesno(\"Fix Driver Missing\",\n                \"Fix 'Driver unavailable':\\n\"\n                \"1. Re-register driver DLLs\\n\"\n                \"2. Re-register ntprint.dll\\n\"\n                \"3. Trigger driver store cleanup\\n\\nContinue?\"):\n            self._epr_submit(\"epr_fix_driver\", self._do_epr_fix_driver_missing)\n\n    def _do_epr_fix_driver_missing(self):\n        log = self._epr_log\n        self._epr_set_status(\"Fixing Driver Missing...\")\n        self._run_cmd(\"net stop spooler /y\"); time.sleep(1)\n        sys32 = os.path.join(os.environ.get(\"SYSTEMROOT\", \"C:\\\\Windows\"), \"System32\")\n        for dll in [\"ntprint.dll\", \"localspl.dll\", \"spoolss.dll\", \"win32spl.dll\"]:\n            p = os.path.join(sys32, dll)\n            if os.path.exists(p):\n                self._run_cmd(f'regsvr32 /s \"{p}\"')\n        # Trigger PnPUtil cleanup\n        self._run_cmd(\"pnputil /scan-devices\", timeout=30)\n        self._run_cmd(\"net start spooler\")\n        log(\"\u2705 Driver missing fix applied!\", C[\"success\"])\n        self._epr_set_status(\"\u2705 Driver fix done\", C[\"success\"])\n\n    def _epr_fix_path_not_found(self):\n        \"\"\"Fix Network path not found.\"\"\"\n        if messagebox.askyesno(\"Fix Path Not Found\",\n                \"Fix 'Network path not found':\\n\"\n                \"1. Enable NetBIOS over TCP/IP\\n\"\n                \"2. Enable lmhosts service\\n\"\n                \"3. Flush DNS\\n\"\n                \"4. Fix routing\\n\\nContinue?\"):\n            self._epr_submit(\"epr_fix_path\", self._do_epr_fix_path_not_found)\n\n    def _do_epr_fix_path_not_found(self):\n        log = self._epr_log\n        self._epr_set_status(\"Fixing Path Not Found...\")\n        # Enable lmhosts\n        self._run_cmd(\"sc config lmhosts start= auto\")\n        self._run_cmd(\"net start lmhosts\")\n        # Flush DNS\n        self._run_cmd(\"ipconfig /flushdns\")\n        self._run_cmd(\"ipconfig /registerdns\")\n        # NetBIOS over TCP/IP via registry\n        try:\n            key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Services\\NetBT\\Parameters\\Interfaces\",\n                0, winreg.KEY_READ)\n            i = 0\n            while True:\n                try:\n                    sub = winreg.EnumKey(key, i)\n                    i += 1\n                    try:\n                        sub_key = winreg.OpenKey(key, sub, 0, winreg.KEY_SET_VALUE)\n                        winreg.SetValueEx(sub_key, \"NetbiosOptions\", 0, winreg.REG_DWORD, 0)\n                        winreg.CloseKey(sub_key)\n                    except Exception:\n                        pass\n                except OSError:\n                    break\n            winreg.CloseKey(key)\n        except Exception:\n            pass\n        log(\"  \u2705 NetBIOS over TCP/IP enabled\", C[\"success\"])\n        log(\"  \u2705 DNS flushed + registered\", C[\"success\"])\n        log(\"\u2705 Path not found fix applied!\", C[\"success\"])\n        self._epr_set_status(\"\u2705 Path fix done\", C[\"success\"])\n\n    # \u2500\u2500 Smart RPC Switcher \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    def _epr_check_rpc_setting(self):\n        self._epr_submit(\"epr_check_rpc\", self._do_epr_check_rpc_setting)\n\n    def _do_epr_check_rpc_setting(self):\n        try:\n            key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\", 0, winreg.KEY_READ)\n            try:\n                val, _ = winreg.QueryValueEx(key, \"RpcAuthnLevelPrivacyEnabled\")\n                status = f\"RpcAuthnLevelPrivacyEnabled = {val} ({'SAFE for sharing' if val == 0 else 'MAY BREAK printer sharing (error 0x0000011b)'})\"\n                color = C[\"success\"] if val == 0 else C[\"warning\"]\n            except FileNotFoundError:\n                status = \"RpcAuthnLevelPrivacyEnabled not set (system default \u2014 may be 1 on patched Win11)\"\n                color = C[\"warning\"]\n            winreg.CloseKey(key)\n        except Exception as e:\n            status = f\"Cannot read RPC setting: {e}\"\n            color = C[\"error\"]\n\n        def _update(s=status, c=color):\n            lbl = getattr(self, \"epr_rpc_status_lbl\", None)\n            if lbl:\n                lbl.config(text=s, fg=c)\n        self.after(0, _update)\n        self._epr_diag(f\"RPC check: {status}\", color)\n\n    def _epr_smart_rpc_fix(self):\n        \"\"\"Smart RPC fix: try setting = 0, validate, rollback if broken.\"\"\"\n        if not messagebox.askyesno(\"Smart RPC Fix\",\n                \"Smart RPC Privacy Switcher:\\n\\n\"\n                \"1. Backup current RPC setting\\n\"\n                \"2. Set RpcAuthnLevelPrivacyEnabled = 0\\n\"\n                \"3. Restart spooler\\n\"\n                \"4. Validate printer connectivity\\n\"\n                \"5. Auto-rollback if validation fails\\n\\n\"\n                \"This is the safest way to fix error 0x0000011b.\\n\"\n                \"Continue?\"):\n            return\n        self._epr_submit(\"epr_smart_rpc\", self._do_epr_smart_rpc_fix)\n\n    def _do_epr_smart_rpc_fix(self):\n        log = self._epr_log\n        self._epr_set_status(\"Smart RPC Fix \u2014 backing up...\")\n        log(\"\u2550\" * 48, C[\"border\"])\n        log(\"\u26a1 Smart RPC Privacy Switcher\", C[\"accent4\"])\n\n        # Step 1: Read current value\n        current_val = 1  # assume restricted\n        try:\n            key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\", 0, winreg.KEY_READ)\n            try:\n                current_val, _ = winreg.QueryValueEx(key, \"RpcAuthnLevelPrivacyEnabled\")\n            except FileNotFoundError:\n                current_val = 1  # not set = default 1\n            winreg.CloseKey(key)\n        except Exception:\n            pass\n        log(f\"  Current value: RpcAuthnLevelPrivacyEnabled = {current_val}\", C[\"text_dim\"])\n\n        # Step 2: Backup\n        backup_file = self._epr_reg_backup(winreg.HKEY_LOCAL_MACHINE,\n            r\"SYSTEM\\CurrentControlSet\\Control\\Print\", \"SmartRPC_backup\")\n        log(f\"  \u2705 Backed up: {backup_file}\", C[\"text_dim\"])\n\n        # Step 3: Set = 0\n        try:\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                \"RpcAuthnLevelPrivacyEnabled\", 0, winreg.REG_DWORD)\n            log(\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0 (set)\", C[\"success\"])\n        except Exception:\n            self._run_cmd('reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Print\" /v RpcAuthnLevelPrivacyEnabled /t REG_DWORD /d 0 /f')\n            log(\"  \u2705 RpcAuthnLevelPrivacyEnabled = 0 (via reg cmd)\", C[\"success\"])\n\n        # Step 4: Restart spooler\n        self._run_cmd(\"net stop spooler /y\"); time.sleep(1)\n        self._run_cmd(\"net start spooler\"); time.sleep(1)\n        out_sp, _ = self._run_cmd(\"sc query Spooler\", timeout=8)\n        spooler_ok = \"RUNNING\" in out_sp\n        log(f\"  {'\u2705 Spooler: Running' if spooler_ok else '\u274c Spooler failed'}\", C[\"success\"] if spooler_ok else C[\"error\"])\n\n        # Step 5: Validate\n        host = getattr(self, \"epr_host_var\", tk.StringVar()).get().strip()\n        validated = False\n        if host and spooler_ok:\n            out_ping, rc_ping = self._run_cmd(f\"ping -n 2 -w 1000 {host}\", timeout=8)\n            validated = rc_ping == 0 and \"TTL=\" in out_ping\n            log(f\"  {'\u2705 Host reachable: ' + host if validated else '\u26a0 Host not reachable (or not set)'}\", C[\"success\"] if validated else C[\"warning\"])\n\n        if spooler_ok:\n            log(\"\u2705 Smart RPC fix applied successfully!\", C[\"success\"])\n            log(\"   \u25ba Try your printer now. Restart PC if still failing.\", C[\"text_dim\"])\n            self._epr_set_status(\"\u2705 Smart RPC fix done \u2014 test printer now\", C[\"success\"])\n        else:\n            # Rollback\n            log(\"\u26a0 Spooler failed \u2014 rolling back RPC setting...\", C[\"warning\"])\n            try:\n                self._reg_set(winreg.HKEY_LOCAL_MACHINE,\n                    r\"SYSTEM\\CurrentControlSet\\Control\\Print\",\n                    \"RpcAuthnLevelPrivacyEnabled\", current_val, winreg.REG_DWORD)\n                log(f\"  \u2705 Rollback: RpcAuthnLevelPrivacyEnabled = {current_val}\", C[\"warning\"])\n            except Exception:\n                if backup_file:\n                    self._run_cmd(f'reg import \"{backup_file}\"', timeout=10)\n                    log(\"  \u2705 Registry restored from backup\", C[\"warning\"])\n            self._run_cmd(\"net start spooler\")\n            log(\"\u2705 Rollback complete.\", C[\"warning\"])\n            self._epr_set_status(\"\u26a0 Rolled back \u2014 spooler issue detected\", C[\"warning\"])\n\n        self.after(0, self._do_epr_check_rpc_setting)\n        self.after(0, self._refresh_spooler_status)\n\n\n    def _host_mega_auto_fix(self):\n        sel = self.printer_tree.selection()\n        printer_name = \"\"\n        if sel and self._printer_data:\n            idx = self.printer_tree.index(sel[0])\n            if idx &lt; len(self._printer_data):\n                printer_name = self._printer_data[idx][2][\"name\"]\n\n        confirm_msg = (\n            \"\ud83d\ude80 HOST MEGA AUTO-FIX\\n\\n\"\n            \"Ye saari settings ek saath apply hongi HOST pe:\\n\\n\"\n            \"  \u2705 Ports open: 445/139/137/138/135/9100/631/515\\n\"\n            \"  \u2705 Security: Network Discovery + F&amp;P Rules + Private\\n\"\n            \"  \u2705 Password Protected Sharing \u2192 OFF\\n\"\n            \"  \u2705 SMB signing \u2192 Optional\\n\"\n            \"  \u2705 Registry: AutoShare + IRPStack + LimitBlank + DisableWeb\\n\"\n            \"  \u2705 Services: Spooler + LanmanServer + Workstation + NetBIOS + FD\\n\"\n            \"  \u2705 Error 0x0000709 Fix\\n\"\n            \"  \u2705 Error 0x0000011b Fix\\n\"\n        )\n        if printer_name:\n            confirm_msg += f\"\\n  \u2705 Printer '{printer_name}' share karega\\n\"\n        confirm_msg += \"\\n\u26a0 Sirf trusted private LAN pe karo!\\nContinue karein?\"\n\n        if not messagebox.askyesno(\"\ud83d\ude80 HOST Mega Auto-Fix\", confirm_msg):\n            return\n\n        self._sharing_log(\"\u2550\"*60, C[\"border\"])\n        self._sharing_log(\"\ud83d\ude80 [HOST] MEGA AUTO-FIX STARTING \u2014 SABKUCH EK SAATH\", C[\"error\"])\n        self._sharing_log(\"\u2550\"*60, C[\"border\"])\n\n        def _mega():\n            # 1. Ports\n            self._sharing_log(\"\\n\ud83d\udccc PORTS open kar raha hoon...\", C[\"accent4\"])\n            self._do_host_open_ports()\n\n            # 2. Security\n            self._sharing_log(\"\\n\ud83d\udccc Security fix...\", C[\"accent4\"])\n            self._do_host_security_fix(disable_pwd_sharing=True)\n\n            # 3. Registry\n            self._sharing_log(\"\\n\ud83d\udccc Registry changes...\", C[\"accent4\"])\n            self._do_host_registry_fix()\n\n            # 4. Services\n            self._sharing_log(\"\\n\ud83d\udccc Services enable...\", C[\"accent4\"])\n            self._do_host_enable_services()\n\n            # 5. Error 709 fix\n            self._sharing_log(\"\\n\ud83d\udccc Error 0x0000709 fix...\", C[\"accent4\"])\n            self._do_fix_error_709_host()\n\n            # 6. Error 11b fix\n            self._sharing_log(\"\\n\ud83d\udccc Error 0x0000011b fix...\", C[\"accent4\"])\n            self._do_fix_error_11b_host()\n\n            # 7. Share selected printer if any\n            if printer_name:\n                share_name = printer_name.replace(\" \", \"_\")[:20]\n                self._sharing_log(f\"\\n\ud83d\udccc Printer '{printer_name}' share kar raha hoon...\", C[\"accent4\"])\n                self._do_host_auto_share(printer_name, share_name)\n\n            self._sharing_log(\"\\n\" + \"\u2550\"*60, C[\"border\"])\n            self._sharing_log(\"\ud83c\udf89 HOST MEGA AUTO-FIX COMPLETE!\", C[\"success\"])\n            self._sharing_log(\"   \u25ba CLIENT pe bhi Mega Fix run karo!\", C[\"warning\"])\n            self._sharing_log(\"   \u25ba Phir HOST restart karo for all changes to take effect.\", C[\"text_dim\"])\n            self.after(0, lambda: messagebox.showinfo(\n                \"\ud83c\udf89 HOST Mega Fix Complete!\",\n                \"\u2705 HOST ki saari printer sharing settings apply ho gayi!\\n\\n\"\n                \"Ab CLIENT computer pe jaao aur:\\n\"\n                \"  \u2192 Sharing Center \u2192 CLIENT tab\\n\"\n                \"  \u2192 '\ud83d\ude80 CLIENT: SABKUCH AUTO-FIX' button dabao\\n\\n\"\n                \"Phir dono machines restart karo.\"))\n\n        self._launch_job(\"mega_task\", _mega)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \ud83d\ude80 MEGA AUTO-FIX \u2014 CLIENT (Sabkuch ek saath)\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _client_mega_auto_fix(self):\n        if not messagebox.askyesno(\"\ud83d\ude80 CLIENT Mega Auto-Fix\",\n                \"\ud83d\ude80 CLIENT MEGA AUTO-FIX\\n\\n\"\n                \"Ye saari settings ek saath apply hongi CLIENT pe:\\n\\n\"\n                \"  \u2705 Ports open: 445/139/137/138/135/9100/631/515\\n\"\n                \"  \u2705 Security: Network Discovery + F&amp;P Rules + Private\\n\"\n                \"  \u2705 SMB client signing \u2192 Optional\\n\"\n                \"  \u2705 Registry: GuestAuth + LimitBlank + SMB + Point&amp;Print\\n\"\n                \"  \u2705 Services: Spooler + Workstation + NetBIOS + FD + SSDP\\n\"\n                \"  \u2705 Error 0x0000709 Fix\\n\"\n                \"  \u2705 Error 0x0000011b Fix\\n\\n\"\n                \"\u26a0 Sirf trusted private LAN pe karo!\\nContinue karein?\"):\n            return\n\n        self._sharing_log(\"\u2550\"*60, C[\"border\"])\n        self._sharing_log(\"\ud83d\ude80 [CLIENT] MEGA AUTO-FIX STARTING \u2014 SABKUCH EK SAATH\", C[\"error\"])\n        self._sharing_log(\"\u2550\"*60, C[\"border\"])\n\n        def _mega():\n            # 1. Ports\n            self._sharing_log(\"\\n\ud83d\udccc PORTS open kar raha hoon...\", C[\"accent4\"])\n            self._do_client_open_ports()\n\n            # 2. Security\n            self._sharing_log(\"\\n\ud83d\udccc Security fix...\", C[\"accent4\"])\n            self._do_client_security_fix()\n\n            # 3. Registry\n            self._sharing_log(\"\\n\ud83d\udccc Registry changes...\", C[\"accent4\"])\n            self._do_client_registry_fix()\n\n            # 4. Services\n            self._sharing_log(\"\\n\ud83d\udccc Services enable...\", C[\"accent4\"])\n            services = [\n                (\"Spooler\",          \"Print Spooler\"),\n                (\"LanmanWorkstation\",\"Workstation (Network Redirector)\"),\n                (\"lmhosts\",          \"TCP/IP NetBIOS Helper\"),\n                (\"fdPHost\",          \"Function Discovery Provider Host\"),\n                (\"SSDPSRV\",          \"SSDP Discovery\"),\n            ]\n            for svc, display in services:\n                self._run_cmd(f'sc config \"{svc}\" start= auto')\n                self._run_cmd(f'sc start \"{svc}\"')\n                self._sharing_log(f\"  \u2705 {display} \u2192 Auto+Started\", C[\"success\"])\n\n            # 5. Error 709 fix\n            self._sharing_log(\"\\n\ud83d\udccc Error 0x0000709 fix...\", C[\"accent4\"])\n            self._do_fix_error_709_client()\n\n            # 6. Error 11b fix\n            self._sharing_log(\"\\n\ud83d\udccc Error 0x0000011b fix...\", C[\"accent4\"])\n            self._do_fix_error_11b_client()\n\n            self._sharing_log(\"\\n\" + \"\u2550\"*60, C[\"border\"])\n            self._sharing_log(\"\ud83c\udf89 CLIENT MEGA AUTO-FIX COMPLETE!\", C[\"success\"])\n            self._sharing_log(\"   \u25ba Ab 'Host se Printer Connect Karo' button se printer add karo.\", C[\"text_dim\"])\n            self.after(0, lambda: messagebox.showinfo(\n                \"\ud83c\udf89 CLIENT Mega Fix Complete!\",\n                \"\u2705 CLIENT ki saari printer sharing settings apply ho gayi!\\n\\n\"\n                \"Ab printer connect karne ke liye:\\n\"\n                \"  \u2192 'Host ke Shared Printer se Connect Karo' button dabao\\n\"\n                \"  \u2192 Host IP aur Share Name dalo\\n\\n\"\n                \"Agar abhi bhi error aaye \u2014 dono machines restart karo.\"))\n\n        self._launch_job(\"mega_task\", _mega)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    #  \ud83d\udcbb CLIENT COMPUTER \u2014 PRINTER SHARING METHODS\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n    def _client_open_ports(self):\n        if not messagebox.askyesno(\"Client: Port Fix\",\n                \"CLIENT computer pe ye ports open honge:\\n\\n\"\n                \"\u2022 445 TCP/UDP  \u2014 SMB access\\n\"\n                \"\u2022 139 TCP      \u2014 NetBIOS Session\\n\"\n                \"\u2022 137 UDP      \u2014 NetBIOS Name\\n\"\n                \"\u2022 138 UDP      \u2014 NetBIOS Datagram\\n\"\n                \"\u2022 135 TCP      \u2014 RPC\\n\\n\"\n                \"\u26a0 Private/trusted network pe karo!\\nContinue karein?\"):\n            return\n        self._sharing_log(\"\u2550\"*56, C[\"border\"])\n        self._sharing_log(\"\ud83d\udd0c [CLIENT] Ports khol raha hoon...\", C[\"accent2\"])\n        self._launch_job(\"client_open_ports\", self._do_client_open_ports)\n\n    def _do_client_open_ports(self):\n        ports = [\n            (445,  \"TCP\", \"SmbClient-TCP\"),\n            (445,  \"UDP\", \"SmbClient-UDP\"),\n            (139,  \"TCP\", \"NetBIOS-Sess-Client\"),\n            (137,  \"UDP\", \"NetBIOS-Name-Client\"),\n            (138,  \"UDP\", \"NetBIOS-Dgm-Client\"),\n            (135,  \"TCP\", \"RPC-Client\"),\n        ]\n        for port, proto, name in ports:\n            cmd = (f'netsh advfirewall firewall add rule '\n                   f'name=\"GodawariClient_{name}\" '\n                   f'dir=in action=allow protocol={proto} '\n                   f'localport={port} profile=any')\n            _, rc = self._run_cmd(cmd)\n            self._sharing_log(\n                f\"  {'\u2705' if rc==0 else '\u26a0'} Port {port}/{proto} ({name})\",\n                C[\"success\"] if rc == 0 else C[\"warning\"])\n        self._run_cmd(\n            'netsh advfirewall firewall set rule '\n            'group=\"File and Printer Sharing\" new enable=Yes profile=any')\n        self._sharing_log(\"  \u2705 File &amp; Printer Sharing rules (Client) \u2192 ON\", C[\"success\"])\n        self._sharing_log(\"\u2705 [CLIENT] Port fix complete!\", C[\"success\"])\n\n    def _client_security_fix(self):\n        if not messagebox.askyesno(\"Client: Security &amp; Firewall Fix\",\n                \"CLIENT security changes:\\n\\n\"\n                \"\u2022 Network Discovery \u2192 Enable\\n\"\n                \"\u2022 File &amp; Printer Sharing rules \u2192 ON\\n\"\n                \"\u2022 Network profile \u2192 Private\\n\"\n                \"\u2022 SMB client signing \u2192 Optional\\n\"\n                \"\u2022 Point &amp; Print driver settings\\n\\n\"\n                \"Continue karein?\"):\n            return\n        self._sharing_log(\"\u2550\"*56, C[\"border\"])\n        self._sharing_log(\"\ud83d\udd12 [CLIENT] Security fix chal raha hai...\", C[\"accent2\"])\n        self._launch_job(\"client_security_fix\", self._do_client_security_fix)\n\n    def _do_client_security_fix(self):\n        # Network Discovery\n        self._run_cmd(\n            'netsh advfirewall firewall set rule group=\"Network Discovery\" '\n            'new enable=Yes profile=private')\n        self._sharing_log(\"  \u2705 Network Discovery \u2192 ON\", C[\"success\"])\n\n        # F&amp;P Sharing rules\n        self._run_cmd(\n            'netsh advfirewall firewall set rule '\n            'group=\"File and Printer Sharing\" new enable=Yes profile=any')\n        self._sharing_log(\"  \u2705 F&amp;P Sharing rules \u2192 ON\", C[\"success\"])\n\n        # Private profile\n        self._run_cmd('powershell -Command \"Set-NetConnectionProfile -NetworkCategory Private\"')\n        self._sharing_log(\"  \u2705 Network profile \u2192 Private\", C[\"success\"])\n\n        # SMB client signing \u2014 optional\n        self._run_cmd(\n            'reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanWorkstation\\\\Parameters\" '\n            '/v RequireSecuritySignature /t REG_DWORD /d 0 /f')\n        self._run_cmd(\n            'reg add \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\LanmanWorkstation\\\\Parameters\" '\n            '/v EnableSecuritySignature /t REG_DWORD /d 1 /f')\n        self._sharing_log(\"  \u2705 SMB client signature \u2192 Optional\", C[\"success\"])\n\n        # Point &amp; Print \u2014 relax for easier driver install\n        self._run_cmd(\n            'reg add \"HKLM/SOFTWARE/Policies/Microsoft/Windows NT/Printers/PointAndPrint\" '\n            '/v NoWarningNoElevationOnInstall /t REG_DWORD /d 1 /f')\n        self._run_cmd(\n            'reg add \"HKLM/SOFTWARE/Policies/Microsoft/Windows NT/Printers/PointAndPrint\" '\n            '/v UpdatePromptSettings /t REG_DWORD /d 2 /f')\n        self._sharing_log(\"  \u2705 Point &amp; Print settings configured\", C[\"success\"])\n        self._sharing_log(\"\u2705 [CLIENT] Security fix complete!\", C[\"success\"])\n\n    def _client_registry_fix(self):\n        if not messagebox.askyesno(\"Client: Registry Changes\",\n                \"CLIENT registry changes:\\n\\n\"\n                \"\u2022 AllowInsecureGuestAuth = 1\\n\"\n                \"  (Guest/no-password shares access)\\n\"\n                \"\u2022 LimitBlankPasswordUse  = 0\\n\"\n                \"  (Blank password se connect)\\n\"\n                \"\u2022 RequireSecuritySignature = 0\\n\"\n                \"  (SMB signing optional on client)\\n\"\n                \"\u2022 Point &amp; Print restrictions relax\\n\\n\"\n                \"\u26a0 Sirf trusted network pe karo!\\nContinue karein?\"):\n            return\n        self._sharing_log(\"\u2550\"*56, C[\"border\"])\n        self._sharing_log(\"\ud83d\udddd [CLIENT] Registry changes apply kar raha hoon...\", C[\"accent2\"])\n        self._launch_job(\"client_registry_fix\", self._do_client_registry_fix)\n\n    def _do_client_registry_fix(self):\n        changes = [\n            (winreg.HKEY_LOCAL_MACHINE,\n             r\"SYSTEM\\CurrentControlSet\\Services\\LanmanWorkstation\\Parameters\",\n             \"AllowInsecureGuestAuth\", 1, winreg.REG_DWORD),\n            (winreg.HKEY_LOCAL_MACHINE,\n             r\"SYSTEM\\CurrentControlSet\\Control\\Lsa\",\n             \"LimitBlankPasswordUse\", 0, winreg.REG_DWORD),\n            (winreg.HKEY_LOCAL_MACHINE,\n             r\"SYSTEM\\CurrentControlSet\\Services\\LanmanWorkstation\\Parameters\",\n             \"RequireSecuritySignature\", 0, winreg.REG_DWORD),\n        ]\n        for hive, path, name, val, typ in changes:\n            try:\n                self._reg_set(hive, path, name, val, typ)\n                self._sharing_log(f\"  \u2705 {name} = {val}\", C[\"success\"])\n            except Exception as e:\n                self._sharing_log(f\"  \u26a0 {name}: {e}\", C[\"warning\"])\n\n        # Point &amp; Print via reg commands\n        for cmd in [\n            'reg add \"HKLM/SOFTWARE/Policies/Microsoft/Windows NT/Printers/PointAndPrint\" '\n            '/v RestrictDriverInstallationToAdministrators /t REG_DWORD /d 0 /f',\n            'reg add \"HKLM/SOFTWARE/Policies/Microsoft/Windows NT/Printers/PointAndPrint\" '\n            '/v NoWarningNoElevationOnInstall /t REG_DWORD /d 1 /f',\n            'reg add \"HKLM/SOFTWARE/Policies/Microsoft/Windows NT/Printers/PointAndPrint\" '\n            '/v UpdatePromptSettings /t REG_DWORD /d 2 /f',\n        ]:\n            self._run_cmd(cmd)\n        self._sharing_log(\"  \u2705 Point &amp; Print registry \u2192 configured\", C[\"success\"])\n        self._sharing_log(\"\u2705 [CLIENT] Registry changes complete!\", C[\"success\"])\n        self._sharing_log(\"   \u26a0 Restart recommended.\", C[\"warning\"])\n\n    def _client_connect_printer(self):\n        \"\"\"CLIENT: Dialog to connect to HOST's shared printer.\"\"\"\n        dlg = tk.Toplevel(self)\n        dlg.title(\"\ud83d\udda8 Client \u2014 Host se Shared Printer Connect Karo\")\n        dlg.geometry(\"540x470\")\n        dlg.configure(bg=C[\"bg\"])\n        dlg.grab_set()\n\n        tk.Label(dlg, text=\"\ud83d\udda8  Client: Host se Printer Connect Karo\",\n                 font=FONTS[\"subhead\"], fg=C[\"accent2\"], bg=C[\"bg\"]).pack(\n                 pady=(16,4), padx=20)\n        tk.Label(dlg,\n                 text=\"Host PC ka naam/IP aur Printer Share Name daalein\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"]).pack(padx=20)\n\n        info = tk.Frame(dlg, bg=C[\"card\"])\n        info.pack(fill=\"x\", padx=20, pady=8)\n\n        fields = {}\n        field_defs = [\n            (\"Host PC Name / IP:\",   \"host\",  \"e.g. 192.168.1.5  ya  OFFICPC\",  False),\n            (\"Printer Share Name:\",  \"share\", \"e.g. HP_LaserJet\",                False),\n            (\"Username (optional):\", \"user\",  \"khali chhod sakte hain\",           False),\n            (\"Password (optional):\", \"pwd\",   \"khali chhod sakte hain\",           True),\n        ]\n        for lbl, key, placeholder, secret in field_defs:\n            row = tk.Frame(info, bg=C[\"card\"])\n            row.pack(fill=\"x\", pady=4, padx=8)\n            tk.Label(row, text=lbl, font=FONTS[\"body\"], fg=C[\"text\"],\n                     bg=C[\"card\"], width=22, anchor=\"w\").pack(side=\"left\")\n            e = tk.Entry(row, font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"],\n                         insertbackground=C[\"text\"], relief=\"flat\", bd=4,\n                         width=24, show=\"*\" if secret else \"\")\n            e.insert(0, placeholder)\n            e.bind(\"\",\n                   lambda ev, p=placeholder, en=e: en.delete(0, \"end\") if en.get() == p else None)\n            e.bind(\"\",\n                   lambda ev, p=placeholder, en=e: en.insert(0, p) if not en.get() else None)\n            e.pack(side=\"left\", padx=4)\n            fields[key] = e\n\n        log = scrolledtext.ScrolledText(\n            dlg, height=9, font=FONTS[\"mono\"],\n            bg=C[\"bg\"], fg=C[\"text\"], bd=0, state=\"disabled\")\n        log.pack(fill=\"both\", expand=True, padx=20, pady=4)\n\n        def _log(msg, col=C[\"text\"]):\n            log.config(state=\"normal\")\n            log.insert(\"end\", msg + \"\\n\")\n            log.see(\"end\")\n            log.config(state=\"disabled\")\n\n        def _do_connect():\n            host  = fields[\"host\"].get().strip()\n            share = fields[\"share\"].get().strip()\n            user  = fields[\"user\"].get().strip()\n            pwd   = fields[\"pwd\"].get().strip()\n            if not host or \"e.g\" in host:\n                messagebox.showwarning(\"Host Missing\",\n                    \"Host PC ka naam ya IP enter karo.\", parent=dlg)\n                return\n            if not share or \"e.g\" in share:\n                messagebox.showwarning(\"Share Missing\",\n                    \"Printer share name enter karo.\", parent=dlg)\n                return\n            unc = f\"\\\\\\\\{host}\\\\{share}\"\n\n            def _run():\n                _log(f\"\ud83d\udd17 Connecting to: {unc}\")\n\n                # Step 1: Client firewall\n                self._run_cmd(\n                    'netsh advfirewall firewall set rule '\n                    'group=\"File and Printer Sharing\" new enable=Yes profile=any')\n                _log(\"  \u2705 Client firewall rules \u2192 ON\")\n\n                # Step 2: net use (authentication)\n                has_user = user and \"khali\" not in user\n                has_pwd  = pwd  and \"khali\" not in pwd\n                if has_user and has_pwd:\n                    net_cmd = f'net use \"{unc}\" /user:{user} {pwd} /persistent:yes'\n                elif has_user:\n                    net_cmd = f'net use \"{unc}\" /user:{user} /persistent:yes'\n                else:\n                    net_cmd = f'net use \"{unc}\" /persistent:yes'\n\n                out, rc = self._run_cmd(net_cmd, timeout=15)\n                if rc == 0 or \"completed\" in out.lower():\n                    _log(f\"  \u2705 Network path accessible: {unc}\")\n                else:\n                    _log(f\"  \u26a0 net use: {out[:120]}\")\n                    _log(\"  \u2139 Phir bhi printer add karne ki koshish kar raha hoon...\")\n\n                # Step 3: Add printer \u2014 PowerShell\n                out2, rc2 = self._run_cmd(\n                    f'powershell -Command \"Add-Printer -ConnectionName \\'{unc}\\'\"',\n                    timeout=20)\n                if rc2 == 0:\n                    _log(f\"  \u2705 Printer added from {unc}!\")\n                else:\n                    # Fallback 1: rundll32\n                    self._run_cmd(\n                        f'rundll32 printui.dll,PrintUIEntry /in /n \"{unc}\"')\n                    _log(\"  \u2705 Printer add attempt via legacy method (rundll32)\")\n                    _log(f\"  \u2139 Agar nahi hua: Control Panel \u2192 Printers \u2192 \"\n                         f\"Add Printer \u2192 Network \u2192 {unc}\")\n\n                # Step 4: Auto-open confirmation\n                def _confirm():\n                    subprocess.Popen([\"control.exe\", \"printers\"], shell=False)\n                    time.sleep(1)\n                    self._printer_detect()\n                    messagebox.showinfo(\n                        \"\ud83d\udda8 Connection Result\",\n                        f\"Connection attempt complete!\\n\\n\"\n                        f\"Host  : {host}\\n\"\n                        f\"Share : {share}\\n\"\n                        f\"Path  : {unc}\\n\\n\"\n                        \"\u2705 Printers window khul gaya hai.\\n\"\n                        \"Wahan shared printer check karo.\\n\\n\"\n                        \"Agar nahi dikh raha:\\n\"\n                        \"1. Host pe 'Auto-Share' dobara chalao\\n\"\n                        \"2. Host pe 'Port Fix' chalao\\n\"\n                        \"3. Dono PC ek hi workgroup mein hain? Check karo.\",\n                        parent=dlg)\n                self.after(0, _confirm)\n                self._sharing_log(\n                    f\"[CLIENT] Printer connect attempt \u2192 {unc}\", C[\"accent2\"])\n\n            self._launch_job(\"open_network_explorer\", _run)\n\n        def _do_ping():\n            host = fields[\"host\"].get().strip()\n            if not host or \"e.g\" in host:\n                messagebox.showwarning(\"Host Missing\",\n                    \"Host ka IP ya naam pehle enter karo.\", parent=dlg)\n                return\n            threading.Thread(\n                target=lambda: _log(self._run_cmd(f'ping -n 3 {host}')[0]),\n                daemon=True).start()\n\n        def _browse():\n            subprocess.Popen([\"explorer.exe\", \"Network\"], shell=False)\n\n        btn_f = tk.Frame(dlg, bg=C[\"bg\"])\n        btn_f.pack(pady=8)\n        self._btn(btn_f, \"\ud83d\udda8 Connect Printer\",  C[\"btn_warn\"],   _do_connect).pack(side=\"left\", padx=4)\n        self._btn(btn_f, \"\ud83c\udfd3 Ping Host\",        C[\"btn_chip\"],   _do_ping).pack(side=\"left\", padx=4)\n        self._btn(btn_f, \"\ud83c\udf10 Browse Network\",   C[\"btn_info\"],   _browse).pack(side=\"left\", padx=4)\n        self._btn(btn_f, \"\u274c Close\",             C[\"btn_danger\"], dlg.destroy).pack(side=\"left\", padx=4)\n\n    def _build_driver(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udce6 Driver Checker\",\n                             \"Third-party drivers \u2014 outdated ya problem wale dhundho, update karo\")\n\n        # \u2500\u2500 Guide Banner \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        guide = tk.Frame(frame, bg=\"#0D1F0D\", highlightbackground=C[\"accent2\"], highlightthickness=1)\n        guide.pack(fill=\"x\", padx=16, pady=(4, 6))\n        tk.Label(guide, text=\"\ud83d\udcd6  Kaise use karein?\", font=FONTS[\"subhead\"], fg=C[\"accent2\"], bg=\"#0D1F0D\").pack(anchor=\"w\", padx=12, pady=(8,2))\n        for s in [\n            \"\u2460 'Scan Drivers' dabao \u2014 third-party drivers ki list aayegi\",\n            \"\u2461 List mein driver select karo \u2192 'Open in Device Manager' se update/uninstall karo\",\n            \"\u2462 'Open Driver Folder' se driver file directly dekh sakte ho\",\n            \"\u2463 'Export CSV' se list save karo \u2014 customer ko dene ke liye useful\",\n            \"\u26a0  Old 'Link Date' wale drivers update karne chahiye \u2014 yellow mein highlight honge\",\n        ]:\n            tk.Label(guide, text=s, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=\"#0D1F0D\", anchor=\"w\").pack(anchor=\"w\", padx=20, pady=1)\n        tk.Label(guide, text=\"\", bg=\"#0D1F0D\").pack(pady=3)\n\n        # \u2500\u2500 Action Buttons \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        self._action_card_grid(frame, [\n            (\"\ud83d\udd0d\", \"Scan Drivers\",         \"Third-party drivers scan karo\",          C[\"btn_info\"],   self._scan_drivers),\n            (\"\ud83d\udda5\",  \"Open Device Manager\",  \"Windows Device Manager mein update karo\",C[\"btn_warn\"],   self._driver_open_devmgr),\n            (\"\ud83d\udcc2\", \"Open Driver Folder\",   \"Selected driver ki file location kholo\", C[\"btn_chip\"],   self._driver_open_folder),\n            (\"\ud83d\udce5\", \"Export CSV\",           \"Driver list CSV mein save karo\",         C[\"accent2\"],    self._driver_export_csv),\n        ], cols=4)\n\n        # \u2500\u2500 Treeview for driver list \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        tv_frame = tk.Frame(frame, bg=C[\"bg\"])\n        tv_frame.pack(fill=\"both\", expand=True, padx=16, pady=(4, 4))\n\n        cols = (\"Display Name\", \"Module\", \"Type\", \"Link Date\", \"Path\")\n        self.driver_tree = ttk.Treeview(tv_frame, columns=cols, show=\"headings\",\n                                         height=18, style=\"Custom.Treeview\",\n                                         selectmode=\"browse\")\n        for col, w in zip(cols, [200, 130, 80, 110, 380]):\n            self.driver_tree.heading(col, text=col)\n            self.driver_tree.column(col, width=w, anchor=\"w\")\n        self.driver_tree.tag_configure(\"old\",  foreground=C[\"warning\"])\n        self.driver_tree.tag_configure(\"ok\",   foreground=C[\"success\"])\n        dsb = ttk.Scrollbar(tv_frame, orient=\"vertical\", command=self.driver_tree.yview)\n        self.driver_tree.configure(yscrollcommand=dsb.set)\n        self.driver_tree.pack(side=\"left\", fill=\"both\", expand=True)\n        dsb.pack(side=\"right\", fill=\"y\")\n\n        # Status bar\n        self.driver_status_lbl = tk.Label(frame, text=\"  Scan karo \u2014 drivers list yahan aayegi\",\n                                           font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"], anchor=\"w\")\n        self.driver_status_lbl.pack(fill=\"x\", padx=16, pady=(2, 4))\n\n        # Fallback log (error/warnings ke liye)\n        self.driver_log = self._scrolled_text(frame, height=4)\n        self._driver_rows = []   # store parsed data\n        return frame\n\n    def _scan_drivers(self):\n        self._launch_job(\"scan_drivers\", self._do_scan_drivers)\n\n    def _do_scan_drivers(self):\n        import datetime as _dt\n        self.after(0, lambda: self.driver_tree.delete(*self.driver_tree.get_children()))\n        self.after(0, lambda: self.driver_status_lbl.config(text=\"  \u23f3 Scanning drivers...\", fg=C[\"accent4\"]))\n        self._append_log(self.driver_log, \"\ud83d\udd0d driverquery chal raha hai...\", C[\"accent4\"])\n        out, rc = self._run_cmd('driverquery /FO CSV /V', timeout=30)\n        if rc != 0 or not out.strip():\n            self._append_log(self.driver_log, \"\u274c driverquery failed. Admin mode mein run karo.\", C[\"error\"])\n            self.after(0, lambda: self.driver_status_lbl.config(text=\"  \u274c Scan failed \u2014 Admin mode use karo\", fg=C[\"error\"]))\n            return\n        try:\n            reader = csv.DictReader(io.StringIO(out))\n            self._driver_rows = []\n            cutoff_year = _dt.datetime.now().year - 3   # 3 saal purana = old\n\n            for r in reader:\n                mod  = (r.get(\"Module Name\") or r.get(\"ModuleName\") or \"\").strip()\n                disp = (r.get(\"Display Name\") or r.get(\"DisplayName\") or \"\").strip()\n                dtype= (r.get(\"Driver Type\")  or r.get(\"DriverType\")  or \"\").strip()\n                link = (r.get(\"Link Date\")    or r.get(\"LinkDate\")    or \"\").strip()\n                path = (r.get(\"Path\") or \"\").strip()\n                if not mod and not disp:\n                    continue\n                if \"microsoft\" in (disp.lower() + \" \" + path.lower()):\n                    continue\n                self._driver_rows.append((disp or mod, mod, dtype, link, path))\n\n            # Sort: purane pehle (link date ascending)\n            self._driver_rows.sort(key=lambda x: (x[3] or \"0000\", x[0].lower()))\n\n            def populate():\n                for name, mod, dtype, link, path in self._driver_rows:\n                    # Tag: old if link year &lt; cutoff\n                    tag = \"ok\"\n                    try:\n                        yr = int(link.split(\"/\")[-1]) if \"/\" in link else int(link[-4:]) if len(link) &gt;= 4 else 9999\n                        if yr &lt; cutoff_year:\n                            tag = \"old\"\n                    except:\n                        pass\n                    self.driver_tree.insert(\"\", \"end\", values=(name, mod, dtype, link, path), tags=(tag,))\n\n                total = len(self._driver_rows)\n                self.driver_status_lbl.config(\n                    text=f\"  \u2705 {total} third-party drivers found  |  \ud83d\udfe1 Yellow = 3+ saal purane (update recommended)\",\n                    fg=C[\"success\"])\n                self._append_log(self.driver_log, f\"\u2705 {total} drivers found.\", C[\"success\"])\n            self.after(0, populate)\n\n        except Exception as e:\n            self._append_log(self.driver_log, f\"\u26a0 Parse error: {e}\", C[\"warning\"])\n            self.after(0, lambda: self.driver_status_lbl.config(text=f\"  \u26a0 Error: {e}\", fg=C[\"warning\"]))\n\n    def _driver_open_devmgr(self):\n        \"\"\"Windows Device Manager open karo \u2014 wahan driver update/uninstall possible hai.\"\"\"\n        self._run_cmd(\"devmgmt.msc\", timeout=5)\n        self._append_log(self.driver_log, \"\u2705 Device Manager khola gaya. Driver select karo \u2192 Right-click \u2192 Update Driver.\", C[\"success\"])\n\n    def _driver_open_folder(self):\n        \"\"\"Selected driver ki folder location Explorer mein open karo.\"\"\"\n        sel = self.driver_tree.selection()\n        if not sel:\n            messagebox.showinfo(\"Select Driver\", \"Pehle list mein ek driver select karo.\")\n            return\n        path = self.driver_tree.item(sel[0])[\"values\"][4]\n        if not path or not os.path.exists(path):\n            messagebox.showwarning(\"Not Found\", f\"Driver file nahi mili:\\n{path}\")\n            return\n        folder = os.path.dirname(path)\n        try:\n            os.startfile(folder)\n            self._append_log(self.driver_log, f\"\ud83d\udcc2 Folder khola: {folder}\", C[\"success\"])\n        except Exception as e:\n            messagebox.showerror(\"Error\", str(e))\n\n    # ---------- DUPLICATE FINDER ----------\n    def _build_dupfinder(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83e\uddec Duplicate Finder\", \"Find &amp; remove duplicate files (size + hash)\")\n\n        top = tk.Frame(frame, bg=C[\"card\"])\n        top.pack(fill=\"x\", padx=16, pady=8)\n\n        tk.Label(top, text=\"Folder:\", font=FONTS[\"body\"], fg=C[\"text\"], bg=C[\"card\"]).pack(side=\"left\", padx=6)\n        self.dup_folder_var = tk.StringVar(value=os.path.join(os.path.expanduser(\"~\"), \"Downloads\"))\n        self.dup_folder_entry = tk.Entry(top, textvariable=self.dup_folder_var, width=46, font=FONTS[\"body\"])\n        self.dup_folder_entry.pack(side=\"left\", padx=6)\n        self._btn(top, \"\ud83d\udcc1 Browse\", C[\"btn_info\"], self._dup_pick_folder).pack(side=\"left\", padx=4)\n\n        tk.Label(top, text=\"Mode:\", font=FONTS[\"body\"], fg=C[\"text\"], bg=C[\"card\"]).pack(side=\"left\", padx=(12, 4))\n        self.dup_mode_var = tk.StringVar(value=\"fast\")\n        ttk.Combobox(top, values=[\"fast\", \"accurate\"], textvariable=self.dup_mode_var,\n                     width=10, font=FONTS[\"body\"], state=\"readonly\").pack(side=\"left\", padx=4)\n\n        tk.Label(top, text=\"Min MB:\", font=FONTS[\"body\"], fg=C[\"text\"], bg=C[\"card\"]).pack(side=\"left\", padx=(12, 4))\n        self.dup_min_mb = tk.Entry(top, width=6, font=FONTS[\"body\"])\n        self.dup_min_mb.insert(0, \"1\")\n        self.dup_min_mb.pack(side=\"left\", padx=4)\n\n        self._action_card_grid(frame, [\n            (\"\ud83d\udd0d\", \"Scan Duplicates\",          \"Folder mein duplicate files dhundho\", C[\"btn_danger\"], self._dup_start_scan),\n            (\"\ud83d\udce6\", \"Move to Quarantine\",        \"Selected files quarantine mein bhejo\",C[\"btn_warn\"],   self._dup_quarantine_selected),\n            (\"\ud83d\uddd1\",  \"Delete Selected\",          \"Selected files permanently delete karo\",C[\"btn_danger\"],self._dup_delete_selected),\n            (\"\ud83d\udcc2\", \"Open Selected Folder\",     \"File ki location folder open karo\",   C[\"btn_chip\"],   self._dup_open_selected_folder),\n        ], cols=4)\n\n        prog = tk.Frame(frame, bg=C[\"card\"])\n        prog.pack(fill=\"x\", padx=16, pady=(0, 6))\n        self.dup_status_lbl = tk.Label(prog, text=\"Ready\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], anchor=\"w\")\n        self.dup_status_lbl.pack(fill=\"x\", padx=8, pady=(6, 2))\n        self.dup_progress = tk.DoubleVar(value=0)\n        ttk.Progressbar(prog, variable=self.dup_progress, maximum=100, mode=\"determinate\").pack(fill=\"x\", padx=8, pady=(0, 8))\n\n        cols = (\"Group\", \"Filename\", \"Size\", \"Path\")\n        self.dup_tree = ttk.Treeview(frame, columns=cols, show=\"headings\", height=20, style=\"Custom.Treeview\", selectmode=\"extended\")\n        for col, w in zip(cols, [80, 260, 90, 520]):\n            self.dup_tree.heading(col, text=col)\n            self.dup_tree.column(col, width=w, anchor=\"w\")\n        vsb = ttk.Scrollbar(frame, orient=\"vertical\", command=self.dup_tree.yview)\n        self.dup_tree.configure(yscrollcommand=vsb.set)\n        self.dup_tree.pack(side=\"left\", fill=\"both\", expand=True, padx=16, pady=8)\n        vsb.pack(side=\"right\", fill=\"y\", pady=8, padx=(0, 8))\n\n        self.dup_log = self._scrolled_text(frame, height=8)\n        self._dup_results = []  # list of meta dicts aligned with displayed rows\n        return frame\n\n    def _dup_pick_folder(self):\n        path = filedialog.askdirectory(title=\"Select Folder to Scan\")\n        if path:\n            self.dup_folder_var.set(path)\n\n    def _dup_start_scan(self):\n        folder = (self.dup_folder_var.get() or \"\").strip()\n        if not folder or not os.path.isdir(folder):\n            messagebox.showwarning(\"Input\", \"Valid folder select karo.\")\n            return\n        mode = (self.dup_mode_var.get() or \"fast\").strip().lower()\n        try:\n            min_mb = float((self.dup_min_mb.get() or \"0\").strip())\n        except Exception:\n            min_mb = 0\n        min_bytes = int(max(0, min_mb) * 1024 * 1024)\n        if not messagebox.askyesno(\"Duplicate Scan\",\n                                   f\"Folder: {folder}\\nMode: {mode}\\nMin size: {min_mb} MB\\n\\nScan start karein?\"):\n            return\n        self.dup_tree.delete(*self.dup_tree.get_children())\n        self._dup_results = []\n        self.dup_progress.set(0)\n        self.dup_status_lbl.config(text=\"Scanning...\", fg=C[\"accent4\"])\n        self._launch_job(\"duplicate_scan\", self._dup_do_scan, folder, mode, min_bytes)\n\n    def _dup_hash_fast(self, path, size):\n        h = hashlib.sha256()\n        with open(path, \"rb\") as f:\n            head = f.read(min(size, 1024 * 1024))\n            h.update(head)\n            if size &gt; 2 * 1024 * 1024:\n                try:\n                    f.seek(max(0, size - 1024 * 1024))\n                    tail = f.read(1024 * 1024)\n                    h.update(tail)\n                except Exception:\n                    pass\n        return h.hexdigest()\n\n    def _dup_hash_full(self, path):\n        h = hashlib.sha256()\n        with open(path, \"rb\") as f:\n            while True:\n                chunk = f.read(1024 * 1024)\n                if not chunk:\n                    break\n                h.update(chunk)\n        return h.hexdigest()\n\n    def _dup_do_scan(self, folder, mode, min_bytes):\n        try:\n            self._append_log(self.dup_log, f\"\ud83d\udd0d Scanning: {folder}\", C[\"accent\"])\n            files = []\n            scanned = 0\n            for dirpath, _, filenames in os.walk(folder):\n                for fn in filenames:\n                    full = os.path.join(dirpath, fn)\n                    try:\n                        st = os.stat(full)\n                        if st.st_size &lt; min_bytes:\n                            continue\n                        files.append((full, int(st.st_size)))\n                    except Exception:\n                        continue\n                scanned += 1\n                if scanned % 200 == 0:\n                    self.after(0, lambda s=scanned: self.dup_status_lbl.config(text=f\"Scanning... {s} folders\", fg=C[\"accent4\"]))\n\n            by_size = {}\n            for p, sz in files:\n                by_size.setdefault(sz, []).append(p)\n            candidates = [(sz, ps) for sz, ps in by_size.items() if len(ps) &gt; 1]\n            if not candidates:\n                self.after(0, lambda: self.dup_status_lbl.config(text=\"No duplicates candidates found.\", fg=C[\"warning\"]))\n                self.after(0, lambda: self.dup_progress.set(100))\n                self._append_log(self.dup_log, \"\u2705 No duplicate candidates (by size).\", C[\"success\"])\n                return\n\n            total = sum(len(ps) for _, ps in candidates)\n            done = 0\n            groups = []\n            for sz, paths in candidates:\n                hash_map = {}\n                for p in paths:\n                    try:\n                        if mode == \"accurate\":\n                            hx = self._dup_hash_full(p)\n                        else:\n                            hx = self._dup_hash_fast(p, sz)\n                        hash_map.setdefault(hx, []).append(p)\n                    except Exception:\n                        continue\n                    done += 1\n                    if done % 25 == 0:\n                        pct = int((done / max(1, total)) * 100)\n                        self.after(0, lambda pct=pct: self.dup_progress.set(pct))\n                        self.after(0, lambda d=done, t=total: self.dup_status_lbl.config(text=f\"Hashing... {d}/{t}\", fg=C[\"accent4\"]))\n                for hx, ps in hash_map.items():\n                    if len(ps) &gt; 1:\n                        groups.append({\"size\": sz, \"hash\": hx, \"paths\": ps})\n\n            def render():\n                self.dup_tree.delete(*self.dup_tree.get_children())\n                self._dup_results = []\n                gid = 0\n                dup_files = 0\n                dup_bytes = 0\n                for g in groups:\n                    gid += 1\n                    group_label = f\"G{gid}\"\n                    for p in g[\"paths\"]:\n                        name = os.path.basename(p)\n                        self.dup_tree.insert(\"\", \"end\",\n                                             values=(group_label, name, self._fmt_size(g[\"size\"]), p))\n                        self._dup_results.append({\"path\": p, \"group\": group_label, \"size\": g[\"size\"], \"hash\": g[\"hash\"]})\n                        dup_files += 1\n                    # duplicates count excludes one \"original\"\n                    if len(g[\"paths\"]) &gt; 1:\n                        dup_bytes += (len(g[\"paths\"]) - 1) * g[\"size\"]\n                self.dup_progress.set(100)\n                if groups:\n                    self.dup_status_lbl.config(\n                        text=f\"\u2705 {len(groups)} duplicate group(s) found | extra space: {self._fmt_size(dup_bytes)}\",\n                        fg=C[\"success\"])\n                    self._append_log(self.dup_log, f\"\u2705 Groups: {len(groups)} | Extra space: {self._fmt_size(dup_bytes)}\", C[\"success\"])\n                else:\n                    self.dup_status_lbl.config(text=\"No duplicates found (hash matched none).\", fg=C[\"warning\"])\n                    self._append_log(self.dup_log, \"\u2705 No duplicates after hashing.\", C[\"success\"])\n\n            self.after(0, render)\n        except Exception as e:\n            self.after(0, lambda: self.dup_status_lbl.config(text=f\"Scan failed: {e}\", fg=C[\"error\"]))\n\n    def _dup_selected_entries(self):\n        items = []\n        for iid in self.dup_tree.selection():\n            idx = self.dup_tree.index(iid)\n            if 0 &lt;= idx &lt; len(self._dup_results):\n                items.append(self._dup_results[idx])\n        return items\n\n    def _dup_quarantine_selected(self):\n        sel = self._dup_selected_entries()\n        if not sel:\n            messagebox.showinfo(\"No Selection\", \"Pehle duplicate files select karo.\")\n            return\n        base = (self.dup_folder_var.get() or \"\").strip()\n        quarantine = os.path.join(base, \"_Duplicate_Quarantine\")\n        if not messagebox.askyesno(\"Quarantine\",\n                                   f\"Selected {len(sel)} file(s) quarantine folder me move honge:\\n{quarantine}\\n\\nProceed?\"):\n            return\n        os.makedirs(quarantine, exist_ok=True)\n        moved = 0\n        for it in sel:\n            src = it.get(\"path\", \"\")\n            if not src or not os.path.exists(src):\n                continue\n            dst = os.path.join(quarantine, os.path.basename(src))\n            # avoid overwrite\n            if os.path.exists(dst):\n                root, ext = os.path.splitext(dst)\n                dst = f\"{root}_{int(time.time())}{ext}\"\n            try:\n                shutil.move(src, dst)\n                moved += 1\n            except Exception as e:\n                self._append_log(self.dup_log, f\"\u274c Move failed: {src} ({e})\", C[\"error\"])\n        self._append_log(self.dup_log, f\"\u2705 Moved to quarantine: {moved}\", C[\"success\"])\n        self._dup_start_scan()\n\n    def _dup_delete_selected(self):\n        sel = self._dup_selected_entries()\n        if not sel:\n            messagebox.showinfo(\"No Selection\", \"Pehle duplicate files select karo.\")\n            return\n        if not messagebox.askyesno(\"Permanent Delete\",\n                                   f\"\u26a0\ufe0f Selected {len(sel)} file(s) PERMANENT delete honge.\\nUndo possible nahi.\\n\\nProceed?\"):\n            return\n        deleted = 0\n        for it in sel:\n            src = it.get(\"path\", \"\")\n            if not src or not os.path.exists(src):\n                continue\n            try:\n                os.remove(src)\n                deleted += 1\n            except Exception as e:\n                self._append_log(self.dup_log, f\"\u274c Delete failed: {src} ({e})\", C[\"error\"])\n        self._append_log(self.dup_log, f\"\ud83d\uddd1 Deleted: {deleted}\", C[\"warning\"])\n        self._dup_start_scan()\n\n    def _dup_open_selected_folder(self):\n        sel = self._dup_selected_entries()\n        if not sel:\n            messagebox.showinfo(\"No Selection\", \"Pehle ek file select karo.\")\n            return\n        p = sel[0].get(\"path\", \"\")\n        if not p:\n            return\n        folder = os.path.dirname(p)\n        try:\n            os.startfile(folder)\n        except Exception:\n            pass\n\n    def _build_backup(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udcbe Backup/Restore\", \"Profiles\")\n        self._action_card_grid(frame, [\n            (\"\ud83d\udcc0\", \"Backup Settings\",  \"Current settings JSON mein save karo\", C[\"btn_info\"], self._backup_settings),\n            (\"\ud83d\udd04\", \"Restore Settings\", \"Pehle saved settings wapas lao\",       C[\"btn_warn\"], self._restore_settings),\n        ], cols=2)\n        self.backup_log = self._scrolled_text(frame, height=18)\n        return frame\n\n    def _backup_settings(self):\n        data = {\"reg\": {k: v.get() for k, v in self.reg_vars.items()}, \"gp\": {k: v.get() for k, v in self.gp_vars.items()}}\n        fpath = filedialog.asksaveasfilename(defaultextension=\".json\", filetypes=[(\"JSON\",\"*.json\")])\n        if fpath:\n            with open(fpath, \"w\") as f:\n                json.dump(data, f, indent=2)\n            self._append_log(self.backup_log, \"\u2705 Saved\", C[\"success\"])\n\n    def _restore_settings(self):\n        fpath = filedialog.askopenfilename(filetypes=[(\"JSON\",\"*.json\")])\n        if fpath:\n            with open(fpath, \"r\") as f:\n                data = json.load(f)\n            if \"reg\" in data:\n                for k, val in data[\"reg\"].items():\n                    if k in self.reg_vars:\n                        self.reg_vars[k].set(bool(val))\n            self._append_log(self.backup_log, \"\u2705 Restored\", C[\"success\"])\n\n    def _build_report(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udcca HTML Report\", \"Export system report\")\n        self._action_card_grid(frame, [\n            (\"\ud83d\udcd1\", \"Generate Report\", \"System ka HTML report export karo\", C[\"btn_info\"], self._export_report),\n        ], cols=1)\n        self.report_log = self._scrolled_text(frame, height=18)\n        return frame\n\n    def _export_report(self):\n        fpath = filedialog.asksaveasfilename(defaultextension=\".html\", filetypes=[(\"HTML\",\"*.html\")])\n        if fpath:\n            vm = psutil.virtual_memory()\n            du = psutil.disk_usage(\"/\")\n            html = f\"\nGodawari Report\nCPU: {psutil.cpu_percent()}% | RAM: {vm.percent}% | Disk: {du.percent}%\"\n            with open(fpath, \"w\") as f:\n                f.write(html)\n            self._append_log(self.report_log, \"\u2705 Saved\", C[\"success\"])\n            os.startfile(fpath)\n\n    def _build_log(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udcdd Activity Log\", \"History\")\n        self._action_card_grid(frame, [\n            (\"\ud83d\udcbe\", \"Save Log\",   \"Log file Desktop pe save karo\",C[\"btn_info\"],   self._save_log),\n            (\"\ud83d\uddd1\", \"Clear Log\",  \"Log screen saaf karo\",          C[\"btn_danger\"], self._clear_log),\n        ], cols=2)\n        log_frame = tk.Frame(frame, bg=C[\"card\"])\n        log_frame.pack(fill=\"both\", expand=True, padx=16, pady=8)\n        self.log_text = scrolledtext.ScrolledText(log_frame, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"], height=28, bd=0, wrap=\"word\", relief=\"flat\", state=\"disabled\")\n        self.log_text.pack(fill=\"both\", expand=True, padx=8, pady=(0,8))\n        for line, color in self.log_lines:\n            self.log_text.config(state=\"normal\")\n            self.log_text.insert(\"end\", line + \"\\n\", f\"c{color.replace('#','')}\")\n            self.log_text.tag_config(f\"c{color.replace('#','')}\", foreground=color)\n            self.log_text.config(state=\"disabled\")\n        return frame\n\n    def _save_log(self):\n        path = os.path.join(os.path.expanduser(\"~\"), \"Desktop\", f\"Godawari_Log_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.txt\")\n        self.log_text.config(state=\"normal\")\n        with open(path, \"w\", encoding=\"utf-8\") as f:\n            f.write(self.log_text.get(\"1.0\", \"end\"))\n        self.log_text.config(state=\"disabled\")\n        messagebox.showinfo(\"Saved\", f\"Log saved to Desktop\")\n\n    def _clear_log(self):\n        self.log_lines.clear()\n        self.log_text.config(state=\"normal\")\n        self.log_text.delete(\"1.0\", \"end\")\n        self.log_text.config(state=\"disabled\")\n\n    # ---------- REMAINING HARDWARE SECTIONS (unchanged) ----------\n    def _build_motherboard(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udda5\ufe0f Motherboard Info\", \"Board &amp; BIOS\", hw=True)\n        self._action_card_grid(frame, [\n            (\"\ud83d\udda5\", \"Scan Motherboard\", \"Board maker, model, BIOS version\", C[\"btn_hw\"], self._scan_mb),\n        ], cols=1)\n        self.mb_log = self._scrolled_text(frame, 20)\n        return frame\n\n    def _scan_mb(self):\n        self.mb_log.config(state=\"normal\")\n        self.mb_log.delete(\"1.0\", \"end\")\n        self.mb_log.config(state=\"disabled\")\n        self._launch_job(\"scan_mb\", self._do_scan_mb)\n\n    def _do_scan_mb(self):\n        out, _ = self._run_cmd(\"wmic baseboard get Manufacturer,Product,Version,SerialNumber /format:list\")\n        self._append_log(self.mb_log, \"\u2550\"*50, C[\"border\"])\n        self._append_log(self.mb_log, \"  MOTHERBOARD INFORMATION\", C[\"hw_accent\"])\n        for line in out.splitlines():\n            if \"=\" in line:\n                self._append_log(self.mb_log, f\"  {line}\", C[\"text\"])\n        self._set_status(\"Motherboard scan complete\", C[\"success\"])\n\n    def _build_chip_diag(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udd2c CPU Diagnostics\", \"Architecture &amp; Cache\", hw=True)\n        self._action_card_grid(frame, [\n            (\"\ud83d\udd2c\", \"Full CPU Analysis\", \"CPU cores, cache, speed details\", C[\"btn_chip\"], self._scan_cpu),\n        ], cols=1)\n        self.chip_log = self._scrolled_text(frame, 20)\n        return frame\n\n    def _scan_cpu(self):\n        self.chip_log.config(state=\"normal\")\n        self.chip_log.delete(\"1.0\", \"end\")\n        self.chip_log.config(state=\"disabled\")\n        self._launch_job(\"scan_cpu\", self._do_scan_cpu)\n\n    def _do_scan_cpu(self):\n        out, _ = self._run_cmd(\"wmic cpu get Name,MaxClockSpeed,NumberOfCores,L2CacheSize,L3CacheSize /format:list\")\n        self._append_log(self.chip_log, \"\u2550\"*50, C[\"border\"])\n        self._append_log(self.chip_log, \"  CPU ARCHITECTURE &amp; CACHE\", C[\"hw_accent\"])\n        for line in out.splitlines():\n            if \"=\" in line:\n                self._append_log(self.chip_log, f\"  {line}\", C[\"text\"])\n\n    def _build_voltage_monitor(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\u26a1 Voltage Monitor\", \"PSU Rails Reference\", hw=True)\n        self._action_card_grid(frame, [\n            (\"\u26a1\", \"Scan Voltages\", \"PSU rails reference chart dekhao\", C[\"btn_chip\"], self._scan_volts),\n        ], cols=1)\n        self.volt_log = self._scrolled_text(frame, 20)\n        return frame\n\n    def _scan_volts(self):\n        self.volt_log.config(state=\"normal\")\n        self.volt_log.delete(\"1.0\", \"end\")\n        self.volt_log.config(state=\"disabled\")\n        self._launch_job(\"scan_volts\", self._do_scan_volts)\n\n    def _do_scan_volts(self):\n        self._append_log(self.volt_log, \"  PSU Rails (ATX Standard Reference):\", C[\"hw_accent\"])\n        for rail, spec in [(\"3.3V Rail\", \"3.135-3.465V\"), (\"5V Rail\", \"4.750-5.250V\"), (\"12V Rail\", \"11.400-12.600V\")]:\n            self._append_log(self.volt_log, f\"  {rail:&lt;15}: {spec}\", C[\"text\"])\n\n    def _build_gpu_diag_fixed(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83c\udfae GPU Diagnostics\", \"Real GPU Stats\", hw=True)\n        self._action_card_grid(frame, [\n            (\"\ud83c\udfae\", \"Scan GPU\", \"Graphics card details scan karo\", C[\"btn_chip\"], self._scan_gpu),\n        ], cols=1)\n        self.gpu_log = self._scrolled_text(frame, 20)\n        return frame\n\n    def _scan_gpu(self):\n        self.gpu_log.config(state=\"normal\")\n        self.gpu_log.delete(\"1.0\", \"end\")\n        self.gpu_log.config(state=\"disabled\")\n        self._launch_job(\"scan_gpu\", self._do_scan_gpu)\n\n    def _do_scan_gpu(self):\n        out, _ = self._run_cmd(\"wmic path win32_VideoController get Name,AdapterRAM,DriverVersion,VideoProcessor /format:list\")\n        self._append_log(self.gpu_log, \"\u2550\"*50, C[\"border\"])\n        self._append_log(self.gpu_log, \"  GPU INFORMATION\", C[\"hw_accent\"])\n        for line in out.splitlines():\n            if \"=\" in line and line.split(\"=\")[1].strip():\n                if \"AdapterRAM\" in line:\n                    try:\n                        line = f\"VRAM={self._fmt_size(int(line.split('=')[1]))}\"\n                    except:\n                        pass\n                self._append_log(self.gpu_log, line, C[\"text\"])\n\n    def _build_ram_slots(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83c\udccf RAM Slots\", \"DIMM Info\", hw=True)\n        self._action_card_grid(frame, [\n            (\"\ud83c\udccf\", \"Scan RAM Slots\", \"DIMM slot info \u2014 size, speed, brand\", C[\"btn_chip\"], self._scan_dimms),\n        ], cols=1)\n        self.ramslot_log = self._scrolled_text(frame, 20)\n        return frame\n\n    def _scan_dimms(self):\n        self.ramslot_log.config(state=\"normal\")\n        self.ramslot_log.delete(\"1.0\", \"end\")\n        self.ramslot_log.config(state=\"disabled\")\n        self._launch_job(\"scan_dimms\", self._do_scan_dimms)\n\n    def _do_scan_dimms(self):\n        out, _ = self._run_cmd(\"wmic memorychip get BankLabel,Capacity,Speed,Manufacturer /format:list\")\n        self._append_log(self.ramslot_log, \"\u2550\"*50, C[\"border\"])\n        self._append_log(self.ramslot_log, \"  RAM SLOT INFORMATION\", C[\"hw_accent\"])\n        for line in out.splitlines():\n            if \"=\" in line:\n                self._append_log(self.ramslot_log, f\"  {line}\", C[\"text\"])\n\n    def _build_post_codes(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udcdf POST Codes\", \"Reference\", hw=True)\n        self.post_tree = ttk.Treeview(frame, columns=(\"BIOS\", \"Code\", \"Meaning\", \"Fix\"), show=\"headings\", height=24, style=\"Custom.Treeview\")\n        for col, w in zip((\"BIOS\", \"Code\", \"Meaning\", \"Fix\"), [100,100,300,400]):\n            self.post_tree.heading(col, text=col)\n            self.post_tree.column(col, width=w, anchor=\"w\")\n        for row in [(\"AMI\",\"1 Beep\",\"DRAM Refresh\",\"Reseat RAM\"),\n                    (\"AMI\",\"5 Beeps\",\"CPU Error\",\"Reseat CPU\"),\n                    (\"Award\",\"1 Long\",\"DRAM Error\",\"Check RAM\"),\n                    (\"Phoenix\",\"1-1-2\",\"CPU Fail\",\"Check CPU Socket\")]:\n            self.post_tree.insert(\"\", \"end\", values=row)\n        self.post_tree.pack(fill=\"both\", expand=True, padx=16, pady=8)\n        return frame\n\n    def _build_cap_check(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udd0d Capacitor Guide\", \"Visual Inspection\", hw=True)\n        self.cap_guide = self._scrolled_text(frame, 25)\n        self._append_log(self.cap_guide, \"\u274c BAD: Bulging top, leaked crust.\\n\u2705 GOOD: Flat top, clean base.\\nMOSFET BAD: Cracked, burnt legs.\", C[\"error\"])\n        return frame\n\n    # ---------- POWER BOOST SECTION (clean grid layout) ----------\n    def _build_boost_section(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\u26a1 Ultimate Power Boost\", \"PC ki speed badhaane ke liye professional tweaks \u2014 ek click mein\")\n\n        # \u2500\u2500 Top: One-Click master button \u2500\u2500\n        master_row = tk.Frame(frame, bg=C[\"card\"])\n        master_row.pack(fill=\"x\", padx=16, pady=(10, 4))\n        tk.Label(master_row, text=\"\ud83d\udd25  Sabse pehle yahi chalao:\",\n                 font=FONTS[\"subhead\"], fg=C[\"accent4\"], bg=C[\"card\"]).pack(side=\"left\", padx=14, pady=10)\n        def one_click_all_boosts():\n            if self._create_restore_point(\"Ultimate Power Boost\"):\n                self._launch_job(\"run_all_boosts\", self._run_all_boosts)\n        tk.Button(master_row, text=\"\u26a1 ONE-CLICK: Saare Boosts Apply Karo\",\n                  font=(\"Segoe UI\", 11, \"bold\"), bg=C[\"accent4\"], fg=C[\"bg\"],\n                  bd=0, padx=20, pady=10, cursor=\"hand2\",\n                  command=one_click_all_boosts).pack(side=\"left\", padx=10, pady=8)\n\n        # \u2500\u2500 Grid: individual tweak cards \u2500\u2500\n        grid_lbl = tk.Frame(frame, bg=C[\"bg\"])\n        grid_lbl.pack(fill=\"x\", padx=16, pady=(8, 2))\n        tk.Label(grid_lbl, text=\"Ya alag alag apply karo:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"]).pack(side=\"left\")\n\n        grid = tk.Frame(frame, bg=C[\"bg\"])\n        grid.pack(fill=\"x\", padx=16, pady=4)\n\n        boost_items = [\n            (\"\u26a1\", \"CPU Cores Unpark\",   \"Sabhi cores active karo\\n(latency kum hoti hai)\",       C[\"btn_hw\"],     lambda: self._confirm_and_run(\"Unpark CPU Cores\", \"Sabhi CPU cores hamesha active rahenge, latency kum hogi.\", lambda: f\"CPU cores: {psutil.cpu_count()}\", self._unpark_cpu_cores, None)),\n            (\"\ud83c\udfaf\", \"App Priority Fix\",   \"Foreground app ko\\nzyada CPU do\",                        C[\"btn_info\"],   lambda: self._confirm_and_run(\"Priority Optimizer\", \"Foreground apps ko zyada CPU priority milegi.\", lambda: \"Default Windows settings.\", self._auto_priority_optimizer, None)),\n            (\"\ud83d\udcc0\", \"Pagefile Optimize\",  \"RAM ke hisaab se\\nPagefile set karo (1.5x)\",             C[\"btn_warn\"],   lambda: self._confirm_and_run(\"Optimal Pagefile\", \"Pagefile 1.5x RAM size pe set hoga.\", lambda: \"Current pagefile badle ga.\", self._optimal_pagefile, None)),\n            (\"\ud83e\udde0\", \"RAM Compression Off\",\"Memory compression band\\n(CPU load ghatega)\",            C[\"btn_chip\"],   lambda: self._confirm_and_run(\"Disable Memory Compression\", \"Memory compression disable hoga, CPU load kum hoga.\", lambda: \"Currently on.\", self._disable_memory_compression, None)),\n            (\"\ud83c\udfae\", \"Game Mode ON\",       \"Game Mode + GPU\\nScheduling enable karo\",                C[\"btn_info\"],   lambda: self._confirm_and_run(\"Game Mode\", \"Game Mode aur GPU hardware scheduling enable hoga.\", lambda: \"Current: unknown.\", self._enable_game_mode, None)),\n            (\"\u2601\ufe0f\", \"OneDrive Hatao\",     \"OneDrive uninstall karo\\n(Explorer fast hoga)\",          C[\"btn_danger\"], lambda: self._confirm_and_run(\"Remove OneDrive\", \"OneDrive poori tarah uninstall hoga.\", lambda: \"OneDrive installed hai.\", self._remove_onedrive, None)),\n        ]\n\n        for i, (emoji, title, desc, color, cmd) in enumerate(boost_items):\n            col = i % 3\n            row_n = i // 3\n            card = tk.Frame(grid, bg=C[\"card\"], highlightbackground=color, highlightthickness=1)\n            card.grid(row=row_n, column=col, padx=6, pady=6, sticky=\"nsew\")\n            grid.columnconfigure(col, weight=1)\n            tk.Label(card, text=emoji, font=(\"Segoe UI\", 18), fg=color, bg=C[\"card\"]).pack(pady=(10, 2))\n            tk.Label(card, text=title, font=FONTS[\"subhead\"], fg=C[\"text\"], bg=C[\"card\"]).pack()\n            tk.Label(card, text=desc, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"],\n                     justify=\"center\", wraplength=180).pack(padx=8, pady=4)\n            tk.Button(card, text=\"\u25b6 Apply\", font=FONTS[\"small\"],\n                      bg=color, fg=C[\"bg\"] if color in [C[\"accent\"], C[\"accent2\"], C[\"accent4\"]] else C[\"text\"],\n                      bd=0, padx=14, pady=5, cursor=\"hand2\",\n                      command=cmd).pack(pady=(0, 10))\n\n        # \u2500\u2500 Log area \u2500\u2500\n        tk.Label(frame, text=\"  Result Log:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"]).pack(anchor=\"w\", padx=16, pady=(8, 2))\n        self.boost_log = self._scrolled_text(frame, height=10)\n        return frame\n\n    def _run_all_boosts(self):\n        self._append_log(self.boost_log, \"Starting Deep Scan + Ultimate Power Boost...\", C[\"accent4\"])\n        self._deep_boost_scan()\n        self._unpark_cpu_cores(quiet=True)\n        self._auto_priority_optimizer(quiet=True)\n        self._optimal_pagefile(quiet=True)\n        self._disable_memory_compression(quiet=True)\n        self._enable_game_mode(quiet=True)\n        self._remove_onedrive(quiet=True)\n        self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Multimedia\\SystemProfile\", \"NetworkThrottlingIndex\", 0xffffffff, winreg.REG_DWORD, \"Network throttling disabled\", self.boost_log)\n        self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\DeliveryOptimization\\Config\", \"DODownloadMode\", 0, winreg.REG_DWORD, \"Delivery Optimization P2P off\", self.boost_log)\n        self._service_stop_checked(\"DoSvc\", \"Delivery Optimization service\", self.boost_log)\n        self._service_config_checked(\"DoSvc\", \"disabled\", \"Delivery Optimization service\", self.boost_log)\n        self._run_cmd('powercfg -h off')\n        self._reg_set_checked(winreg.HKEY_LOCAL_MACHINE, r\"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Power\", \"HiberbootEnabled\", 0, winreg.REG_DWORD, \"Fast Startup disabled\", self.boost_log)\n        self._append_log(self.boost_log, \"\ud83c\udf89 All boosts applied! Restart recommended.\", C[\"success\"])\n        self._set_status(\"Ultimate Power Boost Complete\", C[\"success\"])\n\n    def _deep_boost_scan(self):\n        try:\n            vm = psutil.virtual_memory()\n            self._append_log(self.boost_log, f\"Deep scan: RAM used {vm.percent:.1f}% | available {self._fmt_size(vm.available)}\", C[\"text\"])\n            heavy = []\n            for proc in psutil.process_iter(['pid', 'name', 'memory_info']):\n                try:\n                    mem = proc.info.get('memory_info')\n                    rss = mem.rss if mem else 0\n                    if rss:\n                        heavy.append((rss, proc.info.get('pid'), proc.info.get('name') or 'unknown'))\n                except Exception:\n                    pass\n            for rss, pid, name in sorted(heavy, reverse=True)[:5]:\n                self._append_log(self.boost_log, f\"Deep scan process: PID {pid} {name} {self._fmt_size(rss)}\", C[\"text_dim\"])\n            junk_total = 0\n            for path in [os.environ.get(\"TEMP\", \"\"), r\"C:\\Windows\\Temp\", os.path.join(os.environ.get(\"LOCALAPPDATA\", \"\"), r\"Microsoft\\Windows\\Explorer\")]:\n                if path and os.path.exists(path):\n                    junk_total += self._folder_size(path)\n            self._append_log(self.boost_log, f\"Deep scan cache estimate: {self._fmt_size(junk_total)}\", C[\"accent\"])\n        except Exception as e:\n            self._append_log(self.boost_log, f\"Deep scan skipped: {e}\", C[\"warning\"])\n\n    def _unpark_cpu_cores(self, quiet=False):\n        try:\n            self._run_cmd('powercfg -setacvalueindex scheme_current sub_processor 0cc5b647-c1df-4637-891a-dec35c318583 0')\n            self._run_cmd('powercfg -setactive scheme_current')\n            msg = \"\u2705 CPU Cores Unparked (All cores active)\"\n            if not quiet:\n                self._append_log(self.boost_log, msg, C[\"success\"])\n            else:\n                self._log(msg, \"OK\")\n        except:\n            pass\n\n    def _auto_priority_optimizer(self, quiet=False):\n        self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Multimedia\\SystemProfile\", \"SystemResponsiveness\", 0, winreg.REG_DWORD)\n        self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Multimedia\\SystemProfile\", \"EnablePriorityBoost\", 1, winreg.REG_DWORD)\n        self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Multimedia\\SystemProfile\\Tasks\\Games\", \"GPU Priority\", 8, winreg.REG_DWORD)\n        self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Multimedia\\SystemProfile\\Tasks\\Games\", \"Priority\", 6, winreg.REG_DWORD)\n        msg = \"\u2705 Foreground app priority boosted, background lowered\"\n        if not quiet:\n            self._append_log(self.boost_log, msg, C[\"success\"])\n        else:\n            self._log(msg, \"OK\")\n\n    def _optimal_pagefile(self, quiet=False):\n        try:\n            total_ram_gb = psutil.virtual_memory().total // (1024**3)\n            recommended_mb = max(1024, total_ram_gb * 1024)  # min 1GB\n            self._run_cmd(f'wmic pagefileset where name=\"C:\\\\\\\\pagefile.sys\" set InitialSize={recommended_mb},MaximumSize={recommended_mb}')\n            msg = f\"\u2705 Pagefile set to {recommended_mb}MB (1x RAM)\"\n            if not quiet:\n                self._append_log(self.boost_log, msg, C[\"success\"])\n        except Exception as e:\n            self._append_log(self.boost_log, f\"Pagefile error: {e}\", C[\"error\"])\n\n    def _disable_memory_compression(self, quiet=False):\n        self._run_cmd('powershell \"Disable-MMAgent -MemoryCompression\"')\n        msg = \"\u2705 Memory Compression Disabled (CPU load reduced)\"\n        if not quiet:\n            self._append_log(self.boost_log, msg, C[\"success\"])\n        else:\n            self._log(msg, \"OK\")\n\n    def _enable_game_mode(self, quiet=False):\n        self._reg_set(winreg.HKEY_CURRENT_USER, r\"Software\\Microsoft\\Windows\\CurrentVersion\\GameDVR\", \"AppCaptureEnabled\", 0, winreg.REG_DWORD)\n        self._reg_set(winreg.HKEY_CURRENT_USER, r\"Software\\Microsoft\\Windows\\CurrentVersion\\GameDVR\", \"GameDVR_Enabled\", 0, winreg.REG_DWORD)\n        self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\PolicyManager\\default\\ApplicationManagement\\AllowGameDVR\", \"value\", 0, winreg.REG_DWORD)\n        self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Multimedia\\SystemProfile\", \"SystemResponsiveness\", 0, winreg.REG_DWORD)\n        self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Multimedia\\SystemProfile\\Tasks\\Games\", \"GPU Priority\", 8, winreg.REG_DWORD)\n        self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Multimedia\\SystemProfile\\Tasks\\Games\", \"Priority\", 6, winreg.REG_DWORD)\n        msg = \"\u2705 Game Mode + GPU Scheduling Enabled\"\n        if not quiet:\n            self._append_log(self.boost_log, msg, C[\"success\"])\n        else:\n            self._log(msg, \"OK\")\n\n    def _remove_onedrive(self, quiet=False):\n        try:\n            self._run_cmd('taskkill /f /im OneDrive.exe')\n            self._run_cmd('%SystemRoot%\\\\SysWOW64\\\\OneDriveSetup.exe /uninstall')\n            self._run_cmd('%SystemRoot%\\\\System32\\\\OneDriveSetup.exe /uninstall')\n            self._run_cmd('rd \"%UserProfile%\\\\OneDrive\" /s /q')\n            self._reg_set(winreg.HKEY_LOCAL_MACHINE, r\"SOFTWARE\\Policies\\Microsoft\\Windows\\OneDrive\", \"DisableFileSyncNGSC\", 1, winreg.REG_DWORD)\n            msg = \"\u2705 OneDrive completely removed (Explorer will be faster)\"\n            if not quiet:\n                self._append_log(self.boost_log, msg, C[\"success\"])\n            else:\n                self._log(msg, \"OK\")\n        except Exception as e:\n            self._append_log(self.boost_log, f\"OneDrive removal error: {e}\", C[\"error\"])\n\n    # ---------- QUICK ACTIONS ----------\n    def _quick_clean_and_ram(self):\n        \"\"\"Clean Temp + RAM Optimize \u2014 ek saath dono kaam\"\"\"\n        self._quick_clean_temp()\n        self.after(500, self._quick_optimize_ram)\n\n    def _quick_services_and_registry(self):\n        \"\"\"Services disable + Registry tweaks \u2014 ek saath dono kaam\"\"\"\n        self._quick_services()\n        self.after(500, self._quick_registry)\n\n    def _quick_clean_temp(self):\n        self._show_section(\"cleaner\")\n        self._professional_scan()\n\n    def _quick_optimize_ram(self):\n        self._show_section(\"memory\")\n        self._ram_empty_with_confirm()\n\n    def _quick_services(self):\n        self._show_section(\"services\")\n        self._scan_impacting_services()\n\n    def _quick_registry(self):\n        self._show_section(\"registry\")\n        self._apply_registry()\n\n    def _full_scan(self):\n        def before():\n            return \"Starting full system scan (cleaner + services).\"\n        def action():\n            self._do_full_scan()\n        self._confirm_and_run(\"Full System Scan\", \"This will scan for junk files and heavy services. No changes will be applied automatically.\", before, action, None)\n\n    def _do_full_scan(self):\n        self._do_clean_scan()\n        self._do_scan_services()\n        self._log(\"Full scan complete\", \"OK\")\n\n    def _one_click_health_scan(self):\n        self._set_status(\"Health scan...\", C[\"accent4\"])\n        self._launch_job(\"health_scan\", self._do_health_scan)\n\n    def _do_health_scan(self):\n        try:\n            report = self.health_engine.analyze()\n            self._last_health_report = report\n            self.after(0, lambda: self._apply_health_report_ui(report))\n            lines = [f\"Health Score: {report['score']}/100 ({report['grade']})\"]\n            for c in report.get(\"checks\", [])[:12]:\n                lines.append(f\"  \u2022 {c['name']}: {c['detail']}\")\n            if report.get(\"recommendations\"):\n                lines.append(\"\\nRecommendations:\")\n                for r in report[\"recommendations\"]:\n                    lines.append(f\"  \u2192 {r}\")\n            msg = \"\\n\".join(lines)\n            self.after(0, lambda: messagebox.showinfo(\"System Health Scan\", msg))\n            self.after(0, lambda: self._set_status(f\"Health score: {report['score']}/100\", C[\"success\"]))\n        except Exception as e:\n            self.after(0, lambda: messagebox.showerror(\"Health Scan\", str(e)))\n\n    def _apply_health_report_ui(self, report):\n        if not report or \"health\" not in getattr(self, \"dash_cards\", {}):\n            return\n        try:\n            score = int(report.get(\"score\", 0))\n            grade = report.get(\"grade\", \"\")\n            color = C.get(report.get(\"color\", \"accent\"), C[\"accent\"])\n            self.dash_cards[\"health\"]._value_lbl.config(text=f\"{score}\")\n            self.dash_cards[\"health\"]._bar.config(value=score)\n            if hasattr(self, \"safety_health_lbl\"):\n                self.safety_health_lbl.config(\n                    text=f\"{score}/100 \u2014 {grade}\", fg=color)\n            if hasattr(self, \"dashboard_recommendation_tree\"):\n                self._refresh_intelligent_recommendations()\n            if hasattr(self, \"safety_recommendations\"):\n                self.safety_recommendations.config(text=self._recommendations_as_text(limit=6), fg=C[\"text\"])\n        except Exception:\n            pass\n\n    def _refresh_health_score_card(self):\n        def task():\n            try:\n                report = self.health_engine.analyze()\n                self._last_health_report = report\n                self.after(0, lambda r=report: self._apply_health_report_ui(r))\n            except Exception:\n                pass\n        self._launch_job(\"health_score_refresh\", task)\n\n    def _one_click_all_boosts(self):\n        if self._create_restore_point(\"One Click All Boosts\"):\n            self._launch_job(\"run_all_boosts\", self._run_all_boosts)\n\n    # ---------- ADVANCED TOOLS ----------\n    def _adv_tree(self, parent, columns, height=12):\n        wrap = tk.Frame(parent, bg=C[\"card\"])\n        tree = ttk.Treeview(wrap, columns=columns, show=\"headings\", height=height, style=\"Custom.Treeview\")\n        vsb = ttk.Scrollbar(wrap, orient=\"vertical\", command=tree.yview)\n        hsb = ttk.Scrollbar(wrap, orient=\"horizontal\", command=tree.xview)\n        tree.configure(yscrollcommand=vsb.set, xscrollcommand=hsb.set)\n        tree.grid(row=0, column=0, sticky=\"nsew\")\n        vsb.grid(row=0, column=1, sticky=\"ns\")\n        hsb.grid(row=1, column=0, sticky=\"ew\")\n        wrap.rowconfigure(0, weight=1)\n        wrap.columnconfigure(0, weight=1)\n        for col in columns:\n            tree.heading(col, text=col)\n            tree.column(col, width=130, anchor=\"w\", stretch=True)\n        return wrap, tree\n\n    def _adv_card(self, parent, title):\n        frame = tk.LabelFrame(parent, text=title, font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"], bd=1, relief=\"flat\", labelanchor=\"nw\")\n        return frame\n\n    def _build_driver_manager(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"Driver Manager\", \"Driver scan, purane driver aur unsigned risk check\")\n        content = self._scrollable_section_body(frame)\n        self._action_card_grid(content, [\n            (\"\ud83d\udd0d\", \"Driver Scan\", \"Saare drivers scan karo\", C[\"btn_info\"], self._driver_scan_all),\n            (\"\ud83d\udccb\", \"Purane Only\", \"Purane drivers filter karo\", C[\"btn_chip\"], self._driver_filter_old),\n            (\"\ud83d\udd04\", \"Unsigned Only\", \"Unsigned drivers filter karo\", C[\"btn_warn\"], self._driver_filter_unsigned),\n            (\"\ud83d\udcbe\", \"CSV Backup\", \"Driver list CSV mein save karo\", C[\"btn\"], self._driver_export_csv),\n            (\"\ud83c\udf10\", \"Device Manager\", \"Device Manager kholo\", C[\"accent2\"], lambda: self._run_cmd(\"devmgmt.msc\")),\n            (\"\u2699\", \"Driver Update via WU\", \"Windows Update se driver updates dhundo\", C[\"btn_chip\"], self._easydriver_update_via_windows_update),\n        ], cols=6)\n        body = tk.Frame(content, bg=C[\"bg\"])\n        body.pack(fill=\"both\", expand=True, padx=14, pady=8)\n        left = tk.Frame(body, bg=C[\"card\"])\n        left.pack(side=\"left\", fill=\"both\", expand=True, padx=(0,8))\n        right = tk.Frame(body, bg=C[\"card\"], width=380)\n        right.pack(side=\"right\", fill=\"both\", padx=(8,0))\n        right.pack_propagate(False)\n        cols = [\"Device Name\", \"Driver Version\", \"Driver Date\", \"Status\", \"Age\"]\n        wrap, self.driver_tree = self._adv_tree(left, cols, height=18)\n        wrap.pack(fill=\"both\", expand=True, padx=8, pady=8)\n        self.driver_tree.tag_configure(\"old\", foreground=C[\"warning\"])\n        self.driver_tree.tag_configure(\"very_old\", foreground=C[\"error\"])\n        self.driver_tree.tag_configure(\"unsigned\", foreground=C[\"error\"])\n        self.driver_tree.tag_configure(\"ok\", foreground=C[\"success\"])\n        self.driver_tree.bind(\"&lt;&gt;\", self._driver_on_select)\n        self.driver_detail = tk.Frame(right, bg=C[\"card\"])\n        self.driver_detail.pack(fill=\"both\", expand=True, padx=10, pady=10)\n        tk.Label(self.driver_detail, text=\"Driver select karo\", font=FONTS[\"subhead\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\")\n        self.driver_log = self._scrolled_text(content, height=7)\n        self.driver_all_rows = []\n        return frame\n\n    def _build_easy_driver_clone(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udda5 Easy Driver\",\n                             \"Missing/Outdated driver scan, Windows Update driver install, backup &amp; restore \u2014 DriverEasy style\")\n        content = self._scrollable_section_body(frame)\n\n        # \u2500\u2500 Fixed top area: info banner + action buttons \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        top = tk.Frame(content, bg=C[\"bg\"])\n        top.pack(fill=\"x\")\n\n        info = tk.Frame(top, bg=\"#0D1A0D\", highlightbackground=C[\"accent2\"], highlightthickness=1)\n        info.pack(fill=\"x\", padx=16, pady=(4, 6))\n        for txt in [\n            \"\ud83c\udf10 Internet required for Windows Update driver downloads.\",\n            \"\ud83d\udcbe Driver backup uses built-in pnputil export/restore.\",\n            \"\u26a0 Only signed drivers install successfully \u2014 unsigned drivers are skipped.\",\n            \"\u2705 Missing driver scan uses real PnP device status and WMI fallback.\",\n        ]:\n            tk.Label(info, text=txt, font=FONTS[\"small\"], fg=C[\"text_dim\"],\n                     bg=\"#0D1A0D\", anchor=\"w\").pack(anchor=\"w\", padx=12, pady=1)\n        tk.Label(info, text=\"\", bg=\"#0D1A0D\").pack(pady=2)\n\n        self._action_card_grid(top, [\n            (\"\ud83d\udd0d\", \"Scan Missing\",  \"Error/missing drivers dhundo\", C[\"error\"],   self._easydriver_scan_and_show),\n            (\"\ud83d\udccb\", \"Scan Outdated\", \"Purane drivers list karo\",       C[\"btn_warn\"], self._easydriver_show_outdated),\n            (\"\ud83c\udf10\", \"Update via WU\",  \"Windows Update se install karo\", C[\"btn_chip\"], self._easydriver_update_via_windows_update),\n            (\"\ud83d\udcbe\", \"Backup All\",    \"Saare installed drivers export karo\", C[\"accent2\"], self._easydriver_backup_all),\n            (\"\ud83d\udce5\", \"Restore Backup\", \"Backup folder se restore karo\",   C[\"btn_chip\"], self._easydriver_restore_from_backup),\n            (\"\ud83d\udda5\", \"Device Manager\", \"Windows Device Manager kholo\",   C[\"btn\"],     lambda: self._run_cmd(\"devmgmt.msc\", timeout=5)),\n        ], cols=3)\n\n        # \u2500\u2500 Progress bar (always visible, fixed below buttons) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        clone_prog_frame = tk.Frame(content, bg=C[\"card\"], relief=\"flat\", bd=0)\n        clone_prog_frame.pack(fill=\"x\", padx=16, pady=(4, 2))\n        self.clone_status_label = tk.Label(\n            clone_prog_frame,\n            text=\"Ready\",\n            font=FONTS[\"small\"],\n            fg=C[\"text_dim\"],\n            bg=C[\"card\"],\n            anchor=\"w\"\n        )\n        self.clone_status_label.pack(fill=\"x\", padx=6, pady=(4, 2))\n        self.clone_progress_var = tk.DoubleVar(value=0.0)\n        self.clone_progress_bar = ttk.Progressbar(\n            clone_prog_frame,\n            variable=self.clone_progress_var,\n            maximum=100.0,\n            mode=\"determinate\"\n        )\n        self.clone_progress_bar.pack(fill=\"x\", padx=6, pady=(0, 6))\n\n        # \u2500\u2500 Scrollable body: tree + log \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        body_outer = tk.Frame(content, bg=C[\"bg\"])\n        body_outer.pack(fill=\"both\", expand=True, padx=16, pady=(4, 6))\n\n        cols = (\"Device Name\", \"Status\", \"Class\", \"Severity\", \"Action\")\n        self.driver_easy_tree = ttk.Treeview(body_outer, columns=cols, show=\"headings\",\n                                              height=12, style=\"Custom.Treeview\",\n                                              selectmode=\"browse\")\n        for col, w in zip(cols, [300, 90, 120, 90, 150]):\n            self.driver_easy_tree.heading(col, text=col)\n            self.driver_easy_tree.column(col, width=w, anchor=\"w\")\n        self.driver_easy_tree.tag_configure(\"critical\", foreground=C[\"error\"])\n        self.driver_easy_tree.tag_configure(\"warning\", foreground=C[\"warning\"])\n        self.driver_easy_tree.tag_configure(\"ok\", foreground=C[\"success\"])\n\n        vsb = ttk.Scrollbar(body_outer, orient=\"vertical\", command=self.driver_easy_tree.yview)\n        self.driver_easy_tree.configure(yscrollcommand=vsb.set)\n        self.driver_easy_tree.pack(side=\"left\", fill=\"both\", expand=True)\n        vsb.pack(side=\"right\", fill=\"y\")\n\n        self.driver_easy_log = self._scrolled_text(content, height=6)\n        self.driver_easy_rows = []\n        return frame\n\n    def _easydriver_set_progress(self, pct, text=None, mode=\"determinate\"):\n        def _update():\n            try:\n                pct_float = max(0.0, min(100.0, float(pct)))\n            except Exception:\n                pct_float = 0.0\n            if hasattr(self, \"clone_progress_bar\"):\n                try:\n                    self.clone_progress_bar.stop()\n                    self.clone_progress_bar.config(mode=mode)\n                    if mode == \"indeterminate\":\n                        self.clone_progress_bar.start(10)\n                except Exception:\n                    pass\n            if hasattr(self, \"clone_progress_var\"):\n                try:\n                    self.clone_progress_var.set(pct_float)\n                except Exception:\n                    pass\n            if hasattr(self, \"clone_status_label\") and text is not None:\n                self.clone_status_label.config(text=f\"{int(pct_float)}% - {str(text)[:180]}\")\n        self.after(0, _update)\n\n    def _easydriver_scan_and_show(self):\n        self._append_log(self.driver_easy_log, \"\ud83d\udd0d Easy Driver scan starting...\", C[\"accent\"])\n        self._easydriver_set_progress(0, \"Scanning missing/error drivers...\")\n        self._launch_job(\"easy_driver_scan\", self._do_easydriver_scan)\n\n    def _easydriver_show_outdated(self):\n        self._append_log(self.driver_easy_log, \"\ud83d\udd0d Easy Driver outdated scan starting...\", C[\"accent\"])\n        self._easydriver_set_progress(0, \"Scanning outdated drivers...\")\n        self._launch_job(\"easy_driver_outdated\", self._do_easydriver_show_outdated)\n\n    def _easydriver_check_internet(self):\n        import urllib.request\n        import urllib.error\n\n        for url in [\n            \"https://www.microsoft.com\",\n            \"https://www.google.com\",\n            \"https://1.1.1.1\",\n        ]:\n            try:\n                urllib.request.urlopen(url, timeout=5)\n                return True\n            except Exception:\n                continue\n\n        messagebox.showerror(\n            \"Internet Connection Nahi Mili\",\n            \"Driver auto-download ke liye internet zaroori hai.\\n\\n\"\n            \"Kya check karo:\\n\"\n            \"  1\ufe0f\u20e3  Wi-Fi ya LAN cable connected hai?\\n\"\n            \"  2\ufe0f\u20e3  Antivirus/Firewall block to nahi kar raha?\\n\"\n            \"  3\ufe0f\u20e3  Browser mein koi website khulti hai?\\n\\n\"\n            \"Offline kya kar sakte hain:\\n\"\n            \"  \u2705 Driver Scan \u2014 chalegi\\n\"\n            \"  \u2705 Driver Backup \u2014 chalegi (pnputil)\\n\"\n            \"  \u2705 Driver Restore \u2014 chalegi (agar backup hai)\\n\"\n            \"  \u274c Auto Download \u2014 nahi chalegi\"\n        )\n        return False\n\n    def _easydriver_update_via_windows_update(self):\n        if not hasattr(self, \"driver_easy_log\") and hasattr(self, \"driver_log\"):\n            self.driver_easy_log = self.driver_log\n        if not self._easydriver_check_internet():\n            return\n\n        if not messagebox.askyesno(\n            \"Windows Update Driver\",\n            \"Windows Update se drivers download aur install honge.\\n\\n\"\n            \"\u26a0 Kuch drivers ke liye reboot required hoga.\\n\"\n            \"\u26a0 Installation mein 5-15 minute lag sakta hai.\\n\\n\"\n            \"Pehle system restore point create kiya jaayega.\\n\\n\"\n            \"Continue karein?\"\n        ):\n            return\n\n        self._easydriver_set_progress(5, \"Creating restore point...\")\n        self._append_log(self.driver_easy_log, \"System Restore Point bana raha hoon...\", C[\"accent4\"])\n        rp = safe_powershell(\n            'Checkpoint-Computer -Description \"GodawariDriverUpdate\" '\n            '-RestorePointType DEVICE_DRIVER_INSTALL', timeout=120)\n        if rp.returncode == 0:\n            self._append_log(self.driver_easy_log, \"\u2705 Restore point created\", C[\"success\"])\n\n        wu_script = r\"\"\"\n        try {\n            $UpdateSession = New-Object -ComObject Microsoft.Update.Session\n            $Searcher = $UpdateSession.CreateUpdateSearcher()\n            $SearchResult = $Searcher.Search(\"IsInstalled=0 and Type='Driver'\")\n\n            $Updates = $SearchResult.Updates\n            $Count = $Updates.Count\n\n            if ($Count -eq 0) {\n                Write-Output \"NO_UPDATES\"\n                exit 0\n            }\n\n            Write-Output \"FOUND:$Count\"\n\n            $ToInstall = New-Object -ComObject Microsoft.Update.UpdateColl\n            for ($i=0; $i -lt $Updates.Count; $i++) {\n                $update = $Updates.Item($i)\n                Write-Output \"DRIVER:$($update.Title)\"\n                $ToInstall.Add($update) | Out-Null\n            }\n\n            $Downloader = $UpdateSession.CreateUpdateDownloader()\n            $Downloader.Updates = $ToInstall\n            Write-Output \"DOWNLOADING...\"\n            $DownloadResult = $Downloader.Download()\n            Write-Output \"DOWNLOAD_RC:$($DownloadResult.ResultCode)\"\n\n            $Installer = $UpdateSession.CreateUpdateInstaller()\n            $Installer.Updates = $ToInstall\n            Write-Output \"INSTALLING...\"\n            $InstallResult = $Installer.Install()\n            Write-Output \"INSTALL_RC:$($InstallResult.ResultCode)\"\n            Write-Output \"REBOOT_REQUIRED:$($InstallResult.RebootRequired)\"\n\n        } catch {\n            Write-Output \"ERROR:$($_.Exception.Message)\"\n        }\n        \"\"\"\n\n        def run_wu():\n            self._easydriver_set_progress(15, \"Searching Windows Update drivers...\")\n            result = safe_powershell(wu_script, timeout=600)\n            for line in result.output.splitlines():\n                line = line.strip()\n                if not line:\n                    continue\n                if line == \"NO_UPDATES\":\n                    self._easydriver_set_progress(100, \"No driver updates found.\")\n                    self.after(0, lambda: self._append_log(self.driver_easy_log, \"\u2705 Saare drivers up-to-date hain!\", C[\"success\"]))\n                elif line.startswith(\"FOUND:\"):\n                    count = line.split(\":\", 1)[1]\n                    self._easydriver_set_progress(30, f\"{count} driver update(s) found.\")\n                    self.after(0, lambda c=count: self._append_log(self.driver_easy_log, f\"\ud83d\udd0d {c} driver update(s) mila!\", C[\"accent4\"]))\n                elif line.startswith(\"DRIVER:\"):\n                    name = line.split(\":\", 1)[1]\n                    self.after(0, lambda n=name: self._append_log(self.driver_easy_log, f\"  \ud83d\udce6 {n}\", C[\"text\"]))\n                elif line.startswith(\"DOWNLOADING\"):\n                    self._easydriver_set_progress(45, \"Downloading driver updates...\", \"indeterminate\")\n                elif line.startswith(\"DOWNLOAD_RC:\"):\n                    self._easydriver_set_progress(65, f\"Download finished rc={line.split(':', 1)[1]}\")\n                elif line.startswith(\"INSTALLING\"):\n                    self._easydriver_set_progress(75, \"Installing driver updates...\", \"indeterminate\")\n                elif line.startswith(\"INSTALL_RC:\"):\n                    rc = line.split(\":\", 1)[1]\n                    status = \"\u2705 Install successful\" if rc in (\"2\", \"3\") else f\"\u26a0 Install rc={rc}\"\n                    color = C[\"success\"] if rc in (\"2\", \"3\") else C[\"warning\"]\n                    self._easydriver_set_progress(100 if rc in (\"2\", \"3\") else 90, status)\n                    self.after(0, lambda s=status, c=color: self._append_log(self.driver_easy_log, s, c))\n                elif line.startswith(\"REBOOT_REQUIRED:True\"):\n                    self.after(0, lambda: messagebox.showinfo(\n                        \"Reboot Required\",\n                        \"Driver install complete!\\n\\nSystem restart zaroori hai.\\nAbhi restart karein?\"\n                    ))\n                elif line.startswith(\"ERROR:\"):\n                    err = line.split(\":\", 1)[1]\n                    self._easydriver_set_progress(0, f\"Windows Update failed: {err}\")\n                    self.after(0, lambda e=err: self._append_log(self.driver_easy_log, f\"\u274c Error: {e}\", C[\"error\"]))\n\n        self._launch_job(\"easy_driver_update\", run_wu)\n\n    def _easydriver_backup_all(self):\n        backup_dir = filedialog.askdirectory(\n            title=\"Driver Backup Folder Select Karo (naya ya khali folder choose karo)\")\n        if not backup_dir:\n            return\n\n        if not messagebox.askyesno(\n            \"Driver Backup Confirm\",\n            f\"Saare installed drivers yahan export honge:\\n{backup_dir}\\n\\n\" \\\n            \"Isme kuch minute lag sakte hain.\\nContinue?\"):\n            return\n\n        self._append_log(self.driver_easy_log, f\"Driver backup shuru: {backup_dir}\", C[\"accent4\"])\n        self._easydriver_set_progress(0, \"Driver backup starting...\")\n\n        def run_backup():\n            self._easydriver_set_progress(10, \"Exporting installed drivers...\", \"indeterminate\")\n            result = safe_run([\"pnputil\", \"/export-driver\", \"*\", backup_dir], timeout=300)\n            out = (result.output or \"\").strip()\n            rc = result.returncode\n            inf_count = 0\n            try:\n                for root, _, files in os.walk(backup_dir):\n                    for f in files:\n                        if f.lower().endswith(\".inf\"):\n                            inf_count += 1\n            except Exception:\n                pass\n            if rc == 0:\n                self._easydriver_set_progress(100, f\"Backup complete: {inf_count} drivers exported.\")\n                self.after(0, lambda: self._append_log(\n                    self.driver_easy_log,\n                    f\"\u2705 Backup complete! {inf_count} drivers exported to:\\n{backup_dir}\",\n                    C[\"success\"]))\n                self.after(0, lambda: messagebox.showinfo(\n                    \"Backup Complete\",\n                    f\"\u2705 {inf_count} driver files backup ho gaye!\\n\\nLocation:\\n{backup_dir}\\n\\n\"\n                    \"Restore ke liye: 'Restore From Backup' button dabao.\"))\n            else:\n                self._easydriver_set_progress(0, f\"Backup failed rc={rc}\")\n                self.after(0, lambda: self._append_log(\n                    self.driver_easy_log,\n                    f\"\u274c Backup failed (rc={rc})\\n{out[:300]}\",\n                    C[\"error\"]))\n\n        self._launch_job(\"easy_driver_backup\", run_backup)\n\n    def _easydriver_restore_from_backup(self):\n        backup_dir = filedialog.askdirectory(\n            title=\"Driver Backup Folder Select Karo (jahan .inf files hain)\")\n        if not backup_dir:\n            return\n\n        inf_files = [f for f in os.listdir(backup_dir) if f.lower().endswith(\".inf\")]\n        if not inf_files:\n            messagebox.showerror(\"INF Files Nahi Mili\",\n                                 f\"Selected folder mein koi .inf file nahi mili:\\n{backup_dir}\\n\\n\"\n                                 \"Sahi backup folder select karo.\")\n            return\n\n        if not messagebox.askyesno(\n            \"Driver Restore Confirm\",\n            f\"Folder: {backup_dir}\\n\"\n            f\"INF files found: {len(inf_files)}\\n\\n\"\n            \"\u26a0 Yeh sab drivers install karne ki koshish karega.\\n\"\n            \"\u26a0 Kuch drivers ke liye reboot required ho sakta hai.\\n\"\n            \"\u26a0 Sirf digitally signed drivers install honge.\\n\\n\"\n            \"Continue?\"):\n            return\n\n        self._append_log(self.driver_easy_log,\n                         f\"Driver restore shuru: {backup_dir} ({len(inf_files)} INF files)\",\n                         C[\"accent4\"])\n        self._easydriver_set_progress(0, f\"Restoring {len(inf_files)} driver INF files...\")\n\n        def run_restore():\n            self._easydriver_set_progress(15, \"Installing drivers from backup...\", \"indeterminate\")\n            backup_dir_abs = os.path.abspath(backup_dir)\n            cmd = [\n                \"pnputil\",\n                \"/add-driver\",\n                backup_dir_abs,\n                \"/subdirs\",\n                \"/install\",\n            ]\n            result = safe_run(cmd, timeout=600)\n            out = (result.output or \"\").strip()\n            rc = result.returncode\n            installed = sum(1 for line in out.splitlines() if \"published name\" in line.lower())\n            failed = sum(1 for line in out.splitlines() if \"failed\" in line.lower())\n            status = \"OK\" if rc == 0 else \"PARTIAL\"\n            color = C[\"success\"] if status == \"OK\" else C[\"warning\"]\n            self._easydriver_set_progress(100 if rc == 0 else 90, f\"Restore {status}: {installed} installed, {failed} failed\")\n            self.after(0, lambda: self._append_log(\n                self.driver_easy_log,\n                f\"{'\u2705' if status=='OK' else '\u26a0'} Restore complete: \"\n                f\"{installed} drivers installed, {failed} failed\\n\"\n                f\"Return code: {rc}\",\n                color))\n            if rc == 0:\n                self.after(0, lambda: messagebox.showinfo(\n                    \"Restore Complete\",\n                    f\"\u2705 Driver restore complete!\\n\\n\"\n                    f\"Installed: {installed}\\n\"\n                    f\"Failed: {failed}\\n\\n\"\n                    \"System restart recommended.\"))\n\n        self._launch_job(\"easy_driver_restore\", run_restore)\n\n    def _easydriver_fill_tree(self, rows):\n        self.driver_easy_tree.delete(*self.driver_easy_tree.get_children())\n        for row in rows:\n            self.driver_easy_tree.insert(\"\", \"end\",\n                values=(row[\"name\"], row[\"status\"], row[\"class\"], row[\"severity\"], row[\"action\"]),\n                tags=(row[\"severity\"],))\n\n    def _easydriver_scan_missing(self):\n        script = \"\"\"\n        $devices = Get-PnpDevice -PresentOnly |\n            Where-Object { $_.Status -ne 'OK' } |\n            Select-Object Status, Class, FriendlyName, InstanceId,\n                          @{N='HardwareID';E={($_.HardwareID -join ';')}} |\n            ConvertTo-Json -Depth 2\n        \"\"\"\n        result = safe_powershell(script, timeout=60)\n        if result.returncode != 0 or not result.output.strip():\n            return self._easydriver_scan_missing_wmi()\n        try:\n            data = json.loads(result.output)\n            if isinstance(data, dict):\n                data = [data]\n        except json.JSONDecodeError:\n            return self._easydriver_scan_missing_wmi()\n        missing = []\n        for device in data:\n            name = device.get(\"FriendlyName\") or device.get(\"InstanceId\") or \"Unknown Device\"\n            status = device.get(\"Status\") or \"Unknown\"\n            missing.append({\n                \"name\": name,\n                \"status\": status,\n                \"class\": device.get(\"Class\") or \"Unknown\",\n                \"severity\": \"critical\" if status.lower() in (\"error\",\"unknown\") else \"warning\",\n                \"action\": \"Install Driver\" if status.lower() == \"unknown\" else \"Update Driver\",\n            })\n        return missing\n\n    def _easydriver_scan_missing_wmi(self):\n        script = \"\"\"\n        Get-WmiObject Win32_PnPEntity |\n        Where-Object { $_.ConfigManagerErrorCode -ne 0 } |\n        Select-Object Name, ConfigManagerErrorCode, DeviceID,\n                      @{N='HardwareID';E={($_.HardwareID -join ';')}} |\n        ConvertTo-Json\n        \"\"\"\n        result = safe_powershell(script, timeout=60)\n        try:\n            data = json.loads(result.output)\n            if isinstance(data, dict):\n                data = [data]\n            return [{\n                \"name\": d.get(\"Name\", \"Unknown\"),\n                \"status\": f\"Error Code {d.get('ConfigManagerErrorCode')}\",\n                \"class\": \"Unknown\",\n                \"severity\": \"warning\",\n                \"action\": \"Update Driver\",\n            } for d in data if d.get(\"Name\")]\n        except Exception:\n            return []\n\n    def _do_easydriver_scan(self):\n        try:\n            self._easydriver_set_progress(20, \"Querying PnP devices...\")\n            self.after(0, lambda: self._append_log(self.driver_easy_log, \"\ud83d\udd0d WMI aur PnP device query chal rahi hai...\", C[\"text_dim\"]))\n            rows = self._easydriver_scan_missing()\n            self._easydriver_set_progress(70, \"Preparing scan results...\")\n            if not rows:\n                self._easydriver_set_progress(100, \"No missing/error drivers detected.\")\n                self.after(0, lambda: self._append_log(self.driver_easy_log, \"\u2705 No missing or error drivers detected.\", C[\"success\"]))\n                self.after(0, lambda: self._easydriver_fill_tree([]))\n                return\n            for device in rows:\n                name = device.get(\"name\", \"Unknown\")\n                self.after(0, lambda n=name: self._append_log(self.driver_easy_log, f\"  \u2022 Checking: {n}\", C[\"text_dim\"]))\n            self.after(0, lambda: self._easydriver_fill_tree(rows))\n            self._easydriver_set_progress(100, f\"{len(rows)} problem device(s) detected.\")\n            self.after(0, lambda: self._append_log(self.driver_easy_log, f\"\u2705 {len(rows)} problem device(s) detected.\", C[\"warning\"]))\n        except Exception as e:\n            self._easydriver_set_progress(0, f\"Driver scan failed: {e}\")\n            self.after(0, lambda: self._append_log(self.driver_easy_log, f\"\u26a0 Driver scan failed: {e}\", C[\"error\"]))\n\n    def _do_easydriver_show_outdated(self):\n        try:\n            self._easydriver_set_progress(20, \"Reading signed driver inventory...\")\n            script = \"\"\"\n            Get-WmiObject Win32_PnPSignedDriver |\n            Select-Object DeviceName,DriverVersion,DriverDate,IsSigned,InfName |\n            ConvertTo-Json -Depth 2\n            \"\"\"\n            result = safe_powershell(script, timeout=120)\n            if result.returncode != 0 or not result.output.strip():\n                raise RuntimeError(\"Driver WMI query failed\")\n            data = json.loads(result.output)\n            if isinstance(data, dict):\n                data = [data]\n            rows = []\n            now = datetime.datetime.now()\n            total = max(1, len(data))\n            for d in data:\n                dt = self._driver_parse_date(d.get(\"DriverDate\"))\n                days = (now - dt).days if dt else None\n                signed = bool(d.get(\"IsSigned\"))\n                if days is None or days &lt; 365:\n                    continue\n                rows.append({\n                    \"name\": d.get(\"DeviceName\") or \"Unknown\",\n                    \"status\": \"Signed\" if signed else \"Unsigned\",\n                    \"class\": d.get(\"InfName\") or \"Driver Package\",\n                    \"severity\": \"critical\" if not signed else \"warning\",\n                    \"action\": f\"{days} days old\",\n                })\n                if len(rows) % 20 == 0:\n                    self._easydriver_set_progress(min(85, 20 + int((len(rows) / total) * 60)), \"Analyzing driver ages...\")\n            if not rows:\n                self._easydriver_set_progress(100, \"No outdated drivers older than 365 days found.\")\n                self.after(0, lambda: self._append_log(self.driver_easy_log, \"\u2705 No outdated drivers older than 365 days found.\", C[\"success\"]))\n                self.after(0, lambda: self._easydriver_fill_tree([]))\n                return\n            self.after(0, lambda: self._easydriver_fill_tree(rows))\n            self._easydriver_set_progress(100, f\"{len(rows)} outdated drivers detected.\")\n            self.after(0, lambda: self._append_log(self.driver_easy_log, f\"\u2705 {len(rows)} outdated drivers detected.\", C[\"warning\"]))\n        except Exception as e:\n            self._easydriver_set_progress(0, f\"Outdated scan failed: {e}\")\n            self.after(0, lambda: self._append_log(self.driver_easy_log, f\"\u26a0 Outdated scan failed: {e}\", C[\"error\"]))\n\n    def _build_partition_manager(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udcbd Partition Manager\",\n                             \"Partition operations with safe merge, shrink, extend, format, clone, and restore support.\")\n        content = self._scrollable_section_body(frame)\n\n        # \u2500\u2500 Fixed top: action buttons \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        top = tk.Frame(content, bg=C[\"bg\"])\n        top.pack(fill=\"x\")\n\n        self._action_card_grid(top, [\n            (\"\ud83d\udd04\", \"Refresh\", \"Partition map refresh karo\", C[\"accent\"], self._partition_refresh_tree),\n            (\"\ud83d\udd17\", \"Merge\", \"Do partitions merge karo\", C[\"accent2\"], self._partition_merge_prompt),\n            (\"\u2194\ufe0f\", \"Split\", \"Partition split karo\", C[\"btn_warn\"], self._partition_split_prompt),\n            (\"\u2b06\ufe0f\", \"Extend\", \"Partition expand karo\", C[\"btn_chip\"], self._partition_extend_prompt),\n            (\"\u2b07\ufe0f\", \"Shrink\", \"Partition shrink karo\", C[\"warning\"], self._partition_shrink_prompt),\n            (\"\ud83c\udf00\", \"Clone\", \"Partition contents clone karo\", C[\"btn\"], self._partition_clone_prompt),\n            (\"\u2699\ufe0f\", \"Format\", \"Partition NTFS format karo\", C[\"error\"], self._partition_format_prompt),\n            (\"\ud83d\udd20\", \"Change Letter\", \"Drive letter change karo\", C[\"btn\"], self._partition_change_letter_prompt),\n            (\"\u26d4\", \"Cancel\", \"Running partition op cancel karo\", C[\"warning\"], self._partition_cancel_operation),\n            (\"\ud83d\udcbe\", \"Backup Table\", \"Partition table ka backup banao\", C[\"accent4\"], self._partition_backup_table),\n        ], cols=3)\n\n        # \u2500\u2500 Progress bars (FIXED \u2014 always visible, below buttons) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        prog_container = tk.Frame(content, bg=C[\"bg\"])\n        prog_container.pack(fill=\"x\", padx=16, pady=(6, 2))\n\n        # Operation progress bar\n        progress_label_frame = tk.Frame(prog_container, bg=C[\"bg\"])\n        progress_label_frame.pack(fill=\"x\")\n        self.partition_op_status = tk.Label(\n            progress_label_frame,\n            text=\"Ready for partition operations.\",\n            font=FONTS[\"small\"],\n            fg=C[\"text_dim\"],\n            bg=C[\"bg\"],\n            anchor=\"w\",\n        )\n        self.partition_op_status.pack(side=\"left\", fill=\"x\", expand=True)\n        self.partition_op_pct_label = tk.Label(\n            progress_label_frame,\n            text=\"0%\",\n            font=FONTS[\"small\"],\n            fg=C[\"text_dim\"],\n            bg=C[\"bg\"],\n            anchor=\"e\",\n            width=6,\n        )\n        self.partition_op_pct_label.pack(side=\"right\")\n        self.partition_op_progress_var = tk.DoubleVar(value=0.0)\n        self.partition_op_progress_bar = ttk.Progressbar(\n            prog_container,\n            variable=self.partition_op_progress_var,\n            maximum=100.0,\n            mode=\"determinate\",\n        )\n        self.partition_op_progress_bar.pack(fill=\"x\", pady=(2, 6))\n\n        # Merge-specific progress bar\n        self.partition_merge_status_label = tk.Label(\n            prog_container,\n            text=\"Ready for partition merge operations.\",\n            font=FONTS[\"small\"],\n            fg=C[\"text_dim\"],\n            bg=C[\"bg\"],\n            anchor=\"w\",\n        )\n        self.partition_merge_status_label.pack(fill=\"x\")\n        self.partition_merge_progress_var = tk.DoubleVar(value=0.0)\n        self.partition_merge_progress = ttk.Progressbar(\n            prog_container,\n            variable=self.partition_merge_progress_var,\n            maximum=100.0,\n            mode=\"determinate\"\n        )\n        self.partition_merge_progress.pack(fill=\"x\", pady=(2, 4))\n\n        # \u2500\u2500 Disk bar canvas (responsive width &amp; redraw on resize) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        self.partition_canvas = tk.Canvas(content, height=self._dpi_px(80), bg=C[\"card\"], bd=0, highlightthickness=0)\n        self.partition_canvas.pack(fill=\"x\", padx=16, pady=(4, 4))\n        self.partition_canvas.bind(\"\", lambda event: self._partition_redraw_disk_bar())\n\n        # \u2500\u2500 Detail label \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        self.partition_detail = tk.Label(content, text=\"Select partition for details.\", font=FONTS[\"small\"],\n                                         fg=C[\"text_dim\"], bg=C[\"bg\"], anchor=\"w\")\n        self.partition_detail.pack(fill=\"x\", padx=16, pady=(0, 2))\n\n        # \u2500\u2500 Tree + log in scrollable body (expands to fill remaining space) \u2500\n        body = tk.Frame(content, bg=C[\"bg\"])\n        body.pack(fill=\"both\", expand=True, padx=16, pady=(0, 4))\n\n        cols = (\"Disk\", \"Partition\", \"Letter\", \"Type\", \"SizeGB\", \"FS\", \"Health\")\n        self.partition_tree = ttk.Treeview(body, columns=cols, show=\"headings\",\n                                           height=14, style=\"Custom.Treeview\",\n                                           selectmode=\"extended\")\n        for col, width in zip(cols, [60, 70, 70, 140, 90, 110, 110]):\n            self.partition_tree.heading(col, text=col)\n            self.partition_tree.column(col, width=width, anchor=\"w\")\n        self.partition_tree.tag_configure(\"warning\", foreground=C[\"warning\"])\n        self.partition_tree.tag_configure(\"error\", foreground=C[\"error\"])\n        self.partition_tree.pack(side=\"left\", fill=\"both\", expand=True)\n\n        vsb = ttk.Scrollbar(body, orient=\"vertical\", command=self.partition_tree.yview)\n        self.partition_tree.configure(yscrollcommand=vsb.set)\n        vsb.pack(side=\"right\", fill=\"y\")\n\n        self.partition_tree.bind(\"&lt;&gt;\", self._partition_on_tree_select)\n\n        self.partition_log = self._scrolled_text(content, height=5)\n        self.partition_data = {}\n        self._partition_refresh_tree()\n        return frame\n\n    def _partition_refresh_tree(self):\n        self._append_log(self.partition_log, \"\ud83d\udd04 Refreshing partition map...\", C[\"accent\"])\n        self._launch_job(\"partition_refresh\", self._partition_refresh_worker)\n\n    def _partition_refresh_worker(self):\n        try:\n            self._partition_update_progress(10, \"Querying disk and partition metadata...\")\n            data = self._partition_fetch_all_disks()\n            if not data or not data.get(\"Partitions\"):\n                self._partition_update_progress(0, \"Partition refresh failed: no data returned.\")\n                self.after(0, lambda: self._append_log(self.partition_log, \"\u274c Partition refresh failed.\", C[\"error\"]))\n                return\n            self.partition_data = data\n            self.after(0, lambda: self._partition_render_tree(data))\n            self._partition_update_progress(100, \"Partition map refreshed.\")\n            self.after(0, lambda: self._append_log(self.partition_log, \"\u2705 Partition map refreshed.\", C[\"success\"]))\n        except Exception as e:\n            self._partition_update_progress(0, f\"Partition refresh failed: {e}\")\n            self.after(0, lambda: self._append_log(self.partition_log, f\"\u274c Partition refresh failed: {e}\", C[\"error\"]))\n        finally:\n            self._partition_reset_progress_delayed(1500)\n\n    def _partition_update_progress(self, pct, status_text):\n        def _update():\n            try:\n                pct_float = max(0.0, min(100.0, float(pct)))\n            except Exception:\n                pct_float = 0.0\n            if hasattr(self, \"partition_op_progress_var\"):\n                self.partition_op_progress_var.set(pct_float)\n            if hasattr(self, \"partition_op_status\"):\n                self.partition_op_status.config(text=str(status_text)[:200])\n            if hasattr(self, \"partition_op_pct_label\"):\n                self.partition_op_pct_label.config(text=f\"{int(pct_float)}%\")\n            if hasattr(self, \"partition_merge_status_label\"):\n                self.partition_merge_status_label.config(text=str(status_text)[:200])\n            if hasattr(self, \"partition_merge_progress_var\"):\n                self.partition_merge_progress_var.set(pct_float)\n        self.after(0, _update)\n\n    def _partition_reset_progress_delayed(self, delay_ms=3000, session_id=None):\n        def _reset():\n            with self._partition_op_lock:\n                if session_id and self._partition_operation_session != session_id:\n                    return\n            self._partition_update_progress(0, \"Ready for partition operations.\")\n        self.after(delay_ms, _reset)\n\n    def _partition_start_operation(self, name):\n        with self._partition_op_lock:\n            if self._partition_operation_active:\n                return False, \"Another partition operation is already running.\"\n            self._partition_operation_active = True\n            self._partition_operation_session = f\"partition-{int(time.time() * 1000)}\"\n            self._partition_cancel_event.clear()\n            self._partition_operation_log = []\n            self._partition_operation_start_time = time.time()\n        self._partition_update_progress(0, f\"{name} initializing...\")\n        self._audit_event(\"partition_operation_start\", {\n            \"session\": self._partition_operation_session,\n            \"name\": name,\n        })\n        return True, self._partition_operation_session\n\n    def _partition_end_operation(self, session_id, success, message, color=C[\"success\"]):\n        with self._partition_op_lock:\n            if self._partition_operation_session != session_id:\n                return\n            elapsed = time.time() - (self._partition_operation_start_time or time.time())\n            self._partition_operation_active = False\n            self._partition_operation_session = None\n            self._partition_operation_start_time = None\n        self._audit_event(\"partition_operation_end\", {\n            \"session\": session_id,\n            \"success\": success,\n            \"message\": message,\n            \"elapsed_seconds\": round(elapsed, 2),\n        })\n        self._partition_update_progress(100 if success else 0, message)\n        self._partition_reset_progress_delayed(3000, session_id)\n\n    def _partition_cancel_operation(self):\n        if not self._partition_operation_active:\n            self._append_log(self.partition_log, \"\u26a0 Koi active partition operation nahi hai.\", C[\"warning\"])\n            return\n        self._partition_cancel_event.set()\n        self._partition_update_progress(0, \"Cancellation requested... Please wait.\")\n        self._append_log(self.partition_log, \"\u23f9 Partition operation cancellation requested.\", C[\"warning\"])\n        self._audit_event(\"partition_operation_cancel_requested\", {\"session\": self._partition_operation_session})\n\n    def _partition_operation_is_cancelled(self):\n        return self._partition_cancel_event.is_set()\n\n    def _partition_log_diagnostic(self, level, message, extra=None):\n        entry = {\n            \"ts\": datetime.datetime.now().isoformat(timespec=\"seconds\"),\n            \"level\": level,\n            \"message\": message,\n        }\n        if extra:\n            entry.update(extra)\n        self._partition_operation_log.append(entry)\n        self._audit_event(\"partition_operation_log\", entry)\n        color = C[\"success\"] if level == \"OK\" else C[\"warning\"] if level in (\"WARN\", \"INFO\") else C[\"error\"]\n        self._append_log(self.partition_log, message, color)\n\n    def _partition_run_powershell_cancelable(self, script, timeout=60):\n        Result = collections.namedtuple(\"Result\", [\"returncode\", \"output\"])\n        proc = subprocess.Popen(\n            [\"powershell\", \"-NoProfile\", \"-NonInteractive\", \"-Command\", script],\n            stdout=subprocess.PIPE,\n            stderr=subprocess.PIPE,\n            text=True,\n            creationflags=subprocess.CREATE_NO_WINDOW,\n        )\n        deadline = time.time() + timeout\n        while proc.poll() is None and time.time() &lt; deadline:\n            if self._partition_operation_is_cancelled():\n                proc.terminate()\n                try:\n                    proc.wait(10)\n                except Exception:\n                    proc.kill()\n                return Result(1, \"Operation cancelled\")\n            time.sleep(0.5)\n        if proc.poll() is None:\n            proc.kill()\n            return Result(1, \"Timeout waiting for PowerShell\")\n        out, err = proc.communicate()\n        return Result(proc.returncode, (out or \"\") + (err or \"\"))\n\n    def _partition_run_cmd_cancelable(self, cmd, timeout=3600):\n        start = time.time()\n        proc = subprocess.Popen(\n            cmd,\n            stdout=subprocess.PIPE,\n            stderr=subprocess.PIPE,\n            text=True,\n            creationflags=subprocess.CREATE_NO_WINDOW,\n        )\n        while proc.poll() is None:\n            if self._partition_operation_is_cancelled():\n                proc.terminate()\n                try:\n                    proc.wait(10)\n                except Exception:\n                    proc.kill()\n                return SafeRunResult(\"Operation cancelled\", 1, args=list(cmd), elapsed_ms=int((time.time() - start) * 1000))\n            if time.time() - start &gt; timeout:\n                proc.kill()\n                return SafeRunResult(\"Timeout waiting for command\", -1, args=list(cmd), elapsed_ms=int((time.time() - start) * 1000), timed_out=True)\n            time.sleep(0.5)\n        out, err = proc.communicate()\n        elapsed = int((time.time() - start) * 1000)\n        return SafeRunResult((out or \"\") + (err or \"\"), proc.returncode, args=list(cmd), elapsed_ms=elapsed)\n\n    def _partition_query_disk_info(self, disk_number):\n        script = f\"$d = Get-Disk -Number {disk_number} -ErrorAction Stop; $dyn = $d | Select-Object -ExpandProperty IsDynamic -ErrorAction SilentlyContinue; [pscustomobject]@{{Number=$d.Number;PartitionStyle=$d.PartitionStyle;IsSystem=$d.IsSystem;IsBoot=$d.IsBoot;IsOffline=$d.IsOffline;IsReadOnly=$d.IsReadOnly;IsDynamic=$dyn}} | ConvertTo-Json -Depth 2\"\n        result = safe_powershell(script, timeout=15)\n        if result.returncode != 0 or not result.output.strip():\n            return {}\n        try:\n            return json.loads(result.output)\n        except Exception:\n            return {}\n\n    def _partition_query_partition_info(self, part):\n        if not part or 'DiskNumber' not in part or 'PartitionNumber' not in part:\n            return {}\n        script = f\"Get-Partition -DiskNumber {part['DiskNumber']} -PartitionNumber {part['PartitionNumber']} | Select-Object DriveLetter,Type,IsBoot,IsOffline,AccessPaths,Size,SizeRemaining,IsHidden | ConvertTo-Json -Depth 2\"\n        result = safe_powershell(script, timeout=15)\n        if result.returncode != 0 or not result.output.strip():\n            return {}\n        try:\n            info = json.loads(result.output)\n            if isinstance(info, dict):\n                return info\n            return info[0] if isinstance(info, list) and info else info\n        except Exception:\n            return {}\n\n    def _partition_query_supported_size(self, disk_number, partition_number):\n        script = f\"Get-PartitionSupportedSize -DiskNumber {disk_number} -PartitionNumber {partition_number} | ConvertTo-Json -Depth 2\"\n        result = safe_powershell(script, timeout=15)\n        if result.returncode != 0 or not result.output.strip():\n            return {}\n        try:\n            return json.loads(result.output)\n        except Exception:\n            return {}\n\n    def _partition_query_volume_info(self, drive_letter):\n        if not drive_letter:\n            return {}\n        script = f\"Get-Volume -DriveLetter {drive_letter} | Select-Object DriveLetter,FileSystem,HealthStatus,Size,SizeRemaining,DriveType | ConvertTo-Json -Depth 2\"\n        result = safe_powershell(script, timeout=15)\n        if result.returncode != 0 or not result.output.strip():\n            return {}\n        try:\n            info = json.loads(result.output)\n            if isinstance(info, dict):\n                return info\n            return info[0] if isinstance(info, list) and info else info\n        except Exception:\n            return {}\n\n    def _partition_detect_bitlocker(self, letter):\n        if not letter:\n            return False, \"\"\n        script = f\"try {{ Get-BitLockerVolume -MountPoint '{letter}:' | Select-Object ProtectionStatus,VolumeStatus | ConvertTo-Json -Depth 2 }} catch {{ Write-Output '' }}\"\n        result = safe_powershell(script, timeout=15)\n        if result.returncode != 0 or not result.output.strip():\n            return False, \"\"\n        try:\n            info = json.loads(result.output)\n            protection = info.get('ProtectionStatus') if isinstance(info, dict) else None\n            status = info.get('VolumeStatus') if isinstance(info, dict) else None\n            enabled = protection not in (0, None) or (status and status.lower() != 'fullydecrypted')\n            return bool(enabled), f\"BitLocker status={status}, protection={protection}\"\n        except Exception:\n            return False, \"\"\n\n    def _partition_folder_size(self, path):\n        total = 0\n        try:\n            for root, _, files in os.walk(path):\n                for f in files:\n                    try:\n                        total += os.path.getsize(os.path.join(root, f))\n                    except Exception:\n                        pass\n        except Exception:\n            pass\n        return total\n\n    def _partition_confirm_action(self, title, message, warnings=None):\n        body = message\n        if warnings:\n            body += \"\\n\\nWarnings:\\n\" + \"\\n\".join([f\"- {w}\" for w in warnings])\n        body += \"\\n\\nBackup recommend kiya jata hai. Continue?\"\n        return messagebox.askyesno(title, body)\n\n    def _partition_preflight_checks(self, action, part=None, dest_part=None, new_size=None):\n        result = {\"ok\": True, \"errors\": [], \"warnings\": [], \"details\": {}}\n        if not is_admin():\n            result[\"ok\"] = False\n            result[\"errors\"].append(\"Administrator privileges required for partition operations.\")\n            return result\n        if action in (\"extend\", \"shrink\", \"split\", \"format\", \"change_letter\", \"merge\", \"clone\"):\n            if part is None:\n                result[\"ok\"] = False\n                result[\"errors\"].append(\"Partition metadata missing.\")\n                return result\n            if part.get(\"DriveLetter\", \"\").upper() == \"C\":\n                result[\"errors\"].append(\"System volume C: pe direct operation unsafe hai.\")\n            if part.get(\"Type\") in {\"System\", \"Reserved\", \"Recovery\", \"EFI\", \"Unknown\"}:\n                result[\"warnings\"].append(\"Selected partition type is special or protected.\")\n            disk_info = self._partition_query_disk_info(part[\"DiskNumber\"])\n            if disk_info.get(\"IsOffline\"):\n                result[\"errors\"].append(\"Target disk is offline.\")\n            if disk_info.get(\"IsReadOnly\"):\n                result[\"errors\"].append(\"Target disk is read-only.\")\n            if disk_info.get(\"IsDynamic\"):\n                result[\"warnings\"].append(\"Dynamic disk detected \u2014 partition operations may not be fully supported.\")\n            if disk_info.get(\"PartitionStyle\") not in (\"MBR\", \"GPT\"):\n                result[\"warnings\"].append(\"Unknown or unsupported partition style.\")\n            if action in (\"extend\", \"shrink\", \"split\") and new_size is not None:\n                supported = self._partition_query_supported_size(part[\"DiskNumber\"], part[\"PartitionNumber\"])\n                if supported:\n                    min_size = supported.get(\"SizeMin\") or 0\n                    max_size = supported.get(\"SizeMax\") or 0\n                    requested = int(new_size * 1024 ** 3)\n                    if action == \"shrink\" and requested &lt; min_size:\n                        result[\"errors\"].append(\"Requested shrink size below supported minimum.\")\n                    if action == \"extend\" and requested &gt; max_size:\n                        result[\"errors\"].append(\"Requested extend size exceeds supported maximum.\")\n                    if action == \"split\" and requested &gt;= (part.get(\"Size\") or 0):\n                        result[\"errors\"].append(\"Split size must be smaller than current partition size.\")\n        if action == \"clone\":\n            src_letter = part.get(\"DriveLetter\")\n            dst_letter = dest_part.get(\"DriveLetter\") if dest_part else None\n            if not src_letter or not dst_letter:\n                result[\"errors\"].append(\"Clone ke liye dono source aur destination drive letters chahiye.\")\n            else:\n                source_bytes = self._partition_folder_size(f\"{src_letter}:\\\\\")\n                try:\n                    usage = shutil.disk_usage(f\"{dst_letter}:\\\\\")\n                    if usage.free &lt; source_bytes:\n                        result[\"errors\"].append(\"Destination volume par kaafi free space nahi hai.\")\n                except Exception:\n                    result[\"warnings\"].append(\"Destination free space check failed; manual verify karo.\")\n                if source_bytes == 0:\n                    result[\"warnings\"].append(\"Source folder size calculation zero ya failed. Progress estimate may be inaccurate.\")\n        if action == \"format\":\n            if part.get(\"DriveLetter\", \"\").upper() == \"C\":\n                result[\"errors\"].append(\"System volume C: ko format nahi kiya ja sakta.\")\n            bitlocker_enabled, bitlocker_info = self._partition_detect_bitlocker(part.get(\"DriveLetter\"))\n            if bitlocker_enabled:\n                result[\"errors\"].append(f\"BitLocker enabled on {part.get('DriveLetter', '')}: \u2014 disable before formatting. {bitlocker_info}\")\n        if action == \"change_letter\":\n            new_letter = dest_part if isinstance(dest_part, str) else None\n            if new_letter and new_letter.upper() == \"C\":\n                result[\"errors\"].append(\"Drive letter C: reserved hai \u2014 choose another letter.\")\n        if action == \"merge\":\n            if dest_part and part and part.get(\"DiskNumber\") != dest_part.get(\"DiskNumber\"):\n                result[\"errors\"].append(\"Merge ke liye same disk par partitions hone chahiye.\")\n            if dest_part and abs(int(part.get(\"PartitionNumber\", 0)) - int(dest_part.get(\"PartitionNumber\", 0))) != 1:\n                result[\"errors\"].append(\"Merge ke liye partitions adjacent hone chahiye.\")\n        if result[\"errors\"]:\n            result[\"ok\"] = False\n        return result\n\n    def _partition_verify_post_operation(self, action, part=None, expected=None):\n        if not part or not part.get(\"DiskNumber\"):\n            return False, \"Post-operation verification failed: partition metadata missing.\"\n        if action in (\"extend\", \"shrink\", \"split\"):\n            info = self._partition_query_partition_info(part)\n            if not info:\n                return False, \"Unable to verify partition after resize/split.\"\n            if expected is not None and isinstance(expected, (int, float)):\n                actual_gb = round((info.get(\"Size\") or 0) / (1024 ** 3), 2)\n                if abs(actual_gb - expected) &gt; 0.5:\n                    return False, f\"Expected size {expected} GB, actual {actual_gb} GB.\"\n        if action == \"change_letter\":\n            info = self._partition_query_partition_info(part)\n            if info and str(info.get(\"DriveLetter\", \"\")).upper() != str(expected).upper():\n                return False, f\"Drive letter change verification failed - expected {expected}:.\"\n        if action == \"format\":\n            vol = self._partition_query_volume_info(part.get(\"DriveLetter\"))\n            if not vol or vol.get(\"FileSystem\") != \"NTFS\":\n                return False, f\"Format verification failed \u2014 expected NTFS on {part.get('DriveLetter','')}:\"\n            if vol.get(\"HealthStatus\", \"\").lower() not in (\"healthy\", \"healthy\"):\n                return False, f\"Volume health warning: {vol.get('HealthStatus')}\"\n        return True, \"Verification passed\"\n\n    def _partition_render_tree(self, data):\n        self.partition_tree.delete(*self.partition_tree.get_children())\n        partitions = data.get(\"Partitions\") or []\n        volumes = data.get(\"Volumes\") or []\n        if isinstance(partitions, dict):\n            partitions = [partitions]\n        if isinstance(volumes, dict):\n            volumes = [volumes]\n\n        for part in partitions:\n            disk = part.get(\"DiskNumber\")\n            pno = part.get(\"PartitionNumber\")\n            letter = part.get(\"DriveLetter\") or \"\"\n            ptype = part.get(\"Type\") or \"\"\n            sizegb = part.get(\"SizeGB\") or round((part.get(\"Size\") or 0) / (1024**3), 2)\n            fs = \"\"\n            health = \"\"\n            if letter:\n                vol = next((v for v in volumes if v.get(\"DriveLetter\") == letter), None)\n                if vol:\n                    fs = vol.get(\"FileSystem\") or \"\"\n                    health = vol.get(\"HealthStatus\") or \"\"\n            self.partition_tree.insert(\"\", \"end\", iid=f\"{disk}-{pno}\", values=(disk, pno, letter, ptype, sizegb, fs, health))\n\n        if data.get(\"Disks\"):\n            disk = data.get(\"Disks\")[0]\n            self._partition_selected_disk = str(disk.get(\"Number\"))\n            parts = [p for p in partitions if str(p.get(\"DiskNumber\")) == str(disk.get(\"Number\"))]\n            self._partition_draw_disk_bar(self.partition_canvas, disk, parts)\n\n    def _partition_redraw_disk_bar(self):\n        if not getattr(self, \"partition_data\", None):\n            return\n        selected_disk = getattr(self, \"_partition_selected_disk\", None)\n        disks = self.partition_data.get(\"Disks\") or []\n        disk = None\n        if selected_disk is not None:\n            disk = next((d for d in disks if str(d.get(\"Number\")) == str(selected_disk)), None)\n        if not disk and disks:\n            disk = disks[0]\n            self._partition_selected_disk = str(disk.get(\"Number\"))\n        if not disk:\n            return\n        parts = [p for p in (self.partition_data.get(\"Partitions\") or []) if str(p.get(\"DiskNumber\")) == str(disk.get(\"Number\"))]\n        self._partition_draw_disk_bar(self.partition_canvas, disk, parts)\n\n    def _partition_on_tree_select(self, event=None):\n        sel = self.partition_tree.selection()\n        if not sel:\n            return\n        values = self.partition_tree.item(sel[0])[\"values\"]\n        if len(values) &lt; 2:\n            return\n        disk, pno = values[0], values[1]\n        self._partition_selected_disk = str(disk)\n        part = self._partition_find_data(disk, pno)\n        if not part:\n            return\n        details = [\n            f\"Disk: {disk}\",\n            f\"Partition: {pno}\",\n            f\"Type: {part.get('Type','Unknown')}\",\n            f\"Letter: {part.get('DriveLetter','')}\",\n            f\"Size: {part.get('SizeGB') or round((part.get('Size') or 0)/(1024**3),2)} GB\",\n        ]\n        self.partition_detail.config(text=\" | \".join(details))\n        disk_data = next((d for d in (self.partition_data.get('Disks') or []) if str(d.get('Number')) == str(disk)), None)\n        if disk_data:\n            parts = [p for p in (self.partition_data.get('Partitions') or []) if str(p.get('DiskNumber')) == str(disk)]\n            self._partition_draw_disk_bar(self.partition_canvas, disk_data, parts)\n\n    def _partition_find_data(self, disk, partition_number):\n        for part in (self.partition_data.get(\"Partitions\") or []):\n            if str(part.get(\"DiskNumber\")) == str(disk) and str(part.get(\"PartitionNumber\")) == str(partition_number):\n                return part\n        return None\n\n    def _partition_fetch_all_disks(self):\n        script = \"\"\"\n        $disks = Get-Disk | Select-Object Number,Size,FriendlyName,PartitionStyle,OperationalStatus,@{N='SizeGB';E={[math]::Round($_.Size/1GB,2)}}\n        $parts = Get-Partition | Select-Object DiskNumber,PartitionNumber,DriveLetter,Size,Type,IsActive,IsHidden,@{N='SizeGB';E={[math]::Round($_.Size/1GB,2)}},@{N='AccessPaths';E={$_.AccessPaths -join ';'}}\n        $vols  = Get-Volume | Select-Object DriveLetter,FileSystem,SizeRemaining,Size,HealthStatus,@{N='FreeGB';E={[math]::Round($_.SizeRemaining/1GB,2)}},@{N='TotalGB';E={[math]::Round($_.Size/1GB,2)}}\n        @{Disks=$disks; Partitions=$parts; Volumes=$vols} | ConvertTo-Json -Depth 4\n        \"\"\"\n        result = safe_powershell(script, timeout=30)\n        if result.returncode != 0 or not result.output.strip():\n            return self._partition_fetch_via_wmic()\n        try:\n            return json.loads(result.output)\n        except json.JSONDecodeError:\n            return self._partition_fetch_via_wmic()\n\n    def _partition_fetch_via_wmic(self):\n        script = \"\"\"\n        Get-WmiObject Win32_DiskPartition |\n        Select-Object DiskIndex,Index,Name,Size,Type,Bootable |\n        ConvertTo-Json\n        \"\"\"\n        result = safe_powershell(script, timeout=20)\n        try:\n            data = json.loads(result.output)\n            if isinstance(data, dict):\n                data = [data]\n            return {\"Disks\": [], \"Partitions\": data, \"Volumes\": []}\n        except Exception:\n            return {\"Disks\": [], \"Partitions\": [], \"Volumes\": []}\n\n    def _partition_draw_disk_bar(self, canvas, disk_data, partitions):\n        canvas.delete(\"all\")\n        W = canvas.winfo_width() or 900\n        H = max(self._dpi_px(60), canvas.winfo_height() or self._dpi_px(60))\n        colors = {\n            \"System\": \"#FF6B6B\",\n            \"Primary\": \"#4DABF7\",\n            \"Recovery\": \"#FFD43B\",\n            \"Unknown\": \"#868E96\",\n            \"Unallocated\": \"#2D3436\",\n        }\n        total_bytes = sum(p.get(\"Size\", 0) for p in partitions)\n        if total_bytes == 0:\n            return\n        x = 0\n        for p in partitions:\n            w = int((p.get(\"Size\", 0) / total_bytes) * W)\n            if w &lt; 2:\n                w = 2\n            ptype = p.get(\"Type\", \"Primary\")\n            color = colors.get(ptype, \"#4DABF7\")\n            letter = p.get(\"DriveLetter\") or \"?\"\n            size_gb = round((p.get(\"Size\") or 0) / (1024**3), 1)\n            canvas.create_rectangle(x, 5, x + w - 2, H - 5,\n                                    fill=color, outline=\"#1A1A2A\", width=1)\n            if w &gt; 40:\n                canvas.create_text(x + w//2, H//2,\n                                   text=f\"{letter}:\\n{size_gb}GB\",\n                                   font=(\"Segoe UI\", 8, \"bold\"),\n                                   fill=\"white\", anchor=\"center\")\n            x += w\n        disk_total = disk_data.get(\"Size\", 0)\n        unalloc = disk_total - total_bytes\n        if unalloc &gt; 100 * 1024 * 1024:\n            w = int((unalloc / disk_total) * W)\n            canvas.create_rectangle(x, 5, x + w - 2, H - 5,\n                                    fill=\"#2D3436\", outline=\"#555\", width=1,\n                                    dash=(4, 2))\n            if w &gt; 60:\n                canvas.create_text(x + w//2, H//2,\n                                   text=f\"Free\\n{round(unalloc/(1024**3),1)}GB\",\n                                   font=(\"Segoe UI\", 8), fill=\"#AAA\", anchor=\"center\")\n\n    def _partition_merge_prompt(self):\n        sel = self.partition_tree.selection()\n        if len(sel) != 2:\n            messagebox.showinfo(\"Select Two Partitions\", \"Pehle 2 adjacent partitions select karo \u2014 source aur destination.\")\n            return\n        src_data = self._partition_find_data(*self.partition_tree.item(sel[0])[\"values\"][:2])\n        dst_data = self._partition_find_data(*self.partition_tree.item(sel[1])[\"values\"][:2])\n        if not src_data or not dst_data:\n            return\n        if src_data.get(\"SizeGB\", 0) &gt; dst_data.get(\"SizeGB\", 0):\n            source, dest = dst_data, src_data\n        else:\n            source, dest = src_data, dst_data\n        if not messagebox.askyesno(\"Merge Partitions\",\n                                  f\"Source: {source.get('DriveLetter','')} ({source.get('SizeGB')} GB)\\n\"\n                                  f\"Destination: {dest.get('DriveLetter','')} ({dest.get('SizeGB')} GB)\\n\\n\"\n                                  \"Data source ko destination par copy karke merge kiya jayega. Continue?\" ):\n            return\n        self._launch_job(\"partition_merge\", self._partition_merge_worker, source, dest)\n\n    def _partition_merge_worker(self, source, dest):\n        started, session_id = self._partition_start_operation(\"Merge Partitions\")\n        if not started:\n            self._append_log(self.partition_log, \"\u26a0 Another partition operation is already running.\", C[\"warning\"])\n            return\n        success = False\n        message = \"Partition merge failed\"\n        try:\n            self._partition_update_progress(0, \"Partition merge started...\")\n            success, message = self._partition_merge(source, dest)\n            color = C[\"success\"] if success else C[\"error\"]\n            self.after(0, lambda: self._append_log(self.partition_log, message, color))\n            if success:\n                self._partition_update_progress(100, \"Partition merge completed.\")\n                self.after(0, self._partition_refresh_tree)\n            else:\n                self._partition_update_progress(0, \"Partition merge failed.\")\n        except Exception as e:\n            message = f\"Partition merge failed: {e}\"\n            self._partition_log_diagnostic(\"ERROR\", message)\n            self._partition_update_progress(0, message)\n        finally:\n            self._partition_end_operation(session_id, success, message, C[\"success\"] if success else C[\"error\"])\n\n    def _partition_merge(self, source_part, dest_part):\n        journal = []\n        def update_merge_progress(percent, text=None):\n            self._partition_update_progress(percent, text or \"Merging...\")\n            if text is not None and hasattr(self, \"partition_merge_status_label\"):\n                self.after(0, lambda: self.partition_merge_status_label.config(text=text))\n            if hasattr(self, \"partition_merge_progress_var\"):\n                self.after(0, lambda: self.partition_merge_progress_var.set(max(0.0, min(100.0, float(percent)))))\n\n        def jlog(msg, level=\"INFO\", pct=None):\n            journal.append({\"ts\": datetime.datetime.now().isoformat(), \"level\": level, \"msg\": msg})\n            self._append_log(self.partition_log, msg, C[\"success\"] if level == \"OK\" else C[\"warning\"] if level == \"WARN\" else C[\"error\"])\n            if pct is not None:\n                update_merge_progress(pct, msg)\n\n        if not is_admin():\n            jlog(\"Admin rights nahi hain. Run as Administrator karo.\", \"ERROR\")\n            return False, \"Admin required\"\n\n        if source_part.get(\"DiskNumber\") != dest_part.get(\"DiskNumber\"):\n            jlog(\"Partitions alag disk par hain \u2014 merge supported nahi. Use same disk.\", \"ERROR\")\n            return False, \"Different disks\"\n\n        if abs(int(source_part.get(\"PartitionNumber\", 0)) - int(dest_part.get(\"PartitionNumber\", 0))) != 1:\n            jlog(\"Partitions adjacent nahi hain. Merge ke liye adjacent partitions chahiye.\", \"ERROR\")\n            return False, \"Partitions not adjacent\"\n\n        protected_types = {\"System\", \"Reserved\", \"Recovery\", \"EFI\", \"Unknown\"}\n        if source_part.get(\"Type\") in protected_types or dest_part.get(\"Type\") in protected_types:\n            jlog(\"System/Recovery partition pe merge block hai.\", \"ERROR\")\n            return False, \"Protected partition\"\n\n        jlog(\"SMART check chal raha hai...\", \"INFO\")\n        smart_script = \"\"\"\n        Get-WmiObject -Namespace root/wmi -Class MSStorageDriver_FailurePredictStatus |\n            Select-Object PredictFailure,Reason | ConvertTo-Json\n        \"\"\"\n        smart_result = safe_powershell(smart_script, timeout=15)\n        try:\n            smart_data = json.loads(smart_result.output)\n            if isinstance(smart_data, dict):\n                smart_data = [smart_data]\n            for s in smart_data:\n                if s.get(\"PredictFailure\"):\n                    jlog(\"SMART: Disk failure predicted! Merge BLOCKED. Pehle data backup karo.\", \"ERROR\")\n                    return False, \"SMART failure predicted\"\n        except Exception:\n            jlog(\"SMART check available nahi \u2014 proceeding with caution.\", \"WARN\")\n\n        src_letter = source_part.get(\"DriveLetter\") or self._partition_assign_temp_letter(source_part)\n        dst_letter = dest_part.get(\"DriveLetter\") or self._partition_assign_temp_letter(dest_part)\n        backup_dir = os.path.join(os.environ.get(\"APPDATA\", \"\"), \"GodawariOptimizer\", \"partition_backups\")\n        os.makedirs(backup_dir, exist_ok=True)\n        if src_letter and dst_letter:\n            self._record_rollback_point(\n                \"partition_merge\",\n                details={\n                    \"source_letter\": src_letter,\n                    \"dest_letter\": dst_letter,\n                    \"src_disk\": source_part.get(\"DiskNumber\"),\n                    \"src_partition\": source_part.get(\"PartitionNumber\"),\n                    \"dest_disk\": dest_part.get(\"DiskNumber\"),\n                    \"dest_partition\": dest_part.get(\"PartitionNumber\"),\n                    \"backup_dir\": backup_dir,\n                },\n                snapshot_path=backup_dir)\n        if not src_letter or not dst_letter:\n            jlog(\"Drive letter missing \u2014 merge ke liye drive letters chahiye.\", \"ERROR\")\n            return False, \"Drive letter required\"\n\n        jlog(f\"Data copy shuru kar raha hoon: {src_letter}: \u2192 {dst_letter}: ...\", \"INFO\")\n        ts = datetime.datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n        copy_log = os.path.join(backup_dir, f\"robocopy_{ts}.log\")\n        robocopy_cmd = [\n            \"robocopy\",\n            f\"{src_letter}:\\\\\",\n            f\"{dst_letter}:\\\\GodawariMerge_{ts}\",\n            \"/MIR\", \"/COPYALL\", \"/R:3\", \"/W:5\",\n            \"/NFL\", f\"/LOG:{copy_log}\", \"/TEE\"\n        ]\n        copy_result = safe_run(robocopy_cmd, timeout=7200)\n        if copy_result.returncode &gt;= 8:\n            jlog(f\"Data copy FAILED (rc={copy_result.returncode}). Merge aborted.\", \"ERROR\", pct=20)\n            return False, f\"Robocopy failed: rc={copy_result.returncode}\"\n\n        src_count = self._partition_count_files(f\"{src_letter}:\\\\\")\n        dst_count = self._partition_count_files(f\"{dst_letter}:\\\\GodawariMerge_{ts}\")\n        if src_count &gt; 0 and dst_count &lt; int(src_count * 0.95):\n            jlog(f\"Verification FAILED: src={src_count} files, dst={dst_count} files\", \"ERROR\", pct=40)\n            return False, \"File count mismatch after copy\"\n        jlog(f\"Verification OK: {src_count} \u2192 {dst_count} files\", \"OK\", pct=45)\n\n        diskpart_script = f\"\"\"select disk {source_part['DiskNumber']}\\nselect partition {source_part['PartitionNumber']}\\ndelete partition override\\n\"\"\"\n        diskpart_file = os.path.join(backup_dir, f\"diskpart_delete_{ts}.txt\")\n        with open(diskpart_file, \"w\", encoding=\"utf-8\") as f:\n            f.write(diskpart_script)\n        delete_result = safe_run([\"diskpart\", \"/s\", diskpart_file], timeout=60)\n        if delete_result.returncode != 0:\n            jlog(f\"Partition delete failed: {delete_result.output[:200]}\", \"ERROR\", pct=55)\n            return False, \"Delete failed\"\n        jlog(\"Source partition deleted.\", \"OK\", pct=60)\n\n        extend_script = f\"\"\"select disk {dest_part['DiskNumber']}\\nselect partition {dest_part['PartitionNumber']}\\nextend\\n\"\"\"\n        extend_file = os.path.join(backup_dir, f\"diskpart_extend_{ts}.txt\")\n        with open(extend_file, \"w\", encoding=\"utf-8\") as f:\n            f.write(extend_script)\n        extend_result = safe_run([\"diskpart\", \"/s\", extend_file], timeout=60)\n        if extend_result.returncode != 0:\n            ps_extend = f\"\"\"\n            $maxSize = (Get-PartitionSupportedSize -DiskNumber {dest_part['DiskNumber']} -PartitionNumber {dest_part['PartitionNumber']}).SizeMax\n            Resize-Partition -DiskNumber {dest_part['DiskNumber']} -PartitionNumber {dest_part['PartitionNumber']} -Size $maxSize\n            \"\"\"\n            ps_result = safe_powershell(ps_extend, timeout=60)\n            if ps_result.returncode != 0:\n                jlog(\"Extend FAILED \u2014 manual extend required via Disk Management\", \"ERROR\", pct=70)\n                return False, \"Extend failed\"\n        jlog(\"Partition extended!\", \"OK\", pct=75)\n\n        verify_script = f\"\"\"\n        Get-Partition -DiskNumber {dest_part['DiskNumber']} -PartitionNumber {dest_part['PartitionNumber']} |\n            Select-Object @{{N='SizeGB';E={{[math]::Round($_.Size/1GB,2)}}}} |\n            ConvertTo-Json\n        \"\"\"\n        verify_result = safe_powershell(verify_script, timeout=15)\n        try:\n            new_size = json.loads(verify_result.output).get(\"SizeGB\", 0)\n            expected = round((source_part.get(\"SizeGB\", 0) + dest_part.get(\"SizeGB\", 0)) * 0.98, 1)\n            if new_size &gt;= expected:\n                jlog(f\"VERIFY OK: New size = {new_size} GB\", \"OK\", pct=90)\n            else:\n                jlog(f\"Size verify: {new_size} GB (expected ~{expected} GB) \u2014 check manually\", \"WARN\", pct=85)\n        except Exception:\n            jlog(\"Size verify parse failed \u2014 visually confirm\", \"WARN\", pct=85)\n\n        journal_file = os.path.join(backup_dir, f\"partition_merge_journal_{ts}.json\")\n        with open(journal_file, \"w\", encoding=\"utf-8\") as f:\n            json.dump(journal, f, indent=2, ensure_ascii=False)\n        jlog(f\"Merge complete! Journal saved: {journal_file}\", \"OK\")\n        return True, \"Merge successful\"\n\n    def _partition_count_files(self, path):\n        count = 0\n        try:\n            for root, _, files in os.walk(path):\n                count += len(files)\n        except Exception:\n            pass\n        return count\n\n    def _partition_assign_temp_letter(self, part):\n        if part.get(\"DriveLetter\"):\n            return part[\"DriveLetter\"]\n        existing = [v for v in \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"]\n        script = 'Get-Volume | Select-Object -ExpandProperty DriveLetter | ConvertTo-Json'\n        result = safe_powershell(script, timeout=15)\n        used = set()\n        try:\n            letters = json.loads(result.output)\n            if isinstance(letters, list):\n                used.update([str(x) for x in letters if x])\n            elif isinstance(letters, str):\n                used.add(letters)\n        except Exception:\n            pass\n        for letter in \"RSTUVWXYZ\":\n            if letter in used:\n                continue\n            assign_script = f\"$p = Get-Partition -DiskNumber {part['DiskNumber']} -PartitionNumber {part['PartitionNumber']}; Add-PartitionAccessPath -InputObject $p -AssignDriveLetter -DriveLetter {letter} -ErrorAction SilentlyContinue\"\n            assign_res = safe_powershell(assign_script, timeout=20)\n            if assign_res.returncode == 0:\n                return letter\n        return None\n\n    def _partition_extend_prompt(self):\n        sel = self.partition_tree.selection()\n        if len(sel) != 1:\n            messagebox.showinfo(\"Select Partition\", \"Pehle ek partition select karo.\")\n            return\n        values = self.partition_tree.item(sel[0])[\"values\"]\n        part = self._partition_find_data(*values[:2])\n        if not part:\n            return\n        import tkinter.simpledialog as simpledialog\n        current = part.get(\"SizeGB\") or round((part.get(\"Size\") or 0)/(1024**3),2)\n        new_size = simpledialog.askfloat(\"Extend Partition\", f\"Naya size (GB) enter karo (current {current}):\", initialvalue=current + 10, minvalue=current + 1)\n        if not new_size:\n            return\n        if not messagebox.askyesno(\"Extend Partition\", f\"Partition {part.get('DriveLetter','')} ko {new_size} GB tak extend karna hai?\\nContinue?\"):\n            return\n        preflight = self._partition_preflight_checks(\"extend\", part, new_size=new_size)\n        if not preflight[\"ok\"]:\n            messagebox.showerror(\"Preflight Failed\", \"\\n\".join(preflight[\"errors\"]))\n            return\n        if preflight[\"warnings\"] and not self._partition_confirm_action(\"Extend Partition\", f\"Extending partition {part.get('DriveLetter','')} to {new_size} GB.\", preflight[\"warnings\"]):\n            return\n        dry_run = messagebox.askyesno(\"Dry-Run Recommended\", \"Dry-run preview recommended for partition extend. Yes = preview only, No = run actual operation now.\")\n        self._launch_job(\"partition_extend\", self._partition_extend_worker, part, new_size, dry_run)\n\n    def _partition_extend_worker(self, part, new_size, dry_run=False):\n        started, session_id = self._partition_start_operation(\"Extend Partition\")\n        if not started:\n            self._append_log(self.partition_log, \"\u26a0 Another partition operation is already running.\", C[\"warning\"])\n            return\n        self._partition_log_diagnostic(\"INFO\", f\"Starting partition extend: {part.get('DriveLetter','')} to {new_size} GB\", {\"dry_run\": dry_run})\n        command = f\"Resize-Partition -DiskNumber {part['DiskNumber']} -PartitionNumber {part['PartitionNumber']} -Size ({new_size}GB)\"\n        if dry_run:\n            command += \" -WhatIf\"\n        self._partition_update_progress(15, \"Preparing extend command...\")\n        self._partition_log_diagnostic(\"INFO\", \"Executing Resize-Partition (or dry-run).\")\n        self._partition_update_progress(35, \"Executing PowerShell command...\")\n        result = self._partition_run_powershell_cancelable(command, timeout=90)\n        if self._partition_operation_is_cancelled():\n            self._partition_log_diagnostic(\"WARN\", \"Extend operation cancelled.\")\n            self._partition_end_operation(session_id, False, \"Extend cancelled\", C[\"warning\"])\n            return\n        self._partition_update_progress(70, \"Verifying result...\")\n        if result.returncode == 0:\n            if dry_run:\n                self._partition_log_diagnostic(\"OK\", \"Dry-run complete: extend command validated.\")\n                self._partition_end_operation(session_id, True, \"Dry-run complete\", C[\"success\"])\n                return\n            verify_ok, verify_msg = self._partition_verify_post_operation(\"extend\", part, expected=new_size)\n            if verify_ok:\n                self._partition_log_diagnostic(\"OK\", f\"Extended to {new_size} GB successfully.\")\n                self.after(0, self._partition_refresh_tree)\n                self._partition_end_operation(session_id, True, f\"\u2705 Extended to {new_size} GB successfully!\", C[\"success\"])\n            else:\n                self._partition_log_diagnostic(\"ERROR\", verify_msg)\n                self._partition_end_operation(session_id, False, f\"\u274c Extend verify failed: {verify_msg}\", C[\"error\"])\n        else:\n            self._partition_log_diagnostic(\"ERROR\", f\"Extend failed: {result.output[:200]}\")\n            self._partition_end_operation(session_id, False, \"\u274c Extend failed\", C[\"error\"])\n\n    def _partition_shrink_prompt(self):\n        sel = self.partition_tree.selection()\n        if len(sel) != 1:\n            messagebox.showinfo(\"Select Partition\", \"Pehle ek partition select karo.\")\n            return\n        values = self.partition_tree.item(sel[0])[\"values\"]\n        part = self._partition_find_data(*values[:2])\n        if not part:\n            return\n        import tkinter.simpledialog as simpledialog\n        current = part.get(\"SizeGB\") or round((part.get(\"Size\") or 0)/(1024**3),2)\n        new_size = simpledialog.askfloat(\"Shrink Partition\", f\"Naya size (GB) enter karo (current {current}):\", initialvalue=max(current - 10, 1), minvalue=1, maxvalue=current - 1)\n        if not new_size:\n            return\n        if not messagebox.askyesno(\"Shrink Partition\", f\"Partition {part.get('DriveLetter','')} ko {new_size} GB tak shrink karna hai?\\nContinue?\"):\n            return\n        preflight = self._partition_preflight_checks(\"shrink\", part, new_size=new_size)\n        if not preflight[\"ok\"]:\n            messagebox.showerror(\"Preflight Failed\", \"\\n\".join(preflight[\"errors\"]))\n            return\n        if preflight[\"warnings\"] and not self._partition_confirm_action(\"Shrink Partition\", f\"Shrinking partition {part.get('DriveLetter','')} to {new_size} GB.\", preflight[\"warnings\"]):\n            return\n        dry_run = messagebox.askyesno(\"Dry-Run Recommended\", \"Dry-run preview recommended for partition shrink. Yes = preview only, No = run actual operation now.\")\n        self._launch_job(\"partition_shrink\", self._partition_shrink_worker, part, new_size, dry_run)\n\n    def _partition_shrink_worker(self, part, new_size, dry_run=False):\n        started, session_id = self._partition_start_operation(\"Shrink Partition\")\n        if not started:\n            self._append_log(self.partition_log, \"\u26a0 Another partition operation is already running.\", C[\"warning\"])\n            return\n        self._partition_log_diagnostic(\"INFO\", f\"Starting partition shrink: {part.get('DriveLetter','')} to {new_size} GB\", {\"dry_run\": dry_run})\n        command = f\"Resize-Partition -DiskNumber {part['DiskNumber']} -PartitionNumber {part['PartitionNumber']} -Size ({new_size}GB)\"\n        if dry_run:\n            command += \" -WhatIf\"\n        self._partition_update_progress(15, \"Preparing shrink command...\")\n        self._partition_update_progress(35, \"Executing PowerShell command...\")\n        result = self._partition_run_powershell_cancelable(command, timeout=90)\n        if self._partition_operation_is_cancelled():\n            self._partition_log_diagnostic(\"WARN\", \"Shrink operation cancelled.\")\n            self._partition_end_operation(session_id, False, \"Shrink cancelled\", C[\"warning\"])\n            return\n        self._partition_update_progress(70, \"Verifying shrink result...\")\n        if result.returncode == 0:\n            if dry_run:\n                self._partition_log_diagnostic(\"OK\", \"Dry-run complete: shrink command validated.\")\n                self._partition_end_operation(session_id, True, \"Dry-run complete\", C[\"success\"])\n                return\n            verify_ok, verify_msg = self._partition_verify_post_operation(\"shrink\", part, expected=new_size)\n            if verify_ok:\n                self._partition_log_diagnostic(\"OK\", f\"Shrunk to {new_size} GB successfully.\")\n                self.after(0, self._partition_refresh_tree)\n                self._partition_end_operation(session_id, True, f\"\u2705 Shrunk to {new_size} GB successfully!\", C[\"success\"])\n            else:\n                self._partition_log_diagnostic(\"ERROR\", verify_msg)\n                self._partition_end_operation(session_id, False, f\"\u274c Shrink verify failed: {verify_msg}\", C[\"error\"])\n        else:\n            self._partition_log_diagnostic(\"ERROR\", f\"Shrink failed: {result.output[:200]}\")\n            self._partition_end_operation(session_id, False, \"\u274c Shrink failed\", C[\"error\"])\n\n    def _partition_format_prompt(self):\n        sel = self.partition_tree.selection()\n        if len(sel) != 1:\n            messagebox.showinfo(\"Select Partition\", \"Pehle ek partition select karo.\")\n            return\n        values = self.partition_tree.item(sel[0])[\"values\"]\n        part = self._partition_find_data(*values[:2])\n        if not part:\n            messagebox.showinfo(\"Format Partition\", \"Partition metadata nahi mila.\")\n            return\n        if not messagebox.askyesno(\n            \"Format Partition\",\n            f\"Partition {part.get('DriveLetter','(no letter)')} ko NTFS se format karne se saari files permanently delete ho jayengi.\\n\\n\"\n            \"Yeh operation irreversible hai.\\n\\nContinue?\"\n        ):\n            return\n        preflight = self._partition_preflight_checks(\"format\", part)\n        if not preflight[\"ok\"]:\n            messagebox.showerror(\"Preflight Failed\", \"\\n\".join(preflight[\"errors\"]))\n            return\n        if preflight[\"warnings\"] and not self._partition_confirm_action(\n            \"Format Partition\",\n            f\"Formatting partition {part.get('DriveLetter','')} to NTFS.\",\n            preflight[\"warnings\"]\n        ):\n            return\n        dry_run = messagebox.askyesno(\n            \"Dry-Run Recommended\",\n            \"Dry-run preview recommended for format. Yes = preview only, No = run actual operation now.\"\n        )\n        self._launch_job(\"partition_format\", self._partition_format_worker, part, dry_run)\n\n    def _partition_format_worker(self, part, dry_run=False):\n        started, session_id = self._partition_start_operation(\"Format Partition\")\n        if not started:\n            self._append_log(self.partition_log, \"\u26a0 Another partition operation is already running.\", C[\"warning\"])\n            return\n        self._partition_log_diagnostic(\"INFO\", f\"Starting format on partition {part.get('DriveLetter','')} ({part.get('DiskNumber')}/{part.get('PartitionNumber')})\", {\"dry_run\": dry_run})\n        label = f\"Godawari_{datetime.datetime.now().strftime('%Y%m%d')}\"\n        self._partition_update_progress(10, \"Preparing format command...\")\n        if part.get(\"DriveLetter\"):\n            command = f\"Format-Volume -DriveLetter {part['DriveLetter']} -FileSystem NTFS -NewFileSystemLabel '{label}' -Confirm:$false\"\n        else:\n            command = f\"$part = Get-Partition -DiskNumber {part['DiskNumber']} -PartitionNumber {part['PartitionNumber']}; Format-Volume -Partition $part -FileSystem NTFS -NewFileSystemLabel '{label}' -Confirm:$false\"\n        if dry_run:\n            command += \" -WhatIf\"\n        self._partition_update_progress(35, \"Executing format command...\")\n        result = self._partition_run_powershell_cancelable(command, timeout=120)\n        if self._partition_operation_is_cancelled():\n            self._partition_log_diagnostic(\"WARN\", \"Format operation cancelled.\")\n            self._partition_end_operation(session_id, False, \"Format cancelled\", C[\"warning\"])\n            return\n        if result.returncode == 0:\n            if dry_run:\n                self._partition_log_diagnostic(\"OK\", \"Dry-run complete: format command validated.\")\n                self._partition_end_operation(session_id, True, \"Dry-run complete\", C[\"success\"])\n                return\n            self._partition_update_progress(65, \"Verifying format result...\")\n            verify_ok, verify_msg = self._partition_verify_post_operation(\"format\", part)\n            if verify_ok:\n                self._partition_log_diagnostic(\"OK\", f\"Partition formatted to NTFS successfully.\")\n                self.after(0, self._partition_refresh_tree)\n                self._partition_end_operation(session_id, True, \"\u2705 Partition formatted successfully\", C[\"success\"])\n            else:\n                self._partition_log_diagnostic(\"ERROR\", verify_msg)\n                self._partition_end_operation(session_id, False, f\"\u274c Format verify failed: {verify_msg}\", C[\"error\"])\n        else:\n            self._partition_log_diagnostic(\"ERROR\", f\"Format failed: {result.output[:200]}\")\n            self._partition_end_operation(session_id, False, \"\u274c Format failed\", C[\"error\"])\n\n    def _partition_change_letter_prompt(self):\n        sel = self.partition_tree.selection()\n        if len(sel) != 1:\n            messagebox.showinfo(\"Select Partition\", \"Pehle ek partition select karo.\")\n            return\n        values = self.partition_tree.item(sel[0])[\"values\"]\n        part = self._partition_find_data(*values[:2])\n        if not part:\n            return\n        import tkinter.simpledialog as simpledialog\n        new_letter = simpledialog.askstring(\"Change Drive Letter\", \"Naya drive letter enter karo:\", initialvalue=part.get(\"DriveLetter\") or \"G\")\n        if not new_letter:\n            return\n        letter = new_letter.strip().upper()[:1]\n        if not letter.isalpha():\n            messagebox.showerror(\"Invalid Letter\", \"Sirf A-Z drive letter use karo.\")\n            return\n        if not messagebox.askyesno(\"Change Drive Letter\", f\"{part.get('DriveLetter','')} ko {letter}: pe change karna hai?\\nContinue?\"):\n            return\n        preflight = self._partition_preflight_checks(\"change_letter\", part, dest_part=letter)\n        if not preflight[\"ok\"]:\n            messagebox.showerror(\"Preflight Failed\", \"\\n\".join(preflight[\"errors\"]))\n            return\n        if preflight[\"warnings\"] and not self._partition_confirm_action(\"Change Drive Letter\", f\"Changing drive letter for {part.get('DriveLetter','')} to {letter}:\", preflight[\"warnings\"]):\n            return\n        dry_run = messagebox.askyesno(\"Dry-Run Recommended\", \"Dry-run preview recommended for drive letter change. Yes = preview only, No = run actual operation now.\")\n        self._launch_job(\"partition_change_letter\", self._partition_change_letter_worker, part, letter, dry_run)\n\n    def _partition_change_letter_worker(self, part, letter, dry_run=False):\n        started, session_id = self._partition_start_operation(\"Change Drive Letter\")\n        if not started:\n            self._append_log(self.partition_log, \"\u26a0 Another partition operation is already running.\", C[\"warning\"])\n            return\n        self._partition_log_diagnostic(\"INFO\", f\"Starting drive letter change: {part.get('DriveLetter','')} \u2192 {letter}\", {\"dry_run\": dry_run})\n        command = f\"Set-Partition -DiskNumber {part['DiskNumber']} -PartitionNumber {part['PartitionNumber']} -NewDriveLetter {letter}\"\n        if dry_run:\n            command += \" -WhatIf\"\n        self._partition_update_progress(15, \"Preparing change letter command...\")\n        self._partition_update_progress(50, \"Executing PowerShell Set-Partition...\")\n        result = self._partition_run_powershell_cancelable(command, timeout=45)\n        if self._partition_operation_is_cancelled():\n            self._partition_log_diagnostic(\"WARN\", \"Drive letter change cancelled.\")\n            self._partition_end_operation(session_id, False, \"Change letter cancelled\", C[\"warning\"])\n            return\n        if result.returncode == 0:\n            if dry_run:\n                self._partition_log_diagnostic(\"OK\", \"Dry-run complete: drive letter change command validated.\")\n                self._partition_end_operation(session_id, True, \"Dry-run complete\", C[\"success\"])\n                return\n            verify_ok, verify_msg = self._partition_verify_post_operation(\"change_letter\", part, expected=letter)\n            if verify_ok:\n                self._partition_log_diagnostic(\"OK\", f\"Drive letter changed to {letter} successfully.\")\n                self.after(0, self._partition_refresh_tree)\n                self._partition_end_operation(session_id, True, f\"\u2705 Drive letter changed to {letter}:\", C[\"success\"])\n            else:\n                self._partition_log_diagnostic(\"ERROR\", verify_msg)\n                self._partition_end_operation(session_id, False, f\"\u274c Change letter verify failed: {verify_msg}\", C[\"error\"])\n        else:\n            self._partition_log_diagnostic(\"ERROR\", f\"Change letter failed: {result.output[:200]}\")\n            self._partition_end_operation(session_id, False, \"\u274c Change letter failed\", C[\"error\"])\n\n    def _partition_split_prompt(self):\n        sel = self.partition_tree.selection()\n        if len(sel) != 1:\n            messagebox.showinfo(\"Select Partition\", \"Pehle ek partition select karo.\")\n            return\n        values = self.partition_tree.item(sel[0])[\"values\"]\n        part = self._partition_find_data(*values[:2])\n        if not part:\n            return\n        import tkinter.simpledialog as simpledialog\n        current = part.get(\"SizeGB\") or round((part.get(\"Size\") or 0)/(1024**3),2)\n        new_size = simpledialog.askfloat(\"Split Partition\", f\"Nayi sub-partition ka size (GB) enter karo, current {current}:\", initialvalue=max(current / 2, 1), minvalue=1, maxvalue=current - 1)\n        if not new_size:\n            return\n        if not messagebox.askyesno(\"Split Partition\", f\"Partition {current} GB se {new_size} GB ka new partition banega. Continue?\"):\n            return\n        preflight = self._partition_preflight_checks(\"split\", part, new_size=new_size)\n        if not preflight[\"ok\"]:\n            messagebox.showerror(\"Preflight Failed\", \"\\n\".join(preflight[\"errors\"]))\n            return\n        if preflight[\"warnings\"] and not self._partition_confirm_action(\"Split Partition\", f\"Split partition {part.get('DriveLetter','')} into new {new_size} GB volume.\", preflight[\"warnings\"]):\n            return\n        dry_run = messagebox.askyesno(\"Dry-Run Recommended\", \"Dry-run preview recommended for partition split. Yes = preview only, No = run actual operation now.\")\n        self._launch_job(\"partition_split\", self._partition_split_worker, part, new_size, dry_run)\n\n    def _partition_split_worker(self, part, new_size, dry_run=False):\n        started, session_id = self._partition_start_operation(\"Split Partition\")\n        if not started:\n            self._append_log(self.partition_log, \"\u26a0 Another partition operation is already running.\", C[\"warning\"])\n            return\n        if not is_admin():\n            self._partition_log_diagnostic(\"ERROR\", \"Admin rights required for split.\")\n            self._partition_end_operation(session_id, False, \"Admin required\", C[\"error\"])\n            return\n        self._partition_log_diagnostic(\"INFO\", f\"Starting partition split: {part.get('DriveLetter','')} -&gt; {new_size} GB\", {\"dry_run\": dry_run})\n        self._partition_update_progress(25, \"Preparing split plan...\")\n        command = f\"$diskNum = {part['DiskNumber']}; $partNum = {part['PartitionNumber']}; $newSize = {new_size}GB; $currentPart = Get-Partition -DiskNumber $diskNum -PartitionNumber $partNum; $targetSize = $currentPart.Size - $newSize - 1MB; Resize-Partition -DiskNumber $diskNum -PartitionNumber $partNum -Size $targetSize\"\n        if not dry_run:\n            command += \"; $newPart = New-Partition -DiskNumber $diskNum -Size $newSize -AssignDriveLetter; Format-Volume -DriveLetter $newPart.DriveLetter -FileSystem NTFS -NewFileSystemLabel 'GodawariSplit' -Confirm:$false\"\n        else:\n            command += \" -WhatIf\"\n        self._partition_update_progress(40, \"Executing split command...\")\n        result = self._partition_run_powershell_cancelable(command, timeout=240)\n        if self._partition_operation_is_cancelled():\n            self._partition_log_diagnostic(\"WARN\", \"Split operation cancelled.\")\n            self._partition_end_operation(session_id, False, \"Split cancelled\", C[\"warning\"])\n            return\n        if result.returncode == 0:\n            if dry_run:\n                self._partition_log_diagnostic(\"OK\", \"Dry-run complete: split command validated.\")\n                self._partition_end_operation(session_id, True, \"Dry-run complete\", C[\"success\"])\n                return\n            self._partition_update_progress(85, \"Verifying split result...\")\n            verify_ok, verify_msg = self._partition_verify_post_operation(\"split\", part, expected=new_size)\n            if verify_ok:\n                self._partition_log_diagnostic(\"OK\", f\"Split created with {new_size} GB successfully.\")\n                self.after(0, self._partition_refresh_tree)\n                self._partition_end_operation(session_id, True, f\"\u2705 Split created with {new_size} GB.\", C[\"success\"])\n            else:\n                self._partition_log_diagnostic(\"ERROR\", verify_msg)\n                self._partition_end_operation(session_id, False, f\"\u274c Split verify failed: {verify_msg}\", C[\"error\"])\n        else:\n            self._partition_log_diagnostic(\"ERROR\", f\"Split failed: {result.output[:200]}\")\n            self._partition_end_operation(session_id, False, \"\u274c Split failed\", C[\"error\"])\n\n    def _partition_clone_prompt(self):\n        sel = self.partition_tree.selection()\n        if len(sel) != 1:\n            messagebox.showinfo(\"Select Partition\", \"Pehle ek source partition select karo.\")\n            return\n        src = self._partition_find_data(*self.partition_tree.item(sel[0])[\"values\"][:2])\n        if not src or not src.get(\"DriveLetter\"):\n            messagebox.showinfo(\"Clone Partition\", \"Source partition ko drive letter chahiye.\")\n            return\n        candidates = [p for p in (self.partition_data.get(\"Partitions\") or []) if p.get(\"DriveLetter\") and p.get(\"DriveLetter\") != src.get(\"DriveLetter\")]\n        if not candidates:\n            messagebox.showinfo(\"Clone Partition\", \"Kam se kam ek destination partition drive letter ke saath chahiye.\")\n            return\n        options = [f\"{p.get('DriveLetter')}: {p.get('SizeGB')}GB {p.get('Type')}\" for p in candidates]\n        import tkinter.simpledialog as simpledialog\n        choice = simpledialog.askstring(\"Clone Target\", \"Destination partition choose karo:\\n\" + \"\\n\".join(options), initialvalue=options[0])\n        if not choice:\n            return\n        selected = None\n        for p, label in zip(candidates, options):\n            if choice.strip() == label:\n                selected = p\n                break\n        if not selected:\n            messagebox.showerror(\"Invalid Selection\", \"Valid destination select karo.\")\n            return\n        if not messagebox.askyesno(\"Clone Partition\", f\"Source {src.get('DriveLetter')}: ko {selected.get('DriveLetter')}: par clone karna hai?\\nContinue?\"):\n            return\n        preflight = self._partition_preflight_checks(\"clone\", src, dest_part=selected)\n        if not preflight[\"ok\"]:\n            messagebox.showerror(\"Preflight Failed\", \"\\n\".join(preflight[\"errors\"]))\n            return\n        if preflight[\"warnings\"] and not self._partition_confirm_action(\"Clone Partition\", f\"Clone {src.get('DriveLetter','')} to {selected.get('DriveLetter','')}.\", preflight[\"warnings\"]):\n            return\n        dry_run = messagebox.askyesno(\"Dry-Run Recommended\", \"Dry-run preview recommended for partition clone. Yes = preview only, No = run actual operation now.\")\n        self._launch_job(\"partition_clone\", self._partition_clone_worker, src, selected, dry_run)\n\n    def _partition_clone_worker(self, source_part, dest_part, dry_run=False):\n        started, session_id = self._partition_start_operation(\"Clone Partition\")\n        if not started:\n            self._append_log(self.partition_log, \"\u26a0 Another partition operation is already running.\", C[\"warning\"])\n            return\n        src_letter = source_part.get(\"DriveLetter\")\n        dst_letter = dest_part.get(\"DriveLetter\")\n        if not src_letter or not dst_letter:\n            self._partition_log_diagnostic(\"ERROR\", \"Clone failed: drive letters required.\")\n            self._partition_end_operation(session_id, False, \"Clone failed\", C[\"error\"])\n            return\n        self._partition_log_diagnostic(\"INFO\", f\"Starting clone: {src_letter}: \u2192 {dst_letter}:\", {\"dry_run\": dry_run})\n        ts = datetime.datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n        dst_folder = f\"{dst_letter}:\\\\GodawariClone_{ts}\"\n        copy_log = os.path.join(os.environ.get(\"APPDATA\", \"\"), \"GodawariOptimizer\", \"partition_backups\", f\"clone_{ts}.log\")\n        os.makedirs(os.path.dirname(copy_log), exist_ok=True)\n        self._partition_update_progress(10, \"Calculating source size...\")\n        total_bytes = self._partition_folder_size(f\"{src_letter}:\\\\\")\n        self._partition_log_diagnostic(\"INFO\", f\"Source size: {total_bytes} bytes\")\n        if not dry_run:\n            try:\n                usage = shutil.disk_usage(f\"{dst_letter}:\\\\\")\n                if usage.free &lt; total_bytes:\n                    self._partition_log_diagnostic(\"ERROR\", \"Destination volume does not have enough free space.\")\n                    self._partition_end_operation(session_id, False, \"Clone failed: insufficient free space\", C[\"error\"])\n                    return\n            except Exception:\n                self._partition_log_diagnostic(\"WARN\", \"Unable to verify destination free space.\")\n        self._partition_update_progress(20, f\"Starting robocopy (source size: {round(total_bytes/1024**3,1)} GB)...\")\n        cmd = [\"robocopy\", f\"{src_letter}:\\\\\", dst_folder, \"/MIR\", \"/COPYALL\", \"/R:3\", \"/W:5\", f\"/LOG:{copy_log}\", \"/TEE\"]\n        if dry_run:\n            cmd.append(\"/L\")\n        result = self._partition_run_cmd_cancelable(cmd, timeout=7200)\n        if self._partition_operation_is_cancelled():\n            self._partition_log_diagnostic(\"WARN\", \"Clone operation cancelled.\")\n            self._partition_end_operation(session_id, False, \"Clone cancelled\", C[\"warning\"])\n            return\n        self._partition_update_progress(90, \"Verifying copied files...\")\n        if dry_run:\n            self._partition_log_diagnostic(\"OK\", \"Dry-run complete: clone plan validated.\")\n            self._partition_end_operation(session_id, True, \"Dry-run complete\", C[\"success\"])\n            return\n        if result.returncode &gt;= 8:\n            self._partition_log_diagnostic(\"ERROR\", f\"Clone failed: rc={result.returncode}\")\n            self._partition_end_operation(session_id, False, \"\u274c Clone failed\", C[\"error\"])\n        else:\n            self._partition_log_diagnostic(\"OK\", f\"Clone complete: {dst_folder}\")\n            self.after(0, self._partition_refresh_tree)\n            self._partition_end_operation(session_id, True, f\"\u2705 Clone complete: {dst_folder}\", C[\"success\"])\n\n    def _partition_backup_table(self):\n        self._launch_job(\"partition_backup\", self._partition_backup_table_worker)\n\n    def _partition_backup_table_worker(self):\n        backup_dir = os.path.join(os.environ.get(\"APPDATA\", \"\"), \"GodawariOptimizer\", \"partition_backups\")\n        os.makedirs(backup_dir, exist_ok=True)\n        ts = datetime.datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n        backup_file = os.path.join(backup_dir, f\"partition_backup_{ts}.json\")\n        backup_script = \"\"\"\n        $data = @{\n            Disks = (Get-Disk | ConvertTo-Json -Depth 3)\n            Partitions = (Get-Partition | ConvertTo-Json -Depth 3)\n        }\n        $data | ConvertTo-Json -Depth 4\n        \"\"\"\n        self._partition_update_progress(20, \"Reading partition table...\")\n        self._partition_update_progress(50, \"PowerShell query running...\")\n        result = safe_powershell(backup_script, timeout=20)\n        if result.returncode == 0 and result.output.strip():\n            with open(backup_file, \"w\", encoding=\"utf-8\") as f:\n                f.write(result.output)\n            self._partition_update_progress(100, \"\u2705 Partition table backup saved!\")\n            self.after(0, lambda: self._append_log(self.partition_log, f\"\u2705 Partition table backup saved: {backup_file}\", C[\"success\"]))\n        else:\n            self._partition_update_progress(0, \"\u274c Backup failed\")\n            self.after(0, lambda: self._append_log(self.partition_log, f\"\u274c Partition backup failed: {getattr(result, 'output', '')[:200]}\", C[\"error\"]))\n        self._partition_reset_progress_delayed(3000)\n\n    def _partition_get_selected_partitions(self):\n        return [self._partition_find_data(*self.partition_tree.item(iid)[\"values\"][:2]) for iid in self.partition_tree.selection() if self._partition_find_data(*self.partition_tree.item(iid)[\"values\"][:2])]\n\n    def _driver_scan_all(self):\n        self._append_log(self.driver_log, \"Driver scan shuru ho raha hai...\", C[\"accent\"])\n        self._launch_job(\"driver_scan_all\", self._do_driver_scan)\n\n    def _driver_age_text(self, days):\n        if days is None:\n            return \"Nahi pata\"\n        if days &gt;= 365:\n            return f\"{days//365} saal {(days%365)//30} mahine\"\n        return f\"{days} din\"\n\n    def _driver_parse_date(self, raw):\n        try:\n            if not raw:\n                return None\n            text = str(raw)\n            if re.match(r\"^\\d{14}\", text):\n                return datetime.datetime.strptime(text[:14], \"%Y%m%d%H%M%S\")\n            m = re.search(r\"/Date\\((\\d+)\", text)\n            if m:\n                return datetime.datetime.fromtimestamp(int(m.group(1)) / 1000)\n            for fmt in (\"%Y-%m-%dT%H:%M:%S\", \"%m/%d/%Y %H:%M:%S\", \"%Y-%m-%d\"):\n                try:\n                    return datetime.datetime.strptime(text[:19], fmt)\n                except Exception:\n                    pass\n        except Exception:\n            return None\n        return None\n\n    def _do_driver_scan(self):\n        try:\n            cmd = 'powershell -NoProfile -Command \"Get-WmiObject Win32_PnPSignedDriver | Select-Object DeviceName,DriverVersion,DriverDate,IsSigned,InfName | ConvertTo-Json\"'\n            out, rc = self._run_cmd(cmd, timeout=180)\n            if rc != 0:\n                self._append_log(self.driver_log, f\"Error aaya: {out[:300]}\", C[\"error\"])\n                return\n            data = json.loads(out) if out.strip() else []\n            if isinstance(data, dict):\n                data = [data]\n            rows = []\n            now = datetime.datetime.now()\n            for d in data:\n                dt = self._driver_parse_date(d.get(\"DriverDate\"))\n                days = (now - dt).days if dt else None\n                signed = bool(d.get(\"IsSigned\"))\n                tag = \"ok\"\n                if not signed:\n                    tag = \"unsigned\"\n                elif days is not None and days &gt; 730:\n                    tag = \"very_old\"\n                elif days is not None and days &gt; 365:\n                    tag = \"old\"\n                rows.append({\n                    \"device\": d.get(\"DeviceName\") or \"Naam nahi mila\",\n                    \"version\": d.get(\"DriverVersion\") or \"Nahi pata\",\n                    \"date\": dt.strftime(\"%Y-%m-%d\") if dt else \"Nahi pata\",\n                    \"signed\": signed,\n                    \"inf\": d.get(\"InfName\") or \"Nahi pata\",\n                    \"days\": days,\n                    \"age\": self._driver_age_text(days),\n                    \"tag\": tag,\n                })\n            self.after(0, lambda: self._driver_fill_rows(rows))\n        except Exception as e:\n            self._append_log(self.driver_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _driver_fill_rows(self, rows):\n        try:\n            self.driver_all_rows = rows\n            self.driver_tree.delete(*self.driver_tree.get_children())\n            for idx, r in enumerate(rows):\n                status = \"Signed\" if r[\"signed\"] else \"Unsigned\"\n                self.driver_tree.insert(\"\", \"end\", iid=str(idx), values=(r[\"device\"], r[\"version\"], r[\"date\"], status, r[\"age\"]), tags=(r[\"tag\"],))\n            self._append_log(self.driver_log, f\"\u2705 Kaam ho gaya: {len(rows)} drivers load ho gaye\", C[\"success\"])\n        except Exception as e:\n            self._append_log(self.driver_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _driver_filter_old(self):\n        try:\n            rows = [r for r in getattr(self, \"driver_all_rows\", []) if (r.get(\"days\") or 0) &gt;= 365]\n            self._driver_fill_rows(rows)\n            self._append_log(self.driver_log, \"Purane drivers filter ho gaye\", C[\"warning\"])\n        except Exception as e:\n            self._append_log(self.driver_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _driver_filter_unsigned(self):\n        try:\n            rows = [r for r in getattr(self, \"driver_all_rows\", []) if not r.get(\"signed\")]\n            self._driver_fill_rows(rows)\n            self._append_log(self.driver_log, \"Unsigned drivers filter ho gaye\", C[\"warning\"])\n        except Exception as e:\n            self._append_log(self.driver_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _driver_on_select(self, event):\n        try:\n            sel = self.driver_tree.selection()\n            if not sel:\n                return\n            vals = self.driver_tree.item(sel[0], \"values\")\n            device = vals[0]\n            row = next((r for r in getattr(self, \"driver_all_rows\", []) if r.get(\"device\") == device), None)\n            if not row:\n                return\n            for w in self.driver_detail.winfo_children():\n                w.destroy()\n            tk.Label(self.driver_detail, text=row[\"device\"], font=(\"Segoe UI\", 13, \"bold\"), fg=C[\"accent\"], bg=C[\"card\"], wraplength=330, justify=\"left\").pack(anchor=\"w\", pady=(0,8))\n            info = [\n                f\"Version: {row['version']}\",\n                f\"Date: {row['date']}\",\n                f\"Signed: {'Haan' if row['signed'] else 'Nahi'}\",\n                f\"INF file: {row['inf']}\",\n            ]\n            for line in info:\n                tk.Label(self.driver_detail, text=line, font=FONTS[\"body\"], fg=C[\"text\"], bg=C[\"card\"], wraplength=330, justify=\"left\").pack(anchor=\"w\", pady=2)\n            if not row[\"signed\"]:\n                rec, color = \"\u26a0 Unsigned driver - security risk\", C[\"error\"]\n            elif (row.get(\"days\") or 0) &gt; 730:\n                rec, color = \"\u26a0 Bahut purana driver - update recommended\", C[\"warning\"]\n            elif row.get(\"days\") is not None and row[\"days\"] &lt; 180:\n                rec, color = \"\u2705 Recent driver - action ki zaroorat nahi\", C[\"success\"]\n            else:\n                rec, color = \"Info: Driver theek lag raha hai\", C[\"text_dim\"]\n            tk.Label(self.driver_detail, text=rec, font=FONTS[\"subhead\"], fg=color, bg=C[\"card\"], wraplength=330, justify=\"left\").pack(anchor=\"w\", pady=12)\n        except Exception as e:\n            self._append_log(self.driver_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _driver_export_csv(self):\n        try:\n            rows = getattr(self, \"driver_all_rows\", [])\n            if not rows:\n                messagebox.showwarning(\"Data nahi mila\", \"Pehle driver scan karo\")\n                return\n            csv_mod = __import__(\"csv\")\n            desktop = os.path.join(os.environ.get(\"USERPROFILE\", \"\"), \"Desktop\")\n            path = os.path.join(desktop, f\"Godawari_Driver_Report_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.csv\")\n            with open(path, \"w\", newline=\"\", encoding=\"utf-8-sig\") as f:\n                writer = csv_mod.writer(f)\n                writer.writerow([\"DeviceName\", \"DriverVersion\", \"DriverDate\", \"Signed\", \"Age\"])\n                for r in rows:\n                    writer.writerow([r[\"device\"], r[\"version\"], r[\"date\"], \"Haan\" if r[\"signed\"] else \"Nahi\", r[\"age\"]])\n            self._append_log(self.driver_log, f\"\u2705 Kaam ho gaya: CSV save hua - {path}\", C[\"success\"])\n            messagebox.showinfo(\"Kaam ho gaya\", f\"Driver CSV save ho gaya:\\n{path}\")\n        except Exception as e:\n            self._append_log(self.driver_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _build_svc_presets(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"Services Preset Manager\", \"Gaming, office, safe aur repair presets\")\n        content = self._scrollable_section_body(frame)\n        self.svc_presets_data = {\n            \"Gaming\": {\"description\": \"Maximum performance - gaming ke liye\", \"icon\": \"\ud83c\udfae\", \"color\": C[\"btn_danger\"], \"disable\": [\"SysMain\",\"DiagTrack\",\"WSearch\",\"TabletInputService\",\"Fax\",\"PrintNotify\",\"WerSvc\",\"XblAuthManager\",\"XblGameSave\",\"XboxNetApiSvc\"], \"manual\": [\"wuauserv\"], \"keep_running\": [\"AudioSrv\",\"AudioEndpointBuilder\",\"Themes\"]},\n            \"Office/Work\": {\"description\": \"Stable aur fast - office work ke liye\", \"icon\": \"\ud83d\udcbc\", \"color\": C[\"btn_info\"], \"disable\": [\"XblAuthManager\",\"XblGameSave\",\"XboxNetApiSvc\",\"Fax\",\"RetailDemo\",\"DiagTrack\"], \"manual\": [\"SysMain\",\"WSearch\"], \"keep_running\": [\"wuauserv\",\"AudioSrv\",\"Themes\"]},\n            \"Minimal/Safe\": {\"description\": \"Sirf zaroori services - slow PC ke liye\", \"icon\": \"\ud83d\udee1\", \"color\": C[\"btn_chip\"], \"disable\": [\"SysMain\",\"DiagTrack\",\"WSearch\",\"TabletInputService\",\"Fax\",\"PrintNotify\",\"WerSvc\",\"XblAuthManager\",\"XblGameSave\",\"XboxNetApiSvc\",\"RetailDemo\",\"MapsBroker\",\"lfsvc\",\"SharedAccess\"], \"manual\": [\"wuauserv\",\"BITS\"], \"keep_running\": [\"AudioSrv\",\"Themes\",\"LanmanWorkstation\"]},\n            \"Repair Shop\": {\"description\": \"Troubleshooting ke liye - diagnostics on\", \"icon\": \"\ud83d\udd27\", \"color\": C[\"hw_accent\"], \"disable\": [\"XblAuthManager\",\"XblGameSave\",\"Fax\",\"RetailDemo\"], \"manual\": [\"DiagTrack\",\"WerSvc\"], \"keep_running\": [\"WSearch\",\"wuauserv\",\"SysMain\",\"AudioSrv\"]},\n        }\n        self.svc_selected_preset = tk.StringVar(value=\"Gaming\")\n        self.svc_preset_snapshot = {}\n        self.svc_preset_cards = {}\n        cards = tk.Frame(content, bg=C[\"bg\"])\n        cards.pack(fill=\"x\", padx=14, pady=8)\n        for i, (name, data) in enumerate(self.svc_presets_data.items()):\n            card = tk.Frame(cards, bg=C[\"card\"], highlightbackground=data[\"color\"], highlightthickness=1, cursor=\"hand2\")\n            card.grid(row=0, column=i, sticky=\"nsew\", padx=5)\n            cards.columnconfigure(i, weight=1)\n            tk.Label(card, text=data[\"icon\"], font=(\"Segoe UI\", 22), fg=data[\"color\"], bg=C[\"card\"]).pack(pady=(8,0))\n            tk.Label(card, text=name, font=FONTS[\"subhead\"], fg=C[\"text\"], bg=C[\"card\"]).pack()\n            tk.Label(card, text=data[\"description\"], font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=220).pack(padx=8, pady=(0,8))\n            card.bind(\"\", lambda e, n=name: self._svc_preset_select(n))\n            for child in card.winfo_children():\n                child.bind(\"\", lambda e, n=name: self._svc_preset_select(n))\n            self.svc_preset_cards[name] = card\n        body = tk.Frame(content, bg=C[\"bg\"])\n        body.pack(fill=\"both\", expand=True, padx=14)\n        left = tk.Frame(body, bg=C[\"card\"])\n        left.pack(side=\"left\", fill=\"both\", expand=True, padx=(0,8))\n        right = tk.Frame(body, bg=C[\"card\"], width=360)\n        right.pack(side=\"right\", fill=\"both\", padx=(8,0))\n        right.pack_propagate(False)\n        wrap, self.svc_tree = self._adv_tree(left, [\"Service Naam\", \"Display Naam\", \"Action\", \"Current Status\"], height=16)\n        wrap.pack(fill=\"both\", expand=True, padx=8, pady=8)\n        self.svc_tree.tag_configure(\"risk\", foreground=C[\"error\"])\n        self.svc_status_text = self._scrolled_text(right, height=15)\n        btns = tk.Frame(content, bg=C[\"bg\"])\n        btns.pack(fill=\"x\", padx=14, pady=6)\n        for label, color, cmd in [\n            (\"Status Check\", C[\"btn_info\"], self._svc_preset_check_status),\n            (\"Preset Apply\", C[\"btn_danger\"], lambda: self._svc_preset_apply(self.svc_selected_preset.get())),\n            (\"Custom Save\", C[\"btn\"], self._svc_preset_save_custom),\n            (\"Custom Load\", C[\"btn_chip\"], self._svc_preset_load_custom),\n            (\"Previous Restore\", C[\"btn_warn\"], self._svc_preset_restore),\n        ]:\n            self._btn(btns, label, color, cmd).pack(side=\"left\", padx=4)\n        self.svc_log = self._scrolled_text(content, height=6)\n        self._svc_preset_select(\"Gaming\")\n        return frame\n\n    def _svc_preset_select(self, preset_name):\n        try:\n            self.svc_selected_preset.set(preset_name)\n            for name, card in self.svc_preset_cards.items():\n                card.configure(bg=C[\"panel\"] if name == preset_name else C[\"card\"])\n                for child in card.winfo_children():\n                    child.configure(bg=card[\"bg\"])\n            data = self.svc_presets_data[preset_name]\n            self.svc_tree.delete(*self.svc_tree.get_children())\n            for svc in data.get(\"disable\", []):\n                self.svc_tree.insert(\"\", \"end\", values=(svc, svc, \"Disable\", \"Check pending\"))\n            for svc in data.get(\"manual\", []):\n                self.svc_tree.insert(\"\", \"end\", values=(svc, svc, \"Manual\", \"Check pending\"))\n            for svc in data.get(\"keep_running\", []):\n                self.svc_tree.insert(\"\", \"end\", values=(svc, svc, \"Keep\", \"Check pending\"))\n            self._append_log(self.svc_log, f\"{preset_name} preset select ho gaya\", C[\"accent\"])\n        except Exception as e:\n            self._append_log(self.svc_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _svc_preset_check_status(self):\n        try:\n            services = []\n            for iid in self.svc_tree.get_children():\n                vals = self.svc_tree.item(iid, \"values\")\n                if len(vals) &gt;= 3:\n                    services.append((iid, vals[0], vals[2]))\n            self._launch_job(\"svc_preset_check\", self._do_svc_preset_check, services)\n        except Exception as e:\n            self._append_log(self.svc_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _do_svc_preset_check(self, services=None):\n        try:\n            updates = []\n            for iid, svc, action in (services or []):\n                status = self._svc_get_status(svc)\n                updates.append((iid, status, action))\n            def apply():\n                for iid, status, action in updates:\n                    vals = list(self.svc_tree.item(iid, \"values\"))\n                    vals[3] = status\n                    tags = (\"risk\",) if status == \"Running\" and vals[2] == \"Disable\" else ()\n                    self.svc_tree.item(iid, values=vals, tags=tags)\n                self._append_log(self.svc_log, \"\u2705 Kaam ho gaya: Service status update ho gaya\", C[\"success\"])\n            self.after(0, apply)\n        except Exception as e:\n            self._append_log(self.svc_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _svc_preset_apply(self, preset_name):\n        try:\n            data = self.svc_presets_data.get(preset_name)\n            if not data:\n                messagebox.showwarning(\"Preset nahi mila\", \"Pehle preset select karo\")\n                return\n            count = len(data.get(\"disable\", [])) + len(data.get(\"manual\", []))\n            if not messagebox.askyesno(\"Confirm karo\", f\"{preset_name} preset apply karna hai?\\n{count} services change hongi.\"):\n                return\n            self._launch_job(\"svc_preset_apply\", self._do_svc_preset_apply, preset_name, data)\n        except Exception as e:\n            self._append_log(self.svc_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _do_svc_preset_apply(self, preset_name, preset_data):\n        try:\n            affected = set(preset_data.get(\"disable\", []) + preset_data.get(\"manual\", []) + preset_data.get(\"keep_running\", []))\n            self.svc_preset_snapshot = {svc: self._svc_get_start_type(svc) for svc in affected}\n            for svc in preset_data.get(\"disable\", []):\n                out, rc = self._run_cmd(f\"sc config {svc} start= disabled\", timeout=40)\n                self._append_log(self.svc_log, f\"{svc}: disabled set - rc {rc}\", C[\"warning\"] if rc else C[\"success\"])\n                self._run_cmd(f\"sc stop {svc}\", timeout=25)\n            for svc in preset_data.get(\"manual\", []):\n                out, rc = self._run_cmd(f\"sc config {svc} start= demand\", timeout=40)\n                self._append_log(self.svc_log, f\"{svc}: manual set - rc {rc}\", C[\"success\"] if rc == 0 else C[\"warning\"])\n            self._append_log(self.svc_log, f\"\u2705 Kaam ho gaya: {preset_name} preset apply ho gaya\", C[\"success\"])\n            self._svc_preset_check_status()\n        except Exception as e:\n            self._append_log(self.svc_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _svc_preset_save_custom(self):\n        self._launch_job(\"svc_custom_save\", self._svc_preset_save_custom_worker)\n\n    def _svc_preset_save_custom_worker(self):\n        try:\n            all_svcs = set()\n            for data in self.svc_presets_data.values():\n                all_svcs.update(data.get(\"disable\", []) + data.get(\"manual\", []) + data.get(\"keep_running\", []))\n            custom = {\"description\": \"Saved custom service state\", \"icon\": \"\ud83d\udcbe\", \"color\": C[\"btn\"], \"disable\": [], \"manual\": [], \"keep_running\": []}\n            for svc in all_svcs:\n                st = self._svc_get_start_type(svc)\n                if st == \"disabled\":\n                    custom[\"disable\"].append(svc)\n                elif st == \"demand\":\n                    custom[\"manual\"].append(svc)\n                elif st == \"auto\":\n                    custom[\"keep_running\"].append(svc)\n            path = os.path.join(os.environ.get(\"APPDATA\", \"\"), \"GodawariOptimizer\", \"svc_custom.json\")\n            os.makedirs(os.path.dirname(path), exist_ok=True)\n            with open(path, \"w\", encoding=\"utf-8\") as f:\n                json.dump(custom, f, indent=2)\n            self.svc_presets_data[\"Custom\"] = custom\n            self._append_log(self.svc_log, f\"\u2705 Kaam ho gaya: Custom preset save hua - {path}\", C[\"success\"])\n        except Exception as e:\n            self._append_log(self.svc_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _svc_preset_load_custom(self):\n        try:\n            path = os.path.join(os.environ.get(\"APPDATA\", \"\"), \"GodawariOptimizer\", \"svc_custom.json\")\n            if not os.path.exists(path):\n                messagebox.showwarning(\"Custom nahi mila\", \"Custom preset abhi save nahi hai\")\n                return\n            with open(path, \"r\", encoding=\"utf-8\") as f:\n                self.svc_presets_data[\"Custom\"] = json.load(f)\n            self._svc_preset_select(\"Custom\")\n            self._append_log(self.svc_log, \"\u2705 Kaam ho gaya: Custom preset load ho gaya\", C[\"success\"])\n        except Exception as e:\n            self._append_log(self.svc_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _svc_preset_restore(self):\n        try:\n            if not getattr(self, \"svc_preset_snapshot\", {}):\n                messagebox.showwarning(\"Snapshot nahi mila\", \"Restore ke liye pehle preset apply hona chahiye\")\n                return\n            if not messagebox.askyesno(\"Confirm karo\", \"Previous service state restore karna hai?\"):\n                return\n            self._launch_job(\"svc_restore\", self._svc_preset_restore_worker)\n        except Exception as e:\n            self._append_log(self.svc_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _svc_preset_restore_worker(self):\n        try:\n            for svc, st in self.svc_preset_snapshot.items():\n                if st in (\"auto\", \"demand\", \"disabled\"):\n                    out, rc = self._run_cmd(f\"sc config {svc} start= {st}\", timeout=40)\n                    self._append_log(self.svc_log, f\"{svc}: {st} restore - rc {rc}\", C[\"success\"] if rc == 0 else C[\"warning\"])\n            self._append_log(self.svc_log, \"\u2705 Kaam ho gaya: Previous state restore ho gayi\", C[\"success\"])\n        except Exception as e:\n            self._append_log(self.svc_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _svc_get_start_type(self, service_name):\n        try:\n            out, rc = self._run_cmd(f\"sc qc {service_name}\", timeout=20)\n            m = re.search(r\"START_TYPE\\s+:\\s+\\d+\\s+(\\w+)\", out)\n            text = (m.group(1).lower() if m else \"\")\n            if \"auto\" in text:\n                return \"auto\"\n            if \"demand\" in text:\n                return \"demand\"\n            if \"disabled\" in text:\n                return \"disabled\"\n        except Exception:\n            pass\n        return \"unknown\"\n\n    def _svc_get_status(self, service_name):\n        try:\n            out, rc = self._run_cmd(f\"sc query {service_name}\", timeout=20)\n            m = re.search(r\"STATE\\s+:\\s+\\d+\\s+(\\w+)\", out)\n            if m:\n                return \"Running\" if m.group(1).upper() == \"RUNNING\" else \"Stopped\"\n        except Exception:\n            pass\n        return \"Unknown\"\n\n    # Remaining advanced menus are implemented as operational compact panels.\n    def _build_disk_analyzer(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"Disk Space Analyzer\", \"Drive/folder size aur Windows bloat check\")\n        content = self._scrollable_section_body(frame)\n        top = tk.Frame(content, bg=C[\"bg\"])\n        top.pack(fill=\"x\", padx=14, pady=8)\n        string_mod = __import__(\"string\")\n        drives = [f\"{d}:\\\\\" for d in string_mod.ascii_uppercase if os.path.exists(f\"{d}:\\\\\")]\n        self.disk_drive_var = tk.StringVar(value=drives[0] if drives else \"C:\\\\\")\n        self.disk_depth_var = tk.IntVar(value=2)\n        ttk.Combobox(top, textvariable=self.disk_drive_var, values=drives + [\"Custom folder browse karo\"], width=28, state=\"readonly\").pack(side=\"left\", padx=4)\n        tk.Spinbox(top, from_=1, to=5, textvariable=self.disk_depth_var, width=5, bg=C[\"card\"], fg=C[\"text\"]).pack(side=\"left\", padx=4)\n        self._btn(top, \"Scan Drive\", C[\"btn_info\"], self._disk_start_scan).pack(side=\"left\", padx=4)\n        status = tk.Frame(content, bg=C[\"bg\"])\n        status.pack(fill=\"x\", padx=14, pady=(0, 6))\n        self.disk_scan_status = tk.Label(status, text=\"Ready to scan.\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"], anchor=\"w\")\n        self.disk_scan_status.pack(side=\"left\", fill=\"x\", expand=True)\n        self.disk_scan_progress_var = tk.DoubleVar(value=0.0)\n        self.disk_scan_progress = ttk.Progressbar(status, variable=self.disk_scan_progress_var, maximum=100.0, mode=\"determinate\")\n        self.disk_scan_progress.pack(side=\"right\", fill=\"x\", expand=False, ipadx=90, padx=(8, 0))\n        body = tk.Frame(content, bg=C[\"bg\"])\n        body.pack(fill=\"both\", expand=True, padx=14)\n        left = tk.Frame(body, bg=C[\"card\"])\n        left.pack(side=\"left\", fill=\"both\", expand=True, padx=(0,8))\n        right = tk.Frame(body, bg=C[\"card\"], width=360)\n        right.pack(side=\"right\", fill=\"both\", padx=(8,0))\n        right.pack_propagate(False)\n        wrap, self.disk_tree = self._adv_tree(left, [\"Folder\", \"Size\", \"Files Count\", \"% Parent\"], height=18)\n        wrap.pack(fill=\"both\", expand=True, padx=8, pady=8)\n        self.disk_summary = self._scrolled_text(right, height=18)\n        self._action_card_grid(content, [\n            (\"\ud83d\udd0d\", \"Scan Drive\", \"Selected drive scan karo\", C[\"btn_info\"], self._disk_start_scan),\n            (\"\ud83d\udcc2\", \"Folder Kholo\", \"Selected folder Explorer mein kholo\", C[\"btn_chip\"], self._disk_open_selected),\n            (\"\ud83e\uddf9\", \"Temp Clean\", \"Temp folders directly clean karo\", C[\"btn_warn\"], self._disk_clean_temp),\n            (\"\ud83d\udcbe\", \"Report Export\", \"Results CSV mein save karo\", C[\"btn\"], self._disk_export_report),\n            (\"\ud83d\udd04\", \"Refresh\", \"Dobara scan karo\", C[\"accent2\"], self._disk_start_scan),\n        ], cols=5)\n        self.disk_log = self._scrolled_text(content, height=5)\n        self.disk_results = []\n        return frame\n\n    def _disk_start_scan(self):\n        try:\n            root = self.disk_drive_var.get()\n            if root == \"Custom folder browse karo\":\n                root = filedialog.askdirectory()\n                if not root:\n                    return\n                self.disk_drive_var.set(root)\n            self._append_log(self.disk_log, f\"Scan shuru: {root}\", C[\"accent\"])\n            self._disk_update_scan_progress(0, f\"Scanning {root}...\")\n            self._launch_job(\"disk_scan\", self._do_disk_scan, root, int(self.disk_depth_var.get()))\n        except Exception as e:\n            self._append_log(self.disk_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _disk_update_scan_progress(self, pct, text=None):\n        def _update():\n            try:\n                pct_float = max(0.0, min(100.0, float(pct)))\n            except Exception:\n                pct_float = 0.0\n            if hasattr(self, \"disk_scan_progress_var\"):\n                self.disk_scan_progress_var.set(pct_float)\n            if hasattr(self, \"disk_scan_status\") and text is not None:\n                self.disk_scan_status.config(text=f\"{int(pct_float)}% - {str(text)[:160]}\")\n        self.after(0, _update)\n\n    def _do_disk_scan(self, root_path, max_depth):\n        try:\n            root_path = os.path.abspath(root_path)\n            base_depth = root_path.rstrip(\"\\\\/\").count(os.sep)\n            results = []\n            scanned_dirs = 0\n            for cur, dirs, files in os.walk(root_path):\n                depth = cur.rstrip(\"\\\\/\").count(os.sep) - base_depth\n                if depth &gt; max_depth:\n                    dirs[:] = []\n                    continue\n                dirs[:] = [d for d in dirs if not d.startswith(\"$\")]\n                size, count = self._disk_get_folder_size(cur)\n                results.append((cur, size, count, 0))\n                scanned_dirs += 1\n                if scanned_dirs % 8 == 0:\n                    self._disk_update_scan_progress(min(95, 5 + scanned_dirs), f\"{scanned_dirs} folders scanned...\")\n                if len(results) &gt; 250:\n                    break\n            results.sort(key=lambda x: x[1], reverse=True)\n            top = results[:50]\n            bloat = self._disk_check_windows_bloat()\n            self._disk_update_scan_progress(100, f\"{len(top)} folders ready.\")\n            self.after(0, lambda: (self._disk_populate_treeview(top), self._disk_generate_recommendations(bloat)))\n        except Exception as e:\n            self._disk_update_scan_progress(0, f\"Scan failed: {e}\")\n            self._append_log(self.disk_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _disk_get_folder_size(self, path):\n        total = 0\n        count = 0\n        try:\n            for root, dirs, files in os.walk(path):\n                dirs[:] = [d for d in dirs if not d.startswith(\"$\")]\n                for fn in files:\n                    try:\n                        fp = os.path.join(root, fn)\n                        total += os.path.getsize(fp)\n                        count += 1\n                        if count &gt;= 3000:\n                            return total, count\n                    except Exception:\n                        continue\n        except Exception:\n            return total, count\n        return total, count\n\n    def _disk_populate_treeview(self, results):\n        try:\n            self.disk_results = results\n            self.disk_tree.delete(*self.disk_tree.get_children())\n            parent_size = results[0][1] if results else 1\n            for path, size, count, _pct in results:\n                pct = (size / parent_size * 100) if parent_size else 0\n                self.disk_tree.insert(\"\", \"end\", values=(path, self._fmt_size_disk(size), count, f\"{pct:.1f}%\"))\n            self._append_log(self.disk_log, f\"\u2705 Kaam ho gaya: {len(results)} folders show ho rahe hain\", C[\"success\"])\n        except Exception as e:\n            self._append_log(self.disk_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _disk_check_windows_bloat(self):\n        data = {}\n        try:\n            user = os.environ.get(\"USERNAME\", \"\")\n            paths = {\n                \"Windows Temp\": r\"C:\\Windows\\Temp\",\n                \"User Temp\": os.path.join(os.environ.get(\"USERPROFILE\", \"\"), \"AppData\", \"Local\", \"Temp\"),\n                \"Windows Update Cache\": r\"C:\\Windows\\SoftwareDistribution\\Download\",\n                \"Windows Installer\": r\"C:\\Windows\\Installer\",\n                \"Recycle Bin\": r\"C:\\$Recycle.Bin\",\n                \"hiberfil.sys\": r\"C:\\hiberfil.sys\",\n                \"pagefile.sys\": r\"C:\\pagefile.sys\",\n            }\n            for name, path in paths.items():\n                if os.path.isfile(path):\n                    data[name] = os.path.getsize(path)\n                elif os.path.isdir(path):\n                    data[name] = self._disk_get_folder_size(path)[0]\n                else:\n                    data[name] = 0\n        except Exception as e:\n            self._append_log(self.disk_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n        return data\n\n    def _disk_generate_recommendations(self, bloat_data):\n        try:\n            self.disk_summary.config(state=\"normal\")\n            self.disk_summary.delete(\"1.0\", \"end\")\n            self.disk_summary.insert(\"end\", \"Windows Bloat Summary\\n\\n\")\n            recs = []\n            for name, size in bloat_data.items():\n                self.disk_summary.insert(\"end\", f\"{name}: {self._fmt_size_disk(size)}\\n\")\n            if bloat_data.get(\"Windows Temp\", 0) + bloat_data.get(\"User Temp\", 0) &gt; 500*1024*1024:\n                recs.append(\"\ud83d\udfe1 Temp files cleanup recommended - Junk Cleaner use karo\")\n            if bloat_data.get(\"Windows Update Cache\", 0) &gt; 1024*1024*1024:\n                recs.append(\"\ud83d\udfe1 Windows Update cache bada hai - safe clear ho sakta hai\")\n            if bloat_data.get(\"Recycle Bin\", 0) &gt; 100*1024*1024:\n                recs.append(\"\ud83d\udfe1 Recycle Bin empty karo\")\n            if bloat_data.get(\"hiberfil.sys\", 0) &gt; 2*1024*1024*1024:\n                recs.append(\"\ud83d\udfe1 Hibernation disable karo agar laptop nahi hai: powercfg /h off\")\n            if bloat_data.get(\"Windows Installer\", 0) &gt; 2*1024*1024*1024:\n                recs.append(\"\u26a0 Windows Installer folder bada hai - careful cleanup needed\")\n            self.disk_summary.insert(\"end\", \"\\nRecommendations\\n\\n\" + (\"\\n\".join(recs) if recs else \"\u2705 Koi badi cleanup warning nahi mili\"))\n            self.disk_summary.config(state=\"disabled\")\n        except Exception as e:\n            self._append_log(self.disk_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _disk_open_selected(self):\n        try:\n            sel = self.disk_tree.selection()\n            if not sel:\n                messagebox.showwarning(\"Select karo\", \"Pehle folder select karo\")\n                return\n            path = self.disk_tree.item(sel[0], \"values\")[0]\n            if os.path.exists(path):\n                os.startfile(path)\n        except Exception as e:\n            self._append_log(self.disk_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _disk_clean_temp(self):\n        if messagebox.askyesno(\"Confirm karo\", \"Temp files delete karne hain?\"):\n            self._launch_job(\"disk_clean_temp\", self._disk_clean_temp_worker)\n\n    def _disk_clean_temp_worker(self):\n        try:\n            for folder in [r\"C:\\Windows\\Temp\", os.path.join(os.environ.get(\"USERPROFILE\", \"\"), \"AppData\", \"Local\", \"Temp\")]:\n                if os.path.isdir(folder):\n                    for name in os.listdir(folder):\n                        p = os.path.join(folder, name)\n                        try:\n                            shutil.rmtree(p) if os.path.isdir(p) else os.remove(p)\n                        except Exception:\n                            pass\n            self._append_log(self.disk_log, \"\u2705 Kaam ho gaya: Temp clean ho gaya\", C[\"success\"])\n        except Exception as e:\n            self._append_log(self.disk_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _disk_export_report(self):\n        try:\n            if not getattr(self, \"disk_results\", []):\n                messagebox.showwarning(\"Data nahi mila\", \"Pehle disk scan karo\")\n                return\n            csv_mod = __import__(\"csv\")\n            path = os.path.join(os.environ.get(\"USERPROFILE\", \"\"), \"Desktop\", f\"Godawari_Disk_Report_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.csv\")\n            with open(path, \"w\", newline=\"\", encoding=\"utf-8-sig\") as f:\n                writer = csv_mod.writer(f)\n                writer.writerow([\"Folder\", \"SizeBytes\", \"FilesCount\"])\n                for r in self.disk_results:\n                    writer.writerow([r[0], r[1], r[2]])\n            messagebox.showinfo(\"Kaam ho gaya\", f\"Report save ho gayi:\\n{path}\")\n        except Exception as e:\n            self._append_log(self.disk_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _fmt_size_disk(self, bytes):\n        try:\n            val = float(bytes)\n            for unit in [\"B\", \"KB\", \"MB\", \"GB\", \"TB\"]:\n                if val &lt; 1024:\n                    return f\"{val:.1f} {unit}\"\n                val /= 1024\n            return f\"{val:.1f} PB\"\n        except Exception:\n            return \"0 B\"\n\n    def _build_bsod_history(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"BSOD History\", \"Crash events, stop code aur minidump report\")\n        content = self._scrollable_section_body(frame)\n        self._action_card_grid(content, [\n            (\"\ud83d\udd0d\", \"BSOD Scan\", \"Event log se BSOD history nikalo\", C[\"btn_info\"], self._bsod_scan),\n            (\"\ud83d\udcc2\", \"Dump Folder\", \"Minidump folder kholo\", C[\"btn_chip\"], self._bsod_open_dumps),\n            (\"\ud83d\udccb\", \"Dump Copy\", \"Dumps Desktop pe copy karo\", C[\"btn_warn\"], self._bsod_copy_dumps),\n            (\"\ud83d\udcbe\", \"Report Export\", \"BSOD report save karo\", C[\"btn\"], self._bsod_export_report),\n            (\"\ud83e\uddf9\", \"Events Clear\", \"BSOD events clean karo\", C[\"btn_danger\"], self._bsod_clear_events),\n        ], cols=5)\n        body = tk.Frame(content, bg=C[\"bg\"])\n        body.pack(fill=\"both\", expand=True, padx=14, pady=8)\n        left = tk.Frame(body, bg=C[\"card\"])\n        left.pack(side=\"left\", fill=\"both\", expand=True, padx=(0,8))\n        right = tk.Frame(body, bg=C[\"card\"], width=390)\n        right.pack(side=\"right\", fill=\"both\", padx=(8,0))\n        right.pack_propagate(False)\n        wrap, self.bsod_tree = self._adv_tree(left, [\"Date Time\", \"Event ID\", \"Stop Code\", \"Description\"], height=14)\n        wrap.pack(fill=\"both\", expand=True, padx=8, pady=8)\n        self.bsod_tree.bind(\"&lt;&gt;\", self._bsod_on_select)\n        self.bsod_detail = self._scrolled_text(right, height=16)\n        dump_frame = tk.Frame(content, bg=C[\"card\"])\n        dump_frame.pack(fill=\"x\", padx=14, pady=(0,8))\n        wrap2, self.bsod_dump_tree = self._adv_tree(dump_frame, [\"File Naam\", \"Date\", \"Size\"], height=5)\n        wrap2.pack(fill=\"x\", padx=8, pady=8)\n        self.bsod_log = self._scrolled_text(content, height=5)\n        self.bsod_rows = []\n        return frame\n\n    def _bsod_scan(self):\n        self._append_log(self.bsod_log, \"BSOD scan shuru ho raha hai...\", C[\"accent\"])\n        self._launch_job(\"bsod_scan\", self._do_bsod_scan)\n\n    def _do_bsod_scan(self):\n        try:\n            cmd = '''powershell -NoProfile -Command \"Get-WinEvent -FilterHashtable @{LogName='System'; Id=41,1001,6008} -MaxEvents 50 -ErrorAction SilentlyContinue | Select-Object TimeCreated, Id, Message | ConvertTo-Json\"'''\n            out, rc = self._run_cmd(cmd, timeout=120)\n            data = json.loads(out) if out.strip() else []\n            if isinstance(data, dict):\n                data = [data]\n            rows = []\n            for ev in data:\n                msg = ev.get(\"Message\", \"\") or \"\"\n                code = self._bsod_parse_stop_code(msg)\n                desc = \"BugCheck crash\" if str(ev.get(\"Id\")) == \"1001\" else (\"Unexpected shutdown\" if str(ev.get(\"Id\")) == \"6008\" else \"Kernel Power restart\")\n                rows.append({\"time\": str(ev.get(\"TimeCreated\", \"\"))[:19], \"id\": str(ev.get(\"Id\", \"\")), \"code\": code, \"desc\": desc, \"msg\": msg})\n            dumps = []\n            dump_dir = r\"C:\\Windows\\Minidump\"\n            if os.path.isdir(dump_dir):\n                for fn in os.listdir(dump_dir):\n                    if fn.lower().endswith(\".dmp\"):\n                        p = os.path.join(dump_dir, fn)\n                        try:\n                            dumps.append((fn, datetime.datetime.fromtimestamp(os.path.getmtime(p)).strftime(\"%Y-%m-%d %H:%M\"), self._fmt_size_disk(os.path.getsize(p))))\n                        except Exception:\n                            pass\n            self.after(0, lambda: self._bsod_fill(rows, dumps))\n        except Exception as e:\n            self._append_log(self.bsod_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _bsod_fill(self, rows, dumps):\n        self.bsod_rows = rows\n        self.bsod_tree.delete(*self.bsod_tree.get_children())\n        for i, r in enumerate(rows):\n            self.bsod_tree.insert(\"\", \"end\", iid=str(i), values=(r[\"time\"], r[\"id\"], r[\"code\"], r[\"desc\"]))\n        self.bsod_dump_tree.delete(*self.bsod_dump_tree.get_children())\n        for d in dumps:\n            self.bsod_dump_tree.insert(\"\", \"end\", values=d)\n        self._append_log(self.bsod_log, f\"\u2705 Kaam ho gaya: {len(rows)} events aur {len(dumps)} dumps mile\", C[\"success\"])\n\n    def _bsod_parse_stop_code(self, message):\n        try:\n            m = re.search(r\"0x[0-9A-Fa-f]{8}\", message or \"\")\n            return m.group(0).upper() if m else \"Nahi mila\"\n        except Exception:\n            return \"Nahi mila\"\n\n    def _bsod_stop_db(self):\n        return {\n            \"0X0000001A\": (\"MEMORY_MANAGEMENT\", \"RAM faulty hai ya driver memory corrupt kar raha hai\", \"RAM test karo - MemTest86 chalao\"),\n            \"0X0000003B\": (\"SYSTEM_SERVICE_EXCEPTION\", \"Driver ya system service mein error\", \"Recent driver uninstall karo\"),\n            \"0X0000007E\": (\"SYSTEM_THREAD_EXCEPTION\", \"Driver crash - usually graphics ya chipset driver\", \"GPU driver reinstall karo\"),\n            \"0X0000007F\": (\"UNEXPECTED_KERNEL_MODE_TRAP\", \"CPU hardware error ya overclocking\", \"Overclock remove karo, RAM check karo\"),\n            \"0X00000050\": (\"PAGE_FAULT_IN_NONPAGED_AREA\", \"RAM ya driver ne invalid memory access kiya\", \"RAM slots change karo, driver update karo\"),\n            \"0X0000009F\": (\"DRIVER_POWER_STATE_FAILURE\", \"Sleep/hibernate se wake pe driver fail\", \"Power management driver update karo\"),\n            \"0X000000D1\": (\"DRIVER_IRQL_NOT_LESS_OR_EQUAL\", \"Driver ne wrong memory access kiya - faulty driver\", \"Recent installed driver remove karo\"),\n            \"0X000000EF\": (\"CRITICAL_PROCESS_DIED\", \"Windows ka critical process crash ho gaya\", \"SFC /scannow chalao\"),\n            \"0X0000000A\": (\"IRQL_NOT_LESS_OR_EQUAL\", \"Driver IRQ level problem - usually RAM ya driver\", \"RAM test + driver check\"),\n            \"0X00000024\": (\"NTFS_FILE_SYSTEM\", \"NTFS disk corruption - HDD/SSD issue\", \"chkdsk /f /r chalao\"),\n            \"0X0000002E\": (\"DATA_BUS_ERROR\", \"RAM ya motherboard hardware fault\", \"RAM replace karo\"),\n            \"0X00000074\": (\"BAD_SYSTEM_CONFIG_INFO\", \"Registry corrupt hai\", \"Registry repair ya Windows repair chalao\"),\n            \"0X000000C4\": (\"DRIVER_VERIFIER_DETECTED_VIOLATION\", \"Driver Verifier ne faulty driver pakda\", \"Driver Verifier disable karo: verifier /reset\"),\n            \"0XC0000005\": (\"ACCESS_VIOLATION\", \"Program ne invalid memory access kiya\", \"Application reinstall karo\"),\n        }\n\n    def _bsod_on_select(self, event):\n        try:\n            sel = self.bsod_tree.selection()\n            if not sel:\n                return\n            r = self.bsod_rows[int(sel[0])]\n            name, explain, fix = self._bsod_stop_db().get(r[\"code\"].upper(), (\"Unknown Stop Code\", f\"Stop code database mein nahi - online search karo: {r['code']}\", \"Microsoft support aur driver history check karo\"))\n            text = f\"Date/Time: {r['time']}\\nEvent ID: {r['id']}\\nStop Code: {r['code']}\\nNaam: {name}\\n\\nSamjhaav: {explain}\\n\\nFix Steps:\\n1. {fix}\\n2. Recent driver/update check karo\\n3. RAM aur disk health test karo\\n\\nFull Message:\\n{r['msg'][:1200]}\"\n            self.bsod_detail.config(state=\"normal\")\n            self.bsod_detail.delete(\"1.0\", \"end\")\n            self.bsod_detail.insert(\"end\", text)\n            self.bsod_detail.config(state=\"disabled\")\n        except Exception as e:\n            self._append_log(self.bsod_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _bsod_open_dumps(self):\n        try:\n            os.startfile(r\"C:\\Windows\\Minidump\")\n        except Exception as e:\n            self._append_log(self.bsod_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _bsod_copy_dumps(self):\n        self._launch_job(\"bsod_copy_dumps\", self._bsod_copy_dumps_worker)\n\n    def _bsod_copy_dumps_worker(self):\n        try:\n            src = r\"C:\\Windows\\Minidump\"\n            dst = os.path.join(os.environ.get(\"USERPROFILE\", \"\"), \"Desktop\", \"Minidumps\")\n            os.makedirs(dst, exist_ok=True)\n            count = 0\n            if os.path.isdir(src):\n                for fn in os.listdir(src):\n                    if fn.lower().endswith(\".dmp\"):\n                        shutil.copy2(os.path.join(src, fn), os.path.join(dst, fn))\n                        count += 1\n            self._append_log(self.bsod_log, f\"\u2705 Kaam ho gaya: {count} dump files copy ho gaye\", C[\"success\"])\n        except Exception as e:\n            self._append_log(self.bsod_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _bsod_export_report(self):\n        try:\n            path = os.path.join(os.environ.get(\"USERPROFILE\", \"\"), \"Desktop\", f\"Godawari_BSOD_Report_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.txt\")\n            with open(path, \"w\", encoding=\"utf-8\") as f:\n                for r in getattr(self, \"bsod_rows\", []):\n                    f.write(f\"{r['time']} | {r['id']} | {r['code']} | {r['desc']}\\n{r['msg']}\\n\\n\")\n            messagebox.showinfo(\"Kaam ho gaya\", f\"BSOD report save ho gayi:\\n{path}\")\n        except Exception as e:\n            self._append_log(self.bsod_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _bsod_clear_events(self):\n        if messagebox.askyesno(\"Confirm karo\", \"System event log clear karna destructive action hai. Kya continue karna hai?\"):\n            self._launch_job(\"bsod_clear_events\", lambda: self._append_log(self.bsod_log, f\"Result: {self._run_cmd('wevtutil cl System', timeout=60)[0]}\", C[\"warning\"]))\n\n    def _bsod_search_online(self, stop_code):\n        try:\n            os.startfile(f\"https://www.google.com/search?q=BSOD+{stop_code}+fix\")\n        except Exception as e:\n            self._append_log(self.bsod_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _build_corrupt_wizard(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"Corrupt Windows Repair Wizard\", \"Step-by-step SFC, DISM aur CBS analysis\")\n        content = self._scrollable_section_body(frame)\n        self.corrupt_results = {}\n        self.corrupt_indicator = tk.Frame(content, bg=C[\"bg\"])\n        self.corrupt_indicator.pack(fill=\"x\", padx=14, pady=8)\n        self.corrupt_content = tk.Frame(content, bg=C[\"card\"])\n        self.corrupt_content.pack(fill=\"both\", expand=True, padx=14, pady=8)\n        self.corrupt_log = self._scrolled_text(content, height=8)\n        nav = tk.Frame(content, bg=C[\"bg\"])\n        nav.pack(fill=\"x\", padx=14, pady=6)\n        self._btn(nav, \"\u21a9 Back\", C[\"btn_chip\"], self._corrupt_wizard_back).pack(side=\"left\", padx=4)\n        self._btn(nav, \"\u25b6 Next Step\", C[\"btn_info\"], self._corrupt_wizard_next).pack(side=\"left\", padx=4)\n        self._btn(nav, \"\u23ed Skip Step\", C[\"btn_warn\"], self._corrupt_wizard_skip).pack(side=\"left\", padx=4)\n        self._btn(nav, \"\u23f9 Stop\", C[\"btn_danger\"], self._corrupt_wizard_stop).pack(side=\"left\", padx=4)\n        self._corrupt_wizard_show_step(1)\n        return frame\n\n    def _corrupt_wizard_build_step_indicator(self, parent):\n        for w in parent.winfo_children():\n            w.destroy()\n        for i in range(1, 7):\n            color = C[\"accent\"] if i == self._corrupt_wizard_step else (C[\"success\"] if i &lt; self._corrupt_wizard_step else C[\"border\"])\n            tk.Label(parent, text=f\"  {i}  \", font=FONTS[\"subhead\"], fg=C[\"text\"], bg=color).pack(side=\"left\", padx=6, pady=4)\n        tk.Label(parent, text=f\"Step {self._corrupt_wizard_step} of 6\", font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"bg\"]).pack(side=\"left\", padx=14)\n\n    def _corrupt_wizard_show_step(self, step_num):\n        self._corrupt_wizard_step = max(1, min(6, int(step_num)))\n        self._corrupt_wizard_build_step_indicator(self.corrupt_indicator)\n        for w in self.corrupt_content.winfo_children():\n            w.destroy()\n        getattr(self, f\"_corrupt_wizard_build_step{self._corrupt_wizard_step}\")(self.corrupt_content)\n\n    def _corrupt_step_label(self, parent, title, body):\n        tk.Label(parent, text=title, font=(\"Segoe UI\", 16, \"bold\"), fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=14, pady=(14,4))\n        tk.Label(parent, text=body, font=FONTS[\"body\"], fg=C[\"text\"], bg=C[\"card\"], wraplength=900, justify=\"left\").pack(anchor=\"w\", padx=14, pady=(0,10))\n\n    def _corrupt_wizard_build_step1(self, parent):\n        self._corrupt_step_label(parent, \"Pre-Check &amp; Restore Point\", \"Repair shuru karne se pehle admin, free space aur Windows version check hota hai.\")\n        self._btn(parent, \"Pre-check chalao\", C[\"btn_info\"], lambda: self._launch_job(\"corrupt_precheck\", self._corrupt_check_prerequisites)).pack(anchor=\"w\", padx=14)\n        self._btn(parent, \"Restore Point banao\", C[\"btn_warn\"], lambda: self._launch_job(\"corrupt_restore_point\", lambda: self._append_log(self.corrupt_log, self._run_cmd('wmic.exe /Namespace:\\\\\\\\root\\\\default Path SystemRestore Call CreateRestorePoint \"Before Corrupt Windows Repair\", 100, 7', timeout=120)[0], C[\"warning\"]))).pack(anchor=\"w\", padx=14, pady=6)\n\n    def _corrupt_wizard_build_step2(self, parent):\n        self._corrupt_step_label(parent, \"SFC Scan\", \"Windows system files check karta hai aur corrupt files repair karne ki koshish karta hai.\")\n        self._btn(parent, \"Run SFC\", C[\"btn_info\"], lambda: self._launch_job(\"corrupt_sfc_1\", self._do_corrupt_sfc_scan, 2)).pack(anchor=\"w\", padx=14)\n\n    def _corrupt_wizard_build_step3(self, parent):\n        self._corrupt_step_label(parent, \"DISM RestoreHealth\", \"Windows image repair karta hai. Internet connection helpful hota hai.\")\n        self._btn(parent, \"Run DISM\", C[\"btn_danger\"], lambda: self._launch_job(\"corrupt_dism\", self._do_corrupt_dism)).pack(anchor=\"w\", padx=14)\n\n    def _corrupt_wizard_build_step4(self, parent):\n        self._corrupt_step_label(parent, \"SFC Re-scan\", \"DISM ke baad SFC dobara chalao taaki files final verify ho sakein.\")\n        self._btn(parent, \"Run SFC Dobara\", C[\"btn_info\"], lambda: self._launch_job(\"corrupt_sfc_2\", self._do_corrupt_sfc_scan, 4)).pack(anchor=\"w\", padx=14)\n\n    def _corrupt_wizard_build_step5(self, parent):\n        self._corrupt_step_label(parent, \"CBS Log Analysis\", \"CBS.log se exact corrupt file names nikaale jaate hain.\")\n        self._btn(parent, \"Analyze CBS Log\", C[\"btn_chip\"], lambda: self._launch_job(\"corrupt_cbs\", self._do_corrupt_cbs_analysis)).pack(anchor=\"w\", padx=14)\n        wrap, self.corrupt_cbs_tree = self._adv_tree(parent, [\"File Naam\", \"Path\", \"Status\"], height=8)\n        wrap.pack(fill=\"both\", expand=True, padx=14, pady=10)\n\n    def _corrupt_wizard_build_step6(self, parent):\n        self._corrupt_step_label(parent, \"Result &amp; Next Steps\", \"Repair run ka summary aur advanced recovery options.\")\n        for label, cmd in [(\"Open WinRE\", \"reagentc /boottore\"), (\"Safe Mode Enable\", \"bcdedit /set {current} safeboot minimal\"), (\"chkdsk Schedule\", \"chkdsk C: /f /r /x\"), (\"System Reset Option\", \"ms-settings:recovery\")]:\n            self._btn(parent, label, C[\"btn_warn\"], lambda c=cmd: self._run_cmd(c, timeout=120)).pack(side=\"left\", padx=8, pady=12)\n        self._btn(parent, \"Repair Report Save\", C[\"btn\"], self._corrupt_save_report).pack(side=\"left\", padx=8, pady=12)\n\n    def _corrupt_wizard_next(self):\n        self._corrupt_wizard_show_step(self._corrupt_wizard_step + 1)\n\n    def _corrupt_wizard_back(self):\n        self._corrupt_wizard_show_step(self._corrupt_wizard_step - 1)\n\n    def _corrupt_wizard_skip(self):\n        self._append_log(self.corrupt_log, f\"Step {self._corrupt_wizard_step} skip ho gaya\", C[\"warning\"])\n        self._corrupt_wizard_next()\n\n    def _corrupt_wizard_stop(self):\n        self._corrupt_wizard_running = False\n        self._append_log(self.corrupt_log, \"Stop request set ho gaya. Running command khatam hone par rukega.\", C[\"warning\"])\n\n    def _do_corrupt_sfc_scan(self, step):\n        try:\n            self._corrupt_wizard_running = True\n            out, rc = self._run_cmd(\"sfc /scannow\", timeout=3600)\n            result, color = self._corrupt_parse_sfc_result(out)\n            self.corrupt_results[f\"sfc_{step}\"] = result\n            self._append_log(self.corrupt_log, out[-3000:], color)\n            self._append_log(self.corrupt_log, result, color)\n        except Exception as e:\n            self._append_log(self.corrupt_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n        finally:\n            self._corrupt_wizard_running = False\n\n    def _do_corrupt_dism(self):\n        try:\n            out, rc = self._run_cmd(\"DISM /Online /Cleanup-Image /RestoreHealth /NoRestart\", timeout=3600)\n            ok = \"restore operation completed successfully\" in out.lower()\n            self.corrupt_results[\"dism\"] = \"DISM success\" if ok else \"DISM warning\"\n            self._append_log(self.corrupt_log, out[-3000:], C[\"success\"] if ok else C[\"warning\"])\n        except Exception as e:\n            self._append_log(self.corrupt_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _do_corrupt_cbs_analysis(self):\n        try:\n            rows = self._corrupt_parse_cbs_log()\n            def fill():\n                if hasattr(self, \"corrupt_cbs_tree\"):\n                    self.corrupt_cbs_tree.delete(*self.corrupt_cbs_tree.get_children())\n                    for r in rows:\n                        self.corrupt_cbs_tree.insert(\"\", \"end\", values=r)\n                self._append_log(self.corrupt_log, f\"\u2705 Kaam ho gaya: {len(rows)} CBS entries mile\", C[\"success\"] if not rows else C[\"warning\"])\n            self.after(0, fill)\n        except Exception as e:\n            self._append_log(self.corrupt_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _corrupt_parse_sfc_result(self, output):\n        low = (output or \"\").lower()\n        if \"did not find any integrity violations\" in low:\n            return \"\u2705 Corruption nahi mila\", C[\"success\"]\n        if \"found corrupt files and successfully repaired\" in low or \"repaired them\" in low:\n            return \"\u2705 Files automatically fix ho gayi\", C[\"success\"]\n        if \"unable to fix\" in low or \"unable to repair\" in low:\n            return \"\u26a0 Repair needed - Step 3 DISM chalao\", C[\"error\"]\n        if \"could not perform\" in low:\n            return \"\u26a0 Admin mode required ho sakta hai\", C[\"warning\"]\n        return \"SFC result clear nahi hai - log check karo\", C[\"warning\"]\n\n    def _corrupt_parse_cbs_log(self):\n        rows = []\n        path = r\"C:\\Windows\\Logs\\CBS\\CBS.log\"\n        if not os.path.exists(path):\n            return rows\n        with open(path, \"r\", encoding=\"utf-8\", errors=\"ignore\") as f:\n            for line in f:\n                if \"[SR]\" not in line:\n                    continue\n                name = None\n                for pat in [r\"\\[SR\\].*?Cannot repair member file \\[l:.*?\\](.+?),\", r\"\\[SR\\] Repairing (.+?) \\.\", r\"Cannot repair member file.*?\\\\(.+?)$\"]:\n                    m = re.search(pat, line)\n                    if m:\n                        name = m.group(1).strip().strip('\"')\n                        break\n                if name:\n                    rows.append((os.path.basename(name), name, \"CBS mein mention\"))\n                if len(rows) &gt;= 200:\n                    break\n        return rows\n\n    def _corrupt_check_prerequisites(self):\n        try:\n            admin = bool(ctypes.windll.shell32.IsUserAnAdmin())\n            free = shutil.disk_usage(\"C:\\\\\").free\n            ver = platform.platform()\n            self._append_log(self.corrupt_log, f\"Admin: {'Haan' if admin else 'Nahi'}\", C[\"success\"] if admin else C[\"error\"])\n            self._append_log(self.corrupt_log, f\"C free space: {self._fmt_size_disk(free)}\", C[\"success\"] if free &gt; 2*1024*1024*1024 else C[\"error\"])\n            self._append_log(self.corrupt_log, f\"Windows: {ver}\", C[\"accent\"])\n        except Exception as e:\n            self._append_log(self.corrupt_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _corrupt_save_report(self):\n        try:\n            path = os.path.join(os.environ.get(\"USERPROFILE\", \"\"), \"Desktop\", f\"Godawari_Repair_Report_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.txt\")\n            text = self.corrupt_log.get(\"1.0\", \"end\")\n            with open(path, \"w\", encoding=\"utf-8\") as f:\n                f.write(text)\n            messagebox.showinfo(\"Kaam ho gaya\", f\"Repair report save ho gayi:\\n{path}\")\n        except Exception as e:\n            self._append_log(self.corrupt_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _build_password_audit(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"Password &amp; Security Audit\", \"Accounts, firewall, BitLocker aur failed login check\")\n        content = self._scrollable_section_body(frame)\n        self._action_card_grid(content, [\n            (\"\ud83d\udd0d\", \"Full Scan\", \"Poora security audit chalao\", C[\"btn_info\"], self._sec_full_scan),\n            (\"\ud83d\udd12\", \"Firewall On\", \"Saare firewall profiles on karo\", C[\"btn_danger\"], self._sec_enable_firewall),\n            (\"\ud83d\udc65\", \"Guest Fix\", \"Guest account disable karo\", C[\"btn_warn\"], self._sec_fix_guest),\n            (\"\ud83d\udcbe\", \"Report Export\", \"Security report save karo\", C[\"btn\"], self._sec_export_report),\n            (\"\ud83d\udd11\", \"Password Reset\", \"Selected account ka password reset karo\", C[\"btn_chip\"], self._sec_reset_selected_password),\n        ], cols=5)\n        self.sec_summary = tk.Frame(content, bg=C[\"bg\"])\n        self.sec_summary.pack(fill=\"x\", padx=14)\n        self.sec_summary_labels = []\n        for title in [\"Local Accounts\", \"Security Issues\", \"Firewall\", \"BitLocker\"]:\n            card = self._stat_card(self.sec_summary, title, \"Scan pending\", C[\"accent\"])\n            card.pack(side=\"left\", fill=\"x\", expand=True, padx=5, pady=6)\n            self.sec_summary_labels.append(card._value_lbl)\n        nb = ttk.Notebook(content)\n        nb.pack(fill=\"both\", expand=True, padx=14, pady=8)\n        self.sec_trees = {}\n        for tab, cols in {\n            \"Accounts\": [\"Username\", \"Account Type\", \"Status\", \"Password Required\", \"Last Logon\", \"Risk\"],\n            \"Firewall\": [\"Profile\", \"State\", \"Inbound\", \"Outbound\", \"Note\"],\n            \"BitLocker\": [\"Drive\", \"Status\", \"Protection\", \"Encryption\", \"Recovery Key\"],\n            \"Login Events\": [\"Time\", \"Username\", \"Logon Type\", \"Source IP\", \"Reason\"],\n        }.items():\n            pane = tk.Frame(nb, bg=C[\"card\"])\n            nb.add(pane, text=tab)\n            wrap, tree = self._adv_tree(pane, cols, height=10)\n            wrap.pack(fill=\"both\", expand=True, padx=8, pady=8)\n            self.sec_trees[tab] = tree\n        self.sec_reco = self._scrolled_text(content, height=5)\n        self.sec_log = self._scrolled_text(content, height=5)\n        self.sec_data = {}\n        return frame\n\n    def _sec_full_scan(self):\n        self._launch_job(\"security_full_scan\", self._do_sec_full_scan)\n\n    def _do_sec_full_scan(self):\n        try:\n            data = {\"accounts\": self._sec_scan_accounts(), \"firewall\": self._sec_scan_firewall(), \"bitlocker\": self._sec_scan_bitlocker(), \"login\": self._sec_scan_login_events()}\n            self.sec_data = data\n            self.after(0, lambda: (self._sec_populate_accounts_tab(data[\"accounts\"]), self._sec_populate_firewall_tab(data[\"firewall\"]), self._sec_populate_bitlocker_tab(data[\"bitlocker\"]), self._sec_populate_login_tab(data[\"login\"]), self._sec_generate_recommendations(data)))\n        except Exception as e:\n            self._append_log(self.sec_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _sec_scan_accounts(self):\n        out, rc = self._run_cmd('powershell -NoProfile -Command \"Get-LocalUser | Select-Object Name,Enabled,PasswordRequired,LastLogon | ConvertTo-Json\"', timeout=80)\n        users = json.loads(out) if out.strip().startswith((\"{\", \"[\")) else []\n        if isinstance(users, dict):\n            users = [users]\n        admins_out, _ = self._run_cmd(\"net localgroup Administrators\", timeout=40)\n        return {\"users\": users, \"admins_text\": admins_out}\n\n    def _sec_scan_firewall(self):\n        out, rc = self._run_cmd(\"netsh advfirewall show allprofiles\", timeout=60)\n        return out\n\n    def _sec_scan_bitlocker(self):\n        rows = []\n        string_mod = __import__(\"string\")\n        for d in string_mod.ascii_uppercase:\n            drive = f\"{d}:\"\n            if os.path.exists(drive + \"\\\\\"):\n                out, rc = self._run_cmd(f\"manage-bde -status {drive}\", timeout=45)\n                rows.append((drive, out))\n        return rows\n\n    def _sec_scan_login_events(self):\n        out, rc = self._run_cmd(\"powershell -NoProfile -Command \\\"Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4625} -MaxEvents 30 -ErrorAction SilentlyContinue | Select-Object TimeCreated, Message | ConvertTo-Json\\\"\", timeout=90)\n        try:\n            data = json.loads(out) if out.strip() else []\n            return [data] if isinstance(data, dict) else data\n        except Exception:\n            return []\n\n    def _sec_populate_accounts_tab(self, data):\n        tree = self.sec_trees[\"Accounts\"]\n        tree.delete(*tree.get_children())\n        admins = data.get(\"admins_text\", \"\")\n        risks = 0\n        for u in data.get(\"users\", []):\n            name = u.get(\"Name\", \"\")\n            is_admin = name and name.lower() in admins.lower()\n            enabled = bool(u.get(\"Enabled\"))\n            pwd = bool(u.get(\"PasswordRequired\"))\n            risk = \"OK\"\n            if name.lower() == \"guest\" and enabled:\n                risk = \"HIGH\"\n            elif not pwd:\n                risk = \"MEDIUM\"\n            if risk != \"OK\":\n                risks += 1\n            tree.insert(\"\", \"end\", values=(name, \"Admin\" if is_admin else \"User\", \"Enabled\" if enabled else \"Disabled\", \"Haan\" if pwd else \"Nahi\", str(u.get(\"LastLogon\", \"\"))[:19], risk))\n        self.sec_summary_labels[0].config(text=f\"{len(data.get('users', []))} users\")\n        self.sec_summary_labels[1].config(text=f\"{risks} issues\")\n\n    def _sec_populate_firewall_tab(self, data):\n        tree = self.sec_trees[\"Firewall\"]\n        tree.delete(*tree.get_children())\n        on_count = len(re.findall(r\"State\\s+ON\", data, re.I))\n        for profile in [\"Domain\", \"Private\", \"Public\"]:\n            m = re.search(profile + r\".*?State\\s+(\\w+).*?Firewall Policy\\s+([^\\r\\n]+)\", data, re.I | re.S)\n            state = m.group(1) if m else \"Unknown\"\n            policy = m.group(2) if m else \"Nahi mila\"\n            tree.insert(\"\", \"end\", values=(profile, state, policy, policy, \"Firewall profile\"))\n        self.sec_summary_labels[2].config(text=\"All ON\" if on_count &gt;= 3 else \"Partially OFF\")\n\n    def _sec_populate_bitlocker_tab(self, data):\n        tree = self.sec_trees[\"BitLocker\"]\n        tree.delete(*tree.get_children())\n        protected = 0\n        for drive, out in data:\n            conv = re.search(r\"Conversion Status:\\s+(.+)\", out)\n            prot = re.search(r\"Protection Status:\\s+(.+)\", out)\n            enc = re.search(r\"Encryption Method:\\s+(.+)\", out)\n            ptxt = prot.group(1).strip() if prot else \"Unknown\"\n            if \"On\" in ptxt:\n                protected += 1\n            tree.insert(\"\", \"end\", values=(drive, conv.group(1).strip() if conv else \"Unknown\", ptxt, enc.group(1).strip() if enc else \"Unknown\", \"Check needed\"))\n        self.sec_summary_labels[3].config(text=f\"{protected}/{len(data)} protected\")\n\n    def _sec_populate_login_tab(self, data):\n        tree = self.sec_trees[\"Login Events\"]\n        tree.delete(*tree.get_children())\n        for ev in data:\n            msg = ev.get(\"Message\", \"\") or \"\"\n            user = re.search(r\"Account Name:\\s+([^\\r\\n]+)\", msg)\n            typ = re.search(r\"Logon Type:\\s+(\\d+)\", msg)\n            ip = re.search(r\"Source Network Address:\\s+([^\\r\\n]+)\", msg)\n            reason = re.search(r\"Failure Reason:\\s+([^\\r\\n]+)\", msg)\n            tree.insert(\"\", \"end\", values=(str(ev.get(\"TimeCreated\", \"\"))[:19], user.group(1).strip() if user else \"Nahi mila\", typ.group(1) if typ else \"Nahi\", ip.group(1).strip() if ip else \"-\", reason.group(1).strip() if reason else \"-\"))\n\n    def _sec_generate_recommendations(self, all_data):\n        recs = []\n        users = all_data.get(\"accounts\", {}).get(\"users\", [])\n        guest = [u for u in users if str(u.get(\"Name\", \"\")).lower() == \"guest\" and u.get(\"Enabled\")]\n        no_pwd = [u.get(\"Name\") for u in users if not u.get(\"PasswordRequired\")]\n        if guest:\n            recs.append(\"\u274c Guest account immediately disable karo\")\n        if no_pwd:\n            recs.append(\"\u274c In accounts ko password lagao: \" + \", \".join(map(str, no_pwd)))\n        if \"State                                 OFF\" in all_data.get(\"firewall\", \"\"):\n            recs.append(\"\u274c Windows Firewall enable karo\")\n        if not recs:\n            recs.append(\"\u2705 Major security issue nahi mila\")\n        self.sec_reco.config(state=\"normal\")\n        self.sec_reco.delete(\"1.0\", \"end\")\n        self.sec_reco.insert(\"end\", \"\\n\".join(recs))\n        self.sec_reco.config(state=\"disabled\")\n        self._append_log(self.sec_log, \"\u2705 Kaam ho gaya: Security audit complete\", C[\"success\"])\n\n    def _sec_enable_firewall(self):\n        if messagebox.askyesno(\"Confirm karo\", \"Saare firewall profiles ON karne hain?\"):\n            self._launch_job(\"sec_firewall_on\", lambda: self._append_log(self.sec_log, self._run_cmd(\"netsh advfirewall set allprofiles state on\", timeout=60)[0], C[\"success\"]))\n\n    def _sec_fix_guest(self):\n        if messagebox.askyesno(\"Confirm karo\", \"Guest account disable karna hai?\"):\n            self._launch_job(\"sec_guest_fix\", lambda: self._append_log(self.sec_log, self._run_cmd(\"net user Guest /active:no\", timeout=60)[0], C[\"success\"]))\n\n    def _sec_export_report(self):\n        try:\n            path = os.path.join(os.environ.get(\"USERPROFILE\", \"\"), \"Desktop\", f\"Godawari_Security_Report_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.json\")\n            with open(path, \"w\", encoding=\"utf-8\") as f:\n                json.dump(getattr(self, \"sec_data\", {}), f, indent=2, ensure_ascii=False, default=str)\n            messagebox.showinfo(\"Kaam ho gaya\", f\"Security report save ho gayi:\\n{path}\")\n        except Exception as e:\n            self._append_log(self.sec_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _sec_account_action(self, action, username):\n        cmds = {\"enable\": f\"net user {username} /active:yes\", \"disable\": f\"net user {username} /active:no\", \"require_password\": f\"net user {username} /passwordreq:yes\", \"remove_admin\": f\"net localgroup Administrators {username} /delete\"}\n        if action in cmds and messagebox.askyesno(\"Confirm karo\", f\"{username} par action apply karna hai?\"):\n            self._launch_job(\"sec_account_action\", lambda: self._append_log(self.sec_log, self._run_cmd(cmds[action], timeout=60)[0], C[\"warning\"]))\n\n    def _sec_reset_selected_password(self):\n        \"\"\"Reset password for selected account. PASSWORD FIELD IS OPTIONAL.\n        \n        ENGINEERING FIX #2: Allow empty password input to be treated as 'skip' or 'no-password mode'.\n        Empty input no longer triggers a validation error - user can choose to skip password reset.\n        \"\"\"\n        try:\n            tree = self.sec_trees.get(\"Accounts\") if hasattr(self, \"sec_trees\") else None\n            if tree is None:\n                messagebox.showwarning(\"Account select karo\", \"Pehle Security Scan chalao aur account select karo\")\n                return\n            sel = tree.selection()\n            if not sel:\n                messagebox.showwarning(\"Account select karo\", \"Pehle Accounts tab mein user select karo\")\n                return\n            username = tree.item(sel[0], \"values\")[0]\n            if not username:\n                messagebox.showwarning(\"User nahi mila\", \"Selected account ka username nahi mila\")\n                return\n            \n            simpledialog = __import__(\"tkinter.simpledialog\", fromlist=[\"askstring\"])\n            \n            # FIX: Password is now OPTIONAL - user can enter empty password to skip\n            new_password = simpledialog.askstring(\n                \"Naya password\",\n                f\"{username} ke liye naya password daalo:\\n\\n(Khali chhod ke OK karo to skip ho jayega)\",\n                show=\"*\"\n            )\n            if new_password is None:\n                # User clicked Cancel - operation aborted\n                return\n            \n            # FIX: Empty password is now ACCEPTED as 'skip' or 'no-password' mode\n            if not new_password:\n                # User entered empty password - ask if they want to skip OR set no password\n                choice = messagebox.askyesnocancel(\n                    \"Password Reset - Confirmation\",\n                    f\"Blank password entry for {username}:\\n\\n\"\n                    \"Yes = Set empty password (no-password mode)\\n\"\n                    \"No = Skip this account\\n\"\n                    \"Cancel = Go back and enter password\"\n                )\n                if choice is None:\n                    # User clicked Cancel - go back to ask for password again\n                    self._sec_reset_selected_password()\n                    return\n                elif choice is False:\n                    # User clicked No - skip this account\n                    messagebox.showinfo(\"Skipped\", f\"Password reset skipped for {username}\")\n                    return\n                # choice is True - proceed with empty password (no-password mode)\n            else:\n                # User entered a password - confirm it\n                confirm_password = simpledialog.askstring(\n                    \"Password confirm\",\n                    \"Naya password dobara daalo:\",\n                    show=\"*\"\n                )\n                if confirm_password is None:\n                    return\n                if new_password != confirm_password:\n                    messagebox.showerror(\"Password match nahi\", \"Dono password same nahi hain\")\n                    return\n                if len(new_password) &lt; 6:\n                    if not messagebox.askyesno(\"Password weak hai\", \"Password 6 characters se chhota hai. Kya phir bhi set karna hai?\"):\n                        return\n            \n            # Final confirmation before executing password reset\n            mode_text = \"no-password mode\" if not new_password else \"set karna\"\n            if not messagebox.askyesno(\"Kya aap sure hain?\", f\"{username} ka password {mode_text} hai? Confirm karo?\"):\n                return\n            \n            self._launch_job(\"sec_password_reset\", self._do_sec_reset_password, username, new_password)\n        except Exception as e:\n            self._append_log(self.sec_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _do_sec_reset_password(self, username, new_password):\n        \"\"\"Execute password reset for the user account.\n        \n        ENGINEERING FIX #3: Handles both regular passwords AND empty passwords (no-password mode).\n        Empty password is accepted and processed without error.\n        \"\"\"\n        try:\n            # FIX: Support empty password for no-password mode\n            if new_password == \"\":\n                # No-password mode: set empty password using PowerShell\n                cmd = (\n                    f\"powershell -NoProfile -Command \"\n                    f'\"$user = [ADSI](\\'WinNT://./\\' + \\'{username}\\'); '\n                    f'$user.SetPassword(\\'\\'); $user.CommitChanges()\"'\n                )\n                out, rc = self._run_cmd(cmd, timeout=60)\n                success_msg = f\"\u2705 No-password mode set for {username}\"\n                user_msg = f\"No-password mode activated for {username}\"\n            else:\n                # Regular password reset using net user command\n                out, rc = self._run_cmd([\"net\", \"user\", username, new_password], timeout=60)\n                success_msg = f\"\u2705 Kaam ho gaya: {username} ka password reset ho gaya\"\n                user_msg = f\"{username} ka password reset ho gaya\"\n            \n            if rc == 0:\n                self._append_log(self.sec_log, success_msg, C[\"success\"])\n                self.after(0, lambda m=user_msg: messagebox.showinfo(\"Kaam ho gaya\", m))\n                self.after(500, self._sec_full_scan)\n            else:\n                error_text = out[:300] if out else \"Unknown error\"\n                self._append_log(self.sec_log, f\"Password reset nahi hua: {error_text}\", C[\"error\"])\n                self.after(0, lambda: messagebox.showerror(\n                    \"Password reset nahi hua\",\n                    f\"{username} ka password reset nahi hua.\\n{error_text}\"\n                ))\n        except Exception as e:\n            self._append_log(self.sec_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _build_auto_backup(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"Auto Backup\", \"Sources, destination, schedule aur registry backup\")\n        content = self._scrollable_section_body(frame)\n        top = tk.Frame(content, bg=C[\"bg\"])\n        top.pack(fill=\"x\", padx=14, pady=8)\n        src = self._adv_card(top, \"Backup Sources\")\n        src.pack(side=\"left\", fill=\"both\", expand=True, padx=(0,8))\n        self.backup_source_list = tk.Listbox(src, bg=C[\"card\"], fg=C[\"text\"], selectbackground=C[\"accent\"], height=8)\n        self.backup_source_list.pack(fill=\"both\", expand=True, padx=8, pady=8)\n        user = os.environ.get(\"USERPROFILE\", \"\")\n        if not self.backup_sources:\n            self.backup_sources = [os.path.join(user, x) for x in [\"Desktop\", \"Documents\", \"Downloads\", \"Pictures\"] if os.path.exists(os.path.join(user, x))]\n        for p in self.backup_sources:\n            self.backup_source_list.insert(\"end\", p)\n        self._btn(src, \"Custom Folder Add\", C[\"btn_chip\"], lambda: self._backup_add_source()).pack(side=\"left\", padx=8, pady=4)\n        self._btn(src, \"Selected Remove\", C[\"btn_warn\"], lambda: self._backup_remove_source()).pack(side=\"left\", padx=8, pady=4)\n        dst = self._adv_card(top, \"Destination &amp; Schedule\")\n        dst.pack(side=\"right\", fill=\"both\", expand=True, padx=(8,0))\n        tk.Entry(dst, textvariable=self.backup_dest_var, bg=C[\"panel\"], fg=C[\"text\"]).pack(fill=\"x\", padx=8, pady=4)\n        self._btn(dst, \"Browse\", C[\"btn_chip\"], lambda: self.backup_dest_var.set(filedialog.askdirectory() or self.backup_dest_var.get())).pack(anchor=\"w\", padx=8)\n        ttk.Combobox(dst, textvariable=self.backup_schedule_var, values=[\"Manual Only\", \"Daily\", \"Weekly\", \"Monthly\"], state=\"readonly\").pack(fill=\"x\", padx=8, pady=4)\n        tk.Entry(dst, textvariable=self.backup_time_var, bg=C[\"panel\"], fg=C[\"text\"]).pack(fill=\"x\", padx=8, pady=4)\n        modes = self._adv_card(content, \"\ud83d\udcc1 Overwrite Mode - Backup Size Control\")\n        modes.pack(fill=\"x\", padx=14, pady=6)\n        for val, txt in [(\"mirror\", \"\u267b Overwrite Previous (Mirror) - size same rahega\"), (\"versioned\", \"\ud83d\udcc5 Keep Last N Versions - purane auto delete\"), (\"incremental\", \"\u26a1 Incremental - sirf changed files\")]:\n            tk.Radiobutton(modes, text=txt, variable=self.backup_overwrite_mode, value=val, bg=C[\"card\"], fg=C[\"text\"], selectcolor=C[\"panel\"], activebackground=C[\"card\"]).pack(anchor=\"w\", padx=8)\n        tk.Spinbox(modes, from_=1, to=10, textvariable=self.backup_keep_n, width=5, bg=C[\"panel\"], fg=C[\"text\"]).pack(anchor=\"w\", padx=28, pady=2)\n        reg = self._adv_card(content, \"\ud83d\uddc2 Registry Auto-Backup (RegBack)\")\n        reg.pack(fill=\"x\", padx=14, pady=6)\n        tk.Checkbutton(reg, text=\"RegBack enable rakho\", variable=self.regback_enabled, bg=C[\"card\"], fg=C[\"text\"], selectcolor=C[\"panel\"]).pack(anchor=\"w\", padx=8)\n        tk.Label(reg, text=\"Windows crash ho jaaye to restore ke liye SYSTEM, SOFTWARE, SAM, SECURITY, DEFAULT hives backup honge\", fg=C[\"warning\"], bg=C[\"card\"], font=FONTS[\"small\"], wraplength=1050, justify=\"left\").pack(anchor=\"w\", padx=8)\n        self._action_card_grid(content, [\n            (\"\u25b6\", \"Backup Now\", \"Abhi backup chalao\", C[\"btn_info\"], self._backup_run_now),\n            (\"\ud83d\udcc5\", \"Schedule Enable\", \"Task Scheduler mein add karo\", C[\"btn_chip\"], self._backup_schedule_enable),\n            (\"\u274c\", \"Schedule Remove\", \"Scheduled task hatao\", C[\"btn_warn\"], self._backup_schedule_remove),\n            (\"\ud83d\udcc2\", \"Folder Kholo\", \"Backup folder kholo\", C[\"accent2\"], self._backup_open_folder),\n            (\"\ud83d\udcbe\", \"Config Save\", \"Settings save karo\", C[\"btn\"], self._backup_save_config),\n            (\"\ud83d\udcc2\", \"Config Load\", \"Settings load karo\", C[\"btn_chip\"], self._backup_load_config),\n        ], cols=6)\n        # \u2500\u2500 Progress bar \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        prog_card = self._adv_card(content, \"\ud83d\udcca Backup Progress\")\n        prog_card.pack(fill=\"x\", padx=14, pady=4)\n        self.backup_progress_var = tk.DoubleVar(value=0.0)\n        self.backup_progress_bar = ttk.Progressbar(\n            prog_card, variable=self.backup_progress_var,\n            maximum=100, mode=\"determinate\")\n        self.backup_progress_bar.pack(fill=\"x\", padx=12, pady=(4, 2))\n        self.backup_status_lbl = tk.Label(\n            prog_card, text=\"Ready \u2014 'Backup Now' press karo\",\n            font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"])\n        self.backup_status_lbl.pack(anchor=\"w\", padx=12, pady=(0, 6))\n        # \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        wrap, self.backup_history_tree = self._adv_tree(content, [\"#\", \"Date Time\", \"Mode\", \"Sources\", \"Destination\", \"Total Size\", \"Status\", \"Duration\"], height=6)\n        wrap.pack(fill=\"x\", padx=14, pady=6)\n        self.backup_log = self._scrolled_text(content, height=6)\n        self._backup_load_config(silent=True)\n        self._backup_refresh_history()\n        return frame\n\n    def _backup_add_source(self):\n        p = filedialog.askdirectory()\n        if p:\n            self.backup_sources.append(p)\n            self.backup_source_list.insert(\"end\", p)\n\n    def _backup_remove_source(self):\n        try:\n            idx = self.backup_source_list.curselection()\n            if idx:\n                self.backup_sources.pop(idx[0])\n                self.backup_source_list.delete(idx[0])\n        except Exception as e:\n            self._append_log(self.backup_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _backup_run_now(self):\n        try:\n            dest = self.backup_dest_var.get().strip()\n            sources = self._backup_get_selected_sources()\n            mode = self.backup_overwrite_mode.get()\n            keep_n = int(self.backup_keep_n.get())\n            regback = bool(self.regback_enabled.get())\n            self._launch_job(\"auto_backup_now\", self._do_run_backup, dest, sources, mode, keep_n, regback)\n        except Exception as e:\n            self._append_log(self.backup_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _do_run_backup(self, dest=None, sources=None, mode=None, keep_n=None, regback_enabled=None):\n        def _set_status(msg, pct=None, color=None):\n            try:\n                self.after(0, lambda m=msg, c=color or C[\"text_dim\"]:\n                           self.backup_status_lbl.config(text=m, fg=c)\n                           if False else None)\n                self.after(0, lambda m=msg, c=color or C[\"text_dim\"]:\n                           self.backup_status_lbl.config(text=m, fg=c))\n                if pct is not None:\n                    self.after(0, lambda p=float(pct): self.backup_progress_var.set(p))\n            except Exception:\n                pass\n\n        def _set_indeterminate(on=True):\n            try:\n                if on:\n                    self.after(0, lambda: self.backup_progress_bar.config(mode=\"indeterminate\"))\n                    self.after(50, lambda: self.backup_progress_bar.start(12))\n                else:\n                    self.after(0, lambda: self.backup_progress_bar.stop())\n                    self.after(0, lambda: self.backup_progress_bar.config(mode=\"determinate\"))\n            except Exception:\n                pass\n\n        try:\n            dest = (dest or \"\").strip()\n            sources = list(sources or [])\n            if not dest or not os.path.isdir(dest):\n                self._append_log(self.backup_log, \"Pehle valid destination folder select karo\", C[\"error\"])\n                _set_status(\"\u274c Destination folder invalid hai\", color=C[\"error\"])\n                return\n            if not sources:\n                self._append_log(self.backup_log, \"Pehle backup source select karo\", C[\"error\"])\n                _set_status(\"\u274c Koi source select nahi kiya\", color=C[\"error\"])\n                return\n\n            start = time.time()\n            timestamp = datetime.datetime.now().strftime(\"%Y-%m-%d_%H-%M\")\n            mode = mode or \"mirror\"\n            base_dest = dest\n            if mode == \"versioned\":\n                base_dest = os.path.join(dest, f\"Backup_{timestamp}\")\n                os.makedirs(base_dest, exist_ok=True)\n\n            total_sources = len([s for s in sources if os.path.isdir(s)])\n            done_sources = 0\n\n            for source in sources:\n                if not os.path.isdir(source):\n                    self._append_log(self.backup_log, f\"\u26a0\ufe0f Skipped (not found): {source}\", C[\"warning\"])\n                    continue\n\n                src_name = os.path.basename(source.rstrip(\"\\\\/\")) or source\n                dest_sub = os.path.join(base_dest, src_name)\n\n                # Pre-count files for determinate progress\n                try:\n                    file_count = sum(len(files) for _, _, files in os.walk(source))\n                except Exception:\n                    file_count = 0\n\n                _set_status(f\"\ud83d\udcc2 Copying: {src_name}  ({done_sources+1}/{total_sources})  [{file_count} files]\",\n                            pct=(done_sources / max(1, total_sources)) * 85, color=C[\"accent4\"])\n                self._append_log(self.backup_log,\n                                 f\"\u25b6 Source: {source}  \u2192  {dest_sub}  ({file_count} files)\",\n                                 C[\"accent4\"])\n\n                flag = \"/MIR\" if mode == \"mirror\" else (\"/XO /E\" if mode == \"incremental\" else \"/E\")\n\n                # Stream robocopy output line by line for live feedback\n                try:\n                    startupinfo = subprocess.STARTUPINFO()\n                    startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW\n                    proc = subprocess.Popen(\n                        f'robocopy \"{source}\" \"{dest_sub}\" {flag} /R:2 /W:5 /NP /TEE',\n                        shell=True,\n                        stdout=subprocess.PIPE,\n                        stderr=subprocess.STDOUT,\n                        text=True,\n                        startupinfo=startupinfo,\n                    )\n                    copied = 0\n                    for line in proc.stdout:\n                        line = line.strip()\n                        if not line:\n                            continue\n                        # robocopy progress lines contain file names\n                        if any(x in line.lower() for x in [\"new file\", \"newer\", \"extra\", \"copying\"]):\n                            copied += 1\n                            if copied % 5 == 0 or file_count &lt;= 20:\n                                _set_status(\n                                    f\"\ud83d\udcc2 {src_name}: {copied} files copied\u2026\",\n                                    pct=min(85, (done_sources / max(1, total_sources)) * 85 +\n                                            min(15, (copied / max(1, file_count)) * 15)),\n                                    color=C[\"accent4\"]\n                                )\n                        # Log important lines only\n                        if any(x in line for x in [\"ERROR\", \"WARN\", \"Access is denied\", \"Failed\"]):\n                            self._append_log(self.backup_log, f\"  \u26a0\ufe0f {line}\", C[\"warning\"])\n                    rc = proc.wait()\n                except Exception as pex:\n                    rc = -1\n                    self._append_log(self.backup_log, f\"\u26a0\ufe0f robocopy error: {pex}\", C[\"warning\"])\n\n                color = C[\"success\"] if rc &lt; 8 else C[\"warning\"]\n                self._append_log(self.backup_log,\n                                 f\"  \u2705 {src_name}: robocopy exit code {rc}  ({copied if 'copied' in dir() else '?'} files copied)\",\n                                 color)\n                done_sources += 1\n\n            # Versioned: cleanup old backups\n            if mode == \"versioned\":\n                glob_mod = __import__(\"glob\")\n                versions = sorted(glob_mod.glob(os.path.join(dest, \"Backup_*\")))\n                while len(versions) &gt; int(keep_n or 3):\n                    shutil.rmtree(versions.pop(0), ignore_errors=True)\n\n            # Registry backup\n            _set_status(\"\ud83d\uddc2 Registry backup chal raha hai\u2026\", pct=88, color=C[\"accent4\"])\n            reg_backup_path = \"\"\n            if bool(regback_enabled):\n                reg_backup_path = self._do_regback_backup(base_dest) or \"\"\n\n            # Final size\n            _set_status(\"\ud83d\udcca Size calculate ho raha hai\u2026\", pct=95, color=C[\"text_dim\"])\n            total = self._backup_calculate_size(base_dest)\n            dur = time.time() - start\n            status = \"Files + Registry\" if reg_backup_path else \"Files only\"\n\n            self._backup_add_history({\n                \"dt\": datetime.datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\"),\n                \"mode\": mode,\n                \"sources\": len(sources),\n                \"dest\": base_dest,\n                \"size\": f\"{total:.1f} MB\",\n                \"status\": status,\n                \"duration\": f\"{dur:.1f}s\"\n            })\n\n            _set_status(f\"\u2705 Backup complete! {total:.1f} MB  \u2022  {dur:.1f}s\", pct=100, color=C[\"success\"])\n            self._append_log(self.backup_log, f\"\u2705 Kaam ho gaya: Backup complete  [{total:.1f} MB, {dur:.1f}s]\", C[\"success\"])\n            if reg_backup_path:\n                self._append_log(self.backup_log, f\"Registry recovery backup: {reg_backup_path}\", C[\"success\"])\n            self.after(0, lambda: messagebox.showinfo(\"Kaam ho gaya\", f\"\u2705 Backup complete!\\n\\nSize: {total:.1f} MB\\nTime: {dur:.1f}s\\nDest: {base_dest}\"))\n\n        except Exception as e:\n            _set_indeterminate(False)\n            _set_status(f\"\u274c Error: {e}\", pct=0, color=C[\"error\"])\n            self._append_log(self.backup_log, f\"\u274c Error aaya: {str(e)}\", C[\"error\"])\n\n    def _do_regback_backup(self, dest_folder):\n        try:\n            stamp = datetime.datetime.now().strftime(\"%Y-%m-%d_%H-%M-%S\")\n            reg_dest = os.path.join(dest_folder, f\"Registry_Recovery_{stamp}\")\n            os.makedirs(reg_dest, exist_ok=True)\n            regback = r\"C:\\Windows\\System32\\config\\RegBack\"\n            names = [\"DEFAULT\", \"SAM\", \"SECURITY\", \"SOFTWARE\", \"SYSTEM\"]\n            manifest = {\n                \"created_at\": datetime.datetime.now().isoformat(timespec=\"seconds\"),\n                \"machine\": platform.node(),\n                \"windows\": platform.platform(),\n                \"method\": \"\",\n                \"files\": [],\n                \"restore_note\": \"WinRE Command Prompt se restore karne ke liye RESTORE_GUIDE_HINGLISH.txt padho.\",\n            }\n            if os.path.exists(os.path.join(regback, \"SYSTEM\")) and os.path.getsize(os.path.join(regback, \"SYSTEM\")) &gt; 0:\n                manifest[\"method\"] = \"RegBack folder copy\"\n                for n in names:\n                    src = os.path.join(regback, n)\n                    if os.path.exists(src):\n                        dst = os.path.join(reg_dest, f\"{n}.hiv\")\n                        shutil.copy2(src, dst)\n                        manifest[\"files\"].append(self._backup_registry_file_info(dst, n))\n                        self._append_log(self.backup_log, f\"{n} hive backup ho gaya\", C[\"success\"])\n            else:\n                manifest[\"method\"] = \"Live reg save\"\n                hive_cmds = [\n                    (\"SYSTEM\", \"HKLM\\\\SYSTEM\"),\n                    (\"SOFTWARE\", \"HKLM\\\\SOFTWARE\"),\n                    (\"SAM\", \"HKLM\\\\SAM\"),\n                    (\"SECURITY\", \"HKLM\\\\SECURITY\"),\n                    (\"DEFAULT\", \"HKU\\\\.DEFAULT\"),\n                ]\n                for hive_name, hive_key in hive_cmds:\n                    dst = os.path.join(reg_dest, f\"{hive_name}.hiv\")\n                    out, rc = self._run_cmd(f'reg save \"{hive_key}\" \"{dst}\" /y', timeout=180)\n                    if rc == 0 and os.path.exists(dst):\n                        manifest[\"files\"].append(self._backup_registry_file_info(dst, hive_name))\n                        self._append_log(self.backup_log, f\"{hive_name} hive backup ho gaya\", C[\"success\"])\n                    else:\n                        self._append_log(self.backup_log, f\"{hive_name} hive backup nahi hua: {out[:200]}\", C[\"warning\"])\n            self._backup_write_registry_restore_guide(reg_dest, manifest)\n            with open(os.path.join(reg_dest, \"registry_manifest.json\"), \"w\", encoding=\"utf-8\") as f:\n                json.dump(manifest, f, indent=2, ensure_ascii=False)\n            self._append_log(self.backup_log, \"Registry crash-recovery backup complete ho gaya\", C[\"success\"])\n            return reg_dest\n        except Exception as e:\n            self._append_log(self.backup_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n            return \"\"\n\n    def _backup_registry_file_info(self, path, hive_name):\n        try:\n            h = hashlib.sha256()\n            with open(path, \"rb\") as f:\n                for chunk in iter(lambda: f.read(1024 * 1024), b\"\"):\n                    h.update(chunk)\n            return {\n                \"hive\": hive_name,\n                \"file\": os.path.basename(path),\n                \"size_bytes\": os.path.getsize(path),\n                \"sha256\": h.hexdigest(),\n            }\n        except Exception as e:\n            return {\n                \"hive\": hive_name,\n                \"file\": os.path.basename(path),\n                \"size_bytes\": 0,\n                \"error\": str(e),\n            }\n\n    def _backup_write_registry_restore_guide(self, reg_dest, manifest):\n        try:\n            guide = os.path.join(reg_dest, \"RESTORE_GUIDE_HINGLISH.txt\")\n            lines = [\n                \"Godawari Computers - Registry Crash Recovery Guide\",\n                \"\",\n                \"Kab use kare:\",\n                \"- Windows boot nahi ho raha ho aur registry corrupt ka doubt ho.\",\n                \"- Pehle customer ka data backup verify karo.\",\n                \"- Ye advanced recovery hai. Galat hive restore karne se Windows aur kharab ho sakta hai.\",\n                \"\",\n                \"WinRE se restore ka tarika:\",\n                \"1. Windows Recovery Environment open karo.\",\n                \"2. Troubleshoot &gt; Advanced options &gt; Command Prompt kholo.\",\n                \"3. Windows drive letter confirm karo. WinRE mein C: kabhi-kabhi D: hota hai.\",\n                \"   Command: bcdedit | find \\\"osdevice\\\"\",\n                \"4. Existing registry hives ka backup banao:\",\n                \"   mkdir C:\\\\Windows\\\\System32\\\\config\\\\Godawari_BadRegistry_Backup\",\n                \"   copy C:\\\\Windows\\\\System32\\\\config\\\\SYSTEM C:\\\\Windows\\\\System32\\\\config\\\\Godawari_BadRegistry_Backup\\\\SYSTEM.bad\",\n                \"   copy C:\\\\Windows\\\\System32\\\\config\\\\SOFTWARE C:\\\\Windows\\\\System32\\\\config\\\\Godawari_BadRegistry_Backup\\\\SOFTWARE.bad\",\n                \"   copy C:\\\\Windows\\\\System32\\\\config\\\\SAM C:\\\\Windows\\\\System32\\\\config\\\\Godawari_BadRegistry_Backup\\\\SAM.bad\",\n                \"   copy C:\\\\Windows\\\\System32\\\\config\\\\SECURITY C:\\\\Windows\\\\System32\\\\config\\\\Godawari_BadRegistry_Backup\\\\SECURITY.bad\",\n                \"   copy C:\\\\Windows\\\\System32\\\\config\\\\DEFAULT C:\\\\Windows\\\\System32\\\\config\\\\Godawari_BadRegistry_Backup\\\\DEFAULT.bad\",\n                \"\",\n                \"5. Is backup folder se hives restore karo. BACKUP_PATH ko actual path se replace karo:\",\n                \"   copy /y BACKUP_PATH\\\\SYSTEM.hiv C:\\\\Windows\\\\System32\\\\config\\\\SYSTEM\",\n                \"   copy /y BACKUP_PATH\\\\SOFTWARE.hiv C:\\\\Windows\\\\System32\\\\config\\\\SOFTWARE\",\n                \"   copy /y BACKUP_PATH\\\\SAM.hiv C:\\\\Windows\\\\System32\\\\config\\\\SAM\",\n                \"   copy /y BACKUP_PATH\\\\SECURITY.hiv C:\\\\Windows\\\\System32\\\\config\\\\SECURITY\",\n                \"   copy /y BACKUP_PATH\\\\DEFAULT.hiv C:\\\\Windows\\\\System32\\\\config\\\\DEFAULT\",\n                \"\",\n                \"6. Restart karo:\",\n                \"   wpeutil reboot\",\n                \"\",\n                \"Important:\",\n                \"- Agar backup external drive par hai to pehle drive letter check karo: diskpart &gt; list volume\",\n                \"- SYSTEM aur SOFTWARE hives same backup set se restore karo.\",\n                \"- BitLocker enabled ho to recovery key ki zaroorat pad sakti hai.\",\n                \"\",\n                f\"Backup created at: {manifest.get('created_at', '')}\",\n                f\"Machine: {manifest.get('machine', '')}\",\n                f\"Windows: {manifest.get('windows', '')}\",\n                f\"Backup method: {manifest.get('method', '')}\",\n                \"\",\n                \"Files:\",\n            ]\n            for item in manifest.get(\"files\", []):\n                lines.append(f\"- {item.get('hive')}: {item.get('file')} | {item.get('size_bytes')} bytes | sha256 {item.get('sha256', '')}\")\n            with open(guide, \"w\", encoding=\"utf-8\") as f:\n                f.write(\"\\n\".join(lines))\n        except Exception as e:\n            self._append_log(self.backup_log, f\"Restore guide banane mein error aaya: {str(e)}\", C[\"warning\"])\n\n    def _backup_config_data(self):\n        return {\"sources\": self.backup_sources, \"dest\": self.backup_dest_var.get(), \"schedule\": self.backup_schedule_var.get(), \"time\": self.backup_time_var.get(), \"mode\": self.backup_overwrite_mode.get(), \"keep_n\": self.backup_keep_n.get(), \"regback\": self.regback_enabled.get(), \"history\": getattr(self, \"backup_history\", [])}\n\n    def _backup_save_config(self):\n        try:\n            os.makedirs(os.path.dirname(self.backup_config_file), exist_ok=True)\n            with open(self.backup_config_file, \"w\", encoding=\"utf-8\") as f:\n                json.dump(self._backup_config_data(), f, indent=2, ensure_ascii=False)\n            self._append_log(self.backup_log, \"\u2705 Kaam ho gaya: Config save ho gaya\", C[\"success\"])\n        except Exception as e:\n            self._append_log(self.backup_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _backup_load_config(self, silent=False):\n        try:\n            if os.path.exists(self.backup_config_file):\n                with open(self.backup_config_file, \"r\", encoding=\"utf-8\") as f:\n                    data = json.load(f)\n                self.backup_sources = data.get(\"sources\", self.backup_sources)\n                self.backup_dest_var.set(data.get(\"dest\", \"\"))\n                self.backup_schedule_var.set(data.get(\"schedule\", \"Manual Only\"))\n                self.backup_time_var.set(data.get(\"time\", \"02:00\"))\n                self.backup_overwrite_mode.set(data.get(\"mode\", \"mirror\"))\n                self.backup_keep_n.set(int(data.get(\"keep_n\", 3)))\n                self.regback_enabled.set(bool(data.get(\"regback\", True)))\n                self.backup_history = data.get(\"history\", [])\n                if hasattr(self, \"backup_source_list\"):\n                    self.backup_source_list.delete(0, \"end\")\n                    for p in self.backup_sources:\n                        self.backup_source_list.insert(\"end\", p)\n            if not silent:\n                self._append_log(self.backup_log, \"\u2705 Kaam ho gaya: Config load ho gaya\", C[\"success\"])\n        except Exception as e:\n            if not silent:\n                self._append_log(self.backup_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _backup_schedule_enable(self):\n        try:\n            sched = self.backup_schedule_var.get()\n            if sched == \"Manual Only\":\n                messagebox.showwarning(\"Schedule nahi hai\", \"Daily, Weekly ya Monthly select karo\")\n                return\n            script_path = sys.argv[0]\n            time_txt = self.backup_time_var.get()\n            sc = \"daily\" if sched == \"Daily\" else (\"weekly /d MON\" if sched == \"Weekly\" else \"monthly /d 1\")\n            cmd = f'schtasks /create /tn \"GodawariAutoBackup\" /tr \"pythonw \\\\\"{script_path}\\\\\" --backup\" /sc {sc} /st {time_txt} /f'\n            self._launch_job(\"backup_schedule_enable\", lambda: self._append_log(self.backup_log, self._run_cmd(cmd, timeout=90)[0], C[\"success\"]))\n        except Exception as e:\n            self._append_log(self.backup_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _backup_schedule_remove(self):\n        if messagebox.askyesno(\"Confirm karo\", \"GodawariAutoBackup scheduled task remove karna hai?\"):\n            self._launch_job(\"backup_schedule_remove\", lambda: self._append_log(self.backup_log, self._run_cmd('schtasks /delete /tn \"GodawariAutoBackup\" /f', timeout=60)[0], C[\"warning\"]))\n\n    def _backup_add_history(self, entry):\n        self.backup_history = getattr(self, \"backup_history\", [])\n        self.backup_history.insert(0, entry)\n        self.backup_history = self.backup_history[:50]\n        self.after(0, self._backup_save_config)\n        self.after(0, self._backup_refresh_history)\n\n    def _backup_refresh_history(self):\n        try:\n            if not hasattr(self, \"backup_history\"):\n                self.backup_history = []\n            if hasattr(self, \"backup_history_tree\"):\n                self.backup_history_tree.delete(*self.backup_history_tree.get_children())\n                for i, h in enumerate(self.backup_history[:50], 1):\n                    self.backup_history_tree.insert(\"\", \"end\", values=(i, h.get(\"dt\", \"\"), h.get(\"mode\", \"\"), h.get(\"sources\", \"\"), h.get(\"dest\", \"\"), h.get(\"size\", \"\"), h.get(\"status\", \"\"), h.get(\"duration\", \"\")))\n        except Exception as e:\n            self._append_log(self.backup_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _backup_calculate_size(self, folder):\n        total = 0\n        try:\n            for root, dirs, files in os.walk(folder):\n                for fn in files:\n                    try:\n                        total += os.path.getsize(os.path.join(root, fn))\n                    except Exception:\n                        pass\n        except Exception:\n            pass\n        return total / (1024 * 1024)\n\n    def _backup_open_folder(self):\n        try:\n            dest = self.backup_dest_var.get().strip()\n            if dest and os.path.isdir(dest):\n                os.startfile(dest)\n            else:\n                messagebox.showwarning(\"Folder nahi mila\", \"Pehle valid backup folder select karo\")\n        except Exception as e:\n            self._append_log(self.backup_log, f\"Error aaya: {str(e)}\", C[\"error\"])\n\n    def _backup_get_selected_sources(self):\n        try:\n            if hasattr(self, \"backup_source_list\") and self.backup_source_list.curselection():\n                return [self.backup_source_list.get(i) for i in self.backup_source_list.curselection()]\n            return list(self.backup_sources)\n        except Exception:\n            return list(self.backup_sources)\n\n    # ---------- UTILITIES ----------\n    def _toggle_theme(self):\n        self.current_theme = \"light\" if self.current_theme == \"dark\" else \"dark\"\n        self.theme_btn.config(text=\"\u2600\ufe0f\" if self.current_theme == \"light\" else \"\ud83c\udf19\")\n\n    def _save_settings(self):\n        try:\n            with open(self.settings_file, \"w\") as f:\n                json.dump({\"theme\": self.current_theme}, f)\n        except:\n            pass\n\n    def _load_settings(self):\n        if os.path.exists(self.settings_file):\n            try:\n                with open(self.settings_file, \"r\") as f:\n                    data = json.load(f)\n                    self.current_theme = data.get(\"theme\", \"dark\")\n            except:\n                pass\n\n    def _fmt_size(self, size):\n        for unit in [\"B\",\"KB\",\"MB\",\"GB\"]:\n            if size &lt; 1024:\n                return f\"{size:.1f} {unit}\"\n            size /= 1024\n        return f\"{size:.1f} TB\"\n\n    def _format_seconds(self, seconds):\n        try:\n            seconds = max(0, int(float(seconds)))\n        except Exception:\n            seconds = 0\n        h, rem = divmod(seconds, 3600)\n        m, s = divmod(rem, 60)\n        if h:\n            return f\"{h:02d}:{m:02d}:{s:02d}\"\n        return f\"{m:02d}:{s:02d}\"\n\n    def _section_header(self, parent, title, subtitle=\"\", hw=False):\n        hdr = tk.Frame(parent, bg=C[\"panel\"] if not hw else \"#1A0A2E\")\n        hdr.pack(fill=\"x\")\n        fg = C[\"hw_accent\"] if hw else C[\"accent\"]\n        tk.Label(hdr, text=f\"  {title}\", font=FONTS[\"heading\"], fg=fg, bg=hdr[\"bg\"]).pack(side=\"left\", pady=10, padx=8)\n        if subtitle:\n            tk.Label(hdr, text=f\"\u2014  {subtitle}\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=hdr[\"bg\"]).pack(side=\"left\", pady=10)\n\n    def _btn(self, parent, text, color, cmd):\n        return tk.Button(parent, text=self._fix_text(text), font=FONTS[\"small\"], bg=color, fg=C[\"text\"], bd=0, padx=12, pady=6, cursor=\"hand2\", command=cmd)\n\n    def _action_card_grid(self, parent, actions, cols=4, button_refs=None):\n        \"\"\"\n        HDD/SSD repair jaisa card-grid banata hai.\n        actions = list of (emoji, title, subtitle, color, cmd_func)\n        cols = columns per row (default 4)\n        button_refs = optional list to collect created button widgets.\n        \"\"\"\n        grid_frame = tk.Frame(parent, bg=C[\"bg\"])\n        grid_frame.pack(fill=\"x\", padx=14, pady=4)\n        cols = max(1, min(int(cols or 1), 4))\n        for i in range(cols):\n            grid_frame.columnconfigure(i, weight=1)\n        for idx, (emoji, title, subtitle, color, cmd_func) in enumerate(actions):\n            col = idx % cols\n            row_n = idx // cols\n            card = tk.Frame(grid_frame, bg=C[\"card\"], bd=1, relief=\"flat\",\n                            highlightbackground=color, highlightthickness=1)\n            card.grid(row=row_n, column=col, padx=5, pady=5, sticky=\"nsew\")\n            tk.Label(card, text=emoji, font=(\"Segoe UI\", 18),\n                     fg=color, bg=C[\"card\"]).pack(pady=(8, 2))\n            tk.Label(card, text=title, font=FONTS[\"subhead\"],\n                     fg=C[\"text\"], bg=C[\"card\"]).pack()\n            tk.Label(card, text=subtitle, font=FONTS[\"small\"],\n                     fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=160, justify=\"center\").pack(padx=6)\n            btn = tk.Button(card, text=\"\u25b6  Run\", font=FONTS[\"small\"],\n                      bg=color, fg=\"#000\" if color in (C.get(\"accent\",\"\"), C.get(\"accent2\",\"\")) else C[\"text\"],\n                      bd=0, padx=12, pady=5, cursor=\"hand2\",\n                      command=cmd_func)\n            btn.pack(pady=(6, 10))\n            if isinstance(button_refs, list):\n                button_refs.append(btn)\n        return grid_frame\n\n    def _compact_action_grid(self, parent, actions, cols=2):\n        grid = tk.Frame(parent, bg=C[\"card\"])\n        grid.pack(fill=\"x\", padx=8, pady=(0, 6))\n        cols = max(1, int(cols or 1))\n        for i in range(cols):\n            grid.columnconfigure(i, weight=1)\n        for idx, (label, color, cmd_func) in enumerate(actions):\n            row = idx // cols\n            col = idx % cols\n            btn = tk.Button(\n                grid, text=self._fix_text(label), font=FONTS[\"small\"],\n                bg=color, fg=C[\"text\"], bd=0, padx=8, pady=5,\n                cursor=\"hand2\", command=cmd_func\n            )\n            btn.grid(row=row, column=col, sticky=\"ew\", padx=3, pady=3)\n        return grid\n\n    def _bind_tree_responsive_columns(self, tree, specs):\n        \"\"\"\n        specs: [(column_name, base_width, grow_weight), ...]\n        Keeps tree columns readable while allowing wide screens to use extra room.\n        \"\"\"\n        safe_specs = []\n        for col, base, weight in specs:\n            try:\n                safe_specs.append((col, max(40, int(base)), max(0, int(weight))))\n            except Exception:\n                pass\n        if not safe_specs:\n            return\n\n        def _resize(_event=None):\n            try:\n                base_total = sum(base for _col, base, _weight in safe_specs)\n                available = max(tree.winfo_width() - 28, base_total)\n                extra = max(0, available - base_total)\n                weight_total = sum(weight for _col, _base, weight in safe_specs) or 1\n                for col, base, weight in safe_specs:\n                    width = base + int(extra * (weight / weight_total))\n                    tree.column(col, width=width, stretch=True)\n            except Exception:\n                pass\n\n        tree.bind(\"\", _resize, add=\"+\")\n        try:\n            tree.after(80, _resize)\n        except Exception:\n            pass\n\n    def _scrolled_text(self, parent, height=12):\n        st = scrolledtext.ScrolledText(parent, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], height=height, bd=0, wrap=\"word\", relief=\"flat\", state=\"disabled\")\n        st.pack(fill=\"both\", expand=True, padx=8, pady=(0,8))\n        return st\n\n    def _stat_card(self, parent, title, value, color):\n        card = tk.Frame(parent, bg=C[\"card\"], pady=14, padx=14)\n        tk.Label(card, text=title, font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\")\n        lbl = tk.Label(card, text=value, font=(\"Segoe UI\", 22, \"bold\"), fg=color, bg=C[\"card\"])\n        lbl.pack(anchor=\"w\", pady=(4,0))\n        bar = ttk.Progressbar(card, length=140, mode=\"determinate\")\n        bar.pack(fill=\"x\", pady=(6,0))\n        card._value_lbl = lbl\n        card._bar = bar\n        return card\n\n    def _append_log(self, widget, msg, color=None):\n        def _do():\n            try:\n                widget.config(state=\"normal\")\n                start = widget.index(\"end-1c\")\n                widget.insert(\"end\", self._fix_text(msg) + \"\\n\")\n                if color:\n                    end = widget.index(\"end-1c\")\n                    tag = f\"c{color.replace('#','')}\"\n                    widget.tag_config(tag, foreground=color)\n                    widget.tag_add(tag, start, end)\n                widget.see(\"end\")\n                widget.config(state=\"disabled\")\n            except:\n                pass\n        self.after(0, _do)\n\n    def _reg_set(self, hive, path, name, value, vtype):\n        try:\n            key = winreg.OpenKey(hive, path, 0, winreg.KEY_ALL_ACCESS)\n        except:\n            key = winreg.CreateKey(hive, path)\n        winreg.SetValueEx(key, name, 0, vtype, value)\n        winreg.CloseKey(key)\n\n    def _reg_get(self, hive, path, name):\n        try:\n            key = winreg.OpenKey(hive, path, 0, winreg.KEY_READ)\n            try:\n                value, vtype = winreg.QueryValueEx(key, name)\n                return True, value, vtype\n            finally:\n                winreg.CloseKey(key)\n        except FileNotFoundError:\n            return False, None, None\n        except OSError:\n            return False, None, None\n\n    def _same_reg_value(self, current, desired, vtype):\n        if vtype == winreg.REG_DWORD:\n            try:\n                return int(current) == int(desired)\n            except Exception:\n                return False\n        if vtype == winreg.REG_BINARY:\n            return bytes(current or b\"\") == bytes(desired or b\"\")\n        return str(current) == str(desired)\n\n    def _action_summary(self, title, results):\n        changed = sum(1 for r in results if r.get(\"state\") == \"changed\")\n        already = sum(1 for r in results if r.get(\"state\") == \"already\")\n        failed = [r for r in results if r.get(\"state\") == \"failed\"]\n        lines = [f\"{title} summary:\"]\n        lines.append(f\"Applied now: {changed}\")\n        lines.append(f\"Already done: {already}\")\n        if failed:\n            lines.append(f\"Failed: {len(failed)}\")\n            lines.extend(f\"- {r.get('label', 'item')}: {r.get('error', '')}\" for r in failed[:8])\n        elif changed == 0 and already &gt; 0:\n            lines.append(\"No new change needed.\")\n        return {\n            \"changed\": changed,\n            \"already\": already,\n            \"failed\": len(failed),\n            \"already_done\": changed == 0 and already &gt; 0 and not failed,\n            \"message\": \"\\n\".join(lines),\n        }\n\n    def _reg_set_checked(self, hive, path, name, value, vtype, label=None, log_widget=None):\n        label = label or name\n        exists, current, current_type = self._reg_get(hive, path, name)\n        if exists and current_type == vtype and self._same_reg_value(current, value, vtype):\n            if log_widget is not None:\n                self._append_log(log_widget, f\"Already done: {label}\", C[\"warning\"])\n            return {\"state\": \"already\", \"label\": label}\n        try:\n            self._reg_set(hive, path, name, value, vtype)\n            if log_widget is not None:\n                self._append_log(log_widget, f\"Applied: {label}\", C[\"success\"])\n            return {\"state\": \"changed\", \"label\": label}\n        except Exception as e:\n            if log_widget is not None:\n                self._append_log(log_widget, f\"Failed: {label} - {e}\", C[\"error\"])\n            return {\"state\": \"failed\", \"label\": label, \"error\": str(e)}\n\n    def _service_state(self, name):\n        out, rc = self._run_cmd(f'sc query \"{name}\"', timeout=20)\n        if rc != 0:\n            return \"\", out\n        match = re.search(r\"STATE\\s*:\\s*\\d+\\s+([A-Z_]+)\", out, re.I)\n        return (match.group(1).upper() if match else \"\"), out\n\n    def _service_start_mode(self, name):\n        out, rc = self._run_cmd(f'sc qc \"{name}\"', timeout=20)\n        if rc != 0:\n            return \"\", out\n        match = re.search(r\"START_TYPE\\s*:\\s*\\d+\\s+([A-Z_]+)\", out, re.I)\n        return (match.group(1).upper() if match else \"\"), out\n\n    def _service_dependents(self, name):\n        \"\"\"\n        Return list of dependent service names (best-effort).\n        Uses: sc enumdepend \n        \"\"\"\n        out, rc = self._run_cmd(f'sc enumdepend \"{name}\"', timeout=25)\n        if rc != 0 or not out:\n            return []\n        deps = []\n        for ln in out.splitlines():\n            ln = ln.strip()\n            if not ln:\n                continue\n            m = re.search(r\"^SERVICE_NAME:\\s*(.+)$\", ln, re.I)\n            if m:\n                dep = m.group(1).strip()\n                if dep and dep.lower() not in {name.lower()}:\n                    deps.append(dep)\n        # Dedupe preserve order\n        seen = set()\n        uniq = []\n        for d in deps:\n            dl = d.lower()\n            if dl in seen:\n                continue\n            seen.add(dl)\n            uniq.append(d)\n        return uniq\n\n    def _svc_snapshot_path(self):\n        base = getattr(self, \"backup_dir\", \"\") or os.getcwd()\n        return os.path.join(base, \"service_startmode_snapshot.json\")\n\n    def _svc_save_start_mode_snapshot(self, names):\n        try:\n            items = {}\n            for n in names:\n                mode, _ = self._service_start_mode(n)\n                if mode:\n                    items[n] = mode\n            if not items:\n                return\n            payload = {\n                \"ts\": datetime.datetime.now().isoformat(timespec=\"seconds\"),\n                \"items\": items,\n            }\n            with open(self._svc_snapshot_path(), \"w\", encoding=\"utf-8\") as f:\n                json.dump(payload, f, ensure_ascii=False, indent=2)\n        except Exception:\n            pass\n\n    def _svc_restore_snapshot(self):\n        path = self._svc_snapshot_path()\n        if not os.path.exists(path):\n            messagebox.showwarning(\"No Snapshot\", f\"Snapshot file nahi mili:\\n{path}\\n\\nPehle disable actions chalao (snapshot auto save hota hai).\")\n            return\n        if not messagebox.askyesno(\"Restore Snapshot\", \"Snapshot se previous service start-modes restore karein?\\n(Admin required for some services)\"):\n            return\n        try:\n            with open(path, \"r\", encoding=\"utf-8\") as f:\n                payload = json.load(f)\n            items = (payload or {}).get(\"items\", {}) if isinstance(payload, dict) else {}\n        except Exception as e:\n            messagebox.showerror(\"Snapshot Error\", str(e))\n            return\n        if not items:\n            messagebox.showinfo(\"Empty Snapshot\", \"Snapshot empty hai.\")\n            return\n        # Map SC qc START_TYPE to sc config value\n        map_mode = {\n            \"DISABLED\": \"disabled\",\n            \"AUTO_START\": \"auto\",\n            \"DEMAND_START\": \"demand\",\n        }\n        results = []\n        for name, mode in items.items():\n            start_type = map_mode.get(str(mode).upper(), \"demand\")\n            results.append(self._service_config_checked(name, start_type, f\"{name} start={start_type}\", None))\n        summary = self._action_summary(\"Service Snapshot Restore\", results)\n        messagebox.showinfo(\"Restore Result\", summary[\"message\"])\n        self._scan_impacting_services()\n\n    def _svc_apply_pack(self, pack):\n        if not messagebox.askyesno(\"Apply Service Pack\", f\"Apply recommended pack: {pack}?\\n\\nReboot recommended.\"):\n            return\n        # Keep it conservative; snapshot first for rollback\n        targets = []\n        if pack == \"ssd_laptop\":\n            targets = [\n                (\"SysMain\", \"disabled\"),\n                (\"WSearch\", \"disabled\"),\n                (\"DiagTrack\", \"disabled\"),\n            ]\n        elif pack == \"hdd_desktop\":\n            targets = [\n                (\"DiagTrack\", \"disabled\"),\n                (\"WSearch\", \"disabled\"),\n            ]\n        names = [t[0] for t in targets]\n        self._svc_save_start_mode_snapshot(names)\n        results = []\n        for svc, start in targets:\n            results.append(self._service_config_checked(svc, start, f\"{svc} start={start}\", None))\n            if start == \"disabled\":\n                results.append(self._service_stop_checked(svc, svc, None))\n        summary = self._action_summary(f\"Service Pack: {pack}\", results)\n        messagebox.showinfo(\"Pack Result\", summary[\"message\"] + \"\\nRestart recommended.\")\n        self._scan_impacting_services()\n\n    def _service_stop_checked(self, name, label=None, log_widget=None):\n        label = label or name\n        state, detail = self._service_state(name)\n        if state == \"STOPPED\":\n            if log_widget is not None:\n                self._append_log(log_widget, f\"Already stopped: {label}\", C[\"warning\"])\n            return {\"state\": \"already\", \"label\": label}\n        out, rc = self._run_cmd(f'sc stop \"{name}\"', timeout=40)\n        combined = f\"{detail}\\n{out}\".lower()\n        if rc == 0 or \"stop_pending\" in combined or \"stopped\" in combined:\n            if log_widget is not None:\n                self._append_log(log_widget, f\"Stopped: {label}\", C[\"success\"])\n            return {\"state\": \"changed\", \"label\": label}\n        if \"not been started\" in combined or \"service has not been started\" in combined:\n            if log_widget is not None:\n                self._append_log(log_widget, f\"Already stopped: {label}\", C[\"warning\"])\n            return {\"state\": \"already\", \"label\": label}\n        if log_widget is not None:\n            self._append_log(log_widget, f\"Stop failed: {label} - {out[:120]}\", C[\"error\"])\n        return {\"state\": \"failed\", \"label\": label, \"error\": out[:300]}\n\n    def _service_start_checked(self, name, label=None, log_widget=None):\n        label = label or name\n        state, _ = self._service_state(name)\n        if state == \"RUNNING\":\n            if log_widget is not None:\n                self._append_log(log_widget, f\"Already running: {label}\", C[\"warning\"])\n            return {\"state\": \"already\", \"label\": label}\n        out, rc = self._run_cmd(f'sc start \"{name}\"', timeout=40)\n        combined = out.lower()\n        if rc == 0 or \"running\" in combined or \"start_pending\" in combined:\n            if log_widget is not None:\n                self._append_log(log_widget, f\"Started: {label}\", C[\"success\"])\n            return {\"state\": \"changed\", \"label\": label}\n        if \"already running\" in combined or \"instance of the service is already running\" in combined:\n            if log_widget is not None:\n                self._append_log(log_widget, f\"Already running: {label}\", C[\"warning\"])\n            return {\"state\": \"already\", \"label\": label}\n        if log_widget is not None:\n            self._append_log(log_widget, f\"Start failed: {label} - {out[:120]}\", C[\"error\"])\n        return {\"state\": \"failed\", \"label\": label, \"error\": out[:300]}\n\n    def _service_config_checked(self, name, start_type, label=None, log_widget=None):\n        label = label or name\n        desired = {\n            \"disabled\": \"DISABLED\",\n            \"auto\": \"AUTO_START\",\n            \"demand\": \"DEMAND_START\",\n            \"manual\": \"DEMAND_START\",\n        }.get(str(start_type).lower(), str(start_type).upper())\n        current, _ = self._service_start_mode(name)\n        if current == desired:\n            if log_widget is not None:\n                self._append_log(log_widget, f\"Already configured: {label} start={start_type}\", C[\"warning\"])\n            return {\"state\": \"already\", \"label\": label}\n        out, rc = self._run_cmd(f'sc config \"{name}\" start= {start_type}', timeout=30)\n        if rc == 0:\n            if log_widget is not None:\n                self._append_log(log_widget, f\"Configured: {label} start={start_type}\", C[\"success\"])\n            return {\"state\": \"changed\", \"label\": label}\n        if log_widget is not None:\n            self._append_log(log_widget, f\"Config failed: {label} - {out[:120]}\", C[\"error\"])\n        return {\"state\": \"failed\", \"label\": label, \"error\": out[:300]}\n\n    def _fsutil_last_access_checked(self, log_widget=None):\n        label = \"NTFS last access timestamp\"\n        out, _ = self._run_cmd(\"fsutil behavior query disablelastaccess\", timeout=20)\n        match = re.search(r\"DisableLastAccess\\s*=\\s*(\\d+)\", out, re.I)\n        if match and int(match.group(1)) in (1, 3):\n            if log_widget is not None:\n                self._append_log(log_widget, f\"Already done: {label}\", C[\"warning\"])\n            return {\"state\": \"already\", \"label\": label}\n        out, rc = self._run_cmd(\"fsutil behavior set disablelastaccess 1\", timeout=30)\n        if rc == 0:\n            if log_widget is not None:\n                self._append_log(log_widget, f\"Applied: {label}\", C[\"success\"])\n            return {\"state\": \"changed\", \"label\": label}\n        if log_widget is not None:\n            self._append_log(log_widget, f\"Failed: {label} - {out[:120]}\", C[\"error\"])\n        return {\"state\": \"failed\", \"label\": label, \"error\": out[:300]}\n\n    def _task_records_from_schtasks(self, out):\n        try:\n            reader = csv.DictReader(io.StringIO(out))\n            records = []\n            for row in reader:\n                task_name = (row.get(\"TaskName\") or row.get(\"Task Name\") or \"\").strip()\n                if task_name:\n                    records.append(row)\n            if records:\n                return records\n        except Exception:\n            pass\n        records = []\n        try:\n            for row in csv.reader(io.StringIO(out)):\n                if len(row) &lt; 2:\n                    continue\n                first = row[0].strip()\n                if first in (\"HostName\", \"TaskName\"):\n                    continue\n                task_name = row[1].strip() if len(row) &gt; 1 else first\n                if task_name:\n                    records.append({\n                        \"TaskName\": task_name,\n                        \"Status\": row[3].strip() if len(row) &gt; 3 else \"\",\n                        \"Last Run Time\": row[5].strip() if len(row) &gt; 5 else \"\",\n                        \"Run As User\": row[14].strip() if len(row) &gt; 14 else \"\",\n                        \"Task To Run\": row[8].strip() if len(row) &gt; 8 else \"\",\n                        \"Scheduled Task State\": row[11].strip() if len(row) &gt; 11 else \"\",\n                    })\n        except Exception:\n            pass\n        return records\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # SUSPICIOUS / UNKNOWN PROCESS SCANNER\n    # Checks: Running processes, Startup (Registry + Folder),\n    #         Hidden folders, Scheduled tasks \u2014 flags unknown ones\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _build_suspicion_scanner(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n        self._section_header(frame, \"\ud83d\udd34 Suspicious Process &amp; Entry Scanner\",\n                             \"Unknown processes in RAM, Startup, Registry &amp; Hidden Folders\")\n        body = self._scrollable_section_body(frame)\n\n        self._action_card_grid(body, [\n            (\"\ud83d\udd0d\", \"Full Scan\",           \"Processes, startup, folders, tasks sab scan\",C[\"btn_danger\"], self._susp_full_scan),\n            (\"\u26a1\", \"Scan Running Procs\",  \"RAM mein chal rahe unknown processes\",       C[\"btn_warn\"],   self._susp_scan_procs),\n            (\"\ud83d\ude80\", \"Scan Startup\",        \"Startup entries mein suspicious cheezein\",   C[\"btn_info\"],   self._susp_scan_startup),\n            (\"\ud83d\udcc1\", \"Scan Hidden Folders\", \"Hidden folders dhundho\",                     C[\"btn_hw\"],     self._susp_scan_hidden),\n            (\"\ud83d\udcc5\", \"Scan Unknown Tasks\",  \"Unknown scheduled tasks flag karo\",          C[\"btn_chip\"],   self._susp_scan_tasks),\n            (\"\ud83d\uddd1\",  \"Kill Selected\",      \"Selected process terminate karo\",            C[\"btn_danger\"], self._susp_kill_selected),\n            (\"\ud83d\udd12\", \"Disable Selected\",    \"Selected entry disable karo\",                C[\"btn_warn\"],   self._susp_disable_selected),\n            (\"\ud83d\udce6\", \"Quarantine Selected\", \"Selected file quarantine mein bhejo\",        C[\"btn_info\"],   self._susp_quarantine_selected),\n            (\"\ud83d\udd17\", \"VirusTotal URL\",      \"URL clipboard mein copy karo\",               C[\"btn_chip\"],   self._susp_copy_virustotal_url),\n        ], cols=3)\n\n        # \u2500\u2500 Stats row \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        stats_row = tk.Frame(body, bg=C[\"bg\"])\n        stats_row.pack(fill=\"x\", padx=16, pady=6)\n        self.susp_count_vars = {}\n        for i, (k, lbl, col) in enumerate([\n            (\"proc\",    \"Running Procs\",   C[\"error\"]),\n            (\"startup\", \"Startup Entries\", C[\"warning\"]),\n            (\"hidden\",  \"Hidden Items\",    C[\"hw_accent\"]),\n            (\"tasks\",   \"Unknown Tasks\",   C[\"accent4\"]),\n            (\"total\",   \"TOTAL FLAGS\",     C[\"accent\"]),\n        ]):\n            card = tk.Frame(stats_row, bg=C[\"card\"], padx=12, pady=8)\n            card.grid(row=0, column=i, padx=5, sticky=\"ew\")\n            stats_row.columnconfigure(i, weight=1)\n            tk.Label(card, text=lbl,  font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\")\n            v = tk.StringVar(value=\"--\")\n            self.susp_count_vars[k] = v\n            tk.Label(card, textvariable=v, font=(\"Segoe UI\",16,\"bold\"), fg=col, bg=C[\"card\"]).pack(anchor=\"w\")\n\n        # \u2500\u2500 Full-width flagged entries list \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        list_frame = tk.Frame(body, bg=C[\"card\"])\n        list_frame.pack(fill=\"both\", expand=True, padx=16, pady=(4,0))\n        list_frame.rowconfigure(0, weight=1)\n        list_frame.columnconfigure(0, weight=1)\n\n        tk.Label(list_frame, text=\"  \ud83d\udea8 Flagged Entries  (saari entries ek sath \u2014 click karo detail ke liye)\",\n                 font=FONTS[\"subhead\"], fg=C[\"error\"], bg=C[\"card\"]).grid(\n                 row=0, column=0, columnspan=2, sticky=\"w\", pady=(8,4), padx=8)\n\n        cols = (\"Category\",\"Name\",\"Risk\",\"Location/PID\",\"Action\")\n        self.susp_tree = ttk.Treeview(list_frame, columns=cols, show=\"headings\",\n                                      height=24, style=\"Custom.Treeview\")\n        widths = [110, 220, 80, 380, 100]\n        for col, w in zip(cols, widths):\n            self.susp_tree.heading(col, text=col)\n            self.susp_tree.column(col, width=w, anchor=\"w\")\n        self.susp_tree.tag_configure(\"high\",   foreground=C[\"error\"])\n        self.susp_tree.tag_configure(\"medium\", foreground=C[\"warning\"])\n        self.susp_tree.tag_configure(\"low\",    foreground=C[\"text_dim\"])\n        lsb = ttk.Scrollbar(list_frame, orient=\"vertical\", command=self.susp_tree.yview)\n        hsb2 = ttk.Scrollbar(list_frame, orient=\"horizontal\", command=self.susp_tree.xview)\n        self.susp_tree.configure(yscrollcommand=lsb.set, xscrollcommand=hsb2.set)\n        self.susp_tree.grid(row=1, column=0, sticky=\"nsew\", padx=(8,0), pady=(0,0))\n        lsb.grid(row=1, column=1, sticky=\"ns\", pady=(0,0))\n        hsb2.grid(row=2, column=0, sticky=\"ew\", padx=(8,0), pady=(0,4))\n        list_frame.rowconfigure(1, weight=1)\n        self._bind_tree_responsive_columns(self.susp_tree, [\n            (\"Category\", 110, 1), (\"Name\", 220, 3), (\"Risk\", 80, 0),\n            (\"Location/PID\", 380, 5), (\"Action\", 100, 1)\n        ])\n        self.susp_tree.bind(\"&lt;&gt;\", self._susp_on_select)\n\n        # \u2500\u2500 Bottom: detail strip + legend \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        bot = tk.Frame(body, bg=C[\"panel\"])\n        bot.pack(fill=\"x\", padx=16, pady=(2,4))\n        bot.columnconfigure(0, weight=1)\n        bot.columnconfigure(1, weight=0)\n\n        # Detail box\n        detail_wrap = tk.Frame(bot, bg=C[\"card\"])\n        detail_wrap.grid(row=0, column=0, sticky=\"nsew\", padx=(0,6), pady=4)\n        detail_wrap.rowconfigure(1, weight=1)\n        detail_wrap.columnconfigure(0, weight=1)\n\n        hdr_d = tk.Frame(detail_wrap, bg=C[\"card\"])\n        hdr_d.grid(row=0, column=0, sticky=\"ew\", padx=6, pady=(4,2))\n        tk.Label(hdr_d, text=\"  \ud83d\udd0d Entry Details &amp; Recommendation\",\n                 font=FONTS[\"subhead\"], fg=C[\"warning\"], bg=C[\"card\"]).pack(side=\"left\")\n        tk.Label(hdr_d, text=\"(entry click karo \u2014 yahan detail dikhegi)\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\", padx=6)\n\n        self.susp_detail = scrolledtext.ScrolledText(\n            detail_wrap, font=FONTS[\"mono\"], bg=C[\"bg\"], fg=C[\"text\"],\n            height=5, bd=0, relief=\"flat\", state=\"disabled\", wrap=\"word\")\n        self.susp_detail.grid(row=1, column=0, sticky=\"nsew\", padx=6, pady=(0,4))\n\n        # Legend (right side of bottom strip)\n        leg_wrap = tk.Frame(bot, bg=C[\"card\"])\n        leg_wrap.grid(row=0, column=1, sticky=\"nsew\", padx=(0,0), pady=4)\n        tk.Label(leg_wrap, text=\"  Legend\", font=FONTS[\"small\"],\n                 fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=8, pady=(6,2))\n        for color, label in [(C[\"error\"],   \"\ud83d\udd34 High Risk\"),\n                             (C[\"warning\"], \"\ud83d\udfe1 Medium Risk\"),\n                             (C[\"text_dim\"],\"\u26aa Low / Safe\")]:\n            tk.Label(leg_wrap, text=label, font=FONTS[\"small\"],\n                     fg=color, bg=C[\"card\"]).pack(anchor=\"w\", padx=12, pady=2)\n\n        self.susp_status = tk.Label(body, text=\"  Click 'Full Scan' to detect suspicious entries\",\n                                    font=FONTS[\"small\"], fg=C[\"accent2\"], bg=C[\"bg\"], anchor=\"w\")\n        self.susp_status.pack(fill=\"x\", padx=16, pady=(0,4))\n\n        # Internal store: {iid: meta_dict}\n        self._susp_meta = {}\n        return frame\n\n    def _susp_quarantine_dir(self):\n        base = getattr(self, \"backup_dir\", \"\") or os.path.join(os.path.expanduser(\"~\"), \"Desktop\")\n        q = os.path.join(base, \"Godawari_Quarantine\")\n        try:\n            os.makedirs(q, exist_ok=True)\n        except Exception:\n            pass\n        return q\n\n    def _susp_quarantine_selected(self):\n        sel = self.susp_tree.selection()\n        if not sel:\n            messagebox.showinfo(\"No Selection\", \"Select entries first.\")\n            return\n        qdir = self._susp_quarantine_dir()\n        moved = 0\n        for iid in sel:\n            meta = self._susp_meta.get(iid, {})\n            p = meta.get(\"exe\") or meta.get(\"path\") or \"\"\n            if not p or not os.path.exists(p) or os.path.isdir(p):\n                continue\n            dst = os.path.join(qdir, os.path.basename(p))\n            if os.path.exists(dst):\n                root, ext = os.path.splitext(dst)\n                dst = f\"{root}_{int(time.time())}{ext}\"\n            try:\n                shutil.move(p, dst)\n                moved += 1\n                self.susp_tree.delete(iid)\n            except Exception as e:\n                messagebox.showwarning(\"Move failed\", f\"{p}\\n{e}\")\n        self._set_status(f\"Quarantined {moved} file(s)\", C[\"success\"] if moved else C[\"warning\"])\n        messagebox.showinfo(\"Quarantine\", f\"\u2705 Quarantined: {moved}\\nFolder:\\n{qdir}\")\n\n    def _susp_copy_virustotal_url(self):\n        sel = self.susp_tree.selection()\n        if not sel:\n            messagebox.showinfo(\"No Selection\", \"Select a file/process entry first.\")\n            return\n        iid = sel[0]\n        meta = self._susp_meta.get(iid, {})\n        p = meta.get(\"exe\") or meta.get(\"path\") or \"\"\n        if not p or not os.path.exists(p) or os.path.isdir(p):\n            messagebox.showwarning(\"No File\", \"Selected entry ke paas valid file path nahi hai.\")\n            return\n        try:\n            h = self._sha256_file(p)\n            url = f\"https://www.virustotal.com/gui/file/{h}\"\n            self.clipboard_clear()\n            self.clipboard_append(url)\n            self.update()\n            messagebox.showinfo(\"Copied\", f\"\u2705 VirusTotal URL copied:\\n{url}\")\n        except Exception as e:\n            messagebox.showerror(\"Error\", str(e))\n\n    # \u2500\u2500 Scan orchestrators \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _susp_full_scan(self):\n        self.susp_status.config(text=\"  \ud83d\udd0d Full scan running...\", fg=C[\"accent4\"])\n        for i in self.susp_tree.get_children():\n            self.susp_tree.delete(i)\n        self._susp_meta.clear()\n        for k in self.susp_count_vars:\n            self.susp_count_vars[k].set(\"...\")\n        self._launch_job(\"susp_full_scan\", self._do_susp_full_scan)\n\n    def _do_susp_full_scan(self):\n        pc = self._do_susp_scan_procs(batch=True)\n        sc = self._do_susp_scan_startup(batch=True)\n        hc = self._do_susp_scan_hidden(batch=True)\n        tc = self._do_susp_scan_tasks(batch=True)\n        total = pc + sc + hc + tc\n        def update():\n            self.susp_count_vars[\"proc\"].set(str(pc))\n            self.susp_count_vars[\"startup\"].set(str(sc))\n            self.susp_count_vars[\"hidden\"].set(str(hc))\n            self.susp_count_vars[\"tasks\"].set(str(tc))\n            self.susp_count_vars[\"total\"].set(str(total))\n            self.susp_status.config(\n                text=f\"  \u2705 Scan complete \u2014 {total} suspicious entries found\",\n                fg=C[\"success\"] if total == 0 else C[\"error\"])\n        self.after(0, update)\n\n    def _susp_scan_procs(self):\n        self._launch_job(\"susp_scan_procs\", self._do_susp_scan_procs)\n\n    def _susp_scan_startup(self):\n        self._launch_job(\"susp_scan_startup\", self._do_susp_scan_startup)\n\n    def _susp_scan_hidden(self):\n        self._launch_job(\"susp_scan_hidden\", self._do_susp_scan_hidden)\n\n    def _susp_scan_tasks(self):\n        self._launch_job(\"susp_scan_tasks\", self._do_susp_scan_tasks)\n\n    # \u2500\u2500 Known-safe whitelist (lowercase) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    _KNOWN_SAFE = {\n        \"system\",\"system idle process\",\"svchost.exe\",\"lsass.exe\",\"winlogon.exe\",\n        \"csrss.exe\",\"smss.exe\",\"wininit.exe\",\"services.exe\",\"explorer.exe\",\n        \"taskhostw.exe\",\"taskhost.exe\",\"dwm.exe\",\"spoolsv.exe\",\"searchindexer.exe\",\n        \"antimalware service executable\",\"msmpeng.exe\",\"msseces.exe\",\n        \"audiodg.exe\",\"fontdrvhost.exe\",\"sihost.exe\",\"runtimebroker.exe\",\n        \"ctfmon.exe\",\"dllhost.exe\",\"conhost.exe\",\"cmd.exe\",\"powershell.exe\",\n        \"python.exe\",\"pythonw.exe\",\"msiexec.exe\",\"wuauclt.exe\",\"wermgr.exe\",\n        \"backgroundtaskhost.exe\",\"settingsynchost.exe\",\"compattelrunner.exe\",\n        \"dashost.exe\",\"searchhost.exe\",\"securityhealthsystray.exe\",\n        \"shellexperiencehost.exe\",\"startmenuexperiencehost.exe\",\n        \"textinputhost.exe\",\"useroobebroker.exe\",\"applicationframehost.exe\",\n    }\n\n    _SUSPICIOUS_INDICATORS = [\n        \"temp\",\"tmp\",\"appdata\\\\local\\\\temp\",\"appdata\\\\roaming\",\n        \"programdata\",\"users\\\\public\",\"recycle\",\"windows\\\\temp\",\n        \"\\\\downloads\\\\\",\"no description\",\"unknown\",\"(null)\",\n    ]\n\n    _HIGH_RISK_NAMES = {\n        \"cryptominer\",\"miner\",\"torrent\",\"hack\",\"crack\",\"keygen\",\"patch\",\n        \"loader\",\"injector\",\"rat\",\"trojan\",\"worm\",\"virus\",\"malware\",\n        \"spyware\",\"adware\",\"pup\",\"hijack\",\"rootkit\",\n    }\n\n    def _susp_risk(self, name, path):\n        n = name.lower()\n        p = (path or \"\").lower()\n        if any(h in n for h in self._HIGH_RISK_NAMES):\n            return \"High\"\n        if any(ind in p for ind in self._SUSPICIOUS_INDICATORS):\n            return \"Medium\"\n        if n not in self._KNOWN_SAFE and name.endswith(\".exe\"):\n            if any(c.isdigit() for c in name[:6]):\n                return \"Medium\"\n        return \"Low\"\n\n    def _susp_insert(self, category, name, risk, location, action, meta=None):\n        tag = {\"High\":\"high\",\"Medium\":\"medium\"}.get(risk,\"low\")\n        iid = self.susp_tree.insert(\"\",\"end\",\n            values=(category, name, risk, location, action), tags=(tag,))\n        self._susp_meta[iid] = meta or {}\n\n    # \u2500\u2500 Running Process scan \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _do_susp_scan_procs(self, batch=False):\n        rows = []\n        for proc in psutil.process_iter(['pid','name','exe','cmdline','username','cpu_percent','memory_info']):\n            try:\n                pname = (proc.info.get('name') or \"\").strip()\n                exe   = (proc.info.get('exe')  or \"\").strip()\n                pid   = proc.info['pid']\n                if pid in (0, 4) or not pname:\n                    continue\n                risk = self._susp_risk(pname, exe)\n                try:\n                    mem_mb = round((proc.info.get('memory_info') or proc.memory_info()).rss / (1024*1024), 1)\n                    mem_str = f\"{mem_mb} MB\"\n                except:\n                    mem_str = \"--\"\n                rows.append((\"Running Proc\", pname, risk,\n                             f\"PID:{pid}  {exe[:55]}  RAM:{mem_str}\", \"Kill\",\n                             {\"pid\":pid,\"exe\":exe,\"type\":\"proc\",\n                              \"cmdline\":\" \".join(proc.info.get('cmdline') or [])}))\n            except:\n                pass\n\n        # Sort: High risk pehle, phir naam se\n        risk_order = {\"High\": 0, \"Medium\": 1, \"Low\": 2}\n        rows.sort(key=lambda r: (risk_order.get(r[2], 3), r[1].lower()))\n\n        def insert():\n            for r in rows:\n                self._susp_insert(*r)\n            if not batch:\n                flagged = sum(1 for r in rows if r[2] in (\"High\",\"Medium\"))\n                self.susp_count_vars[\"proc\"].set(str(len(rows)))\n                self.susp_status.config(\n                    text=f\"  Processes: {len(rows)} total  |  {flagged} flagged (High/Medium)\",\n                    fg=C[\"warning\"] if flagged else C[\"success\"])\n        self.after(0, insert)\n        return len(rows)\n\n    # \u2500\u2500 Startup scan (Registry + Folder) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _do_susp_scan_startup(self, batch=False):\n        rows = []\n        reg_paths = [\n            (winreg.HKEY_CURRENT_USER,  r\"Software\\Microsoft\\Windows\\CurrentVersion\\Run\",     \"HKCU Run\"),\n            (winreg.HKEY_LOCAL_MACHINE, r\"Software\\Microsoft\\Windows\\CurrentVersion\\Run\",     \"HKLM Run\"),\n            (winreg.HKEY_CURRENT_USER,  r\"Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce\", \"HKCU RunOnce\"),\n            (winreg.HKEY_LOCAL_MACHINE, r\"Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce\", \"HKLM RunOnce\"),\n            (winreg.HKEY_LOCAL_MACHINE, r\"Software\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Run\", \"HKLM Run(32)\"),\n        ]\n        for hive, path, label in reg_paths:\n            try:\n                key = winreg.OpenKey(hive, path, 0, winreg.KEY_READ)\n                i = 0\n                while True:\n                    try:\n                        name, value, _ = winreg.EnumValue(key, i)\n                        risk = self._susp_risk(name, value)\n                        # Flag anything in risky paths or unknown names\n                        if risk != \"Low\" or any(ind in value.lower()\n                                                 for ind in self._SUSPICIOUS_INDICATORS):\n                            rows.append((f\"Startup/{label}\", name, risk,\n                                         value[:80], \"Disable\",\n                                         {\"type\":\"reg_startup\",\"hive\":hive,\n                                          \"path\":path,\"name\":name,\"value\":value}))\n                        i += 1\n                    except OSError:\n                        break\n                winreg.CloseKey(key)\n            except:\n                pass\n\n        # Startup folders\n        for folder, label in [\n            (os.path.join(os.environ.get(\"APPDATA\",\"\"),\n                          r\"Microsoft\\Windows\\Start Menu\\Programs\\Startup\"), \"User Startup Folder\"),\n            (os.path.join(os.environ.get(\"PROGRAMDATA\",\"\"),\n                          r\"Microsoft\\Windows\\Start Menu\\Programs\\StartUp\"),  \"Common Startup Folder\"),\n        ]:\n            if not os.path.exists(folder):\n                continue\n            for f in Path(folder).glob(\"*\"):\n                if f.is_file():\n                    risk = self._susp_risk(f.name, str(f))\n                    rows.append((f\"Startup Folder\", f.name, risk,\n                                 str(f)[:80], \"Open Folder\",\n                                 {\"type\":\"folder_startup\",\"path\":str(f)}))\n\n        def insert():\n            for r in rows:\n                self._susp_insert(*r)\n            if not batch:\n                self.susp_count_vars[\"startup\"].set(str(len(rows)))\n                self.susp_status.config(\n                    text=f\"  Startup scan: {len(rows)} flagged\", fg=C[\"warning\"] if rows else C[\"success\"])\n        self.after(0, insert)\n        return len(rows)\n\n    # \u2500\u2500 Hidden folder scan \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _do_susp_scan_hidden(self, batch=False):\n        rows = []\n        scan_roots = [\n            os.environ.get(\"APPDATA\",\"\"),\n            os.environ.get(\"LOCALAPPDATA\",\"\"),\n            os.environ.get(\"PROGRAMDATA\",\"\"),\n            os.path.join(os.environ.get(\"SYSTEMROOT\",\"C:\\\\Windows\"), \"Temp\"),\n            os.path.join(os.environ.get(\"SYSTEMROOT\",\"C:\\\\Windows\"), \"System32\\\\Tasks\"),\n        ]\n        exe_exts = {\".exe\",\".bat\",\".cmd\",\".vbs\",\".ps1\",\".js\",\".scr\",\".pif\",\".com\"}\n        count = 0\n        for root_path in scan_roots:\n            if not os.path.exists(root_path):\n                continue\n            try:\n                for entry in os.scandir(root_path):\n                    try:\n                        # Hidden attribute check (Windows: FILE_ATTRIBUTE_HIDDEN = 2)\n                        attrs = entry.stat().st_file_attributes if hasattr(entry.stat(), 'st_file_attributes') else 0\n                        is_hidden = bool(attrs &amp; 2)\n                        ext = os.path.splitext(entry.name)[1].lower()\n                        is_exec = ext in exe_exts\n                        if is_hidden and is_exec:\n                            risk = \"High\"\n                        elif is_hidden and entry.is_dir():\n                            risk = \"Medium\"\n                        elif is_exec and any(\n                                ind in entry.path.lower()\n                                for ind in [\"temp\",\"tmp\",\"appdata\",\"programdata\"]):\n                            risk = \"Medium\"\n                        else:\n                            continue\n                        rows.append((\"Hidden/Temp Exec\",\n                                     entry.name, risk,\n                                     entry.path[:80], \"Open Folder\",\n                                     {\"type\":\"hidden_file\",\"path\":entry.path}))\n                        count += 1\n                        if count &gt;= 50:\n                            break\n                    except:\n                        pass\n            except:\n                pass\n            if count &gt;= 50:\n                break\n\n        def insert():\n            for r in rows:\n                self._susp_insert(*r)\n            if not batch:\n                self.susp_count_vars[\"hidden\"].set(str(len(rows)))\n                self.susp_status.config(\n                    text=f\"  Hidden scan: {len(rows)} flagged\", fg=C[\"warning\"] if rows else C[\"success\"])\n        self.after(0, insert)\n        return len(rows)\n\n    # \u2500\u2500 Unknown Scheduled Task scan \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _do_susp_scan_tasks(self, batch=False):\n        rows = []\n        out, _ = self._run_cmd('schtasks /query /fo CSV /v', timeout=20)\n        ms_paths = {\"\\\\microsoft\\\\\", \"\\\\windows\\\\\"}\n        seen = set()\n        for record in self._task_records_from_schtasks(out):\n            task_path = (record.get(\"TaskName\") or \"\").strip()\n            status = (record.get(\"Status\") or record.get(\"Scheduled Task State\") or \"\").strip()\n            run_as = (record.get(\"Run As User\") or \"\").strip()\n            task_to_run = (record.get(\"Task To Run\") or \"\").strip()\n            if not task_path or task_path in seen:\n                continue\n            seen.add(task_path)\n            path_low = task_path.lower()\n            process_text = task_to_run or task_path\n            if any(ms in path_low for ms in ms_paths):\n                continue\n            if status.lower() == \"disabled\":\n                continue\n            risk = \"High\" if any(x in (path_low + \" \" + process_text.lower()) for x in [\"temp\",\"tmp\",\"appdata\",\"programdata\",\"public\"]) else \"Medium\"\n            rows.append((\"Unknown Task\", task_path, risk,\n                         f\"Status:{status}  RunAs:{run_as[:30]}  Process:{process_text[:60]}\", \"Disable\",\n                         {\"type\":\"task\",\"path\":task_path}))\n\n        def insert():\n            for r in rows:\n                self._susp_insert(*r)\n            if not batch:\n                self.susp_count_vars[\"tasks\"].set(str(len(rows)))\n                self.susp_status.config(\n                    text=f\"  Task scan: {len(rows)} flagged\", fg=C[\"warning\"] if rows else C[\"success\"])\n        self.after(0, insert)\n        return len(rows)\n\n    # \u2500\u2500 Selection handler \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _susp_on_select(self, event=None):\n        sel = self.susp_tree.selection()\n        if not sel:\n            return\n        iid = sel[0]\n        vals = self.susp_tree.item(iid, \"values\")\n        meta = self._susp_meta.get(iid, {})\n        cat, name, risk, location, action = vals\n        lines = [\n            f\"Category  : {cat}\",\n            f\"Name      : {name}\",\n            f\"Risk      : {risk}\",\n            f\"Location  : {location}\",\n            f\"Action    : {action}\",\n            \"\",\n        ]\n        if meta.get(\"exe\"):\n            lines.append(f\"EXE Path  : {meta['exe']}\")\n        if meta.get(\"cmdline\"):\n            lines.append(f\"CMD Line  : {meta['cmdline'][:200]}\")\n        if meta.get(\"value\"):\n            lines.append(f\"Reg Value : {meta['value']}\")\n        lines += [\"\", \"\u2500\"*50, \"\"]\n        t = meta.get(\"type\",\"\")\n        if risk == \"High\":\n            lines.append(\"\u26a0 RECOMMENDATION: High-risk entry detected!\")\n            lines.append(\"  \u2192 Terminate/disable immediately if you don't recognize it.\")\n            lines.append(\"  \u2192 Upload the EXE to virustotal.com for verification.\")\n        elif risk == \"Medium\":\n            lines.append(\"\u26a0 RECOMMENDATION: Unknown entry \u2014 verify before disabling.\")\n            lines.append(\"  \u2192 Search the process name online.\")\n            lines.append(\"  \u2192 If not recognized, use 'Disable Selected'.\")\n        else:\n            lines.append(\"\u2139 LOW RISK \u2014 Unusual location but may be legitimate.\")\n            lines.append(\"  \u2192 Monitor if CPU/RAM usage is high.\")\n        if t == \"proc\":\n            lines.append(f\"\\nKill command: taskkill /PID {meta.get('pid','')} /F\")\n        elif t in (\"reg_startup\",\"folder_startup\"):\n            lines.append(\"\\nTo remove: use 'Disable Selected' button above.\")\n        elif t == \"task\":\n            lines.append(f\"\\nDisable: schtasks /Change /TN \\\"{meta.get('path','')}\\\" /Disable\")\n\n        self.susp_detail.config(state=\"normal\")\n        self.susp_detail.delete(\"1.0\",\"end\")\n        self.susp_detail.insert(\"end\", \"\\n\".join(lines))\n        self.susp_detail.config(state=\"disabled\")\n\n    # \u2500\u2500 Action buttons \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    def _susp_kill_selected(self):\n        sel = self.susp_tree.selection()\n        if not sel:\n            messagebox.showinfo(\"No Selection\",\"Select a running process entry to kill.\")\n            return\n        killed = 0\n        for iid in sel:\n            meta = self._susp_meta.get(iid, {})\n            if meta.get(\"type\") == \"proc\":\n                pid = meta.get(\"pid\")\n                if pid and messagebox.askyesno(\"Kill Process\",\n                        f\"Kill PID {pid} ({self.susp_tree.item(iid,'values')[1]})?\"):\n                    out, rc = self._run_cmd(f'taskkill /PID {pid} /F')\n                    if rc == 0:\n                        self.susp_tree.delete(iid)\n                        killed += 1\n                    else:\n                        messagebox.showerror(\"Failed\", f\"Could not kill PID {pid}:\\n{out}\")\n        if killed:\n            self._set_status(f\"Killed {killed} process(es)\", C[\"success\"])\n\n    def _susp_disable_selected(self):\n        sel = self.susp_tree.selection()\n        if not sel:\n            messagebox.showinfo(\"No Selection\",\"Select an entry to disable.\")\n            return\n        disabled = 0\n        for iid in sel:\n            meta = self._susp_meta.get(iid, {})\n            t = meta.get(\"type\",\"\")\n            name_disp = self.susp_tree.item(iid,\"values\")[1]\n            if not messagebox.askyesno(\"Disable Entry\", f\"Disable '{name_disp}'?\"):\n                continue\n            try:\n                if t == \"reg_startup\":\n                    hive = meta[\"hive\"]\n                    path = meta[\"path\"]\n                    name = meta[\"name\"]\n                    value = meta[\"value\"]\n                    key = winreg.OpenKey(hive, path, 0,\n                                        winreg.KEY_SET_VALUE | winreg.KEY_READ)\n                    # Rename with disabled prefix\n                    winreg.SetValueEx(key, \"__GodawariDisabled__\"+name, 0,\n                                      winreg.REG_SZ, value)\n                    winreg.DeleteValue(key, name)\n                    winreg.CloseKey(key)\n                    disabled += 1\n                    self.susp_tree.delete(iid)\n                elif t == \"folder_startup\":\n                    src = Path(meta[\"path\"])\n                    dst = src.with_name(src.name + \".disabled\")\n                    if src.exists():\n                        src.rename(dst)\n                    disabled += 1\n                    self.susp_tree.delete(iid)\n                elif t == \"task\":\n                    task_path = meta.get(\"path\",\"\")\n                    self._run_cmd(f'schtasks /Change /TN \"{task_path}\" /Disable')\n                    disabled += 1\n                    self.susp_tree.delete(iid)\n                elif t == \"hidden_file\":\n                    path = meta.get(\"path\",\"\")\n                    if messagebox.askyesno(\"Delete File\",\n                            f\"Delete this suspicious file?\\n{path}\"):\n                        try:\n                            os.remove(path)\n                        except Exception as e:\n                            messagebox.showerror(\"Error\", str(e))\n                    disabled += 1\n                    self.susp_tree.delete(iid)\n            except Exception as e:\n                messagebox.showerror(\"Error\", f\"Could not disable {name_disp}:\\n{e}\")\n        if disabled:\n            self._set_status(f\"Disabled {disabled} suspicious entry(ies)\", C[\"success\"])\n\n    def _create_restore_point(self, description=\"Godawari Optimizer\"):\n        if self._restore_prompt_count &gt; 0:\n            return True\n        mgr = getattr(self, \"restore_point_manager\", None)\n        if mgr is None:\n            return True\n\n        def _ask(desc):\n            return messagebox.askyesno(\"Restore Point\", f\"Create restore point?\\n{desc}\")\n\n        self._restore_prompt_count += 1\n        self._set_status(\"Creating restore point...\", C[\"warning\"])\n        ok = mgr.create(description, ask_callback=_ask, force=False)\n        if ok:\n            self._audit_event(\"restore_point_created\", {\"description\": description})\n            return True\n        return messagebox.askyesno(\"Failed\", \"Restore point failed. Continue anyway?\")\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # HDD / SSD REPAIR SECTION \u2014 Real Actions with Before/After Proof\n    # Features: SMART, Bad Sector Repair, MBR/BCD Fix, NTFS Fix,\n    #           Partition Repair, VSS Repair, Defrag/TRIM, Offline Mode\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _build_hdd_repair(self, parent):\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n\n        # \u2500\u2500 Section Header \u2500\u2500\n        hdr = tk.Frame(frame, bg=C[\"panel\"], pady=10)\n        hdr.pack(fill=\"x\")\n        tk.Label(hdr, text=\"\ud83d\udcbe  HDD / SSD REPAIR CENTER\",\n                 font=(\"Segoe UI\", 15, \"bold\"), fg=C[\"accent\"], bg=C[\"panel\"]).pack(side=\"left\", padx=18)\n        tk.Label(hdr, text=\"Real Repair \u2022 Bad Sector Fix \u2022 MBR/BCD \u2022 NTFS \u2022 Partition \u2022 WinPE Mode\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"left\", padx=6)\n        tk.Frame(hdr, bg=C[\"accent\"], height=2).pack(side=\"bottom\", fill=\"x\")\n\n        # \u2500\u2500 Scrollable content \u2500\u2500\n        outer = tk.Frame(frame, bg=C[\"bg\"])\n        outer.pack(fill=\"both\", expand=True)\n        canvas2 = tk.Canvas(outer, bg=C[\"bg\"], highlightthickness=0)\n        vsb = tk.Scrollbar(outer, orient=\"vertical\", command=canvas2.yview)\n        self.hdd_scroll_frame = tk.Frame(canvas2, bg=C[\"bg\"])\n        self.hdd_scroll_frame.bind(\"\",\n            lambda e: canvas2.configure(scrollregion=canvas2.bbox(\"all\")))\n        hdd_window = canvas2.create_window((0, 0), window=self.hdd_scroll_frame, anchor=\"nw\")\n        canvas2.configure(yscrollcommand=vsb.set)\n        vsb.pack(side=\"right\", fill=\"y\")\n        canvas2.pack(side=\"left\", fill=\"both\", expand=True)\n\n        def _hdd_resize(e):\n            try:\n                canvas2.itemconfig(hdd_window, width=e.width)\n                canvas2.configure(scrollregion=canvas2.bbox(\"all\"))\n            except Exception:\n                pass\n        canvas2.bind(\"\", _hdd_resize)\n\n        def _hdd_scroll(e):\n            canvas2.yview_scroll(int(-1*(e.delta/120)), \"units\")\n        self._bind_scoped_mousewheel(self.hdd_scroll_frame, canvas2)\n        sf = self.hdd_scroll_frame  # shorthand\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # ROW 1 \u2014 Drive Selector + SMART Info\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        row1 = tk.Frame(sf, bg=C[\"bg\"])\n        row1.pack(fill=\"x\", padx=14, pady=(12, 4))\n\n        # Drive Selector Card\n        drv_card = tk.LabelFrame(row1, text=\" \ud83d\uddb4  Drive Selector \",\n                                 font=FONTS[\"subhead\"], fg=C[\"accent\"],\n                                 bg=C[\"card\"], bd=1, relief=\"flat\")\n        drv_card.pack(side=\"left\", fill=\"y\", padx=(0, 8))\n\n        tk.Label(drv_card, text=\"Target Drive:\", font=FONTS[\"body\"],\n                 fg=C[\"text_dim\"], bg=C[\"card\"]).grid(row=0, column=0, padx=10, pady=6, sticky=\"w\")\n        self.hdd_drive_var = tk.StringVar(value=\"C:\")\n        drives = self._get_available_drives()\n        drv_cb = ttk.Combobox(drv_card, textvariable=self.hdd_drive_var,\n                               values=drives, width=8, state=\"readonly\")\n        drv_cb.grid(row=0, column=1, padx=8, pady=6)\n\n        tk.Label(drv_card, text=\"Mode:\", font=FONTS[\"body\"],\n                 fg=C[\"text_dim\"], bg=C[\"card\"]).grid(row=1, column=0, padx=10, pady=4, sticky=\"w\")\n        self.hdd_mode_var = tk.StringVar(value=\"Online (Live Windows)\")\n        mode_cb = ttk.Combobox(drv_card, textvariable=self.hdd_mode_var,\n                                values=[\"Online (Live Windows)\", \"Offline / WinPE Mode\"],\n                                width=22, state=\"readonly\")\n        mode_cb.grid(row=1, column=1, padx=8, pady=4)\n\n        tk.Button(drv_card, text=\"\ud83d\udd04  Refresh Drives\", font=FONTS[\"small\"],\n                  bg=C[\"btn\"], fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=self._hdd_refresh_drives(drv_cb)).grid(row=2, column=0, columnspan=2,\n                                                                   padx=10, pady=8, sticky=\"ew\")\n\n        # SMART Status Card\n        smart_card = tk.LabelFrame(row1, text=\" \ud83d\udcca  S.M.A.R.T. Drive Health \",\n                                    font=FONTS[\"subhead\"], fg=C[\"accent\"],\n                                    bg=C[\"card\"], bd=1, relief=\"flat\")\n        smart_card.pack(side=\"left\", fill=\"both\", expand=True)\n\n        self.smart_log = scrolledtext.ScrolledText(smart_card, font=FONTS[\"mono\"],\n                                                    bg=\"#050D1A\", fg=C[\"success\"],\n                                                    height=7, state=\"disabled\",\n                                                    insertbackground=C[\"accent\"])\n        self.smart_log.pack(fill=\"both\", expand=True, padx=8, pady=6)\n\n        btn_smart_row = tk.Frame(smart_card, bg=C[\"card\"])\n        btn_smart_row.pack(fill=\"x\", padx=8, pady=(0, 8))\n        tk.Button(btn_smart_row, text=\"\ud83d\udcca Full SMART Report\",\n                  font=FONTS[\"small\"], bg=C[\"btn_info\"], fg=C[\"text\"],\n                  bd=0, padx=10, pady=5, cursor=\"hand2\",\n                  command=self._hdd_smart_report).pack(side=\"left\", padx=4)\n        tk.Button(btn_smart_row, text=\"\u26a1 Quick SMART Check\",\n                  font=FONTS[\"small\"], bg=C[\"btn\"], fg=C[\"text\"],\n                  bd=0, padx=10, pady=5, cursor=\"hand2\",\n                  command=self._hdd_smart_quick).pack(side=\"left\", padx=4)\n        tk.Button(btn_smart_row, text=\"\ud83d\udcbe Save Report\",\n                  font=FONTS[\"small\"], bg=C[\"accent2\"], fg=\"#000\",\n                  bd=0, padx=10, pady=5, cursor=\"hand2\",\n                  command=lambda: self._hdd_save_log(self.smart_log, \"SMART_Report\")).pack(side=\"left\", padx=4)\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # ROW 2 \u2014 Action Buttons Grid\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        row2_lbl = tk.Frame(sf, bg=C[\"bg\"])\n        row2_lbl.pack(fill=\"x\", padx=14, pady=(10, 2))\n        tk.Label(row2_lbl, text=\"\ud83d\udd27  REPAIR ACTIONS  \u2014  Har button real command chalata hai. Proof log mein dikh'ta hai.\",\n                 font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"bg\"]).pack(side=\"left\")\n\n        row2 = tk.Frame(sf, bg=C[\"bg\"])\n        row2.pack(fill=\"x\", padx=14, pady=2)\n\n        def repair_btn(parent, emoji, title, subtitle, color, cmd_func, col, row_n):\n            card = tk.Frame(parent, bg=C[\"card\"], bd=1, relief=\"flat\",\n                            highlightbackground=color, highlightthickness=1)\n            card.grid(row=row_n, column=col, padx=5, pady=5, sticky=\"nsew\")\n            parent.columnconfigure(col, weight=1)\n            tk.Label(card, text=emoji, font=(\"Segoe UI\", 20),\n                     fg=color, bg=C[\"card\"]).pack(pady=(8, 2))\n            tk.Label(card, text=title, font=FONTS[\"subhead\"],\n                     fg=C[\"text\"], bg=C[\"card\"]).pack()\n            tk.Label(card, text=subtitle, font=FONTS[\"small\"],\n                     fg=C[\"text_dim\"], bg=C[\"card\"], wraplength=170).pack(padx=6)\n            tk.Button(card, text=\"\u25b6  Run\", font=FONTS[\"small\"],\n                      bg=color, fg=\"#000\" if color in [C[\"accent\"], C[\"accent2\"]] else C[\"text\"],\n                      bd=0, padx=12, pady=5, cursor=\"hand2\",\n                      command=cmd_func).pack(pady=(6, 10))\n\n        repair_btn(row2, \"\ud83e\ude7a\", \"Bad Sector Scan+Fix\",\n                   \"chkdsk /f /r /x\\nBad sectors mark+recover\", C[\"warning\"],\n                   self._hdd_bad_sector_fix, 0, 0)\n        repair_btn(row2, \"\ud83d\udd11\", \"MBR / Boot Repair\",\n                   \"bootrec /fixmbr\\nbootrec /fixboot\\nbootrec /rebuildbcd\", C[\"accent3\"],\n                   self._hdd_mbr_repair, 1, 0)\n        repair_btn(row2, \"\ud83d\udcc1\", \"NTFS File System Fix\",\n                   \"fsutil dirty bit\\nNTFS journal reset\\nchkdsk /f\", C[\"accent\"],\n                   self._hdd_ntfs_fix, 2, 0)\n        repair_btn(row2, \"\ud83d\udcc2\", \"Partition Table Repair\",\n                   \"diskpart automount\\nPartition visibility\\nDrive letter assign\", C[\"btn_info\"],\n                   self._hdd_partition_repair, 3, 0)\n\n        row2b = tk.Frame(sf, bg=C[\"bg\"])\n        row2b.pack(fill=\"x\", padx=14, pady=2)\n        repair_btn(row2b, \"\ud83d\udd04\", \"VSS / Shadow Copy Fix\",\n                   \"VSS service repair\\nShadow storage reset\", C[\"accent2\"],\n                   self._hdd_vss_repair, 0, 0)\n        repair_btn(row2b, \"\u26a1\", \"SSD TRIM + Optimize\",\n                   \"Optimize-Volume -ReTrim\\nSSD best practice\", C[\"hw_accent\"],\n                   self._hdd_ssd_trim, 1, 0)\n        repair_btn(row2b, \"\ud83d\uddc2\", \"HDD Defrag\",\n                   \"defrag /U /V /X\\nFull defrag + report\", C[\"accent4\"],\n                   self._hdd_defrag, 2, 0)\n        repair_btn(row2b, \"\ud83e\udd16\", \"Auto Optimize (TRIM/Defrag)\",\n                   \"Detect SSD/HDD\\nRun best optimize\", C[\"btn_chip\"],\n                   self._hdd_auto_optimize, 3, 0)\n        repair_btn(row2b, \"\ud83e\uddf9\", \"Disk Cleanup (Deep)\",\n                   \"cleanmgr /sagerun:1\\nSystem files bhi clean\", C[\"btn\"],\n                   self._hdd_deep_cleanup, 3, 0)\n\n        row2c = tk.Frame(sf, bg=C[\"bg\"])\n        row2c.pack(fill=\"x\", padx=14, pady=2)\n        repair_btn(row2c, \"\ud83c\udfe5\", \"SFC + DISM Full Repair\",\n                   \"SFC /scannow output\\nDISM RestoreHealth live\", C[\"accent3\"],\n                   self._hdd_sfc_dism_full, 0, 0)\n        repair_btn(row2c, \"\ud83d\udccb\", \"Error Event Log\",\n                   \"Last 20 Disk errors\\nEvent Viewer data\", C[\"accent\"],\n                   self._hdd_error_log, 1, 0)\n        repair_btn(row2c, \"\ud83d\udca5\", \"BSoD / Crash Dump Info\",\n                   \"Last crash details\\nMinidump analysis\", C[\"accent3\"],\n                   self._hdd_bsod_info, 2, 0)\n        repair_btn(row2c, \"\ud83d\ude80\", \"One-Click Full Repair\",\n                   \"SMART+SFC+CHKDSK\\n+MBR+VSS \u2014 All in one\", C[\"warning\"],\n                   self._hdd_full_repair, 3, 0)\n\n        svc_card = tk.LabelFrame(sf, text=\" \ud83d\udee1\ufe0f  Win32 Telemetry Service Control Panel \",\n                                 font=FONTS[\"subhead\"], fg=C[\"accent4\"],\n                                 bg=C[\"card\"], bd=1, relief=\"flat\")\n        svc_card.pack(fill=\"x\", padx=14, pady=(10, 4))\n        tk.Label(svc_card,\n                 text=\"Only safe, non-essential telemetry services are shown here. Critical OS services are excluded.\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"], justify=\"left\").pack(anchor=\"w\", padx=10, pady=(10, 2))\n        svc_row = tk.Frame(svc_card, bg=C[\"card\"])\n        svc_row.pack(fill=\"x\", padx=10, pady=(0, 6))\n        self.hdd_service_status_lbl = tk.Label(svc_row, text=\"Telemetry panel ready\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"])\n        self.hdd_service_status_lbl.pack(side=\"left\", anchor=\"w\")\n        tk.Button(svc_row, text=\"\ud83d\udd0d Scan Safe Services\", font=FONTS[\"small\"], bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=10, pady=4, cursor=\"hand2\",\n                  command=self._hdd_refresh_service_list).pack(side=\"right\", padx=4)\n        list_frame = tk.Frame(svc_card, bg=C[\"card\"])\n        list_frame.pack(fill=\"x\", padx=10, pady=(0, 6))\n        self.hdd_service_listbox = tk.Listbox(list_frame, height=4, selectmode=\"extended\",\n                                              bg=C[\"bg\"], fg=C[\"text\"], font=FONTS[\"small\"], relief=\"flat\", bd=0)\n        self.hdd_service_listbox.pack(side=\"left\", fill=\"both\", expand=True)\n        scrollbar = tk.Scrollbar(list_frame, orient=\"vertical\", command=self.hdd_service_listbox.yview)\n        scrollbar.pack(side=\"right\", fill=\"y\")\n        self.hdd_service_listbox.config(yscrollcommand=scrollbar.set)\n        action_row = tk.Frame(svc_card, bg=C[\"card\"])\n        action_row.pack(fill=\"x\", padx=10, pady=(0, 10))\n        tk.Button(action_row, text=\"\u26d4 Stop Selected\", font=FONTS[\"small\"], bg=C[\"btn_warn\"], fg=C[\"text\"], bd=0, padx=10, pady=4, cursor=\"hand2\",\n                  command=self._hdd_stop_selected_telemetry_services).pack(side=\"left\", padx=4)\n        tk.Button(action_row, text=\"\u267b\ufe0f Refresh Status\", font=FONTS[\"small\"], bg=C[\"btn\"], fg=C[\"text\"], bd=0, padx=10, pady=4, cursor=\"hand2\",\n                  command=self._hdd_refresh_service_list).pack(side=\"left\", padx=4)\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # ROW 3 \u2014 WinPE / Offline Mode\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        winpe_card = tk.LabelFrame(sf, text=\" \ud83d\udda5\ufe0f  WinPE / Offline Mode \u2014 Boot-Level Repair Commands \",\n                                    font=FONTS[\"subhead\"], fg=C[\"accent4\"],\n                                    bg=C[\"card\"], bd=1, relief=\"flat\")\n        winpe_card.pack(fill=\"x\", padx=14, pady=(10, 4))\n\n        winpe_info = tk.Frame(winpe_card, bg=C[\"card\"])\n        winpe_info.pack(fill=\"x\", padx=10, pady=(6, 4))\n        info_text = (\"WinPE / Offline Mode mein yeh tool Windows Recovery Environment (RE) ke saath kaam karta hai.\\n\"\n                     \"Jab Windows boot nahi hota \u2014 tab bhi yeh commands kaam karte hain.\\n\"\n                     \"How to use: PC restart karo \u2192 F8/Shift+F8 dabao \u2192 Troubleshoot \u2192 Command Prompt \u2192 script chalao\")\n        tk.Label(winpe_info, text=info_text, font=FONTS[\"small\"], fg=C[\"accent4\"],\n                 bg=C[\"card\"], justify=\"left\").pack(anchor=\"w\")\n\n        winpe_btns = tk.Frame(winpe_card, bg=C[\"card\"])\n        winpe_btns.pack(fill=\"x\", padx=10, pady=(2, 10))\n\n        def wbtn(txt, cmd, col):\n            tk.Button(winpe_btns, text=txt, font=FONTS[\"small\"],\n                      bg=C[\"btn_warn\"], fg=C[\"text\"], bd=0, padx=10, pady=6,\n                      cursor=\"hand2\", command=cmd).grid(row=0, column=col, padx=4, pady=2, sticky=\"ew\")\n            winpe_btns.columnconfigure(col, weight=1)\n\n        wbtn(\"\ud83d\udd11 Generate MBR Fix .bat\", self._winpe_gen_mbr_bat, 0)\n        wbtn(\"\ud83e\ude7a Generate ChkDsk .bat\", self._winpe_gen_chkdsk_bat, 1)\n        wbtn(\"\ud83d\udccb Generate Full Repair .bat\", self._winpe_gen_full_bat, 2)\n        wbtn(\"\ud83d\udcbf Open Windows RE\", self._winpe_open_recovery, 3)\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # ROW 4 \u2014 Action Log\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        log_card = tk.LabelFrame(sf, text=\" \ud83d\udccb  Repair Action Log \u2014 Proof of Every Action \",\n                                  font=FONTS[\"subhead\"], fg=C[\"accent2\"],\n                                  bg=C[\"card\"], bd=1, relief=\"flat\")\n        log_card.pack(fill=\"x\", padx=14, pady=(6, 14))\n\n        log_btns = tk.Frame(log_card, bg=C[\"card\"])\n        log_btns.pack(fill=\"x\", padx=8, pady=(6, 2))\n        tk.Button(log_btns, text=\"\ud83d\uddd1 Clear Log\", font=FONTS[\"small\"],\n                  bg=C[\"btn_danger\"], fg=C[\"text\"], bd=0, padx=8, pady=4,\n                  cursor=\"hand2\",\n                  command=lambda: self._hdd_clear_log()).pack(side=\"left\", padx=4)\n        tk.Button(log_btns, text=\"\ud83d\udcbe Save Log to Desktop\", font=FONTS[\"small\"],\n                  bg=C[\"accent2\"], fg=\"#000\", bd=0, padx=8, pady=4,\n                  cursor=\"hand2\",\n                  command=lambda: self._hdd_save_log(self.hdd_log, \"HDD_Repair_Log\")).pack(side=\"left\", padx=4)\n\n        self.hdd_log = scrolledtext.ScrolledText(log_card, font=FONTS[\"mono\"],\n                                                  bg=\"#030810\", fg=C[\"text\"],\n                                                  height=12, state=\"disabled\",\n                                                  insertbackground=C[\"accent\"])\n        self.hdd_log.pack(fill=\"both\", expand=True, padx=8, pady=(2, 10))\n        self._hdd_log(\"\ud83d\udcbe HDD/SSD Repair Center Ready. Drive select karo aur action lo.\", C[\"accent\"])\n        self._hdd_log(f\"\ud83d\udda5  Mode: {self.hdd_mode_var.get()} | Drive: {self.hdd_drive_var.get()}\", C[\"text_dim\"])\n\n        return frame\n\n    # \u2500\u2500 Drive helpers \u2500\u2500\n    def _get_available_drives(self):\n        drives = []\n        for letter in \"CDEFGHIJKLMNOPQRSTUVWXYZ\":\n            path = f\"{letter}:\\\\\"\n            if os.path.exists(path):\n                drives.append(f\"{letter}:\")\n        return drives if drives else [\"C:\"]\n\n    def _hdd_refresh_drives(self, cb):\n        def _do():\n            drives = self._get_available_drives()\n            cb[\"values\"] = drives\n            self._hdd_log(f\"\ud83d\udd04 Drives refreshed: {', '.join(drives)}\", C[\"accent2\"])\n        return _do\n\n    def _hdd_log(self, msg, color=None):\n        ts = datetime.datetime.now().strftime(\"%H:%M:%S\")\n        full = f\"[{ts}]  {msg}\"\n        self._append_log(self.hdd_log, full, color or C[\"text\"])\n\n    def _hdd_clear_log(self):\n        try:\n            self.hdd_log.config(state=\"normal\")\n            self.hdd_log.delete(\"1.0\", \"end\")\n            self.hdd_log.config(state=\"disabled\")\n        except:\n            pass\n\n    def _hdd_save_log(self, widget, prefix):\n        try:\n            content = widget.get(\"1.0\", \"end\")\n            desktop = os.path.join(os.path.expanduser(\"~\"), \"Desktop\")\n            ts = datetime.datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n            fpath = os.path.join(desktop, f\"{prefix}_{ts}.txt\")\n            with open(fpath, \"w\", encoding=\"utf-8\") as f:\n                f.write(content)\n            messagebox.showinfo(\"Saved\", f\"Log saved to:\\n{fpath}\")\n            self._hdd_log(f\"\ud83d\udcbe Log saved: {fpath}\", C[\"accent2\"])\n        except Exception as e:\n            messagebox.showerror(\"Error\", str(e))\n\n    def _hdd_safe_telemetry_services(self):\n        return {\n            \"diagtrack\": \"Connected User Experiences and Telemetry\",\n            \"wersvc\": \"Windows Error Reporting Service\",\n            \"wmpnetworksvc\": \"WMP Network Sharing Service\",\n            \"dmwappushservice\": \"Device Management WAP Push Service\",\n            \"wsearch\": \"Windows Search\",\n        }\n\n    def _hdd_refresh_service_list(self):\n        try:\n            self.hdd_service_listbox.delete(0, \"end\")\n            safe_services = self._hdd_safe_telemetry_services()\n            found = []\n            for svc in psutil.win_service_iter():\n                try:\n                    info = svc.as_dict(attrs=[\"name\", \"display_name\", \"status\"])\n                except Exception:\n                    continue\n                name = str(info.get(\"name\", \"\") or \"\").lower()\n                if name not in safe_services:\n                    continue\n                display = safe_services.get(name, info.get(\"display_name\", \"Unknown\"))\n                status = str(info.get(\"status\", \"unknown\")).capitalize()\n                entry = f\"{name} | {display} | {status}\"\n                self.hdd_service_listbox.insert(\"end\", entry)\n                found.append(entry)\n            self.hdd_service_status_lbl.config(text=f\"{len(found)} safe telemetry services listed.\")\n            if not found:\n                self.hdd_service_status_lbl.config(text=\"No safe telemetry services found on this system.\")\n        except Exception as e:\n            self.hdd_service_status_lbl.config(text=f\"Service scan failed: {str(e)[:80]}\")\n\n    def _hdd_stop_selected_telemetry_services(self):\n        selected = [self.hdd_service_listbox.get(i) for i in self.hdd_service_listbox.curselection()]\n        if not selected:\n            messagebox.showinfo(\"Select Service\", \"Pehele ek ya zyada service select karo.\")\n            return\n        if not messagebox.askyesno(\"Stop Services\", \"Selected telemetry services ko stop karna safe hai. Continue karo?\"):\n            return\n        stopped = 0\n        errors = []\n        for row in selected:\n            name = row.split(\"|\")[0].strip()\n            try:\n                svc = psutil.win_service_get(name)\n                status = svc.status()\n                if status.lower() == \"running\":\n                    svc.stop()\n                    stopped += 1\n                    self._hdd_service_status_lbl.config(text=f\"Stopping {name}...\")\n                else:\n                    errors.append(f\"{name} already {status}\")\n            except Exception as e:\n                errors.append(f\"{name}: {e}\")\n        if stopped:\n            self._hdd_service_status_lbl.config(text=f\"{stopped} telemetry service(s) stop requested.\")\n        if errors:\n            self._hdd_service_status_lbl.config(text=f\"Errors: {len(errors)} (see log)\")\n        self._hdd_recovery_emit_metrics({\n            \"service_control\": f\"Stopped {stopped} services | Errors: {len(errors)}\",\n            \"status_text\": \"Telemetry service control action complete.\",\n            \"progress_pct\": None,\n        })\n\n    def _hdd_action_submit(self, name, target, *args, **kwargs):\n        if not hasattr(self, \"_hdd_action_lock\"):\n            self._hdd_action_lock = threading.Lock()\n            self._hdd_action_running = False\n        with self._hdd_action_lock:\n            if getattr(self, \"_hdd_action_running\", False):\n                self._hdd_log(\"\u26a0\ufe0f HDD/Recovery action already running \u2014 duplicate request skipped.\", C[\"warning\"])\n                return False\n            self._hdd_action_running = True\n\n        def _wrapped(*args, **kwargs):\n            try:\n                return target(*args, **kwargs)\n            finally:\n                with self._hdd_action_lock:\n                    self._hdd_action_running = False\n                try:\n                    gc.collect()\n                except Exception:\n                    pass\n\n        manager = getattr(self, \"worker_manager\", None)\n        if manager is not None and hasattr(manager, \"submit\"):\n            try:\n                manager.submit(name, _wrapped, *args, **kwargs)\n                return True\n            except Exception:\n                pass\n        try:\n            threading.Thread(target=_wrapped, args=args, kwargs=kwargs, daemon=True).start()\n            return True\n        except Exception:\n            return False\n\n    def _do_kernel_working_set_trim(self):\n        batch = {\n            \"phase\": \"kernel_trim\",\n            \"status_text\": \"Kernel working-set trim running...\",\n            \"progress_pct\": 0.0,\n            \"trimmed_processes\": 0,\n            \"errors\": 0,\n            \"delta_mb\": 0,\n        }\n        self._hdd_recovery_emit_metrics(batch)\n        before = psutil.virtual_memory()\n        kernel32 = ctypes.windll.kernel32\n        psapi = ctypes.windll.psapi\n        last_dispatch = time.monotonic()\n        safe_system = {\n            \"system\", \"idle\", \"csrss.exe\", \"wininit.exe\", \"services.exe\",\n            \"lsass.exe\", \"smss.exe\", \"svchost.exe\", \"explorer.exe\", \"dwm.exe\",\n            \"taskeng.exe\", \"taskhostw.exe\", \"winlogon.exe\",\n        }\n        for proc in psutil.process_iter(['pid', 'name']):\n            try:\n                pid = int(proc.info.get('pid') or 0)\n                if pid &lt;= 0 or pid == os.getpid():\n                    continue\n                name = str(proc.info.get('name') or '').lower()\n                if name in safe_system:\n                    continue\n                handle = kernel32.OpenProcess(0x001F0FFF, False, pid)\n                if not handle:\n                    continue\n                try:\n                    if psapi.EmptyWorkingSet(handle):\n                        batch[\"trimmed_processes\"] += 1\n                    try:\n                        kernel32.SetProcessWorkingSetSize(handle, -1, -1)\n                    except Exception:\n                        pass\n                finally:\n                    kernel32.CloseHandle(handle)\n            except (PermissionError, psutil.AccessDenied):\n                batch[\"errors\"] += 1\n            except Exception:\n                batch[\"errors\"] += 1\n            if time.monotonic() - last_dispatch &gt;= 0.120:\n                batch[\"status_text\"] = f\"Kernel trim scanning processes... {batch['trimmed_processes']} trimmed\"\n                batch[\"progress_pct\"] = min(100.0, (batch[\"trimmed_processes\"] / max(1, psutil.cpu_count(logical=False) * 3)) * 100.0)\n                self._hdd_recovery_emit_metrics(batch.copy())\n                last_dispatch = time.monotonic()\n        after = psutil.virtual_memory()\n        batch[\"status_text\"] = f\"Kernel trim complete \u2014 {batch['trimmed_processes']} processes trimmed\"\n        batch[\"progress_pct\"] = 100.0\n        batch[\"delta_mb\"] = int((after.available - before.available) / 1024**2)\n        self._hdd_recovery_emit_metrics(batch.copy())\n        self._hdd_log(f\"\u2705 Kernel working set trim complete, freed {self._fmt_size(batch['delta_mb'] * 1024**2)}\", C[\"success\"])\n\n    def _do_background_priority_demotion(self):\n        before = psutil.virtual_memory()\n        batch = {\n            \"phase\": \"priority_demotion\",\n            \"status_text\": \"Background process priority demotion running...\",\n            \"progress_pct\": 0.0,\n            \"demoted\": 0,\n            \"scanned\": 0,\n            \"errors\": 0,\n            \"delta_mb\": 0,\n        }\n        self._hdd_recovery_emit_metrics(batch)\n        idle_class = getattr(psutil, 'IDLE_PRIORITY_CLASS', getattr(psutil, 'BELOW_NORMAL_PRIORITY_CLASS', 64))\n        keep_names = {\n            'explorer.exe', 'taskmgr.exe', 'chrome.exe', 'firefox.exe', 'msedge.exe',\n            'dwm.exe', 'svchost.exe', 'services.exe', 'lsass.exe', 'wininit.exe',\n            'winlogon.exe', 'csrss.exe', 'system', 'idle', 'spoolsv.exe', 'steam.exe',\n        }\n        last_dispatch = time.monotonic()\n        for proc in psutil.process_iter(['pid', 'name', 'username', 'nice']):\n            batch[\"scanned\"] += 1\n            try:\n                pid = int(proc.info.get('pid') or 0)\n                if pid &lt;= 0 or pid == os.getpid():\n                    continue\n                name = str(proc.info.get('name') or '').lower()\n                username = str(proc.info.get('username') or '').lower()\n                if name in keep_names or any(term in name for term in ('microsoft', 'windows', 'service', 'system', 'sql', 'svchost')):\n                    continue\n                if username in ('nt authority\\\\system', 'local service', 'network service'):\n                    continue\n                current = proc.info.get('nice')\n                if current == idle_class:\n                    continue\n                try:\n                    proc.nice(idle_class)\n                    batch[\"demoted\"] += 1\n                except (PermissionError, psutil.AccessDenied):\n                    batch[\"errors\"] += 1\n                except Exception:\n                    batch[\"errors\"] += 1\n            except (PermissionError, psutil.AccessDenied):\n                batch[\"errors\"] += 1\n            except Exception:\n                batch[\"errors\"] += 1\n            if time.monotonic() - last_dispatch &gt;= 0.120:\n                batch[\"status_text\"] = f\"Demoting background apps... {batch['demoted']} demoted\"\n                batch[\"progress_pct\"] = min(100.0, (batch[\"scanned\"] / max(1, psutil.cpu_count(logical=False) * 10)) * 100.0)\n                self._hdd_recovery_emit_metrics(batch.copy())\n                last_dispatch = time.monotonic()\n        after = psutil.virtual_memory()\n        batch[\"status_text\"] = f\"Priority demotion done \u2014 {batch['demoted']} apps moved to idle\"\n        batch[\"progress_pct\"] = 100.0\n        batch[\"delta_mb\"] = int((after.available - before.available) / 1024**2) if 'before' in locals() else 0\n        self._hdd_recovery_emit_metrics(batch.copy())\n        self._hdd_log(f\"\u2705 Background process demotion complete: {batch['demoted']} processes\", C[\"success\"])\n\n    def _do_smart_standby_boost(self):\n        batch = {\n            \"phase\": \"standby_boost\",\n            \"status_text\": \"Smart standby booster evaluating memory...\",\n            \"progress_pct\": 0.0,\n            \"predicted_ram_mb\": 0,\n            \"confidence_score\": 0,\n            \"delta_mb\": 0,\n        }\n        vm = psutil.virtual_memory()\n        before = vm.available\n        standby_bytes = getattr(vm, 'standby', None) or getattr(vm, 'cached', 0)\n        standby_mb = int(standby_bytes / 1024**2)\n        predicted_free_mb = int(min(standby_mb * 0.65, before / 1024**2 * 0.60))\n        batch[\"predicted_ram_mb\"] = predicted_free_mb\n        batch[\"confidence_score\"] = min(98, max(35, int((standby_mb / max(1, vm.total / 1024**2)) * 100)))\n        batch[\"status_text\"] = f\"Standby booster ready \u2014 {self._fmt_size(standby_bytes)} standby memory detected\"\n        self._hdd_recovery_emit_metrics(batch.copy())\n        if standby_mb &lt; 64:\n            batch[\"status_text\"] = \"Standby memory low; no booster action required.\"\n            batch[\"progress_pct\"] = 100.0\n            self._hdd_recovery_emit_metrics(batch.copy())\n            self._hdd_log(\"\u2139\ufe0f Standby booster skipped; standby cache low.\", C[\"text_dim\"])\n            return\n        self._purge_memory_lists()\n        after = psutil.virtual_memory()\n        batch[\"delta_mb\"] = int((after.available - before) / 1024**2)\n        batch[\"status_text\"] = f\"Standby boost complete \u2014 freed {self._fmt_size(batch['delta_mb'] * 1024**2)}\"\n        batch[\"progress_pct\"] = 100.0\n        self._hdd_recovery_emit_metrics(batch.copy())\n        self._hdd_log(f\"\u2705 Standby booster freed {self._fmt_size(batch['delta_mb'] * 1024**2)}\", C[\"success\"])\n\n    def _do_ram_compression_predictor(self):\n        try:\n            vm = psutil.virtual_memory()\n            predicted_free_mb = int(min(vm.available / 1024**2 * 0.20, vm.total / 1024**2 * 0.08))\n            confidence = min(95, max(30, int((100 - vm.percent) * 0.55 + 10)))\n            score_text = f\"Prediction: {self._fmt_size(predicted_free_mb * 1024**2)} free | Confidence {confidence}%\"\n            self.after(0, lambda: self.hdd_compression_pred_var.set(score_text))\n            self._hdd_recovery_emit_metrics({\n                \"phase\": \"compression_predictor\",\n                \"status_text\": \"RAM compression prediction ready\",\n                \"progress_pct\": 100.0,\n                \"predicted_ram_mb\": predicted_free_mb,\n                \"confidence_score\": confidence,\n            })\n            self._hdd_log(f\"\ud83e\udde0 {score_text}\", C[\"accent4\"])\n        except Exception as e:\n            self._hdd_log(f\"Compression predictor failed: {e}\", C[\"warning\"])\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # 1. SMART REPORT\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _hdd_smart_quick(self):\n        drive = self.hdd_drive_var.get().replace(\":\", \"\")\n        self._hdd_log(f\"\ud83d\udcca Quick SMART check: {drive}:\", C[\"accent\"])\n        self._append_log(self.smart_log, f\"[SMART QUICK CHECK \u2014 Drive {drive}:]\\n\", C[\"accent\"])\n\n        def _run():\n            # WMIC disk status\n            out1, rc1 = self._run_cmd(\n                f'wmic diskdrive get Caption,Status,MediaType,Size /format:list', timeout=15)\n            # PowerShell physical disk health\n            out2, rc2 = self._run_cmd(\n                'powershell -Command \"Get-PhysicalDisk | Select FriendlyName,HealthStatus,OperationalStatus,Size | Format-List\"',\n                timeout=15)\n            # Disk space info\n            out3, rc3 = self._run_cmd(\n                f'wmic logicaldisk where \"DeviceID=\\'{drive}:\\'\" get Caption,FreeSpace,Size,FileSystem,VolumeName /format:list',\n                timeout=10)\n\n            self.after(0, lambda: self._append_log(self.smart_log,\n                f\"\u2500\u2500 Physical Disk Status \u2500\u2500\\n{out1}\\n\\n\u2500\u2500 Health Status \u2500\u2500\\n{out2}\\n\\n\u2500\u2500 Logical Disk \u2500\u2500\\n{out3}\\n\",\n                C[\"text\"]))\n            status = \"OK\" if (\"OK\" in out1.upper() or \"HEALTHY\" in out2.upper()) else \"WARNING\"\n            color = C[\"success\"] if status == \"OK\" else C[\"error\"]\n            self.after(0, lambda: self._hdd_log(\n                f\"\u2705 SMART Quick: Drive {drive}: \u2014 Status: {status}\", color))\n            self.after(0, lambda: self._set_status(f\"SMART check done: {status}\", color))\n            if status != \"OK\":\n                self.after(0, lambda: self._hdd_log(\"\u26a0\ufe0f SMART warning detected \u2014 backup data immediately!\", C[\"warning\"]))\n\n        self._launch_job(\"hdd_smart_quick\", _run)\n\n    def _hdd_smart_report(self):\n        drive = self.hdd_drive_var.get().replace(\":\", \"\")\n        self._hdd_log(f\"\ud83d\udcca Full SMART Report starting for {drive}:\", C[\"accent\"])\n        self._append_log(self.smart_log, \"\\n[\u2550\u2550\u2550 FULL SMART REPORT \u2550\u2550\u2550]\\n\", C[\"accent\"])\n\n        def _run():\n            cmds = [\n                (\"Physical Disk Info\",\n                 'wmic diskdrive get Caption,Model,Status,MediaType,Size,InterfaceType,FirmwareRevision /format:list'),\n                (\"Volume Info\",\n                 f'wmic logicaldisk where \"DeviceID=\\'{drive}:\\'\" get Caption,FreeSpace,Size,FileSystem,VolumeName,DriveType /format:list'),\n                (\"Disk Partition\",\n                 f'wmic partition where \"DriveLetter=\\'{drive}:\\'\" get BlockSize,Bootable,Caption,DiskIndex,Index,Size,Type /format:list'),\n                (\"Physical Disk Health (PS)\",\n                 'powershell -Command \"Get-PhysicalDisk | Format-List *\"'),\n                (\"Disk Reliability (PS)\",\n                 'powershell -Command \"Get-Disk | Select Number,FriendlyName,HealthStatus,OperationalStatus,PartitionStyle,Size | Format-List\"'),\n                (\"Disk Errors (Event Log)\",\n                 'powershell -Command \"Get-EventLog -LogName System -Source \\\\\"disk\\\\\" -Newest 10 -ErrorAction SilentlyContinue | Select TimeGenerated,EntryType,Message | Format-List\"'),\n            ]\n            for label, cmd in cmds:\n                out, rc = self._run_cmd(cmd, timeout=20)\n                self.after(0, lambda l=label, o=out: self._append_log(\n                    self.smart_log, f\"\\n\u2500\u2500 {l} \u2500\u2500\\n{o}\\n\", C[\"text_dim\"]))\n\n            self.after(0, lambda: self._hdd_log(\"\u2705 Full SMART Report complete. Smart log mein dekho.\", C[\"success\"]))\n            self.after(0, lambda: self._set_status(\"SMART Report Complete\", C[\"success\"]))\n\n        self._launch_job(\"hdd_smart_report\", _run)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # 2. BAD SECTOR SCAN + FIX\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _hdd_bad_sector_fix(self):\n        drive = self.hdd_drive_var.get()\n        letter = drive.replace(\":\", \"\")\n        is_system = letter.upper() == \"C\"\n\n        if is_system:\n            msg = (f\"Drive {drive} system drive hai (Windows isi pe hai).\\n\\n\"\n                   f\"chkdsk /f /r NEXT BOOT pe schedule hoga.\\n\"\n                   f\"PC restart hoga aur chkdsk boot se pehle chalega.\\n\\n\"\n                   f\"Kya aap restart karke chkdsk schedule karna chahte hain?\")\n        else:\n            msg = (f\"Drive {drive} pe Bad Sector Scan + Fix chalega.\\n\\n\"\n                   f\"Command: chkdsk {drive} /f /r /x\\n\"\n                   f\"  /f = Errors fix karega\\n\"\n                   f\"  /r = Bad sectors dhundega aur data recover karega\\n\"\n                   f\"  /x = Drive forcefully dismount karega\\n\\n\"\n                   f\"\u26a0\ufe0f  Yeh 30-90 minutes le sakta hai!\\n\\n\"\n                   f\"BEFORE:\\n{self._hdd_disk_info_before(drive)}\\n\\nProceed?\")\n\n        if not messagebox.askyesno(\"Bad Sector Repair\", msg):\n            return\n\n        def _run():\n            self.after(0, lambda: self._hdd_log(f\"\ud83e\ude7a Bad Sector Fix started: {drive}\", C[\"accent4\"]))\n            self.after(0, lambda: self._set_status(f\"chkdsk {drive} running...\", C[\"accent4\"]))\n\n            if is_system:\n                # Schedule for next boot\n                out, rc = self._run_cmd(f'echo Y | chkdsk {drive} /f /r', timeout=15)\n                self.after(0, lambda: self._hdd_log(\n                    f\"\ud83d\udccb chkdsk output:\\n{out}\", C[\"text\"]))\n                if rc == 0 or \"schedule\" in out.lower() or \"next time\" in out.lower():\n                    self.after(0, lambda: self._hdd_log(\n                        \"\u2705 PROOF: chkdsk next boot ke liye schedule ho gaya!\", C[\"success\"]))\n                    self.after(0, lambda: messagebox.showinfo(\"Scheduled\",\n                        f\"\u2705 chkdsk {drive}: next restart pe automatically chalega.\\n\\n\"\n                        f\"PROOF: 'chkdsk schedule' registry mein set ho gayi hai.\\n\"\n                        f\"Verify: regedit \u2192 HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Session Manager\\\\BootExecute\"))\n                else:\n                    self.after(0, lambda: self._hdd_log(f\"\u26a0\ufe0f Output: {out}\", C[\"warning\"]))\n            else:\n                # Run immediately on non-system drive\n                out, rc = self._run_cmd(f'chkdsk {drive} /f /r /x', timeout=3600)\n                self.after(0, lambda: self._hdd_log(\n                    f\"\ud83d\udccb chkdsk Full Output:\\n{out[-1000:]}\", C[\"text\"]))\n\n                # Parse results\n                errors_found = any(k in out.lower() for k in\n                    [\"bad sector\", \"error\", \"found\", \"repaired\", \"corrupt\"])\n                clean = any(k in out.lower() for k in\n                    [\"no errors\", \"0 bad sectors\", \"found no problems\"])\n\n                if clean:\n                    self.after(0, lambda: self._hdd_log(\n                        f\"\u2705 PROOF: Drive {drive} \u2014 No bad sectors found. Drive clean hai!\", C[\"success\"]))\n                    self.after(0, lambda: messagebox.showinfo(\"Clean Drive\",\n                        f\"\u2705 Drive {drive}: CLEAN\\n\\nchkdsk ne koi bad sector nahi paaya.\\n\\nFull output log mein hai.\"))\n                elif errors_found:\n                    self.after(0, lambda: self._hdd_log(\n                        f\"\u26a0\ufe0f PROOF: Bad sectors mili/repair ki gayi. Output check karo.\", C[\"warning\"]))\n                    self.after(0, lambda: messagebox.showwarning(\"Repaired\",\n                        f\"\u26a0\ufe0f Drive {drive}: Issues found and repaired.\\n\\nBad sectors data lost ho sakta hai.\\n\\nBackup ASAP recommended!\"))\n                else:\n                    self.after(0, lambda: self._hdd_log(\n                        f\"\ud83d\udccb chkdsk complete. Output log mein hai.\", C[\"text_dim\"]))\n\n            self.after(0, lambda: self._set_status(\"chkdsk Done\", C[\"success\"]))\n\n        self._launch_job(\"hdd_bad_sector_fix\", _run)\n\n    def _hdd_disk_info_before(self, drive):\n        try:\n            usage = psutil.disk_usage(drive + \"\\\\\")\n            total_gb = usage.total / (1024**3)\n            used_gb = usage.used / (1024**3)\n            free_gb = usage.free / (1024**3)\n            return (f\"Drive: {drive}\\n\"\n                    f\"Total: {total_gb:.1f} GB\\n\"\n                    f\"Used:  {used_gb:.1f} GB\\n\"\n                    f\"Free:  {free_gb:.1f} GB ({100 - usage.percent:.1f}% free)\")\n        except:\n            return f\"Drive: {drive} (size info unavailable)\"\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # 3. MBR / BCD REPAIR\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _hdd_mbr_repair(self):\n        msg = (\"\u26a0\ufe0f  MBR / Boot Repair \u2014 Ye sirf tab use karo jab:\\n\\n\"\n               \"\u2022 PC boot nahi ho raha\\n\"\n               \"\u2022 'Boot sector not found' error aa raha hai\\n\"\n               \"\u2022 BCD (Boot Configuration Data) corrupt hai\\n\\n\"\n               \"Commands jo chalenge:\\n\"\n               \"  1. bootrec /fixmbr      \u2190 MBR rewrite\\n\"\n               \"  2. bootrec /fixboot     \u2190 Boot sector fix\\n\"\n               \"  3. bootrec /scanos      \u2190 Windows installations scan\\n\"\n               \"  4. bootrec /rebuildbcd  \u2190 BCD rebuild\\n\\n\"\n               \"REQUIRE: Admin rights (already have) + Restart recommended after.\\n\\n\"\n               \"Proceed?\")\n        if not messagebox.askyesno(\"MBR / Boot Repair\", msg):\n            return\n\n        def _run():\n            self.after(0, lambda: self._hdd_log(\"\ud83d\udd11 MBR/BCD Repair starting...\", C[\"accent3\"]))\n            results = []\n            steps = [\n                (\"bootrec /fixmbr\",     \"MBR rewrite\"),\n                (\"bootrec /fixboot\",    \"Boot sector fix\"),\n                (\"bootrec /scanos\",     \"OS scan\"),\n                (\"bootrec /rebuildbcd\", \"BCD rebuild\"),\n            ]\n            for cmd, label in steps:\n                out, rc = self._run_cmd(cmd, timeout=60)\n                status = \"\u2705\" if rc == 0 else \"\u26a0\ufe0f\"\n                color = C[\"success\"] if rc == 0 else C[\"warning\"]\n                result_line = f\"{status} {label}: rc={rc} | {out[:120]}\"\n                results.append(result_line)\n                self.after(0, lambda r=result_line, c=color: self._hdd_log(r, c))\n\n            summary = \"\\n\".join(results)\n            self.after(0, lambda: messagebox.showinfo(\"MBR/BCD Repair Complete\",\n                f\"\u2705 MBR/BCD Repair Done!\\n\\n{summary}\\n\\n\"\n                f\"PROOF: bootrec commands ran with above return codes.\\n\"\n                f\"Restart karo aur check karo PC boot hota hai ya nahi.\"))\n            self.after(0, lambda: self._set_status(\"MBR/BCD Repair Done\", C[\"success\"]))\n\n        threading.Thread(target=_run, daemon=True).start()\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # 4. NTFS FILE SYSTEM FIX\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _hdd_ntfs_fix(self):\n        drive = self.hdd_drive_var.get()\n        letter = drive.replace(\":\", \"\")\n        msg = (f\"NTFS File System Fix \u2014 Drive {drive}\\n\\n\"\n               f\"Steps:\\n\"\n               f\"  1. Dirty bit check (fsutil dirty query)\\n\"\n               f\"  2. NTFS USN Journal reset\\n\"\n               f\"  3. chkdsk /f (errors fix, no bad sector scan)\\n\\n\"\n               f\"Ye fast hai (5-15 min). System drive pe next boot schedule hoga.\\n\\nProceed?\")\n        if not messagebox.askyesno(\"NTFS Fix\", msg):\n            return\n\n        def _run():\n            self.after(0, lambda: self._hdd_log(f\"\ud83d\udcc1 NTFS Fix: {drive}\", C[\"accent\"]))\n\n            # Step 1: dirty bit\n            out1, _ = self._run_cmd(f'fsutil dirty query {drive}', timeout=10)\n            dirty = \"dirty\" in out1.lower()\n            self.after(0, lambda: self._hdd_log(\n                f\"{'\u26a0\ufe0f Dirty bit SET \u2014 NTFS needs repair' if dirty else '\u2705 Dirty bit: Clean'}\",\n                C[\"warning\"] if dirty else C[\"success\"]))\n\n            # Step 2: USN Journal reset\n            out2, rc2 = self._run_cmd(\n                f'fsutil usn deletejournal /d {drive}', timeout=15)\n            out3, rc3 = self._run_cmd(\n                f'fsutil usn createjournal m=1000 a=100 {drive}', timeout=15)\n            j_ok = rc2 == 0 and rc3 == 0\n            self.after(0, lambda: self._hdd_log(\n                f\"{'\u2705' if j_ok else '\u26a0\ufe0f'} NTFS Journal reset: {'Done' if j_ok else 'Partial (may need admin)'}\",\n                C[\"success\"] if j_ok else C[\"warning\"]))\n\n            # Step 3: chkdsk /f\n            if letter.upper() == \"C\":\n                out4, rc4 = self._run_cmd(f'echo Y | chkdsk {drive} /f', timeout=15)\n                scheduled = True\n            else:\n                out4, rc4 = self._run_cmd(f'chkdsk {drive} /f', timeout=1800)\n                scheduled = False\n\n            self.after(0, lambda: self._hdd_log(\n                f\"\ud83d\udccb chkdsk /f output:\\n{out4[-500:]}\", C[\"text\"]))\n\n            proof = (f\"PROOF:\\n\"\n                     f\"1. Dirty bit: {'SET (needed fix)' if dirty else 'Clean'}\\n\"\n                     f\"2. USN Journal: {'Reset OK' if j_ok else 'Partial'}\\n\"\n                     f\"3. chkdsk /f: {'Scheduled next boot' if scheduled else 'Ran immediately'} (rc={rc4})\\n\\n\"\n                     f\"Full output log mein hai.\")\n            self.after(0, lambda: messagebox.showinfo(\"NTFS Fix Complete\", proof))\n            self.after(0, lambda: self._hdd_log(\"\u2705 NTFS Fix complete.\", C[\"success\"]))\n            self.after(0, lambda: self._set_status(\"NTFS Fix Done\", C[\"success\"]))\n\n        self._launch_job(\"hdd_ntfs_fix\", _run)\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # 5. PARTITION TABLE REPAIR\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _hdd_partition_repair(self):\n        drive = self.hdd_drive_var.get()\n        msg = (f\"Partition Repair \u2014 Drive {drive}\\n\\n\"\n               f\"Kya karega:\\n\"\n               f\"  1. Disk list \u2014 saare disks + partitions dikhayega\\n\"\n               f\"  2. Automount enable \u2014 hidden drives visible karega\\n\"\n               f\"  3. Drive letter assign karega agar missing ho\\n\"\n               f\"  4. Volume info + filesystem type check\\n\\n\"\n               f\"Proceed?\")\n        if not messagebox.askyesno(\"Partition Repair\", msg):\n            return\n\n        def _run():\n            self.after(0, lambda: self._hdd_log(\"\ud83d\udcc2 Partition Repair starting...\", C[\"btn_info\"]))\n\n            # Step 1: List disks\n            out1, _ = self._run_cmd(\n                'powershell -Command \"Get-Disk | Select Number,FriendlyName,PartitionStyle,HealthStatus,Size | Format-Table -AutoSize\"',\n                timeout=15)\n            self.after(0, lambda: self._hdd_log(f\"\ud83d\udccb Disk List:\\n{out1}\", C[\"text\"]))\n\n            # Step 2: List volumes\n            out2, _ = self._run_cmd(\n                'powershell -Command \"Get-Volume | Select DriveLetter,FileSystemLabel,FileSystem,HealthStatus,DriveType,Size,SizeRemaining | Format-Table -AutoSize\"',\n                timeout=15)\n            self.after(0, lambda: self._hdd_log(f\"\ud83d\udccb Volume List:\\n{out2}\", C[\"text\"]))\n\n            # Step 3: Enable automount\n            diskpart_script = \"automount enable\\nexit\\n\"\n            tmp = os.path.join(tempfile.gettempdir(), \"goda_diskpart.txt\")\n            with open(tmp, \"w\") as f:\n                f.write(diskpart_script)\n            out3, rc3 = self._run_cmd(f'diskpart /s \"{tmp}\"', timeout=20)\n            self.after(0, lambda: self._hdd_log(\n                f\"{'\u2705' if rc3 == 0 else '\u26a0\ufe0f'} Automount: {out3[:100]}\", C[\"success\"] if rc3 == 0 else C[\"warning\"]))\n\n            # Step 4: Check if target drive letter exists\n            letter = drive.replace(\":\", \"\")\n            out4, _ = self._run_cmd(\n                f'powershell -Command \"Get-Partition | Where-Object DriveLetter -eq \\'{letter}\\' | Format-List *\"',\n                timeout=10)\n            if out4.strip():\n                self.after(0, lambda: self._hdd_log(\n                    f\"\u2705 Drive {drive} partition info:\\n{out4[:300]}\", C[\"success\"]))\n            else:\n                self.after(0, lambda: self._hdd_log(\n                    f\"\u26a0\ufe0f Drive {drive} partition na mile \u2014 drive letter assign karni pad sakti hai\", C[\"warning\"]))\n\n            proof = (f\"PROOF \u2014 Partition Repair Done:\\n\"\n                     f\"1. Disk list fetched: {len(out1.splitlines())} lines\\n\"\n                     f\"2. Volume list fetched: {len(out2.splitlines())} volumes\\n\"\n                     f\"3. Automount enabled: rc={rc3}\\n\"\n                     f\"4. Partition check: {'Found' if out4.strip() else 'Not found (manual assign needed)'}\\n\\n\"\n                     f\"Full details log mein hain.\")\n            self.after(0, lambda: messagebox.showinfo(\"Partition Repair\", proof))\n            self.after(0, lambda: self._set_status(\"Partition Repair Done\", C[\"success\"]))\n\n        threading.Thread(target=_run, daemon=True).start()\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # 6. VSS / SHADOW COPY FIX\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _hdd_vss_repair(self):\n        msg = (\"VSS / Shadow Copy Fix\\n\\n\"\n               \"Steps:\\n\"\n               \"  1. VSS service stop\\n\"\n               \"  2. Old shadow copies delete\\n\"\n               \"  3. Shadow storage resize\\n\"\n               \"  4. VSS service restart\\n\"\n               \"  5. Volume Shadow Copy verify\\n\\n\"\n               \"\u26a0\ufe0f Existing restore points delete ho jayenge!\\n\\nProceed?\")\n        if not messagebox.askyesno(\"VSS Fix\", msg):\n            return\n\n        def _run():\n            self.after(0, lambda: self._hdd_log(\"\ud83d\udd04 VSS Repair starting...\", C[\"accent2\"]))\n            drive = self.hdd_drive_var.get()\n            steps_done = []\n\n            cmds = [\n                (\"net stop vss\",                               \"VSS stop\"),\n                (\"net stop swprv\",                             \"SWPRV stop\"),\n                (\"vssadmin delete shadows /all /quiet\",        \"Delete old shadows\"),\n                (f\"vssadmin resize shadowstorage /for={drive} /on={drive} /maxsize=10%\",\n                                                               \"Resize shadow storage\"),\n                (\"net start swprv\",                            \"SWPRV start\"),\n                (\"net start vss\",                              \"VSS start\"),\n            ]\n            for cmd, label in cmds:\n                out, rc = self._run_cmd(cmd, timeout=30)\n                ok = rc == 0\n                steps_done.append(f\"{'\u2705' if ok else '\u26a0\ufe0f'} {label}\")\n                self.after(0, lambda l=label, o=out, c=(C[\"success\"] if ok else C[\"warning\"]):\n                    self._hdd_log(f\"{'\u2705' if c==C['success'] else '\u26a0\ufe0f'} {l}: {o[:80]}\", c))\n\n            # Verify VSS running\n            out_v, _ = self._run_cmd('sc query vss', timeout=10)\n            running = \"running\" in out_v.lower()\n            self.after(0, lambda: self._hdd_log(\n                f\"{'\u2705 VSS service: RUNNING' if running else '\u26a0\ufe0f VSS service: Not running'}\",\n                C[\"success\"] if running else C[\"warning\"]))\n\n            proof = \"\\n\".join(steps_done) + f\"\\n\\nVSS Final Status: {'RUNNING \u2705' if running else 'Stopped \u26a0\ufe0f'}\"\n            self.after(0, lambda: messagebox.showinfo(\"VSS Repair Complete\",\n                f\"VSS / Shadow Copy Repair Done!\\n\\n{proof}\"))\n            self.after(0, lambda: self._set_status(\"VSS Repair Done\", C[\"success\"]))\n\n        threading.Thread(target=_run, daemon=True).start()\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # 7. SSD TRIM\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _hdd_ssd_trim(self):\n        drive = self.hdd_drive_var.get()\n        letter = drive.replace(\":\", \"\")\n\n        def _run():\n            self.after(0, lambda: self._hdd_log(f\"\u26a1 SSD TRIM + Optimize: {drive}\", C[\"hw_accent\"]))\n\n            # Check if SSD\n            out_type, _ = self._run_cmd(\n                f'powershell -Command \"(Get-PhysicalDisk | Where-Object {{ $_.DeviceId -eq (Get-Partition -DriveLetter \\'{letter}\\' -ErrorAction SilentlyContinue | Select -ExpandProperty DiskNumber) }}).MediaType\"',\n                timeout=10)\n            is_ssd = \"SSD\" in out_type.upper() or \"Solid\" in out_type\n\n            self.after(0, lambda: self._hdd_log(\n                f\"{'\u26a1 SSD detected' if is_ssd else '\u26a0\ufe0f HDD detected \u2014 TRIM not applicable, use Defrag instead'}\",\n                C[\"hw_accent\"] if is_ssd else C[\"warning\"]))\n\n            # TRIM\n            out1, rc1 = self._run_cmd(\n                f'powershell -Command \"Optimize-Volume -DriveLetter {letter} -ReTrim -Verbose\"',\n                timeout=120)\n            # Also optimize\n            out2, rc2 = self._run_cmd(\n                f'defrag {drive} /U /H /L', timeout=120)\n\n            self.after(0, lambda: self._hdd_log(f\"\ud83d\udccb TRIM output:\\n{out1[-300:]}\", C[\"text\"]))\n            self.after(0, lambda: self._hdd_log(\n                f\"{'\u2705' if rc1 == 0 else '\u26a0\ufe0f'} TRIM: rc={rc1}\", C[\"success\"] if rc1 == 0 else C[\"warning\"]))\n\n            proof = (f\"PROOF \u2014 SSD TRIM Done:\\n\"\n                     f\"Drive: {drive}\\n\"\n                     f\"Optimize-Volume -ReTrim: rc={rc1}\\n\"\n                     f\"defrag /L (thin provision): rc={rc2}\\n\"\n                     f\"Output: {out1[:200]}\")\n            self.after(0, lambda: messagebox.showinfo(\"SSD TRIM Complete\", proof))\n            self.after(0, lambda: self._set_status(\"SSD TRIM Done\", C[\"success\"]))\n\n        threading.Thread(target=_run, daemon=True).start()\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # 8. HDD DEFRAG\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _hdd_defrag(self):\n        drive = self.hdd_drive_var.get()\n        letter = drive.replace(\":\", \"\")\n        if not messagebox.askyesno(\"HDD Defrag\",\n            f\"Drive {drive} ko defragment karein?\\n\\n\"\n            f\"Command: defrag {drive} /U /V /X\\n\"\n            f\"  /U = Progress dikhao\\n  /V = Verbose report\\n  /X = Free space consolidate\\n\\n\"\n            f\"\u26a0\ufe0f 30-120 min lag sakta hai!\\n\\nProceed?\"):\n            return\n\n        def _run():\n            # Safety: avoid defrag on SSD (best-effort detection)\n            try:\n                ana, _ = self._run_cmd(f'defrag {drive} /A', timeout=120)\n                low = (ana or \"\").lower()\n                if \"solid state\" in low or \"ssd\" in low:\n                    self.after(0, lambda: self._hdd_log(\n                        f\"\u26a0\ufe0f Detected SSD for {drive}. Defrag skip. Use SSD TRIM instead.\", C[\"warning\"]))\n                    self.after(0, lambda: messagebox.showwarning(\n                        \"SSD Detected\",\n                        f\"Drive {drive} SSD lag rahi hai.\\n\\nSSD pe Defrag recommend nahi hota.\\n'\ud83d\udca8 SSD TRIM' use karo.\"\n                    ))\n                    return\n            except Exception:\n                pass\n            self.after(0, lambda: self._hdd_log(f\"\ud83d\uddc2 Defrag starting: {drive}\", C[\"accent4\"]))\n            self.after(0, lambda: self._set_status(f\"Defrag {drive}...\", C[\"accent4\"]))\n\n            before_info = self._hdd_disk_info_before(drive)\n            out, rc = self._run_cmd(f'defrag {drive} /U /V /X', timeout=7200)\n\n            self.after(0, lambda: self._hdd_log(f\"\ud83d\udccb Defrag output:\\n{out[-800:]}\", C[\"text\"]))\n\n            # Parse fragmentation info\n            lines = out.splitlines()\n            frag_lines = [l for l in lines if \"fragment\" in l.lower() or \"%\" in l]\n\n            proof = (f\"PROOF \u2014 HDD Defrag Done:\\n\\n\"\n                     f\"BEFORE:\\n{before_info}\\n\\n\"\n                     f\"Defrag rc: {rc}\\n\"\n                     f\"Fragmentation info:\\n\" + \"\\n\".join(frag_lines[:5]) +\n                     f\"\\n\\nFull output log mein hai.\")\n            self.after(0, lambda: messagebox.showinfo(\"Defrag Complete\", proof))\n            self.after(0, lambda: self._hdd_log(\"\u2705 Defrag complete!\", C[\"success\"]))\n            self.after(0, lambda: self._set_status(\"Defrag Done\", C[\"success\"]))\n\n        threading.Thread(target=_run, daemon=True).start()\n\n    def _hdd_auto_optimize(self):\n        drive = self.hdd_drive_var.get()\n        if not messagebox.askyesno(\"Auto Optimize\",\n                                   f\"Drive {drive} ke liye best optimize run karein?\\n\\nSSD \u2192 TRIM\\nHDD \u2192 Defrag\"):\n            return\n\n        def _run():\n            # Best-effort detection (simple, robust quoting)\n            out, _ = self._run_cmd(\n                'powershell -Command \"Get-PhysicalDisk | Select FriendlyName,MediaType,HealthStatus | Format-List *\"',\n                timeout=15\n            )\n            low = (out or \"\").lower()\n            if \"ssd\" in low or \"solid state\" in low:\n                self.after(0, lambda: self._hdd_log(\"\ud83e\udd16 Auto: SSD detected \u2192 running TRIM\", C[\"hw_accent\"]))\n                self.after(0, self._hdd_ssd_trim)\n            else:\n                self.after(0, lambda: self._hdd_log(\"\ud83e\udd16 Auto: HDD assumed \u2192 running Defrag\", C[\"accent4\"]))\n                self.after(0, self._hdd_defrag)\n\n        threading.Thread(target=_run, daemon=True).start()\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # 9. DEEP DISK CLEANUP\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _hdd_deep_cleanup(self):\n        drive = self.hdd_drive_var.get()\n        if not messagebox.askyesno(\"Deep Disk Cleanup\",\n            f\"Drive {drive} ka deep cleanup karein?\\n\\n\"\n            f\"Steps:\\n\"\n            f\"  1. cleanmgr /sageset:1 \u2192 all categories select\\n\"\n            f\"  2. cleanmgr /sagerun:1 \u2192 cleanup run\\n\"\n            f\"  3. Windows.old folder check\\n\"\n            f\"  4. Temp/Prefetch cleanup\\n\\nProceed?\"):\n            return\n\n        def _run():\n            self.after(0, lambda: self._hdd_log(\"\ud83e\uddf9 Deep Cleanup starting...\", C[\"btn\"]))\n\n            before = psutil.disk_usage(drive + \"\\\\\").free / (1024**3)\n\n            # Configure cleanup categories before running cleanup\n            cleanup_root = r\"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\VolumeCaches\"\n            categories = [\n                \"Temporary Files\", \"Recycle Bin\", \"Temporary Internet Files\",\n                \"Old ChkDsk Files\", \"Windows Error Reporting Files\",\n                \"Delivery Optimization Files\", \"Thumbnail Cache\",\n                \"Downloaded Program Files\",\n            ]\n            for cat in categories:\n                try:\n                    self._run_cmd(\n                        f'reg add \"{cleanup_root}\\\\{cat}\" /v StateFlags0099 /t REG_DWORD /d 2 /f',\n                        timeout=10)\n                except Exception:\n                    pass\n            self._run_cmd('cleanmgr /sageset:1', timeout=30)\n            out1, rc1 = self._run_cmd('cleanmgr /sagerun:1', timeout=300)\n            self.after(0, lambda: self._hdd_log(\n                f\"{'\u2705' if rc1 == 0 else '\u26a0\ufe0f'} cleanmgr: rc={rc1}\", C[\"success\"] if rc1 == 0 else C[\"warning\"]))\n\n            # Remove Windows.old if exists\n            wold = os.path.join(drive + \"\\\\\", \"Windows.old\")\n            if os.path.exists(wold):\n                try:\n                    out2, rc2 = self._run_cmd(f'rd /s /q \"{wold}\"', timeout=120)\n                    self.after(0, lambda: self._hdd_log(\"\u2705 Windows.old deleted!\", C[\"success\"]))\n                except:\n                    self.after(0, lambda: self._hdd_log(\"\u26a0\ufe0f Windows.old delete failed (in use)\", C[\"warning\"]))\n\n            # Temp cleanup\n            for path in [os.environ.get(\"TEMP\",\"\"), os.environ.get(\"TMP\",\"\"),\n                          \"C:\\\\Windows\\\\Temp\"]:\n                if path and os.path.exists(path):\n                    for f in Path(path).glob(\"*\"):\n                        try:\n                            if f.is_file():\n                                f.unlink()\n                            elif f.is_dir():\n                                shutil.rmtree(str(f), ignore_errors=True)\n                        except:\n                            pass\n\n            after = psutil.disk_usage(drive + \"\\\\\").free / (1024**3)\n            freed = after - before\n            color = C[\"success\"] if freed &gt; 0.1 else C[\"text_dim\"]\n            self.after(0, lambda: self._hdd_log(\n                f\"\u2705 PROOF: Free space {before:.1f} GB \u2192 {after:.1f} GB | Freed: {freed:.2f} GB\", color))\n            self.after(0, lambda: messagebox.showinfo(\"Deep Cleanup Complete\",\n                f\"\u2705 Deep Cleanup Done!\\n\\n\"\n                f\"BEFORE Free: {before:.2f} GB\\n\"\n                f\"AFTER Free:  {after:.2f} GB\\n\"\n                f\"Freed:       {freed:.2f} GB\"))\n            self.after(0, lambda: self._set_status(f\"Cleanup Done \u2014 {freed:.1f}GB freed\", C[\"success\"]))\n\n        threading.Thread(target=_run, daemon=True).start()\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # 10. SFC + DISM (FULL WITH OUTPUT)\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _hdd_sfc_dism_full(self):\n        if not messagebox.askyesno(\"SFC + DISM Full Repair\",\n            \"Windows File Integrity Repair chalein?\\n\\n\"\n            \"Step 1: SFC /scannow (5-15 min)\\n\"\n            \"Step 2: DISM /RestoreHealth (10-30 min)\\n\\n\"\n            \"\u26a0\ufe0f Internet needed for DISM.\\n\"\n            \"Full output log mein dikhega (pehle sirf 'Done' dikh'ta tha \u2014 ab full proof milega)\\n\\nProceed?\"):\n            return\n\n        def _run():\n            self.after(0, lambda: self._hdd_log(\"\ud83c\udfe5 SFC starting...\", C[\"accent3\"]))\n            self.after(0, lambda: self._set_status(\"SFC /scannow running...\", C[\"accent3\"]))\n\n            # SFC with full output capture\n            out_sfc, rc_sfc = self._run_cmd('sfc /scannow', timeout=900)\n            self.after(0, lambda: self._hdd_log(f\"\ud83d\udccb SFC Output:\\n{out_sfc}\", C[\"text\"]))\n\n            if \"no integrity violations\" in out_sfc.lower():\n                sfc_result = \"\u2705 No corrupt files found\"\n                sfc_color = C[\"success\"]\n            elif \"found and repaired\" in out_sfc.lower() or \"repaired\" in out_sfc.lower():\n                sfc_result = \"\u2705 Corrupt files found AND REPAIRED\"\n                sfc_color = C[\"accent4\"]\n            elif \"unable to fix\" in out_sfc.lower():\n                sfc_result = \"\u26a0\ufe0f Some files could not be repaired \u2014 run DISM then retry SFC\"\n                sfc_color = C[\"warning\"]\n            else:\n                sfc_result = f\"\ud83d\udccb SFC rc={rc_sfc} \u2014 check output above\"\n                sfc_color = C[\"text_dim\"]\n\n            self.after(0, lambda: self._hdd_log(f\"SFC PROOF: {sfc_result}\", sfc_color))\n\n            # DISM\n            self.after(0, lambda: self._hdd_log(\"\ud83c\udfe5 DISM RestoreHealth starting...\", C[\"accent3\"]))\n            self.after(0, lambda: self._set_status(\"DISM RestoreHealth...\", C[\"accent3\"]))\n            out_dism, rc_dism = self._run_cmd(\n                'DISM /Online /Cleanup-Image /RestoreHealth', timeout=3600)\n            self.after(0, lambda: self._hdd_log(f\"\ud83d\udccb DISM Output:\\n{out_dism[-800:]}\", C[\"text\"]))\n\n            if rc_dism == 0:\n                dism_result = \"\u2705 DISM RestoreHealth: SUCCESS\"\n                dism_color = C[\"success\"]\n            else:\n                dism_result = f\"\u26a0\ufe0f DISM rc={rc_dism} \u2014 internet check karo ya CBS log dekho\"\n                dism_color = C[\"warning\"]\n\n            self.after(0, lambda: self._hdd_log(f\"DISM PROOF: {dism_result}\", dism_color))\n\n            proof = (f\"FULL PROOF:\\n\\n\"\n                     f\"SFC /scannow:\\n  rc={rc_sfc}\\n  Result: {sfc_result}\\n\\n\"\n                     f\"DISM RestoreHealth:\\n  rc={rc_dism}\\n  Result: {dism_result}\\n\\n\"\n                     f\"Full output HDD log mein hai.\")\n            self.after(0, lambda: messagebox.showinfo(\"SFC + DISM Complete\", proof))\n            self.after(0, lambda: self._set_status(\"SFC + DISM Done\", C[\"success\"]))\n\n        threading.Thread(target=_run, daemon=True).start()\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # 11. ERROR EVENT LOG\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _hdd_error_log(self):\n        def _run():\n            self.after(0, lambda: self._hdd_log(\"\ud83d\udccb Fetching disk error events...\", C[\"accent\"]))\n            out, rc = self._run_cmd(\n                'powershell -Command \"Get-EventLog -LogName System -EntryType Error,Warning -Newest 30 '\n                '-ErrorAction SilentlyContinue | Where-Object {$_.Source -match \\'disk|ntfs|volsnap|storport|iaStorV\\'} '\n                '| Select-Object TimeGenerated,EntryType,Source,Message | Format-List\"',\n                timeout=30)\n            if not out.strip() or rc != 0:\n                out2, _ = self._run_cmd(\n                    'powershell -Command \"Get-WinEvent -LogName System -MaxEvents 50 -ErrorAction SilentlyContinue '\n                    '| Where-Object {$_.Message -match \\'disk|NTFS|sector\\'} '\n                    '| Select-Object TimeCreated,LevelDisplayName,Message | Format-List\"',\n                    timeout=30)\n                out = out2\n\n            self.after(0, lambda: self._hdd_log(\n                f\"\ud83d\udccb Disk Error Events:\\n{out if out.strip() else 'No recent disk errors found \u2014 system clean!'}\",\n                C[\"text\"]))\n\n            if not out.strip():\n                self.after(0, lambda: messagebox.showinfo(\"Event Log\",\n                    \"\u2705 No recent disk errors in Event Log!\\n\\nDisk system clean hai.\"))\n            else:\n                error_count = out.count(\"TimeGenerated\") + out.count(\"TimeCreated\")\n                self.after(0, lambda: messagebox.showwarning(\"Disk Errors Found\",\n                    f\"\u26a0\ufe0f {error_count} disk-related events found!\\n\\n\"\n                    f\"PROOF: Event Log se real data fetch kiya.\\n\"\n                    f\"Full details HDD log mein hain.\\n\\n\"\n                    f\"Recommendation: Bad sector scan chalao.\"))\n            self.after(0, lambda: self._set_status(\"Error Log Fetched\", C[\"success\"]))\n\n        threading.Thread(target=_run, daemon=True).start()\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # 12. BSOD / CRASH INFO\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _hdd_bsod_info(self):\n        def _run():\n            self.after(0, lambda: self._hdd_log(\"\ud83d\udca5 Fetching BSoD / Crash info...\", C[\"accent3\"]))\n\n            # Check minidump folder\n            minidump_path = r\"C:\\Windows\\Minidump\"\n            dumps = []\n            if os.path.exists(minidump_path):\n                dumps = sorted(Path(minidump_path).glob(\"*.dmp\"),\n                               key=lambda x: x.stat().st_mtime, reverse=True)[:5]\n\n            # Get last crash from Event Log\n            out_crash, _ = self._run_cmd(\n                'powershell -Command \"Get-EventLog -LogName System -Source \\'Microsoft-Windows-WER-SystemErrorReporting\\' '\n                '-Newest 5 -ErrorAction SilentlyContinue | Select TimeGenerated,Message | Format-List\"',\n                timeout=20)\n            # Reliability history\n            out_rel, _ = self._run_cmd(\n                'powershell -Command \"Get-WinEvent -ProviderName Microsoft-Windows-Kernel-Power -MaxEvents 5 '\n                '-ErrorAction SilentlyContinue | Select TimeCreated,LevelDisplayName,Message | Format-List\"',\n                timeout=20)\n            # Last BSOD from registry\n            out_reg, _ = self._run_cmd(\n                r'reg query \"HKLM\\SYSTEM\\CurrentControlSet\\Control\\CrashControl\" /v DumpFile',\n                timeout=10)\n\n            dump_info = \"\"\n            if dumps:\n                dump_info = f\"Recent Minidumps ({len(dumps)} files):\\n\"\n                for d in dumps:\n                    mtime = datetime.datetime.fromtimestamp(d.stat().st_mtime).strftime(\"%Y-%m-%d %H:%M\")\n                    dump_info += f\"  \u2022 {d.name} ({mtime}, {d.stat().st_size//1024} KB)\\n\"\n            else:\n                dump_info = \"No minidumps found \u2014 system stable hai ya dump disabled hai\\n\"\n\n            full_info = (f\"[BSoD / Crash Analysis]\\n\\n\"\n                         f\"{dump_info}\\n\"\n                         f\"\u2500\u2500 Event Log Crashes \u2500\u2500\\n{out_crash or 'No crash events'}\\n\\n\"\n                         f\"\u2500\u2500 Kernel Power Events \u2500\u2500\\n{out_rel or 'No power events'}\\n\\n\"\n                         f\"\u2500\u2500 Dump Config \u2500\u2500\\n{out_reg}\")\n\n            self.after(0, lambda: self._hdd_log(full_info, C[\"text\"]))\n            try:\n                deep_report, deep_severity, deep_count = self._build_bsod_deep_report()\n                deep_color = C[\"warning\"] if deep_severity == \"warning\" else C[\"success\"]\n                self.after(0, lambda r=deep_report, c=deep_color: self._hdd_log(\n                    \"\\n[Advanced BSoD Troubleshooting + Solution]\\n\" + r, c))\n            except Exception as e:\n                self.after(0, lambda err=e: self._hdd_log(\n                    f\"Advanced BSoD diagnosis failed: {err}\", C[\"warning\"]))\n\n            if dumps:\n                self.after(0, lambda: messagebox.showwarning(\"Crash Dumps Found\",\n                    f\"\u26a0\ufe0f {len(dumps)} minidump file(s) found!\\n\\n\"\n                    f\"PROOF: C:\\\\Windows\\\\Minidump mein actual .dmp files hain.\\n\\n\"\n                    f\"Latest: {dumps[0].name}\\n\\n\"\n                    f\"Analysis ke liye WinDbg ya WhoCrashed use karo.\"))\n            else:\n                self.after(0, lambda: messagebox.showinfo(\"BSoD Info\",\n                    \"\u2705 No recent BSoD/crash dumps found!\\n\\nSystem stable lag raha hai.\"))\n\n        threading.Thread(target=_run, daemon=True).start()\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # 13. ONE-CLICK FULL REPAIR\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _hdd_full_repair(self):\n        drive = self.hdd_drive_var.get()\n        msg = (f\"\u26a1 ONE-CLICK FULL HDD/SSD REPAIR\\n\\n\"\n               f\"Drive: {drive}\\n\\n\"\n               f\"Ye kya karega:\\n\"\n               f\"  1. \u2705 SMART Quick Check\\n\"\n               f\"  2. \u2705 NTFS Dirty Bit + Journal Reset\\n\"\n               f\"  3. \u2705 VSS / Shadow Copy Repair\\n\"\n               f\"  4. \u2705 SFC /scannow (file integrity)\\n\"\n               f\"  5. \u2705 DISM RestoreHealth\\n\"\n               f\"  6. \u2705 chkdsk /f (next boot if C:)\\n\"\n               f\"  7. \u2705 Deep Temp Cleanup\\n\"\n               f\"  8. \u2705 Error Event Log check\\n\\n\"\n               f\"\u26a0\ufe0f 45-90 minutes lag sakta hai!\\n\"\n               f\"\u26a0\ufe0f Internet DISM ke liye chahiye.\\n\\n\"\n               f\"Proceed?\")\n        if not messagebox.askyesno(\"Full Repair\", msg):\n            return\n\n        def _run():\n            results = []\n            def log_step(msg, color=None):\n                self.after(0, lambda m=msg, c=color: self._hdd_log(m, c or C[\"text\"]))\n                results.append(msg)\n\n            log_step(f\"\ud83d\ude80 FULL REPAIR STARTED \u2014 Drive {drive}\", C[\"accent\"])\n\n            # 1. SMART\n            log_step(\"Step 1/8: SMART Quick Check...\", C[\"text_dim\"])\n            out1, _ = self._run_cmd('wmic diskdrive get Caption,Status /format:list', timeout=15)\n            smart_ok = \"OK\" in out1.upper()\n            log_step(f\"{'\u2705' if smart_ok else '\u26a0\ufe0f'} SMART: {'OK' if smart_ok else 'Warning \u2014 check output'}\",\n                     C[\"success\"] if smart_ok else C[\"warning\"])\n\n            # 2. NTFS\n            log_step(\"Step 2/8: NTFS Journal Reset...\", C[\"text_dim\"])\n            self._run_cmd(f'fsutil usn deletejournal /d {drive}', timeout=15)\n            self._run_cmd(f'fsutil usn createjournal m=1000 a=100 {drive}', timeout=15)\n            log_step(\"\u2705 NTFS Journal reset done\", C[\"success\"])\n\n            # 3. VSS\n            log_step(\"Step 3/8: VSS Repair...\", C[\"text_dim\"])\n            self._run_cmd('net stop vss', timeout=20)\n            self._run_cmd('vssadmin delete shadows /all /quiet', timeout=30)\n            self._run_cmd('net start vss', timeout=20)\n            log_step(\"\u2705 VSS repaired\", C[\"success\"])\n\n            # 4. SFC\n            log_step(\"Step 4/8: SFC /scannow...\", C[\"text_dim\"])\n            out_sfc, rc_sfc = self._run_cmd('sfc /scannow', timeout=900)\n            if \"no integrity violations\" in out_sfc.lower():\n                log_step(\"\u2705 SFC: No corrupt files\", C[\"success\"])\n            elif \"repaired\" in out_sfc.lower():\n                log_step(\"\u2705 SFC: Files repaired!\", C[\"accent4\"])\n            else:\n                log_step(f\"\u26a0\ufe0f SFC rc={rc_sfc}\", C[\"warning\"])\n\n            # 5. DISM\n            log_step(\"Step 5/8: DISM RestoreHealth...\", C[\"text_dim\"])\n            out_dism, rc_dism = self._run_cmd(\n                'DISM /Online /Cleanup-Image /RestoreHealth', timeout=3600)\n            log_step(f\"{'\u2705' if rc_dism == 0 else '\u26a0\ufe0f'} DISM: rc={rc_dism}\",\n                     C[\"success\"] if rc_dism == 0 else C[\"warning\"])\n\n            # 6. chkdsk\n            log_step(\"Step 6/8: chkdsk...\", C[\"text_dim\"])\n            letter = drive.replace(\":\", \"\")\n            if letter.upper() == \"C\":\n                self._run_cmd(f'echo Y | chkdsk {drive} /f', timeout=15)\n                log_step(\"\u2705 chkdsk: Scheduled for next boot (C: drive)\", C[\"success\"])\n            else:\n                out_ck, rc_ck = self._run_cmd(f'chkdsk {drive} /f', timeout=1800)\n                log_step(f\"{'\u2705' if rc_ck == 0 else '\u26a0\ufe0f'} chkdsk: rc={rc_ck}\", C[\"success\"] if rc_ck == 0 else C[\"warning\"])\n\n            # 7. Temp cleanup\n            log_step(\"Step 7/8: Temp cleanup...\", C[\"text_dim\"])\n            before_free = psutil.disk_usage(drive + \"\\\\\").free / (1024**3)\n            for path in [os.environ.get(\"TEMP\",\"\"), \"C:\\\\Windows\\\\Temp\"]:\n                if path and os.path.exists(path):\n                    for f in Path(path).glob(\"*\"):\n                        try:\n                            if f.is_file(): f.unlink()\n                            elif f.is_dir(): shutil.rmtree(str(f), ignore_errors=True)\n                        except: pass\n            after_free = psutil.disk_usage(drive + \"\\\\\").free / (1024**3)\n            log_step(f\"\u2705 Temp cleanup: {after_free - before_free:.1f} GB freed\", C[\"success\"])\n\n            # 8. Error log check\n            log_step(\"Step 8/8: Error log check...\", C[\"text_dim\"])\n            out_err, _ = self._run_cmd(\n                'powershell -Command \"Get-EventLog -LogName System -EntryType Error -Newest 5 '\n                '-ErrorAction SilentlyContinue | Where-Object {$_.Source -match \\'disk|ntfs\\'} | Measure-Object | Select-Object Count\"',\n                timeout=20)\n            log_step(f\"\u2705 Error log checked: {out_err.strip()}\", C[\"success\"])\n\n            # Final summary\n            summary = \"\\n\".join(results[-10:])\n            self.after(0, lambda: messagebox.showinfo(\"\u2705 Full Repair Complete!\",\n                f\"ONE-CLICK FULL REPAIR DONE!\\n\\nDrive: {drive}\\n\\n\"\n                f\"PROOF \u2014 Steps completed:\\n{summary}\\n\\n\"\n                f\"\u26a0\ufe0f Restart karo aur chkdsk boot pe chalega (agar C: drive tha).\\n\"\n                f\"Full details HDD log mein hain.\"))\n            self.after(0, lambda: self._set_status(\"Full Repair DONE!\", C[\"success\"]))\n\n        threading.Thread(target=_run, daemon=True).start()\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # WINPE \u2014 Generate .bat scripts\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _winpe_gen_mbr_bat(self):\n        drive = self.hdd_drive_var.get()\n        content = f\"\"\"@echo off\n:: Godawari Computers \u2014 MBR / BCD Repair Script\n:: WinPE / Recovery Mode mein chalao\n:: Drive: {drive}\necho.\necho ========================================\necho  GODAWARI COMPUTERS \u2014 MBR REPAIR\necho ========================================\necho.\necho Step 1: Fixing MBR...\nbootrec /fixmbr\necho.\necho Step 2: Fixing Boot Sector...\nbootrec /fixboot\necho.\necho Step 3: Scanning OS installations...\nbootrec /scanos\necho.\necho Step 4: Rebuilding BCD...\nbootrec /rebuildbcd\necho.\necho Step 5: Disk list check...\ndiskpart /s %~dp0diskpart_list.txt\necho.\necho ========================================\necho  DONE! Restart karo.\necho ========================================\npause\n\"\"\"\n        diskpart_content = \"list disk\\nlist volume\\nexit\\n\"\n        desktop = os.path.join(os.path.expanduser(\"~\"), \"Desktop\")\n        fpath = os.path.join(desktop, \"Godawari_MBR_Fix.bat\")\n        fpath2 = os.path.join(desktop, \"diskpart_list.txt\")\n        try:\n            with open(fpath, \"w\") as f: f.write(content)\n            with open(fpath2, \"w\") as f: f.write(diskpart_content)\n            self._hdd_log(f\"\u2705 MBR Fix .bat saved: {fpath}\", C[\"success\"])\n            messagebox.showinfo(\"Saved\",\n                f\"\u2705 MBR Repair .bat file Desktop pe save ho gayi!\\n\\n{fpath}\\n\\n\"\n                f\"WinPE mein USB pe copy karo aur chalao.\")\n        except Exception as e:\n            messagebox.showerror(\"Error\", str(e))\n\n    def _winpe_gen_chkdsk_bat(self):\n        drive = self.hdd_drive_var.get()\n        content = f\"\"\"@echo off\n:: Godawari Computers \u2014 ChkDsk Repair Script\n:: WinPE / Recovery Mode mein chalao\necho.\necho ========================================\necho  GODAWARI COMPUTERS \u2014 CHKDSK REPAIR\necho  Drive: {drive}\necho ========================================\necho.\necho Bad Sector Scan + Fix starting...\necho (Yeh 30-90 min le sakta hai)\necho.\nchkdsk {drive} /f /r /x\necho.\necho NTFS Journal Reset...\nfsutil usn deletejournal /d {drive}\nfsutil usn createjournal m=1000 a=100 {drive}\necho.\necho ========================================\necho  DONE!\necho ========================================\npause\n\"\"\"\n        desktop = os.path.join(os.path.expanduser(\"~\"), \"Desktop\")\n        fpath = os.path.join(desktop, \"Godawari_ChkDsk_Fix.bat\")\n        try:\n            with open(fpath, \"w\") as f: f.write(content)\n            self._hdd_log(f\"\u2705 ChkDsk .bat saved: {fpath}\", C[\"success\"])\n            messagebox.showinfo(\"Saved\",\n                f\"\u2705 ChkDsk .bat Desktop pe save ho gayi!\\n\\n{fpath}\\n\\n\"\n                f\"WinPE ya Recovery CMD mein chalao.\")\n        except Exception as e:\n            messagebox.showerror(\"Error\", str(e))\n\n    def _winpe_gen_full_bat(self):\n        drive = self.hdd_drive_var.get()\n        content = f\"\"\"@echo off\n:: Godawari Computers \u2014 Full Repair Script\n:: WinPE / Recovery Mode mein chalao\necho.\necho ========================================\necho  GODAWARI COMPUTERS \u2014 FULL REPAIR\necho  Drive: {drive}\necho ========================================\necho.\necho [1/6] MBR Fix...\nbootrec /fixmbr\nbootrec /fixboot\nbootrec /rebuildbcd\necho.\necho [2/6] Bad Sector Scan...\nchkdsk {drive} /f /r /x\necho.\necho [3/6] NTFS Fix...\nfsutil usn deletejournal /d {drive}\nfsutil usn createjournal m=1000 a=100 {drive}\necho.\necho [4/6] SFC Scan...\nsfc /scannow\necho.\necho [5/6] DISM Repair...\nDISM /Online /Cleanup-Image /RestoreHealth\necho.\necho [6/6] DNS + Network Reset...\nipconfig /flushdns\nnetsh winsock reset\nnetsh int ip reset\necho.\necho ========================================\necho  ALL DONE! Restart karo.\necho ========================================\npause\n\"\"\"\n        desktop = os.path.join(os.path.expanduser(\"~\"), \"Desktop\")\n        fpath = os.path.join(desktop, \"Godawari_Full_Repair.bat\")\n        try:\n            with open(fpath, \"w\") as f: f.write(content)\n            self._hdd_log(f\"\u2705 Full Repair .bat saved: {fpath}\", C[\"success\"])\n            messagebox.showinfo(\"Saved\",\n                f\"\u2705 Full Repair .bat Desktop pe save ho gayi!\\n\\n{fpath}\\n\\n\"\n                f\"USB pe copy karo \u2192 WinPE/Recovery CMD mein chalao \u2192 Admin rights se.\")\n        except Exception as e:\n            messagebox.showerror(\"Error\", str(e))\n\n    def _winpe_open_recovery(self):\n        if not messagebox.askyesno(\"Open Windows Recovery\",\n            \"Windows Recovery Environment (RE) kholein?\\n\\n\"\n            \"PC restart hoga aur Recovery menu aayega.\\n\\n\"\n            \"Wahan se: Troubleshoot \u2192 Advanced \u2192 Command Prompt\\n\\n\"\n            \"Proceed?\"):\n            return\n        out, rc = self._run_cmd('reagentc /boottore', timeout=15)\n        if rc == 0:\n            self._hdd_log(\"\u2705 Recovery mode set \u2014 restarting...\", C[\"accent4\"])\n            messagebox.showinfo(\"Restarting\",\n                \"\u2705 System Recovery mode mein restart ho raha hai!\\n\\n\"\n                \"Wahan se Command Prompt select karo aur .bat script chalao.\")\n            self._run_cmd('shutdown /r /t 5 /c \"Godawari: Restarting to Recovery\"', timeout=10)\n        else:\n            self._hdd_log(f\"\u26a0\ufe0f reagentc failed: {out} \u2014 manual restart karo F8 dabao\", C[\"warning\"])\n            messagebox.showwarning(\"Manual Method\",\n                \"\u26a0\ufe0f Automatic recovery boot nahi hua.\\n\\n\"\n                \"Manual method:\\n\"\n                \"1. PC restart karo\\n\"\n                \"2. Boot ke time F8 dabao\\n\"\n                \"3. Troubleshoot \u2192 Advanced Options \u2192 Command Prompt\\n\"\n                \"4. Wahan .bat script chalao\")\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # OFFICE &amp; PDF TOOLS SECTION\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _build_office_tools(self, parent):\n        \"\"\"\n        Professional Office &amp; PDF Tools section.\n        Sub-tabs:\n          1. Image / PDF Converter  (JPG\u2192PDF, PDF\u2192Images)\n          2. PDF Operations         (Merge, Split, Rotate, Compress)\n          3. Office Converter       (DOC/XLS/PPT \u2192 PDF, PDF \u2192 Word/Excel)\n          4. Office File Repair     (DOCX, XLSX, PPTX, PDF recovery)\n        Dependencies must be available locally/offline; no runtime downloads.\n        \"\"\"\n        import threading\n\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n\n        # \u2500\u2500 Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        hdr = tk.Frame(frame, bg=C[\"panel\"])\n        hdr.pack(fill=\"x\")\n        tk.Label(hdr, text=\"  \ud83d\udcc4 Office &amp; PDF Tools\",\n                 font=FONTS[\"heading\"], fg=C[\"accent\"], bg=C[\"panel\"]).pack(side=\"left\", pady=10, padx=8)\n        tk.Label(hdr, text=\"Image\u2194PDF \u00b7 Merge \u00b7 Split \u00b7 Convert \u00b7 Repair  |  Offline local engines only\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"left\", pady=10, padx=4)\n\n        # \u2500\u2500 Sub-tab bar \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        tab_bar = tk.Frame(frame, bg=C[\"card\"])\n        tab_bar.pack(fill=\"x\", padx=0, pady=0)\n        tk.Frame(tab_bar, bg=C[\"border\"], height=1).pack(side=\"bottom\", fill=\"x\")\n\n        content_host = tk.Frame(frame, bg=C[\"bg\"])\n        content_host.pack(fill=\"both\", expand=True)\n\n        self._office_tab_frames = {}\n        self._office_active_tab = tk.StringVar(value=\"img_pdf\")\n\n        subtabs = [\n            (\"img_pdf\",    \"\ud83d\uddbc  Image \u2194 PDF\"),\n            (\"pdf_ops\",    \"\ud83d\udccb  PDF Operations\"),\n            (\"office_conv\",\"\ud83d\udcca  Office Converter\"),\n            (\"file_repair\",\"\ud83d\udd27  File Repair\"),\n        ]\n        self._office_tab_btns = {}\n\n        def _switch_office_tab(key):\n            self._office_active_tab.set(key)\n            for k, btn in self._office_tab_btns.items():\n                btn.config(bg=C[\"accent\"] if k == key else C[\"panel\"],\n                           fg=C[\"bg\"]     if k == key else C[\"text\"])\n            for k, f in self._office_tab_frames.items():\n                if k == key:\n                    f.pack(fill=\"both\", expand=True)\n                else:\n                    f.pack_forget()\n\n        for key, label in subtabs:\n            btn = tk.Button(tab_bar, text=label, font=FONTS[\"body\"],\n                            bg=C[\"panel\"], fg=C[\"text\"], bd=0,\n                            padx=18, pady=8, cursor=\"hand2\",\n                            command=lambda k=key: _switch_office_tab(k))\n            btn.pack(side=\"left\")\n            self._office_tab_btns[key] = btn\n\n        # \u2500\u2500 Shared log widget \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        log_host = tk.Frame(frame, bg=C[\"card\"])\n        log_host.pack(fill=\"x\", side=\"bottom\")\n        tk.Label(log_host, text=\"  Activity Log\", font=FONTS[\"small\"],\n                 fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=8, pady=(6,0))\n        self._ot_log = scrolledtext.ScrolledText(log_host, height=5, state=\"disabled\",\n                                                  bg=C[\"bg\"], fg=C[\"text\"], font=FONTS[\"small\"],\n                                                  bd=0, relief=\"flat\")\n        self._ot_log.pack(fill=\"x\", padx=8, pady=(2,6))\n\n        def ot_log(msg, color=None):\n            ts = datetime.datetime.now().strftime(\"%H:%M:%S\")\n            full = f\"[{ts}] {msg}\\n\"\n            self._ot_log.config(state=\"normal\")\n            tag = f\"c{abs(hash(color or 'def'))}\"\n            self._ot_log.tag_config(tag, foreground=color or C[\"text\"])\n            self._ot_log.insert(\"end\", full, tag)\n            self._ot_log.see(\"end\")\n            self._ot_log.config(state=\"disabled\")\n\n        self._ot_log_fn = ot_log\n\n        def _ensure_pkg(pkg_import, pip_name=None):\n            \"\"\"Return True only when an offline/local dependency is already available.\"\"\"\n            pip_name = pip_name or pkg_import\n            try:\n                __import__(pkg_import)\n                return True\n            except ImportError:\n                ot_log(\n                    f\"\u274c Missing local dependency: {pip_name}. Runtime download/install is disabled; bundle the offline wheel/package.\",\n                    C[\"error\"],\n                )\n            return False\n\n        self._ot_ensure_pkg = _ensure_pkg\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # TAB 1 \u2014 Image \u2194 PDF\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        t1 = tk.Frame(content_host, bg=C[\"bg\"])\n        self._office_tab_frames[\"img_pdf\"] = t1\n\n        def _make_card(parent, title):\n            card = tk.Frame(parent, bg=C[\"card\"])\n            card.pack(fill=\"x\", padx=16, pady=8)\n            tk.Label(card, text=title, font=FONTS[\"subhead\"],\n                     fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=10, pady=(8,4))\n            tk.Frame(card, bg=C[\"border\"], height=1).pack(fill=\"x\", padx=10)\n            body = tk.Frame(card, bg=C[\"card\"])\n            body.pack(fill=\"x\", padx=10, pady=8)\n            return body\n\n        # \u2500\u2500 JPG / PNG \u2192 single PDF \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        c1a = _make_card(t1, \"\ud83d\uddbc  Images \u2192 PDF  (JPG / PNG / BMP / TIFF \u2192 one PDF)\")\n        tk.Label(c1a, text=\"Images select karo (multiple Ctrl+click):\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\")\n\n        self._ot_img2pdf_files = tk.StringVar(value=\"\")\n        img2pdf_entry = tk.Entry(c1a, textvariable=self._ot_img2pdf_files,\n                                  font=FONTS[\"small\"], bg=C[\"bg\"], fg=C[\"text\"],\n                                  insertbackground=C[\"text\"], width=60)\n        img2pdf_entry.pack(side=\"left\", padx=(0,6), pady=4)\n\n        def _browse_images():\n            files = filedialog.askopenfilenames(\n                title=\"Images select karo\",\n                filetypes=[(\"Image files\",\"*.jpg *.jpeg *.png *.bmp *.tiff *.tif *.gif *.webp\"),\n                           (\"All files\",\"*.*\")])\n            if files:\n                self._ot_img2pdf_files.set(\";\".join(files))\n\n        tk.Button(c1a, text=\"Browse\u2026\", font=FONTS[\"small\"], bg=C[\"btn_info\"],\n                  fg=C[\"text\"], bd=0, padx=10, pady=4, cursor=\"hand2\",\n                  command=_browse_images).pack(side=\"left\", padx=4)\n\n        def _do_img2pdf():\n            paths = [p.strip() for p in self._ot_img2pdf_files.get().split(\";\") if p.strip()]\n            if not paths:\n                messagebox.showwarning(\"Warning\", \"Pehle images select karo.\")\n                return\n            # Pehli image ke naam se default PDF naam suggest karo\n            first_base = os.path.splitext(os.path.basename(paths[0]))[0] if paths else \"output\"\n            out = filedialog.asksaveasfilename(title=\"Output PDF save karein\",\n                                               defaultextension=\".pdf\",\n                                               initialfile=first_base,\n                                               filetypes=[(\"PDF\",\"*.pdf\")])\n            if not out:\n                return\n            def _run():\n                try:\n                    result = offline_images_to_pdf(\n                        paths,\n                        out,\n                        dpi=150,\n                        margin_mm=10,\n                        quality=85,\n                        auto_orientation=True,\n                        progress=lambda i, total, msg: ot_log(f\"  {i}/{total}: {msg}\", C[\"text_dim\"]),\n                    )\n                    ot_log(f\"\u2705 PDF bana diya: {out}  ({result.get('pages', 0)} images)\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"Done!\",\n                        f\"\u2705 {result.get('pages', 0)} images \u2192 PDF\\n\\n{out}\"))\n                except Exception as ex:\n                    ot_log(f\"\u274c Error: {ex}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n            threading.Thread(target=_run, daemon=True).start()\n\n        tk.Button(c1a, text=\"\u25b6 Convert to PDF\", font=FONTS[\"body\"],\n                  bg=C[\"accent\"], fg=C[\"bg\"], bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=_do_img2pdf).pack(side=\"left\", padx=10)\n\n        # \u2500\u2500 PDF \u2192 Images \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        c1b = _make_card(t1, \"\ud83d\udcc4  PDF \u2192 Images  (choose format: JPG / PNG / BMP / TIFF)\")\n        r1b = tk.Frame(c1b, bg=C[\"card\"])\n        r1b.pack(fill=\"x\")\n        tk.Label(r1b, text=\"PDF file:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_pdf2img_path = tk.StringVar()\n        tk.Entry(r1b, textvariable=self._ot_pdf2img_path, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=48).pack(side=\"left\", padx=4)\n        tk.Button(r1b, text=\"Browse\u2026\", font=FONTS[\"small\"], bg=C[\"btn_info\"],\n                  fg=C[\"text\"], bd=0, padx=10, pady=4, cursor=\"hand2\",\n                  command=lambda: self._ot_pdf2img_path.set(\n                      filedialog.askopenfilename(filetypes=[(\"PDF\",\"*.pdf\"),(\"All\",\"*.*\")])\n                  )).pack(side=\"left\", padx=4)\n\n        r1b2 = tk.Frame(c1b, bg=C[\"card\"])\n        r1b2.pack(fill=\"x\", pady=(4,0))\n        tk.Label(r1b2, text=\"Output format:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_pdf2img_fmt = tk.StringVar(value=\"JPG\")\n        for fmt in (\"JPG\", \"PNG\", \"BMP\", \"TIFF\"):\n            tk.Radiobutton(r1b2, text=fmt, variable=self._ot_pdf2img_fmt, value=fmt,\n                           font=FONTS[\"small\"], bg=C[\"card\"], fg=C[\"text\"],\n                           selectcolor=C[\"bg\"], activebackground=C[\"card\"]).pack(side=\"left\", padx=6)\n\n        tk.Label(r1b2, text=\"  DPI:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_pdf2img_dpi = tk.StringVar(value=\"150\")\n        tk.Entry(r1b2, textvariable=self._ot_pdf2img_dpi, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=5).pack(side=\"left\", padx=4)\n\n        def _do_pdf2img():\n            pdf_path = self._ot_pdf2img_path.get().strip()\n            if not pdf_path or not os.path.isfile(pdf_path):\n                messagebox.showwarning(\"Warning\", \"Valid PDF select karo.\")\n                return\n            out_dir = filedialog.askdirectory(title=\"Output folder choose karo\")\n            if not out_dir:\n                return\n            fmt  = self._ot_pdf2img_fmt.get()\n            try:\n                dpi = int(self._ot_pdf2img_dpi.get())\n            except Exception:\n                dpi = 150\n            def _run():\n                try:\n                    result = offline_pdf_to_images(\n                        pdf_path,\n                        out_dir,\n                        fmt=fmt.lower(),\n                        dpi=dpi,\n                        pages=None,\n                        jpeg_quality=90,\n                        progress=lambda i, total, msg: ot_log(f\"  {i}/{total}: {msg}\", C[\"text_dim\"]),\n                    )\n                    saved = result.get(\"count\", 0)\n                    ot_log(f\"\u2705 {saved} pages saved to: {out_dir}\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"Done!\", f\"\u2705 {saved} images saved!\\n\\n{out_dir}\"))\n                except Exception as ex:\n                    ot_log(f\"\u274c Error: {ex}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n            threading.Thread(target=_run, daemon=True).start()\n\n        tk.Button(c1b, text=\"\u25b6 Convert to Images\", font=FONTS[\"body\"],\n                  bg=C[\"accent\"], fg=C[\"bg\"], bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=_do_pdf2img).pack(anchor=\"w\", pady=(6,0))\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # TAB 2 \u2014 PDF Operations\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        t2 = tk.Frame(content_host, bg=C[\"bg\"])\n        self._office_tab_frames[\"pdf_ops\"] = t2\n\n        # \u2500\u2500 PDF Merge \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        c2a = _make_card(t2, \"\ud83d\udcce  PDF Merge  (multiple PDFs \u2192 ek PDF)\")\n        tk.Label(c2a, text=\"PDFs select karo (order matters):\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(anchor=\"w\")\n\n        self._ot_merge_list = tk.Listbox(c2a, bg=C[\"bg\"], fg=C[\"text\"], font=FONTS[\"small\"],\n                                          height=4, selectmode=\"extended\",\n                                          selectbackground=C[\"accent\"], activestyle=\"none\")\n        self._ot_merge_list.pack(fill=\"x\", pady=4)\n\n        mr = tk.Frame(c2a, bg=C[\"card\"])\n        mr.pack(fill=\"x\")\n        def _merge_add():\n            files = filedialog.askopenfilenames(filetypes=[(\"PDF\",\"*.pdf\"),(\"All\",\"*.*\")])\n            for f in files:\n                self._ot_merge_list.insert(\"end\", f)\n        def _merge_remove():\n            for i in reversed(self._ot_merge_list.curselection()):\n                self._ot_merge_list.delete(i)\n        def _merge_up():\n            sel = self._ot_merge_list.curselection()\n            for i in sel:\n                if i == 0: continue\n                txt = self._ot_merge_list.get(i)\n                self._ot_merge_list.delete(i)\n                self._ot_merge_list.insert(i-1, txt)\n                self._ot_merge_list.selection_set(i-1)\n        def _merge_down():\n            sel = list(self._ot_merge_list.curselection())\n            for i in reversed(sel):\n                if i &gt;= self._ot_merge_list.size()-1: continue\n                txt = self._ot_merge_list.get(i)\n                self._ot_merge_list.delete(i)\n                self._ot_merge_list.insert(i+1, txt)\n                self._ot_merge_list.selection_set(i+1)\n\n        for txt, cmd in [(\"+ Add PDFs\", _merge_add), (\"\u2715 Remove\", _merge_remove),\n                          (\"\u2191 Up\", _merge_up), (\"\u2193 Down\", _merge_down)]:\n            tk.Button(mr, text=txt, font=FONTS[\"small\"], bg=C[\"btn_info\"], fg=C[\"text\"],\n                      bd=0, padx=8, pady=4, cursor=\"hand2\", command=cmd).pack(side=\"left\", padx=3)\n\n        def _do_merge():\n            files = list(self._ot_merge_list.get(0, \"end\"))\n            if len(files) &lt; 2:\n                messagebox.showwarning(\"Warning\", \"Kam se kam 2 PDFs add karo.\")\n                return\n            out = filedialog.asksaveasfilename(title=\"Merged PDF save karein\",\n                                               defaultextension=\".pdf\",\n                                               filetypes=[(\"PDF\",\"*.pdf\")])\n            if not out:\n                return\n            def _run():\n                try:\n                    if not _ensure_pkg(\"pikepdf\"):\n                        return\n                    import pikepdf\n                    pdf_out = pikepdf.Pdf.new()\n                    for f in files:\n                        with pikepdf.open(f) as src:\n                            pdf_out.pages.extend(src.pages)\n                    pdf_out.save(out)\n                    ot_log(f\"\u2705 Merged {len(files)} PDFs \u2192 {out}\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"Done!\", f\"\u2705 {len(files)} PDFs merge ho gaye!\\n\\n{out}\"))\n                except Exception as ex:\n                    ot_log(f\"\u274c Merge error: {ex}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n            threading.Thread(target=_run, daemon=True).start()\n\n        tk.Button(c2a, text=\"\u25b6 Merge PDFs\", font=FONTS[\"body\"],\n                  bg=C[\"accent\"], fg=C[\"bg\"], bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=_do_merge).pack(anchor=\"w\", pady=(6,0))\n\n        # \u2500\u2500 PDF Split \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        c2b = _make_card(t2, \"\u2702\ufe0f  PDF Split  (ek PDF \u2192 alag alag pages ya ranges)\")\n        r2b = tk.Frame(c2b, bg=C[\"card\"])\n        r2b.pack(fill=\"x\")\n        tk.Label(r2b, text=\"PDF:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_split_path = tk.StringVar()\n        tk.Entry(r2b, textvariable=self._ot_split_path, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=46).pack(side=\"left\", padx=4)\n        tk.Button(r2b, text=\"Browse\u2026\", font=FONTS[\"small\"], bg=C[\"btn_info\"],\n                  fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=lambda: self._ot_split_path.set(\n                      filedialog.askopenfilename(filetypes=[(\"PDF\",\"*.pdf\"),(\"All\",\"*.*\")]))).pack(side=\"left\")\n\n        r2b2 = tk.Frame(c2b, bg=C[\"card\"])\n        r2b2.pack(fill=\"x\", pady=4)\n        tk.Label(r2b2, text=\"Mode:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_split_mode = tk.StringVar(value=\"all\")\n        tk.Radiobutton(r2b2, text=\"Har page alag file\", variable=self._ot_split_mode, value=\"all\",\n                       font=FONTS[\"small\"], bg=C[\"card\"], fg=C[\"text\"],\n                       selectcolor=C[\"bg\"], activebackground=C[\"card\"]).pack(side=\"left\", padx=6)\n        tk.Radiobutton(r2b2, text=\"Range (e.g. 1-3, 5, 7-9):\", variable=self._ot_split_mode, value=\"range\",\n                       font=FONTS[\"small\"], bg=C[\"card\"], fg=C[\"text\"],\n                       selectcolor=C[\"bg\"], activebackground=C[\"card\"]).pack(side=\"left\")\n        self._ot_split_range = tk.StringVar(value=\"1-3, 4-6\")\n        tk.Entry(r2b2, textvariable=self._ot_split_range, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=18).pack(side=\"left\", padx=4)\n\n        def _parse_ranges(text, total):\n            pages = set()\n            for part in text.split(\",\"):\n                part = part.strip()\n                if \"-\" in part:\n                    try:\n                        a, b = part.split(\"-\")\n                        pages.update(range(int(a)-1, int(b)))\n                    except Exception:\n                        pass\n                else:\n                    try:\n                        pages.add(int(part)-1)\n                    except Exception:\n                        pass\n            return sorted(p for p in pages if 0 &lt;= p &lt; total)\n\n        def _do_split():\n            pdf_path = self._ot_split_path.get().strip()\n            if not pdf_path or not os.path.isfile(pdf_path):\n                messagebox.showwarning(\"Warning\", \"Valid PDF select karo.\")\n                return\n            out_dir = filedialog.askdirectory(title=\"Output folder choose karo\")\n            if not out_dir:\n                return\n            mode = self._ot_split_mode.get()\n            def _run():\n                try:\n                    if not _ensure_pkg(\"pikepdf\"):\n                        return\n                    import pikepdf\n                    base = os.path.splitext(os.path.basename(pdf_path))[0]\n                    with pikepdf.open(pdf_path) as src:\n                        total = len(src.pages)\n                        if mode == \"all\":\n                            page_groups = [(i, [i]) for i in range(total)]\n                        else:\n                            idxs = _parse_ranges(self._ot_split_range.get(), total)\n                            if not idxs:\n                                ot_log(\"\u274c Range invalid hai.\", C[\"error\"]); return\n                            # Split on commas \u2192 each comma-segment = one file\n                            raw_parts = [p.strip() for p in self._ot_split_range.get().split(\",\") if p.strip()]\n                            page_groups = []\n                            for seg in raw_parts:\n                                grp = _parse_ranges(seg, total)\n                                page_groups.append((seg, grp))\n                        saved = 0\n                        for label, pages in page_groups:\n                            if not pages:\n                                continue\n                            out_pdf = pikepdf.Pdf.new()\n                            for idx in pages:\n                                out_pdf.pages.append(src.pages[idx])\n                            out_name = f\"{base}_p{label}.pdf\" if mode == \"range\" else f\"{base}_page{label+1:04d}.pdf\"\n                            out_pdf.save(os.path.join(out_dir, out_name))\n                            saved += 1\n                    ot_log(f\"\u2705 Split done: {saved} files \u2192 {out_dir}\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"Done!\", f\"\u2705 {saved} files split!\\n\\n{out_dir}\"))\n                except Exception as ex:\n                    ot_log(f\"\u274c Split error: {ex}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n            threading.Thread(target=_run, daemon=True).start()\n\n        tk.Button(c2b, text=\"\u25b6 Split PDF\", font=FONTS[\"body\"],\n                  bg=C[\"accent\"], fg=C[\"bg\"], bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=_do_split).pack(anchor=\"w\", pady=(6,0))\n\n        # \u2500\u2500 PDF Rotate \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        c2c = _make_card(t2, \"\ud83d\udd04  PDF Rotate  (pages ko rotate karo)\")\n        r2c = tk.Frame(c2c, bg=C[\"card\"])\n        r2c.pack(fill=\"x\")\n        tk.Label(r2c, text=\"PDF:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_rot_path = tk.StringVar()\n        tk.Entry(r2c, textvariable=self._ot_rot_path, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=46).pack(side=\"left\", padx=4)\n        tk.Button(r2c, text=\"Browse\u2026\", font=FONTS[\"small\"], bg=C[\"btn_info\"],\n                  fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=lambda: self._ot_rot_path.set(\n                      filedialog.askopenfilename(filetypes=[(\"PDF\",\"*.pdf\"),(\"All\",\"*.*\")]))).pack(side=\"left\")\n        r2c2 = tk.Frame(c2c, bg=C[\"card\"])\n        r2c2.pack(fill=\"x\", pady=4)\n        tk.Label(r2c2, text=\"Rotation:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_rot_deg = tk.StringVar(value=\"90\")\n        for d in (\"90\", \"180\", \"270\"):\n            tk.Radiobutton(r2c2, text=f\"{d}\u00b0\", variable=self._ot_rot_deg, value=d,\n                           font=FONTS[\"small\"], bg=C[\"card\"], fg=C[\"text\"],\n                           selectcolor=C[\"bg\"], activebackground=C[\"card\"]).pack(side=\"left\", padx=8)\n        tk.Label(r2c2, text=\"  Pages (blank=all, e.g. 1,3,5):\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_rot_pages = tk.StringVar(value=\"\")\n        tk.Entry(r2c2, textvariable=self._ot_rot_pages, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=14).pack(side=\"left\", padx=4)\n\n        def _do_rotate():\n            pdf_path = self._ot_rot_path.get().strip()\n            if not pdf_path or not os.path.isfile(pdf_path):\n                messagebox.showwarning(\"Warning\",\"Valid PDF select karo.\"); return\n            out = filedialog.asksaveasfilename(title=\"Rotated PDF save karein\",\n                                               defaultextension=\".pdf\",\n                                               filetypes=[(\"PDF\",\"*.pdf\")])\n            if not out: return\n            deg = int(self._ot_rot_deg.get())\n            def _run():\n                try:\n                    if not _ensure_pkg(\"pikepdf\"): return\n                    import pikepdf\n                    pages_raw = self._ot_rot_pages.get().strip()\n                    with pikepdf.open(pdf_path) as pdf:\n                        total = len(pdf.pages)\n                        if pages_raw:\n                            idxs = set()\n                            for p in pages_raw.split(\",\"):\n                                try: idxs.add(int(p.strip())-1)\n                                except Exception: pass\n                        else:\n                            idxs = set(range(total))\n                        for i, page in enumerate(pdf.pages):\n                            if i in idxs:\n                                cur = int(page.get(\"/Rotate\", 0))\n                                page[\"/Rotate\"] = (cur + deg) % 360\n                        pdf.save(out)\n                    ot_log(f\"\u2705 Rotated {len(idxs)} pages by {deg}\u00b0 \u2192 {out}\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"Done!\", f\"\u2705 PDF rotated!\\n\\n{out}\"))\n                except Exception as ex:\n                    ot_log(f\"\u274c Rotate error: {ex}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n            threading.Thread(target=_run, daemon=True).start()\n\n        tk.Button(c2c, text=\"\u25b6 Rotate PDF\", font=FONTS[\"body\"],\n                  bg=C[\"accent\"], fg=C[\"bg\"], bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=_do_rotate).pack(anchor=\"w\", pady=(6,0))\n\n        # \u2500\u2500 PDF Compress \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        c2d = _make_card(t2, \"\ud83d\udce6  PDF Compress  (file size kam karo)\")\n        r2d = tk.Frame(c2d, bg=C[\"card\"])\n        r2d.pack(fill=\"x\")\n        tk.Label(r2d, text=\"PDF:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_comp_path = tk.StringVar()\n        tk.Entry(r2d, textvariable=self._ot_comp_path, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=46).pack(side=\"left\", padx=4)\n        tk.Button(r2d, text=\"Browse\u2026\", font=FONTS[\"small\"], bg=C[\"btn_info\"],\n                  fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=lambda: self._ot_comp_path.set(\n                      filedialog.askopenfilename(filetypes=[(\"PDF\",\"*.pdf\"),(\"All\",\"*.*\")]))).pack(side=\"left\")\n\n        def _do_compress():\n            pdf_path = self._ot_comp_path.get().strip()\n            if not pdf_path or not os.path.isfile(pdf_path):\n                messagebox.showwarning(\"Warning\",\"Valid PDF select karo.\"); return\n            out = filedialog.asksaveasfilename(title=\"Compressed PDF save karein\",\n                                               defaultextension=\".pdf\",\n                                               filetypes=[(\"PDF\",\"*.pdf\")])\n            if not out: return\n            def _run():\n                try:\n                    if not _ensure_pkg(\"pikepdf\"): return\n                    import pikepdf\n                    before = os.path.getsize(pdf_path)\n                    with pikepdf.open(pdf_path) as pdf:\n                        pdf.save(out, compress_streams=True, object_stream_mode=pikepdf.ObjectStreamMode.generate)\n                    after = os.path.getsize(out)\n                    saved_pct = max(0, (before-after)/before*100) if before else 0\n                    msg = (f\"\u2705 Compressed!\\n\"\n                           f\"Before: {_human_size(before)}\\n\"\n                           f\"After:  {_human_size(after)}\\n\"\n                           f\"Saved:  {saved_pct:.1f}%\")\n                    ot_log(msg, C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"Done!\", f\"{msg}\\n\\n{out}\"))\n                except Exception as ex:\n                    ot_log(f\"\u274c Compress error: {ex}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n            threading.Thread(target=_run, daemon=True).start()\n\n        tk.Button(c2d, text=\"\u25b6 Compress PDF\", font=FONTS[\"body\"],\n                  bg=C[\"accent\"], fg=C[\"bg\"], bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=_do_compress).pack(anchor=\"w\", pady=(6,0))\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # TAB 3 \u2014 Office Converter\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        t3 = tk.Frame(content_host, bg=C[\"bg\"])\n        self._office_tab_frames[\"office_conv\"] = t3\n\n        tk.Label(t3, text=\"  \u2139\ufe0f  Office Converter requires Microsoft Office (Word/Excel) to be installed.\",\n                 font=FONTS[\"small\"], fg=C[\"accent4\"], bg=C[\"bg\"]).pack(anchor=\"w\", padx=16, pady=(8,2))\n        tk.Label(t3, text=\"  PDF \u2192 Word/Excel uses python-docx + openpyxl (no Office needed).\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"bg\"]).pack(anchor=\"w\", padx=16, pady=(0,4))\n\n        # \u2500\u2500 DOC/DOCX/XLS/XLSX/PPT/PPTX \u2192 PDF via Word/Excel COM \u2500\n        c3a = _make_card(t3, \"\ud83d\udcdd  Office File \u2192 PDF  (Word / Excel / PowerPoint)\")\n        r3a = tk.Frame(c3a, bg=C[\"card\"])\n        r3a.pack(fill=\"x\")\n        tk.Label(r3a, text=\"File:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_o2p_path = tk.StringVar()\n        tk.Entry(r3a, textvariable=self._ot_o2p_path, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=46).pack(side=\"left\", padx=4)\n        tk.Button(r3a, text=\"Browse\u2026\", font=FONTS[\"small\"], bg=C[\"btn_info\"],\n                  fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=lambda: self._ot_o2p_path.set(\n                      filedialog.askopenfilename(\n                          filetypes=[(\"Office files\",\"*.doc *.docx *.xls *.xlsx *.ppt *.pptx *.odt *.ods *.odp\"),\n                                     (\"All\",\"*.*\")]))).pack(side=\"left\")\n\n        def _do_office2pdf():\n            src = self._ot_o2p_path.get().strip()\n            if not src or not os.path.isfile(src):\n                messagebox.showwarning(\"Warning\",\"Valid Office file select karo.\"); return\n            out = filedialog.asksaveasfilename(title=\"Output PDF save karein\",\n                                               defaultextension=\".pdf\",\n                                               filetypes=[(\"PDF\",\"*.pdf\")])\n            if not out: return\n            def _run():\n                try:\n                    src_abs = os.path.abspath(src)\n                    out_abs = os.path.abspath(out)\n                    ext = os.path.splitext(src_abs)[1].lower()\n                    try:\n                        ot_log(\"LibreOffice offline engine se convert ho raha hai...\", C[\"text_dim\"])\n                        offline_office_to_pdf(src_abs, out_abs, timeout=180)\n                        ot_log(f\"OK LibreOffice convert done -&gt; {out_abs}\", C[\"success\"])\n                        self.after(0, lambda: messagebox.showinfo(\"Done!\", f\"PDF ready!\\n\\n{out_abs}\"))\n                        return\n                    except Exception as lo_ex:\n                        ot_log(f\"LibreOffice unavailable/failed: {lo_ex}\", C[\"warning\"])\n\n                    try:\n                        offline_office_com_to_pdf(src_abs, out_abs)\n                        ot_log(f\"OK Microsoft Office COM convert done -&gt; {out_abs}\", C[\"success\"])\n                        self.after(0, lambda: messagebox.showinfo(\"Done!\", f\"PDF ready!\\n\\n{out_abs}\"))\n                        return\n                    except Exception as com_ex:\n                        ot_log(f\"Microsoft Office COM unavailable/failed: {com_ex}\", C[\"warning\"])\n\n                    raise RuntimeError(\"No local Office PDF engine available. Install LibreOffice or Microsoft Office.\")\n\n                    # Try LibreOffice first (free)\n                    lo_paths = [\n                        r\"C:\\Program Files\\LibreOffice\\program\\soffice.exe\",\n                        r\"C:\\Program Files (x86)\\LibreOffice\\program\\soffice.exe\",\n                    ]\n                    lo_found = None  # handled by offline_office_to_pdf above\n                    if lo_found:\n                        ot_log(\"LibreOffice se convert ho raha hai\u2026\", C[\"text_dim\"])\n                        tmp_dir = tempfile.mkdtemp()\n                        res = safe_run([lo_found, \"--headless\", \"--convert-to\", \"pdf\",\n                                        \"--outdir\", tmp_dir, src_abs], timeout=120)\n                        gen = os.path.join(tmp_dir, os.path.splitext(os.path.basename(src_abs))[0]+\".pdf\")\n                        if os.path.isfile(gen):\n                            shutil.move(gen, out_abs)\n                            ot_log(f\"\u2705 LibreOffice convert done \u2192 {out_abs}\", C[\"success\"])\n                            self.after(0, lambda: messagebox.showinfo(\"Done!\", f\"\u2705 PDF ready!\\n\\n{out_abs}\"))\n                            return\n                    # COM automation fallback (MS Office required)\n                    try:\n                        import win32com.client\n                    except ImportError:\n                        _ensure_pkg(\"win32com\", \"pywin32\")\n                        import win32com.client\n\n                    if ext in (\".doc\", \".docx\", \".odt\"):\n                        app_prog = \"Word.Application\"\n                        wdFormatPDF = 17\n                        word = win32com.client.DispatchEx(app_prog)\n                        word.Visible = False\n                        try:\n                            doc = word.Documents.Open(src_abs)\n                            doc.SaveAs(out_abs, FileFormat=wdFormatPDF)\n                            doc.Close()\n                        finally:\n                            word.Quit()\n                        ot_log(f\"\u2705 Word \u2192 PDF: {out_abs}\", C[\"success\"])\n                    elif ext in (\".xls\", \".xlsx\", \".ods\"):\n                        xl = win32com.client.DispatchEx(\"Excel.Application\")\n                        xl.Visible = False\n                        try:\n                            wb = xl.Workbooks.Open(src_abs)\n                            wb.ExportAsFixedFormat(0, out_abs)\n                            wb.Close(False)\n                        finally:\n                            xl.Quit()\n                        ot_log(f\"\u2705 Excel \u2192 PDF: {out_abs}\", C[\"success\"])\n                    elif ext in (\".ppt\", \".pptx\", \".odp\"):\n                        pp = win32com.client.DispatchEx(\"PowerPoint.Application\")\n                        pp.Visible = True\n                        try:\n                            prs = pp.Presentations.Open(src_abs, WithWindow=False)\n                            prs.SaveAs(out_abs, 32)   # ppSaveAsPDF = 32\n                            prs.Close()\n                        finally:\n                            pp.Quit()\n                        ot_log(f\"\u2705 PowerPoint \u2192 PDF: {out_abs}\", C[\"success\"])\n                    else:\n                        ot_log(\"\u274c Format supported nahi hai COM automation ke liye.\", C[\"error\"])\n                        return\n                    self.after(0, lambda: messagebox.showinfo(\"Done!\", f\"\u2705 PDF ready!\\n\\n{out_abs}\"))\n                except Exception as ex:\n                    ot_log(f\"Convert error: {ex}\\n(Tip: LibreOffice ya Microsoft Office local/offline install chahiye)\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\",\n                        f\"{ex}\\n\\nTip: LibreOffice ya Microsoft Office local/offline install karke dobara try karo.\"))\n            if getattr(self, \"worker_manager\", None):\n                self.worker_manager.submit(_run, name=\"office_to_pdf\")\n            else:\n                threading.Thread(target=_run, daemon=True).start()\n\n        tk.Button(c3a, text=\"\u25b6 Convert to PDF\", font=FONTS[\"body\"],\n                  bg=C[\"accent\"], fg=C[\"bg\"], bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=_do_office2pdf).pack(anchor=\"w\", pady=(6,0))\n\n        # \u2500\u2500 PDF \u2192 Word (text extraction) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        c3b = _make_card(t3, \"\ud83d\udcc4\u2192\ud83d\udcdd  PDF \u2192 Word  (text extraction \u2014 python-docx)\")\n        r3b = tk.Frame(c3b, bg=C[\"card\"])\n        r3b.pack(fill=\"x\")\n        tk.Label(r3b, text=\"PDF:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_p2w_path = tk.StringVar()\n        tk.Entry(r3b, textvariable=self._ot_p2w_path, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=46).pack(side=\"left\", padx=4)\n        tk.Button(r3b, text=\"Browse\u2026\", font=FONTS[\"small\"], bg=C[\"btn_info\"],\n                  fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=lambda: self._ot_p2w_path.set(\n                      filedialog.askopenfilename(filetypes=[(\"PDF\",\"*.pdf\"),(\"All\",\"*.*\")]))).pack(side=\"left\")\n\n        def _do_pdf2word():\n            pdf_path = self._ot_p2w_path.get().strip()\n            if not pdf_path or not os.path.isfile(pdf_path):\n                messagebox.showwarning(\"Warning\",\"Valid PDF select karo.\"); return\n            out = filedialog.asksaveasfilename(title=\"Word file save karein\",\n                                               defaultextension=\".docx\",\n                                               filetypes=[(\"Word\",\"*.docx\")])\n            if not out: return\n            def _run():\n                try:\n                    if not _ensure_pkg(\"pikepdf\"): return\n                    if not _ensure_pkg(\"docx\", \"python-docx\"): return\n                    import pikepdf, docx\n                    doc = docx.Document()\n                    doc.add_heading(\"PDF \u2192 Word Conversion\", 0)\n                    doc.add_paragraph(f\"Source: {pdf_path}\")\n                    doc.add_paragraph(\"\u2500\" * 60)\n                    # Text extraction via pikepdf content streams\n                    with pikepdf.open(pdf_path) as pdf:\n                        for page_num, page in enumerate(pdf.pages):\n                            doc.add_heading(f\"Page {page_num+1}\", level=2)\n                            try:\n                                raw = page.obj.get(\"/Contents\")\n                                if raw is None:\n                                    doc.add_paragraph(\"[Empty page]\")\n                                    continue\n                                contents = pdf.get_object(raw.objgen) if hasattr(raw, 'objgen') else raw\n                                if hasattr(contents, 'read_bytes'):\n                                    data = contents.read_bytes()\n                                elif hasattr(contents, '__iter__'):\n                                    data = b\"\".join(s.read_bytes() for s in contents if hasattr(s, 'read_bytes'))\n                                else:\n                                    data = b\"\"\n                                try:\n                                    data = zlib.decompress(data)\n                                except Exception:\n                                    pass\n                                text_bits = re.findall(rb'\\(([^)]*)\\)', data)\n                                plain = \" \".join(b.decode(\"latin-1\", errors=\"replace\") for b in text_bits)\n                                doc.add_paragraph(plain[:4000] or \"[Could not extract text \u2014 scanned PDF?]\")\n                            except Exception as pe:\n                                doc.add_paragraph(f\"[Page extract error: {pe}]\")\n                    doc.save(out)\n                    ot_log(f\"\u2705 PDF \u2192 Word done: {out}\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"Done!\",\n                        f\"\u2705 Word file ready!\\n\\n{out}\\n\\n\"\n                        \"Note: Scanned PDFs ke liye OCR (Tesseract) ki zaroorat hoti hai.\"))\n                except Exception as ex:\n                    ot_log(f\"\u274c PDF\u2192Word error: {ex}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n            threading.Thread(target=_run, daemon=True).start()\n\n        tk.Button(c3b, text=\"\u25b6 PDF \u2192 Word\", font=FONTS[\"body\"],\n                  bg=C[\"accent\"], fg=C[\"bg\"], bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=_do_pdf2word).pack(anchor=\"w\", pady=(6,0))\n\n        # \u2500\u2500 PDF \u2192 Excel (table extraction) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        c3c = _make_card(t3, \"\ud83d\udcc4\u2192\ud83d\udcca  PDF \u2192 Excel  (table/text extraction \u2014 openpyxl)\")\n        r3c = tk.Frame(c3c, bg=C[\"card\"])\n        r3c.pack(fill=\"x\")\n        tk.Label(r3c, text=\"PDF:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_p2x_path = tk.StringVar()\n        tk.Entry(r3c, textvariable=self._ot_p2x_path, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=46).pack(side=\"left\", padx=4)\n        tk.Button(r3c, text=\"Browse\u2026\", font=FONTS[\"small\"], bg=C[\"btn_info\"],\n                  fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=lambda: self._ot_p2x_path.set(\n                      filedialog.askopenfilename(filetypes=[(\"PDF\",\"*.pdf\"),(\"All\",\"*.*\")]))).pack(side=\"left\")\n\n        def _do_pdf2excel():\n            pdf_path = self._ot_p2x_path.get().strip()\n            if not pdf_path or not os.path.isfile(pdf_path):\n                messagebox.showwarning(\"Warning\",\"Valid PDF select karo.\"); return\n            out = filedialog.asksaveasfilename(title=\"Excel file save karein\",\n                                               defaultextension=\".xlsx\",\n                                               filetypes=[(\"Excel\",\"*.xlsx\")])\n            if not out: return\n            def _run():\n                try:\n                    if not _ensure_pkg(\"pikepdf\"): return\n                    if not _ensure_pkg(\"openpyxl\"): return\n                    import pikepdf, openpyxl\n                    wb = openpyxl.Workbook()\n                    with pikepdf.open(pdf_path) as pdf:\n                        for page_num, page in enumerate(pdf.pages):\n                            ws = wb.create_sheet(title=f\"Page {page_num+1}\")\n                            ws.append([f\"=== PDF Page {page_num+1} ===\"])\n                            try:\n                                raw = page.obj.get(\"/Contents\")\n                                if raw is None:\n                                    ws.append([\"[Empty page]\"]); continue\n                                contents = pdf.get_object(raw.objgen) if hasattr(raw,'objgen') else raw\n                                if hasattr(contents,'read_bytes'):\n                                    data = contents.read_bytes()\n                                elif hasattr(contents,'__iter__'):\n                                    data = b\"\".join(s.read_bytes() for s in contents if hasattr(s,'read_bytes'))\n                                else:\n                                    data = b\"\"\n                                try: data = zlib.decompress(data)\n                                except Exception: pass\n                                text_bits = re.findall(rb'\\(([^)]*)\\)', data)\n                                lines = \" \".join(b.decode(\"latin-1\",errors=\"replace\") for b in text_bits)\n                                for row in lines.split(\"  \"):\n                                    row = row.strip()\n                                    if row:\n                                        ws.append([row])\n                            except Exception as pe:\n                                ws.append([f\"[Error: {pe}]\"])\n                    if \"Sheet\" in wb.sheetnames:\n                        del wb[\"Sheet\"]\n                    wb.save(out)\n                    ot_log(f\"\u2705 PDF \u2192 Excel done: {out}\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"Done!\",\n                        f\"\u2705 Excel ready!\\n\\n{out}\\n\\n\"\n                        \"Tip: Complex tables ke liye Tabula-py try karo.\"))\n                except Exception as ex:\n                    ot_log(f\"\u274c PDF\u2192Excel error: {ex}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n            threading.Thread(target=_run, daemon=True).start()\n\n        tk.Button(c3c, text=\"\u25b6 PDF \u2192 Excel\", font=FONTS[\"body\"],\n                  bg=C[\"accent\"], fg=C[\"bg\"], bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=_do_pdf2excel).pack(anchor=\"w\", pady=(6,0))\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # TAB 4 \u2014 Office File Repair\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        t4 = tk.Frame(content_host, bg=C[\"bg\"])\n        self._office_tab_frames[\"file_repair\"] = t4\n\n        # \u2500\u2500 Info banner \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        info_bar = tk.Frame(t4, bg=C[\"panel\"])\n        info_bar.pack(fill=\"x\", padx=16, pady=8)\n        tk.Label(info_bar,\n                 text=(\"  \ud83d\udd27  Office File Repair Engine\\n\"\n                       \"  DOCX/XLSX/PPTX = ZIP-based repair (pikepdf/python-docx/openpyxl)\\n\"\n                       \"  PDF = cross-reference table rebuild (pikepdf)\\n\"\n                       \"  Corrupt/truncated files ke liye best-effort recovery\"),\n                 font=FONTS[\"small\"], fg=C[\"text\"], bg=C[\"panel\"],\n                 justify=\"left\").pack(anchor=\"w\", padx=10, pady=8)\n\n        # \u2500\u2500 DOCX Repair \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        c4a = _make_card(t4, \"\ud83d\udcdd  Corrupt DOCX Repair\")\n        r4a = tk.Frame(c4a, bg=C[\"card\"])\n        r4a.pack(fill=\"x\")\n        tk.Label(r4a, text=\"Corrupt DOCX:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_fix_docx_path = tk.StringVar()\n        tk.Entry(r4a, textvariable=self._ot_fix_docx_path, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=44).pack(side=\"left\", padx=4)\n        tk.Button(r4a, text=\"Browse\u2026\", font=FONTS[\"small\"], bg=C[\"btn_info\"],\n                  fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=lambda: self._ot_fix_docx_path.set(\n                      filedialog.askopenfilename(filetypes=[(\"Word\",\"*.docx *.doc\"),(\"All\",\"*.*\")]))).pack(side=\"left\")\n\n        def _do_repair_docx():\n            src = self._ot_fix_docx_path.get().strip()\n            if not src or not os.path.isfile(src):\n                messagebox.showwarning(\"Warning\",\"Valid DOCX select karo.\"); return\n            out = filedialog.asksaveasfilename(title=\"Repaired DOCX save karein\",\n                                               defaultextension=\".docx\",\n                                               filetypes=[(\"Word\",\"*.docx\")])\n            if not out: return\n            def _run():\n                import zipfile\n                try:\n                    # Step 1: try python-docx direct open\n                    if not _ensure_pkg(\"docx\",\"python-docx\"): return\n                    import docx as _docx_mod\n                    try:\n                        doc = _docx_mod.Document(src)\n                        doc.save(out)\n                        ot_log(f\"\u2705 DOCX repair (direct): {out}\", C[\"success\"])\n                        self.after(0, lambda: messagebox.showinfo(\"Done!\", f\"\u2705 DOCX repaired!\\n\\n{out}\"))\n                        return\n                    except Exception as e1:\n                        ot_log(f\"  Direct open failed ({e1}), ZIP recovery try kar raha hai\u2026\", C[\"warning\"])\n\n                    # Step 2: ZIP-level recovery\n                    with zipfile.ZipFile(src, \"r\") as z:\n                        names = z.namelist()\n                    # Try to recover word/document.xml\n                    with zipfile.ZipFile(src, \"r\") as z_in:\n                        tmp_dir = tempfile.mkdtemp()\n                        recovered = []\n                        for name in names:\n                            try:\n                                data = z_in.read(name)\n                                dest = os.path.join(tmp_dir, name)\n                                os.makedirs(os.path.dirname(dest), exist_ok=True)\n                                with open(dest, \"wb\") as f:\n                                    f.write(data)\n                                recovered.append(name)\n                            except Exception:\n                                ot_log(f\"  \u26a0\ufe0f Skip: {name}\", C[\"warning\"])\n                    # Repack\n                    with zipfile.ZipFile(out, \"w\", compression=zipfile.ZIP_DEFLATED) as z_out:\n                        for name in recovered:\n                            z_out.write(os.path.join(tmp_dir, name), name)\n                    shutil.rmtree(tmp_dir, ignore_errors=True)\n                    ot_log(f\"\u2705 DOCX ZIP recovery: {len(recovered)}/{len(names)} parts saved \u2192 {out}\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"Done!\",\n                        f\"\u2705 DOCX ZIP repair done!\\n{len(recovered)}/{len(names)} parts recovered.\\n\\n{out}\"))\n                except Exception as ex:\n                    ot_log(f\"\u274c DOCX repair error: {ex}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n            threading.Thread(target=_run, daemon=True).start()\n\n        tk.Button(c4a, text=\"\u25b6 Repair DOCX\", font=FONTS[\"body\"],\n                  bg=C[\"warning\"], fg=C[\"bg\"], bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=_do_repair_docx).pack(anchor=\"w\", pady=(6,0))\n\n        # \u2500\u2500 XLSX Repair \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        c4b = _make_card(t4, \"\ud83d\udcca  Corrupt XLSX Repair\")\n        r4b = tk.Frame(c4b, bg=C[\"card\"])\n        r4b.pack(fill=\"x\")\n        tk.Label(r4b, text=\"Corrupt XLSX:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_fix_xlsx_path = tk.StringVar()\n        tk.Entry(r4b, textvariable=self._ot_fix_xlsx_path, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=44).pack(side=\"left\", padx=4)\n        tk.Button(r4b, text=\"Browse\u2026\", font=FONTS[\"small\"], bg=C[\"btn_info\"],\n                  fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=lambda: self._ot_fix_xlsx_path.set(\n                      filedialog.askopenfilename(filetypes=[(\"Excel\",\"*.xlsx *.xls\"),(\"All\",\"*.*\")]))).pack(side=\"left\")\n\n        def _do_repair_xlsx():\n            src = self._ot_fix_xlsx_path.get().strip()\n            if not src or not os.path.isfile(src):\n                messagebox.showwarning(\"Warning\",\"Valid XLSX select karo.\"); return\n            out = filedialog.asksaveasfilename(title=\"Repaired XLSX save karein\",\n                                               defaultextension=\".xlsx\",\n                                               filetypes=[(\"Excel\",\"*.xlsx\")])\n            if not out: return\n            def _run():\n                import zipfile\n                try:\n                    if not _ensure_pkg(\"openpyxl\"): return\n                    import openpyxl\n                    # Step 1: direct open\n                    try:\n                        wb = openpyxl.load_workbook(src, read_only=False, data_only=True, keep_links=False)\n                        wb.save(out)\n                        ot_log(f\"\u2705 XLSX repair (direct): {out}\", C[\"success\"])\n                        self.after(0, lambda: messagebox.showinfo(\"Done!\", f\"\u2705 XLSX repaired!\\n\\n{out}\"))\n                        return\n                    except Exception as e1:\n                        ot_log(f\"  Direct open failed ({e1}), ZIP recovery\u2026\", C[\"warning\"])\n                    # Step 2: ZIP recovery\n                    with zipfile.ZipFile(src,\"r\") as z:\n                        names = z.namelist()\n                    tmp_dir = tempfile.mkdtemp()\n                    recovered = []\n                    with zipfile.ZipFile(src,\"r\") as z_in:\n                        for name in names:\n                            try:\n                                data = z_in.read(name)\n                                dest = os.path.join(tmp_dir, name)\n                                os.makedirs(os.path.dirname(dest), exist_ok=True)\n                                with open(dest,\"wb\") as f: f.write(data)\n                                recovered.append(name)\n                            except Exception:\n                                ot_log(f\"  \u26a0\ufe0f Skip: {name}\", C[\"warning\"])\n                    with zipfile.ZipFile(out,\"w\",compression=zipfile.ZIP_DEFLATED) as z_out:\n                        for name in recovered:\n                            z_out.write(os.path.join(tmp_dir,name), name)\n                    shutil.rmtree(tmp_dir, ignore_errors=True)\n                    ot_log(f\"\u2705 XLSX ZIP recovery: {len(recovered)}/{len(names)} \u2192 {out}\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"Done!\",\n                        f\"\u2705 XLSX ZIP repair done!\\n{len(recovered)}/{len(names)} parts recovered.\\n\\n{out}\"))\n                except Exception as ex:\n                    ot_log(f\"\u274c XLSX repair error: {ex}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n            threading.Thread(target=_run, daemon=True).start()\n\n        tk.Button(c4b, text=\"\u25b6 Repair XLSX\", font=FONTS[\"body\"],\n                  bg=C[\"warning\"], fg=C[\"bg\"], bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=_do_repair_xlsx).pack(anchor=\"w\", pady=(6,0))\n\n        # \u2500\u2500 PDF Repair \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        c4c = _make_card(t4, \"\ud83d\udcc4  Corrupt PDF Repair  (cross-reference rebuild \u2014 pikepdf)\")\n        r4c = tk.Frame(c4c, bg=C[\"card\"])\n        r4c.pack(fill=\"x\")\n        tk.Label(r4c, text=\"Corrupt PDF:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_fix_pdf_path = tk.StringVar()\n        tk.Entry(r4c, textvariable=self._ot_fix_pdf_path, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=44).pack(side=\"left\", padx=4)\n        tk.Button(r4c, text=\"Browse\u2026\", font=FONTS[\"small\"], bg=C[\"btn_info\"],\n                  fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=lambda: self._ot_fix_pdf_path.set(\n                      filedialog.askopenfilename(filetypes=[(\"PDF\",\"*.pdf\"),(\"All\",\"*.*\")]))).pack(side=\"left\")\n\n        def _do_repair_pdf():\n            src = self._ot_fix_pdf_path.get().strip()\n            if not src or not os.path.isfile(src):\n                messagebox.showwarning(\"Warning\",\"Valid PDF select karo.\"); return\n            out = filedialog.asksaveasfilename(title=\"Repaired PDF save karein\",\n                                               defaultextension=\".pdf\",\n                                               filetypes=[(\"PDF\",\"*.pdf\")])\n            if not out: return\n            def _run():\n                try:\n                    if not _ensure_pkg(\"pikepdf\"): return\n                    import pikepdf\n                    before = os.path.getsize(src)\n                    with pikepdf.open(src, suppress_warnings=False,\n                                      allow_overwriting_input=False) as pdf:\n                        # pikepdf auto-rebuilds xref table on save\n                        pdf.save(out, fix_metadata_version=True,\n                                 compress_streams=True,\n                                 object_stream_mode=pikepdf.ObjectStreamMode.generate)\n                    after = os.path.getsize(out)\n                    ot_log(f\"\u2705 PDF repair done: {out}  ({_human_size(before)} \u2192 {_human_size(after)})\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"Done!\",\n                        f\"\u2705 PDF repaired!\\n\"\n                        f\"Before: {_human_size(before)}\\nAfter: {_human_size(after)}\\n\\n{out}\"))\n                except Exception as ex:\n                    ot_log(f\"\u274c PDF repair error: {ex}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n            threading.Thread(target=_run, daemon=True).start()\n\n        tk.Button(c4c, text=\"\u25b6 Repair PDF\", font=FONTS[\"body\"],\n                  bg=C[\"warning\"], fg=C[\"bg\"], bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=_do_repair_pdf).pack(anchor=\"w\", pady=(6,0))\n\n        # \u2500\u2500 PPTX Repair \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        c4d = _make_card(t4, \"\ud83d\udcca  Corrupt PPTX Repair  (PowerPoint ZIP recovery)\")\n        r4d = tk.Frame(c4d, bg=C[\"card\"])\n        r4d.pack(fill=\"x\")\n        tk.Label(r4d, text=\"Corrupt PPTX:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"card\"]).pack(side=\"left\")\n        self._ot_fix_pptx_path = tk.StringVar()\n        tk.Entry(r4d, textvariable=self._ot_fix_pptx_path, font=FONTS[\"small\"],\n                 bg=C[\"bg\"], fg=C[\"text\"], insertbackground=C[\"text\"], width=44).pack(side=\"left\", padx=4)\n        tk.Button(r4d, text=\"Browse\u2026\", font=FONTS[\"small\"], bg=C[\"btn_info\"],\n                  fg=C[\"text\"], bd=0, padx=8, pady=4, cursor=\"hand2\",\n                  command=lambda: self._ot_fix_pptx_path.set(\n                      filedialog.askopenfilename(filetypes=[(\"PowerPoint\",\"*.pptx *.ppt\"),(\"All\",\"*.*\")]))).pack(side=\"left\")\n\n        def _do_repair_pptx():\n            src = self._ot_fix_pptx_path.get().strip()\n            if not src or not os.path.isfile(src):\n                messagebox.showwarning(\"Warning\",\"Valid PPTX select karo.\"); return\n            out = filedialog.asksaveasfilename(title=\"Repaired PPTX save karein\",\n                                               defaultextension=\".pptx\",\n                                               filetypes=[(\"PowerPoint\",\"*.pptx\")])\n            if not out: return\n            def _run():\n                import zipfile\n                try:\n                    with zipfile.ZipFile(src,\"r\") as z:\n                        names = z.namelist()\n                    tmp_dir = tempfile.mkdtemp()\n                    recovered = []\n                    with zipfile.ZipFile(src,\"r\") as z_in:\n                        for name in names:\n                            try:\n                                data = z_in.read(name)\n                                dest = os.path.join(tmp_dir,name)\n                                os.makedirs(os.path.dirname(dest),exist_ok=True)\n                                with open(dest,\"wb\") as f: f.write(data)\n                                recovered.append(name)\n                            except Exception:\n                                ot_log(f\"  \u26a0\ufe0f Skip: {name}\", C[\"warning\"])\n                    with zipfile.ZipFile(out,\"w\",compression=zipfile.ZIP_DEFLATED) as z_out:\n                        for name in recovered:\n                            z_out.write(os.path.join(tmp_dir,name), name)\n                    shutil.rmtree(tmp_dir, ignore_errors=True)\n                    ot_log(f\"\u2705 PPTX repair: {len(recovered)}/{len(names)} parts \u2192 {out}\", C[\"success\"])\n                    self.after(0, lambda: messagebox.showinfo(\"Done!\",\n                        f\"\u2705 PPTX repaired!\\n{len(recovered)}/{len(names)} parts recovered.\\n\\n{out}\"))\n                except Exception as ex:\n                    ot_log(f\"\u274c PPTX repair error: {ex}\", C[\"error\"])\n                    self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n            threading.Thread(target=_run, daemon=True).start()\n\n        tk.Button(c4d, text=\"\u25b6 Repair PPTX\", font=FONTS[\"body\"],\n                  bg=C[\"warning\"], fg=C[\"bg\"], bd=0, padx=14, pady=6, cursor=\"hand2\",\n                  command=_do_repair_pptx).pack(anchor=\"w\", pady=(6,0))\n\n        # \u2500\u2500 Activate first tab \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        _switch_office_tab(\"img_pdf\")\n        return frame\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # EXCEL TOOLS SECTION\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _build_excel_tools(self, parent):\n        \"\"\"\n        Excel Tools:\n          Tab 1 \u2014 Format Conversion   (Excel\u2194CSV, sheet splitter)\n          Tab 2 \u2014 Data Cleaning       (duplicate rows, bulk formatter, password remove)\n          Tab 3 \u2014 Merge &amp; Audit       (bulk merge, formula auditor)\n          Tab 4 \u2014 DOCX Security       (password protect / remove Word files)\n        \"\"\"\n        import threading, zipfile\n\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n\n        # \u2500\u2500 Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        hdr = tk.Frame(frame, bg=C[\"panel\"])\n        hdr.pack(fill=\"x\")\n        tk.Label(hdr, text=\"  \ud83d\udcca Excel &amp; Word Tools\",\n                 font=FONTS[\"heading\"], fg=C[\"accent\"], bg=C[\"panel\"]).pack(side=\"left\", pady=10, padx=8)\n        tk.Label(hdr, text=\"CSV \u00b7 Merge \u00b7 Clean \u00b7 Audit \u00b7 Password  |  Offline local dependencies only\",\n                 font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"left\", pady=10)\n\n        # \u2500\u2500 Sub-tab bar \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        tab_bar = tk.Frame(frame, bg=C[\"card\"])\n        tab_bar.pack(fill=\"x\")\n        tk.Frame(tab_bar, bg=C[\"border\"], height=1).pack(side=\"bottom\", fill=\"x\")\n        content_host = tk.Frame(frame, bg=C[\"bg\"])\n        content_host.pack(fill=\"both\", expand=True)\n\n        _xt_frames = {}\n        _xt_btns   = {}\n\n        def _xt_switch(key):\n            for k, b in _xt_btns.items():\n                b.config(bg=C[\"accent\"] if k==key else C[\"panel\"],\n                         fg=C[\"bg\"]     if k==key else C[\"text\"])\n            for k, f in _xt_frames.items():\n                (f.pack if k==key else f.pack_forget)(fill=\"both\", expand=True) if k==key else f.pack_forget()\n\n        subtabs = [(\"conv\",\"\u21c4  Conversion\"), (\"clean\",\"\ud83e\uddf9  Data Clean\"),\n                   (\"merge\",\"\ud83d\udd17  Merge &amp; Audit\"), (\"security\",\"\ud83d\udd10  Security\")]\n        for key, label in subtabs:\n            b = tk.Button(tab_bar, text=label, font=FONTS[\"body\"],\n                          bg=C[\"panel\"], fg=C[\"text\"], bd=0, padx=18, pady=8, cursor=\"hand2\",\n                          command=lambda k=key: _xt_switch(k))\n            b.pack(side=\"left\")\n            _xt_btns[key] = b\n\n        # \u2500\u2500 Shared log \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        log_host = tk.Frame(frame, bg=C[\"card\"])\n        log_host.pack(fill=\"x\", side=\"bottom\")\n        tk.Label(log_host, text=\"  Activity Log\", font=FONTS[\"small\"],\n                 fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=8, pady=(5,0))\n        _xt_log_w = scrolledtext.ScrolledText(log_host, height=4, state=\"disabled\",\n                                               bg=C[\"bg\"], fg=C[\"text\"], font=FONTS[\"small\"], bd=0)\n        _xt_log_w.pack(fill=\"x\", padx=8, pady=(2,6))\n\n        def xt_log(msg, color=None):\n            ts = datetime.datetime.now().strftime(\"%H:%M:%S\")\n            _xt_log_w.config(state=\"normal\")\n            tag = f\"t{abs(hash(color or ''))}\"\n            _xt_log_w.tag_config(tag, foreground=color or C[\"text\"])\n            _xt_log_w.insert(\"end\", f\"[{ts}] {msg}\\n\", tag)\n            _xt_log_w.see(\"end\")\n            _xt_log_w.config(state=\"disabled\")\n\n        def _xpkg(imp, pip=None):\n            pip = pip or imp\n            try: __import__(imp); return True\n            except ImportError:\n                xt_log(f\"\u274c Missing local dependency: {pip}. Runtime download/install is disabled.\", C[\"error\"])\n                return False\n\n        def _card(par, title):\n            c = tk.Frame(par, bg=C[\"card\"])\n            c.pack(fill=\"x\", padx=16, pady=10)\n            tk.Label(c, text=title, font=FONTS[\"subhead\"], fg=C[\"accent\"], bg=C[\"card\"]).pack(anchor=\"w\", padx=10, pady=(8,4))\n            tk.Frame(c, bg=C[\"border\"], height=1).pack(fill=\"x\", padx=10)\n            b = tk.Frame(c, bg=C[\"card\"])\n            b.pack(fill=\"x\", padx=10, pady=10)\n            return b\n\n        def _row(par): r=tk.Frame(par,bg=C[\"card\"]); r.pack(fill=\"x\",pady=3); return r\n        def _lbl(par,txt): tk.Label(par,text=txt,font=FONTS[\"small\"],fg=C[\"text_dim\"],bg=C[\"card\"]).pack(side=\"left\",padx=(0,4))\n        def _entry(par,var,w=44): return tk.Entry(par,textvariable=var,font=FONTS[\"small\"],bg=C[\"bg\"],fg=C[\"text\"],insertbackground=C[\"text\"],width=w)\n        def _browse_btn(par,cmd): tk.Button(par,text=\"Browse\u2026\",font=FONTS[\"small\"],bg=C[\"btn_info\"],fg=C[\"text\"],bd=0,padx=8,pady=3,cursor=\"hand2\",command=cmd).pack(side=\"left\",padx=4)\n        def _action_btn(par,txt,cmd,color=None): tk.Button(par,text=txt,font=FONTS[\"body\"],bg=color or C[\"accent\"],fg=C[\"bg\"],bd=0,padx=14,pady=6,cursor=\"hand2\",command=cmd).pack(anchor=\"w\",pady=(8,2))\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # TAB 1 \u2014 Conversion\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        t1 = tk.Frame(content_host, bg=C[\"bg\"])\n        _xt_frames[\"conv\"] = t1\n\n        # Excel \u2192 CSV\n        b1a = _card(t1, \"\ud83d\udce4  Excel \u2192 CSV  (each sheet = one CSV)\")\n        r = _row(b1a); _lbl(r,\"XLSX:\"); v1a=tk.StringVar(); _entry(r,v1a).pack(side=\"left\",padx=4)\n        _browse_btn(r, lambda: v1a.set(filedialog.askopenfilename(filetypes=[(\"Excel\",\"*.xlsx *.xls\"),(\"All\",\"*.*\")])))\n        def _do_xl2csv():\n            src=v1a.get().strip()\n            if not src or not os.path.isfile(src): messagebox.showwarning(\"\",\"Valid XLSX select karo.\"); return\n            out_dir=filedialog.askdirectory(title=\"Output folder\")\n            if not out_dir: return\n            def _r():\n                try:\n                    if not _xpkg(\"openpyxl\"): return\n                    import openpyxl\n                    wb=openpyxl.load_workbook(src,data_only=True)\n                    saved=0\n                    for sh in wb.sheetnames:\n                        ws=wb[sh]\n                        out_path=os.path.join(out_dir,f\"{os.path.splitext(os.path.basename(src))[0]}_{sh}.csv\")\n                        with open(out_path,\"w\",newline=\"\",encoding=\"utf-8-sig\") as f:\n                            import csv as _csv\n                            w=_csv.writer(f)\n                            for row in ws.iter_rows(values_only=True): w.writerow([c if c is not None else \"\" for c in row])\n                        saved+=1\n                    xt_log(f\"\u2705 {saved} CSV files \u2192 {out_dir}\", C[\"success\"])\n                    self.after(0,lambda: messagebox.showinfo(\"Done!\",f\"\u2705 {saved} sheets exported!\\n{out_dir}\"))\n                except Exception as ex: xt_log(f\"\u274c {ex}\",C[\"error\"]); self.after(0,lambda: messagebox.showerror(\"Error\",str(ex)))\n            threading.Thread(target=_r,daemon=True).start()\n        _action_btn(b1a,\"\u25b6 Excel \u2192 CSV\",_do_xl2csv)\n\n        # CSV \u2192 Excel\n        b1b = _card(t1, \"\ud83d\udce5  CSV \u2192 Excel  (multiple CSVs \u2192 one XLSX, each = sheet)\")\n        r=_row(b1b); _lbl(r,\"CSVs:\"); v1b=tk.StringVar(); _entry(r,v1b,52).pack(side=\"left\",padx=4)\n        _browse_btn(r,lambda: v1b.set(\";\".join(filedialog.askopenfilenames(filetypes=[(\"CSV\",\"*.csv\"),(\"All\",\"*.*\")]))))\n        def _do_csv2xl():\n            files=[f.strip() for f in v1b.get().split(\";\") if f.strip()]\n            if not files: messagebox.showwarning(\"\",\"CSV select karo.\"); return\n            out=filedialog.asksaveasfilename(title=\"Output XLSX\",defaultextension=\".xlsx\",filetypes=[(\"Excel\",\"*.xlsx\")])\n            if not out: return\n            def _r():\n                try:\n                    if not _xpkg(\"openpyxl\"): return\n                    import openpyxl, csv as _csv\n                    wb=openpyxl.Workbook()\n                    wb.remove(wb.active)\n                    for f in files:\n                        sh_name=os.path.splitext(os.path.basename(f))[0][:31]\n                        ws=wb.create_sheet(title=sh_name)\n                        with open(f,newline=\"\",encoding=\"utf-8-sig\",errors=\"replace\") as fh:\n                            for row in _csv.reader(fh): ws.append(row)\n                    wb.save(out)\n                    xt_log(f\"\u2705 {len(files)} CSVs \u2192 {out}\",C[\"success\"])\n                    self.after(0,lambda: messagebox.showinfo(\"Done!\",f\"\u2705 Excel ready!\\n{out}\"))\n                except Exception as ex: xt_log(f\"\u274c {ex}\",C[\"error\"]); self.after(0,lambda: messagebox.showerror(\"Error\",str(ex)))\n            threading.Thread(target=_r,daemon=True).start()\n        _action_btn(b1b,\"\u25b6 CSV \u2192 Excel\",_do_csv2xl)\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # TAB 2 \u2014 Data Cleaning\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        t2 = tk.Frame(content_host, bg=C[\"bg\"])\n        _xt_frames[\"clean\"] = t2\n\n        # Duplicate row remover\n        b2a = _card(t2, \"\ud83e\uddf9  Duplicate Row Finder &amp; Remover\")\n        r=_row(b2a); _lbl(r,\"XLSX:\"); v2a=tk.StringVar(); _entry(r,v2a).pack(side=\"left\",padx=4)\n        _browse_btn(r,lambda: v2a.set(filedialog.askopenfilename(filetypes=[(\"Excel\",\"*.xlsx\"),(\"All\",\"*.*\")])))\n        r2=_row(b2a); _lbl(r2,\"Sheet name (blank=first):\"); v2a_sh=tk.StringVar(); _entry(r2,v2a_sh,16).pack(side=\"left\",padx=4)\n        _lbl(r2,\"  Key columns (e.g. A,B or blank=all):\"); v2a_col=tk.StringVar(); _entry(r2,v2a_col,14).pack(side=\"left\",padx=4)\n        self._xt_dup_mode = tk.StringVar(value=\"remove\")\n        r3=_row(b2a)\n        tk.Radiobutton(r3,text=\"Remove duplicates\",variable=self._xt_dup_mode,value=\"remove\",\n                       font=FONTS[\"small\"],bg=C[\"card\"],fg=C[\"text\"],selectcolor=C[\"bg\"],activebackground=C[\"card\"]).pack(side=\"left\",padx=6)\n        tk.Radiobutton(r3,text=\"Only mark/highlight\",variable=self._xt_dup_mode,value=\"mark\",\n                       font=FONTS[\"small\"],bg=C[\"card\"],fg=C[\"text\"],selectcolor=C[\"bg\"],activebackground=C[\"card\"]).pack(side=\"left\",padx=6)\n\n        def _do_dedup():\n            src=v2a.get().strip()\n            if not src or not os.path.isfile(src): messagebox.showwarning(\"\",\"Valid XLSX select karo.\"); return\n            out=filedialog.asksaveasfilename(title=\"Output XLSX\",defaultextension=\".xlsx\",filetypes=[(\"Excel\",\"*.xlsx\")])\n            if not out: return\n            def _r():\n                try:\n                    if not _xpkg(\"openpyxl\"): return\n                    import openpyxl\n                    from openpyxl.styles import PatternFill\n                    wb=openpyxl.load_workbook(src)\n                    sh_name=v2a_sh.get().strip() or wb.sheetnames[0]\n                    ws=wb[sh_name]\n                    data=list(ws.iter_rows(values_only=False))\n                    if not data: xt_log(\"\u26a0\ufe0f Sheet empty.\",C[\"warning\"]); return\n                    col_raw=v2a_col.get().strip()\n                    if col_raw:\n                        col_idxs=[ord(c.strip().upper())-65 for c in col_raw.split(\",\") if c.strip()]\n                    else:\n                        col_idxs=list(range(ws.max_column))\n                    seen=set(); dup_rows=[]; keep_rows=[]\n                    for i,row in enumerate(data):\n                        key=tuple((row[c].value if cmw:\n                                    img=img.resize((mw,int(img.height*mw/img.width)),Image.LANCZOS)\n                            base=os.path.splitext(os.path.basename(fp))[0]\n                            ext=\".jpg\" if fmt==\"JPEG\" else f\".{fmt.lower()}\"\n                            out_path=os.path.join(out_dir,f\"{base}{v1_suf.get()}{ext}\")\n                            save_kw={\"quality\":q} if fmt in (\"JPEG\",\"WEBP\") else {}\n                            img.convert(\"RGB\").save(out_path,fmt,**save_kw)\n                            done+=1\n                        except Exception as e: it_log(f\"\u26a0\ufe0f {fp}: {e}\",C[\"warning\"])\n                    it_log(f\"\u2705 {done}/{len(files)} images processed \u2192 {out_dir}\",C[\"success\"])\n                    self.after(0,lambda: messagebox.showinfo(\"Done!\",f\"\u2705 {done} images done!\\n{out_dir}\"))\n                except Exception as ex: it_log(f\"\u274c {ex}\",C[\"error\"]); self.after(0,lambda: messagebox.showerror(\"Error\",str(ex)))\n            threading.Thread(target=_r,daemon=True).start()\n        _abtn(b1,\"\u25b6 Resize &amp; Compress\",_do_resize)\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # TAB 2 \u2014 OCR\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        t2=tk.Frame(content_host,bg=C[\"bg\"]); _it_frames[\"ocr\"]=t2\n\n        b2=_card(t2,\"\ud83d\udcd6  OCR \u2014 Image / Screenshot \u2192 Text / Word / Excel\")\n        tk.Label(b2,text=\"\u26a0\ufe0f  Tesseract OCR pehle install karna hoga: https://github.com/UB-Mannheim/tesseract/wiki\",\n                 font=FONTS[\"small\"],fg=C[\"accent4\"],bg=C[\"card\"],cursor=\"hand2\").pack(anchor=\"w\",pady=(0,6))\n        r=_row(b2); _lbl(r,\"Images (multi-select):\"); v2_files=tk.StringVar(); _entry(r,v2_files,48)\n        _browse(r,lambda: v2_files.set(\";\".join(filedialog.askopenfilenames(\n            filetypes=[(\"Images\",\"*.jpg *.jpeg *.png *.bmp *.tiff *.webp\"),(\"All\",\"*.*\")]))))\n\n        r2=_row(b2)\n        _lbl(r2,\"Language:\"); v2_lang=tk.StringVar(value=\"eng+hin\")\n        for l in [(\"eng+hin\",\"Hindi+English\"),(\"eng\",\"English only\"),(\"hin\",\"Hindi only\")]:\n            tk.Radiobutton(r2,text=l[1],variable=v2_lang,value=l[0],font=FONTS[\"small\"],bg=C[\"card\"],fg=C[\"text\"],selectcolor=C[\"bg\"],activebackground=C[\"card\"]).pack(side=\"left\",padx=6)\n\n        r3=_row(b2); _lbl(r3,\"Output format:\"); v2_out=tk.StringVar(value=\"txt\")\n        for t,l in [(\"txt\",\"Plain Text\"),(\"docx\",\"Word DOCX\"),(\"xlsx\",\"Excel XLSX\")]:\n            tk.Radiobutton(r3,text=l,variable=v2_out,value=t,font=FONTS[\"small\"],bg=C[\"card\"],fg=C[\"text\"],selectcolor=C[\"bg\"],activebackground=C[\"card\"]).pack(side=\"left\",padx=6)\n\n        r4=_row(b2); _lbl(r4,\"Tesseract path (agar auto-detect fail ho):\"); v2_tess=tk.StringVar(value=r\"C:\\Program Files\\Tesseract-OCR\\tesseract.exe\")\n        _entry(r4,v2_tess,38)\n\n        def _do_ocr():\n            files=[f.strip() for f in v2_files.get().split(\";\") if f.strip()]\n            if not files: messagebox.showwarning(\"\",\"Images select karo.\"); return\n            out=filedialog.asksaveasfilename(title=\"Output file save\",\n                defaultextension=f\".{v2_out.get()}\",\n                filetypes=[(\"Output\",f\"*.{v2_out.get()}\"),(\"All\",\"*.*\")])\n            if not out: return\n            def _r():\n                try:\n                    if not _ipkg(\"PIL\",\"Pillow\"): return\n                    if not _ipkg(\"pytesseract\"): return\n                    import pytesseract\n                    from PIL import Image\n                    tp=v2_tess.get().strip()\n                    if tp and os.path.isfile(tp): pytesseract.pytesseract.tesseract_cmd=tp\n                    all_text=[]\n                    for fp in files:\n                        it_log(f\"  OCR: {os.path.basename(fp)}\u2026\",C[\"text_dim\"])\n                        img=Image.open(fp)\n                        txt=pytesseract.image_to_string(img,lang=v2_lang.get())\n                        all_text.append(f\"=== {os.path.basename(fp)} ===\\n{txt}\\n\")\n                    out_fmt=v2_out.get()\n                    if out_fmt==\"txt\":\n                        with open(out,\"w\",encoding=\"utf-8\") as f: f.write(\"\\n\".join(all_text))\n                    elif out_fmt==\"docx\":\n                        if not _ipkg(\"docx\",\"python-docx\"): return\n                        import docx\n                        doc=docx.Document()\n                        for block in all_text: doc.add_paragraph(block)\n                        doc.save(out)\n                    elif out_fmt==\"xlsx\":\n                        if not _ipkg(\"openpyxl\"): return\n                        import openpyxl\n                        wb=openpyxl.Workbook(); ws=wb.active; ws.title=\"OCR\"\n                        ws.append([\"Source File\",\"Extracted Text\"])\n                        for fp,txt in zip(files,all_text): ws.append([os.path.basename(fp),txt])\n                        wb.save(out)\n                    it_log(f\"\u2705 OCR done: {len(files)} files \u2192 {out}\",C[\"success\"])\n                    self.after(0,lambda: messagebox.showinfo(\"Done!\",f\"\u2705 OCR complete!\\n{out}\"))\n                except Exception as ex: it_log(f\"\u274c {ex}\\nTip: Tesseract install karo aur path sahi set karo.\",C[\"error\"]); self.after(0,lambda: messagebox.showerror(\"Error\",str(ex)))\n            threading.Thread(target=_r,daemon=True).start()\n        _abtn(b2,\"\u25b6 Run OCR\",_do_ocr)\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # TAB 3 \u2014 Background Remove\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        t3=tk.Frame(content_host,bg=C[\"bg\"]); _it_frames[\"bg\"]=t3\n\n        b3=_card(t3,\"\u2702  Background Remover  (rembg \u2014 AI-powered, first run ~100MB download)\")\n        tk.Label(b3,text=\"\u2139\ufe0f  First use mein model download hoga (~100 MB). Internet chahiye.\",\n                 font=FONTS[\"small\"],fg=C[\"accent4\"],bg=C[\"card\"]).pack(anchor=\"w\",pady=(0,6))\n        r=_row(b3); _lbl(r,\"Images:\"); v3_files=tk.StringVar(); _entry(r,v3_files,50)\n        _browse(r,lambda: v3_files.set(\";\".join(filedialog.askopenfilenames(\n            filetypes=[(\"Images\",\"*.jpg *.jpeg *.png *.webp *.bmp\"),(\"All\",\"*.*\")]))))\n        r2=_row(b3); _lbl(r2,\"Output suffix:\"); v3_suf=tk.StringVar(value=\"_nobg\"); _entry(r2,v3_suf,12)\n        _lbl(r2,\"  Output format (PNG recommended for transparency):\"); v3_fmt=tk.StringVar(value=\"PNG\")\n        for f in (\"PNG\",\"WEBP\"):\n            tk.Radiobutton(r2,text=f,variable=v3_fmt,value=f,font=FONTS[\"small\"],bg=C[\"card\"],fg=C[\"text\"],selectcolor=C[\"bg\"],activebackground=C[\"card\"]).pack(side=\"left\",padx=5)\n\n        def _do_bgrem():\n            files=[f.strip() for f in v3_files.get().split(\";\") if f.strip()]\n            if not files: messagebox.showwarning(\"\",\"Images select karo.\"); return\n            out_dir=filedialog.askdirectory(title=\"Output folder\")\n            if not out_dir: return\n            def _r():\n                try:\n                    if not _ipkg(\"rembg\"): return\n                    if not _ipkg(\"PIL\",\"Pillow\"): return\n                    from rembg import remove\n                    from PIL import Image\n                    import io\n                    done=0\n                    for fp in files:\n                        try:\n                            it_log(f\"  Processing: {os.path.basename(fp)}\u2026\",C[\"text_dim\"])\n                            with open(fp,\"rb\") as f: inp=f.read()\n                            out_bytes=remove(inp)\n                            base=os.path.splitext(os.path.basename(fp))[0]\n                            fmt=v3_fmt.get(); ext=\".png\" if fmt==\"PNG\" else \".webp\"\n                            out_path=os.path.join(out_dir,f\"{base}{v3_suf.get()}{ext}\")\n                            img=Image.open(io.BytesIO(out_bytes))\n                            img.save(out_path,fmt)\n                            done+=1\n                        except Exception as e: it_log(f\"\u26a0\ufe0f {os.path.basename(fp)}: {e}\",C[\"warning\"])\n                    it_log(f\"\u2705 Background removed: {done}/{len(files)} \u2192 {out_dir}\",C[\"success\"])\n                    self.after(0,lambda: messagebox.showinfo(\"Done!\",f\"\u2705 {done} images processed!\\n{out_dir}\"))\n                except Exception as ex: it_log(f\"\u274c {ex}\",C[\"error\"]); self.after(0,lambda: messagebox.showerror(\"Error\",str(ex)))\n            threading.Thread(target=_r,daemon=True).start()\n        _abtn(b3,\"\u25b6 Remove Background\",_do_bgrem)\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # TAB 4 \u2014 Crop (Images + PDF)\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        t4=tk.Frame(content_host,bg=C[\"bg\"]); _it_frames[\"crop\"]=t4\n\n        # Image crop\n        b4a=_card(t4,\"\u2702\ufe0f  Image Crop  (pixels \u2014 left, top, right, bottom)\")\n        r=_row(b4a); _lbl(r,\"Images:\"); v4a_files=tk.StringVar(); _entry(r,v4a_files,48)\n        _browse(r,lambda: v4a_files.set(\";\".join(filedialog.askopenfilenames(\n            filetypes=[(\"Images\",\"*.jpg *.jpeg *.png *.bmp *.tiff *.webp\"),(\"All\",\"*.*\")]))))\n        r2=_row(b4a)\n        _lbl(r2,\"Left:\"); v4a_l=tk.StringVar(value=\"0\"); _entry(r2,v4a_l,6)\n        _lbl(r2,\"Top:\"); v4a_t=tk.StringVar(value=\"0\"); _entry(r2,v4a_t,6)\n        _lbl(r2,\"Right:\"); v4a_r=tk.StringVar(value=\"800\"); _entry(r2,v4a_r,6)\n        _lbl(r2,\"Bottom:\"); v4a_b=tk.StringVar(value=\"600\"); _entry(r2,v4a_b,6)\n        # Suffix nahi \u2014 output folder alag hai, naam same rahega\n\n        def _do_img_crop():\n            files=[f.strip() for f in v4a_files.get().split(\";\") if f.strip()]\n            if not files: messagebox.showwarning(\"\",\"Images select karo.\"); return\n            out_dir=filedialog.askdirectory(title=\"Output folder\")\n            if not out_dir: return\n            def _r():\n                try:\n                    if not _ipkg(\"PIL\",\"Pillow\"): return\n                    from PIL import Image\n                    box=(int(v4a_l.get()),int(v4a_t.get()),int(v4a_r.get()),int(v4a_b.get()))\n                    done=0\n                    for fp in files:\n                        try:\n                            img=Image.open(fp)\n                            cropped=img.crop(box)\n                            base,ext=os.path.splitext(os.path.basename(fp))\n                            out_path=os.path.join(out_dir,f\"{base}{ext}\")  # same naam, alag folder\n                            cropped.save(out_path)\n                            done+=1\n                        except Exception as e: it_log(f\"\u26a0\ufe0f {os.path.basename(fp)}: {e}\",C[\"warning\"])\n                    it_log(f\"\u2705 Cropped {done}/{len(files)} images \u2192 {out_dir}\",C[\"success\"])\n                    self.after(0,lambda: messagebox.showinfo(\"Done!\",f\"\u2705 {done} images cropped!\\n{out_dir}\"))\n                except Exception as ex: it_log(f\"\u274c {ex}\",C[\"error\"]); self.after(0,lambda: messagebox.showerror(\"Error\",str(ex)))\n            threading.Thread(target=_r,daemon=True).start()\n        _abtn(b4a,\"\u25b6 Crop Images (pixel values)\",_do_img_crop)\n\n        # \u2500\u2500 Visual Mouse Crop for Images \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        def _do_visual_img_crop():\n            \"\"\"Mouse se drag karke image ka area select karo aur crop karo.\"\"\"\n            files=[f.strip() for f in v4a_files.get().split(\";\") if f.strip()]\n            if not files:\n                messagebox.showwarning(\"\",\"Pehle images select karo (upar wale entry mein).\")\n                return\n            if not _ipkg(\"PIL\",\"Pillow\"):\n                return\n            from PIL import Image as _PILImg, ImageTk as _ITk\n\n            # File index state\n            img_state = {\n                \"idx\": 0,\n                \"files\": files,\n                \"rect\": None,\n                \"drag_start\": None,\n                \"photo\": None,\n                \"scale\": 1.0,\n                \"orig_w\": 1, \"orig_h\": 1,\n                \"img_x\": 0, \"img_y\": 0,\n            }\n\n            iwin = tk.Toplevel(self)\n            iwin.title(\"\ud83d\uddb1  Visual Image Crop \u2014 Mouse se area select karo\")\n            iwin.geometry(\"980x700\")\n            iwin.configure(bg=C[\"bg\"])\n            iwin.grab_set()\n\n            # \u2500\u2500 Top controls \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            ictrl = tk.Frame(iwin, bg=C[\"panel\"])\n            ictrl.pack(fill=\"x\")\n            tk.Label(ictrl, text=\"Image:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"left\", padx=(10,4))\n            ifile_var = tk.StringVar(value=\"1\")\n            ifile_spin = tk.Spinbox(ictrl, from_=1, to=len(files), textvariable=ifile_var,\n                                    width=5, font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"],\n                                    buttonbackground=C[\"card\"])\n            ifile_spin.pack(side=\"left\", padx=4)\n            tk.Label(ictrl, text=f\"/ {len(files)}\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"left\")\n\n            iname_lbl = tk.Label(ictrl, text=\"\", font=FONTS[\"small\"], fg=C[\"accent4\"], bg=C[\"panel\"])\n            iname_lbl.pack(side=\"left\", padx=10)\n\n            icoord_lbl = tk.Label(ictrl, text=\"Selection: None\", font=FONTS[\"small\"],\n                                   fg=C[\"accent\"], bg=C[\"panel\"])\n            icoord_lbl.pack(side=\"left\", padx=16)\n\n            tk.Label(ictrl, text=\"\ud83d\uddb1 Drag to select crop area\", font=FONTS[\"small\"],\n                     fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"right\", padx=14)\n\n            # \u2500\u2500 Canvas \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            icf = tk.Frame(iwin, bg=C[\"bg\"])\n            icf.pack(fill=\"both\", expand=True, padx=8, pady=4)\n            icanvas = tk.Canvas(icf, bg=\"#1a1a2e\", cursor=\"crosshair\", highlightthickness=0)\n            icanvas.pack(fill=\"both\", expand=True)\n\n            def render_image(idx):\n                img_state[\"idx\"] = idx\n                img_state[\"rect\"] = None\n                icanvas.delete(\"all\")\n                fp = files[idx]\n                iname_lbl.config(text=os.path.basename(fp))\n                try:\n                    pil = _PILImg.open(fp)\n                    cw = icanvas.winfo_width() or 900\n                    ch = icanvas.winfo_height() or 560\n                    ow, oh = pil.size\n                    img_state[\"orig_w\"] = ow\n                    img_state[\"orig_h\"] = oh\n                    scale = min((cw-20)/ow, (ch-20)/oh, 1.0)\n                    img_state[\"scale\"] = scale\n                    disp = pil.resize((int(ow*scale), int(oh*scale)), _PILImg.LANCZOS)\n                    photo = _ITk.PhotoImage(disp)\n                    img_state[\"photo\"] = photo\n                    ix = (cw - int(ow*scale)) // 2\n                    iy = (ch - int(oh*scale)) // 2\n                    img_state[\"img_x\"] = ix\n                    img_state[\"img_y\"] = iy\n                    icanvas.create_image(ix, iy, anchor=\"nw\", image=photo, tags=\"img\")\n                    icanvas.create_rectangle(ix-1, iy-1, ix+int(ow*scale)+1, iy+int(oh*scale)+1,\n                                             outline=C[\"accent\"], width=1, tags=\"border\")\n                    icoord_lbl.config(text=\"Selection: None \u2014 drag karke area choose karo\")\n                except Exception as e:\n                    icoord_lbl.config(text=f\"Error loading image: {e}\")\n\n            irect_id = [None]\n\n            def ion_press(event):\n                img_state[\"drag_start\"] = (event.x, event.y)\n                img_state[\"rect\"] = None\n                if irect_id[0]:\n                    icanvas.delete(irect_id[0])\n                    irect_id[0] = None\n\n            def ion_drag(event):\n                if not img_state[\"drag_start\"]:\n                    return\n                x0,y0 = img_state[\"drag_start\"]\n                x1,y1 = event.x, event.y\n                if irect_id[0]:\n                    icanvas.delete(irect_id[0])\n                irect_id[0] = icanvas.create_rectangle(x0,y0,x1,y1,\n                    outline=\"#00FF88\", width=2, dash=(4,2), tags=\"isel\")\n                ix, iy = img_state[\"img_x\"], img_state[\"img_y\"]\n                sc = img_state[\"scale\"]\n                px0 = max(0, (min(x0,x1)-ix)/sc)\n                py0 = max(0, (min(y0,y1)-iy)/sc)\n                px1 = min(img_state[\"orig_w\"], (max(x0,x1)-ix)/sc)\n                py1 = min(img_state[\"orig_h\"], (max(y0,y1)-iy)/sc)\n                icoord_lbl.config(text=f\"Selection: ({px0:.0f},{py0:.0f}) \u2192 ({px1:.0f},{py1:.0f}) px  |  {px1-px0:.0f}\u00d7{py1-py0:.0f} px\")\n\n            def ion_release(event):\n                if not img_state[\"drag_start\"]:\n                    return\n                x0,y0 = img_state[\"drag_start\"]\n                x1,y1 = event.x, event.y\n                if abs(x1-x0)&lt;8 or abs(y1-y0)&lt;8:\n                    img_state[\"rect\"] = None\n                    icoord_lbl.config(text=\"Too small \u2014 thoda bada area select karo\")\n                    return\n                ix, iy = img_state[\"img_x\"], img_state[\"img_y\"]\n                sc = img_state[\"scale\"]\n                cx0,cy0 = min(x0,x1), min(y0,y1)\n                cx1,cy1 = max(x0,x1), max(y0,y1)\n                px0 = max(0, (cx0-ix)/sc)\n                py0 = max(0, (cy0-iy)/sc)\n                px1 = min(img_state[\"orig_w\"], (cx1-ix)/sc)\n                py1 = min(img_state[\"orig_h\"], (cy1-iy)/sc)\n                img_state[\"rect\"] = (int(px0), int(py0), int(px1), int(py1))\n                icoord_lbl.config(text=f\"\u2705 Selected: ({int(px0)},{int(py0)}) \u2192 ({int(px1)},{int(py1)}) px  |  Click 'Apply Crop'\")\n\n            icanvas.bind(\"\", ion_press)\n            icanvas.bind(\"\", ion_drag)\n            icanvas.bind(\"\", ion_release)\n\n            def igo_img(*_):\n                try:\n                    idx = int(ifile_var.get())-1\n                    idx = max(0, min(idx, len(files)-1))\n                    render_image(idx)\n                except Exception:\n                    pass\n            ifile_spin.config(command=igo_img)\n            ifile_spin.bind(\"\", igo_img)\n            icanvas.bind(\"\", lambda e: self.after(100, lambda: render_image(img_state[\"idx\"])))\n\n            # \u2500\u2500 Bottom buttons \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            ibtn_row = tk.Frame(iwin, bg=C[\"panel\"])\n            ibtn_row.pack(fill=\"x\", pady=4)\n\n            def apply_img_visual_crop():\n                if not img_state[\"rect\"]:\n                    messagebox.showwarning(\"\", \"Pehle mouse se area select karo.\")\n                    return\n                out_dir = filedialog.askdirectory(title=\"Cropped images save karne ke liye folder\")\n                if not out_dir:\n                    return\n                box = img_state[\"rect\"]\n                crop_all = crop_all_var.get()\n                target_idxs = list(range(len(files))) if crop_all else [img_state[\"idx\"]]\n                def _icrop_run():\n                    try:\n                        done = 0\n                        for idx in target_idxs:\n                            fp = files[idx]\n                            try:\n                                pil = _PILImg.open(fp)\n                                # Clamp box to actual image size\n                                ow, oh = pil.size\n                                safe_box = (\n                                    max(0, box[0]), max(0, box[1]),\n                                    min(ow, box[2]), min(oh, box[3])\n                                )\n                                cropped = pil.crop(safe_box)\n                                base, ext = os.path.splitext(os.path.basename(fp))\n                                suf = v4a_suf.get()\n                                out_path = os.path.join(out_dir, f\"{base}{ext}\")  # same naam, alag folder\n                                cropped.save(out_path)\n                                done += 1\n                            except Exception as e:\n                                it_log(f\"\u26a0\ufe0f {os.path.basename(fp)}: {e}\", C[\"warning\"])\n                        it_log(f\"\u2705 Visual crop: {done}/{len(target_idxs)} images \u2192 {out_dir}\", C[\"success\"])\n                        self.after(0, lambda: messagebox.showinfo(\"Done!\", f\"\u2705 {done} images cropped!\\n{out_dir}\"))\n                        self.after(0, iwin.destroy)\n                    except Exception as ex:\n                        it_log(f\"\u274c {ex}\", C[\"error\"])\n                        self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n                threading.Thread(target=_icrop_run, daemon=True).start()\n\n            crop_all_var = tk.BooleanVar(value=False)\n            tk.Checkbutton(ibtn_row, text=\"Sab images pe same crop apply karo\",\n                           variable=crop_all_var, font=FONTS[\"small\"],\n                           bg=C[\"panel\"], fg=C[\"text\"], selectcolor=C[\"bg\"],\n                           activebackground=C[\"panel\"]).pack(side=\"left\", padx=12, pady=6)\n\n            def ireset_sel():\n                img_state[\"rect\"] = None\n                if irect_id[0]:\n                    icanvas.delete(irect_id[0])\n                    irect_id[0] = None\n                icoord_lbl.config(text=\"Selection: Reset \u2014 dobara drag karo\")\n\n            tk.Button(ibtn_row, text=\"\u2705 Apply Crop\", font=FONTS[\"body\"],\n                      bg=C[\"success\"], fg=C[\"bg\"], bd=0, padx=20, pady=8,\n                      cursor=\"hand2\", command=apply_img_visual_crop).pack(side=\"left\", padx=8, pady=6)\n            tk.Button(ibtn_row, text=\"\ud83d\udd04 Reset\", font=FONTS[\"body\"],\n                      bg=C[\"btn_warn\"], fg=C[\"text\"], bd=0, padx=12, pady=8,\n                      cursor=\"hand2\", command=ireset_sel).pack(side=\"left\", padx=4)\n            tk.Button(ibtn_row, text=\"\u25c0 Prev\", font=FONTS[\"body\"],\n                      bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=10, pady=8,\n                      cursor=\"hand2\",\n                      command=lambda: (ifile_var.set(max(1, int(ifile_var.get())-1)), igo_img())).pack(side=\"left\", padx=4)\n            tk.Button(ibtn_row, text=\"Next \u25b6\", font=FONTS[\"body\"],\n                      bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=10, pady=8,\n                      cursor=\"hand2\",\n                      command=lambda: (ifile_var.set(min(len(files), int(ifile_var.get())+1)), igo_img())).pack(side=\"left\", padx=4)\n            tk.Button(ibtn_row, text=\"\u274c Cancel\", font=FONTS[\"body\"],\n                      bg=C[\"btn_danger\"], fg=C[\"text\"], bd=0, padx=12, pady=8,\n                      cursor=\"hand2\", command=iwin.destroy).pack(side=\"right\", padx=12)\n\n            iwin.update_idletasks()\n            self.after(150, lambda: render_image(0))\n\n        _abtn(b4a, \"\ud83d\uddb1  Visual Mouse Crop \u2014 Image (interactive)\", _do_visual_img_crop)\n\n        # PDF crop (page margins) + Visual Mouse Crop\n        b4b=_card(t4,\"\u2702\ufe0f  PDF Page Crop  (trim margins mm se  OR  mouse se visually select karo)\")\n        r=_row(b4b); _lbl(r,\"PDF:\"); v4b_pdf=tk.StringVar(); _entry(r,v4b_pdf,46)\n        _browse(r,lambda: v4b_pdf.set(filedialog.askopenfilename(filetypes=[(\"PDF\",\"*.pdf\"),(\"All\",\"*.*\")])))\n        r2=_row(b4b)\n        _lbl(r2,\"Left mm:\"); v4b_l=tk.StringVar(value=\"10\"); _entry(r2,v4b_l,5)\n        _lbl(r2,\"Bottom mm:\"); v4b_bot=tk.StringVar(value=\"10\"); _entry(r2,v4b_bot,5)\n        _lbl(r2,\"Right mm:\"); v4b_rr=tk.StringVar(value=\"10\"); _entry(r2,v4b_rr,5)\n        _lbl(r2,\"Top mm:\"); v4b_top=tk.StringVar(value=\"10\"); _entry(r2,v4b_top,5)\n        _lbl(r2,\"  Pages (blank=all):\"); v4b_pg=tk.StringVar(value=\"\"); _entry(r2,v4b_pg,10)\n\n        def _do_pdf_crop():\n            src=v4b_pdf.get().strip()\n            if not src or not os.path.isfile(src): messagebox.showwarning(\"\",\"Valid PDF select karo.\"); return\n            # Original PDF naam se default naam suggest karo\n            src_base=os.path.splitext(os.path.basename(src))[0]\n            out=filedialog.asksaveasfilename(title=\"Cropped PDF\",defaultextension=\".pdf\",\n                                             initialfile=src_base,\n                                             filetypes=[(\"PDF\",\"*.pdf\")])\n            if not out: return\n            def _r():\n                try:\n                    if not _ipkg(\"pikepdf\"): return\n                    import pikepdf\n                    # 1 mm \u2248 2.8346 PDF points\n                    mm2pt=lambda mm: float(mm)*2.8346\n                    l=mm2pt(v4b_l.get()); b=mm2pt(v4b_bot.get())\n                    rr=mm2pt(v4b_rr.get()); t=mm2pt(v4b_top.get())\n                    pages_raw=v4b_pg.get().strip()\n                    def _pk(v): return pikepdf.Real(round(v,4))\n                    with pikepdf.open(src) as pdf:\n                        total=len(pdf.pages)\n                        if pages_raw:\n                            idxs=set()\n                            for p in pages_raw.split(\",\"):\n                                p=p.strip()\n                                if \"-\" in p:\n                                    a,bb=p.split(\"-\"); [idxs.add(i) for i in range(int(a)-1,int(bb))]\n                                else:\n                                    try: idxs.add(int(p)-1)\n                                    except: pass\n                        else:\n                            idxs=set(range(total))\n                        for i,page in enumerate(pdf.pages):\n                            if i not in idxs: continue\n                            mb=page.mediabox\n                            x0,y0,x1,y1=float(mb[0]),float(mb[1]),float(mb[2]),float(mb[3])\n                            page.cropbox=pikepdf.Array([_pk(x0+l),_pk(y0+b),_pk(x1-rr),_pk(y1-t)])\n                        pdf.save(out)\n                    it_log(f\"\u2705 PDF cropped ({len(idxs)} pages) \u2192 {out}\",C[\"success\"])\n                    self.after(0,lambda: messagebox.showinfo(\"Done!\",f\"\u2705 PDF cropped!\\n{out}\"))\n                except Exception as ex: it_log(f\"\u274c {ex}\",C[\"error\"]); self.after(0,lambda: messagebox.showerror(\"Error\",str(ex)))\n            threading.Thread(target=_r,daemon=True).start()\n        _abtn(b4b,\"\u25b6 Crop PDF (mm margins)\",_do_pdf_crop)\n\n        # \u2500\u2500 Visual Mouse Crop \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        def _do_visual_pdf_crop():\n            \"\"\"Mouse se drag karke PDF page ka area select karo aur crop karo.\"\"\"\n            src = v4b_pdf.get().strip()\n            if not src or not os.path.isfile(src):\n                messagebox.showwarning(\"\", \"Pehle PDF select karo.\")\n                return\n            # Ensure dependencies\n            fitz_ok = _ipkg(\"fitz\", \"PyMuPDF\")\n            if not fitz_ok:\n                messagebox.showerror(\"Error\", \"PyMuPDF local package missing hai. Offline bundle/wheel se install karein.\")\n                return\n            import fitz\n            doc = fitz.open(src)\n            total_pages = len(doc)\n            if total_pages == 0:\n                messagebox.showerror(\"Error\", \"PDF mein koi page nahi hai.\")\n                doc.close()\n                return\n\n            # \u2500\u2500 Visual Crop Window \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            crop_win = tk.Toplevel(self)\n            crop_win.title(\"\ud83d\uddb1  Visual PDF Crop \u2014 Mouse se area select karo\")\n            crop_win.geometry(\"950x720\")\n            crop_win.configure(bg=C[\"bg\"])\n            crop_win.grab_set()\n\n            # State\n            state = {\n                \"page_idx\": 0,\n                \"rect\": None,       # (x1,y1,x2,y2) in canvas coords\n                \"drag_start\": None,\n                \"photo\": None,\n                \"scale\": 1.0,\n                \"page_w\": 1, \"page_h\": 1,\n                \"canvas_w\": 780, \"canvas_h\": 540,\n            }\n\n            # \u2500\u2500 Top controls \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            ctrl = tk.Frame(crop_win, bg=C[\"panel\"])\n            ctrl.pack(fill=\"x\", pady=0)\n            tk.Label(ctrl, text=\"Page:\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"left\", padx=(10,4))\n            page_var = tk.StringVar(value=\"1\")\n            page_spin = tk.Spinbox(ctrl, from_=1, to=total_pages, textvariable=page_var,\n                                   width=5, font=FONTS[\"body\"], bg=C[\"bg\"], fg=C[\"text\"],\n                                   buttonbackground=C[\"card\"])\n            page_spin.pack(side=\"left\", padx=4)\n            tk.Label(ctrl, text=f\"/ {total_pages}\", font=FONTS[\"small\"], fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"left\")\n\n            apply_all_var = tk.BooleanVar(value=False)\n            tk.Checkbutton(ctrl, text=\"Sab pages pe apply karo\", variable=apply_all_var,\n                           font=FONTS[\"small\"], bg=C[\"panel\"], fg=C[\"text\"],\n                           selectcolor=C[\"bg\"], activebackground=C[\"panel\"]).pack(side=\"left\", padx=16)\n\n            coord_lbl = tk.Label(ctrl, text=\"Selection: None\", font=FONTS[\"small\"],\n                                 fg=C[\"accent\"], bg=C[\"panel\"])\n            coord_lbl.pack(side=\"left\", padx=10)\n\n            tk.Label(ctrl, text=\"\ud83d\uddb1 Drag to select crop area\", font=FONTS[\"small\"],\n                     fg=C[\"text_dim\"], bg=C[\"panel\"]).pack(side=\"right\", padx=14)\n\n            # \u2500\u2500 Canvas \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            canvas_frame = tk.Frame(crop_win, bg=C[\"bg\"])\n            canvas_frame.pack(fill=\"both\", expand=True, padx=8, pady=4)\n            canvas = tk.Canvas(canvas_frame, bg=\"#1a1a2e\", cursor=\"crosshair\",\n                                highlightthickness=0)\n            canvas.pack(fill=\"both\", expand=True)\n\n            def render_page(page_idx):\n                \"\"\"Render a PDF page onto the canvas.\"\"\"\n                state[\"page_idx\"] = page_idx\n                state[\"rect\"] = None\n                canvas.delete(\"all\")\n                page = doc[page_idx]\n                cw = canvas.winfo_width() or 780\n                ch = canvas.winfo_height() or 540\n                state[\"canvas_w\"] = cw\n                state[\"canvas_h\"] = ch\n                pw = page.rect.width\n                ph = page.rect.height\n                state[\"page_w\"] = pw\n                state[\"page_h\"] = ph\n                # Scale to fit canvas with padding\n                scale = min((cw - 20) / pw, (ch - 20) / ph)\n                state[\"scale\"] = scale\n                mat = fitz.Matrix(scale, scale)\n                pix = page.get_pixmap(matrix=mat)\n                import io as _io\n                from PIL import Image as _PILImg, ImageTk as _ITk\n                pil = _PILImg.open(_io.BytesIO(pix.tobytes(\"ppm\")))\n                photo = _ITk.PhotoImage(pil)\n                state[\"photo\"] = photo  # keep reference\n                state[\"img_x\"] = (cw - pix.width)  // 2\n                state[\"img_y\"] = (ch - pix.height) // 2\n                canvas.create_image(state[\"img_x\"], state[\"img_y\"], anchor=\"nw\", image=photo, tags=\"page\")\n                # Border\n                canvas.create_rectangle(\n                    state[\"img_x\"]-1, state[\"img_y\"]-1,\n                    state[\"img_x\"]+pix.width+1, state[\"img_y\"]+pix.height+1,\n                    outline=C[\"accent\"], width=1, tags=\"border\")\n                coord_lbl.config(text=\"Selection: None \u2014 drag karke area choose karo\")\n\n            # \u2500\u2500 Mouse drag for selection \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            rect_id = [None]\n\n            def on_press(event):\n                state[\"drag_start\"] = (event.x, event.y)\n                state[\"rect\"] = None\n                if rect_id[0]:\n                    canvas.delete(rect_id[0])\n                    rect_id[0] = None\n\n            def on_drag(event):\n                if not state[\"drag_start\"]:\n                    return\n                x0, y0 = state[\"drag_start\"]\n                x1, y1 = event.x, event.y\n                if rect_id[0]:\n                    canvas.delete(rect_id[0])\n                rect_id[0] = canvas.create_rectangle(\n                    x0, y0, x1, y1,\n                    outline=\"#00FF88\", width=2, dash=(4,2), tags=\"sel\")\n                # Show size hint\n                ix, iy = state[\"img_x\"], state[\"img_y\"]\n                sc = state[\"scale\"]\n                # Clamp to page\n                px0 = max(0, (min(x0,x1) - ix) / sc)\n                py0 = max(0, (min(y0,y1) - iy) / sc)\n                px1 = min(state[\"page_w\"], (max(x0,x1) - ix) / sc)\n                py1 = min(state[\"page_h\"], (max(y0,y1) - iy) / sc)\n                coord_lbl.config(text=f\"Selection: ({px0:.0f},{py0:.0f}) \u2192 ({px1:.0f},{py1:.0f}) pt  |  {px1-px0:.0f}\u00d7{py1-py0:.0f} pt\")\n\n            def on_release(event):\n                if not state[\"drag_start\"]:\n                    return\n                x0, y0 = state[\"drag_start\"]\n                x1, y1 = event.x, event.y\n                if abs(x1-x0) &lt; 10 or abs(y1-y0) &lt; 10:\n                    state[\"rect\"] = None\n                    coord_lbl.config(text=\"Too small \u2014 thoda bada area select karo\")\n                    return\n                # Convert canvas coords \u2192 PDF points\n                ix, iy = state[\"img_x\"], state[\"img_y\"]\n                sc = state[\"scale\"]\n                pw, ph = state[\"page_w\"], state[\"page_h\"]\n                # PDF origin is bottom-left, canvas top-left\n                cx0, cy0 = min(x0,x1), min(y0,y1)\n                cx1, cy1 = max(x0,x1), max(y0,y1)\n                # Clamp\n                pdf_x0 = max(0.0, (cx0 - ix) / sc)\n                pdf_y0_top = max(0.0, (cy0 - iy) / sc)  # distance from top\n                pdf_x1 = min(pw, (cx1 - ix) / sc)\n                pdf_y1_top = min(ph, (cy1 - iy) / sc)\n                # Convert to PDF coords (y flipped): pdf_y = ph - canvas_y\n                pdf_y1 = ph - pdf_y0_top   # top of selection in PDF coords\n                pdf_y0 = ph - pdf_y1_top   # bottom of selection in PDF coords\n                state[\"rect\"] = (pdf_x0, pdf_y0, pdf_x1, pdf_y1)\n                coord_lbl.config(text=f\"\u2705 Selected: ({pdf_x0:.0f},{pdf_y0:.0f}) \u2192 ({pdf_x1:.0f},{pdf_y1:.0f}) pt  |  Click 'Apply Crop'\")\n\n            canvas.bind(\"\", on_press)\n            canvas.bind(\"\", on_drag)\n            canvas.bind(\"\", on_release)\n\n            def go_page(*_):\n                try:\n                    idx = int(page_var.get()) - 1\n                    idx = max(0, min(idx, total_pages-1))\n                    render_page(idx)\n                except Exception:\n                    pass\n            page_spin.config(command=go_page)\n            page_spin.bind(\"\", go_page)\n\n            # Render on canvas resize\n            def on_resize(event):\n                render_page(state[\"page_idx\"])\n            canvas.bind(\"\", lambda e: self.after(100, lambda: render_page(state[\"page_idx\"])))\n\n            # \u2500\u2500 Bottom buttons \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            btn_row = tk.Frame(crop_win, bg=C[\"panel\"])\n            btn_row.pack(fill=\"x\", pady=4)\n\n            def apply_visual_crop():\n                if not state[\"rect\"]:\n                    messagebox.showwarning(\"\", \"Pehle mouse se area select karo.\")\n                    return\n                src_base = os.path.splitext(os.path.basename(src))[0]\n                out = filedialog.asksaveasfilename(\n                    title=\"Cropped PDF save karein\",\n                    defaultextension=\".pdf\",\n                    initialfile=src_base,\n                    filetypes=[(\"PDF\", \"*.pdf\")])\n                if not out:\n                    return\n                crop_box = state[\"rect\"]   # (x0, y0, x1, y1) in PDF points\n                apply_all = apply_all_var.get()\n                target_pages = list(range(total_pages)) if apply_all else [state[\"page_idx\"]]\n                def _crop_run():\n                    try:\n                        if not _ipkg(\"pikepdf\"): return\n                        import pikepdf\n                        def _pkv(v): return pikepdf.Real(round(v,4))\n                        with pikepdf.open(src) as pdf:\n                            for pidx in range(len(pdf.pages)):\n                                if pidx not in target_pages:\n                                    continue\n                                page = pdf.pages[pidx]\n                                mb = page.mediabox\n                                page.cropbox = pikepdf.Array([\n                                    _pkv(crop_box[0]),\n                                    _pkv(crop_box[1]),\n                                    _pkv(crop_box[2]),\n                                    _pkv(crop_box[3]),\n                                ])\n                            pdf.save(out)\n                        it_log(f\"\u2705 Visual crop applied ({len(target_pages)} pages) \u2192 {out}\", C[\"success\"])\n                        self.after(0, lambda: messagebox.showinfo(\"Done!\",\n                            f\"\u2705 PDF visually cropped!\\n{out}\"))\n                        self.after(0, crop_win.destroy)\n                    except Exception as ex:\n                        it_log(f\"\u274c Visual crop error: {ex}\", C[\"error\"])\n                        self.after(0, lambda: messagebox.showerror(\"Error\", str(ex)))\n                threading.Thread(target=_crop_run, daemon=True).start()\n\n            def reset_selection():\n                state[\"rect\"] = None\n                if rect_id[0]:\n                    canvas.delete(rect_id[0])\n                    rect_id[0] = None\n                coord_lbl.config(text=\"Selection: Reset \u2014 dobara drag karo\")\n\n            tk.Button(btn_row, text=\"\u2705 Apply Crop\", font=FONTS[\"body\"],\n                      bg=C[\"success\"], fg=C[\"bg\"], bd=0, padx=20, pady=8,\n                      cursor=\"hand2\", command=apply_visual_crop).pack(side=\"left\", padx=12, pady=6)\n            tk.Button(btn_row, text=\"\ud83d\udd04 Reset Selection\", font=FONTS[\"body\"],\n                      bg=C[\"btn_warn\"], fg=C[\"text\"], bd=0, padx=14, pady=8,\n                      cursor=\"hand2\", command=reset_selection).pack(side=\"left\", padx=6)\n            tk.Button(btn_row, text=\"\u25c0 Prev Page\", font=FONTS[\"body\"],\n                      bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=12, pady=8,\n                      cursor=\"hand2\",\n                      command=lambda: (page_var.set(max(1, int(page_var.get())-1)), go_page())).pack(side=\"left\", padx=4)\n            tk.Button(btn_row, text=\"Next Page \u25b6\", font=FONTS[\"body\"],\n                      bg=C[\"btn_info\"], fg=C[\"text\"], bd=0, padx=12, pady=8,\n                      cursor=\"hand2\",\n                      command=lambda: (page_var.set(min(total_pages, int(page_var.get())+1)), go_page())).pack(side=\"left\", padx=4)\n            tk.Button(btn_row, text=\"\u274c Cancel\", font=FONTS[\"body\"],\n                      bg=C[\"btn_danger\"], fg=C[\"text\"], bd=0, padx=12, pady=8,\n                      cursor=\"hand2\",\n                      command=lambda: (doc.close(), crop_win.destroy())).pack(side=\"right\", padx=12)\n\n            # Initial render after window shows\n            crop_win.update_idletasks()\n            self.after(150, lambda: render_page(0))\n\n        _abtn(b4b, \"\ud83d\uddb1  Visual Mouse Crop (interactive)\", _do_visual_pdf_crop)\n\n        _it_switch(\"resize\")\n        return frame\n\n\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    # FILE MANAGER TOOLS SECTION\n    # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n    def _build_file_tools(self, parent):\n        \"\"\"\n        File Manager Tools:\n          Tab 1 \u2014 Bulk Rename         (counter, date, prefix/suffix, regex)\n          Tab 2 \u2014 Duplicate Finder    (MD5/SHA256 content-based)\n        \"\"\"\n        import threading, hashlib\n\n        frame = tk.Frame(parent, bg=C[\"bg\"])\n\n        hdr=tk.Frame(frame,bg=C[\"panel\"]); hdr.pack(fill=\"x\")\n        tk.Label(hdr,text=\"  \ud83d\uddc2 File Manager Tools\",font=FONTS[\"heading\"],fg=C[\"accent\"],bg=C[\"panel\"]).pack(side=\"left\",pady=10,padx=8)\n        tk.Label(hdr,text=\"Bulk Rename \u00b7 Duplicate Finder  |  No extra installs needed\",\n                 font=FONTS[\"small\"],fg=C[\"text_dim\"],bg=C[\"panel\"]).pack(side=\"left\",pady=10)\n\n        tab_bar=tk.Frame(frame,bg=C[\"card\"]); tab_bar.pack(fill=\"x\")\n        tk.Frame(tab_bar,bg=C[\"border\"],height=1).pack(side=\"bottom\",fill=\"x\")\n        content_host=tk.Frame(frame,bg=C[\"bg\"]); content_host.pack(fill=\"both\",expand=True)\n\n        _ft_frames={}; _ft_btns={}\n        def _ft_switch(key):\n            for k,b in _ft_btns.items():\n                b.config(bg=C[\"accent\"] if k==key else C[\"panel\"],\n                         fg=C[\"bg\"]     if k==key else C[\"text\"])\n            for k,f in _ft_frames.items():\n                f.pack(fill=\"both\",expand=True) if k==key else f.pack_forget()\n\n        for key,label in [(\"rename\",\"\u270f  Bulk Rename\"),(\"dupfind\",\"\ud83d\udd0d  Duplicate Finder\")]:\n            b=tk.Button(tab_bar,text=label,font=FONTS[\"body\"],bg=C[\"panel\"],fg=C[\"text\"],\n                        bd=0,padx=18,pady=8,cursor=\"hand2\",command=lambda k=key: _ft_switch(k))\n            b.pack(side=\"left\"); _ft_btns[key]=b\n\n        log_host=tk.Frame(frame,bg=C[\"card\"]); log_host.pack(fill=\"x\",side=\"bottom\")\n        tk.Label(log_host,text=\"  Activity Log\",font=FONTS[\"small\"],fg=C[\"accent\"],bg=C[\"card\"]).pack(anchor=\"w\",padx=8,pady=(5,0))\n        _ft_log_w=scrolledtext.ScrolledText(log_host,height=4,state=\"disabled\",bg=C[\"bg\"],fg=C[\"text\"],font=FONTS[\"small\"],bd=0)\n        _ft_log_w.pack(fill=\"x\",padx=8,pady=(2,6))\n\n        def ft_log(msg,color=None):\n            ts=datetime.datetime.now().strftime(\"%H:%M:%S\")\n            _ft_log_w.config(state=\"normal\")\n            tag=f\"t{abs(hash(color or ''))}\"\n            _ft_log_w.tag_config(tag,foreground=color or C[\"text\"])\n            _ft_log_w.insert(\"end\",f\"[{ts}] {msg}\\n\",tag)\n            _ft_log_w.see(\"end\"); _ft_log_w.config(state=\"disabled\")\n\n        def _card(par,title):\n            c=tk.Frame(par,bg=C[\"card\"]); c.pack(fill=\"x\",padx=16,pady=10)\n            tk.Label(c,text=title,font=FONTS[\"subhead\"],fg=C[\"accent\"],bg=C[\"card\"]).pack(anchor=\"w\",padx=10,pady=(8,4))\n            tk.Frame(c,bg=C[\"border\"],height=1).pack(fill=\"x\",padx=10)\n            b=tk.Frame(c,bg=C[\"card\"]); b.pack(fill=\"x\",padx=10,pady=10); return b\n\n        def _row(par): r=tk.Frame(par,bg=C[\"card\"]); r.pack(fill=\"x\",pady=3); return r\n        def _lbl(par,txt): tk.Label(par,text=txt,font=FONTS[\"small\"],fg=C[\"text_dim\"],bg=C[\"card\"]).pack(side=\"left\",padx=(0,4))\n        def _entry(par,var,w=44): e=tk.Entry(par,textvariable=var,font=FONTS[\"small\"],bg=C[\"bg\"],fg=C[\"text\"],insertbackground=C[\"text\"],width=w); e.pack(side=\"left\",padx=4); return e\n        def _browse(par,cmd): tk.Button(par,text=\"Browse\u2026\",font=FONTS[\"small\"],bg=C[\"btn_info\"],fg=C[\"text\"],bd=0,padx=8,pady=3,cursor=\"hand2\",command=cmd).pack(side=\"left\",padx=4)\n        def _abtn(par,txt,cmd,color=None): tk.Button(par,text=txt,font=FONTS[\"body\"],bg=color or C[\"accent\"],fg=C[\"bg\"],bd=0,padx=14,pady=6,cursor=\"hand2\",command=cmd).pack(anchor=\"w\",pady=(8,2))\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # TAB 1 \u2014 Bulk Rename\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        t1=tk.Frame(content_host,bg=C[\"bg\"]); _ft_frames[\"rename\"]=t1\n\n        b1=_card(t1,\"\u270f\ufe0f  Bulk File Rename\")\n        r=_row(b1); _lbl(r,\"Folder:\"); v1_dir=tk.StringVar(); _entry(r,v1_dir,48)\n        _browse(r,lambda: v1_dir.set(filedialog.askdirectory(title=\"Folder select karo\")))\n        r2=_row(b1); _lbl(r2,\"Filter extension (e.g. .jpg or blank=all):\"); v1_ext=tk.StringVar(value=\"\"); _entry(r2,v1_ext,8)\n\n        # Pattern options\n        opt_frame=tk.LabelFrame(b1,text=\"  Rename Pattern  (all options combine karein)\",\n                                 font=FONTS[\"small\"],fg=C[\"accent\"],bg=C[\"card\"],bd=1,relief=\"groove\")\n        opt_frame.pack(fill=\"x\",pady=6)\n        or1=tk.Frame(opt_frame,bg=C[\"card\"]); or1.pack(fill=\"x\",padx=8,pady=4)\n        _lbl(or1,\"Prefix:\"); v1_pre=tk.StringVar(); _entry(or1,v1_pre,12)\n        _lbl(or1,\"  Suffix (before ext):\"); v1_suf=tk.StringVar(); _entry(or1,v1_suf,12)\n        or2=tk.Frame(opt_frame,bg=C[\"card\"]); or2.pack(fill=\"x\",padx=8,pady=4)\n        v1_counter=tk.BooleanVar(value=True)\n        tk.Checkbutton(or2,text=\"Add counter\",variable=v1_counter,font=FONTS[\"small\"],bg=C[\"card\"],fg=C[\"text\"],selectcolor=C[\"bg\"],activebackground=C[\"card\"]).pack(side=\"left\")\n        _lbl(or2,\"  Start:\"); v1_start=tk.StringVar(value=\"1\"); _entry(or2,v1_start,5)\n        _lbl(or2,\"  Padding (digits):\"); v1_pad=tk.StringVar(value=\"3\"); _entry(or2,v1_pad,4)\n        or3=tk.Frame(opt_frame,bg=C[\"card\"]); or3.pack(fill=\"x\",padx=8,pady=4)\n        v1_date=tk.BooleanVar(value=False)\n        tk.Checkbutton(or3,text=\"Add date\",variable=v1_date,font=FONTS[\"small\"],bg=C[\"card\"],fg=C[\"text\"],selectcolor=C[\"bg\"],activebackground=C[\"card\"]).pack(side=\"left\")\n        _lbl(or3,\"  Date source:\"); v1_datesrc=tk.StringVar(value=\"today\")\n        tk.Radiobutton(or3,text=\"Today\",variable=v1_datesrc,value=\"today\",font=FONTS[\"small\"],bg=C[\"card\"],fg=C[\"text\"],selectcolor=C[\"bg\"],activebackground=C[\"card\"]).pack(side=\"left\",padx=4)\n        tk.Radiobutton(or3,text=\"File modified date\",variable=v1_datesrc,value=\"mtime\",font=FONTS[\"small\"],bg=C[\"card\"],fg=C[\"text\"],selectcolor=C[\"bg\"],activebackground=C[\"card\"]).pack(side=\"left\",padx=4)\n        or4=tk.Frame(opt_frame,bg=C[\"card\"]); or4.pack(fill=\"x\",padx=8,pady=4)\n        v1_replace=tk.BooleanVar(value=False)\n        tk.Checkbutton(or4,text=\"Find &amp; Replace in name:\",variable=v1_replace,font=FONTS[\"small\"],bg=C[\"card\"],fg=C[\"text\"],selectcolor=C[\"bg\"],activebackground=C[\"card\"]).pack(side=\"left\")\n        _lbl(or4,\"Find:\"); v1_find=tk.StringVar(); _entry(or4,v1_find,14)\n        _lbl(or4,\"Replace:\"); v1_rep=tk.StringVar(); _entry(or4,v1_rep,14)\n\n        # Preview\n        prev_lbl=tk.Label(b1,text=\"Preview: (click 'Preview' to see)\",\n                           font=FONTS[\"small\"],fg=C[\"text_dim\"],bg=C[\"card\"],anchor=\"w\")\n        prev_lbl.pack(fill=\"x\",pady=(4,0))\n        prev_box=scrolledtext.ScrolledText(b1,height=5,state=\"disabled\",bg=C[\"bg\"],fg=C[\"text\"],font=FONTS[\"small\"],bd=0)\n        prev_box.pack(fill=\"x\",pady=4)\n\n        def _build_new_name(orig_name, idx, folder):\n            base,ext=os.path.splitext(orig_name)\n            filt=v1_ext.get().strip()\n            if filt and ext.lower()!=filt.lower(): return None  # skip\n            name=base\n            if v1_replace.get():\n                name=name.replace(v1_find.get(),v1_rep.get())\n            date_str=\"\"\n            if v1_date.get():\n                if v1_datesrc.get()==\"today\":\n                    date_str=datetime.datetime.now().strftime(\"%Y%m%d\")\n                else:\n                    try:\n                        mtime=os.path.getmtime(os.path.join(folder,orig_name))\n                        date_str=datetime.datetime.fromtimestamp(mtime).strftime(\"%Y%m%d\")\n                    except: date_str=\"\"\n            ctr_str=\"\"\n            if v1_counter.get():\n                try: start=int(v1_start.get()); pad=int(v1_pad.get())\n                except: start=1; pad=3\n                ctr_str=str(start+idx).zfill(pad)\n            new=v1_pre.get()+date_str+ctr_str+name+v1_suf.get()\n            return new+ext\n\n        def _do_preview():\n            folder=v1_dir.get().strip()\n            if not folder or not os.path.isdir(folder): messagebox.showwarning(\"\",\"Valid folder select karo.\"); return\n            files=sorted(os.listdir(folder))\n            lines=[]; idx=0\n            for f in files:\n                if not os.path.isfile(os.path.join(folder,f)): continue\n                nn=_build_new_name(f,idx,folder)\n                if nn:\n                    lines.append(f\"  {f}  \u2192  {nn}\"); idx+=1\n            prev_box.config(state=\"normal\"); prev_box.delete(\"1.0\",\"end\")\n            prev_box.insert(\"end\",\"\\n\".join(lines) if lines else \"No files match.\"); prev_box.config(state=\"disabled\")\n\n        def _do_rename():\n            folder=v1_dir.get().strip()\n            if not folder or not os.path.isdir(folder): messagebox.showwarning(\"\",\"Valid folder select karo.\"); return\n            if not messagebox.askyesno(\"Confirm Rename\",\"Files rename honge. Undo possible nahi. Proceed?\"): return\n            def _r():\n                files=sorted(os.listdir(folder))\n                done=0; idx=0\n                for f in files:\n                    if not os.path.isfile(os.path.join(folder,f)): continue\n                    nn=_build_new_name(f,idx,folder)\n                    if nn and nn!=f:\n                        try:\n                            os.rename(os.path.join(folder,f),os.path.join(folder,nn))\n                            done+=1\n                        except Exception as e: ft_log(f\"\u26a0\ufe0f {f}: {e}\",C[\"warning\"])\n                    idx+=1\n                ft_log(f\"\u2705 {done} files renamed in {folder}\",C[\"success\"])\n                self.after(0,lambda: messagebox.showinfo(\"Done!\",f\"\u2705 {done} files renamed!\"))\n            threading.Thread(target=_r,daemon=True).start()\n\n        br=_row(b1)\n        tk.Button(br,text=\"\ud83d\udc41 Preview\",font=FONTS[\"body\"],bg=C[\"btn_info\"],fg=C[\"text\"],bd=0,padx=12,pady=6,cursor=\"hand2\",command=_do_preview).pack(side=\"left\",padx=(0,8))\n        tk.Button(br,text=\"\u25b6 Rename Files\",font=FONTS[\"body\"],bg=C[\"accent\"],fg=C[\"bg\"],bd=0,padx=14,pady=6,cursor=\"hand2\",command=_do_rename).pack(side=\"left\")\n\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        # TAB 2 \u2014 Duplicate Finder\n        # \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n        t2=tk.Frame(content_host,bg=C[\"bg\"]); _ft_frames[\"dupfind\"]=t2\n\n        b2=_card(t2,\"\ud83d\udd0d  Duplicate File Finder  (MD5 / SHA256 content-based)\")\n        r=_row(b2); _lbl(r,\"Folder to scan:\"); v2_dir=tk.StringVar(); _entry(r,v2_dir,46)\n        _browse(r,lambda: v2_dir.set(filedialog.askdirectory(title=\"Folder select karo\")))\n        r2=_row(b2)\n        v2_sub=tk.BooleanVar(value=True)\n        tk.Checkbutton(r2,text=\"Include subfolders\",variable=v2_sub,font=FONTS[\"small\"],bg=C[\"card\"],fg=C[\"text\"],selectcolor=C[\"bg\"],activebackground=C[\"card\"]).pack(side=\"left\",padx=4)\n        _lbl(r2,\"  Hash:\"); v2_hash=tk.StringVar(value=\"md5\")\n        tk.Radiobutton(r2,text=\"MD5 (fast)\",variable=v2_hash,value=\"md5\",font=FONTS[\"small\"],bg=C[\"card\"],fg=C[\"text\"],selectcolor=C[\"bg\"],activebackground=C[\"card\"]).pack(side=\"left\",padx=4)\n        tk.Radiobutton(r2,text=\"SHA256 (accurate)\",variable=v2_hash,value=\"sha256\",font=FONTS[\"small\"],bg=C[\"card\"],fg=C[\"text\"],selectcolor=C[\"bg\"],activebackground=C[\"card\"]).pack(side=\"left\",padx=4)\n        _lbl(r2,\"  Min size (KB):\"); v2_min=tk.StringVar(value=\"1\"); _entry(r2,v2_min,6)\n        _lbl(r2,\"  Extension filter (blank=all):\"); v2_ext=tk.StringVar(); _entry(r2,v2_ext,8)\n\n        # Results tree\n        dup_cols=(\"File\",\"Size\",\"Hash\",\"Group\")\n        dup_tree=ttk.Treeview(b2,columns=dup_cols,show=\"headings\",height=10,style=\"Custom.Treeview\")\n        for col,w in zip(dup_cols,[380,80,120,60]):\n            dup_tree.heading(col,text=col); dup_tree.column(col,width=w,anchor=\"w\")\n        dup_sb=ttk.Scrollbar(b2,orient=\"vertical\",command=dup_tree.yview)\n        dup_tree.configure(yscrollcommand=dup_sb.set)\n        dup_tree.pack(side=\"left\",fill=\"both\",expand=True,pady=6)\n        dup_sb.pack(side=\"right\",fill=\"y\",pady=6)\n\n        dup_stat=tk.Label(b2,text=\"\",font=FONTS[\"small\"],fg=C[\"text_dim\"],bg=C[\"card\"]); dup_stat.pack(anchor=\"w\")\n\n        def _file_hash(path, algo):\n            h=hashlib.md5() if algo==\"md5\" else hashlib.sha256()\n            try:\n                with open(path,\"rb\") as f:\n                    for chunk in iter(lambda: f.read(65536),b\"\"): h.update(chunk)\n                return h.hexdigest()\n            except Exception: return None\n\n        def _do_scan_dups():\n            folder=v2_dir.get().strip()\n            if not folder or not os.path.isdir(folder): messagebox.showwarning(\"\",\"Valid folder select karo.\"); return\n            def _r():\n                try:\n                    ft_log(\"\ud83d\udd0d Scanning for duplicates\u2026\",C[\"accent4\"])\n                    algo=v2_hash.get(); sub=v2_sub.get()\n                    try: min_bytes=int(v2_min.get())*1024\n                    except: min_bytes=1024\n                    ext_filter=v2_ext.get().strip().lower()\n                    all_files=[]\n                    if sub:\n                        for root_d,dirs,files in os.walk(folder):\n                            for f in files:\n                                fp=os.path.join(root_d,f)\n                                if ext_filter and not f.lower().endswith(ext_filter): continue\n                                try:\n                                    if os.path.getsize(fp)&gt;=min_bytes: all_files.append(fp)\n                                except: pass\n                    else:\n                        for f in os.listdir(folder):\n                            fp=os.path.join(folder,f)\n                            if not os.path.isfile(fp): continue\n                            if ext_filter and not f.lower().endswith(ext_filter): continue\n                            try:\n                                if os.path.getsize(fp)&gt;=min_bytes: all_files.append(fp)\n                            except: pass\n                    ft_log(f\"  {len(all_files)} files found, hashing\u2026\",C[\"text_dim\"])\n                    hashes={}\n                    for fp in all_files:\n                        h=_file_hash(fp,algo)\n                        if h:\n                            hashes.setdefault(h,[]).append(fp)\n                    dups={h:paths for h,paths in hashes.items() if len(paths)&gt;1}\n                    # Update tree\n                    self.after(0,lambda: dup_tree.delete(*dup_tree.get_children()))\n                    grp=0\n                    for h,paths in dups.items():\n                        grp+=1\n                        for p in paths:\n                            try: sz=_human_size(os.path.getsize(p))\n                            except: sz=\"?\"\n                            self.after(0,lambda p=p,sz=sz,h=h,g=grp: dup_tree.insert(\"\",\"end\",values=(p,sz,h[:12]+\"\u2026\",f\"#{g}\")))\n                    total_dup_files=sum(len(v) for v in dups.values())\n                    stat_msg=f\"\u2705 Found {len(dups)} duplicate groups, {total_dup_files} files\"\n                    self.after(0,lambda: dup_stat.config(text=stat_msg))\n                    ft_log(stat_msg,C[\"success\"] if dups else C[\"text_dim\"])\n                except Exception as ex: ft_log(f\"\u274c {ex}\",C[\"error\"]); self.after(0,lambda: messagebox.showerror(\"Error\",str(ex)))\n            threading.Thread(target=_r,daemon=True).start()\n\n        def _del_selected_dups():\n            sel=dup_tree.selection()\n            if not sel: messagebox.showwarning(\"\",\"Tree mein files select karo.\"); return\n            paths=[dup_tree.item(s)[\"values\"][0] for s in sel]\n            if not messagebox.askyesno(\"Delete?\",f\"{len(paths)} files permanently delete honge?\\n\\nUNDO POSSIBLE NAHI!\\n\\n\"+\"\\n\".join(paths[:10])): return\n            deleted=0\n            for p in paths:\n                try: os.remove(p); deleted+=1\n                except Exception as e: ft_log(f\"\u26a0\ufe0f {p}: {e}\",C[\"warning\"])\n            [dup_tree.delete(s) for s in sel]\n            ft_log(f\"\u2705 {deleted}/{len(paths)} duplicate files deleted.\",C[\"success\"])\n            messagebox.showinfo(\"Done!\",f\"\u2705 {deleted} files deleted.\")\n\n        def _export_dup_report():\n            out=filedialog.asksaveasfilename(title=\"Save Report\",defaultextension=\".csv\",filetypes=[(\"CSV\",\"*.csv\")])\n            if not out: return\n            import csv\n            rows=[dup_tree.item(r)[\"values\"] for r in dup_tree.get_children()]\n            with open(out,\"w\",newline=\"\",encoding=\"utf-8-sig\") as f:\n                w=csv.writer(f); w.writerow(dup_cols); w.writerows(rows)\n            ft_log(f\"\u2705 Report saved: {out}\",C[\"success\"])\n            messagebox.showinfo(\"Done!\",f\"\u2705 Report saved!\\n{out}\")\n\n        br=_row(b2)\n        tk.Button(br,text=\"\u25b6 Scan for Duplicates\",font=FONTS[\"body\"],bg=C[\"accent\"],fg=C[\"bg\"],bd=0,padx=14,pady=6,cursor=\"hand2\",command=_do_scan_dups).pack(side=\"left\",padx=(0,8))\n        tk.Button(br,text=\"\ud83d\uddd1 Delete Selected\",font=FONTS[\"body\"],bg=C[\"error\"],fg=C[\"text\"],bd=0,padx=12,pady=6,cursor=\"hand2\",command=_del_selected_dups).pack(side=\"left\",padx=(0,8))\n        tk.Button(br,text=\"\ud83d\udce5 Export CSV Report\",font=FONTS[\"body\"],bg=C[\"btn_info\"],fg=C[\"text\"],bd=0,padx=12,pady=6,cursor=\"hand2\",command=_export_dup_report).pack(side=\"left\")\n\n        _ft_switch(\"rename\")\n        return frame\n\n# ---------- RUN ----------\nif __name__ == \"__main__\":\n    # Windows + tkinter + psutil already verified at top\n    try:\n        # The maintenance UI needs elevation for printer, disk and recovery actions.\n        if not is_admin() and _admin_elevation_enabled():\n            run_as_admin()\n            sys.exit(0)\n        app = GodawariUltimateOptimizer()\n        app.mainloop()\n    except Exception as e:\n        import traceback\n        err = traceback.format_exc()\n        try:\n            messagebox.showerror(\"Startup Error \u2014 Godawari Optimizer\",\n                f\"App start nahi ho saki:\\n\\n{err[-600:]}\")\n        except:\n            print(\"STARTUP ERROR:\\n\", err)\n            input(\"Press Enter...\")\n", "creation_timestamp": "2026-05-29T17:17:10.000000Z"}]}