| """ |
| FormScout custom Gradio theme — Silas Therapy palette. |
| |
| Warm cream + sage green ground, petrol-teal primary, golden-orange accent, |
| dark slate-green text. Matches https://silastherapy.sk branding. |
| """ |
| from __future__ import annotations |
|
|
| import gradio as gr |
|
|
| |
| CREAM = "#f7eedd" |
| CREAM_DEEP = "#f1e4cc" |
| SAGE = "#bcd3c8" |
| SAGE_DEEP = "#9cbcad" |
| TEAL = "#2b8a8a" |
| TEAL_HOVER = "#1f6e6e" |
| TEAL_DEEP = "#175757" |
| TEAL_LIGHT = "#d6ecec" |
| TEAL_LIGHT_HOVER = "#bfe3e3" |
| GOLD = "#e0a43b" |
| GOLD_DEEP = "#cf922a" |
| INK = "#243a34" |
| INK_MUTED = "#4a5f57" |
| INK_FAINT = "#6b7d75" |
|
|
|
|
| def formscout_theme() -> gr.Theme: |
| """Create the FormScout theme in the Silas Therapy palette.""" |
| return gr.themes.Soft( |
| primary_hue=gr.themes.colors.teal, |
| secondary_hue=gr.themes.colors.amber, |
| neutral_hue=gr.themes.colors.stone, |
| font=[ |
| gr.themes.GoogleFont("Inter"), |
| "ui-sans-serif", |
| "system-ui", |
| "sans-serif", |
| ], |
| font_mono=[ |
| gr.themes.GoogleFont("JetBrains Mono"), |
| "ui-monospace", |
| "monospace", |
| ], |
| ).set( |
| |
| body_background_fill=f"linear-gradient(135deg, {CREAM} 0%, {CREAM_DEEP} 45%, {SAGE} 100%)", |
| body_background_fill_dark=f"linear-gradient(135deg, {CREAM} 0%, {CREAM_DEEP} 45%, {SAGE} 100%)", |
| |
| block_background_fill="rgba(255, 255, 255, 0.72)", |
| block_background_fill_dark="rgba(255, 255, 255, 0.72)", |
| block_border_width="1px", |
| block_border_color="rgba(43, 138, 138, 0.22)", |
| block_shadow="0 6px 22px rgba(36, 58, 52, 0.10)", |
| block_radius="14px", |
| |
| button_primary_background_fill=f"linear-gradient(135deg, {TEAL} 0%, {TEAL_HOVER} 100%)", |
| button_primary_background_fill_hover=f"linear-gradient(135deg, {TEAL_HOVER} 0%, {TEAL_DEEP} 100%)", |
| button_primary_text_color="white", |
| button_primary_border_color="rgba(43, 138, 138, 0.45)", |
| button_secondary_background_fill="rgba(156, 188, 173, 0.55)", |
| button_secondary_text_color=INK, |
| |
| input_background_fill="rgba(255, 255, 255, 0.92)", |
| input_background_fill_dark="rgba(255, 255, 255, 0.92)", |
| input_background_fill_focus="rgba(255, 255, 255, 1.0)", |
| input_border_color="rgba(43, 138, 138, 0.30)", |
| input_border_color_focus="rgba(43, 138, 138, 0.75)", |
| |
| block_label_background_fill="rgba(188, 211, 200, 0.55)", |
| block_label_background_fill_dark="rgba(188, 211, 200, 0.55)", |
| block_label_text_color=INK, |
| block_label_text_color_dark=INK, |
| |
| body_text_color=INK, |
| body_text_color_dark=INK, |
| block_title_text_color=TEAL_DEEP, |
| |
| block_padding="16px", |
| layout_gap="16px", |
| ) |
|
|
|
|
| FORMSCOUT_CSS = f""" |
| /* FormScout — Silas Therapy theme */ |
| |
| .gradio-container {{ |
| max-width: 1400px !important; |
| margin: 0 auto; |
| }} |
| |
| /* Header styling */ |
| .formscout-header {{ |
| text-align: center; |
| padding: 20px 0; |
| border-bottom: 2px solid rgba(43, 138, 138, 0.30); |
| margin-bottom: 20px; |
| }} |
| |
| .formscout-header h1 {{ |
| font-size: 2.2em; |
| background: linear-gradient(135deg, {TEAL} 0%, {GOLD} 100%); |
| -webkit-background-clip: text; |
| -webkit-text-fill-color: transparent; |
| background-clip: text; |
| margin-bottom: 8px; |
| }} |
| |
| /* Safety banner — golden */ |
| .safety-banner {{ |
| background: linear-gradient(90deg, rgba(224, 164, 59, 0.20), rgba(224, 164, 59, 0.08)); |
| border: 1px solid rgba(224, 164, 59, 0.55); |
| border-radius: 8px; |
| padding: 12px 16px; |
| margin: 12px 0; |
| font-size: 0.9em; |
| text-align: center; |
| color: {GOLD_DEEP}; |
| }} |
| |
| /* Dropdown option lists — pin light-teal cells in both modes (Gradio's default |
| --background-fill-primary resolves dark here, same issue as the labels). */ |
| .gradio-container ul.options {{ |
| background: {TEAL_LIGHT} !important; |
| border: 1px solid rgba(43, 138, 138, 0.30) !important; |
| }} |
| .gradio-container ul.options li.item {{ |
| background: {TEAL_LIGHT} !important; |
| color: {INK} !important; |
| }} |
| .gradio-container ul.options li.item:hover, |
| .gradio-container ul.options li.item.active {{ |
| background: {TEAL_LIGHT_HOVER} !important; |
| color: {INK} !important; |
| }} |
| |
| /* Movement-guide illustration — rounded card matching the test selection */ |
| #movement-guide img {{ |
| border-radius: 12px; |
| object-fit: contain; |
| }} |
| #movement-guide {{ |
| border: 1px solid rgba(43, 138, 138, 0.22); |
| border-radius: 14px; |
| }} |
| |
| /* Score display */ |
| .score-card {{ |
| background: rgba(43, 138, 138, 0.08); |
| border: 2px solid rgba(43, 138, 138, 0.35); |
| border-radius: 16px; |
| padding: 24px; |
| text-align: center; |
| }} |
| |
| .score-value {{ |
| font-size: 4em; |
| font-weight: 800; |
| background: linear-gradient(135deg, {TEAL} 0%, {GOLD} 100%); |
| -webkit-background-clip: text; |
| -webkit-text-fill-color: transparent; |
| background-clip: text; |
| }} |
| |
| /* Confidence meter */ |
| .confidence-bar {{ |
| height: 8px; |
| border-radius: 4px; |
| background: rgba(43, 138, 138, 0.18); |
| overflow: hidden; |
| margin-top: 8px; |
| }} |
| |
| .confidence-fill {{ |
| height: 100%; |
| border-radius: 4px; |
| background: linear-gradient(90deg, #d9534f, {GOLD}, {TEAL}); |
| transition: width 0.5s ease; |
| }} |
| |
| /* Pipeline steps indicator */ |
| .pipeline-steps {{ |
| display: flex; |
| gap: 4px; |
| align-items: center; |
| padding: 8px 0; |
| }} |
| |
| .pipeline-step {{ |
| flex: 1; |
| height: 4px; |
| border-radius: 2px; |
| background: rgba(43, 138, 138, 0.18); |
| transition: background 0.3s ease; |
| }} |
| |
| .pipeline-step.active {{ |
| background: {TEAL}; |
| }} |
| |
| .pipeline-step.complete {{ |
| background: {GOLD}; |
| }} |
| |
| /* Asymmetry indicator */ |
| .asymmetry-bar {{ |
| display: flex; |
| align-items: center; |
| gap: 8px; |
| padding: 8px 12px; |
| background: rgba(156, 188, 173, 0.30); |
| border-radius: 8px; |
| margin: 4px 0; |
| }} |
| |
| .asymmetry-label {{ |
| min-width: 60px; |
| font-size: 0.85em; |
| color: {INK_MUTED}; |
| }} |
| |
| .asymmetry-track {{ |
| flex: 1; |
| height: 6px; |
| background: rgba(43, 138, 138, 0.12); |
| border-radius: 3px; |
| position: relative; |
| }} |
| |
| .asymmetry-marker {{ |
| position: absolute; |
| top: -3px; |
| width: 12px; |
| height: 12px; |
| border-radius: 50%; |
| background: {TEAL}; |
| border: 2px solid {GOLD}; |
| }} |
| |
| /* Topographic pattern accent */ |
| .topo-accent {{ |
| color: {INK_FAINT}; |
| background-image: |
| repeating-linear-gradient( |
| 0deg, |
| transparent, |
| transparent 40px, |
| rgba(43, 138, 138, 0.04) 40px, |
| rgba(43, 138, 138, 0.04) 41px |
| ), |
| repeating-linear-gradient( |
| 90deg, |
| transparent, |
| transparent 40px, |
| rgba(43, 138, 138, 0.03) 40px, |
| rgba(43, 138, 138, 0.03) 41px |
| ); |
| }} |
| |
| /* Warning/error states */ |
| .needs-review {{ |
| border-color: rgba(224, 164, 59, 0.65) !important; |
| background: rgba(224, 164, 59, 0.10) !important; |
| }} |
| |
| .low-confidence {{ |
| opacity: 0.7; |
| border-style: dashed !important; |
| }} |
| |
| /* Rubric drawer */ |
| .rubric-item {{ |
| display: flex; |
| align-items: center; |
| gap: 8px; |
| padding: 6px 10px; |
| border-radius: 6px; |
| margin: 2px 0; |
| }} |
| |
| .rubric-met {{ |
| background: rgba(43, 138, 138, 0.10); |
| border-left: 3px solid {TEAL}; |
| }} |
| |
| .rubric-unmet {{ |
| background: rgba(217, 83, 79, 0.10); |
| border-left: 3px solid #d9534f; |
| }} |
| |
| /* Responsive */ |
| @media (max-width: 768px) {{ |
| .gradio-container {{ |
| padding: 8px !important; |
| }} |
| .score-value {{ |
| font-size: 3em; |
| }} |
| }} |
| """ |
|
|