# --- CSS: NEO-BRUTALISM / POP-CYBER --- NEO_CSS = """ @import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;700&display=swap'); @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;700&display=swap'); :root { --bg-color: #E0E7F1; --card-bg: #FFFFFF; --border-color: #000000; --border-width: 3px; --shadow-offset: 12px; --accent-primary: #5E6AD2; /* Blurple */ --accent-secondary: #FF90E8; /* Pink */ --accent-tertiary: #00FF94; /* Green */ --font-main: 'Space Grotesk', sans-serif; --font-mono: 'JetBrains Mono', monospace; } body, gradio-app { font-family: var(--font-main) !important; background-color: var(--bg-color) !important; background-image: radial-gradient(#000 1px, transparent 1px) !important; background-size: 24px 24px !important; /* Dot Grid Pattern */ color: #000 !important; margin: 0 !important; height: 100vh !important; overflow: hidden !important; } /* --- LAYOUT UTILS --- */ .gradio-container { max-width: 100% !important; height: 100vh !important; padding: 32px !important; box-sizing: border-box !important; display: flex !important; flex-direction: column !important; } /* Main Flex Row - Forces both children to respect flex rules */ .main-row { flex: 1 !important; /* Fill remaining height */ height: auto !important; gap: 32px !important; display: flex !important; justify-content: center !important; align-items: stretch !important; /* Force full height */ width: 100% !important; } /* --- 1. SIDEBAR (The Control Panel) --- */ .sidebar-col { background: #FFFFFF !important; border: var(--border-width) solid var(--border-color) !important; box-shadow: var(--shadow-offset) var(--shadow-offset) 0px #000000 !important; padding: 32px !important; display: flex !important; flex-direction: column !important; /* RESPONSIVE RULES - PROPORTIONAL */ flex: 3 !important; /* Take up 3 parts */ width: 30% !important; min-width: 250px !important; /* Allow shrinking but prevent breaking */ border-radius: 0px !important; z-index: 10; height: auto !important; /* Follow parent stretch */ } /* Sidebar Branding */ .brand-box { background: #000; color: #FFF; padding: 20px; font-family: var(--font-mono); font-weight: 700; font-size: 24px; text-transform: uppercase; margin-bottom: 40px; border: 2px solid #000; text-align: center; letter-spacing: 2px; } /* Sidebar Buttons */ .nav-btn { background: #FFFFFF !important; border: 3px solid #000 !important; border-radius: 0px !important; margin-bottom: 20px !important; font-family: var(--font-main) !important; font-weight: 700 !important; font-size: 18px !important; color: #000 !important; box-shadow: 6px 6px 0px #000 !important; transition: all 0.1s !important; text-align: left !important; padding: 16px 24px !important; } .nav-btn:hover { transform: translate(-4px, -4px) !important; box-shadow: 10px 10px 0px #000 !important; background: var(--accent-secondary) !important; } .nav-btn:active { transform: translate(2px, 2px) !important; box-shadow: 2px 2px 0px #000 !important; } /* --- 2. MAIN AREA (The Workspace) --- */ .main-col { background: #FFFFFF !important; border: var(--border-width) solid var(--border-color) !important; box-shadow: var(--shadow-offset) var(--shadow-offset) 0px #000000 !important; padding: 0 !important; position: relative !important; display: flex !important; flex-direction: column !important; overflow: hidden !important; /* RESPONSIVE RULES - PROPORTIONAL */ flex: 7 !important; /* Take up 7 parts */ width: 70% !important; max-width: 100% !important; /* Remove limit to fill space */ height: 100% !important; /* Fix height collapse */ } /* Top Bar (Status) */ .top-bar { border-bottom: var(--border-width) solid #000; padding: 16px 10px; /* CHANGED: Reduced right padding to move READY badge to edge */ background: #FFF; display: flex; justify-content: space-between; align-items: center; height: 80px; flex-shrink: 0 !important; /* Don't shrink */ } /* Chat Area */ .chat-area { flex-grow: 1 !important; overflow-y: auto !important; padding: 30px 10% 140px 10% !important; background: #FFF !important; height: 100% !important; } /* Gradio cleanup */ .chat-area .wrap { border: none !important; box-shadow: none !important; height: 100% !important;} .gradio-container .prose { background: transparent !important; } /* Bubbles - Neo Style (Gradio 4.x compatible) */ /* USER: Now White with Black Text */ .message.user, .message-row.user-row .message { background: #FFFFFF !important; color: #000000 !important; border: 3px solid #000 !important; border-radius: 0px !important; box-shadow: 6px 6px 0px #000 !important; padding: 16px 24px !important; font-weight: 700 !important; /* BOLD TEXT */ font-size: 16px !important; } /* Force User Children Black & Bold */ .message.user *, .message.user p, .message.user div { color: #000000 !important; font-weight: 700 !important; } /* BOT: Now Accent with White Text */ .message.bot, .message-row.bot-row .message { background: var(--accent-primary) !important; color: #FFFFFF !important; border: 3px solid #000 !important; border-radius: 0px !important; box-shadow: 6px 6px 0px #000 !important; padding: 16px 24px !important; font-family: var(--font-mono) !important; font-weight: 700 !important; /* BOLD TEXT */ font-size: 15px !important; } /* Force Bot Children White & Bold */ .message.bot *, .message.bot p, .message.bot div, .message.bot span { color: #FFFFFF !important; font-weight: 700 !important; } /* FIX: Add padding to bottom of chat list so last message isn't hidden behind Input Box */ .bubble-wrap, .message-wrap { padding-bottom: 160px !important; } /* Input Area */ .input-wrapper { position: absolute; bottom: 0; left: 0; right: 0; padding: 30px; background: #FFFFFF; border-top: var(--border-width) solid #000; z-index: 20; } .chat-input textarea { background: #FFF !important; border: 3px solid #000 !important; border-radius: 0px !important; padding: 20px !important; font-family: var(--font-mono) !important; font-size: 18px !important; color: #000000 !important; /* Darker Text */ box-shadow: inset 4px 4px 0px rgba(0,0,0,0.1) !important; } .chat-input textarea:focus { background: #FFFCF0 !important; border-color: #000 !important; color: #000000 !important; } .chat-input textarea::placeholder { color: #333333 !important; /* Darker Placeholder */ opacity: 1 !important; } /* --- WIDGETS --- */ /* Status Badge */ .neo-status-badge { border: 3px solid #000; padding: 6px 16px; border-radius: 30px; display: inline-block; box-shadow: 3px 3px 0px #000; } .neo-status-text { font-family: var(--font-mono); font-weight: 700; font-size: 14px; color: #000; letter-spacing: 1px; } /* Inspector (Right Sidebar Stub) */ .inspector-box { border: 2px solid #000; background: #EEE; padding: 12px; font-family: var(--font-mono); font-size: 12px; margin-top: 12px; box-shadow: 4px 4px 0px #000; } .inspector-label { font-weight: 700; margin-bottom: 6px; } /* --- VIEW CONTAINERS (Isolation) --- */ .chat-view, .tools-view { flex-grow: 1 !important; display: flex !important; flex-direction: column !important; overflow: hidden !important; border: none !important; padding: 0 !important; margin: 0 !important; background: transparent !important; } /* --- MCP DESKTOP (App Icon Style - Neo Brutalist) --- */ .mcp-desktop { display: flex; flex-direction: column; height: 100%; background: transparent; /* Transparent to show white main-col background */ padding: 0; overflow: hidden; align-items: center; justify-content: center; } .desktop-grid { display: grid; grid-template-columns: repeat(3, 110px); gap: 28px; padding: 40px; justify-content: center; align-content: center; } /* --- MCP APP ICON (Neo-Brutalist Card) --- */ .mcp-app { display: flex; flex-direction: column; align-items: center; gap: 10px; cursor: pointer; transition: all 0.1s ease; position: relative; } .mcp-app:hover { transform: translate(-3px, -3px); } .mcp-app:active { transform: translate(2px, 2px); } .app-icon { width: 80px; height: 80px; background: #FFFFFF; border: 3px solid #000000; box-shadow: 6px 6px 0px #000000; display: flex; align-items: center; justify-content: center; font-size: 36px; transition: all 0.1s ease; } .mcp-app:hover .app-icon { box-shadow: 10px 10px 0px #000000; } .mcp-app:active .app-icon { box-shadow: 2px 2px 0px #000000; } /* Active State: Same as inactive, indicator dot shows status */ .mcp-app.active .app-icon { border-color: #000000; box-shadow: 6px 6px 0px #000000; } .mcp-app.active:hover .app-icon { box-shadow: 10px 10px 0px #000000; } .mcp-app.active:active .app-icon { box-shadow: 2px 2px 0px #000000; } .app-name { font-family: var(--font-mono); font-size: 12px; font-weight: 700; color: #000000; text-align: center; max-width: 90px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } /* Active Indicator (Small Green Dot) */ .app-indicator { position: absolute; top: -4px; right: 6px; width: 12px; height: 12px; background: var(--accent-tertiary); border: 2px solid #000; box-shadow: 2px 2px 0px #000; } /* Add New Button */ .mcp-app.add-new .app-icon { background: transparent; border-style: dashed; border-color: #999; box-shadow: none; font-size: 28px; color: #999; } .mcp-app.add-new:hover .app-icon { border-color: #000; color: #000; background: rgba(0,0,0,0.03); box-shadow: none; } .mcp-app.add-new .app-name { color: #999; } .mcp-app.add-new:hover .app-name { color: #000; } /* Page Indicator (Pagination Dots) */ .desktop-pagination { display: flex; gap: 10px; padding: 24px; } .page-dot { width: 10px; height: 10px; background: #CCC; border: 2px solid #000; cursor: pointer; transition: all 0.15s; } .page-dot:hover { background: #999; } .page-dot.active { background: #000; width: 28px; } /* --- INSPECTOR VIEW --- */ .inspector-view { flex-grow: 1 !important; display: flex !important; flex-direction: column !important; overflow: hidden !important; border: none !important; padding: 0 !important; margin: 0 !important; background: transparent !important; } .inspector-panel { display: flex; flex-direction: column; background: #0a0a0a; height: 100%; /* Fill parent container */ max-height: 600px; /* Same as chatbot height */ overflow: hidden; font-family: var(--font-mono); font-size: 12px; border-radius: 8px; } .inspector-header { display: flex; justify-content: space-between; align-items: center; padding: 12px 16px; background: #111; border-bottom: 1px solid #333; } .inspector-title { font-weight: 700; color: #888; } .inspector-status { color: var(--accent-tertiary); font-size: 11px; } .inspector-log { flex: 1; overflow-y: auto; overflow-x: hidden; padding: 12px; display: flex; flex-direction: column; gap: 8px; scroll-behavior: smooth; } .log-entry { background: #151515; border: 1px solid #222; padding: 10px 12px; border-radius: 4px; } .log-entry.outgoing { border-left: 3px solid var(--accent-secondary); } .log-entry.incoming { border-left: 3px solid var(--accent-tertiary); } .log-entry.highlight { background: rgba(0, 255, 148, 0.05); border: 1px solid var(--accent-tertiary); } /* === BIDIRECTIONAL COMMUNICATION HIGHLIGHT === */ /* Special styling for our custom client_state notifications */ .log-entry.bidirectional { background: linear-gradient(135deg, rgba(94, 106, 210, 0.15), rgba(255, 144, 232, 0.15)) !important; border: 2px solid var(--accent-primary) !important; border-left: 4px solid var(--accent-secondary) !important; box-shadow: 0 0 10px rgba(94, 106, 210, 0.3); animation: bidirectional-pulse 2s infinite; } .log-entry.bidirectional .log-direction { background: linear-gradient(135deg, var(--accent-primary), var(--accent-secondary)) !important; color: #FFF !important; font-weight: 700; } .log-entry.bidirectional .log-method { color: var(--accent-secondary) !important; font-weight: 700; } @keyframes bidirectional-pulse { 0%, 100% { box-shadow: 0 0 5px rgba(94, 106, 210, 0.3); } 50% { box-shadow: 0 0 15px rgba(255, 144, 232, 0.5); } } .log-direction { font-size: 10px; font-weight: 700; padding: 2px 6px; border-radius: 3px; margin-right: 8px; } .log-entry.outgoing .log-direction { background: rgba(255, 230, 0, 0.15); color: var(--accent-secondary); } .log-entry.incoming .log-direction { background: rgba(0, 255, 148, 0.15); color: var(--accent-tertiary); } .log-method { color: #FFF; font-weight: 600; } .log-payload { margin: 8px 0 0 0; padding: 8px; background: #0a0a0a; border-radius: 3px; color: #888; white-space: pre-wrap; word-break: break-all; font-size: 11px; line-height: 1.4; } .inspector-footer { padding: 10px 16px; background: #111; border-top: 1px solid #333; color: #666; font-size: 11px; } /* --- SECONDARY NAV BUTTON --- */ .nav-btn-secondary { opacity: 0.6; border-style: dashed !important; } .nav-btn-secondary:hover { opacity: 1; } /* --- TOOLS VIEW CONTAINERS --- */ .tools-desktop-container { display: flex; flex-direction: column; align-items: center; gap: 16px; padding: 24px; } /* Server Grid - 3x3 layout like app desktop */ .server-grid { display: grid !important; grid-template-columns: repeat(3, 100px) !important; gap: 24px !important; justify-content: center !important; padding: 32px !important; } /* Server Card Button - App Icon Style (emoji in box, name below) */ .server-card-btn { width: 100px !important; height: auto !important; min-height: 100px !important; background: transparent !important; border: none !important; border-radius: 0 !important; box-shadow: none !important; font-family: var(--font-mono) !important; font-size: 11px !important; font-weight: 700 !important; color: #000000 !important; cursor: pointer !important; transition: all 0.15s ease !important; padding: 0 !important; display: flex !important; flex-direction: column !important; align-items: center !important; justify-content: flex-start !important; gap: 8px !important; white-space: pre-line !important; line-height: 1.2 !important; text-align: center !important; } /* The button text contains emoji + newline + name */ /* We style it so emoji appears large, name appears small below */ .server-card-btn span, .server-card-btn { font-size: 11px !important; } /* Use first-line to make emoji bigger - but this won't work well */ /* Instead, we'll create a visual box effect with background */ /* Create the icon box effect */ .server-card-btn::before { content: ""; display: block; width: 72px; height: 72px; background: #FFFFFF; border: 3px solid #000000; box-shadow: 6px 6px 0px #000000; position: absolute; top: 0; left: 50%; transform: translateX(-50%); z-index: 0; transition: all 0.15s ease; } .server-card-btn { position: relative !important; padding-top: 80px !important; } .server-card-btn:hover::before { transform: translateX(-50%) translate(-3px, -3px); box-shadow: 10px 10px 0px #000000; } .server-card-btn:active::before { transform: translateX(-50%) translate(2px, 2px); box-shadow: 2px 2px 0px #000000; } /* Install Card Button - Dashed style */ .install-card-btn { width: 100px !important; height: auto !important; min-height: 100px !important; background: transparent !important; border: none !important; box-shadow: none !important; font-family: var(--font-mono) !important; font-size: 11px !important; font-weight: 400 !important; color: #999999 !important; cursor: pointer !important; transition: all 0.15s ease !important; padding: 0 !important; display: flex !important; flex-direction: column !important; align-items: center !important; justify-content: flex-start !important; gap: 8px !important; white-space: pre-line !important; line-height: 1.2 !important; text-align: center !important; position: relative !important; padding-top: 80px !important; } .install-card-btn::before { content: "+"; display: flex; align-items: center; justify-content: center; width: 72px; height: 72px; background: transparent; border: 3px dashed #999999; font-size: 32px; color: #999999; position: absolute; top: 0; left: 50%; transform: translateX(-50%); transition: all 0.15s ease; } .install-card-btn:hover { color: var(--accent-primary) !important; } .install-card-btn:hover::before { border-color: var(--accent-primary); color: var(--accent-primary); } /* Install Nav Button - Special styling for sidebar install button */ .install-nav-btn { background: var(--accent-tertiary) !important; color: #000000 !important; border-style: solid !important; } .install-nav-btn:hover { background: #00CC77 !important; } /* Server Selector Dropdown */ .server-selector select { font-family: var(--font-mono) !important; border: 2px solid var(--border-color) !important; border-radius: 0 !important; } /* Server Detail Container */ .server-detail-container { background: var(--card-bg); border: var(--border-width) solid var(--border-color); box-shadow: var(--shadow-offset) var(--shadow-offset) 0px var(--border-color); padding: 24px; } .server-detail-container h2 { font-family: var(--font-mono); margin: 0 0 24px 0; } .server-detail-container .detail-row { margin-bottom: 16px; } .server-detail-container .detail-label { font-family: var(--font-mono); font-size: 12px; color: #666; margin-bottom: 4px; } .server-detail-container .detail-value { font-family: var(--font-mono); background: #F5F5F5; padding: 12px; border: 1px solid #DDD; } /* Danger Button */ .neo-btn-danger { background: #FF3333 !important; color: #FFFFFF !important; border: var(--border-width) solid var(--border-color) !important; box-shadow: 6px 6px 0px var(--border-color) !important; font-family: var(--font-mono) !important; font-weight: 700 !important; padding: 12px 24px !important; cursor: pointer !important; transition: all 0.1s ease !important; } .neo-btn-danger:hover { background: #CC0000 !important; transform: translate(-2px, -2px) !important; box-shadow: 8px 8px 0px var(--border-color) !important; } .neo-btn-danger:active { transform: translate(2px, 2px) !important; box-shadow: 2px 2px 0px var(--border-color) !important; } /* Install Form View - White background, no dark sections */ .install-form-view { background: var(--card-bg) !important; border: var(--border-width) solid var(--border-color) !important; box-shadow: var(--shadow-offset) var(--shadow-offset) 0px var(--border-color) !important; padding: 24px !important; } /* Override any dark backgrounds in install form */ .install-form-view .gr-form, .install-form-view .gr-box, .install-form-view .gr-panel, .install-form-view > div { background: transparent !important; } /* Detail Input - Used in Install Form and Server Detail */ .detail-input { background: transparent !important; } /* Force Label Color to Black - targeting Gradio's internal classes */ .detail-input label, .detail-input span.svelte-1gfkn6j, /* Gradio internal class for label */ .detail-input .label-wrap span { font-family: var(--font-mono) !important; font-size: 11px !important; font-weight: 700 !important; color: #000000 !important; /* Force Black */ opacity: 1 !important; letter-spacing: 0.5px !important; text-transform: uppercase !important; background: transparent !important; } .detail-input input, .detail-input textarea { font-family: var(--font-mono) !important; font-size: 14px !important; border: 2px solid #000000 !important; /* Black border */ border-radius: 0 !important; background: #FFFFFF !important; /* White background */ color: #000000 !important; /* Black text */ padding: 12px !important; } .detail-input input::placeholder, .detail-input textarea::placeholder { color: #666666 !important; /* Darker placeholder */ opacity: 0.7 !important; } .detail-input input:focus, .detail-input textarea:focus { border-color: var(--accent-primary) !important; box-shadow: 4px 4px 0px var(--accent-primary) !important; background: #FFFFFF !important; } /* Neo Button Primary */ .neo-btn-primary { background: var(--accent-primary) !important; color: #FFFFFF !important; border: var(--border-width) solid var(--border-color) !important; box-shadow: 6px 6px 0px var(--border-color) !important; font-family: var(--font-mono) !important; font-weight: 700 !important; padding: 12px 24px !important; cursor: pointer !important; transition: all 0.1s ease !important; } .neo-btn-primary:hover { transform: translate(-2px, -2px) !important; box-shadow: 8px 8px 0px var(--border-color) !important; } .neo-btn-primary:active { transform: translate(2px, 2px) !important; box-shadow: 2px 2px 0px var(--border-color) !important; } /* Neo Button Secondary */ .neo-btn-secondary { background: #FFFFFF !important; color: #000000 !important; border: var(--border-width) solid var(--border-color) !important; box-shadow: 6px 6px 0px var(--border-color) !important; font-family: var(--font-mono) !important; font-weight: 700 !important; padding: 12px 24px !important; cursor: pointer !important; transition: all 0.1s ease !important; } .neo-btn-secondary:hover { transform: translate(-2px, -2px) !important; box-shadow: 8px 8px 0px var(--border-color) !important; } /* Server Detail View */ .server-detail-container { background: var(--card-bg); border: var(--border-width) solid var(--border-color); box-shadow: var(--shadow-offset) var(--shadow-offset) 0px var(--border-color); padding: 24px; } /* Detail Row - Label + Value */ .detail-row { margin-bottom: 16px; } .detail-label { font-family: var(--font-mono); font-size: 11px; font-weight: 700; color: #666; margin-bottom: 6px; letter-spacing: 0.5px; } .detail-value { font-family: var(--font-mono); font-size: 14px; background: #F5F5F5; padding: 12px; border: 1px solid #DDD; color: #000000; } .detail-value code { background: transparent; font-family: var(--font-mono); } /* Server Detail Action Buttons - Equal Width */ .server-detail-container .row { display: flex !important; gap: 12px !important; } .server-detail-container .neo-btn-primary, .server-detail-container .neo-btn-secondary, .server-detail-container .neo-btn-danger { flex: 1 !important; min-width: 0 !important; text-align: center !important; } /* Connected Server Card - Green Border */ .server-card-btn.connected::before { border-color: var(--accent-tertiary) !important; box-shadow: 6px 6px 0px var(--accent-tertiary) !important; } .server-card-btn.connected:hover::before { box-shadow: 10px 10px 0px var(--accent-tertiary) !important; } """