LifeFlow-AI / ui /theme.py
Marco310's picture
Release v1.0.0: Hybrid AI Architecture, Modern UI Overhaul, and Performance Optimizations
1a2b0fa
raw
history blame
26 kB
# 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-card {
flex: 1;
background: white !important;
border: 1px solid #e2e8f0 !important;
border-radius: 12px !important;
padding: 16px !important;
box-shadow: 0 1px 2px rgba(0,0,0,0.05) !important;
transition: transform 0.2s, box-shadow 0.2s;
display: block !important;
}
.timeline-card:hover {
transform: translateX(4px);
box-shadow: 0 4px 6px rgba(0,0,0,0.05) !important;
border-color: var(--primary-color) !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 {
display: flex; align-items: center; gap: 8px; font-size: 0.85rem; color: #64748b;
background: #f8fafc; padding: 8px; border-radius: 8px; margin-top: 8px;
}
.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 { flex: 1; position: sticky; overflow-y: auto; }
.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; }
/* 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; /* 預留高度防止跳動 */
}
</style>
"""