
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ClawOS</title>
    <link rel="stylesheet" href="/static/lib/highlight-default.min.css">
    <link rel="stylesheet" href="/static/lib/xterm.css" />
    <script src="/static/lib/highlight.min.js"></script>
    <script src="/static/lib/xlsx.full.min.js"></script>
    <script src="/static/js/clipboard.min.js"></script>
    <script src="/static/lib/xterm.js"></script>
    <script src="/static/lib/xterm-addon-fit.js"></script>
    <script src="/static/lib/socket.io.min.js"></script>
    <script src="/static/lib/vue.global.prod.js"></script>
    <link rel="stylesheet" href="/static/css/style.css">
    <link rel="stylesheet" href="/static/lib/sweetalert2.min.css">
    <script src="/static/lib/sweetalert2.min.js"></script>
    <script src="/static/lib/echarts.min.js"></script>
    <script src="/static/js/i18n.js"></script>
    <!-- 全局函数预加载（必须在最前） -->
    <script src="/static/js/globals.js"></script>
    <script src="/static/js/file_clipboard.js"></script>
    <script src="/static/js/task_poller.js"></script>
    <script src="/static/js/task_actions.js"></script>
    <script>window.SERVER_IS_WINDOWS = false;</script>
    <!-- 功能模块 -->
    <script src="/static/js/terminal.js"></script>
    <script src="/static/js/preview.js"></script>
    <script src="/static/js/bot.js"></script>
    <script src="/static/js/file_browser.js"></script>
    <script src="/static/js/git.js"></script>
    <script src="/static/js/smallmenu.js"></script>
    <script src="/static/js/system_monitor.js"></script>

    <!-- SweetAlert2 -->
    </head>
