""" Tibetan Text Metrics Theme - Gradio 6 Compatible This theme provides a clean, professional look for the TTM application. Updated for Gradio 6.x compatibility where theme/css are passed to launch(). """ import gradio as gr from gradio.themes.utils import colors, sizes, fonts class TibetanAppTheme(gr.themes.Soft): """ Custom theme for Tibetan Text Metrics application. Gradio 6 Migration Notes: - Theme is now passed to demo.launch(theme=...) instead of gr.Blocks(theme=...) - CSS is now passed to demo.launch(css=...) instead of gr.Blocks(css=...) - Use elem_id and elem_classes for stable CSS targeting """ def __init__(self): super().__init__( primary_hue=colors.blue, secondary_hue=colors.orange, neutral_hue=colors.slate, font=[ fonts.GoogleFont("Inter"), "ui-sans-serif", "system-ui", "sans-serif", ], radius_size=sizes.radius_md, text_size=sizes.text_md, ) # Theme variable overrides using Gradio's theming system self.theme_vars_for_set = { # Global & Body Styles "body_background_fill": "#f0f2f5", "body_text_color": "#333333", "body_text_color_subdued": "#4b5563", # Block/Card Styles "block_background_fill": "#ffffff", "block_radius": "16px", "block_shadow": "0 4px 12px rgba(0, 0, 0, 0.08)", "block_padding": "24px", "block_border_width": "0px", # Button Styles - Secondary "button_secondary_background_fill": "#ffffff", "button_secondary_text_color": "#374151", "button_secondary_border_color": "#d1d5db", "button_secondary_border_color_hover": "#adb5bd", "button_secondary_background_fill_hover": "#f9fafb", # Button Styles - Primary "button_primary_background_fill": "#2563eb", "button_primary_text_color": "#ffffff", "button_primary_border_color": "transparent", "button_primary_background_fill_hover": "#1d4ed8", # Border colors "border_color_accent_subdued": "#e5e7eb", "border_color_primary": "#d1d5db", # Input styles "input_background_fill": "#ffffff", "input_border_color": "#d1d5db", "input_border_color_focus": "#2563eb", } super().set(**self.theme_vars_for_set) def get_css_string(self) -> str: """ Returns custom CSS string for additional styling. Gradio 6 uses different class naming conventions. This CSS uses: - elem_id selectors (#id) for specific components - elem_classes selectors (.class) for groups of components - Gradio 6 native classes where stable """ return """ /* ============================================ GLOBAL STYLES ============================================ */ .gradio-container { font-family: 'Inter', ui-sans-serif, system-ui, sans-serif !important; max-width: 1600px !important; margin: 0 auto !important; font-size: 16px !important; } /* Base font size for all text */ body, .gradio-container * { font-size: 16px; } /* ============================================ TYPOGRAPHY ============================================ */ h1 { font-size: 32px !important; font-weight: 600 !important; color: #111827 !important; margin-bottom: 12px !important; } h2 { font-size: 26px !important; font-weight: 600 !important; color: var(--primary-600, #2563eb) !important; margin-top: 24px !important; margin-bottom: 16px !important; } h3 { font-size: 22px !important; font-weight: 600 !important; color: #1f2937 !important; margin-top: 20px !important; margin-bottom: 12px !important; } /* Labels and form text */ label, .label-wrap, span.svelte-1gfkn6j { font-size: 16px !important; } /* Info text under inputs */ .info { font-size: 14px !important; } /* ============================================ LAYOUT - Steps Row ============================================ */ #steps-row { display: flex !important; align-items: stretch !important; gap: 24px !important; } .step-column { display: flex !important; flex-direction: column !important; flex: 1 !important; } .step-box { padding: 1.5rem !important; flex-grow: 1 !important; display: flex !important; flex-direction: column !important; } /* ============================================ BUTTONS ============================================ */ /* Primary action buttons */ #run-btn-quick, #run-btn-custom { background: var(--button-primary-background-fill, #2563eb) !important; color: var(--button-primary-text-color, #ffffff) !important; font-weight: 600 !important; font-size: 18px !important; padding: 12px 24px !important; border: none !important; border-radius: 8px !important; box-shadow: 0 2px 4px rgba(37, 99, 235, 0.2) !important; transition: all 0.2s ease !important; margin-top: 16px !important; } #run-btn-quick:hover, #run-btn-custom:hover { background: var(--button-primary-background-fill-hover, #1d4ed8) !important; box-shadow: 0 4px 12px rgba(37, 99, 235, 0.3) !important; transform: translateY(-1px) !important; } /* Secondary buttons */ button.secondary { background-color: #ffffff !important; color: #374151 !important; border: 1px solid #d1d5db !important; border-radius: 8px !important; padding: 10px 20px !important; font-weight: 500 !important; } button.secondary:hover { background-color: #f9fafb !important; border-color: #adb5bd !important; } /* ============================================ TABS ============================================ */ .tabs { margin-top: 8px !important; } .tab-nav { border-bottom: 1px solid #e5e7eb !important; margin-bottom: 16px !important; } .tab-nav button { color: #6b7280 !important; background-color: transparent !important; padding: 12px 20px !important; border: none !important; border-bottom: 2px solid transparent !important; font-weight: 500 !important; transition: all 0.2s ease !important; } .tab-nav button:hover { color: #374151 !important; } .tab-nav button.selected { border-bottom: 2px solid var(--primary-500, #3b82f6) !important; color: var(--primary-600, #2563eb) !important; background-color: transparent !important; } /* ============================================ ACCORDIONS ============================================ */ .accordion { border: 1px solid #e5e7eb !important; border-radius: 8px !important; margin-bottom: 12px !important; overflow: hidden !important; } /* Metric info accordions with colored borders */ .metric-info-accordion { border-left: 4px solid #3B82F6 !important; margin-bottom: 1rem !important; background-color: #F8FAFC !important; border-radius: 6px !important; } .jaccard-info { border-left-color: #3B82F6 !important; } .lcs-info { border-left-color: #10B981 !important; } .fuzzy-info { border-left-color: #F59E0B !important; } .semantic-info { border-left-color: #8B5CF6 !important; } .wordcount-info { border-left-color: #EC4899 !important; } /* ============================================ FORM ELEMENTS ============================================ */ /* Radio buttons */ .radio-group label { display: flex !important; align-items: center !important; padding: 10px 16px !important; border: 1px solid #e5e7eb !important; border-radius: 8px !important; margin-bottom: 8px !important; cursor: pointer !important; transition: all 0.2s ease !important; } .radio-group label:hover { background-color: #f9fafb !important; border-color: #d1d5db !important; } .radio-group input:checked + label, .radio-group label.selected { background-color: var(--primary-50, #eff6ff) !important; border-color: var(--primary-500, #3b82f6) !important; } /* Dropdowns */ select, .dropdown { border: 1px solid #d1d5db !important; border-radius: 8px !important; padding: 10px 12px !important; background-color: #ffffff !important; } /* Checkboxes */ input[type="checkbox"] { width: 18px !important; height: 18px !important; accent-color: var(--primary-500, #3b82f6) !important; } /* ============================================ PRESET TABLE ============================================ */ .preset-table table { font-size: 15px !important; margin-top: 16px !important; width: 100% !important; border-collapse: collapse !important; } .preset-table th, .preset-table td { padding: 12px 16px !important; text-align: center !important; border-bottom: 1px solid #e5e7eb !important; } .preset-table th { background-color: #f9fafb !important; font-weight: 600 !important; color: #374151 !important; font-size: 15px !important; } .preset-table tr:hover { background-color: #f9fafb !important; } /* Radio button options - larger text */ .gr-radio label, .gr-radio span { font-size: 16px !important; } /* Dropdown options */ .gr-dropdown, select { font-size: 16px !important; } /* ============================================ RESULTS SECTION ============================================ */ /* Heatmaps and plots - full width */ .plot-container, .plotly, .js-plotly-plot { width: 100% !important; max-width: 100% !important; } /* Remove extra padding/margin from plot containers */ .gr-plot, [data-testid="plot"] { width: 100% !important; padding: 0 !important; } /* Tab content should use full width */ .tabitem, [data-testid="tabitem"] { width: 100% !important; padding: 16px 0 !important; } /* Remove dead space after plots */ .tabs .tabitem > div { margin-bottom: 0 !important; } .metric-heatmap { max-width: 100% !important; width: 100% !important; } /* ============================================ LLM ANALYSIS OUTPUT ============================================ */ #llm-analysis { background-color: #f8f9fa !important; border-left: 4px solid #3B82F6 !important; border-radius: 8px !important; padding: 20px 24px !important; margin: 16px 0 !important; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05) !important; } #llm-analysis h2 { color: #1e40af !important; font-size: 22px !important; margin-bottom: 16px !important; border-bottom: 1px solid #e5e7eb !important; padding-bottom: 8px !important; } #llm-analysis h3, #llm-analysis h4 { color: #1e3a8a !important; margin-top: 18px !important; margin-bottom: 10px !important; } #llm-analysis p { line-height: 1.7 !important; margin-bottom: 12px !important; color: #374151 !important; } #llm-analysis ul, #llm-analysis ol { margin-left: 24px !important; margin-bottom: 16px !important; } #llm-analysis li { margin-bottom: 6px !important; } #llm-analysis strong, #llm-analysis b { color: #1f2937 !important; font-weight: 600 !important; } /* ============================================ RESPONSIVE ADJUSTMENTS ============================================ */ @media (max-width: 768px) { #steps-row { flex-direction: column !important; } .step-column { width: 100% !important; } #run-btn-quick, #run-btn-custom { font-size: 16px !important; padding: 10px 20px !important; } } /* ============================================ UTILITY CLASSES ============================================ */ .custom-header { margin-bottom: 12px !important; color: #374151 !important; } .info-text { font-size: 14px !important; color: #6b7280 !important; margin-top: 4px !important; } """ # Instantiate the theme for easy import tibetan_theme = TibetanAppTheme()