"""Dark neon theme and CSS for the Quant Research Environment UI.""" import gradio as gr from gradio.themes.utils import colors, fonts, sizes _CYAN = colors.Color( c50="#e0fcff", c100="#b8f3ff", c200="#81ecff", c300="#4de5ff", c400="#00e5ff", c500="#00b8d4", c600="#0097a7", c700="#00838f", c800="#006064", c900="#004d40", c950="#003330", name="cyan", ) _DARK_NEUTRAL = colors.Color( c50="#f0f6fc", c100="#c9d1d9", c200="#b1bac4", c300="#8b949e", c400="#6e7681", c500="#484f58", c600="#30363d", c700="#21262d", c800="#161b22", c900="#0d1117", c950="#010409", name="dark_neutral", ) DARK_THEME = gr.themes.Base( primary_hue=_CYAN, secondary_hue=_CYAN, neutral_hue=_DARK_NEUTRAL, font=[ fonts.GoogleFont("Inter"), "ui-sans-serif", "system-ui", "sans-serif", ], font_mono=[ fonts.GoogleFont("JetBrains Mono"), "Fira Code", "Consolas", "monospace", ], radius_size=sizes.radius_sm, ).set( body_background_fill="#0d1117", body_background_fill_dark="#0d1117", body_text_color="#c9d1d9", body_text_color_dark="#c9d1d9", body_text_color_subdued="#8b949e", body_text_color_subdued_dark="#8b949e", block_background_fill="#161b22", block_background_fill_dark="#161b22", block_border_color="#30363d", block_border_color_dark="#30363d", block_label_text_color="#c9d1d9", block_label_text_color_dark="#c9d1d9", block_title_text_color="#c9d1d9", block_title_text_color_dark="#c9d1d9", panel_background_fill="#0d1117", panel_background_fill_dark="#0d1117", panel_border_color="#30363d", panel_border_color_dark="#30363d", input_background_fill="#0d1117", input_background_fill_dark="#0d1117", input_border_color="#30363d", input_border_color_dark="#30363d", button_primary_background_fill="#7c4dff", button_primary_background_fill_dark="#7c4dff", button_primary_background_fill_hover="#9c6fff", button_primary_background_fill_hover_dark="#9c6fff", button_primary_text_color="#ffffff", button_primary_text_color_dark="#ffffff", button_secondary_background_fill="#21262d", button_secondary_background_fill_dark="#21262d", button_secondary_text_color="#c9d1d9", button_secondary_text_color_dark="#c9d1d9", border_color_primary="#30363d", border_color_primary_dark="#30363d", color_accent_soft="#1a1a2e", color_accent_soft_dark="#1a1a2e", ) NEON_CSS = """ /* ========================================= LAYOUT: full-width container, no shifting ========================================= */ .gradio-container { background: #0d1117 !important; max-width: 100% !important; width: 100% !important; padding: 0 !important; margin: 0 !important; } /* Inner wrapper stays centered with max width */ .main, .contain { max-width: 1200px !important; margin: 0 auto !important; padding: 0 24px !important; width: 100% !important; box-sizing: border-box !important; } /* ========================================= TABS: pill-style, sticky, no layout shift ========================================= */ .tabs { width: 100% !important; } .tabs > .tab-nav { position: sticky !important; top: 0 !important; z-index: 100 !important; background: #0d1117 !important; border-bottom: 1px solid #21262d !important; padding: 8px 0 0 0 !important; margin: 0 !important; display: flex !important; gap: 6px !important; justify-content: center !important; flex-wrap: nowrap !important; overflow-x: auto !important; } .tabs > .tab-nav > button { color: #8b949e !important; background: #161b22 !important; border: 1px solid #21262d !important; border-bottom: none !important; border-radius: 8px 8px 0 0 !important; font-weight: 600 !important; font-size: 0.88em !important; padding: 10px 28px !important; transition: all 0.15s ease !important; white-space: nowrap !important; flex-shrink: 0 !important; letter-spacing: 0.2px !important; } .tabs > .tab-nav > button.selected { color: #e0e0e0 !important; background: #1a1a2e !important; border-color: #7c4dff !important; border-bottom: 2px solid #0d1117 !important; box-shadow: 0 -2px 8px rgba(124, 77, 255, 0.15) !important; } .tabs > .tab-nav > button:hover:not(.selected) { color: #c9d1d9 !important; background: #1c2028 !important; border-color: #30363d !important; } /* CRITICAL: Force all tab panels to same fixed width so switching doesn't shift */ .tabitem { width: 100% !important; max-width: 100% !important; min-height: 70vh !important; padding: 20px 0 !important; box-sizing: border-box !important; } /* Force all children inside tabs to respect full width */ .tabitem > div { width: 100% !important; max-width: 100% !important; } /* ========================================= MARKDOWN ========================================= */ .prose h1, .prose h2, .prose h3, .markdown-text h1, .markdown-text h2, .markdown-text h3 { color: #e0e0e0 !important; border-bottom: 1px solid #21262d; padding-bottom: 6px; } .prose h1, .markdown-text h1 { font-size: 1.5em !important; } .prose h2, .markdown-text h2 { font-size: 1.25em !important; color: #c9a0ff !important; } .prose h3, .markdown-text h3 { font-size: 1.05em !important; color: #8b949e !important; } .prose, .prose p, .prose li, .prose td, .prose th, .markdown-text, .markdown-text p, .markdown-text li, .markdown-text td, .markdown-text th { color: #b0b8c1 !important; } .prose strong, .markdown-text strong { color: #e6edf3 !important; } .prose code, .markdown-text code { background: #1a1a2e !important; color: #c9a0ff !important; padding: 2px 6px !important; border-radius: 3px !important; font-size: 0.88em !important; } .prose pre, .markdown-text pre { background: #0d1117 !important; border: 1px solid #21262d !important; border-radius: 6px !important; overflow-x: auto !important; } .prose pre code, .markdown-text pre code { color: #b0b8c1 !important; background: transparent !important; } /* ========================================= TABLES ========================================= */ .prose table, .markdown-text table { border-collapse: collapse !important; width: 100% !important; table-layout: auto !important; overflow-x: auto !important; display: block !important; } .prose th, .markdown-text th { background: #161b22 !important; color: #c9a0ff !important; font-weight: 600 !important; padding: 10px 14px !important; border: 1px solid #21262d !important; text-align: left !important; font-size: 0.85em !important; text-transform: uppercase !important; letter-spacing: 0.3px !important; white-space: nowrap !important; } .prose td, .markdown-text td { padding: 8px 14px !important; border: 1px solid #1a1f26 !important; color: #b0b8c1 !important; } .prose tr:nth-child(even), .markdown-text tr:nth-child(even) { background: rgba(22, 27, 34, 0.5) !important; } /* ========================================= BUTTONS ========================================= */ .primary { background: #7c4dff !important; border: none !important; box-shadow: 0 2px 8px rgba(124, 77, 255, 0.25) !important; transition: all 0.15s ease !important; font-weight: 600 !important; } .primary:hover { background: #9c6fff !important; box-shadow: 0 4px 16px rgba(124, 77, 255, 0.35) !important; transform: translateY(-1px); } /* ========================================= INPUTS ========================================= */ textarea, input[type="text"] { background: #0d1117 !important; border: 1px solid #30363d !important; color: #c9d1d9 !important; } textarea:focus, input[type="text"]:focus { border-color: #7c4dff !important; box-shadow: 0 0 0 2px rgba(124, 77, 255, 0.15) !important; } /* ========================================= ACCORDION ========================================= */ .accordion { border: 1px solid #21262d !important; background: #161b22 !important; } /* ========================================= SCROLLBAR ========================================= */ ::-webkit-scrollbar { width: 6px; height: 6px; } ::-webkit-scrollbar-track { background: #0d1117; } ::-webkit-scrollbar-thumb { background: #30363d; border-radius: 3px; } ::-webkit-scrollbar-thumb:hover { background: #484f58; } /* ========================================= DATAFRAME ========================================= */ .dataframe th { background: #161b22 !important; color: #c9a0ff !important; } .dataframe td { color: #b0b8c1 !important; } /* ========================================= RESPONSIVE: mobile + tablet ========================================= */ @media (max-width: 768px) { .main, .contain { padding: 0 12px !important; } .tabs > .tab-nav > button { padding: 8px 14px !important; font-size: 0.8em !important; } .tabs > .tab-nav { gap: 3px !important; justify-content: flex-start !important; overflow-x: auto !important; -webkit-overflow-scrolling: touch !important; } /* Stack playground columns vertically on mobile */ .playground-row { flex-direction: column !important; } } @media (max-width: 480px) { .tabs > .tab-nav > button { padding: 8px 10px !important; font-size: 0.75em !important; } } @media (min-width: 1600px) { .main, .contain { max-width: 1400px !important; } } /* ========================================= HIDE FOOTER ========================================= */ footer { display: none !important; } """