""" 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'' return f"""
{logo_html}

{title}

{subtitle}

""" 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""" """ 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"""
{message}
""" 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")