/* 仪表盘 */ .quick-actions { display: flex; gap: var(--space-sm); flex-wrap: wrap; margin-bottom: var(--space-xl); } .dashboard-overview { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-xl); margin-bottom: var(--space-xl); } .overview-section { display: flex; flex-direction: column; gap: var(--space-md); } .overview-item { display: flex; align-items: center; justify-content: space-between; padding: var(--space-md) var(--space-lg); background: var(--bg-card); border: 1px solid var(--border-primary); border-radius: var(--radius-lg); transition: all var(--transition-fast); } .overview-item:hover { background: var(--bg-card-hover); border-color: var(--border-focus); } .overview-label { display: flex; align-items: center; gap: var(--space-sm); font-size: var(--font-size-sm); color: var(--text-secondary); font-weight: 500; } .overview-label svg { width: 16px; height: 16px; color: var(--text-tertiary); } .overview-value { display: flex; align-items: center; gap: var(--space-sm); font-size: var(--font-size-sm); font-family: var(--font-mono); color: var(--text-primary); } /* 服务卡片 */ .service-card { display: flex; align-items: center; justify-content: space-between; padding: var(--space-lg); background: var(--bg-card); border: 1px solid var(--border-primary); border-radius: var(--radius-lg); margin-bottom: var(--space-md); transition: all var(--transition-fast); } .service-card:hover { background: var(--bg-card-hover); } .service-info { display: flex; align-items: center; gap: var(--space-md); } .service-name { font-weight: 600; font-size: var(--font-size-md); } .service-desc { font-size: var(--font-size-xs); color: var(--text-tertiary); margin-top: 2px; } .service-actions { display: flex; gap: var(--space-sm); align-items: center; } /* 服务操作加载状态 */ .service-loading { display: flex; align-items: center; gap: var(--space-sm); } .service-spinner { width: 18px; height: 18px; border: 2px solid var(--border-primary); border-top-color: var(--primary); border-radius: 50%; animation: service-spin 0.8s linear infinite; } @keyframes service-spin { to { transform: rotate(360deg); } } .service-loading-text { font-size: var(--font-size-sm); color: var(--text-secondary); font-variant-numeric: tabular-nums; min-width: 100px; } .service-cancel-btn { font-size: var(--font-size-xs) !important; color: var(--text-tertiary) !important; padding: 2px 8px !important; transition: color var(--transition-fast); } .service-cancel-btn:hover { color: var(--error) !important; } /* 状态点:加载中脉冲动画 */ .status-dot.loading { background: var(--warning, #f59e0b); animation: dot-pulse 1s ease-in-out infinite; } @keyframes dot-pulse { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: 0.4; transform: scale(0.8); } } /* 日志加载状态 */ .log-loading { display: flex; align-items: center; justify-content: center; padding: var(--space-xl) 0; } /* 日志工具栏 */ .log-toolbar { display: flex; align-items: center; gap: var(--space-md); margin-bottom: var(--space-md); } /* 日志查看器 */ .log-viewer { background: var(--bg-secondary); border: 1px solid var(--border-primary); border-radius: var(--radius-lg); font-family: var(--font-mono); font-size: var(--font-size-xs); line-height: 1.6; overflow: auto; max-height: calc(100vh - 240px); padding: var(--space-md); } .log-line { white-space: pre-wrap; word-break: break-all; padding: 1px 0; } .log-line:hover { background: var(--bg-glass); } /* 配置项说明 */ .form-hint { font-size: var(--font-size-xs); color: var(--text-tertiary); margin-top: 4px; line-height: 1.5; } /* 配置编辑区 */ .config-section { background: var(--bg-card); border: 1px solid var(--border-primary); border-radius: var(--radius-lg); padding: var(--space-xl); margin-bottom: var(--space-lg); } .config-section-title { display: flex; align-items: center; gap: var(--space-sm); font-size: var(--font-size-lg); font-weight: 600; margin-bottom: var(--space-lg); padding-bottom: var(--space-md); border-bottom: 1px solid var(--border-secondary); } /* 记忆文件管理 */ .memory-layout { display: grid; grid-template-columns: 240px 1fr; gap: var(--space-lg); height: calc(100vh - 200px); } .memory-sidebar { background: var(--bg-card); border: 1px solid var(--border-primary); border-radius: var(--radius-lg); padding: var(--space-md); overflow-y: auto; } .memory-editor { background: var(--bg-card); border: 1px solid var(--border-primary); border-radius: var(--radius-lg); display: flex; flex-direction: column; overflow: hidden; } .memory-editor textarea { flex: 1; width: 100%; background: transparent; border: none; resize: none; outline: none; color: var(--text-primary); font-family: var(--font-mono); font-size: var(--font-size-sm); line-height: 1.7; padding: var(--space-lg); } .file-item { padding: var(--space-sm) var(--space-md); border-radius: var(--radius-sm); font-size: var(--font-size-sm); color: var(--text-secondary); cursor: pointer; transition: all var(--transition-fast); } .file-item:hover { background: var(--bg-glass-hover); color: var(--text-primary); } .file-item.active { background: var(--accent-muted); color: var(--accent-hover); } .editor-area { flex: 1; width: 100%; background: transparent; border: none; resize: none; outline: none; color: var(--text-primary); font-family: var(--font-mono); font-size: var(--font-size-sm); line-height: 1.7; padding: var(--space-lg); } .editor-toolbar { display: flex; align-items: center; justify-content: space-between; padding: var(--space-sm) var(--space-lg); border-bottom: 1px solid var(--border-secondary); } /* 升级进度弹窗 */ .upgrade-progress-wrap { margin-bottom: var(--space-md); } .upgrade-progress-bar { height: 6px; background: var(--bg-tertiary); border-radius: 3px; overflow: hidden; margin-bottom: var(--space-xs); } .upgrade-progress-fill { height: 100%; background: var(--accent); border-radius: 3px; transition: width 0.4s ease; } .upgrade-progress-fill.done { background: var(--success); } .upgrade-progress-fill.error { background: var(--error); } .upgrade-progress-text { font-size: var(--font-size-xs); color: var(--text-secondary); } .upgrade-log-box { max-height: 220px; overflow-y: auto; background: var(--bg-tertiary); border-radius: var(--radius-md); padding: var(--space-sm) var(--space-md); font-family: var(--font-mono); font-size: 11px; line-height: 1.6; color: var(--text-secondary); white-space: pre-wrap; word-break: break-all; } /* 隧道路由卡片 */ .tunnel-routes { display: grid; gap: var(--space-md); margin-top: var(--space-md); } .tunnel-route-card { background: var(--bg-secondary); border: 1px solid var(--border-primary); border-radius: var(--radius-lg); padding: var(--space-lg); transition: all var(--transition-fast); position: relative; overflow: hidden; } .tunnel-route-card::before { content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; background: var(--accent); opacity: 0; transition: opacity var(--transition-fast); } .tunnel-route-card:hover { background: var(--bg-card-hover); border-color: var(--border-focus); } .tunnel-route-card:hover::before { opacity: 1; } .tunnel-route-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--space-sm); } .tunnel-route-name { font-weight: 600; font-size: var(--font-size-md); color: var(--text-primary); } .tunnel-route-badge { display: inline-flex; align-items: center; gap: 4px; padding: 2px 8px; border-radius: var(--radius-sm); font-size: 11px; font-weight: 500; background: var(--success-muted); color: var(--success); } .tunnel-route-domain { display: flex; align-items: center; gap: var(--space-sm); margin-bottom: var(--space-xs); } .tunnel-route-domain a { color: var(--accent); text-decoration: none; font-size: var(--font-size-sm); transition: color var(--transition-fast); } .tunnel-route-domain a:hover { color: var(--accent-hover); text-decoration: underline; } .tunnel-route-service { display: flex; align-items: center; gap: var(--space-xs); font-size: var(--font-size-xs); color: var(--text-tertiary); } .tunnel-route-service code { background: var(--bg-tertiary); padding: 2px 6px; border-radius: var(--radius-sm); font-family: var(--font-mono); font-size: 11px; color: var(--text-secondary); } /* Gateway 配置页 — 选项卡片 */ .gw-option-cards { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-md); } .gw-option-card { display: flex; align-items: flex-start; gap: var(--space-md); padding: var(--space-lg); background: var(--bg-secondary); border: 2px solid var(--border-primary); border-radius: var(--radius-lg); cursor: pointer; transition: all var(--transition-fast); user-select: none; } .gw-option-card:hover { background: var(--bg-card-hover); border-color: var(--border-focus); } .gw-option-card.selected { border-color: var(--accent); background: var(--accent-muted); } .gw-option-icon { width: 36px; height: 36px; flex-shrink: 0; display: flex; align-items: center; justify-content: center; background: var(--bg-tertiary); border-radius: var(--radius-md); color: var(--text-secondary); transition: all var(--transition-fast); } .gw-option-card.selected .gw-option-icon { background: var(--accent); color: white; } .gw-option-icon svg { width: 20px; height: 20px; } .gw-option-text { flex: 1; min-width: 0; } .gw-option-title { font-weight: 600; font-size: var(--font-size-md); color: var(--text-primary); margin-bottom: 2px; } .gw-option-desc { font-size: var(--font-size-xs); color: var(--text-tertiary); line-height: 1.5; } /* Gateway — 高级选项折叠 */ .gw-advanced-toggle { display: flex; align-items: center; gap: var(--space-xs); padding: var(--space-sm) 0; font-size: var(--font-size-sm); color: var(--text-tertiary); cursor: pointer; user-select: none; transition: color var(--transition-fast); } .gw-advanced-toggle:hover { color: var(--text-primary); } .gw-advanced-toggle svg { transition: transform var(--transition-fast); } .gw-advanced-toggle.open svg { transform: rotate(180deg); } .gw-advanced-panel { animation: fadeIn 200ms ease; } /* Gateway — 保存栏 */ .gw-save-bar { display: flex; align-items: center; gap: var(--space-md); margin-top: var(--space-lg); padding-top: var(--space-lg); border-top: 1px solid var(--border-secondary); } .gw-save-bar .btn { display: inline-flex; align-items: center; gap: var(--space-xs); } .gw-save-hint { font-size: var(--font-size-xs); color: var(--text-tertiary); }