Spaces:
Running
Running
| # ui/theme.py | |
| # ui/theme.py | |
| def get_enhanced_css() -> str: | |
| return """ | |
| <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;700;800&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet"> | |
| <style> | |
| /* ============= CSS Variables ============= */ | |
| :root { | |
| --primary-color: #6366f1; | |
| --primary-dark: #4f46e5; | |
| --secondary-color: #10b981; | |
| --accent-color: #f59e0b; | |
| --danger-color: #ef4444; | |
| --glass-bg: rgba(255, 255, 255, 0.7); | |
| --glass-border: 1px solid rgba(255, 255, 255, 0.5); | |
| --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05); | |
| --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1); | |
| --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1); | |
| --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1); | |
| --radius-sm: 8px; | |
| --radius-md: 12px; | |
| --radius-lg: 16px; | |
| --radius-xl: 20px; | |
| --font-main: 'Inter', sans-serif; | |
| } | |
| /* ============= Base Styles ============= */ | |
| body, .gradio-container { | |
| font-family: var(--font-main) !important; | |
| background: #f8fafc !important; | |
| /* ⭐ 新增以下兩行:強制鎖定高度,解決 HF Space 捲動問題 ⭐ */ | |
| height: 100vh !important; /* 高度限制為視窗大小 */ | |
| overflow-y: auto !important; /* 超出範圍時,在內部產生捲軸 */ | |
| } | |
| * { box-sizing: border-box; } | |
| /* ============= 1. Header (保留 Backup 樣式) ============= */ | |
| .app-header-container { | |
| align-items: center !important; | |
| margin-bottom: 24px !important; | |
| padding: 16px 24px !important; | |
| background: rgba(255, 255, 255, 0.8) !important; | |
| backdrop-filter: blur(12px) !important; | |
| -webkit-backdrop-filter: blur(12px) !important; | |
| border-radius: var(--radius-lg) !important; | |
| border: 1px solid rgba(255, 255, 255, 0.5) !important; | |
| box-shadow: var(--shadow-md) !important; | |
| } | |
| .app-header-left { | |
| display: flex; | |
| flex-direction: column; | |
| gap: 4px; | |
| } | |
| .header-controls { | |
| position: fixed !important; /* 固定定位 */ | |
| top: 30px !important; /* 距離頂部 */ | |
| right: 30px !important; /* 距離右側 */ | |
| z-index: 99999 !important; /* 最上層 */ | |
| display: flex !important; | |
| flex-direction: column !important; /* 🔥 關鍵:改為垂直排列 */ | |
| gap: 12px !important; /* 按鈕間距 */ | |
| align-items: center !important; /* 水平置中 */ | |
| /* 視覺優化:垂直膠囊 */ | |
| background: rgba(255, 255, 255, 0.9) !important; | |
| backdrop-filter: blur(12px) !important; | |
| padding: 12px 8px !important; /* 上下寬鬆,左右緊湊 */ | |
| border-radius: 50px !important; /* 大圓角 */ | |
| border: 1px solid rgba(255, 255, 255, 0.6) !important; | |
| box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08) !important; | |
| width: auto !important; | |
| min-width: 0 !important; | |
| height: auto !important; | |
| } | |
| /* 按鈕微調 (確保按鈕是圓的) */ | |
| .header-btn { | |
| min-width: 40px !important; | |
| max-width: 40px !important; | |
| height: 40px !important; | |
| font-size: 1.1rem !important; | |
| margin: 0 !important; | |
| } | |
| .header-btn:hover { | |
| background: #f1f5f9 !important; | |
| border-color: var(--primary-color) !important; | |
| color: var(--primary-color) !important; | |
| transform: translateY(-2px) !important; | |
| box-shadow: var(--shadow-md) !important; | |
| } | |
| .header-btn:active { | |
| transform: translateY(0) !important; | |
| } | |
| /* ============= 2. Animations & Agent Cards (保留 Backup 樣式) ============= */ | |
| @keyframes breathing-glow { | |
| 0% { box-shadow: 0 0 0 0 rgba(99, 102, 241, 0.6), 0 0 20px rgba(99, 102, 241, 0.3); border-color: #6366f1; } | |
| 50% { box-shadow: 0 0 0 8px rgba(99, 102, 241, 0), 0 0 30px rgba(99, 102, 241, 0.5); border-color: #818cf8; } | |
| 100% { box-shadow: 0 0 0 0 rgba(99, 102, 241, 0), 0 0 20px rgba(99, 102, 241, 0.3); border-color: #6366f1; } | |
| } | |
| @keyframes pulse-scale { | |
| 0%, 100% { transform: scale(1); } | |
| 50% { transform: scale(1.03); } | |
| } | |
| /* Agent Grid (用於 Step 3 的 Agent 卡片基礎) */ | |
| .agent-grid { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); | |
| gap: 12px; | |
| margin-top: 10px; | |
| } | |
| .agent-card-mini { | |
| background: white; | |
| padding: 12px; | |
| border-radius: var(--radius-md); | |
| border: 2px solid #e2e8f0; | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| text-align: center; | |
| transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .agent-card-mini.working { | |
| animation: breathing-glow 2s ease-in-out infinite !important; | |
| background: linear-gradient(135deg, #ffffff 0%, #eff6ff 100%) !important; | |
| border-width: 2px !important; | |
| z-index: 10 !important; | |
| position: relative !important; | |
| } | |
| .agent-card-mini.working::before { | |
| content: ''; | |
| position: absolute; top: -50%; left: -50%; width: 200%; height: 200%; | |
| background: radial-gradient(circle, rgba(99, 102, 241, 0.1) 0%, transparent 70%); | |
| animation: pulse-scale 2s ease-in-out infinite; | |
| } | |
| .agent-card-mini:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); } | |
| .agent-avatar-mini { font-size: 28px; margin-bottom: 6px; position: relative; z-index: 1; } | |
| .agent-name-mini { font-weight: 600; font-size: 0.85rem; color: #1e293b; position: relative; z-index: 1; } | |
| .agent-status-dot { height: 8px; width: 8px; border-radius: 50%; display: inline-block; margin-top: 6px; position: relative; z-index: 1; } | |
| /* ============= 3. Chat & Tasks (保留 Backup 樣式) ============= */ | |
| .chat-history { | |
| display: flex; flex-direction: column; gap: 16px; padding: 20px; | |
| background: #fff; border-radius: var(--radius-lg); border: 1px solid #e2e8f0; | |
| max-height: 500px; overflow-y: auto; | |
| } | |
| .chat-message { display: flex; align-items: flex-end; gap: 10px; max-width: 85%; animation: fade-in 0.3s ease-out; } | |
| .chat-message.user { align-self: flex-end; flex-direction: row-reverse; } | |
| .chat-message.assistant { align-self: flex-start; } | |
| .chat-bubble { padding: 12px 16px; border-radius: 18px; font-size: 0.95rem; line-height: 1.5; position: relative; box-shadow: var(--shadow-sm); } | |
| .chat-message.user .chat-bubble { background: var(--primary-color); color: white; border-bottom-right-radius: 4px; } | |
| .chat-message.assistant .chat-bubble { background: #f1f5f9; color: #334155; border-bottom-left-radius: 4px; } | |
| .chat-time { font-size: 0.7rem; opacity: 0.7; margin-top: 4px; text-align: right; } | |
| /* Task Cards */ | |
| .task-card-item { | |
| background: white; | |
| border: 1px solid #e2e8f0; | |
| border-radius: 12px; | |
| padding: 16px; | |
| margin-bottom: 12px; | |
| transition: transform 0.2s; | |
| } | |
| .task-card-item:hover { | |
| border-color: var(--primary-color); | |
| transform: translateY(-2px); | |
| box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); | |
| } | |
| /* ============= 4. Timeline Redesign (Step 4 修正) ============= */ | |
| .timeline-container { | |
| position: relative; | |
| padding: 10px 0 10px 20px; | |
| margin-top: 10px; | |
| } | |
| /* 垂直連接線 */ | |
| .timeline-container::before { | |
| content: ''; | |
| position: absolute; | |
| left: 29px; | |
| top: 20px; | |
| bottom: 20px; | |
| width: 2px; | |
| background: #e2e8f0; | |
| z-index: 0; | |
| } | |
| /* 時間軸項目 - 強制橫排 */ | |
| .timeline-item { | |
| position: relative; | |
| display: flex !important; | |
| flex-direction: row !important; | |
| gap: 20px; | |
| margin-bottom: 24px; | |
| z-index: 1; | |
| align-items: stretch; | |
| } | |
| /* 左側圓點 */ | |
| .timeline-left { | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| min-width: 20px; | |
| padding-top: 4px; | |
| } | |
| .timeline-marker { | |
| width: 20px; | |
| height: 20px; | |
| border-radius: 50%; | |
| background: white; | |
| border: 4px solid var(--primary-color); | |
| box-shadow: 0 0 0 4px #fff; | |
| z-index: 2; | |
| } | |
| /* Timeline 卡片:改為淺灰色背景,製造層次感 */ | |
| .timeline-card { | |
| background: #f8fafc !important; /* 淺灰底 */ | |
| border: 1px solid #e2e8f0 !important; | |
| border-radius: 12px !important; | |
| padding: 16px !important; | |
| box-shadow: 0 1px 2px rgba(0,0,0,0.03) !important; | |
| transition: transform 0.2s, box-shadow 0.2s; | |
| display: block !important; | |
| } | |
| /* Hover 效果:卡片變白並浮起 */ | |
| .timeline-card:hover { | |
| background: #ffffff !important; | |
| transform: translateX(4px); | |
| box-shadow: 0 4px 12px rgba(0,0,0,0.08) !important; | |
| border-color: var(--primary) !important; | |
| } | |
| .timeline-header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: flex-start; | |
| margin-bottom: 8px; | |
| gap: 10px; | |
| } | |
| .timeline-location { font-size: 1rem; font-weight: 700; color: #1e293b; line-height: 1.3; } | |
| .timeline-time-badge { | |
| background: #f1f5f9; color: #64748b; font-size: 0.75rem; font-weight: 600; | |
| padding: 4px 10px; border-radius: 20px; white-space: nowrap; display: flex; align-items: center; gap: 4px; | |
| } | |
| .timeline-meta { | |
| background: #f1f5f9; | |
| border: 1px solid #e2e8f0; | |
| padding: 8px; border-radius: 8px; margin-top: 8px; color: #64748b; | |
| } | |
| .timeline-item:first-child .timeline-marker { border-color: #10b981 !important; } | |
| .timeline-item:last-child .timeline-marker { border-color: #ef4444 !important; } | |
| /* ============= 5. Step 3 War Room (新樣式) ============= */ | |
| .live-report-wrapper { | |
| flex: 1; | |
| background: white; | |
| border: 1px solid #e2e8f0; | |
| border-radius: 16px; | |
| padding: 30px; | |
| min-height: 600px; | |
| box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05); | |
| } | |
| .report-title { | |
| font-size: 1.2rem; font-weight: 700; color: #1e293b; | |
| margin-bottom: 16px; display: flex; align-items: center; gap: 8px; | |
| border-bottom: 2px solid #f1f5f9; padding-bottom: 12px; | |
| } | |
| .war-room-wrapper { | |
| width: 450px; flex-shrink: 0; display: flex; flex-direction: column; gap: 20px; position: sticky; top: 20px; | |
| } | |
| .agent-war-room { | |
| background: white; border-radius: 16px; border: 1px solid #e2e8f0; padding: 24px; | |
| display: flex; flex-direction: column; align-items: center; box-shadow: 0 2px 4px rgba(0,0,0,0.05); | |
| } | |
| .org-chart { width: 100%; display: flex; flex-direction: column; align-items: center; gap: 20px; } | |
| .org-level { display: flex !important; flex-direction: row !important; flex-wrap: wrap; justify-content: center; gap: 12px; width: 100%; z-index: 2; } | |
| .connector-line { width: 2px; height: 20px; background: #cbd5e1; } | |
| .connector-horizontal { height: 2px; width: 80%; background: #cbd5e1; margin-top: -20px; margin-bottom: 10px; } | |
| /* Step 3 的 Agent Card (複用 mini card 但調整寬度) */ | |
| .agent-card-wrap { width: 110px; text-align: center; display: flex; flex-direction: column; align-items: center; } | |
| .agent-card-inner { | |
| background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 10px; padding: 10px; | |
| display: flex; flex-direction: column; align-items: center; width: 100%; transition: transform 0.2s; | |
| } | |
| .agent-card-wrap.working .agent-card-inner { | |
| background: white; border-color: #6366f1; | |
| box-shadow: 0 0 0 4px rgba(99, 102, 241, 0.15); animation: pulse 2s infinite; | |
| } | |
| .agent-avatar { font-size: 24px; margin-bottom: 4px; } | |
| .agent-name { font-weight: 700; font-size: 0.8rem; color: #1e293b; } | |
| .agent-role { font-size: 0.65rem; color: #64748b; text-transform: uppercase; } | |
| .status-badge { font-size: 0.65rem; padding: 2px 6px; border-radius: 8px; background: #e2e8f0; color: #64748b; margin-top: 4px; } | |
| .agent-card-wrap.working .status-badge { background: #e0e7ff; color: #6366f1; } | |
| /* ============= 6. Utils & Layouts ============= */ | |
| .step-container { max-width: 1400px; margin: 0 auto; padding: 0 16px; animation: fade-in 0.4s ease-out; } | |
| .centered-input-container { max-width: 1000px !important; margin: 0 auto; padding: 40px 0; } | |
| .panel-container { background: white; border: 1px solid #e2e8f0; border-radius: 16px; height: 650px !important; display: flex !important; flex-direction: column !important; overflow: hidden; } | |
| .panel-header { padding: 16px 20px; background: #f8fafc; border-bottom: 1px solid #e2e8f0; font-weight: 700; color: var(--text-main); flex-shrink: 0; } | |
| .scrollable-content { flex: 1; overflow-y: auto !important; padding: 20px; background: #fff; } | |
| .chat-input-row { padding: 12px !important; border-top: 1px solid #e2e8f0; background: white; align-items: center !important; } | |
| .split-view-container { display: flex; gap: 24px; height: calc(100vh - 140px); min-height: 600px; } | |
| .split-left-panel .panel-container, .split-left-panel .gradio-group { | |
| background: white !important; | |
| } | |
| .split-right-panel { flex: 2; position: sticky; top: 100px; height: 100%; } | |
| /* Animations */ | |
| @keyframes fade-in { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } | |
| @keyframes slide-in-left { from { opacity: 0; transform: translateX(-20px); } to { opacity: 1; transform: translateX(0); } } | |
| @keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(99, 102, 241, 0.4); } 70% { box-shadow: 0 0 0 6px rgba(0,0,0,0); } 100% { box-shadow: 0 0 0 0 rgba(0,0,0,0); } } | |
| /* Scrollbar */ | |
| ::-webkit-scrollbar { width: 6px; height: 6px; } | |
| ::-webkit-scrollbar-track { background: #f1f5f9; border-radius: 4px; } | |
| ::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 4px; } | |
| ::-webkit-scrollbar-thumb:hover { background: #94a3b8; } | |
| /* 修正 Scrollbar 樣式,讓它明顯一點但好看 */ | |
| .drawer-content::-webkit-scrollbar { width: 6px; } | |
| .drawer-content::-webkit-scrollbar-track { background: transparent; } | |
| .drawer-content::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 4px; } | |
| .drawer-content::-webkit-scrollbar-thumb:hover { background: #94a3b8; } | |
| /* Dark Mode Support */ | |
| .theme-dark body, .theme-dark .gradio-container { background: #0f172a !important; } | |
| .theme-dark .app-header-container, .theme-dark .chat-history, .theme-dark .timeline-card, .theme-dark .metric-card, .theme-dark .agent-card-mini, .theme-dark .agent-card-inner, .theme-dark .live-report-wrapper, .theme-dark .agent-war-room, .theme-dark .task-card-item { | |
| background: #1e293b !important; border-color: #334155 !important; color: #e2e8f0 !important; | |
| } | |
| .theme-dark h1, .theme-dark h2, .theme-dark h3, .theme-dark p, .theme-dark span, .theme-dark .agent-name { color: #e2e8f0 !important; } | |
| .theme-dark .chat-message.assistant .chat-bubble { background: #334155 !important; color: #e2e8f0 !important; } | |
| .theme-dark .agent-name-mini, .theme-dark .metric-card h3 { color: #cbd5e1 !important; } | |
| /* Step 1 Log */ | |
| .agent-stream-box-step1 { | |
| background: #f8fafc; border-radius: 8px; padding: 12px; border: 1px solid #e2e8f0; | |
| min-height: 60px; max-height: 150px; overflow-y: auto; font-family: monospace; font-size: 0.9rem; | |
| margin-bottom: 16px; margin-top: 10px; | |
| } | |
| /* ============= 新版 Quick Start Buttons ============= */ | |
| /* 容器稍微給點間距 */ | |
| .example-container { | |
| gap: 8px !important; | |
| margin-bottom: 16px !important; | |
| } | |
| /* 把按鈕偽裝成卡片列表 */ | |
| .example-btn { | |
| text-align: left !important; /* 文字靠左 */ | |
| justify-content: flex-start !important; /* Flex 內容靠左 */ | |
| height: auto !important; /* 高度自動 */ | |
| white-space: normal !important; /* ⭐ 允許換行 */ | |
| word-break: break-word !important; /* 長字換行 */ | |
| padding: 12px 16px !important; | |
| background: #f8fafc !important; | |
| border: 1px solid #e2e8f0 !important; | |
| color: #475569 !important; | |
| font-weight: 400 !important; /* 字體不要太粗 */ | |
| } | |
| .example-btn:hover { | |
| background: white !important; | |
| border-color: var(--primary-color) !important; | |
| color: var(--primary-color) !important; | |
| box-shadow: 0 4px 6px rgba(0,0,0,0.05) !important; | |
| transform: translateY(-1px); | |
| } | |
| /* ============= 設定彈窗 (Settings Modal) ============= */ | |
| /* 1. 全螢幕遮罩層 (Overlay) */ | |
| .modal-overlay { | |
| position: fixed !important; | |
| top: 0 !important; | |
| left: 0 !important; | |
| width: 100vw !important; | |
| height: 100vh !important; | |
| background: rgba(0, 0, 0, 0.6) !important; /* 半透明黑色背景 */ | |
| backdrop-filter: blur(4px) !important; /* 背景模糊效果 */ | |
| z-index: 100000 !important; /* 必須比 Header 的 99999 還大 */ | |
| display: flex !important; | |
| align-items: center !important; /* 垂直置中 */ | |
| justify-content: center !important; /* 水平置中 */ | |
| padding: 20px !important; | |
| } | |
| /* 2. 彈窗本體 (Modal Box) */ | |
| .modal-box { | |
| background: white !important; | |
| border-radius: 24px !important; | |
| box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25) !important; | |
| border: 1px solid rgba(255, 255, 255, 0.6) !important; | |
| overflow: hidden !important; | |
| /* 🔥 寬度加大,讓橫向空間更舒服 */ | |
| max-width: 600px !important; | |
| width: 100% !important; | |
| display: flex !important; | |
| flex-direction: column !important; | |
| max-height: 90vh !important; /* 最大高度放寬到 90% 視窗高度 */ | |
| } | |
| /* 2. 內容區域 */ | |
| .modal-content { | |
| padding: 0 24px 10px 24px !important; | |
| overflow-y: auto !important; | |
| flex-grow: 1 !important; | |
| /* 🔥🔥🔥 關鍵修正:最小高度加大 🔥🔥🔥 */ | |
| /* 原本 300px -> 改為 500px,確保所有欄位都能直接顯示不用捲動 */ | |
| min-height: 500px !important; | |
| } | |
| /* 3. Footer (保持不變) */ | |
| .modal-footer { | |
| background: #f8fafc !important; | |
| padding: 20px 24px !important; | |
| border-top: 1px solid #f1f5f9 !important; | |
| gap: 12px !important; | |
| flex-shrink: 0 !important; | |
| height: auto !important; | |
| display: flex !important; | |
| align-items: center !important; | |
| } | |
| .modal-title h3 { | |
| font-size: 1.5rem !important; | |
| font-weight: 800 !important; | |
| background: linear-gradient(135deg, #4f46e5, #9333ea); /* 藍紫漸層 */ | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| margin-bottom: 4px !important; | |
| } | |
| .tab-desc p { | |
| font-size: 0.9rem !important; | |
| color: #64748b !important; | |
| margin-bottom: 16px !important; | |
| } | |
| /* 3. 輸入框美化 (移除預設的生硬邊框) */ | |
| .modern-input textarea, .modern-input input { | |
| background-color: #f8fafc !important; | |
| border: 1px solid #e2e8f0 !important; | |
| border-radius: 12px !important; | |
| padding: 10px 14px !important; | |
| transition: all 0.2s ease; | |
| font-size: 0.95rem !important; | |
| } | |
| .modern-input textarea:focus, .modern-input input:focus { | |
| background-color: white !important; | |
| border-color: #6366f1 !important; | |
| box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1) !important; | |
| } | |
| /* 4. Dropdown 美化 & 修復寬度問題 */ | |
| .modern-dropdown .wrap-inner { | |
| background-color: #f8fafc !important; | |
| border-radius: 12px !important; | |
| border: 1px solid #e2e8f0 !important; | |
| } | |
| /* 修復文字被切斷的問題 */ | |
| #provider-dropdown { | |
| min-width: 150px !important; /* 強制最小寬度 */ | |
| } | |
| /* 5. 按鈕美化 */ | |
| .modal-footer { | |
| background: #f8fafc !important; | |
| padding: 20px 24px !important; | |
| border-top: 1px solid #f1f5f9 !important; | |
| gap: 12px !important; | |
| } | |
| /* Cancel 按鈕:柔和灰 */ | |
| .btn-cancel { | |
| background: white !important; | |
| border: 1px solid #e2e8f0 !important; | |
| color: #64748b !important; | |
| border-radius: 10px !important; | |
| font-weight: 500 !important; | |
| } | |
| .btn-cancel:hover { | |
| background: #f1f5f9 !important; | |
| color: #334155 !important; | |
| } | |
| /* Save 按鈕:品牌漸層紫 (取代橘色) */ | |
| #btn-save-config { | |
| background: linear-gradient(135deg, #6366f1 0%, #4f46e5 100%) !important; | |
| border: none !important; | |
| color: white !important; | |
| border-radius: 10px !important; | |
| font-weight: 600 !important; | |
| box-shadow: 0 4px 6px -1px rgba(99, 102, 241, 0.3) !important; | |
| transition: transform 0.1s !important; | |
| } | |
| #btn-save-config:hover { | |
| opacity: 0.95 !important; | |
| box-shadow: 0 6px 10px -1px rgba(99, 102, 241, 0.4) !important; | |
| transform: translateY(-1px) !important; | |
| } | |
| #btn-save-config:active { | |
| transform: translateY(0) !important; | |
| } | |
| /* 2. 內容區域:設定最小高度,並讓它吃掉剩餘空間 */ | |
| .modal-content { | |
| padding: 0 24px 10px 24px !important; | |
| overflow-y: auto !important; | |
| flex-grow: 1 !important; /* 🔥 關鍵:佔據剩餘空間 */ | |
| min-height: 300px !important; /* 🔥 關鍵:設定最小高度,防止內容太少時視窗縮成一團 */ | |
| } | |
| /* 3. Footer:固定高度,不要拉伸 */ | |
| .modal-footer { | |
| background: #f8fafc !important; | |
| padding: 20px 24px !important; | |
| border-top: 1px solid #f1f5f9 !important; | |
| gap: 12px !important; | |
| /* 🔥 關鍵:防止 Footer 被拉高 */ | |
| flex-shrink: 0 !important; | |
| height: auto !important; | |
| display: flex !important; | |
| align-items: center !important; /* 垂直置中,防止按鈕變形 */ | |
| } | |
| /* 彈出動畫 */ | |
| @keyframes modal-pop { | |
| 0% { transform: scale(0.95) translateY(10px); opacity: 0; } | |
| 100% { transform: scale(1) translateY(0); opacity: 1; } | |
| } | |
| /* ============= API Key 佈局優化 ============= */ | |
| /* 1. 縮小左右欄位的間距 (原本約 20px -> 改為 6px) */ | |
| .api-row { | |
| gap: 6px !important; | |
| } | |
| /* 2. 修正 Dropdown 在窄欄位時文字被切斷的問題 */ | |
| #provider-dropdown .wrap-inner { | |
| padding-right: 25px !important; /* 預留空間給箭頭 */ | |
| } | |
| #provider-dropdown input { | |
| text-overflow: ellipsis !important; | |
| min-width: 0 !important; | |
| } | |
| /* 讓 Dropdown 的選單箭頭不要擠到文字 */ | |
| #provider-dropdown svg { | |
| margin-right: -5px !important; | |
| } | |
| .agent-war-room { | |
| background: white !important; /* 強制純白不透明 */ | |
| border: 1px solid #cbd5e1 !important; /* 加深邊框顏色 */ | |
| border-radius: 16px !important; | |
| padding: 24px !important; | |
| box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1) !important; /* 加強陰影 */ | |
| opacity: 1 !important; | |
| } | |
| /* 2. Agent 小卡片:確保它是獨立的實體 */ | |
| .agent-card-inner { | |
| background: #f8fafc !important; /* 淺灰底色,區分層次 */ | |
| border: 1px solid #cbd5e1 !important; /* 明顯的邊框 */ | |
| border-radius: 12px !important; | |
| opacity: 1 !important; /* 拒絕透明 */ | |
| box-shadow: 0 2px 4px rgba(0,0,0,0.05) !important; | |
| transition: all 0.2s !important; | |
| } | |
| /* 3. 正在工作的卡片:亮起來 */ | |
| .agent-card-wrap.working .agent-card-inner { | |
| background: white !important; | |
| border-color: #6366f1 !important; /* 亮紫色邊框 */ | |
| box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.2) !important; /* 發光效果 */ | |
| } | |
| /* 4. ⭐ 關鍵:文字顏色強制矯正 ⭐ */ | |
| /* 不管外面主題怎麼變,這裡的字一定要是深色的 */ | |
| .agent-name { | |
| color: #0f172a !important; /* 深黑藍色 */ | |
| font-weight: 700 !important; | |
| font-size: 0.85rem !important; | |
| opacity: 1 !important; | |
| } | |
| .agent-role { | |
| color: #475569 !important; /* 深灰色 */ | |
| font-weight: 600 !important; | |
| opacity: 1 !important; | |
| } | |
| .status-badge { | |
| color: #334155 !important; | |
| background: #e2e8f0 !important; | |
| border: 1px solid #cbd5e1 !important; | |
| font-weight: 600 !important; | |
| opacity: 1 !important; | |
| } | |
| /* 工作的狀態標籤 */ | |
| .agent-card-wrap.working .status-badge { | |
| background: #e0e7ff !important; | |
| color: #4338ca !important; | |
| border-color: #818cf8 !important; | |
| } | |
| /* 連接線也要加深,不然看不到 */ | |
| .connector-line, .connector-horizontal { | |
| background: #94a3b8 !important; /* 加深灰色 */ | |
| opacity: 0.6 !important; | |
| } | |
| .tabs > .tab-nav > button { | |
| color: #64748b !important; | |
| font-weight: 500 !important; | |
| } | |
| /* 選中的 Tab:品牌紫色 + 紫色底線 */ | |
| .tabs > .tab-nav > button.selected { | |
| color: #6366f1 !important; /* 文字變紫 */ | |
| border-bottom-color: #6366f1 !important; /* 底線變紫 */ | |
| border-bottom-width: 2px !important; | |
| font-weight: 700 !important; | |
| } | |
| .api-status-msg p { | |
| font-size: 0.8rem !important; | |
| margin-top: 6px !important; | |
| margin-left: 8px !important; | |
| font-weight: 600 !important; | |
| font-family: 'Inter', sans-serif !important; | |
| color: #64748b; /* 預設灰色 */ | |
| } | |
| /* 讓輸入框和狀態訊息之間更緊湊 */ | |
| .api-status-msg { | |
| min-height: 20px !important; /* 預留高度防止跳動 */ | |
| } | |
| /* === 1. Summary Card (儀表板) === */ | |
| .summary-card-modern { | |
| /* 改為藍白漸層 */ | |
| background: linear-gradient(135deg, #ffffff 0%, #eff6ff 100%) !important; | |
| border: 1px solid #dbeafe !important; | |
| /* 🔥 修正:縮小內距與下邊距,防止撐出滾動條 */ | |
| border-radius: 16px; | |
| padding: 14px 18px !important; /* 原本是 24px */ | |
| margin-bottom: 12px !important; /* 原本是 20px */ | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| flex-wrap: wrap; | |
| gap: 15px; | |
| /* 消除 Gradio 預設可能帶入的額外高度 */ | |
| min-height: 0 !important; | |
| } | |
| /* 讓 Summary 內的地點文字更跳 */ | |
| .summary-loc { | |
| font-size: 1.4rem; | |
| font-weight: 800; | |
| color: #312e81; /* 深靛藍 */ | |
| margin: 4px 0; | |
| text-shadow: 0 1px 0 rgba(255,255,255,0.8); | |
| } | |
| .summary-label { font-size: 0.75rem; color: #94a3b8; font-weight: 700; letter-spacing: 0.5px; } | |
| .summary-date { font-size: 0.9rem; color: #6366f1; } | |
| .summary-metrics { display: flex; gap: 12px; } | |
| .metric-box { | |
| background: rgba(255, 255, 255, 0.7); | |
| border: 1px solid #e2e8f0; | |
| padding: 8px 16px; | |
| border-radius: 12px; | |
| min-width: 80px; | |
| backdrop-filter: blur(4px); | |
| box-shadow: 0 2px 4px rgba(0,0,0,0.02); | |
| } | |
| .m-val { display: block; font-size: 1.2rem; font-weight: 800; color: #334155; line-height: 1; } | |
| .m-val small { font-size: 0.7rem; margin-left: 2px; } | |
| .m-label { font-size: 0.7rem; color: #64748b; } | |
| .metric-box.alert .m-val { color: #ef4444; } | |
| /* === 2. Agent Status Row (橫向狀態列) === */ | |
| .agent-status-row { | |
| display: flex; | |
| gap: 10px; | |
| overflow-x: auto; /* 如果螢幕太窄,允許橫向捲動 */ | |
| padding-bottom: 5px; | |
| margin-bottom: 15px; | |
| } | |
| .agent-status-card { | |
| flex: 1; | |
| min-width: 120px; | |
| background: white; | |
| border: 1px solid #e2e8f0; | |
| border-radius: 10px; | |
| padding: 10px; | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| transition: all 0.3s; | |
| } | |
| .agent-status-card.working { | |
| border-color: #6366f1; | |
| background: #eff6ff; | |
| box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.1); | |
| } | |
| .agent-name { font-size: 0.8rem; font-weight: 700; color: #1e293b; } | |
| .agent-msg { font-size: 0.7rem; color: #64748b; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } | |
| .agent-status-card.working .agent-msg { color: #6366f1; font-weight: 600; } | |
| /* === 3. Task Card Modern (任務卡片) === */ | |
| .task-card-modern { | |
| background: white; | |
| border: 1px solid #e2e8f0; | |
| border-radius: 10px; | |
| padding: 14px; | |
| margin-bottom: 10px; | |
| border-left-width: 4px; | |
| } | |
| .border-high { border-left-color: #ef4444; } | |
| .border-medium { border-left-color: #f59e0b; } | |
| .border-low { border-left-color: #10b981; } | |
| .tc-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; } | |
| .tc-title { font-weight: 600; color: #334155; font-size: 0.95rem; } | |
| .tc-badge { font-size: 0.7rem; padding: 2px 8px; border-radius: 12px; font-weight: 700; text-transform: uppercase; } | |
| .badge-high { background: #fef2f2; color: #ef4444; } | |
| .badge-medium { background: #fffbeb; color: #f59e0b; } | |
| .badge-low { background: #ecfdf5; color: #10b981; } | |
| .tc-body { font-size: 0.85rem; color: #64748b; display: flex; flex-direction: column; gap: 4px; } | |
| /* 1. 報告與任務列表的通用容器 */ | |
| .live-report-wrapper, .panel-container { | |
| background: white !important; | |
| border: 1px solid #e2e8f0 !important; | |
| border-radius: 16px !important; | |
| padding: 30px !important; | |
| /* 🔥 關鍵:給它一個最小高度,讓它看起來像一張完整的紙,不會因為內容少而縮成一團 */ | |
| min-height: 600px !important; | |
| /* 增加立體感 */ | |
| box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05), 0 2px 4px -1px rgba(0, 0, 0, 0.03) !important; | |
| /* 讓內部的 Markdown 排版更舒適 */ | |
| line-height: 1.6 !important; | |
| font-size: 1rem !important; | |
| color: #334155 !important; | |
| } | |
| /* 2. 針對 Tab 內容的微調 */ | |
| /* 讓 Tab 下方的內容區塊與 Tab 標籤無縫銜接 (可選,視 Gradio 版本而定) */ | |
| .tabitem { | |
| border: none !important; | |
| background: transparent !important; | |
| } | |
| /* 3. 優化 "Analyzing..." 載入文字 */ | |
| /* 讓它不要只是孤單地浮在左上角,而是置中並帶點呼吸感 */ | |
| .live-report-wrapper p:only-child, .panel-container p:only-child { | |
| text-align: center !important; | |
| margin-top: 100px !important; | |
| color: #94a3b8 !important; | |
| font-weight: 500 !important; | |
| animation: pulse-text 2s infinite !important; | |
| } | |
| @keyframes pulse-text { | |
| 0% { opacity: 0.6; } | |
| 50% { opacity: 1; } | |
| 100% { opacity: 0.6; } | |
| } | |
| /* 讓氣泡容器不要拉伸 (預設靠左) */ | |
| .message-wrap { | |
| display: flex !important; | |
| flex-direction: column !important; | |
| align-items: flex-start !important; | |
| gap: 6px !important; | |
| } | |
| /* User 的氣泡改為靠右 */ | |
| .message-wrap.user-row { | |
| align-items: flex-end !important; | |
| } | |
| /* 氣泡本體:寬度適應內容,不要繼承 100% */ | |
| .message-bubble { | |
| width: fit-content !important; | |
| max-width: 80% !important; | |
| height: auto !important; | |
| display: block !important; | |
| white-space: pre-wrap !important; | |
| padding: 10px 14px !important; | |
| } | |
| /* ============= 3. 強化 Page 3 Agent 特效 (呼吸燈) ============= */ | |
| /* 定義強烈的脈衝動畫 */ | |
| @keyframes strong-pulse { | |
| 0% { | |
| box-shadow: 0 0 0 0 rgba(99, 102, 241, 0.4); | |
| border-color: #6366f1; | |
| transform: scale(1); | |
| } | |
| 50% { | |
| box-shadow: 0 0 0 6px rgba(99, 102, 241, 0); /* 擴散光圈 */ | |
| border-color: #818cf8; | |
| transform: scale(1.02); /* 微微放大 */ | |
| } | |
| 100% { | |
| box-shadow: 0 0 0 0 rgba(99, 102, 241, 0); | |
| border-color: #6366f1; | |
| transform: scale(1); | |
| } | |
| } | |
| /* Agent 容器基礎樣式 */ | |
| .agent-status-row { | |
| display: flex; gap: 10px; overflow-x: auto; padding: 10px 5px; margin-bottom: 15px; | |
| } | |
| .agent-status-card { | |
| flex: 1; min-width: 140px; background: white; | |
| border: 1px solid #e2e8f0; border-radius: 12px; | |
| padding: 12px; display: flex; align-items: center; gap: 10px; | |
| transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); | |
| position: relative; | |
| } | |
| /* 🔥 關鍵:套用動畫到 Working 狀態 */ | |
| .agent-status-card.working { | |
| animation: strong-pulse 2s infinite !important; /* 強制執行動畫 */ | |
| background: linear-gradient(135deg, #ffffff 0%, #e0e7ff 100%) !important; /* 微藍背景 */ | |
| z-index: 10; | |
| } | |
| /* 文字顏色也跟著變亮 */ | |
| .agent-status-card.working .agent-msg { | |
| color: #4f46e5 !important; | |
| font-weight: 700 !important; | |
| } | |
| /* 靜態樣式補充 */ | |
| .agent-icon { font-size: 1.5rem; } | |
| .agent-info { overflow: hidden; } | |
| .agent-name { font-size: 0.85rem; font-weight: 700; color: #1e293b; } | |
| .agent-msg { font-size: 0.75rem; color: #64748b; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } | |
| /* 強制修正氣泡變形與留白問題 */ | |
| .map-container-relative { | |
| position: relative !important; | |
| height: 650px !important; /* 🔥 強制高度 */ | |
| width: 100% !important; | |
| border-radius: 16px; | |
| overflow: hidden !important; | |
| border: 1px solid #e2e8f0; | |
| background: white; | |
| } | |
| /* 強制 iframe 填滿容器 */ | |
| .map-container-relative iframe { | |
| width: 100% !important; | |
| height: 100% !important; | |
| border: none !important; | |
| } | |
| /* 2. 浮動抽屜本體 */ | |
| .map-overlay-drawer { | |
| position: absolute !important; | |
| top: 20px !important; | |
| left: 20px !important; | |
| bottom: 20px !important; | |
| width: 380px !important; /* 固定寬度,確保不會擋住太多地圖 */ | |
| height: 85% !important; | |
| background: rgba(255, 255, 255, 0.95) !important; | |
| backdrop-filter: blur(12px) !important; /* 毛玻璃效果 */ | |
| border-radius: 16px !important; | |
| border: 1px solid rgba(255, 255, 255, 0.6) !important; | |
| box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.15), 0 4px 10px -2px rgba(0, 0, 0, 0.1) !important; | |
| z-index: 500 !important; /* 確保在地圖之上 (Leaflet 通常是 z-index 400) */ | |
| display: flex !important; | |
| flex-direction: column !important; | |
| transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important; | |
| /* 🔥 關鍵:讓內部元素可以用 Flex 排列 */ | |
| display: flex !important; | |
| flex-direction: column !important; | |
| overflow: hidden !important; /* 防止圓角被內容切掉 */ | |
| } | |
| /* 3. 抽屜標頭 */ | |
| .drawer-header { | |
| padding: 16px 20px !important; | |
| border-bottom: 1px solid #e2e8f0 !important; | |
| background: #f8fafc !important; | |
| border-radius: 16px 16px 0 0 !important; | |
| display: flex !important; | |
| justify-content: space-between !important; | |
| align-items: center !important; | |
| flex-shrink: 0 !important; | |
| height: 60px !important; | |
| } | |
| .drawer-title p { | |
| margin: 0 !important; | |
| font-size: 1rem !important; | |
| font-weight: 700 !important; | |
| color: #334155 !important; | |
| } | |
| .drawer-tabs .tab-nav { | |
| border-bottom: 1px solid #f1f5f9 !important; | |
| margin: 0 !important; | |
| } | |
| /* 5. 關閉按鈕 (X) */ | |
| .drawer-close-btn { | |
| background: transparent !important; | |
| color: #94a3b8 !important; | |
| border: none !important; | |
| box-shadow: none !important; | |
| font-size: 1.2rem !important; | |
| padding: 4px !important; | |
| width: 32px !important; | |
| min-width: 32px !important; | |
| } | |
| .drawer-close-btn:hover { | |
| color: #ef4444 !important; | |
| background: #fef2f2 !important; | |
| border-radius: 50% !important; | |
| } | |
| /* === 修復抽屜開關按鈕 === */ | |
| .map-overlay-btn { | |
| position: absolute !important; | |
| top: 10px !important; | |
| left:60px !important; | |
| /* 🔥 關鍵:必須比 Leaflet 地圖 (400) 和 Drawer (500) 高 */ | |
| z-index: 1000 !important; | |
| background: white !important; | |
| color: #6366f1 !important; | |
| border: 1px solid #cbd5e1 !important; | |
| box-shadow: 0 4px 6px rgba(0,0,0,0.1) !important; | |
| font-weight: 600 !important; | |
| padding: 8px 12px !important; | |
| } | |
| .map-overlay-btn:hover { | |
| transform: translateY(-2px); | |
| box-shadow: 0 6px 10px rgba(0,0,0,0.15) !important; | |
| } | |
| /* 隱藏 Map 預設的 Label */ | |
| .map-container-relative .label-wrap { | |
| display: none !important; | |
| } | |
| /* 顏色修正 (確保不被舊樣式覆蓋) */ | |
| /* --- 2. Page 4: Map Overlay Drawer (捲軸與排版修復) --- */ | |
| /* 抽屜容器:Flex Column 佈局 */ | |
| .map-overlay-drawer { | |
| display: flex !important; | |
| flex-direction: column !important; | |
| max-height: calc(100% - 40px) !important; /* 防止超出地圖邊界 */ | |
| overflow: hidden !important; /* 外層隱藏溢出 */ | |
| background: rgba(255, 255, 255, 0.98) !important; | |
| border: 1px solid rgba(226, 232, 240, 0.8) !important; | |
| z-index: 5000 !important; | |
| height: 85% !important; | |
| max-height: 600px !important; | |
| } | |
| /* Header:固定高度 */ | |
| .drawer-header { | |
| flex-shrink: 0 !important; | |
| height: auto !important; | |
| border-bottom: 1px solid #e2e8f0 !important; | |
| background: #f8fafc !important; | |
| } | |
| /* 🔥 修正 Tab 跑版:移除負邊距,讓它自然排列 */ | |
| .drawer-tabs { | |
| margin-top: 0 !important; /* 還原 margin */ | |
| display: flex !important; | |
| flex-direction: column !important; | |
| height: 100% !important; | |
| } | |
| /* 讓 Tab 的內容區塊也能捲動 */ | |
| .drawer-tabs .tabitem { | |
| overflow-y: visible !important; | |
| height: auto !important; | |
| } | |
| /* 美化捲軸 (Chrome/Safari) */ | |
| .drawer-content::-webkit-scrollbar { | |
| width: 6px; | |
| } | |
| .drawer-content::-webkit-scrollbar-track { | |
| background: transparent; | |
| } | |
| .drawer-content::-webkit-scrollbar-thumb { | |
| background: #cbd5e1; | |
| border-radius: 3px; | |
| } | |
| /* --- 3. Summary Card Modern (漸層色補丁) --- */ | |
| .summary-card-modern { | |
| background: linear-gradient(120deg, #ffffff 0%, #eff6ff 100%) !important; | |
| border: 1px solid #dbeafe !important; | |
| box-shadow: 0 4px 6px -1px rgba(99, 102, 241, 0.1) !important; | |
| } | |
| .header-controls { | |
| position: fixed !important; | |
| top: 24px !important; | |
| right: 24px !important; | |
| z-index: 99999 !important; | |
| display: flex !important; | |
| flex-direction: column !important; /* 垂直排列 */ | |
| gap: 8px !important; | |
| /* 強制縮小寬度,防止佔滿橫條 */ | |
| width: auto !important; | |
| min-width: 0 !important; | |
| height: auto !important; | |
| /* 膠囊視覺還原 */ | |
| background: rgba(255, 255, 255, 0.9) !important; | |
| backdrop-filter: blur(8px) !important; | |
| padding: 8px !important; | |
| border-radius: 50px !important; | |
| border: 1px solid rgba(255, 255, 255, 0.6) !important; | |
| box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08) !important; | |
| } | |
| /* 3. Page 4 Map 滾動條修復:強制高度與捲軸 */ | |
| .map-overlay-drawer { | |
| display: flex !important; | |
| flex-direction: column !important; | |
| height: 85% !important; /* 🔥 必須給定高度,捲軸才會出現 */ | |
| overflow: hidden !important; | |
| } | |
| /* 4. Page 4 Map 按鈕位移:把 Zoom 按鈕移到右邊 */ | |
| .leaflet-left { | |
| left: auto !important; | |
| right: 20px !important; | |
| } | |
| .header-controls { | |
| position: fixed !important; top: 24px !important; right: 24px !important; z-index: 99999 !important; | |
| display: flex !important; flex-direction: column !important; gap: 8px !important; | |
| width: auto !important; height: auto !important; | |
| background: rgba(255, 255, 255, 0.9) !important; backdrop-filter: blur(8px) !important; | |
| padding: 8px !important; border-radius: 50px !important; | |
| border: 1px solid rgba(255, 255, 255, 0.6) !important; | |
| box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08) !important; | |
| } | |
| /* 2. Page 4 Map Drawer: 強制內容區塊顯示 */ | |
| /* 這裡只做最基本的顯示,不搞複雜的捲軸邏輯,讓瀏覽器自己處理 */ | |
| .map-overlay-drawer { | |
| display: flex !important; | |
| flex-direction: column !important; | |
| height: 80% !important; | |
| overflow: hidden !important; | |
| } | |
| .drawer-content { | |
| flex: 1 !important; | |
| overflow-y: auto !important; | |
| background: white !important; /* 確保內容區是白色的 */ | |
| padding: 0 !important; | |
| display: block !important; | |
| } | |
| /* 3. Page 4 Map 按鈕: 不要動它! */ | |
| /* 刪除任何 .leaflet-left 的設定,讓它自己回到左邊 */ | |
| /* 4. 修改 Show Summary 按鈕位置 (避開左邊的原生按鈕) */ | |
| .map-overlay-btn { | |
| position: absolute !important; | |
| top: 10px !important; | |
| left: 60px !important; /* 強制往右移 60px */ | |
| z-index: 5000 !important; | |
| } | |
| 這確實讓人崩潰,那個 "321 / 31" 的斷行顯示 Gradio 內部的 Flex 容器寬度被壓縮到了極限,而藍色方塊依然巨大則是因為 垂直拉伸 (Stretch) 屬性 仍然存在。 | |
| 這表示即使我們拿掉了 height,Gradio 內部的 CSS 權重還是比我們的高,或者是某層 div 被我們之前的 CSS 誤傷導致寬度歸零。 | |
| 請執行這個 「最終純淨版」 修正。這一次,我們不再對抗 Gradio 的 Flex 機制,而是順著它的毛摸,但強制加上「最小寬度」保護,並殺死「垂直拉伸」。 | |
| 1. 確保 app.py 的 height 真的刪掉了 | |
| (如果你剛剛已經刪了,這步請再次確認就好) | |
| Python | |
| chatbot = gr.Chatbot( | |
| label="AI Assistant", | |
| type="messages", | |
| # height=540, <-- 這行絕對不能有 | |
| elem_classes="native-chatbot", | |
| bubble_full_width=False | |
| ) | |
| 2. 替換 ui/theme.py (純淨修復版) | |
| 請全選刪除 ui/theme.py 裡 Chatbot 相關的 CSS,換成這段。這段代碼移除了所有復雜的絕對定位,回歸最單純的排版,但加強了對 寬度 (Width) 的保護。 | |
| CSS | |
| /* ============= 🛡️ LifeFlow Chatbot: 純淨修復版 🛡️ ============= */ | |
| /* 1. 外層容器:給定高度,讓它有捲軸 */ | |
| .chat-panel-native { | |
| background: white !important; | |
| border: 1px solid #e2e8f0 !important; | |
| border-radius: 16px !important; | |
| height: 600px !important; | |
| overflow: hidden !important; | |
| display: flex !important; | |
| flex-direction: column !important; | |
| box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05) !important; | |
| } | |
| /* 2. Chatbot 本體:自然填滿剩餘空間 */ | |
| .native-chatbot { | |
| background: white !important; | |
| flex-grow: 1 !important; | |
| overflow-y: auto !important; | |
| padding: 20px !important; | |
| border: none !important; | |
| } | |
| /* 3. 訊息行 (Row) */ | |
| .native-chatbot .message-row { | |
| display: flex !important; | |
| flex-direction: row !important; | |
| width: 100% !important; | |
| margin-bottom: 16px !important; | |
| /* 🔥 關鍵一:殺死垂直拉伸 (解決巨大方塊) */ | |
| align-items: flex-start !important; | |
| height: auto !important; | |
| /* 避免被壓縮 */ | |
| flex-shrink: 0 !important; | |
| } | |
| /* 4. 氣泡外殼 (Wrapper) - 這是解決 "321/31" 的關鍵 */ | |
| /* 之前的版本可能漏了這個,導致外殼寬度為 0 */ | |
| .native-chatbot .message-wrap { | |
| display: flex !important; | |
| flex-direction: column !important; | |
| /* 🔥 關鍵二:寬度自動,但不能小於內容 */ | |
| width: auto !important; | |
| min-width: 0 !important; | |
| max-width: 85% !important; | |
| flex-shrink: 1 !important; /* 允許在極端狀況下縮小 */ | |
| flex-grow: 0 !important; /* 禁止無故變寬 */ | |
| } | |
| /* 5. 氣泡本體 (Bubble) */ | |
| .native-chatbot .message { | |
| width: fit-content !important; | |
| height: auto !important; | |
| padding: 8px 12px !important; | |
| font-size: 0.95rem !important; | |
| line-height: 1.5 !important; | |
| /* 🔥 關鍵三:正確的斷字設定 */ | |
| white-space: pre-wrap !important; | |
| word-break: break-word !important; | |
| overflow-wrap: break-word !important; | |
| } | |
| /* 6. Bot (靠左) */ | |
| .native-chatbot .message-row:not(.user-row) { | |
| justify-content: flex-start !important; | |
| } | |
| .native-chatbot .message.bot, | |
| .native-chatbot .message.model, | |
| .native-chatbot .message.assistant, | |
| .native-chatbot .message-row:not(.user-row) .message { | |
| background-color: #f1f5f9 !important; | |
| color: #1e293b !important; | |
| border: 1px solid #e2e8f0 !important; | |
| border-radius: 4px 16px 16px 16px !important; | |
| } | |
| .native-chatbot .message.bot *, .native-chatbot .message-row:not(.user-row) .message * { | |
| color: #1e293b !important; | |
| } | |
| /* 7. User (靠右) */ | |
| .native-chatbot .message-row.user-row { | |
| justify-content: flex-end !important; | |
| } | |
| .native-chatbot .message.user, | |
| .native-chatbot .message-row.user-row .message { | |
| background-color: #6366f1 !important; | |
| color: white !important; | |
| border: none !important; | |
| border-radius: 16px 4px 16px 16px !important; | |
| text-align: left !important; | |
| } | |
| .native-chatbot .message.user * { | |
| color: white !important; | |
| } | |
| /* 8. 輸入框 */ | |
| .chat-input-row { | |
| background: white !important; | |
| border-top: 1px solid #e2e8f0 !important; | |
| padding: 16px !important; | |
| flex-shrink: 0 !important; /* 防止被壓扁 */ | |
| } | |
| /* 9. 隱藏垃圾 */ | |
| .native-chatbot button, | |
| .native-chatbot .avatar-container, | |
| .native-chatbot .message-icon { display: none !important; } | |
| </style> | |
| """ |