<style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        body {
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
            line-height: 1.5;
            color: #24292f;
            background-color: #ffffff;
            padding: 20px;
        }
        :root {
            --global-font-size: var(--global-font-size, 14px);
        }
        .container {
            max-width: 980px;
            margin: 0 auto;
            border: 1px solid #d0d7de;
            border-radius: 6px;
            overflow: hidden;
            display: flex;
            flex-direction: column;
            height: calc(100vh - 60px);
        }
        
        /* 顶部栏 (面包屑) */
        .breadcrumb {
            padding: 8px 12px;
            background-color: #f6f8fa;
            border-bottom: 1px solid #d0d7de;
            font-size: var(--global-font-size, 14px);
            display: flex;
            align-items: center;
            justify-content: space-between;
            position: sticky;
            top: 0;
            z-index: 100;
            gap: 8px;
        }
        .breadcrumb-btn-group {
            display: flex;
            align-items: center;
            gap: 2px;
            flex-shrink: 0;
        }
        .crumb-btn {
            width: 22px;
            height: 22px;
            display: flex;
            align-items: center;
            justify-content: center;
            border-radius: 4px;
            cursor: pointer;
            font-size: 13px;
            transition: all 0.2s;
            text-decoration: none;
        }
        .crumb-btn:hover {
            background: #e8ebee;
        }
        .crumb-btn[data-i18n-title="breadcrumb.create"] {
            background: #2da44e;
            color: white;
            font-weight: bold;
            font-size: 16px;
        }
        .crumb-btn[data-i18n-title="breadcrumb.create"]:hover {
            background: #2c974b;
        }
        .crumb-btn[data-i18n-title="breadcrumb.trash"] {
            color: #dc3545;
        }
        .breadcrumb-fixed a {
            color: #0969da;
            text-decoration: none;
        }
        .breadcrumb-fixed a:hover {
            text-decoration: underline;
        }
        .breadcrumb-fixed a[data-i18n-title="breadcrumb.trash"] {
            color: #dc3545;
        }
        .breadcrumb-left {
            display: flex;
            align-items: center;
            gap: 2px;
            overflow-x: auto;
            overflow-y: hidden;
            flex: 1;
            scroll-behavior: smooth;
            white-space: nowrap;
            min-width: 0;
        }
        /* 隐藏滚动条但保持滚动功能 */
        .breadcrumb-left::-webkit-scrollbar {
            height: 0;
        }
        .breadcrumb-left::-webkit-scrollbar-thumb {
            background: transparent;
        }
        .breadcrumb-left::-webkit-scrollbar-track {
            background: transparent;
        }
        .crumb-name {
            display: flex;
            align-items: center;
            gap: 4px;
            color: #24292f;
        }
        .crumb-count {
            color: #57606a;
            font-size: 12px;
        }
        .breadcrumb-left a {
            color: #0969da;
            text-decoration: none;
            flex-shrink: 0;
        }
        .breadcrumb-left a:hover {
            text-decoration: underline;
        }
        .crumb-sep {
            color: #57606a;
            flex-shrink: 0;
            margin: 0 2px;
        }
        .breadcrumb-right {
            display: flex;
            align-items: center;
            justify-content: flex-end;
            gap: 16px;
            margin-left: auto;
        }

        /* Git状态栏 */
        .git-status-bar {
            display: none;  /* 默认隐藏，由JS控制显示 */
            align-items: center;
            justify-content: space-between;
            padding: 10px 16px;
            margin: 0;
            background: #f6f8fa;
            border-radius: 0;
            cursor: pointer;
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
            font-size: 13px;
            transition: background-color 0.2s ease;
            border: 0;
            border-bottom: 1px solid #d0d7de;
        }
        .git-status-bar:hover {
            background: #eef2f6;
        }
        .git-status-content {
            display: flex;
            align-items: center;
            gap: 8px;
        }
        .git-icon {
            font-size: 16px;
        }
        .git-branch {
            font-weight: 600;
            color: #24292f;
            font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
        }
        .git-status-indicator {
            font-size: 12px;
            margin-left: 4px;
        }
        .git-status-indicator.clean {
            color: #2da44e;
        }
        .git-status-indicator.dirty {
            color: #cf222e;
        }
        .git-stats {
            display: flex;
            gap: 6px;
            margin-left: 8px;
        }
        .git-stat {
            padding: 2px 8px;
            border-radius: 6px;
            font-size: 12px;
            font-weight: 500;
            font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
        }
        .git-stat-added {
            background: rgba(9, 105, 218, 0.10);
            color: #0969da;
            border: 1px solid rgba(9, 105, 218, 0.35);
        }
        .git-stat-modified {
            background: rgba(154, 103, 0, 0.10);
            color: #9a6700;
            border: 1px solid rgba(154, 103, 0, 0.35);
        }
        .git-stat-deleted {
            background: rgba(207, 34, 46, 0.10);
            color: #cf222e;
            border: 1px solid rgba(207, 34, 46, 0.35);
        }
        .git-stat-untracked {
            background: rgba(87, 96, 106, 0.08);
            color: #57606a;
            border: 1px solid rgba(87, 96, 106, 0.25);
        }
        .git-action-btn {
            padding: 4px 10px;
            border-radius: 999px;
            opacity: 0.75;
            transition: opacity 0.2s, background-color 0.2s;
            border: 1px solid rgba(27, 31, 36, 0.15);
            background: rgba(255, 255, 255, 0.6);
        }
        .git-action-btn:hover {
            background: rgba(255, 255, 255, 0.95);
            opacity: 1;
        }
        .git-status-bar:hover .git-action-btn {
            opacity: 1;
        }

        /* 消息提示 */
        .message {
            padding: 10px 16px;
            border-bottom: 1px solid #d0d7de;
            font-size: var(--global-font-size, 14px);
        }
        .success { background-color: #dafbe1; color: #1a7f37; }
        .error { background-color: #ffebe9; color: #cf222e; }

        /* 文件浏览器顶部状态栏 */
        .file-status-bar {
            height: 24px;
            background: linear-gradient(180deg, #1a1a2e 0%, #16213e 100%);
            display: flex;
            align-items: center;
            padding: 0 6px;
            gap: 4px;
            font-size: 10px;
            font-family: 'SF Mono', 'Consolas', 'Monaco', monospace;
            color: #fff;
            white-space: nowrap;
            overflow-x: auto;
        }
        .file-status-item {
            display: flex;
            align-items: center;
            gap: 2px;
        }
        .file-status-item .icon { font-size: 10px; }
        .file-status-item .value { font-weight: 500; font-size: 10px; }
        .file-status-item .unit { color: #8b949e; font-size: 9px; }
        .file-status-item .divider { color: #484f58; margin: 0 2px; }
        .file-status-item .danger { color: #f85149; }
        .file-status-item .warning { color: #d29922; }
        .file-status-item .normal { color: #3fb950; }
        
        /* 文件列表区域 */
        .files-section {
            padding: 0;
            flex: 1;
            overflow-y: auto;
            overflow-x: hidden;
        }
        .file-list {
            display: flex;
            flex-direction: column;
        }
        .file-item {
            display: flex;
            align-items: center;
            padding: 8px 16px;
            border-bottom: 1px solid #d0d7de;
            background-color: white;
            transition: background-color 0.2s;
        }
        .file-item:last-child {
            border-bottom: none;
        }
        .file-item:hover {
            background-color: #f6f8fa;
        }

        /* 三列布局 */
        .file-col-icon {
            width: 32px;
            margin-right: 12px;
            flex-shrink: 0;
            display: flex;
            align-items: center;
            justify-content: center;
        }
        .file-thumbnail {
            width: 32px;
            height: 32px;
            object-fit: cover;
            border-radius: 4px;
            border: 1px solid #d0d7de;
        }
        .file-icon {
            font-size: 20px;
            color: #57606a;
        }

        .file-col-info {
            flex: 1;
            min-width: 0;
            display: flex;
            flex-direction: column;
            justify-content: center;
        }
        .file-name {
            font-size: var(--global-font-size, 14px);
            font-weight: 600;
            color: #24292f;
            line-height: 1.25;
            display: flex;
            align-items: center;
            gap: 8px;
        }
        .file-name.is-symlink {
            color: #58a6ff !important;  /* 亮蓝色 */
        }
        .file-name.is-broken-link {
            background: #000 !important;
            color: #ff4444 !important;
            padding: 2px 6px;
            border-radius: 4px;
        }
        .file-name.is-broken-link::before {
            content: '⚠ ';
        }
        .file-name a {
            color: #24292f;
            text-decoration: none;
        }
        .file-name a:hover {
            color: #0969da;
            text-decoration: underline;
        }
        .file-details-inline {
            font-size: var(--global-font-size, 12px);
            color: #57606a;
            margin-top: 2px;
        }

        .file-col-actions {
            margin-left: 16px;
            flex-shrink: 0;
            display: flex;
            align-items: center;
            gap: 4px;
        }
        .preview-btn {
            background: none;
            border: none;
            cursor: pointer;
            font-size: 16px;
            padding: 4px;
            border-radius: 4px;
            opacity: 0.7;
            transition: opacity 0.2s;
            text-decoration: none;
        }
        .preview-btn:hover {
            opacity: 1;
            background: #f0f0f0;
        }
        .menu-btn {
            background: none;
            color: #57606a;
            width: 28px;
            height: 28px;
            display: flex;
            align-items: center;
            justify-content: center;
            border-radius: 6px;
            font-size: var(--global-font-size, 16px);
            cursor: pointer;
            border: 1px solid transparent;
        }
        .menu-btn:hover {
            background-color: #f3f4f6;
            color: #24292f;
            border-color: #1b1f2426;
        }
        .breadcrumb-folder-menu-btn {
            width: 20px;
            height: 20px;
            font-size: var(--global-font-size, 14px);
            display: inline-flex;
            padding: 0;
            margin: 0 6px;
        }

        .empty-directory {
            text-align: center;
            padding: 40px;
            color: #57606a;
            font-size: var(--global-font-size, 14px);
        }

        /* 浮动上传按钮 (已移除) */
        
        /* 面包屑中的上传按钮 */
        .upload-btn-inline {
            width: 24px; height: 24px;
            background: #2da44e;
            border-radius: 4px;
            display: flex; align-items: center; justify-content: center;
            color: white; font-size: 18px; font-weight: bold;
            cursor: pointer;
            margin-right: 12px;
            box-shadow: 0 1px 3px rgba(0,0,0,0.1);
            transition: background 0.2s;
            flex-shrink: 0;
        }
        .upload-btn-inline:hover {
            background: #2c974b;
        }

        /* Bot 悬浮按钮 (已移除，改用菜单按钮) */
        
        /* 右侧抽屉样式 */
        .right-drawer {
            position: fixed;
            top: 0;
            right: 0;
            width: 196px;
            height: 100%;
            background: #fff;
            box-shadow: -4px 0 20px rgba(0,0,0,0.15);
            transform: translateX(100%);
            transition: transform 0.3s cubic-bezier(0.2, 0.8, 0.2, 1);
            z-index: 2000;
            display: flex;
            flex-direction: column;
        }
        .right-drawer.open {
            transform: translateX(0);
        }
        .right-drawer-backdrop {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0,0,0,0.4);
            opacity: 0;
            visibility: hidden;
            transition: opacity 0.3s, visibility 0.3s;
            z-index: 1999;
        }
        .right-drawer-backdrop.open {
            opacity: 1;
            visibility: visible;
        }
        .right-drawer-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 16px;
            border-bottom: 1px solid #eee;
        }
        .right-drawer-content {
            flex: 1;
            overflow-y: auto;
            padding: 8px;
        }
        .menu-item {
            display: flex;
            align-items: center;
            gap: 12px;
            padding: 14px 16px;
            border-radius: 8px;
            cursor: pointer;
            transition: background-color 0.2s;
            font-size: var(--global-font-size, 16px);
            color: #24292f;
        }
        .menu-item:hover {
            background-color: #f6f8fa;
        }
        .menu-icon {
            font-size: 20px;
        }
        .menu-text {
            font-weight: 500;
        }
        
        /* Bot Drawer 样式 - 使用统一 drawer 样式 */
        #botDrawer {
            max-height: 95vh;
        }
        
        /* 拖拽手柄 */
        .drawer-handle {
            width: 40px;
            height: 4px;
            background: #ccc;
            border-radius: 2px;
            margin: 12px auto 8px;
            cursor: grab;
        }
        .drawer-handle:active { cursor: grabbing; }
        
        /* Drawer Header */
        .drawer-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 8px 16px;
            border-bottom: 1px solid #eee;
        }
        .drawer-title { font-size: var(--global-font-size, 16px); font-weight: 600; }
        .drawer-close-btn {
            background: none; border: none; font-size: 20px; cursor: pointer; color: #666; padding: 4px;
        }
        
        /* 抽屉遮罩层 */
        .drawer-backdrop {
            position: fixed;
            left: 0;
            right: 0;
            top: 0;
            bottom: 0;
            background: rgba(0, 0, 0, 0.5);
            opacity: 0;
            visibility: hidden;
            transition: all 0.3s;
            z-index: 1999;
        }
        .drawer-backdrop.open {
            opacity: 1;
            visibility: visible;
        }

        #dialogBackdrop { z-index: 20040; }
        #dialogDrawer { z-index: 20041; }
        #previewBackdrop, #detailsBackdrop { z-index: 20020; }
        #previewModal, #detailsModal { z-index: 20021; }
        
        /* Terminal Drawer 样式 */
        #terminalDrawer {
            position: fixed;
            left: 0;
            right: 0;
            bottom: 0;
            background: #1a1a1a;
            border-radius: 16px 16px 0 0;
            transform: translateY(110%);
            transition: transform 0.3s cubic-bezier(0.2, 0.8, 0.2, 1), height 0.12s ease-out, max-height 0.12s ease-out, bottom 0.12s ease-out;
            z-index: 2000;
            display: flex;
            flex-direction: column;
            height: 95vh;
            max-height: 95vh;
            will-change: transform, height, bottom;
        }
        #terminalDrawer.kbd-open {
            transition: transform 0.3s cubic-bezier(0.2, 0.8, 0.2, 1);
        }
        #terminalDrawer.open {
            transform: translateY(0);
            box-shadow: 0 -4px 20px rgba(0,0,0,0.3);
        }
        #terminalDrawer .drawer-header {
            background: #1a1a1a;
            border-bottom: 1px solid #333;
        }
        #terminalDrawer .drawer-close-btn {
            color: #fff;
        }
        #terminalDrawer .drawer-handle {
            background: #555;
        }
        
        /* Bot Chat 样式 */
        .bot-container {
            display: flex;
            flex-direction: column;
            flex: 1;
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            position: relative;
            min-height: 0; /* 重要：防止溢出 */
        }
        .bot-chat-box {
            flex: 1;
            overflow-y: auto;
            padding: 15px;
            min-height: 0;
            width: 100%;
        }
        .bot-history {
            display: flex;
            flex-direction: column;
            gap: 12px;
            padding: 0;
            margin: 0;
        }
        .bot-msg {
            display: flex;
            align-items: flex-start;
            gap: 10px;
        }
        .bot-msg-user {
            flex-direction: row-reverse;
        }
        .bot-avatar {
            width: 28px;
            height: 28px;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 18px;
            flex-shrink: 0;
        }
        .bot-bubble {
            max-width: 85%;
            background: #ffffff;
            border: 1px solid #d0d7de;
            border-radius: 10px;
            padding: 8px 10px;
            box-shadow: 0 1px 2px rgba(0,0,0,0.05);
            min-width: 0;
        }
        .bot-msg-user .bot-bubble {
            background: #95ec69;
            border-color: transparent;
        }
        .bot-name {
            font-size: 12px;
            color: #57606a;
            margin-bottom: 6px;
            line-height: 1.2;
        }
        .bot-msg-user .bot-name {
            text-align: right;
        }
        .bot-text {
            font-size: var(--global-font-size, 14px);
            line-height: 1.5;
            word-break: break-word;
            white-space: pre-wrap;
            font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Noto Sans SC", "PingFang SC", "Microsoft YaHei", sans-serif;
        }
        .bot-message {
            display: flex;
            flex-direction: column;
            max-width: 85%;
            margin-bottom: 0;
        }
        .bot-message.user { align-self: flex-end; align-items: flex-end; }
        .bot-message.bot { align-self: flex-start; align-items: flex-start; }
        .bot-message.system { align-self: center; max-width: 90%; align-items: center; margin: 10px auto; }
        
        .bot-message .text {
            padding: 10px 14px;
            border-radius: 8px;
            font-size: var(--global-font-size, 14px);
            line-height: 1.5;
            word-break: break-word;
            white-space: pre-wrap; /* 保留换行 */
            font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Noto Sans SC", "PingFang SC", "Microsoft YaHei", sans-serif;
            box-shadow: 0 1px 2px rgba(0,0,0,0.05);
        }
        .bot-message.user .text { background: #95ec69; color: #000; }
        .bot-message.bot .text { background: #ffffff; color: #000; }
        .bot-message.system .text { 
            background: rgba(0,0,0,0.05); color: #666; font-size: var(--global-font-size, 12px); 
            padding: 4px 10px; border-radius: 4px; box-shadow: none; 
        }
        .bot-message .meta { font-size: 10px; color: #b2b2b2; margin-top: 4px; padding: 0 4px; }

        .bot-input-area {
            /* position: absolute; 改为正常流布局 */
            background: #fff;
            padding: 12px 16px;
            display: flex;
            gap: 8px;
            border-top: 1px solid #eee;
            align-items: flex-end;
            flex-shrink: 0;
        }
        .bot-input {
            flex: 1;
            border: none;
            background: #f5f5f5;
            padding: 8px 12px;
            border-radius: 12px;
            font-size: var(--global-font-size, 14px);
            max-height: 80px;
            resize: none;
            outline: none;
            height: 36px;
            font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Noto Sans SC", "PingFang SC", "Microsoft YaHei", sans-serif;
        }
        .bot-input:focus { background: #fff; box-shadow: 0 0 0 2px #95ec69; }
        .bot-send-btn {
            width: 36px; height: 36px;
            border-radius: 50%;
            background: #95ec69;
            color: white;
            border: none;
            display: flex; align-items: center; justify-content: center;
            cursor: pointer;
            font-size: var(--global-font-size, 16px);
            flex-shrink: 0;
        }
        
        /* Bot Settings Dialog */
        .bot-settings-overlay {
            position: absolute; top: 0; left: 0; right: 0; bottom: 0;
            background: rgba(255,255,255,0.98);
            z-index: 10;
            padding: 20px;
            display: none;
            flex-direction: column;
        }
        .bot-settings-btn {
            /* position: absolute; top: 10px; right: 50px; 改为正常 flex 布局 */
            background: none; border: none; font-size: 18px; cursor: pointer; color: #666;
            z-index: 5;
            padding: 4px 8px;
        }
        .bot-status-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; margin-right: 5px; }
        .bot-dot-connected { background: #07c160; }
        .bot-dot-disconnected { background: #fa5151; }
        .bot-dot-connecting { background: #ffc300; }

        /* Dialog 容器 (关键修复: 恢复隐藏状态) */
        .modal, .confirm-modal {
            display: none; /* 默认隐藏 */
            position: fixed;
            z-index: 2000;
            left: 0;
            top: 0;
            width: 100%;
            height: 100%;
            background-color: rgba(0,0,0,0.4);
            backdrop-filter: blur(2px);
        }

        /* Dialog 样式微调 (GitHub风) */
        .modal-content, .confirm-content {
            background-color: white;
            margin: 10% auto; /* 居中 */
            padding: 0;
            border-radius: 6px;
            border: 1px solid #d0d7de;
            box-shadow: 0 8px 24px rgba(140,149,159,0.2);
            width: 80%;
            max-width: 350px;
            overflow: hidden; /* 防止圆角溢出 */
        }
        .modal-header {
            background-color: #f6f8fa;
            border-bottom: 1px solid #d0d7de;
            padding: 12px 16px;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        .close-btn {
            background: none;
            border: none;
            font-size: 24px;
            cursor: pointer;
            color: #666;
            padding: 0;
            line-height: 1;
        }
        .close-btn:hover {
            color: #24292f;
        }
        .modal-body, .confirm-content > * {
            padding: 16px;
        }
        .confirm-content {
            padding: 0; /* 重置，由内部元素控制 padding */
        }
        .confirm-content h3 {
            margin: 0;
            padding: 16px;
            background-color: #f6f8fa;
            border-bottom: 1px solid #d0d7de;
            font-size: var(--global-font-size, 14px);
        }
        .confirm-content p {
            padding: 0 16px;
            margin: 16px 0;
        }
        .confirm-content input {
            display: block;
            width: calc(100% - 32px);
            margin: 0 16px 16px;
            padding: 5px 12px;
            border: 1px solid #d0d7de;
            border-radius: 6px;
        }
        .modal-buttons {
            padding: 16px;
            border-top: 1px solid #d0d7de;
            background-color: #f6f8fa;
            display: flex;
            justify-content: flex-end;
            gap: 8px;
            margin: 0;
        }

        /* 底部抽屉样式 */
        .bottom-sheet {
            position: fixed;
            bottom: 0;
            left: 50%;
            transform: translateX(-50%);
            width: 100%;
            max-width: 500px;
            background: #fff;
            border-radius: 16px 16px 0 0;
            box-shadow: 0 -4px 20px rgba(0,0,0,0.15);
            max-height: 70vh;
            display: flex;
            flex-direction: column;
            animation: slideUp 0.3s ease-out;
            z-index: 1002;
        }
        @keyframes slideUp {
            from { transform: translateX(-50%) translateY(100%); }
            to { transform: translateX(-50%) translateY(0); }
        }
        @keyframes slideDown {
            from { transform: translateX(-50%) translateY(0); }
            to { transform: translateX(-50%) translateY(100%); }
        }
        .bottom-sheet.closing {
            animation: slideDown 0.2s ease-in forwards;
        }
        .sheet-handle {
            width: 40px;
            height: 4px;
            background: #d0d7de;
            border-radius: 2px;
            margin: 12px auto 8px;
            cursor: grab;
        }
        .sheet-handle:active { cursor: grabbing; }
        .sheet-header {
            padding: 8px 16px 12px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            border-bottom: 1px solid #f0f0f0;
        }
        .sheet-close-btn {
            width: 32px;
            height: 32px;
            border-radius: 50%;
            background: #f0f0f0;
            border: none;
            color: #666;
            font-size: 20px;
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: center;
            transition: all 0.2s;
        }
        .sheet-close-btn:hover {
            background: #e0e0e0;
            color: #333;
        }
        .sheet-content {
            flex: 1;
            overflow-y: auto;
            padding-bottom: max(16px, env(safe-area-inset-bottom));
        }
        /* 遮罩层点击关闭 */
        .modal-close-on-backdrop { cursor: pointer; }

        .modal-title { font-size: var(--global-font-size, 14px); font-weight: 600; color: #24292f; }
        .modal-item { 
            padding: 10px 16px; 
            border-bottom: 1px solid #d0d7de; 
            cursor: pointer;
            font-size: var(--global-font-size, 14px);
            color: #24292f;
        }
        .modal-item:last-child { border-bottom: none; }
        .modal-item:hover { background-color: #0969da; color: white; }
        .modal-item.delete-item { color: #cf222e; }
        .modal-item.delete-item:hover { background-color: #cf222e; color: white; }
        .menu-share-btn {
            display: inline-flex;
            align-items: center;
            gap: 6px;
            padding: 6px 10px;
            border-radius: 999px;
            border: 1px solid #d0d7de;
            background: #ffffff;
            color: #24292f;
            font-size: 12px;
            cursor: pointer;
            flex-shrink: 0;
            transition: background-color 0.15s, border-color 0.15s, color 0.15s;
        }
        .modal-item:hover .menu-share-btn {
            background: rgba(255,255,255,0.18);
            border-color: rgba(255,255,255,0.55);
            color: #ffffff;
        }
        .menu-share-btn:hover {
            background: #f6f8fa;
        }

        /* 配置模态框 */
        #configModal .modal-content { width: 320px; }
        .config-section { padding: 20px; }
        .config-label { display: block; margin-bottom: 10px; font-weight: 500; }
        .font-size-slider { width: 100%; margin-bottom: 15px; }
        .font-preview { 
            padding: 15px; background: #f6f8fa; border-radius: 6px; text-align: center; 
            margin-bottom: 15px; font-size: var(--global-font-size, 14px); 
        }
        
        /* 配置卡片样式 */
        .config-card {
            background: #fff;
            border: 1px solid #e5e7eb;
            border-radius: 10px;
            padding: 14px;
            margin-bottom: 12px;
        }
        .config-card-title {
            font-size: 13px;
            font-weight: 600;
            color: #374151;
            margin-bottom: 12px;
            padding-bottom: 8px;
            border-bottom: 1px solid #f3f4f6;
        }
        .config-card-row {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 8px 0;
        }
        .config-card-row + .config-card-row {
            border-top: 1px solid #f3f4f6;
        }
        .config-card-label {
            font-size: 13px;
            color: #4b5563;
        }
        .config-card-btn {
            padding: 5px 12px;
            font-size: 12px;
            background: #f3f4f6;
            border: 1px solid #e5e7eb;
            border-radius: 6px;
            cursor: pointer;
            color: #374151;
            transition: all 0.2s;
        }
        .config-card-btn:hover {
            background: #e5e7eb;
        }
        .config-card-btn-danger {
            background: #fef2f2;
            border-color: #fecaca;
            color: #dc2626;
        }
        .config-card-btn-danger:hover {
            background: #fee2e2;
        }

        /* 移动端适配 */
        @media (max-width: 768px) {
            body { padding: 0; }
            .container { border: none; border-radius: 0; }
            .file-item { padding: 12px 16px; }
            .file-col-icon { width: 40px; margin-right: 12px; }
            .file-thumbnail { width: 40px; height: 40px; }
            .file-icon { font-size: 24px; }
            .file-name { font-size: 15px; }
            .breadcrumb { padding: 12px 16px; }
        }
    </style>
    <input type="hidden" id="currentBrowsePath" value="">
    <input type="hidden" id="currentBrowseName" value="">
    <input type="hidden" id="rootDir" value="">
    <script>
        window.__INITIAL_PIN_DIR__ = '';
        window.__INITIAL_PINS__ = [];
        window.__INITIAL_GIT_STATUS__ = null;
    </script>

    <!-- SweetAlert2 -->
</head>
<body>
    <div id="taskListenerBar" class="task-listener-bar" role="status" aria-live="polite" aria-hidden="true" style="display:none;">
        <div class="task-spinner" aria-hidden="true"></div>
        <div id="taskListenerText" class="task-listener-text" data-i18n="task.listening">Listening for task status…</div>
    </div>
    <div class="container" id="browseApp">
        <!-- 文件浏览器顶部状态栏 -->
        <div class="file-status-bar" id="fileStatusBar">
            <div class="file-status-item">
                <span class="value" id="statusUser">-</span>
            </div>
            <div class="file-status-item">
                <span class="icon">🖥️</span>
                <span class="value" id="statusCpu">-</span>
            </div>
            <div class="file-status-item">
                <span class="icon">💾</span>
                <span class="value" id="statusMemory">-</span>
            </div>
            <div class="file-status-item">
                <span class="icon">💿</span>
                <span class="value" id="statusDisk">-</span>
            </div>
            <div class="file-status-item">
                <span class="icon">🎮</span>
                <span class="value" id="statusGpu">-</span>
            </div>
            <div class="file-status-item">
                <span class="icon">📦</span>
                <span class="value" id="statusVram">-</span>
            </div>
            <div class="file-status-item">
                <span class="icon">⚡</span>
                <span class="value" id="statusPower">-</span>
            </div>
            <div class="file-status-item">
                <span class="icon">🌐</span>
                <span class="value" id="statusNetworkUp">-</span>
                <span class="unit">↓</span>
                <span class="value" id="statusNetworkDown">-</span>
            </div>
        </div>
        <div class="breadcrumb">
            <!-- 按钮组：新建、回收站、主页 -->
            <div class="breadcrumb-btn-group">
                <form method="post" action="#" enctype="multipart/form-data" id="uploadForm" style="margin:0;">
                    <input type="file" name="file" id="fileInputInline" onchange="handleFileSelect(event)" style="display:none;">
                    <div class="crumb-btn" onclick="openCreateMenuDrawer()" title="Create" data-i18n-title="breadcrumb.create">+</div>
                </form>
                <a href="#" onclick="openTrashDrawer(); return false;" title="Trash" class="crumb-btn" data-i18n-title="breadcrumb.trash">🗑️</a>
                <a :href="browseHref('')" @click="onBreadcrumbClick('', $event)" title="Root Directory" class="crumb-btn" data-i18n-title="fileBrowser.rootDirectory">🏠</a>
                
            </div>
            
            <!-- 滚动区域 -->
            <div class="breadcrumb-left">
                <template v-if="breadcrumbs.length">
                    <template v-for="(crumb, idx) in breadcrumbs" :key="crumb.path">
                        <template v-if="idx === breadcrumbs.length - 1">
                            <span class="crumb-name">
                                {{ crumb.name }}
                                <span class="crumb-count">({{ items.length }})</span>
                                <button type="button" class="menu-btn breadcrumb-folder-menu-btn" onclick="openCurrentFolderMenu(event)" :aria-label="t('fileBrowser.open_folder_menu')" :title="t('common.menu')"><span>⋮</span></button>
                            </span>
                        </template>
                        <template v-else>
                            <a :href="browseHref(crumb.path)" @click="onBreadcrumbClick(crumb.path, $event)">{{ crumb.name }}</a>
                            <span class="crumb-sep">/</span>
                        </template>
                    </template>
                </template>
                <template v-else>
                    <span class="crumb-name">
                        <span class="crumb-count">({{ items.length }})</span>
                        <button type="button" class="menu-btn breadcrumb-folder-menu-btn" onclick="openCurrentFolderMenu(event)" :aria-label="t('fileBrowser.open_folder_menu')" :title="t('common.menu')"><span>⋮</span></button>
                    </span>
                </template>
            </div>
            <div class="breadcrumb-right">
                <button onclick="openSearchModal()" style="background: none; border: none; cursor: pointer; font-size: var(--global-font-size, 16px); opacity: 0.75; padding: 4px 6px;" :title="t('fileBrowser.search_hotkey')">🔍</button>
            </div>
        </div>

        <!-- Git状态栏 -->
        <div id="gitStatusBar" class="git-status-bar" style="display: none;" onclick="openGitModalFromBar()">
            <div class="git-status-content">
                <span class="git-icon">🔀</span>
                <span class="git-branch" id="gitStatusBranch">main</span>
                <span class="git-status-indicator" id="gitStatusIndicator">●</span>
                <span class="git-stats" id="gitStatusStats"></span>
            </div>
                <div class="git-action-btn" data-i18n-title="git.title" title="Git Manager">🔧</div>
        </div>

        <div v-if="message" class="message" :class="messageTypeClass">
            {{ message }}
        </div>

        <div class="files-section">
            <div v-if="items.length" class="file-list">
                <div class="file-item" v-for="(item, idx) in items" :key="item.path || (item.name + ':' + idx)" :id="'file-item-' + (idx + 1)" :data-path="item.path" :data-name="item.name" :data-is-dir="item.is_dir ? 'true' : 'false'" :data-is-image="item.is_image ? 'true' : 'false'" :data-open-method="item.open_method || 'browser'">
                    <!-- 第一列：预览图或图标 + 复选框 -->
                    <div class="file-col-icon">
                        <input type="checkbox" class="file-checkbox" :data-path="item.path" @change="onToggleItemSelection(item.path, $event)" style="margin-right: 8px; cursor: pointer;">
                        <img v-if="item.is_image" :src="thumbUrl(item.path)" :alt="item.name" class="file-thumbnail" onerror="this.style.display='none';">
                        <span v-else class="file-icon">{{ item.icon }}</span>
                    </div>
                    
                    <!-- 第二列：名称 + 详情 -->
                    <div class="file-col-info">
                        <div class="file-name" :class="{ 'is-symlink': !!item.is_symlink, 'is-broken-link': !!item.is_broken_link }">
                            <span>{{ item.name }}</span>
                            <a v-if="isPortDir(item)" :href="portHref(item.name)" target="_blank" style="margin-left: 8px; color: #17a2b8; text-decoration: none; font-size: 1.2em;" :title="t('fileBrowser.open_site')">🔗</a>
                        </div>
                        <div class="file-details-inline">
                            <span class="file-size">
                                {{ item.is_dir ? item.modified + " - " + (item.item_count || 0) + " " + t('common.items') : item.size + " - " + item.modified }}
                            </span>
                        </div>
                    </div>
                    
                    <!-- 第三列：操作按钮 -->
                    <div class="file-col-actions">
                        <!-- 菜单按钮 -->
                        <div class="menu-btn" @click.stop.prevent="openMenu(item)">
                            <span>⋮</span>
                        </div>
                    </div>
                </div>
            </div>
            <div v-else class="empty-directory">
                <p>{{ t('fileBrowser.emptyDirectory') }}</p>
            </div>
        </div>

    </div><!-- end container -->

    <!-- 主菜单抽屉 -->
    <div id="mainMenuDrawer" class="right-drawer" role="dialog" aria-modal="true" aria-label="Start Menu" data-i18n-aria-label="menu.startMenu" aria-hidden="true" tabindex="-1">
        <div class="right-drawer-header">
            <div class="drawer-title" data-i18n="menu.startMenu">Start Menu</div>
            <button id="mainMenuCloseBtn" class="drawer-close-btn" onclick="closeMainMenuModal()" data-i18n-aria-label="menu.closeStartMenu">&times;</button>
        </div>
        <div class="right-drawer-content" id="mainMenuItems">
            <!-- 菜单项由 JS 动态渲染 -->
            <div style="text-align: center; padding: 20px; color: #666;" data-i18n="common.loading">Loading...</div>
        </div>
    </div>
    <div id="mainMenuBackdrop" class="right-drawer-backdrop" onclick="closeMainMenuModal()" aria-hidden="true"></div>
    <div id="srAnnouncer" aria-live="polite" aria-atomic="true" style="position: fixed; width: 1px; height: 1px; overflow: hidden; clip: rect(1px, 1px, 1px, 1px); white-space: nowrap;"></div>

    <!-- 包管理抽屉 -->
    <div id="pkgDrawer" class="right-drawer" style="width: 480px; max-width: 100vw;">
        <div class="right-drawer-header">
            <div class="drawer-title" data-i18n="package.title">Package Manager</div>
            <button class="drawer-close-btn" onclick="closePkgDrawer()">&times;</button>
        </div>
        <div class="right-drawer-content" style="padding: 0;">
            <!-- 搜索框 -->
            <div style="padding: 12px 16px; border-bottom: 1px solid #d0d7de; display: flex; gap: 8px;">
                <input type="text" id="pkgSearchInput" placeholder="Search..." data-i18n-placeholder="package.searchPlaceholder"
                    style="flex: 1; padding: 8px 12px; border: 1px solid #d0d7de; border-radius: 6px; font-size: 14px;"
                    oninput="filterPkgList()">
                <button onclick="loadPkgCurrentTab()" style="padding: 8px 16px; background: #0969da; color: #fff; border: none; border-radius: 6px; cursor: pointer;" data-i18n="common.refresh">Refresh</button>
            </div>
            <!-- Tab 栏 -->
            <div style="display: flex; border-bottom: 1px solid #d0d7de; background: #f6f8fa;">
                <button class="pkg-tab active" data-tab="system" onclick="switchPkgTab('system')" data-i18n="package.tabSystem">System</button>
                <button class="pkg-tab" data-tab="pip" onclick="switchPkgTab('pip')" data-i18n="package.tabPip">pip</button>
                <button class="pkg-tab" data-tab="npm" onclick="switchPkgTab('npm')" data-i18n="package.tabNpm">npm</button>
                <button class="pkg-tab" data-tab="source" onclick="switchPkgTab('source')" data-i18n="package.tabSource">Source</button>
            </div>
            <!-- Tab 内容 -->
            <div id="pkgTabContent" style="height: calc(100vh - 180px); overflow-y: auto; padding: 12px;">
                <!-- 系统包 -->
                <div id="pkgSystem" class="pkg-tab-panel active">
                    <div id="pkgSystemList" class="pkg-list" data-i18n="common.loading">Loading...</div>
                </div>
                <!-- pip 包 -->
                <div id="pkgPip" class="pkg-tab-panel">
                    <div id="pkgPipList" class="pkg-list" data-i18n="common.loading">Loading...</div>
                </div>
                <!-- npm 包 -->
                <div id="pkgNpm" class="pkg-tab-panel">
                    <div id="pkgNpmList" class="pkg-list" data-i18n="common.loading">Loading...</div>
                </div>
                <!-- 源管理 -->
                <div id="pkgSource" class="pkg-tab-panel">
                    <!-- pip 源 -->
                    <div style="margin-bottom: 20px;">
                        <div style="font-size: 13px; color: #57606a; margin-bottom: 8px;" data-i18n="package.pipSource">pip Source</div>
                        <div id="pipSourceCurrent" style="padding: 8px 12px; background: #f6f8fa; border-radius: 6px; margin-bottom: 8px; font-size: 13px;"></div>
                        <div id="pipSourceList" class="source-list"></div>
                    </div>
                    <!-- npm 源 -->
                    <div>
                        <div style="font-size: 13px; color: #57606a; margin-bottom: 8px;" data-i18n="package.npmSource">npm Source</div>
                        <div id="npmSourceCurrent" style="padding: 8px 12px; background: #f6f8fa; border-radius: 6px; margin-bottom: 8px; font-size: 13px;"></div>
                        <div id="npmSourceList" class="source-list"></div>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <div id="pkgDrawerBackdrop" class="right-drawer-backdrop" onclick="closePkgDrawer()" aria-hidden="true" style="display:none;"></div>

    <!-- 性能监控抽屉 -->
    <div id="perfDrawer" class="right-drawer" style="width: 480px; max-width: 100vw;">
        <div class="right-drawer-header">
            <div class="drawer-title" data-i18n="perf.title">Performance Monitor</div>
            <button class="drawer-close-btn" onclick="closePerfDrawer()">&times;</button>
        </div>
        <div class="right-drawer-content" style="padding: 0;">
            <!-- 刷新状态 -->
            <div id="perfStatus" style="padding: 8px 16px; background: #f6f8fa; border-bottom: 1px solid #d0d7de; font-size: 12px; color: #57606a; display: flex; justify-content: space-between;">
                <span id="perfUpdateTime">--:--:--</span>
                <span id="perfAuto" style="color: #0969da;" data-i18n="perf.auto_refreshing">🔄 Auto refreshing</span>
            </div>
            <!-- 监控项 -->
            <div style="padding: 12px; overflow-y: auto; max-height: calc(100vh - 120px);">
                <!-- ECharts 实时图表 -->
                <div id="perfChart" style="height: 180px; margin-bottom: 16px;"></div>
                
                <!-- CPU -->
                <div style="margin-bottom: 16px;">
                    <div style="font-size: 13px; color: #57606a; margin-bottom: 6px;" data-i18n="perf.cpuUsage">CPU Usage</div>
                    <div id="perfCpuBar" style="height: 24px; background: #eaecef; border-radius: 12px; overflow: hidden; position: relative;">
                        <div id="perfCpuFill" style="height: 100%; background: linear-gradient(90deg, #0969da, #58a6ff); transition: width 0.3s; width: 0%;"></div>
                        <div id="perfCpuText" style="position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 500; color: #fff; text-shadow: 0 1px 2px rgba(0,0,0,0.3);">--%</div>
                    </div>
                </div>
                <!-- 内存 -->
                <div style="margin-bottom: 16px;">
                    <div style="font-size: 13px; color: #57606a; margin-bottom: 6px;" data-i18n="perf.memoryUsage">Memory Usage</div>
                    <div id="perfMemBar" style="height: 24px; background: #eaecef; border-radius: 12px; overflow: hidden; position: relative;">
                        <div id="perfMemFill" style="height: 100%; background: linear-gradient(90deg, #1a7f37, #2ea043); transition: width 0.3s; width: 0%;"></div>
                        <div id="perfMemText" style="position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 500; color: #fff; text-shadow: 0 1px 2px rgba(0,0,0,0.3);">-- / --</div>
                    </div>
                </div>
                <!-- 磁盘 -->
                <div style="margin-bottom: 16px;">
                    <div style="font-size: 13px; color: #57606a; margin-bottom: 6px;" data-i18n="perf.diskUsage">Disk Usage</div>
                    <div id="perfDiskBar" style="height: 24px; background: #eaecef; border-radius: 12px; overflow: hidden; position: relative;">
                        <div id="perfDiskFill" style="height: 100%; background: linear-gradient(90deg, #bf8700, #d4a72c); transition: width 0.3s; width: 0%;"></div>
                        <div id="perfDiskText" style="position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 500; color: #fff; text-shadow: 0 1px 2px rgba(0,0,0,0.3);">--%</div>
                    </div>
                </div>
                <!-- 网络 -->
                <div style="margin-bottom: 16px;">
                    <div style="font-size: 13px; color: #57606a; margin-bottom: 6px;" data-i18n="perf.networkTraffic">Network Traffic</div>
                    <div id="perfNetText" style="font-size: 13px; color: #24292f;">↓ -- / ↑ --</div>
                </div>
                <!-- GPU -->
                <div id="perfGpuSection" style="margin-bottom: 16px; display: none;">
                    <div style="font-size: 13px; color: #57606a; margin-bottom: 6px;" data-i18n="perf.gpu">GPU</div>
                    <div id="perfGpuBar" style="height: 24px; background: #eaecef; border-radius: 12px; overflow: hidden; position: relative;">
                        <div id="perfGpuFill" style="height: 100%; background: linear-gradient(90deg, #cf222e, #f85149); transition: width 0.3s; width: 0%;"></div>
                        <div id="perfGpuText" style="position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 500; color: #fff; text-shadow: 0 1px 2px rgba(0,0,0,0.3);">--%</div>
                    </div>
                    <div id="perfGpuInfo" style="font-size: 12px; color: #57606a; margin-top: 6px;">-- / -- MB | --°C</div>
                </div>
            </div>
        </div>
    </div>
    <div id="perfDrawerBackdrop" class="right-drawer-backdrop" onclick="closePerfDrawer()" aria-hidden="true" style="display:none;"></div>

    <!-- 网络管理抽屉 -->
    <div id="networkDrawer" class="right-drawer" style="width: 480px; max-width: 100vw;">
        <div class="right-drawer-header">
            <div class="drawer-title" data-i18n="network.title">Network Manager</div>
            <button class="drawer-close-btn" onclick="closeNetworkDrawer()">&times;</button>
        </div>
        <div class="right-drawer-content" style="padding: 0;">
            <!-- Tab -->
            <div style="display: flex; border-bottom: 1px solid #d0d7de; background: #f6f8fa;">
                <button class="net-tab active" data-tab="interfaces" onclick="switchNetTab('interfaces')" style="flex:1;padding:10px;border:none;background:transparent;font-size:13px;color:#57606a;cursor:pointer;border-bottom:2px solid transparent;" data-i18n="network.tabInterfaces">Interfaces</button>
                <button class="net-tab" data-tab="connections" onclick="switchNetTab('connections')" style="flex:1;padding:10px;border:none;background:transparent;font-size:13px;color:#57606a;cursor:pointer;border-bottom:2px solid transparent;" data-i18n="network.tabConnections">Connections</button>
            </div>
            <!-- 内容 -->
            <div id="netTabContent" style="padding: 12px; overflow-y: auto; max-height: calc(100vh - 180px);">
                <div id="netInterfaces" class="net-tab-panel active"></div>
                <div id="netConnections" class="net-tab-panel" style="display:none;"></div>
            </div>
        </div>
    </div>
    <div id="networkDrawerBackdrop" class="right-drawer-backdrop" onclick="closeNetworkDrawer()" aria-hidden="true" style="display:none;"></div>

    <!-- 用户管理抽屉 -->
    <div id="usersDrawer" class="right-drawer" style="width: 480px; max-width: 100vw;">
        <div class="right-drawer-header">
            <div class="drawer-title" data-i18n="users.title">User Manager</div>
            <button class="drawer-close-btn" onclick="closeUsersDrawer()">&times;</button>
        </div>
        <div class="right-drawer-content" style="padding: 0;">
            <!-- Tab -->
            <div style="display: flex; border-bottom: 1px solid #d0d7de; background: #f6f8fa;">
                <button class="user-tab active" data-tab="users" onclick="switchUserTab('users')" style="flex:1;padding:10px;border:none;background:transparent;font-size:13px;color:#57606a;cursor:pointer;border-bottom:2px solid transparent;" data-i18n="users.tabUsers">Users</button>
                <button class="user-tab" data-tab="groups" onclick="switchUserTab('groups')" style="flex:1;padding:10px;border:none;background:transparent;font-size:13px;color:#57606a;cursor:pointer;border-bottom:2px solid transparent;" data-i18n="users.tabGroups">Groups</button>
            </div>
            <!-- 内容 -->
            <div id="userTabContent" style="padding: 12px; overflow-y: auto; max-height: calc(100vh - 180px);">
                <div id="userUsers" class="user-tab-panel active"></div>
                <div id="userGroups" class="user-tab-panel" style="display:none;"></div>
            </div>
        </div>
    </div>
    <div id="usersDrawerBackdrop" class="right-drawer-backdrop" onclick="closeUsersDrawer()" aria-hidden="true" style="display:none;"></div>

    <!-- 样式 -->
    <style>
    .pkg-tab {
        flex: 1; padding: 10px; border: none; background: transparent; 
        font-size: 13px; color: #57606a; cursor: pointer; border-bottom: 2px solid transparent;
    }
    .pkg-tab.active {
        color: #0969da; border-bottom-color: #0969da; font-weight: 500;
    }
    .pkg-tab:hover:not(.active) { background: #f6f8fa; }
    .pkg-tab-panel { display: none; }
    .pkg-tab-panel.active { display: block; }
    .pkg-item {
        display: flex; align-items: center; padding: 8px 12px; 
        border-bottom: 1px solid #eaecef; cursor: pointer;
    }
    .pkg-item:hover { background: #f6f8fa; }
    .pkg-item-name { flex: 1; font-size: 13px; font-weight: 500; }
    .pkg-item-version { font-size: 11px; color: #8b949e; margin-right: 8px; }
    .pkg-item-action { 
        padding: 4px 8px; font-size: 11px; border-radius: 4px; 
        cursor: pointer; border: 1px solid #d0d7de; background: #fff;
    }
    .pkg-item-action:hover { background: #f6f8fa; }
    .source-item {
        display: flex; align-items: center; padding: 8px 12px;
        border-bottom: 1px solid #eaecef; cursor: pointer;
    }
    .source-item:hover { background: #f6f8fa; }
    .source-item-name { flex: 1; font-size: 13px; }
    .source-item-arrow { color: #8b949e; }
    .source-item.active { background: #f6f8fa; }
    .source-item.active .source-item-arrow { color: #1a7f37; }
    </style>

    <!-- Bot Drawer 遮罩层 -->
    <div id="botBackdrop" class="drawer-backdrop" onclick="closeBotModal()"></div>
    <div id="botDrawer" class="drawer" style="height: 90vh;">
        <!-- 拖拽手柄 -->
        <div class="drawer-handle" id="botDrawerHandle"></div>
        
        <!-- Header -->
        <div class="drawer-header">
            <div id="botDrawerHeaderMain" style="display:flex;justify-content:space-between;align-items:center;gap:10px;flex:1;min-width:0;">
                <div style="font-weight:600;font-size:14px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;" data-i18n="openclaw.config_title">⚙️ OpenClaw Settings</div>
                <div style="display:flex;gap:8px;flex-shrink:0;">
                    <button id="openclawInstallBtn" style="display:none;background:#2da44e;border:none;border-radius:6px;color:#fff;padding:6px 10px;cursor:pointer;font-size:13px;" onclick="serviceInstallAction('openclaw','install')" data-i18n="common.install">Install</button>
                    <button id="openclawReinstallBtn" style="display:none;background:#0969da;border:none;border-radius:6px;color:#fff;padding:6px 10px;cursor:pointer;font-size:13px;" onclick="serviceInstallAction('openclaw','reinstall')" data-i18n="common.reinstall">Reinstall</button>
                    <button id="openclawUninstallBtn" style="display:none;background:#cf222e;border:none;border-radius:6px;color:#fff;padding:6px 10px;cursor:pointer;font-size:13px;" onclick="serviceInstallAction('openclaw','uninstall')" data-i18n="common.uninstall">Uninstall</button>
                    <button style="background:none;border:none;font-size:18px;cursor:pointer;padding:4px;" onclick="loadOpenclawConfig()" title="Refresh" data-i18n-title="common.refresh">🔄</button>
                </div>
            </div>
            <button class="drawer-close-btn" onclick="closeBotModal()">&times;</button>
        </div>
        
        <div class="bot-container">
            <!-- Settings Overlay -->
            <div id="botSettings" class="bot-settings-overlay">
                <h4 data-i18n="bot.settings_title">Settings & Status</h4>
                <div style="margin: 10px 0; font-size: var(--global-font-size, 13px); color: #666;">
                    <span id="botWsDot" class="bot-status-dot bot-dot-disconnected"></span>
                    <span id="botWsStatus" data-i18n="bot.status.disconnected">Disconnected</span>
                </div>
                
                <input type="text" id="botTokenInput" placeholder="Gateway Token (auto-fetched by backend)" data-i18n-placeholder="openclaw.gateway_token_placeholder" value="" disabled style="margin-bottom: 10px; width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 6px; opacity: 0.7;">
                <div style="display: flex; gap: 10px;">
                    <button onclick="botConnect()" class="dialog-btn dialog-btn-primary" style="padding: 8px;" data-i18n="common.connect">Connect</button>
                    <button onclick="botClear()" class="dialog-btn dialog-btn-danger" style="padding: 8px;" data-i18n="bot.clear_history">Clear history</button>
                </div>
                <div style="margin-top: 20px; font-size: var(--global-font-size, 12px); color: #999;">
                    <span data-i18n="bot.sent">Sent</span>: <span id="botSentCount">-</span> | <span data-i18n="bot.rounds">Rounds</span>: <span id="botConvCount">-</span>
                </div>
                <button onclick="toggleBotSettings()" class="dialog-btn" style="margin-top: auto; background: #ddd;" data-i18n="bot.close_settings">Close settings</button>
            </div>

            <div style="display:flex;border-bottom:1px solid #d0d7de;background:#f6f8fa;">
                <button class="bot-tab active" data-tab="config" onclick="switchBotTab('config')" style="flex:1;padding:10px;border:none;background:transparent;font-size:13px;color:#57606a;cursor:pointer;border-bottom:2px solid transparent;" data-i18n="common.settings">Settings</button>
                <button class="bot-tab" data-tab="agents" onclick="switchBotTab('agents')" style="flex:1;padding:10px;border:none;background:transparent;font-size:13px;color:#57606a;cursor:pointer;border-bottom:2px solid transparent;">Agents</button>
                <button class="bot-tab" data-tab="models" onclick="switchBotTab('models')" style="flex:1;padding:10px;border:none;background:transparent;font-size:13px;color:#57606a;cursor:pointer;border-bottom:2px solid transparent;">Models</button>
                <button class="bot-tab" data-tab="channels" onclick="switchBotTab('channels')" style="flex:1;padding:10px;border:none;background:transparent;font-size:13px;color:#57606a;cursor:pointer;border-bottom:2px solid transparent;">Channels</button>
                <button class="bot-tab" data-tab="chat" onclick="switchBotTab('chat')" style="flex:1;padding:10px;border:none;background:transparent;font-size:13px;color:#57606a;cursor:pointer;border-bottom:2px solid transparent;" data-i18n="nav.chat">Chat</button>
            </div>

            <div id="botConfigPanel" style="display:block;overflow-y:auto;flex:1;padding:16px;">
                <div id="botOpenclawConfigContainer"></div>
            </div>

            <div id="botAgentsPanel" style="display:none;overflow-y:auto;flex:1;padding:16px;">
                <div style="display:flex;justify-content:space-between;align-items:center;gap:10px;margin-bottom:12px;">
                    <div style="font-weight:600;font-size:14px;">Agents</div>
                    <div style="display:flex;gap:8px;flex-shrink:0;">
                        <button onclick="openOpenclawAddAgentModal()" style="background:#0969da;border:none;border-radius:6px;color:#fff;padding:6px 10px;cursor:pointer;font-size:13px;" data-i18n="common.add">Add</button>
                        <button style="background:none;border:none;font-size:18px;cursor:pointer;padding:4px;" onclick="loadOpenclawAgents()" title="Refresh" data-i18n-title="common.refresh">🔄</button>
                    </div>
                </div>
                <div id="botOpenclawAgentsContainer"></div>
            </div>

            <div id="botModelsPanel" style="display:none;overflow-y:auto;flex:1;padding:16px;">
                <div style="display:flex;justify-content:space-between;align-items:center;gap:10px;margin-bottom:12px;">
                    <div style="font-weight:600;font-size:14px;">Models</div>
                    <div style="display:flex;gap:8px;flex-shrink:0;">
                        <button onclick="openOpenclawAddModelModal()" style="background:#0969da;border:none;border-radius:6px;color:#fff;padding:6px 10px;cursor:pointer;font-size:13px;" data-i18n="common.add">Add</button>
                        <button style="background:none;border:none;font-size:18px;cursor:pointer;padding:4px;" onclick="loadOpenclawModels()" title="Refresh" data-i18n-title="common.refresh">🔄</button>
                    </div>
                </div>
                <div id="botOpenclawModelsContainer"></div>
            </div>

            <div id="botChannelsPanel" style="display:none;overflow-y:auto;flex:1;padding:16px;">
                <div style="display:flex;justify-content:space-between;align-items:center;gap:10px;margin-bottom:12px;">
                    <div style="font-weight:600;font-size:14px;">Channels</div>
                    <div style="display:flex;gap:8px;flex-shrink:0;">
                        <button onclick="openOpenclawAddChannelModal()" style="background:#0969da;border:none;border-radius:6px;color:#fff;padding:6px 10px;cursor:pointer;font-size:13px;" data-i18n="common.add">Add</button>
                        <button style="background:none;border:none;font-size:18px;cursor:pointer;padding:4px;" onclick="loadOpenclawChannels()" title="Refresh" data-i18n-title="common.refresh">🔄</button>
                    </div>
                </div>
                <div id="botOpenclawChannelsContainer"></div>
            </div>

            <div id="botChatPanel" style="display:none;flex:1;min-height:0;flex-direction:column;position:relative;">
                <div class="bot-chat-box" id="botChatBox" style="flex:1;min-height:0;width:100%;">
                    <ul id="botHistoryList" class="bot-history" style="list-style: none; padding: 0; margin: 0;"></ul>
                </div>
                <button id="botJumpLatestBtn" type="button" onclick="botJumpToLatest()" style="position:absolute;right:16px;bottom:78px;z-index:5;display:none;padding:10px 12px;border-radius:999px;border:1px solid #d0d7de;background:#ffffff;color:#24292f;box-shadow:0 6px 16px rgba(0,0,0,0.12);cursor:pointer;font-size: var(--global-font-size, 12px);" data-i18n="bot.jump_latest">
                    ⬇ Jump to latest
                </button>

                <div class="bot-input-area">
                    <textarea class="bot-input" id="botInput" placeholder="Type a message..." data-i18n-placeholder="bot.input_placeholder" style="flex: 1; border: 1px solid #ddd; background: #f5f5f5; padding: 10px 12px; border-radius: 8px; font-size: var(--global-font-size, 14px); resize: none; outline: none; height: 40px; max-height: 100px;"></textarea>
                    <button class="bot-settings-btn" onclick="toggleBotSettings()" style="background: none; border: 1px solid #d0d7de; font-size: var(--global-font-size, 16px); cursor: pointer; padding: 0 10px; height: 40px; border-radius: 8px; flex-shrink: 0;">⚙️</button>
                    <button class="bot-send-btn" onclick="botSend()" style="width: 40px; height: 40px; border-radius: 8px; background: #95ec69; border: none; display: flex; align-items: center; justify-content: center; cursor: pointer; flex-shrink: 0;">🚀</button>
                </div>
            </div>
        </div>
    </div>

    <!-- 上传状态显示 -->
    <div id="uploadStatus" class="upload-status"></div>

    <div id="archiveProgressBackdrop" class="drawer-backdrop" onclick="closeArchiveProgressDrawer()"></div>
    <div id="archiveProgressDrawer" class="drawer">
        <div class="drawer-handle"></div>
        <div class="drawer-header">
            <div class="drawer-title" data-i18n="archive.compressing">🗜️ Compressing</div>
            <button class="drawer-close-btn" onclick="closeArchiveProgressDrawer()">&times;</button>
        </div>
        <div class="drawer-content" style="padding:16px;">
            <div id="archiveProgressText" style="font-size: var(--global-font-size, 14px); color:#57606a; margin-bottom: 12px;" data-i18n="archive.preparing">Preparing…</div>
            <div class="progress-bar" style="width:100%;height:10px;background:#e5e7eb;border-radius:999px;overflow:hidden;">
                <div id="archiveProgressFill" style="height:100%;width:0%;background:#2da44e;transition:width 0.2s;"></div>
            </div>
        </div>
    </div>

    <div id="dragUploadOverlay" style="position:fixed;inset:0;background:rgba(0,0,0,0.35);backdrop-filter:blur(2px);z-index:1900;display:none;align-items:center;justify-content:center;color:#fff;font-size:18px;font-weight:600;" data-i18n="upload.release_to_upload">
        Release to upload
    </div>
    <div id="dragUploadBackdrop" class="drawer-backdrop" onclick="closeDragUploadDrawer()"></div>
    <div id="dragUploadDrawer" class="drawer">
        <div class="drawer-handle"></div>
        <div class="drawer-header">
            <div class="drawer-title" data-i18n="upload.drag_upload_title">📤 Drag Upload</div>
            <button class="drawer-close-btn" onclick="closeDragUploadDrawer()">&times;</button>
        </div>
        <div class="drawer-content" style="padding:16px;">
            <div style="display:flex;gap:10px;margin-bottom:12px;">
                <input type="text" id="dragUploadTargetPath" style="flex:1;padding:12px;border:1px solid #ddd;border-radius:8px;font-size: var(--global-font-size, 14px);" placeholder="Target path (relative to root)" data-i18n-placeholder="upload.target_path_placeholder">
            </div>
            <div id="dragUploadFileList" style="max-height: 220px; overflow:auto; border:1px solid #eee; border-radius:8px; padding:8px; margin-bottom:12px;"></div>
            <div id="dragUploadProgressText" style="font-size: var(--global-font-size, 12px); color:#57606a; margin-bottom: 8px;"></div>
            <div class="progress-bar" style="width:100%;height:10px;background:#e5e7eb;border-radius:999px;overflow:hidden;margin-bottom:12px;">
                <div id="dragUploadProgressFill" style="height:100%;width:0%;background:#0969da;transition:width 0.2s;"></div>
            </div>
            <div class="modal-buttons" style="padding:0;border:none;background:none;gap:12px;display:flex;">
                <button class="modal-btn modal-btn-cancel" style="flex:1;padding:12px;border-radius:8px;" onclick="closeDragUploadDrawer()" data-i18n="common.cancel">Cancel</button>
                <button class="modal-btn modal-btn-confirm" style="flex:1;padding:12px;border-radius:8px;" onclick="startDragUpload()" data-i18n="upload.start_upload">Start upload</button>
            </div>
        </div>
    </div>

    <div id="pasteImageBackdrop" class="drawer-backdrop" onclick="closePasteImageDrawer()"></div>
    <div id="pasteImageDrawer" class="drawer">
        <div class="drawer-handle"></div>
        <div class="drawer-header">
            <div class="drawer-title" data-i18n="upload.paste_image_title">🖼️ Save Pasted Image</div>
            <button class="drawer-close-btn" onclick="closePasteImageDrawer()">&times;</button>
        </div>
        <div class="drawer-content" style="padding:16px;">
            <div style="display:flex;justify-content:center;margin-bottom:12px;">
                <img id="pasteImagePreview" alt="paste preview" style="max-width: 100%; max-height: 240px; border-radius: 8px; border: 1px solid #eee; display:none;">
            </div>
            <div style="display:flex;gap:10px;margin-bottom:12px;">
                <input type="text" id="pasteImageTargetPath" style="flex:1;padding:12px;border:1px solid #ddd;border-radius:8px;font-size: var(--global-font-size, 14px);" placeholder="Save path (relative to root)" data-i18n-placeholder="upload.save_path_placeholder">
            </div>
            <div style="display:flex;gap:10px;margin-bottom:12px;">
                <input type="text" id="pasteImageFilename" style="flex:1;padding:12px;border:1px solid #ddd;border-radius:8px;font-size: var(--global-font-size, 14px);" placeholder="Filename" data-i18n-placeholder="upload.filename_placeholder">
            </div>
            <div class="modal-buttons" style="padding:0;border:none;background:none;gap:12px;display:flex;">
                <button class="modal-btn modal-btn-cancel" style="flex:1;padding:12px;border-radius:8px;" onclick="closePasteImageDrawer()" data-i18n="common.cancel">Cancel</button>
                <button class="modal-btn modal-btn-confirm" style="flex:1;padding:12px;border-radius:8px;" onclick="savePasteImage()" data-i18n="common.save">Save</button>
            </div>
        </div>
    </div>

    <!-- 预览抽屉 -->
    <div id="previewBackdrop" class="drawer-backdrop" onclick="closePreviewModal()"></div>
    <div id="previewModal" class="drawer">
        <div class="drawer-handle"></div>
        <div class="drawer-header">
            <div class="drawer-title" id="previewTitle" data-i18n="preview.title">Preview</div>
            <button class="drawer-close-btn" onclick="closePreviewModal()">&times;</button>
        </div>
        <div class="drawer-content">
            <div id="previewContent"></div>
        </div>
    </div>

    <div id="createMenuBackdrop" class="drawer-backdrop" onclick="closeCreateMenuDrawer()"></div>
    <div id="createMenuDrawer" class="drawer">
        <div class="drawer-handle"></div>
        <div class="drawer-header">
            <div class="drawer-title" data-i18n="breadcrumb.create">Create</div>
            <button class="drawer-close-btn" onclick="closeCreateMenuDrawer()">&times;</button>
        </div>
        <div class="drawer-content">
            <div class="modal-item" onclick="createMenuUpload()" data-i18n="fileBrowser.upload">📤 Upload</div>
            <div class="modal-item" onclick="createMenuNewFolder()" data-i18n="fileBrowser.newFolder">📁 New Folder</div>
            <div class="modal-item" onclick="createMenuNewFile()" data-i18n="fileBrowser.newFile">📄 New File</div>
            <div class="modal-item" onclick="createMenuNewUrl()" data-i18n="create_menu.url_shortcut">🔗 URL Shortcut</div>
        </div>
    </div>

    <div id="dialogBackdrop" class="drawer-backdrop" onclick="closeDialogDrawer()"></div>
    <div id="dialogDrawer" class="drawer">
        <div class="drawer-handle"></div>
        <div class="drawer-header">
            <div class="drawer-title" id="dialogTitle" data-i18n="common.notice">Notice</div>
            <button class="drawer-close-btn" onclick="closeDialogDrawer()">&times;</button>
        </div>
        <div class="drawer-content">
            <p id="dialogMessage" style="margin: 0 0 12px 0; color: #666; font-size: var(--global-font-size, 14px);"></p>
            <select id="dialogSelect" style="width: 100%; padding: 12px; margin-bottom: 12px; border: 1px solid #ddd; border-radius: 8px; font-size: var(--global-font-size, 14px); box-sizing: border-box; display:none;"></select>
            <input type="text" id="dialogInput" style="width: 100%; padding: 12px; margin-bottom: 16px; border: 1px solid #ddd; border-radius: 8px; font-size: var(--global-font-size, 14px); box-sizing: border-box;">
            <div class="modal-buttons" style="padding: 0; border: none; background: none; gap: 12px; display:flex;">
                <button style="flex: 1; padding: 12px; border-radius: 8px; border: 1px solid #d0d7de; background: #f6f8fa; cursor: pointer;" onclick="closeDialogDrawer()" data-i18n="common.cancel">Cancel</button>
                <button id="dialogConfirmBtn" style="flex: 1; padding: 12px; border-radius: 8px; border: 1px solid transparent; background: #2da44e; color: #fff; cursor: pointer;" onclick="confirmDialogDrawer()" data-i18n="common.confirm">Confirm</button>
            </div>
        </div>
    </div>

    <!-- 网页快捷方式创建弹窗 -->
    <div id="urlShortcutBackdrop" class="drawer-backdrop" onclick="closeUrlShortcutDrawer()"></div>
    <div id="urlShortcutDrawer" class="drawer" style="width: 360px;">
        <div class="drawer-handle"></div>
        <div class="drawer-header">
            <div class="drawer-title" data-i18n="create_menu.create_url_shortcut_title">Create URL Shortcut</div>
            <button class="drawer-close-btn" onclick="closeUrlShortcutDrawer()">&times;</button>
        </div>
        <div class="drawer-content" style="padding: 16px;">
            <div class="form-group" style="margin-bottom: 12px;">
                <label style="display: block; font-size: 12px; color: #888; margin-bottom: 4px;" data-i18n="common.name">Name</label>
                <input type="text" id="urlShortcutName" placeholder="e.g., My Website" data-i18n-placeholder="create_menu.url_name_example" style="width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 6px; font-size: 14px; box-sizing: border-box;">
            </div>
            <div class="form-group" style="margin-bottom: 16px;">
                <label style="display: block; font-size: 12px; color: #888; margin-bottom: 4px;" data-i18n="common.url">URL</label>
                <input type="text" id="urlShortcutUrl" placeholder="e.g., https://example.com" data-i18n-placeholder="create_menu.url_url_example" style="width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 6px; font-size: 14px; box-sizing: border-box;">
            </div>
            <div style="display: flex; gap: 12px;">
                <button onclick="closeUrlShortcutDrawer()" style="flex: 1; padding: 10px; border-radius: 6px; border: 1px solid #ddd; background: #f6f8fa; cursor: pointer;" data-i18n="common.cancel">Cancel</button>
                <button onclick="confirmUrlShortcut()" style="flex: 1; padding: 10px; border-radius: 6px; border: none; background: #2da44e; color: #fff; cursor: pointer;" data-i18n="common.create">Create</button>
            </div>
        </div>
    </div>

    <!-- 删除确认抽屉 -->
    <div id="confirmBackdrop" class="gh-dialog-backdrop" onclick="closeConfirmModal()" style="display:none;">
        <div class="gh-dialog" onclick="event.stopPropagation()">
            <div class="gh-dialog-header">
                <svg id="confirmIcon" class="gh-dialog-icon danger" viewBox="0 0 24 24" fill="currentColor">
                    <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/>
                </svg>
                <div class="gh-dialog-title" id="confirmTitle" data-i18n="common.confirm_action_title">Confirm Action</div>
            </div>
            <div class="gh-dialog-body" id="confirmMessage" data-i18n="common.confirm_action_message">Are you sure you want to proceed?</div>
            <div class="gh-dialog-footer">
                <button class="gh-btn gh-btn-secondary" onclick="closeConfirmModal()" data-i18n="common.cancel">Cancel</button>
                <button class="gh-btn gh-btn-primary" id="confirmBtn" onclick="performConfirm()" data-i18n="common.confirm">Confirm</button>
            </div>
        </div>
    </div>

    <!-- GitHub Alert 弹窗 -->
    <div id="alertBackdrop" class="gh-dialog-backdrop" onclick="closeAlertModal()" style="display:none;">
        <div class="gh-alert" id="alertBox" onclick="event.stopPropagation()">
            <svg id="alertIcon" class="gh-dialog-icon info" viewBox="0 0 24 24" fill="currentColor">
                <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/>
            </svg>
            <div style="flex:1;">
                <div class="gh-dialog-title" id="alertTitle" style="margin-bottom:4px;"></div>
                <div class="gh-dialog-body" id="alertMessage" style="padding:0;"></div>
            </div>
        </div>
    </div>

    <!-- 详情模态框 -->
    <div id="detailsBackdrop" class="drawer-backdrop" onclick="closeDetailsModal()"></div>
    <div id="detailsModal" class="drawer">
        <div class="drawer-handle"></div>
        <div class="drawer-header">
            <div class="drawer-title" data-i18n="fileBrowser.details_title">📋 File Details</div>
            <button class="drawer-close-btn" onclick="closeDetailsModal()">&times;</button>
        </div>
        <div class="drawer-content" id="detailsContent">
            <!-- 内容由 JS 填充 -->
        </div>
    </div>

    <!-- 重命名抽屉 -->
    <div id="renameBackdrop" class="drawer-backdrop" onclick="closeRenameModal()"></div>
    <div id="renameModal" class="drawer">
        <div class="drawer-handle"></div>
        <div class="drawer-header">
            <div class="drawer-title" data-i18n="fileBrowser.rename_title">Rename</div>
            <button class="drawer-close-btn" onclick="closeRenameModal()">&times;</button>
        </div>
        <div class="drawer-content">
            <p style="margin: 0 0 12px 0; color: #666; font-size: var(--global-font-size, 14px);" data-i18n="fileBrowser.rename_prompt">Enter new name</p>
            <input type="text" id="renameInput" style="width: 100%; padding: 12px; margin-bottom: 16px; border: 1px solid #ddd; border-radius: 8px; font-size: var(--global-font-size, 14px); box-sizing: border-box;">
            <div class="modal-buttons" style="padding: 0; border: none; background: none; gap: 12px;">
                <button class="modal-btn modal-btn-cancel" style="flex: 1; padding: 12px; border-radius: 8px;" onclick="closeRenameModal()" data-i18n="common.cancel">Cancel</button>
                <button class="modal-btn modal-btn-confirm" style="flex: 1; padding: 12px; border-radius: 8px;" onclick="performRename()" data-i18n="common.confirm">Confirm</button>
            </div>
        </div>
    </div>

    <!-- 移动抽屉 -->
    <div id="moveBackdrop" class="drawer-backdrop" onclick="closeMoveModal()"></div>
    <div id="moveModal" class="drawer">
        <div class="drawer-handle"></div>
        <div class="drawer-header">
            <div class="drawer-title" data-i18n="fileBrowser.move_title">Move to</div>
            <button class="drawer-close-btn" onclick="closeMoveModal()">&times;</button>
        </div>
        <div class="drawer-content">
            <p style="margin: 0 0 12px 0; color: #666; font-size: var(--global-font-size, 14px);" data-i18n="fileBrowser.move_prompt">Enter target path (relative to root):</p>
            <input type="text" id="moveInput" style="width: 100%; padding: 12px; margin-bottom: 16px; border: 1px solid #ddd; border-radius: 8px; font-size: var(--global-font-size, 14px); box-sizing: border-box;" placeholder="e.g., docs/new-folder" data-i18n-placeholder="move.placeholder">
            <div class="modal-buttons" style="padding: 0; border: none; background: none; gap: 12px;">
                <button class="modal-btn modal-btn-cancel" style="flex: 1; padding: 12px; border-radius: 8px;" onclick="closeMoveModal()" data-i18n="common.cancel">Cancel</button>
                <button class="modal-btn modal-btn-confirm" style="flex: 1; padding: 12px; border-radius: 8px;" onclick="performMove()" data-i18n="common.confirm">Confirm</button>
            </div>
        </div>
    </div>

    <!-- 克隆抽屉 -->
    <div id="cloneBackdrop" class="drawer-backdrop" onclick="Drawer.close('cloneModal')"></div>
    <div id="cloneModal" class="drawer">
        <div class="drawer-handle"></div>
        <div class="drawer-header">
            <div class="drawer-title" data-i18n="clone.in_progress">Cloning...</div>
            <button class="drawer-close-btn" onclick="Drawer.close('cloneModal')">&times;</button>
        </div>
        <div class="drawer-content">
            <p id="cloneStatus" style="text-align: center; color: #666;" data-i18n="clone.processing">Processing...</p>
        </div>
    </div>

    <!-- Terminal Drawer -->
    <div id="terminalBackdrop" class="drawer-backdrop" onclick="closeTerminal()"></div>
    <div id="terminalDrawer">
        <!-- 拖拽手柄 -->
        <div class="drawer-handle" id="terminalDrawerHandle"></div>
        <style>
            .terminal-keyboard .term-key, .terminal-ctrl-keys .term-key {
                background:#444;border:none;color:#fff;padding:8px 10px;border-radius:4px;font-size:13px;cursor:pointer;min-width:36px;touch-action:manipulation;transition:all 0.15s;-webkit-tap-highlight-color:transparent;
            }
            .terminal-keyboard .term-key:active, .terminal-ctrl-keys .term-key:active { background:#666;transform:scale(0.95); }
            .term-key.active { background:#0969da !important; }
            .term-key-small { padding:6px 10px !important;font-size:12px !important;min-width:30px !important; }
            .terminal-keyboard { visibility:hidden;opacity:0;max-height:0;overflow:hidden;padding:0 !important;border-top:0 !important;pointer-events:none;transition:max-height 0.2s ease,opacity 0.2s ease,visibility 0.2s ease,padding 0.2s ease; }
            .terminal-keyboard.visible { visibility:visible;opacity:1;max-height:240px;padding:6px !important;border-top:1px solid #333 !important;pointer-events:auto; }
            @media (min-width:768px) { .terminal-keyboard, .terminal-ctrl-keys { display:none !important; } }
        </style>
        <div id="terminal-container" style="flex:1;overflow:hidden;background:#000;"></div>
        <!-- 虚拟键盘 -->
        <div id="terminalAuxKeyboard" class="terminal-keyboard" style="background:#222;padding:6px;display:flex;flex-direction:column;gap:6px;user-select:none;border-top:1px solid #333;flex-shrink:0;">
            <div style="display:flex;gap:6px;">
                <button type="button" tabindex="-1" class="term-key" onmousedown="handleKeyBtn(event, 'esc')" ontouchstart="handleKeyBtn(event, 'esc')">ESC</button>
                <button type="button" tabindex="-1" class="term-key" onmousedown="handleKeyBtn(event, 'slash')" ontouchstart="handleKeyBtn(event, 'slash')">/</button>
                <button type="button" tabindex="-1" class="term-key" onmousedown="handleKeyBtn(event, 'dash')" ontouchstart="handleKeyBtn(event, 'dash')">—</button>
                <button type="button" tabindex="-1" class="term-key" onmousedown="handleKeyBtn(event, 'home')" ontouchstart="handleKeyBtn(event, 'home')">HOME</button>
                <button type="button" tabindex="-1" class="term-key" onmousedown="handleKeyBtn(event, 'up')" ontouchstart="handleKeyBtn(event, 'up')">↑</button>
                <button type="button" tabindex="-1" class="term-key" onmousedown="handleKeyBtn(event, 'end')" ontouchstart="handleKeyBtn(event, 'end')">END</button>
                <button type="button" tabindex="-1" class="term-key" onmousedown="handleKeyBtn(event, 'pgup')" ontouchstart="handleKeyBtn(event, 'pgup')">PGUP</button>
            </div>
            <div style="display:flex;gap:6px;">
                <button type="button" tabindex="-1" class="term-key" onmousedown="handleKeyBtn(event, 'tab')" ontouchstart="handleKeyBtn(event, 'tab')">TAB</button>
                <button type="button" tabindex="-1" data-mod="ctrl" class="term-key" onmousedown="handleKeyBtn(event, 'ctrl')" ontouchstart="handleKeyBtn(event, 'ctrl')">CTRL</button>
                <button type="button" tabindex="-1" data-mod="alt" class="term-key" onmousedown="handleKeyBtn(event, 'alt')" ontouchstart="handleKeyBtn(event, 'alt')">ALT</button>
                <button type="button" tabindex="-1" class="term-key" onmousedown="handleKeyBtn(event, 'left')" ontouchstart="handleKeyBtn(event, 'left')">←</button>
                <button type="button" tabindex="-1" class="term-key" onmousedown="handleKeyBtn(event, 'down')" ontouchstart="handleKeyBtn(event, 'down')">↓</button>
                <button type="button" tabindex="-1" class="term-key" onmousedown="handleKeyBtn(event, 'right')" ontouchstart="handleKeyBtn(event, 'right')">→</button>
                <button type="button" tabindex="-1" class="term-key" onmousedown="handleKeyBtn(event, 'pgdn')" ontouchstart="handleKeyBtn(event, 'pgdn')">PGDN</button>
            </div>
        </div>
    </div>

    <!-- 进程管理抽屉样式（复制终端抽屉） -->
    <style>
        #processModal {
            position: fixed;
            left: 0;
            right: 0;
            bottom: 0;
            background: #fff;
            border-radius: 16px 16px 0 0;
            transform: translateY(110%);
            transition: transform 0.3s cubic-bezier(0.2, 0.8, 0.2, 1);
            z-index: 2000;
            display: flex;
            flex-direction: column;
            max-height: 85vh;
        }
        #processModal.open {
            transform: translateY(0);
            box-shadow: 0 -4px 20px rgba(0,0,0,0.15);
        }
        #processModal .drawer-header {
            background: #fff;
            border-bottom: 1px solid #eee;
        }
        #processModal .drawer-close-btn {
            color: #666;
        }
        #processModal .drawer-handle {
            background: #ddd;
        }
    </style>

    <!-- clawOS配置抽屉 -->
    <div id="configBackdrop" class="drawer-backdrop" onclick="closeConfigModal()"></div>
    <div id="configModal" class="drawer">
        <div class="drawer-handle"></div>
        <div class="drawer-header">
            <div class="drawer-title" data-i18n="settings.drawer_title">⚙️ Settings</div>
            <button class="drawer-close-btn" onclick="closeConfigModal()">&times;</button>
        </div>
        <div class="drawer-content" style="padding: 16px;">
            <!-- 界面卡片 -->
            <div class="config-card">
                <div class="config-card-title" data-i18n="settings.appearance">Appearance</div>
                <div class="config-card-row">
                    <span class="config-card-label" data-i18n="settings.language">Language</span>
                    <select id="langSelect" onchange="changeLanguage(this.value)" style="padding: 6px 12px; border-radius: 6px; border: 1px solid #d0d7de; font-size: 13px; cursor: pointer;">
                        <option value="zh">中文</option>
                        <option value="en">English</option>
                        <option value="ja">日本語</option>
                    </select>
                </div>
                <div class="config-card-row">
                    <span class="config-card-label" data-i18n="settings.fontSize">Font Size</span>
                    <div style="display: flex; align-items: center; gap: 12px;">
                        <input type="range" id="fontSizeSlider" class="font-size-slider" min="12" max="24" value="14" onchange="updateFontSize(this.value)" style="width: 120px;">
                        <span id="fontSizeValue" style="font-size: 13px; color: #666; min-width: 36px;">14px</span>
                    </div>
                </div>
                <div id="fontPreview" class="font-preview" style="font-size: var(--global-font-size, 14px); margin-top: 8px;" data-i18n="settings.fontPreview">Preview abc ABC 123</div>
            </div>
            
            <!-- 文件管理卡片 -->
            <div class="config-card">
                <div class="config-card-title" data-i18n="nav.files">Files</div>
                <div class="config-card-row">
                    <span class="config-card-label" data-i18n="fileBrowser.openWith">Open With</span>
                    <button class="config-card-btn" onclick="window.open('/file-open-config', '_blank')" data-i18n="common.manage">Manage</button>
                </div>
                <div class="config-card-row">
                    <span class="config-card-label" data-i18n="fileBrowser.currentPath">Current Path</span>
                    <span id="configCurrentPath" style="font-size: 12px; color: #666; max-width: 140px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">/root</span>
                </div>
            </div>
            
            <!-- 工具卡片 -->
            <div class="config-card">
                <div class="config-card-title" data-i18n="common.tools">🔧 Tools</div>
                <div class="config-card-row">
                    <span class="config-card-label" data-i18n="system.clash.title">Clash Proxy</span>
                    <button class="config-card-btn" onclick="closeConfigModal(); setTimeout(openClashModal, 300);" data-i18n="common.settings">Settings</button>
                </div>
                <div class="config-card-row">
                    <span class="config-card-label" data-i18n="tools.email_config">Email Config</span>
                    <button class="config-card-btn" onclick="window.open('/email-config', '_blank')" data-i18n="common.manage">Manage</button>
                </div>
                <div class="config-card-row">
                    <span class="config-card-label" data-i18n="model_config.title">AI Model Config</span>
                    <button class="config-card-btn" onclick="window.open('/ai/model-config', '_blank')" data-i18n="common.manage">Manage</button>
                </div>
            </div>
            
            <!-- 账户卡片 -->
            <div class="config-card">
                <div class="config-card-title" data-i18n="account.title">👤 Account</div>
                <div class="config-card-row">
                    <span class="config-card-label" data-i18n="account.logout_label">Logout</span>
                    <button class="config-card-btn config-card-btn-danger" onclick="logoutAuth()" data-i18n="account.logout_action">Logout</button>
                </div>
            </div>
        </div>
    </div>

    <!-- 搜索模态框 -->
    <div id="searchBackdrop" class="drawer-backdrop" onclick="closeSearchModal()"></div>
    <div id="searchModal" class="drawer">
        <div class="drawer-handle"></div>
        <div class="drawer-header">
            <div class="drawer-title" data-i18n="fileBrowser.search_files_title">🔍 Search Files</div>
            <div style="display:flex;gap:8px;">
                <button style="background:none;border:none;font-size:18px;cursor:pointer;padding:4px;" onclick="resetSearch()" title="Reset" data-i18n-title="common.reset">🔄</button>
                <button class="drawer-close-btn" onclick="closeSearchModal()">&times;</button>
            </div>
        </div>
        <div class="drawer-content" style="padding:0;">
            <div style="padding: 16px;">
                <div style="display: flex; gap: 10px; margin-bottom: 16px;">
                    <input type="text" id="searchInput" style="flex: 1; padding: 12px; border: 1px solid #ddd; border-radius: 8px; font-size: var(--global-font-size, 14px);" placeholder="Search by filename..." data-i18n-placeholder="fileBrowser.search_placeholder" onkeyup="handleSearchKeyup(event)">
                    <button class="modal-btn modal-btn-confirm" style="padding: 12px 20px;" onclick="doSearch()" data-i18n="fileBrowser.search">Search</button>
                </div>
                <div id="searchResults" style="overflow-y: auto;"></div>
            </div>
        </div>
    </div>

    <!-- 回收站抽屉 -->
    <div id="trashBackdrop" class="drawer-backdrop" onclick="closeTrashDrawer()"></div>
    <div id="trashDrawer" class="drawer">
        <div class="drawer-handle"></div>
        <div class="drawer-header">
            <div class="drawer-title" data-i18n="trash.drawer_title">🗑️ Trash</div>
            <div style="display:flex;gap:8px;">
                <button style="background:none;border:none;font-size:18px;cursor:pointer;padding:4px;" onclick="loadTrashList()" title="Refresh" data-i18n-title="common.refresh">🔄</button>
                <button style="background:none;border:none;font-size:18px;cursor:pointer;padding:4px;" onclick="clearTrash()" title="Clear" data-i18n-title="common.clear">🧹</button>
                <button class="drawer-close-btn" onclick="closeTrashDrawer()">&times;</button>
            </div>
        </div>
        <div class="drawer-content" style="padding:0;">
            <div id="trashListContainer" style="padding: 16px;"></div>
        </div>
    </div>
    <!-- 进程管理抽屉 -->
    <div id="processBackdrop" class="drawer-backdrop" onclick="closeProcessModal()"></div>
    <div id="processModal" class="drawer">
        <div class="drawer-handle"></div>
        <div class="drawer-header">
            <div class="drawer-title" data-i18n="system.process.title">Process Management</div>
            <button class="drawer-close-btn" onclick="closeProcessModal()">&times;</button>
        </div>
        <div class="drawer-content" style="padding:0;display:flex;flex-direction:column;max-height:calc(85vh - 60px);">
            <div id="processListContainer" style="flex:1;overflow:auto;"></div>
        </div>
    </div>

    <!-- 进程详情抽屉 -->
    <div id="processDetailBackdrop" class="drawer-backdrop" onclick="Drawer.close('processDetailModal')"></div>
    <div id="processDetailModal" class="drawer">
        <div class="drawer-handle"></div>
        <div class="drawer-header">
            <div class="drawer-title" data-i18n="system.process.detail_title">Process Details</div>
            <button class="drawer-close-btn" onclick="Drawer.close('processDetailModal')">&times;</button>
        </div>
        <div class="drawer-content" style="padding:0;">
            <div id="processDetailContent" style="padding:16px;"></div>
        </div>
    </div>

    <!-- 系统包管理抽屉 -->
    <div id="systemPackageBackdrop" class="drawer-backdrop" onclick="closeSystemPackageModal()"></div>
    <div id="systemPackageModal" class="drawer">
        <div class="drawer-handle"></div>
        <div class="drawer-header">
            <div class="drawer-title" data-i18n="system.package.system_packages">System Packages</div>
            <div style="display:flex;gap:8px;">
                <button style="background:none;border:none;font-size:18px;cursor:pointer;padding:4px;" onclick="loadSystemPackageList()" title="Refresh" data-i18n-title="common.refresh">🔄</button>
                <button class="drawer-close-btn" onclick="closeSystemPackageModal()">&times;</button>
            </div>
        </div>
        <div class="drawer-content" style="padding:0;">
            <div id="systemPackageListContainer" style="padding: 16px;"></div>
        </div>
    </div>

    <!-- Pip 包管理抽屉 -->
    <div id="pipBackdrop" class="drawer-backdrop" onclick="closePipModal()"></div>
    <div id="pipModal" class="drawer">
        <div class="drawer-handle"></div>
        <div class="drawer-header">
            <div class="drawer-title" data-i18n="system.package.pip_packages">Pip Packages</div>
            <div style="display:flex;gap:8px;">
                <button style="background:none;border:none;font-size:18px;cursor:pointer;padding:4px;" onclick="loadPipList()" title="Refresh" data-i18n-title="common.refresh">🔄</button>
                <button class="drawer-close-btn" onclick="closePipModal()">&times;</button>
            </div>
        </div>
        <div class="drawer-content" style="padding:0;">
            <div id="pipListContainer" style="padding: 16px;"></div>
        </div>
    </div>

    <!-- NPM 包管理抽屉 -->
    <div id="npmBackdrop" class="drawer-backdrop" onclick="closeNpmModal()"></div>
    <div id="npmModal" class="drawer">
        <div class="drawer-handle"></div>
        <div class="drawer-header">
            <div class="drawer-title" data-i18n="system.package.npm_packages">NPM Packages</div>
            <div style="display:flex;gap:8px;">
                <button style="background:none;border:none;font-size:18px;cursor:pointer;padding:4px;" onclick="loadNpmList()" title="Refresh" data-i18n-title="common.refresh">🔄</button>
                <button class="drawer-close-btn" onclick="closeNpmModal()">&times;</button>
            </div>
        </div>
        <div class="drawer-content" style="padding:0;">
            <div id="npmListContainer" style="padding: 16px;"></div>
        </div>
    </div>

    <!-- Docker 管理抽屉 -->
    <div id="dockerBackdrop" class="drawer-backdrop" onclick="closeDockerModal()"></div>
    <div id="dockerModal" class="drawer">
        <div class="drawer-handle"></div>
        <div class="drawer-header">
            <div class="drawer-title" data-i18n="system.docker.title">Docker</div>
            <div style="display:flex;gap:8px;">
                <button style="background:none;border:none;font-size:18px;cursor:pointer;padding:4px;" onclick="loadDockerTabs('images')" title="Refresh" data-i18n-title="common.refresh">🔄</button>
                <button class="drawer-close-btn" onclick="closeDockerModal()">&times;</button>
            </div>
        </div>
        <div class="drawer-content" style="padding:0;">
            <div style="display: flex; border-bottom: 1px solid #d0d7de;">
                <button class="docker-tab active" data-tab="images" onclick="loadDockerTabs('images')" style="flex: 1; padding: 12px; background: none; border: none; cursor: pointer; font-size: 14px; border-bottom: 2px solid transparent;" data-i18n="system.docker.images">Images</button>
                <button class="docker-tab" data-tab="containers" onclick="loadDockerTabs('containers')" style="flex: 1; padding: 12px; background: none; border: none; cursor: pointer; font-size: 14px; border-bottom: 2px solid transparent;" data-i18n="system.docker.containers">Containers</button>
            </div>
            <div id="dockerImagesContainer" style="padding: 16px;"></div>
            <div id="dockerContainersContainer" style="padding: 16px; display: none;"></div>
        </div>
    </div>

    <!-- Systemd 服务管理抽屉 -->
    <div id="systemdBackdrop" class="drawer-backdrop" onclick="closeSystemdModal()"></div>
    <div id="systemdModal" class="drawer">
        <div class="drawer-handle"></div>
        <div class="drawer-header">
            <div class="drawer-title" data-i18n="system.systemd.title">Systemd Management</div>
            <div style="display:flex;gap:8px;">
                <button style="background:none;border:none;font-size:18px;cursor:pointer;padding:4px;" onclick="loadSystemdList()" title="Refresh" data-i18n-title="common.refresh">🔄</button>
                <button class="drawer-close-btn" onclick="closeSystemdModal()">&times;</button>
            </div>
        </div>
        <div class="drawer-header" style="border-bottom:1px solid #d0d7de;padding:8px 16px;background:#f6f8fa;">
            <div style="display:flex;gap:8px;align-items:center;">
                <button id="systemdTabUser" onclick="switchSystemdTab('user')" style="padding:6px 14px;border:1px solid #d0d7de;border-radius:6px;background:#fff;cursor:pointer;font-size:13px;">User (<span id="systemdUserCount">-</span>)</button>
                <button id="systemdTabSystem" onclick="switchSystemdTab('system')" style="padding:6px 14px;border:1px solid #d0d7de;border-radius:6px;background:#f6f8fa;cursor:pointer;font-size:13px;">System (<span id="systemdSystemCount">-</span>)</button>
            </div>
            <input type="text" id="systemdSearch" oninput="filterSystemdServices()" placeholder="Search services..." data-i18n-placeholder="systemd.search_placeholder" style="padding:6px 10px;border:1px solid #d0d7de;border-radius:6px;font-size:13px;width:150px;">
        </div>
        <div class="drawer-content" style="padding:0;">
            <div id="systemdListContainer" style="padding: 16px;"></div>
        </div>
    </div>

    <!-- 磁盘管理抽屉 -->
    <div id="diskBackdrop" class="drawer-backdrop" onclick="closeDiskModal()"></div>
    <div id="diskModal" class="drawer">
        <div class="drawer-handle"></div>
        <div class="drawer-header">
            <div class="drawer-title" data-i18n="system.disk.title">Disk Management</div>
            <div style="display:flex;gap:8px;">
                <button style="background:none;border:none;font-size:18px;cursor:pointer;padding:4px;" onclick="loadDiskList()" title="Refresh" data-i18n-title="common.refresh">🔄</button>
                <button class="drawer-close-btn" onclick="closeDiskModal()">&times;</button>
            </div>
        </div>
        <div class="drawer-content" style="padding:0;">
            <div id="diskListContainer" style="padding: 16px;"></div>
        </div>
    </div>

    <!-- 网络管理抽屉 -->
    <div id="networkBackdrop" class="drawer-backdrop" onclick="closeNetworkModal()"></div>
    <div id="networkModal" class="drawer">
        <div class="drawer-handle"></div>
        <div class="drawer-header">
            <div class="drawer-title" data-i18n="system.network.title">Network Management</div>
            <div style="display:flex;gap:8px;">
                <button style="background:none;border:none;font-size:18px;cursor:pointer;padding:4px;" onclick="loadNetworkList()" title="Refresh" data-i18n-title="common.refresh">🔄</button>
                <button class="drawer-close-btn" onclick="closeNetworkModal()">&times;</button>
            </div>
        </div>
        <div class="drawer-content" style="padding:0;">
            <div id="networkListContainer" style="padding: 16px;"></div>
        </div>
    </div>

    <!-- Git管理抽屉 -->
    <div id="gitBackdrop" class="drawer-backdrop" onclick="closeGitModal()"></div>
    <div id="gitModal" class="drawer">
        <div class="drawer-handle"></div>
        <div class="drawer-header">
            <div class="drawer-title" id="gitDrawerTitle" data-i18n="git.title">Git Manager</div>
            <div style="display:flex;gap:8px;">
                <button id="gitRefreshBtn" style="background:none;border:none;width:32px;height:32px;cursor:pointer;display:flex;align-items:center;justify-content:center;" onclick="toggleGitAutoRefresh()" title="Auto refresh" data-i18n-title="git.auto_refresh">
                    <svg id="gitRefreshIcon" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                        <path d="M23 4v6h-6M1 20v-6h6" />
                        <path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15" />
                    </svg>
                </button>
                <button class="drawer-close-btn" onclick="closeGitModal()">&times;</button>
            </div>
        </div>
        <div class="drawer-content" style="padding:0;">
            <div id="gitListContainer" style="padding: 16px;"></div>
        </div>
    </div>

    <!-- 刷新按钮动画样式 -->
    <style>
    @keyframes git-rotate {
        from { transform: rotate(0deg); }
        to { transform: rotate(360deg); }
    }
    .git-spinning {
        animation: git-rotate 1.2s linear infinite;
    }
    </style>

    <!-- Git Commit详情抽屉 -->
    <div id="gitCommitBackdrop" class="drawer-backdrop" onclick="closeGitCommitModal()"></div>
    <div id="gitCommitModal" class="drawer">
        <div class="drawer-handle"></div>
        <div class="drawer-header">
            <div class="drawer-title" data-i18n="git.commit_detail_title">📝 Commit Details</div>
            <div style="display:flex;gap:8px;">
                <button style="background:none;border:none;font-size:16px;cursor:pointer;padding:4px;" onclick="loadGitCommitDetail()" title="Refresh" data-i18n-title="common.refresh">🔄</button>
                <button class="drawer-close-btn" onclick="closeGitCommitModal()">&times;</button>
            </div>
        </div>
        <div class="drawer-content" style="padding:0;">
            <div id="gitCommitContent" style="padding: 16px;"></div>
        </div>
    </div>

    <!-- GPU显卡抽屉 -->
    <div id="gpuBackdrop" class="drawer-backdrop" onclick="closeGpuModal()"></div>
    <div id="gpuModal" class="drawer">
        <div class="drawer-handle"></div>
        <div class="drawer-header">
            <div class="drawer-title" data-i18n="system.gpu.title">GPU Management</div>
            <div style="display:flex;gap:8px;">
                <button style="background:none;border:none;font-size:18px;cursor:pointer;padding:4px;" onclick="loadGpuInfo()" title="Refresh" data-i18n-title="common.refresh">🔄</button>
                <button class="drawer-close-btn" onclick="closeGpuModal()">&times;</button>
            </div>
        </div>
        <div class="drawer-content" style="padding:0;">
            <div id="gpuInfoContainer" style="padding: 16px;"></div>
        </div>
    </div>

    <!-- Ollama模型抽屉 -->
    <div id="ollamaBackdrop" class="drawer-backdrop" onclick="closeOllamaModal()"></div>
    <div id="ollamaModal" class="drawer">
        <div class="drawer-handle"></div>
        <div class="drawer-header">
            <div class="drawer-title" data-i18n="system.ollama.title">Ollama</div>
            <div style="display:flex;gap:8px;">
                <button id="ollamaInstallBtn" style="display:none;background:#2da44e;border:none;border-radius:6px;color:#fff;padding:6px 10px;cursor:pointer;font-size:13px;" onclick="serviceInstallAction('ollama','install')" data-i18n="common.install">Install</button>
                <button id="ollamaReinstallBtn" style="display:none;background:#0969da;border:none;border-radius:6px;color:#fff;padding:6px 10px;cursor:pointer;font-size:13px;" onclick="serviceInstallAction('ollama','reinstall')" data-i18n="common.reinstall">Reinstall</button>
                <button id="ollamaUninstallBtn" style="display:none;background:#cf222e;border:none;border-radius:6px;color:#fff;padding:6px 10px;cursor:pointer;font-size:13px;" onclick="serviceInstallAction('ollama','uninstall')" data-i18n="common.uninstall">Uninstall</button>
                <button style="background:none;border:none;font-size:18px;cursor:pointer;padding:4px;" onclick="loadOllamaModels()" title="Refresh" data-i18n-title="common.refresh">🔄</button>
                <button class="drawer-close-btn" onclick="closeOllamaModal()">&times;</button>
            </div>
        </div>
        <div class="drawer-content" style="padding:0;">
            <div id="ollamaModelsContainer" style="padding: 16px;"></div>
        </div>
    </div>

    <!-- OpenClaw配置抽屉 -->
    <div id="openclawBackdrop" class="drawer-backdrop" onclick="closeOpenclawModal()"></div>
    <div id="openclawModal" class="drawer">
        <div class="drawer-handle"></div>
        <div class="drawer-header">
            <div class="drawer-title" data-i18n="openclaw.config_title">⚙️ OpenClaw Settings</div>
            <div style="display:flex;gap:8px;">
                <button class="drawer-close-btn" onclick="closeOpenclawModal()">&times;</button>
            </div>
        </div>
        <div class="drawer-content" style="padding:0;">
            <div id="openclawConfigContainer" style="padding: 16px;"></div>
        </div>
    </div>

    <!-- Clash代理抽屉 -->
    <div id="clashBackdrop" class="drawer-backdrop" onclick="closeClashModal()"></div>
    <div id="clashModal" class="drawer">
        <div class="drawer-handle"></div>
        <div class="drawer-header">
            <div class="drawer-title" data-i18n="system.clash.title">Clash Proxy</div>
            <div style="display:flex;gap:8px;">
                <button id="clashInstallBtn" style="display:none;background:#2da44e;border:none;border-radius:6px;color:#fff;padding:6px 10px;cursor:pointer;font-size:13px;" onclick="serviceInstallAction('clash','install')" data-i18n="common.install">Install</button>
                <button id="clashReinstallBtn" style="display:none;background:#0969da;border:none;border-radius:6px;color:#fff;padding:6px 10px;cursor:pointer;font-size:13px;" onclick="serviceInstallAction('clash','reinstall')" data-i18n="common.reinstall">Reinstall</button>
                <button id="clashUninstallBtn" style="display:none;background:#cf222e;border:none;border-radius:6px;color:#fff;padding:6px 10px;cursor:pointer;font-size:13px;" onclick="serviceInstallAction('clash','uninstall')" data-i18n="common.uninstall">Uninstall</button>
                <button style="background:none;border:none;font-size:18px;cursor:pointer;padding:4px;" onclick="loadClashConfigEnhanced()" title="Refresh" data-i18n-title="common.refresh">🔄</button>
                <button class="drawer-close-btn" onclick="closeClashModal()">&times;</button>
            </div>
        </div>
        <div class="drawer-content" style="padding:0;">
            <div id="clashContainer" style="padding: 16px;"></div>
        </div>
    </div>

    <!-- FRP管理抽屉 -->
    <div id="frpBackdrop" class="drawer-backdrop" onclick="closeFrpModal()"></div>
    <div id="frpModal" class="drawer">
        <div class="drawer-handle"></div>
        <div class="drawer-header">
            <div class="drawer-title" data-i18n="system.frp.title">FRP Tunnel</div>
            <div style="display:flex;gap:8px;">
                <button id="frpInstallBtn" style="display:none;background:#2da44e;border:none;border-radius:6px;color:#fff;padding:6px 10px;cursor:pointer;font-size:13px;" onclick="serviceInstallAction('frp','install')" data-i18n="common.install">Install</button>
                <button id="frpReinstallBtn" style="display:none;background:#0969da;border:none;border-radius:6px;color:#fff;padding:6px 10px;cursor:pointer;font-size:13px;" onclick="serviceInstallAction('frp','reinstall')" data-i18n="common.reinstall">Reinstall</button>
                <button id="frpUninstallBtn" style="display:none;background:#cf222e;border:none;border-radius:6px;color:#fff;padding:6px 10px;cursor:pointer;font-size:13px;" onclick="serviceInstallAction('frp','uninstall')" data-i18n="common.uninstall">Uninstall</button>
                <button style="background:none;border:none;font-size:18px;cursor:pointer;padding:4px;" onclick="loadFrpConfig()" title="Refresh" data-i18n-title="common.refresh">🔄</button>
                <button class="drawer-close-btn" onclick="closeFrpModal()">&times;</button>
            </div>
        </div>
        <div class="drawer-content" style="padding:0;">
            <div id="frpContainer" style="padding: 16px;"></div>
        </div>
    </div>

        <!-- 批量操作抽屉 (无遮罩) -->
    <div id="batchDrawer" class="drawer" style="box-shadow: 0 -4px 20px rgba(0,0,0,0.15); height:auto; min-height:0;">
        <div class="drawer-handle" style="display:none;"></div>
        <div class="drawer-header" style="padding:8px 12px;">
            <div class="drawer-title" style="display:flex;align-items:center;font-size:13px;">
                <input type="checkbox" id="batchSelectAll" onchange="toggleSelectAll(this)" style="margin-right:8px;">
                <span id="batchCount">Selected 0 items</span>
            </div>
            <button class="drawer-close-btn" onclick="clearSelection()" style="padding:4px 8px;font-size:16px;">&times;</button>
        </div>
        <div class="drawer-content" style="padding:0 8px 8px 0;">
            <div style="display:grid; grid-template-columns: repeat(5, 1fr); gap:6px;">
                <div class="modal-item" onclick="batchArchive()" style="display:flex; flex-direction:column; align-items:center; justify-content:center; padding:8px 4px; border:1px solid #eee; border-radius:6px; cursor:pointer;">
                    <span style="font-size:18px;">🗜️</span>
                    <span style="font-size:11px;margin-top:2px;" data-i18n="file_menu.compress">Compress</span>
                </div>
                <div class="modal-item" onclick="batchMove()" style="display:flex; flex-direction:column; align-items:center; justify-content:center; padding:8px 4px; border:1px solid #eee; border-radius:6px; cursor:pointer;">
                    <span style="font-size:18px;">📁</span>
                    <span style="font-size:11px;margin-top:2px;" data-i18n="file_menu.move">Move</span>
                </div>
                <div class="modal-item" onclick="batchCopy()" style="display:flex; flex-direction:column; align-items:center; justify-content:center; padding:8px 4px; border:1px solid #eee; border-radius:6px; cursor:pointer;">
                    <span style="font-size:18px;">📋</span>
                    <span style="font-size:11px;margin-top:2px;" data-i18n="file_menu.copy">Copy</span>
                </div>
                <div class="modal-item delete-item" onclick="batchDelete()" style="display:flex; flex-direction:column; align-items:center; justify-content:center; padding:8px 4px; border:1px solid #eee; border-radius:6px; color:#cf222e; cursor:pointer;">
                    <span style="font-size:18px;">🗑️</span>
                    <span style="font-size:11px;margin-top:2px;" data-i18n="file_menu.delete">Delete</span>
                </div>
                <div class="modal-item" onclick="clearSelection()" style="display:flex; flex-direction:column; align-items:center; justify-content:center; padding:8px 4px; border:1px solid #eee; border-radius:6px; cursor:pointer;">
                    <span style="font-size:18px;">✖</span>
                    <span style="font-size:11px;margin-top:2px;" data-i18n="common.cancel">Cancel</span>
                </div>
            </div>
        </div>
    </div>

    <div id="clipboardBar" class="clipboard-bar" role="region" aria-label="Clipboard Operations" data-i18n-aria-label="clipboard.title" aria-hidden="true" style="display:none;">
        <button id="clipboardPasteBtn" type="button" class="clipboard-paste-btn" aria-label="Paste here" data-i18n-aria-label="clipboard.paste_here">
            <span id="clipboardLabel" aria-live="polite"></span>
        </button>
        <button id="clipboardCancelBtn" type="button" class="clipboard-cancel-btn" aria-label="Cancel clipboard operation" data-i18n-aria-label="clipboard.cancel_operation">×</button>
    </div>

    <!-- Toast 通知容器 -->
    <div id="toastContainer" class="toast-container"></div>

    <!-- 目标位置选择抽屉 -->
    <div id="targetBackdrop" class="drawer-backdrop" onclick="closeTargetModal()"></div>
    <div id="targetModal" class="drawer">
        <div class="drawer-handle"></div>
        <div class="drawer-header">
            <div class="drawer-title" id="targetModalTitle" data-i18n="move.select_target_title">Select Target</div>
            <button class="drawer-close-btn" onclick="closeTargetModal()">&times;</button>
        </div>
        <div class="drawer-content">
            <input type="text" id="targetPathInput" style="width: 100%; padding: 12px; margin-bottom: 12px; border: 1px solid #ddd; border-radius: 8px; font-size: var(--global-font-size, 14px); box-sizing: border-box;" placeholder="e.g., docs/new-folder" data-i18n-placeholder="move.placeholder">
            <p style="font-size: var(--global-font-size, 12px); color: #666; margin: 0 0 16px 0;" data-i18n="move.relative_to_root_hint">Relative to root directory</p>
            <div class="modal-buttons" style="padding: 0; border: none; background: none; gap: 12px;">
                <button class="modal-btn modal-btn-cancel" style="flex: 1; padding: 12px; border-radius: 8px;" onclick="closeTargetModal()" data-i18n="common.cancel">Cancel</button>
                <button class="modal-btn modal-btn-confirm" style="flex: 1; padding: 12px; border-radius: 8px;" onclick="confirmTargetPath()" data-i18n="common.confirm">Confirm</button>
            </div>
        </div>
    </div>

    <script>
        (function() {
            function getQueryParam(name) {
                try {
                    var url = new URL(window.location.href);
                    return url.searchParams.get(name) || '';
                } catch (e) {
                    return '';
                }
            }

            function parsePortDirName(name) {
                var m = String(name || '').match(/^([0-9]{4})_/);
                return m ? m[1] : '';
            }

            var browseAppEl = document.getElementById('browseApp');
            if (!browseAppEl || !window.Vue || !window.Vue.createApp) { return; }

            window.Vue.createApp({
                data: function() {
                    return {
                        items: [],
                        breadcrumbs: [],
                        currentDir: '',
                        currentDirName: '',
                        message: getQueryParam('message'),
                        messageType: getQueryParam('msg_type') || 'success',
                        loading: true,
                        i18nLang: (function() { try { return localStorage.getItem('clawos_lang') || 'zh'; } catch (e) { return 'zh'; } })(),
                    };
                },
                computed: {
                    messageTypeClass: function() {
                        return this.messageType === 'success' ? 'success' : 'error';
                    }
                },
                methods: {
                    t: function(key) {
                        var _ = this.i18nLang;
                        if (typeof window.I18n !== 'undefined' && typeof window.I18n.t === 'function') {
                            return window.I18n.t(key);
                        }
                        return key;
                    },
                    browseHref: function(relPath) {
                        if (!relPath) { return '/browse/'; }
                        if (typeof window.encodePathForUrl === 'function') {
                            return '/browse/' + window.encodePathForUrl(relPath);
                        }
                        return '/browse/' + encodeURIComponent(relPath);
                    },
                    onBreadcrumbClick: function(relPath, ev) {
                        if (!window.BrowseNavigator || typeof window.BrowseNavigator.navigateTo !== 'function') { return; }
                        if (!window.BrowseNavigator.shouldInterceptClick || !window.BrowseNavigator.shouldInterceptClick(ev)) { return; }
                        if (ev && typeof ev.preventDefault === 'function') ev.preventDefault();
                        window.BrowseNavigator.navigateTo(relPath || '', { replace: false });
                    },
                    thumbUrl: function(relPath) {
                        if (!relPath) { return ''; }
                        if (typeof window.encodePathForUrl === 'function') {
                            return '/thumbnail/' + window.encodePathForUrl(relPath);
                        }
                        return '/thumbnail/' + encodeURIComponent(relPath);
                    },
                    isPortDir: function(item) {
                        return !!(item && item.is_dir && parsePortDirName(item.name));
                    },
                    portHref: function(name) {
                        var port = parsePortDirName(name);
                        if (!port) { return '#'; }
                        return 'http://' + window.location.hostname + ':' + port;
                    },
                    openMenu: function(item) {
                        if (typeof window.showFileSmallMenu !== 'function') { return; }
                        var btn = document.querySelector('#file-item-' + (this.items.indexOf(item) + 1) + ' .menu-btn');
                        window.showFileSmallMenu(item.path || '', item.name || '', !!item.is_dir, btn);
                    },
                    onToggleItemSelection: function(path, event) {
                        if (typeof window.toggleItemSelection !== 'function') { return; }
                        window.toggleItemSelection(path || '', event && event.target);
                    },
                    applyBootstrap: function(data) {
                        console.log('[load] items:', data.items ? data.items.slice(0,3) : 'none');
                        this.items = Array.isArray(data.items) ? data.items : [];
                        this.breadcrumbs = Array.isArray(data.breadcrumbs) ? data.breadcrumbs : [];
                        this.currentDir = typeof data.current_dir === 'string' ? data.current_dir : '';
                        this.currentDirName = typeof data.current_dir_name === 'string' ? data.current_dir_name : '';

                        var pathEl = document.getElementById('currentBrowsePath');
                        if (pathEl) { pathEl.value = this.currentDir || ''; }
                        var nameEl = document.getElementById('currentBrowseName');
                        if (nameEl) { nameEl.value = this.currentDirName || ''; }
                        var rootEl = document.getElementById('rootDir');
                        if (rootEl && typeof data.root_dir === 'string') { rootEl.value = data.root_dir; }

                        // 滚动面包屑到最右边
                        var crumbLeft = document.querySelector('.breadcrumb-left');
                        if (crumbLeft) {
                            setTimeout(function() {
                                crumbLeft.scrollLeft = crumbLeft.scrollWidth;
                            }, 50);
                        }

                        if (typeof data.server_is_windows === 'boolean') {
                            window.SERVER_IS_WINDOWS = data.server_is_windows;
                        }
                        window.__INITIAL_PIN_DIR__ = typeof data.pin_dir === 'string' ? data.pin_dir : '';
                        window.__INITIAL_PINS__ = Array.isArray(data.pins) ? data.pins : [];
                        window.__INITIAL_GIT_STATUS__ = data.git_status || null;
                    },
                    refreshItems: function() {
                        var _this = this;
                        var path = this.currentDir || '';
                        fetch('/api/browse/files?path=' + encodeURIComponent(path), {
                            credentials: 'same-origin',
                            headers: Object.assign({ 'Accept': 'application/json' }, (window.authHeaders || {})),
                        })
                        .then(function(r) { return r.json(); })
                        .then(function(d) {
                            if (d && d.success && d.data && Array.isArray(d.data.items)) {
                                _this.items.splice(0, _this.items.length);
                                _this.items.push.apply(_this.items, d.data.items);
                                _this.$forceUpdate();
                                setTimeout(function() {
                                    if (typeof window.attachFileItemDefaultHandlers === 'function') {
                                        window.attachFileItemDefaultHandlers();
                                    }
                                }, 50);
                            }
                        })
                        .catch(function(e) { console.error('refreshItems error:', e); });
                    },
                    postRenderInit: function() {
                        // 滚动面包屑到最右边
                        var crumbLeft = document.querySelector('.breadcrumb-left');
                        if (crumbLeft) {
                            crumbLeft.scrollLeft = crumbLeft.scrollWidth;
                        }
                        if (typeof window.attachFileItemDefaultHandlers === 'function') {
                            window.attachFileItemDefaultHandlers();
                        }
                        if (typeof window.initPinsForCurrentDir === 'function') {
                            window.initPinsForCurrentDir();
                        }
                        if (typeof window.initDragUploadAndPaste === 'function') {
                            window.initDragUploadAndPaste();
                        }
                        if (typeof window.loadGitStatusBar === 'function') {
                            window.loadGitStatusBar();
                        }
                    },
                    loadState: function() {
                        var rel = '';
                        try {
                            var p = window.location.pathname || '';
                            if (p === '/' || p === '/browse' || p === '/browse/') {
                                rel = '';
                            } else if (p.indexOf('/browse/') === 0) {
                                rel = decodeURIComponent(p.slice('/browse/'.length));
                            }
                        } catch (e) {
                            rel = '';
                        }

                        if (window.BrowseNavigator && typeof window.BrowseNavigator.syncFromLocation === 'function') {
                            window.BrowseNavigator.syncFromLocation({ replace: true });
                            return;
                        }

                        fetch('/api/browse/state?path=' + encodeURIComponent(rel), {
                            credentials: 'same-origin',
                            headers: Object.assign({ 'Accept': 'application/json' }, (window.authHeaders || {})),
                        })
                            .then(function(r) { return r.json(); })
                            .then((function(d) {
                                if (d && d.success && d.data) {
                                    this.applyBootstrap(d.data);
                                    this.$nextTick(this.postRenderInit);
                                    return;
                                }
                                var msg = (d && d.error && d.error.message) ? d.error.message : (typeof I18n !== 'undefined' ? I18n.t('common.load_failed') : 'Load failed');
                                this.messageType = 'error';
                                this.message = msg;
                                this.items = [];
                                this.breadcrumbs = [];
                                this.$nextTick(this.postRenderInit);
                            }).bind(this))
                            .catch((function() {
                                this.messageType = 'error';
                                this.message = (typeof I18n !== 'undefined' ? I18n.t('common.load_failed') : 'Load failed');
                                this.items = [];
                                this.breadcrumbs = [];
                            }).bind(this))
                            .finally((function() {
                                this.loading = false;
                            }).bind(this));
                    },
                    _statusTimer: null,
                    _initStatusBar: function() {
                        var _this = this;
                        // 获取用户名和 hostname
                        var hostname = '';
                        Promise.all([
                            fetch('/api/users/me', { headers: authHeaders() }).then(r => r.json()),
                            fetch('/api/system/status', { headers: authHeaders() }).then(r => r.json())
                        ]).then(function(results) {
                            var userData = results[0];
                            var statusData = results[1];
                            var userEl = document.getElementById('statusUser');
                            if (userEl && userData?.success && userData?.data?.name) {
                                hostname = statusData?.data?.hostname || '';
                                userEl.textContent = userData.data.name + '@' + hostname;
                            }
                        }).catch(function() {});
                        
                        _this._updateStatusBar();
                        _this._statusTimer = setInterval(function() {
                            _this._updateStatusBar();
                        }, 3000);
                    },
                    _updateStatusBar: function() {
                        var _this = this;
                        fetch('/api/system/status', { headers: authHeaders() })
                            .then(function(r) { return r.json(); })
                            .then(function(d) {
                                if (!d || !d.success) return;
                                var s = d.data || {};
                                
                                function colorClass(pct) {
                                    if (pct >= 80) return 'danger';
                                    if (pct >= 50) return 'warning';
                                    return 'normal';
                                }
                                
                                var cpu = document.getElementById('statusCpu');
                                if (cpu) { cpu.textContent = s.cpu ? Math.round(s.cpu) : 0; cpu.className = 'value ' + colorClass(s.cpu); }
                                
                                var mem = document.getElementById('statusMemory');
                                if (mem) { mem.textContent = s.memory_percent ? Math.round(s.memory_percent) : 0; mem.className = 'value ' + colorClass(s.memory_percent); }
                                
                                var disk = document.getElementById('statusDisk');
                                if (disk) { disk.textContent = s.disk_percent ? Math.round(s.disk_percent) : 0; disk.className = 'value ' + colorClass(s.disk_percent); }
                                
                                var gpu = document.getElementById('statusGpu');
                                if (gpu) { gpu.textContent = s.gpu_utilization || 0; gpu.className = 'value ' + colorClass(s.gpu_utilization); }
                                
                                var vram = document.getElementById('statusVram');
                                if (vram) { vram.textContent = s.gpu_memory_percent ? Math.round(s.gpu_memory_percent) : 0; vram.className = 'value ' + colorClass(s.gpu_memory_percent); }
                                
                                var power = document.getElementById('statusPower');
                                if (power) power.textContent = s.gpu_power || 0;
                                
                                document.getElementById('statusNetworkUp').textContent = s.network_rx || 0;
                                document.getElementById('statusNetworkDown').textContent = s.network_tx || 0;
                            })
                            .catch(function() {});
                    }
                },

                mounted: function() {
                    var app = this;
                    // 保存 Vue 组件引用供全局 refreshFileList 使用
                    window.__browseVueApp__ = app;

                    document.addEventListener('i18n:languageChanged', function(e) {
                        if (e && e.detail && e.detail.lang) {
                            app.i18nLang = e.detail.lang;
                        }
                    });
                    
                    var nav = {
                        __abort: null,
                        __seq: 0,
                        __mounted: false,
                        __loadedOnce: false,
                        __app: app,
                        __parsePath: function() {
                            var rel = '';
                            try {
                                var p = window.location.pathname || '';
                                if (p === '/' || p === '/browse' || p === '/browse/') {
                                    rel = '';
                                } else if (p.indexOf('/browse/') === 0) {
                                    rel = decodeURIComponent(p.slice('/browse/'.length));
                                }
                            } catch (e) {
                                rel = '';
                            }
                            return rel;
                        },
                        __href: function(relPath) {
                            if (!relPath) { return '/browse/'; }
                            if (typeof window.encodePathForUrl === 'function') {
                                return '/browse/' + window.encodePathForUrl(relPath);
                            }
                            return '/browse/' + encodeURIComponent(relPath);
                        },
                        __samePath: function(a, b) {
                            return String(a || '').replace(/\\/g, '/') === String(b || '').replace(/\\/g, '/');
                        },
                        navigateTo: function(relPath, opts) {
                            opts = opts || {};
                            var target = String(relPath || '');

                            if (this.__loadedOnce && this.__app && this.__samePath(this.__app.currentDir, target)) {
                                if (opts.replace) {
                                    try { history.replaceState({ path: target }, '', this.__href(target)); } catch (e) {}
                                }
                                return;
                            }

                            if (this.__abort) {
                                try { this.__abort.abort(); } catch (e) {}
                            }
                            this.__abort = new AbortController();
                            this.__seq += 1;
                            var seq = this.__seq;

                            this.__app.loading = true;
                            this.__app.message = '';

                            try {
                                if (opts.replace) {
                                    history.replaceState({ path: target }, '', this.__href(target));
                                } else {
                                    history.pushState({ path: target }, '', this.__href(target));
                                }
                            } catch (e) {}

                            fetch('/api/browse/state?path=' + encodeURIComponent(target), {
                                credentials: 'same-origin',
                                headers: Object.assign({ 'Accept': 'application/json' }, (window.authHeaders || {})),
                                signal: this.__abort.signal,
                            })
                                .then(function(r) { return r.json(); })
                                .then((function(d) {
                                    if (seq !== this.__seq) return;
                                    if (d && d.success && d.data) {
                                        this.__app.applyBootstrap(d.data);
                                        this.__loadedOnce = true;
                                        this.__app.$nextTick(this.__app.postRenderInit);
                                        try { window.scrollTo(0, 0); } catch (e) {}
                                        return;
                                    }
                                    var msg = (d && d.error && d.error.message) ? d.error.message : (typeof I18n !== 'undefined' ? I18n.t('common.load_failed') : 'Load failed');
                                    this.__app.messageType = 'error';
                                    this.__app.message = msg;
                                    this.__app.items = [];
                                    this.__app.breadcrumbs = [];
                                    this.__app.$nextTick(this.__app.postRenderInit);
                                }).bind(this))
                                .catch((function(err) {
                                    if (seq !== this.__seq) return;
                                    if (err && err.name === 'AbortError') return;
                                    this.__app.messageType = 'error';
                                    this.__app.message = (typeof I18n !== 'undefined' ? I18n.t('common.load_failed') : 'Load failed');
                                    this.__app.items = [];
                                    this.__app.breadcrumbs = [];
                                }).bind(this))
                                .finally((function() {
                                    if (seq !== this.__seq) return;
                                    this.__app.loading = false;
                                }).bind(this));
                        },
                        syncFromLocation: function(opts) {
                            opts = opts || {};
                            this.navigateTo(this.__parsePath(), { replace: !!opts.replace });
                        },
                        shouldInterceptClick: function(ev) {
                            if (!ev) return false;
                            if (ev.defaultPrevented) return false;
                            if (ev.button !== 0) return false;
                            if (ev.metaKey || ev.ctrlKey || ev.shiftKey || ev.altKey) return false;
                            return true;
                        }
                    };

                    window.BrowseNavigator = nav;
                    if (!nav.__mounted) {
                        nav.__mounted = true;
                        window.addEventListener('popstate', function() { nav.syncFromLocation({ replace: true }); });
                    }

                    app.loadState();
                    app._initStatusBar();
                }
            }).mount('#browseApp');
        })();
    </script>

    <!-- 底部 Dock -->
    <div class="dock">
        <button class="dock-btn" onclick="openMainMenuModal()" title="Menu" style="font-size:20px;" data-i18n-title="nav.menu">☰</button>
        <button class="dock-btn" onclick="handleMainMenu('bot')" title="Chat" data-i18n-title="nav.chat">🤖</button>
        <button class="dock-btn" onclick="handleMainMenu('terminal')" title="Terminal" data-i18n-title="nav.terminal">🖥️</button>
        <button class="dock-btn" onclick="window.open('/db/manager', '_blank')" title="Database" data-i18n-title="nav.database">🗄️</button>
        <button class="dock-btn" onclick="handleMainMenu('system')" title="Settings" data-i18n-title="nav.settings">⚙️</button>
    </div>
    
    <style>
        .dock {
            position: fixed;
            bottom: 8px;
            left: 50%;
            transform: translateX(-50%);
            display: flex;
            gap: 10px;
            padding: 10px 14px;
            background: rgba(255, 255, 255, 0.75);
            backdrop-filter: blur(16px) saturate(180%);
            -webkit-backdrop-filter: blur(16px) saturate(180%);
            border-radius: 24px;
            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
            border: 1px solid rgba(255, 255, 255, 0.3);
            z-index: 1000;
        }
        .dock-btn {
            width: 42px;
            height: 42px;
            border: none;
            border-radius: 12px;
            background: transparent;
            font-size: 20px;
            cursor: pointer;
            transition: all 0.2s ease;
        }
        .dock-btn:hover {
            background: rgba(0, 0, 0, 0.06);
            transform: translateY(-3px);
        }
        .dock-btn:active {
            transform: translateY(0) scale(0.94);
            background: rgba(0, 0, 0, 0.12);
        }
    </style>

    <script>
    // 页面加载后加载系统设置中的配置信息
    (function() {
        // 加载文件打开方式配置
        fetch('/api/file-open-config')
            .then(function(r) { return r.json(); })
            .then(function(d) {
                var el = document.getElementById('fileOpenConfigList');
                if (el && d.success && d.data) {
                    var html = '';
                    var keys = Object.keys(d.data).slice(0, 3);
                    for (var i = 0; i < keys.length; i++) {
                        var k = keys[i];
                        html += '<div style="padding:8px;background:#f6f8fa;border-radius:6px;margin-bottom:6px;font-size:13px;">';
                        html += '<span style="font-weight:600;">' + k + '</span>: ' + (d.data[k] || '默认');
                        html += '</div>';
                    }
                    if (keys.length > 3) {
                        html += '<div style="color:#666;font-size:12px;">... 共 ' + Object.keys(d.data).length + ' 项</div>';
                    }
                    el.innerHTML = html || '<div style="color:#666;font-size:13px;">暂无配置</div>';
                }
            })
            .catch(function() {
                var el = document.getElementById('fileOpenConfigList');
                if (el) el.innerHTML = '<div style="color:#666;font-size:13px;">加载失败</div>';
            });
        
        // 加载邮件配置状态
        fetch('/api/email/config')
            .then(function(r) { return r.json(); })
            .then(function(d) {
                var el = document.getElementById('emailConfigStatus');
                if (el && d.success && d.data) {
                    var html = '<div style="padding:8px;background:#f6f8fa;border-radius:6px;font-size:13px;">';
                    if (d.data.smtp_server) {
                        html += '✓ SMTP: ' + d.data.smtp_server + ':' + d.data.smtp_port;
                    } else {
                        html += '✗ ' + (typeof I18n !== 'undefined' ? I18n.t('tools.email_not_configured') : 'Not configured');
                    }
                    html += '</div>';
                    el.innerHTML = html;
                } else {
                    el.innerHTML = '<div style="padding:8px;background:#f6f8fa;border-radius:6px;font-size:13px;">✗ ' + (typeof I18n !== 'undefined' ? I18n.t('tools.email_not_configured') : 'Not configured') + '</div>';
                }
            })
            .catch(function() {
                var el = document.getElementById('emailConfigStatus');
                if (el) el.innerHTML = '<div style="color:#666;font-size:13px;">' + (typeof I18n !== 'undefined' ? I18n.t('common.load_failed') : 'Load failed') + '</div>';
            });
    })();

    // ========== 多语言切换功能 ==========
    function changeLanguage(lang) {
        if (typeof I18n !== 'undefined') {
            I18n.setLang(lang);
            // 更新语言选择器的显示
            var select = document.getElementById('langSelect');
            if (select) {
                select.value = lang;
            }
        }
    }

    // 初始化语言选择器
    document.addEventListener('DOMContentLoaded', function() {
        var savedLang = localStorage.getItem('clawos_lang') || 'zh';
        var select = document.getElementById('langSelect');
        if (select) {
            select.value = savedLang;
        }
    });

    // 监听语言变更事件，更新配置抽屉打开时的语言选择器
    document.addEventListener('i18n:languageChanged', function(e) {
        var select = document.getElementById('langSelect');
        if (select && e.detail && e.detail.lang) {
            select.value = e.detail.lang;
        }
    });
    </script>

</body>
</html>

<!-- Email History Modal -->
<div id="emailBackdrop" onclick="closeEmailDrawer()" style="display:none;position:fixed;inset:0;background:rgba(0,0,0,0.5);z-index:9999;"></div>
<div id="emailInputDrawer" style="display:none;position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:#fff;border-radius:8px;box-shadow:0 8px 24px rgba(0,0,0,0.2);z-index:10000;width:300px;max-width:90vw;padding:16px;">
    <div style="font-weight:600;margin-bottom:12px;" data-i18n="email.select_recipient">Select recipient</div>
    <input type="email" id="emailInput" placeholder="Enter email address" data-i18n-placeholder="common.email_placeholder" style="width:100%;padding:10px;margin-bottom:10px;border:1px solid #d0d7de;border-radius:6px;">
    <button onclick="confirmEmail()" style="width:100%;padding:10px;background:#0969da;color:#fff;border:none;border-radius:6px;cursor:pointer;font-size:14px;" data-i18n="common.confirm">Confirm</button>
    <div style="margin-top:16px;color:#57606a;font-size:12px;" data-i18n="email.history_title">History</div>
    <div id="emailHistoryList" style="margin-top:8px;"></div>
</div>
<script>
function openEmailDrawer(callback){emailCallback=callback;document.getElementById('emailInput').value='';loadEmailHistory();document.getElementById('emailBackdrop').style.display='block';document.getElementById('emailInputDrawer').style.display='block';document.getElementById('emailInput').focus();}
function closeEmailDrawer(){document.getElementById('emailBackdrop').style.display='none';document.getElementById('emailInputDrawer').style.display='none';}

function loadEmailHistory(){fetch('/api/email/history').then(r=>r.json()).then(d=>{var h=d.data||[];var l=document.getElementById('emailHistoryList');var noHist=(typeof I18n!=='undefined'?I18n.t('email.no_history'):'No history');l.innerHTML=h.length?h.map(e=>'<div style="display:flex;justify-content:space-between;padding:8px;border-bottom:1px solid #eee;"><span>'+e+'</span><span onclick="delEmailHist(\''+e.replace('@','@')+'\')" style="cursor:pointer;color:#cf222e;padding:4px;">×</span></div>').join(''):'<div style="color:#8b949e;">'+noHist+'</div>';});}
function delEmailHist(e){fetch('/api/email/history',{method:'DELETE',headers:{'Content-Type':'application/json'},body:JSON.stringify({email:e})}).then(r=>r.json()).then(loadEmailHistory);}
function confirmEmail(){var e=document.getElementById('emailInput').value.trim();if(!e)return;fetch('/api/email/history',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({email:e})});closeEmailDrawer();if(emailCallback)emailCallback(e);}
</script>
<!-- Email Drawer -->
<div id="emailDrawer" class="drawer" style="width:320px;display:none;position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:#fff;border-radius:8px;box-shadow:0 8px 24px rgba(0,0,0,0.2);z-index:9999;padding:16px;">
    <div style="font-weight:600;margin-bottom:12px;" data-i18n="email.select_recipient">Select recipient</div>
    <input type="email" id="emailInput" placeholder="Enter email address" data-i18n-placeholder="common.email_placeholder" style="width:100%;padding:10px;margin-bottom:10px;border:1px solid #d0d7de;border-radius:6px;">
    <button onclick="confirmEmail()" style="width:100%;padding:10px;background:#0969da;color:#fff;border:none;border-radius:6px;cursor:pointer;font-size:14px;" data-i18n="common.confirm">Confirm</button>
    <div style="margin-top:16px;color:#57606a;font-size:12px;" data-i18n="email.history_title">History</div>
    <div id="emailHistoryList" style="margin-top:8px;max-height:200px;overflow-y:auto;"></div>
</div>
<div id="emailBackdrop" onclick="closeEmailDrawer()" style="display:none;position:fixed;inset:0;background:rgba(0,0,0,0.5);z-index:9998;" ></div>
