Spaces:
Paused
Paused
| """ | |
| Custom Gradio Theme for Akatsuki AI Technologies | |
| Professional branding and styling for the CEO chatbot interface. | |
| Example usage: | |
| import gradio as gr | |
| from app.theme import get_akatsuki_theme, CUSTOM_CSS | |
| with gr.Blocks(theme=get_akatsuki_theme(), css=CUSTOM_CSS) as demo: | |
| ... | |
| """ | |
| try: | |
| import gradio as gr | |
| from gradio.themes.base import Base | |
| from gradio.themes.utils import colors, fonts, sizes | |
| GRADIO_AVAILABLE = True | |
| except ImportError: | |
| GRADIO_AVAILABLE = False | |
| # Akatsuki Brand Colors | |
| AKATSUKI_COLORS = { | |
| "primary": "#1a1a2e", # Deep navy | |
| "secondary": "#16213e", # Dark blue | |
| "accent": "#0f3460", # Medium blue | |
| "highlight": "#e94560", # Red accent | |
| "text_primary": "#ffffff", | |
| "text_secondary": "#a0a0a0", | |
| "background": "#0f0f23", | |
| "surface": "#1a1a2e", | |
| "border": "#2a2a4e", | |
| } | |
| def get_akatsuki_theme(): | |
| """ | |
| Create custom Gradio theme for Akatsuki AI Technologies. | |
| Returns: | |
| Gradio theme object | |
| """ | |
| if not GRADIO_AVAILABLE: | |
| return None | |
| return gr.themes.Base( | |
| primary_hue=gr.themes.Color( | |
| c50="#e8e8f0", | |
| c100="#c5c5d8", | |
| c200="#9f9fc0", | |
| c300="#7878a8", | |
| c400="#5a5a96", | |
| c500="#1a1a2e", | |
| c600="#16213e", | |
| c700="#0f3460", | |
| c800="#0a2540", | |
| c900="#051525", | |
| c950="#020a10", | |
| ), | |
| secondary_hue=gr.themes.Color( | |
| c50="#fff0f3", | |
| c100="#ffd6de", | |
| c200="#ffb3c1", | |
| c300="#ff8fa3", | |
| c400="#ff6b88", | |
| c500="#e94560", | |
| c600="#d63d56", | |
| c700="#c2354c", | |
| c800="#9e2b3e", | |
| c900="#7a2130", | |
| c950="#4a1420", | |
| ), | |
| neutral_hue=gr.themes.Color( | |
| c50="#f5f5f7", | |
| c100="#e5e5ea", | |
| c200="#d1d1d6", | |
| c300="#aeaeb2", | |
| c400="#8e8e93", | |
| c500="#636366", | |
| c600="#48484a", | |
| c700="#3a3a3c", | |
| c800="#2c2c2e", | |
| c900="#1c1c1e", | |
| c950="#0f0f10", | |
| ), | |
| font=[ | |
| gr.themes.GoogleFont("Inter"), | |
| "ui-sans-serif", | |
| "system-ui", | |
| "sans-serif", | |
| ], | |
| font_mono=[ | |
| gr.themes.GoogleFont("JetBrains Mono"), | |
| "ui-monospace", | |
| "monospace", | |
| ], | |
| ).set( | |
| # Body | |
| body_background_fill="#0f0f23", | |
| body_background_fill_dark="#0a0a18", | |
| # Blocks | |
| block_background_fill="#1a1a2e", | |
| block_background_fill_dark="#151528", | |
| block_border_color="#2a2a4e", | |
| block_border_width="1px", | |
| block_label_background_fill="#16213e", | |
| block_label_text_color="#ffffff", | |
| block_radius="12px", | |
| block_shadow="0 4px 6px -1px rgba(0, 0, 0, 0.3)", | |
| # Inputs | |
| input_background_fill="#16213e", | |
| input_background_fill_dark="#121225", | |
| input_border_color="#2a2a4e", | |
| input_border_width="1px", | |
| input_radius="8px", | |
| # Buttons | |
| button_primary_background_fill="#e94560", | |
| button_primary_background_fill_hover="#d63d56", | |
| button_primary_text_color="#ffffff", | |
| button_secondary_background_fill="#0f3460", | |
| button_secondary_background_fill_hover="#16213e", | |
| button_secondary_text_color="#ffffff", | |
| # Text | |
| body_text_color="#ffffff", | |
| body_text_color_subdued="#a0a0a0", | |
| ) | |
| # Custom CSS for additional styling | |
| CUSTOM_CSS = """ | |
| /* Global styles */ | |
| .gradio-container { | |
| max-width: 1200px !important; | |
| margin: auto !important; | |
| } | |
| /* Header styling */ | |
| .header-container { | |
| text-align: center; | |
| padding: 2rem 1rem; | |
| background: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%); | |
| border-radius: 12px; | |
| margin-bottom: 1.5rem; | |
| border: 1px solid #2a2a4e; | |
| } | |
| .header-title { | |
| font-size: 2rem; | |
| font-weight: 700; | |
| color: #ffffff; | |
| margin-bottom: 0.5rem; | |
| } | |
| .header-subtitle { | |
| font-size: 1rem; | |
| color: #a0a0a0; | |
| } | |
| .header-logo { | |
| width: 80px; | |
| height: 80px; | |
| margin-bottom: 1rem; | |
| border-radius: 50%; | |
| border: 3px solid #e94560; | |
| } | |
| /* Chat container */ | |
| .chat-container { | |
| border: 1px solid #2a2a4e; | |
| border-radius: 12px; | |
| overflow: hidden; | |
| } | |
| /* Message styling */ | |
| .message { | |
| padding: 1rem; | |
| margin: 0.5rem; | |
| border-radius: 12px; | |
| } | |
| .user-message { | |
| background: #0f3460 !important; | |
| border: 1px solid #2a2a4e; | |
| } | |
| .bot-message { | |
| background: #1a1a2e !important; | |
| border: 1px solid #2a2a4e; | |
| } | |
| /* Input area */ | |
| .input-area { | |
| background: #16213e; | |
| padding: 1rem; | |
| border-top: 1px solid #2a2a4e; | |
| } | |
| /* Buttons */ | |
| .primary-btn { | |
| background: linear-gradient(135deg, #e94560 0%, #d63d56 100%) !important; | |
| border: none !important; | |
| font-weight: 600 !important; | |
| transition: transform 0.2s, box-shadow 0.2s !important; | |
| } | |
| .primary-btn:hover { | |
| transform: translateY(-2px) !important; | |
| box-shadow: 0 4px 12px rgba(233, 69, 96, 0.4) !important; | |
| } | |
| .secondary-btn { | |
| background: transparent !important; | |
| border: 1px solid #2a2a4e !important; | |
| color: #a0a0a0 !important; | |
| } | |
| .secondary-btn:hover { | |
| background: #16213e !important; | |
| color: #ffffff !important; | |
| } | |
| /* Status indicator */ | |
| .status-container { | |
| display: flex; | |
| align-items: center; | |
| gap: 0.5rem; | |
| padding: 0.5rem 1rem; | |
| background: #16213e; | |
| border-radius: 8px; | |
| font-size: 0.875rem; | |
| } | |
| .status-dot { | |
| width: 8px; | |
| height: 8px; | |
| border-radius: 50%; | |
| background: #4ade80; | |
| animation: pulse 2s infinite; | |
| } | |
| .status-dot.loading { | |
| background: #fbbf24; | |
| } | |
| .status-dot.error { | |
| background: #ef4444; | |
| } | |
| @keyframes pulse { | |
| 0%, 100% { opacity: 1; } | |
| 50% { opacity: 0.5; } | |
| } | |
| /* Footer */ | |
| .footer { | |
| text-align: center; | |
| padding: 1rem; | |
| color: #636366; | |
| font-size: 0.875rem; | |
| border-top: 1px solid #2a2a4e; | |
| margin-top: 1.5rem; | |
| } | |
| /* Response time badge */ | |
| .response-time { | |
| font-size: 0.75rem; | |
| color: #636366; | |
| padding: 0.25rem 0.5rem; | |
| background: #16213e; | |
| border-radius: 4px; | |
| margin-top: 0.5rem; | |
| display: inline-block; | |
| } | |
| /* Feedback buttons */ | |
| .feedback-btn { | |
| padding: 0.5rem 1rem !important; | |
| font-size: 0.875rem !important; | |
| border-radius: 6px !important; | |
| min-width: auto !important; | |
| } | |
| /* Mobile responsive */ | |
| @media (max-width: 768px) { | |
| .header-title { | |
| font-size: 1.5rem; | |
| } | |
| .header-subtitle { | |
| font-size: 0.875rem; | |
| } | |
| .gradio-container { | |
| padding: 0.5rem !important; | |
| } | |
| } | |
| /* Scrollbar styling */ | |
| ::-webkit-scrollbar { | |
| width: 8px; | |
| height: 8px; | |
| } | |
| ::-webkit-scrollbar-track { | |
| background: #1a1a2e; | |
| } | |
| ::-webkit-scrollbar-thumb { | |
| background: #2a2a4e; | |
| border-radius: 4px; | |
| } | |
| ::-webkit-scrollbar-thumb:hover { | |
| background: #3a3a5e; | |
| } | |
| """ | |
| def get_header_html( | |
| title: str = "AI Executive Assistant", | |
| subtitle: str = "Powered by Akatsuki AI Technologies", | |
| logo_url: str = None, | |
| ) -> str: | |
| """ | |
| Generate header HTML for the chatbot. | |
| Args: | |
| title: Main title | |
| subtitle: Subtitle text | |
| logo_url: Optional logo image URL | |
| Returns: | |
| HTML string | |
| """ | |
| logo_html = "" | |
| if logo_url: | |
| logo_html = f'<img src="{logo_url}" class="header-logo" alt="Logo">' | |
| return f""" | |
| <div class="header-container"> | |
| {logo_html} | |
| <h1 class="header-title">{title}</h1> | |
| <p class="header-subtitle">{subtitle}</p> | |
| </div> | |
| """ | |
| def get_footer_html( | |
| company_name: str = "Akatsuki AI Technologies", | |
| year: int = 2024, | |
| ) -> str: | |
| """ | |
| Generate footer HTML. | |
| Args: | |
| company_name: Company name | |
| year: Copyright year | |
| Returns: | |
| HTML string | |
| """ | |
| return f""" | |
| <div class="footer"> | |
| <p>© {year} {company_name}. All rights reserved.</p> | |
| <p>Powered by fine-tuned Llama 3</p> | |
| </div> | |
| """ | |
| def get_status_html(status: str = "ready", message: str = "Model loaded") -> str: | |
| """ | |
| Generate status indicator HTML. | |
| Args: | |
| status: Status type (ready, loading, error) | |
| message: Status message | |
| Returns: | |
| HTML string | |
| """ | |
| dot_class = "status-dot" | |
| if status == "loading": | |
| dot_class += " loading" | |
| elif status == "error": | |
| dot_class += " error" | |
| return f""" | |
| <div class="status-container"> | |
| <span class="{dot_class}"></span> | |
| <span>{message}</span> | |
| </div> | |
| """ | |
| if __name__ == "__main__": | |
| # Test theme | |
| if GRADIO_AVAILABLE: | |
| theme = get_akatsuki_theme() | |
| print("Theme created successfully") | |
| print(f"Primary hue: {theme.primary_hue}") | |
| else: | |
| print("Gradio not available") | |