Spaces:
Running on Zero
Running on Zero
Download theme.py from PrunaAI/P-H3-Image: direct link, hf CLI and curl.
- Browser
- Download file 28.1 kB
-
https://huggingface.co/spaces/PrunaAI/P-H3-Image/resolve/main/theme.py
- Command line
-
hf download hf://spaces/PrunaAI/P-H3-Image/theme.py
-
curl -L -o theme.py https://huggingface.co/spaces/PrunaAI/P-H3-Image/resolve/main/theme.py
28.1 kB
| """P-Bench visual language: tokens, Gradio theme, header, and footer.""" | |
| import base64 | |
| from pathlib import Path | |
| import gradio as gr | |
| _LOGO_PATH = Path(__file__).resolve().parent / "pruna-logo.png" | |
| _LOGO_DATA_URI = ( | |
| "data:image/png;base64," | |
| + base64.b64encode(_LOGO_PATH.read_bytes()).decode("ascii") | |
| if _LOGO_PATH.exists() | |
| else "https://framerusercontent.com/assets/EUwwqhBQJ7gF86kTZTh8SMO4B94.svg" | |
| ) | |
| THEME = gr.themes.Base( | |
| primary_hue=gr.themes.Color( | |
| c50="#faf5ff", | |
| c100="#f3e8ff", | |
| c200="#e9d5ff", | |
| c300="#d8b4fe", | |
| c400="#c084fc", | |
| c500="#9334e9", | |
| c600="#9334e9", | |
| c700="#7e22ce", | |
| c800="#6b21a8", | |
| c900="#3b0764", | |
| c950="#120b1b", | |
| ), | |
| secondary_hue="zinc", | |
| neutral_hue="zinc", | |
| font=[gr.themes.GoogleFont("Inter"), "ui-sans-serif", "system-ui", "sans-serif"], | |
| font_mono=[gr.themes.GoogleFont("IBM Plex Mono"), "ui-monospace", "monospace"], | |
| ).set( | |
| body_background_fill="#f6f3fa", | |
| body_background_fill_dark="#120b1b", | |
| body_text_color="#18181b", | |
| body_text_color_dark="#fafafa", | |
| body_text_color_subdued="#71717a", | |
| body_text_color_subdued_dark="#a3a3a3", | |
| background_fill_primary="#f6f3fa", | |
| background_fill_primary_dark="#120b1b", | |
| background_fill_secondary="#ffffff", | |
| background_fill_secondary_dark="#171021", | |
| block_background_fill="#ffffff", | |
| block_background_fill_dark="#1d1429", | |
| block_border_color="#e4d7f2", | |
| block_border_color_dark="#4a3962bf", | |
| block_label_text_color="#71717a", | |
| block_label_text_color_dark="#a3a3a3", | |
| block_title_text_color="#18181b", | |
| block_title_text_color_dark="#fafafa", | |
| border_color_primary="#e4d7f2", | |
| border_color_primary_dark="#4a3962bf", | |
| button_primary_background_fill="#9334e9", | |
| button_primary_background_fill_dark="#9334e9", | |
| button_primary_background_fill_hover="#7c22ce", | |
| button_primary_background_fill_hover_dark="#8f35ff", | |
| button_primary_text_color="#ffffff", | |
| button_primary_text_color_dark="#ffffff", | |
| button_secondary_background_fill="#ffffff", | |
| button_secondary_background_fill_dark="#ffffff05", | |
| button_secondary_background_fill_hover="#f3e8ff", | |
| button_secondary_background_fill_hover_dark="rgba(147, 52, 233, 0.10)", | |
| button_secondary_text_color="#18181b", | |
| button_secondary_text_color_dark="#fafafa", | |
| button_secondary_border_color="#e4d7f2", | |
| button_secondary_border_color_dark="#d8b4fe26", | |
| input_background_fill="#ffffff", | |
| input_background_fill_dark="#171021", | |
| input_border_color="#e4d7f2", | |
| input_border_color_dark="#4a3962bf", | |
| input_placeholder_color="#71717a", | |
| input_placeholder_color_dark="#a3a3a3", | |
| link_text_color="#6d28d9", | |
| link_text_color_dark="#bf8bff", | |
| link_text_color_hover="#7c22ce", | |
| link_text_color_hover_dark="#d2a8ff", | |
| shadow_drop="none", | |
| shadow_drop_lg="none", | |
| ) | |
| # Visual tokens from https://www.pruna.ai/, https://playground.pruna.ai/, and PrunaAI/P-Bench. | |
| CSS = """ | |
| :root, :host, .dark, :host(.dark) { | |
| --pruna-bg-primary: #120b1b; | |
| --pruna-bg-card: #171021; | |
| --pruna-bg-elevated: #1d1429; | |
| --pruna-bg-header: #17101f; | |
| --pruna-border: rgba(74, 57, 98, 0.75); | |
| --pruna-hairline: rgba(255, 255, 255, 0.08); | |
| --pruna-text-primary: #fafafa; | |
| --pruna-text-body: #d4d4d4; | |
| --pruna-text-muted: #a3a3a3; | |
| --pruna-accent: #9334e9; | |
| --pruna-accent-bright: #8f35ff; | |
| --pruna-lavender: #d8b4fe; | |
| --pruna-link: #bf8bff; | |
| --pruna-font: "Inter", ui-sans-serif, system-ui, -apple-system, sans-serif; | |
| --pruna-glow: radial-gradient(ellipse 60% 35% at 50% -5%, rgba(147, 52, 233, 0.18), transparent 55%); | |
| --pruna-card-bg: color-mix(in oklab, #1d1429 92%, black 8%); | |
| --pruna-card-shadow: 0 24px 55px rgba(0, 0, 0, 0.42), inset 0 1px rgba(255, 255, 255, 0.04); | |
| --pruna-menu-border: rgba(255, 255, 255, 0.08); | |
| --pruna-menu-bg: rgba(255, 255, 255, 0.03); | |
| --pruna-menu-hover-bg: rgba(255, 255, 255, 0.05); | |
| --pruna-menu-hover-color: #e4e4e7; | |
| --pruna-tab-hover: #e4e4e7; | |
| --pruna-tab-selected: #ffffff; | |
| --pruna-input-bg: rgba(255, 255, 255, 0.03); | |
| --pruna-input-border: rgba(255, 255, 255, 0.08); | |
| --pruna-focus-border: rgba(143, 53, 255, 0.45); | |
| --pruna-focus-ring: 0 0 0 3px rgba(143, 53, 255, 0.16); | |
| --pruna-accordion-bg: rgba(255, 255, 255, 0.02); | |
| --pruna-accordion-border: rgba(216, 180, 254, 0.15); | |
| --pruna-dropdown-hover: #2a1844; | |
| color-scheme: dark; | |
| } | |
| .light, :host(.light) { | |
| --pruna-bg-primary: #f6f3fa; | |
| --pruna-bg-card: #ffffff; | |
| --pruna-bg-elevated: #ffffff; | |
| --pruna-bg-header: #f3eef8; | |
| --pruna-border: rgba(126, 34, 206, 0.16); | |
| --pruna-hairline: rgba(24, 24, 27, 0.08); | |
| --pruna-text-primary: #18181b; | |
| --pruna-text-body: #3f3f46; | |
| --pruna-text-muted: #71717a; | |
| --pruna-accent: #9334e9; | |
| --pruna-accent-bright: #7c22ce; | |
| --pruna-lavender: #7e22ce; | |
| --pruna-link: #6d28d9; | |
| --pruna-glow: radial-gradient(ellipse 60% 35% at 50% -5%, rgba(147, 52, 233, 0.10), transparent 55%); | |
| --pruna-card-bg: #ffffff; | |
| --pruna-card-shadow: 0 10px 28px rgba(88, 28, 135, 0.08); | |
| --pruna-menu-border: var(--pruna-border); | |
| --pruna-menu-bg: var(--pruna-bg-card); | |
| --pruna-menu-hover-bg: rgba(147, 52, 233, 0.06); | |
| --pruna-menu-hover-color: var(--pruna-text-primary); | |
| --pruna-tab-hover: var(--pruna-text-primary); | |
| --pruna-tab-selected: var(--pruna-text-primary); | |
| --pruna-input-bg: var(--pruna-bg-card); | |
| --pruna-input-border: var(--pruna-border); | |
| --pruna-focus-border: rgba(124, 34, 206, 0.45); | |
| --pruna-focus-ring: 0 0 0 3px rgba(143, 53, 255, 0.16); | |
| --pruna-accordion-bg: var(--pruna-bg-card); | |
| --pruna-accordion-border: var(--pruna-border); | |
| --pruna-dropdown-hover: #f3e8ff; | |
| color-scheme: light; | |
| } | |
| html { | |
| width: 100% !important; | |
| max-width: 100% !important; | |
| min-width: 0 !important; | |
| overflow-x: hidden; | |
| overflow-y: auto; | |
| -webkit-text-size-adjust: 100%; | |
| text-size-adjust: 100%; | |
| -webkit-tap-highlight-color: transparent; | |
| } | |
| body, gradio-app { | |
| width: 100% !important; | |
| max-width: 100% !important; | |
| min-width: 0 !important; | |
| overflow: visible; | |
| -webkit-tap-highlight-color: transparent; | |
| } | |
| html, body, gradio-app, .gradio-container, .main, | |
| .gradio-container .main, | |
| .gradio-container .fillable, | |
| .gradio-container .app, | |
| .gradio-container .wrap, | |
| .gradio-container .contain { | |
| background-color: var(--pruna-bg-primary) !important; | |
| background-image: var(--pruna-glow) !important; | |
| background-repeat: no-repeat !important; | |
| background-attachment: scroll !important; | |
| color: var(--pruna-text-primary) !important; | |
| font-family: var(--pruna-font) !important; | |
| } | |
| @media (min-width: 701px) and (hover: hover) and (pointer: fine) { | |
| html, body, gradio-app, .gradio-container, .main, | |
| .gradio-container .main, | |
| .gradio-container .fillable, | |
| .gradio-container .app { | |
| background-attachment: fixed !important; | |
| } | |
| } | |
| button, a, label, input, select, textarea, | |
| [role="button"], [role="tab"], [role="radio"], | |
| .gradio-container * { | |
| -webkit-tap-highlight-color: transparent !important; | |
| } | |
| :root, :host, .dark, .light, gradio-app, .gradio-container { | |
| --input-radius: 10px !important; | |
| --container-radius: 10px !important; | |
| --block-radius: 10px !important; | |
| --embed-radius: 10px !important; | |
| --table-radius: 10px !important; | |
| --checkbox-border-radius: 4px !important; | |
| --button-large-radius: 8px !important; | |
| --button-medium-radius: 8px !important; | |
| --button-small-radius: 8px !important; | |
| --radius-md: 8px !important; | |
| --radius-lg: 10px !important; | |
| --radius-xl: 10px !important; | |
| --radius-2xl: 10px !important; | |
| --radius-3xl: 10px !important; | |
| --radius-xxl: 10px !important; | |
| } | |
| .gradio-container { | |
| width: 100% !important; | |
| max-width: 1200px !important; | |
| min-width: 0 !important; | |
| margin: 0 auto !important; | |
| padding-top: 0 !important; | |
| padding-left: 20px !important; | |
| padding-right: 20px !important; | |
| box-sizing: border-box !important; | |
| overflow-x: hidden; | |
| } | |
| .gradio-container .main, | |
| .gradio-container .wrap, | |
| .gradio-container .contain, | |
| .gradio-container .block, | |
| .gradio-container .form, | |
| .gradio-container .row, | |
| .gradio-container .column, | |
| .gradio-container .gap, | |
| .gradio-container .html-container, | |
| .gradio-container .prose, | |
| .gradio-container .padded, | |
| .main-tabs, | |
| .main-tabs .tab-wrapper, | |
| .main-tabs .tabitem { | |
| max-width: 100% !important; | |
| min-width: 0 !important; | |
| } | |
| .app-header-host, | |
| .app-header-host .html-container, | |
| .app-header-host .prose, | |
| .app-header-host.block, | |
| .app-header-host .padded { | |
| border: none !important; | |
| background: transparent !important; | |
| box-shadow: none !important; | |
| padding: 0 !important; | |
| margin: 0 auto !important; | |
| width: 100% !important; | |
| max-width: none !important; | |
| display: block !important; | |
| text-align: center !important; | |
| overflow: visible !important; | |
| } | |
| .app-header { | |
| position: relative; | |
| display: flex; | |
| flex-direction: column; | |
| align-items: stretch; | |
| width: 100%; | |
| margin: 8px 0 0; | |
| padding: 4px 0 10px; | |
| text-align: center; | |
| } | |
| .app-header-bar { | |
| display: grid; | |
| grid-template-columns: minmax(36px, 1fr) auto minmax(36px, 1fr); | |
| align-items: center; | |
| width: 100%; | |
| column-gap: 8px; | |
| } | |
| .app-header .theme-toggle, | |
| button.theme-toggle { | |
| position: static !important; | |
| top: auto; | |
| right: auto; | |
| grid-column: 3; | |
| justify-self: end; | |
| display: inline-flex !important; | |
| align-items: center !important; | |
| justify-content: center !important; | |
| width: 36px !important; | |
| height: 36px !important; | |
| min-width: 36px !important; | |
| min-height: 36px !important; | |
| margin: 0 !important; | |
| padding: 0 !important; | |
| border: 1px solid var(--pruna-menu-border) !important; | |
| border-radius: 10px !important; | |
| background: var(--pruna-menu-bg) !important; | |
| color: var(--pruna-text-muted) !important; | |
| box-shadow: none !important; | |
| appearance: none !important; | |
| -webkit-appearance: none !important; | |
| box-sizing: border-box !important; | |
| font: inherit !important; | |
| line-height: 0 !important; | |
| cursor: pointer; | |
| z-index: 6; | |
| } | |
| .app-header .theme-toggle:hover, | |
| .app-header .theme-toggle:active, | |
| button.theme-toggle:hover, | |
| button.theme-toggle:active { | |
| color: var(--pruna-menu-hover-color) !important; | |
| background: var(--pruna-menu-hover-bg) !important; | |
| border-color: var(--pruna-menu-border) !important; | |
| box-shadow: none !important; | |
| } | |
| .app-header .theme-toggle:focus, | |
| button.theme-toggle:focus { outline: none !important; } | |
| .app-header .theme-toggle:focus-visible, | |
| button.theme-toggle:focus-visible { | |
| color: var(--pruna-menu-hover-color) !important; | |
| background: var(--pruna-menu-hover-bg) !important; | |
| border-color: var(--pruna-focus-border) !important; | |
| box-shadow: var(--pruna-focus-ring) !important; | |
| } | |
| .app-header .theme-toggle svg, | |
| button.theme-toggle svg { | |
| width: 18px; | |
| height: 18px; | |
| flex-shrink: 0; | |
| } | |
| .app-header .theme-toggle .theme-icon-sun, | |
| button.theme-toggle .theme-icon-sun { display: block !important; } | |
| .app-header .theme-toggle .theme-icon-moon, | |
| button.theme-toggle .theme-icon-moon { display: none !important; } | |
| .app-header .theme-toggle[data-mode="light"] .theme-icon-sun, | |
| button.theme-toggle[data-mode="light"] .theme-icon-sun { display: none !important; } | |
| .app-header .theme-toggle[data-mode="light"] .theme-icon-moon, | |
| button.theme-toggle[data-mode="light"] .theme-icon-moon { display: block !important; } | |
| .app-header-brand { | |
| display: inline-flex !important; | |
| flex-direction: row; | |
| align-items: center; | |
| justify-content: center; | |
| gap: 12px; | |
| grid-column: 2; | |
| justify-self: center; | |
| width: auto !important; | |
| max-width: 100%; | |
| margin: 0; | |
| } | |
| .app-header-logo { | |
| display: block !important; | |
| width: 44px !important; | |
| height: 52px !important; | |
| margin: 0 !important; | |
| object-fit: contain; | |
| flex: 0 0 auto; | |
| } | |
| .gradio-container .app-header-brand h1, | |
| .app-header .app-header-brand h1 { | |
| display: block !important; | |
| width: max-content !important; | |
| max-width: 100% !important; | |
| flex: 0 0 auto !important; | |
| margin: 0 !important; | |
| padding: 0 !important; | |
| text-align: center !important; | |
| font-size: clamp(1.9rem, 3vw, 2.4rem) !important; | |
| font-weight: 700 !important; | |
| letter-spacing: -0.035em; | |
| line-height: 1 !important; | |
| color: var(--pruna-text-primary) !important; | |
| } | |
| .app-header-tagline, | |
| .prose .app-header-tagline, | |
| .gradio-container .app-header-tagline { | |
| display: block !important; | |
| width: 100% !important; | |
| margin: 8px 0 0 !important; | |
| padding: 0 !important; | |
| text-align: center !important; | |
| color: var(--pruna-text-muted) !important; | |
| font-size: 0.95rem !important; | |
| line-height: 1.45 !important; | |
| font-weight: 400 !important; | |
| } | |
| .tabs { gap: 0 !important; } | |
| .main-tabs > .tab-wrapper, | |
| .main-tabs > .tab-nav, | |
| .main-tabs > .tab-container { | |
| height: auto !important; | |
| min-height: 0 !important; | |
| padding: 0 !important; | |
| margin: 0 0 16px !important; | |
| justify-content: center !important; | |
| width: 100% !important; | |
| overflow: visible !important; | |
| } | |
| .main-tabs .tab-container, | |
| .main-tabs .tab-nav { | |
| height: auto !important; | |
| min-height: 0 !important; | |
| justify-content: center !important; | |
| flex-wrap: wrap !important; | |
| overflow: visible !important; | |
| max-width: 100% !important; | |
| gap: 2px; | |
| } | |
| .main-tabs .tab-container::after, | |
| .main-tabs .tab-nav::after { | |
| background: var(--pruna-hairline) !important; | |
| } | |
| .main-tabs .tab-container > button, | |
| .main-tabs .tab-nav > button, | |
| .main-tabs button[role="tab"] { | |
| font-family: var(--pruna-font) !important; | |
| font-size: 0.95rem !important; | |
| font-weight: 600 !important; | |
| letter-spacing: -0.015em !important; | |
| color: var(--pruna-text-muted) !important; | |
| background: transparent !important; | |
| border: none !important; | |
| border-radius: 0 !important; | |
| box-shadow: none !important; | |
| padding: 12px 20px !important; | |
| min-height: 44px !important; | |
| height: auto !important; | |
| } | |
| .main-tabs .tab-container > button:hover:not(.selected), | |
| .main-tabs .tab-nav > button:hover:not(.selected), | |
| .main-tabs button[role="tab"]:hover:not(.selected):not([aria-selected="true"]) { | |
| color: var(--pruna-tab-hover) !important; | |
| background: transparent !important; | |
| } | |
| .main-tabs .tab-container > button.selected, | |
| .main-tabs .tab-container > button[aria-selected="true"], | |
| .main-tabs .tab-nav > button.selected, | |
| .main-tabs .tab-nav > button[aria-selected="true"], | |
| .main-tabs button[role="tab"][aria-selected="true"] { | |
| color: var(--pruna-tab-selected) !important; | |
| background: transparent !important; | |
| } | |
| .main-tabs .tab-container > button.selected::after, | |
| .main-tabs .tab-container > button[aria-selected="true"]::after, | |
| .main-tabs .tab-nav > button.selected::after, | |
| .main-tabs .tab-nav > button[aria-selected="true"]::after, | |
| .main-tabs button[role="tab"][aria-selected="true"]::after { | |
| background: var(--pruna-accent-bright) !important; | |
| height: 2px !important; | |
| } | |
| .main-tabs .tabitem { | |
| padding: 8px 0 0 !important; | |
| border-radius: 0 !important; | |
| overflow: visible !important; | |
| } | |
| .gradio-container h1, .markdown h1, .md h1, .prose h1 { | |
| margin: 0 0 0.65rem !important; | |
| padding: 0 !important; | |
| color: var(--pruna-text-primary) !important; | |
| font-family: var(--pruna-font) !important; | |
| font-size: 1.5rem !important; | |
| font-weight: 700 !important; | |
| letter-spacing: -0.03em !important; | |
| line-height: 1.2 !important; | |
| text-transform: none !important; | |
| } | |
| .markdown, .md, .prose, | |
| .gradio-container .markdown, | |
| .gradio-container .prose { | |
| overflow-wrap: break-word; | |
| max-width: 100%; | |
| } | |
| .markdown p, .md p, .prose p, | |
| .gradio-container .markdown p { | |
| margin: 0 0 0.8rem !important; | |
| color: var(--pruna-text-body) !important; | |
| font-size: 0.95rem !important; | |
| font-weight: 400 !important; | |
| line-height: 1.55 !important; | |
| } | |
| label, .block-label span { | |
| color: var(--pruna-text-muted) !important; | |
| font-size: 0.8rem !important; | |
| font-weight: 500 !important; | |
| } | |
| a { color: var(--pruna-link); } | |
| button.primary, button.lg.primary, .gr-button-primary, .primary-button, | |
| button.primary:hover, button.primary:active, button.primary:focus, | |
| .gr-button-primary:hover, .gr-button-primary:active { | |
| background: var(--pruna-accent) !important; | |
| border: 1px solid color-mix(in oklab, var(--pruna-accent) 72%, transparent) !important; | |
| color: #fff !important; | |
| border-radius: 8px !important; | |
| box-shadow: inset 0 1px #fff3 !important; | |
| font-weight: 600 !important; | |
| outline: none !important; | |
| } | |
| button.secondary, button.lg.secondary, .gr-button-secondary, | |
| .gallery-item, .examples button { | |
| border-radius: 10px !important; | |
| } | |
| .block, .gr-group, .form, .panel, .gr-accordion { | |
| border-color: var(--pruna-border) !important; | |
| background: transparent !important; | |
| border-radius: 10px !important; | |
| } | |
| .wrap-inner, .secondary-wrap { | |
| border: 1px solid var(--pruna-input-border) !important; | |
| border-radius: 10px !important; | |
| background: var(--pruna-input-bg) !important; | |
| min-height: 40px !important; | |
| box-shadow: none !important; | |
| } | |
| .wrap-inner:focus-within { | |
| border-color: var(--pruna-focus-border) !important; | |
| box-shadow: var(--pruna-focus-ring) !important; | |
| } | |
| input:not([type="checkbox"]):not([type="radio"]), textarea, select { | |
| background: var(--pruna-bg-card) !important; | |
| border-color: var(--pruna-border) !important; | |
| color: var(--pruna-text-primary) !important; | |
| border-radius: 10px !important; | |
| } | |
| input[type="checkbox"] { | |
| border-radius: 4px !important; | |
| } | |
| input:focus, textarea:focus, select:focus { | |
| border-color: var(--pruna-focus-border) !important; | |
| box-shadow: var(--pruna-focus-ring) !important; | |
| outline: none !important; | |
| } | |
| .image-container, .upload-container, .image-frame, | |
| [data-testid="image"], [data-testid="gallery"] { | |
| border-radius: 10px !important; | |
| overflow: hidden; | |
| } | |
| .accordion, | |
| .accordion.block { | |
| border: 1px solid var(--pruna-accordion-border) !important; | |
| border-radius: 10px !important; | |
| background: var(--pruna-accordion-bg) !important; | |
| box-shadow: none !important; | |
| overflow: hidden !important; | |
| } | |
| .accordion > .label-wrap, | |
| .accordion .label-wrap { | |
| border: none !important; | |
| background: transparent !important; | |
| box-shadow: none !important; | |
| padding: 11px 14px !important; | |
| font-size: 0.92rem !important; | |
| font-weight: 500 !important; | |
| color: var(--pruna-text-primary) !important; | |
| letter-spacing: -0.01em !important; | |
| } | |
| .accordion > .label-wrap:hover, | |
| .accordion .label-wrap:hover { | |
| background: var(--pruna-menu-hover-bg) !important; | |
| } | |
| .options, | |
| ul.options, | |
| .option-list { | |
| background: var(--pruna-bg-card) !important; | |
| color: var(--pruna-text-primary) !important; | |
| border-color: var(--pruna-border) !important; | |
| border-radius: 10px !important; | |
| } | |
| .options { | |
| border: 1px solid var(--pruna-border) !important; | |
| } | |
| .options .item, | |
| .options li { color: var(--pruna-text-primary) !important; } | |
| .options .item:hover, | |
| .options li:hover, | |
| .options .item.selected, | |
| .options .item.active, | |
| .options .active { | |
| background: var(--pruna-dropdown-hover) !important; | |
| color: var(--pruna-text-primary) !important; | |
| } | |
| .page-footer-host, | |
| .page-footer-host .html-container, | |
| .page-footer-host .prose, | |
| .page-footer-host.block, | |
| .page-footer-host .padded { | |
| border: none !important; | |
| background: transparent !important; | |
| box-shadow: none !important; | |
| padding: 0 !important; | |
| margin: 0 !important; | |
| width: 100% !important; | |
| max-width: none !important; | |
| overflow: visible !important; | |
| } | |
| .page-footer { | |
| margin: 32px 0 16px; | |
| padding: 20px 0 0; | |
| border-top: 1px solid var(--pruna-hairline); | |
| } | |
| .page-footer h3 { | |
| margin: 0 0 10px !important; | |
| font-size: 1.05rem !important; | |
| font-weight: 600 !important; | |
| letter-spacing: -0.015em !important; | |
| text-transform: none !important; | |
| color: var(--pruna-text-primary) !important; | |
| } | |
| .community-footer-links { | |
| display: flex; | |
| flex-wrap: wrap; | |
| gap: 8px 16px; | |
| align-items: center; | |
| } | |
| .community-footer-links a { | |
| color: var(--pruna-text-muted) !important; | |
| text-decoration: none !important; | |
| font-size: 0.9rem !important; | |
| font-weight: 500 !important; | |
| } | |
| .community-footer-links a:hover { color: var(--pruna-link) !important; } | |
| footer, .footer { display: none !important; } | |
| @media (max-width: 700px) { | |
| .gradio-container { | |
| padding-left: 12px !important; | |
| padding-right: 12px !important; | |
| } | |
| .app-header { | |
| padding: 4px 0 8px; | |
| margin: 4px 0 0; | |
| } | |
| .app-header-logo { | |
| width: 36px !important; | |
| height: 42px !important; | |
| } | |
| .app-header-brand h1, | |
| .gradio-container .app-header-brand h1 { | |
| font-size: 1.55rem !important; | |
| } | |
| .app-header-tagline { font-size: 0.88rem !important; padding: 0 8px !important; } | |
| .main-tabs > .tab-wrapper, | |
| .main-tabs > .tab-nav, | |
| .main-tabs > .tab-container { margin: 4px 0 14px !important; } | |
| .main-tabs .tab-container > button, | |
| .main-tabs .tab-nav > button, | |
| .main-tabs button[role="tab"] { | |
| padding: 10px 12px !important; | |
| font-size: 0.88rem !important; | |
| min-height: 40px !important; | |
| } | |
| .community-footer-links { gap: 10px 14px; } | |
| } | |
| """ | |
| HEAD = """ | |
| <script> | |
| (function () { | |
| var mode = "dark"; | |
| try { | |
| var stored = localStorage.getItem("pruna-theme"); | |
| if (stored === "light" || stored === "dark") mode = stored; | |
| else { | |
| var param = new URLSearchParams(location.search).get("__theme"); | |
| if (param === "light" || param === "dark") mode = param; | |
| } | |
| } catch (e) {} | |
| document.documentElement.classList.toggle("dark", mode === "dark"); | |
| document.documentElement.dataset.theme = mode; | |
| })(); | |
| </script> | |
| <link rel="preconnect" href="https://fonts.googleapis.com" /> | |
| <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> | |
| <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" /> | |
| <script> | |
| (() => { | |
| const STORAGE_KEY = "pruna-theme"; | |
| const currentMode = () => { | |
| try { | |
| const stored = localStorage.getItem(STORAGE_KEY); | |
| if (stored === "light" || stored === "dark") return stored; | |
| } catch (e) {} | |
| const param = new URLSearchParams(location.search).get("__theme"); | |
| if (param === "light" || param === "dark") return param; | |
| return "dark"; | |
| }; | |
| const queryAll = (selector) => { | |
| const found = [...document.querySelectorAll(selector)]; | |
| document.querySelectorAll("gradio-app").forEach((app) => { | |
| if (app.shadowRoot) found.push(...app.shadowRoot.querySelectorAll(selector)); | |
| }); | |
| return found; | |
| }; | |
| const applyMode = (mode, persist) => { | |
| const dark = mode === "dark"; | |
| const targets = [ | |
| document.documentElement, | |
| document.body, | |
| ...queryAll(".gradio-container"), | |
| ...document.querySelectorAll("gradio-app"), | |
| ].filter(Boolean); | |
| targets.forEach((el) => { | |
| el.classList.toggle("dark", dark); | |
| el.classList.toggle("light", !dark); | |
| }); | |
| document.documentElement.dataset.theme = mode; | |
| const label = dark ? "Switch to light mode" : "Switch to dark mode"; | |
| queryAll(".theme-toggle").forEach((btn) => { | |
| btn.setAttribute("data-mode", mode); | |
| btn.setAttribute("aria-label", label); | |
| btn.setAttribute("title", label); | |
| }); | |
| if (persist) { | |
| try { localStorage.setItem(STORAGE_KEY, mode); } catch (e) {} | |
| try { | |
| const url = new URL(location.href); | |
| url.searchParams.set("__theme", mode); | |
| history.replaceState(null, "", url); | |
| } catch (e) {} | |
| } | |
| }; | |
| applyMode(currentMode(), false); | |
| document.addEventListener("click", (event) => { | |
| const path = typeof event.composedPath === "function" ? event.composedPath() : [event.target]; | |
| const btn = path.find((el) => el.classList && el.classList.contains("theme-toggle")); | |
| if (!btn) return; | |
| event.preventDefault(); | |
| applyMode(currentMode() === "dark" ? "light" : "dark", true); | |
| }); | |
| const sync = () => applyMode(currentMode(), false); | |
| document.addEventListener("DOMContentLoaded", sync); | |
| window.addEventListener("load", () => { | |
| sync(); | |
| setTimeout(sync, 80); | |
| setTimeout(sync, 400); | |
| }); | |
| const startObserver = () => { | |
| if (!document.body || window.__prunaThemeObserver) return; | |
| window.__prunaThemeObserver = true; | |
| const onMutations = (mutations) => { | |
| const mode = currentMode(); | |
| const isDark = document.documentElement.classList.contains("dark"); | |
| const added = mutations.flatMap((mutation) => [...mutation.addedNodes]).filter((node) => node.nodeType === 1); | |
| const hasContainer = added.some((node) => ( | |
| node.classList?.contains("gradio-container") || | |
| node.querySelector?.(".gradio-container, .theme-toggle") | |
| )); | |
| if ((mode === "dark") !== isDark || hasContainer) applyMode(mode, false); | |
| }; | |
| new MutationObserver(onMutations).observe(document.body, { childList: true, subtree: true }); | |
| document.querySelectorAll("gradio-app").forEach((app) => { | |
| if (app.shadowRoot) { | |
| new MutationObserver(onMutations).observe(app.shadowRoot, { childList: true, subtree: true }); | |
| } | |
| }); | |
| }; | |
| if (document.body) startObserver(); | |
| else document.addEventListener("DOMContentLoaded", startObserver); | |
| })(); | |
| </script> | |
| """ | |
| def render_header( | |
| title: str = "P-H3-Image", | |
| tagline: str = ( | |
| "Pruna's image model for text-to-image and image editing, based on MiniMax-H3. " | |
| "By default every request goes through the prompt upsampler first. " | |
| '<a href="https://huggingface.co/PrunaAI/P-H3-Image">Model card</a>' | |
| ), | |
| ) -> None: | |
| gr.HTML( | |
| f""" | |
| <header class="app-header"> | |
| <div class="app-header-bar"> | |
| <div class="app-header-brand"> | |
| <img class="app-header-logo" src="{_LOGO_DATA_URI}" alt="" /> | |
| <h1>{title}</h1> | |
| </div> | |
| <button type="button" class="theme-toggle" data-mode="dark" aria-label="Switch to light mode" title="Switch to light mode"> | |
| <svg class="theme-icon-sun" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> | |
| <circle cx="12" cy="12" r="4"></circle> | |
| <path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"></path> | |
| </svg> | |
| <svg class="theme-icon-moon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> | |
| <path d="M21 14.5A8.5 8.5 0 1 1 9.5 3 7 7 0 0 0 21 14.5z"></path> | |
| </svg> | |
| </button> | |
| </div> | |
| <p class="app-header-tagline">{tagline}</p> | |
| </header> | |
| """, | |
| padding=False, | |
| elem_classes="app-header-host", | |
| ) | |
| def render_footer() -> None: | |
| gr.HTML( | |
| """ | |
| <div class="page-footer"> | |
| <h3>Join the Pruna AI community</h3> | |
| <div class="community-footer-links"> | |
| <a rel="nofollow" href="https://x.com/PrunaAI" target="_blank">X</a> | |
| <a rel="nofollow" href="https://www.linkedin.com/company/pruna-ai" target="_blank">LinkedIn</a> | |
| <a rel="nofollow" href="https://www.instagram.com/pruna.ai/" target="_blank">Instagram</a> | |
| <a rel="nofollow" href="https://discord.gg/JFQmtFKCjd" target="_blank">Discord</a> | |
| <a rel="nofollow" href="https://github.com/PrunaAI/pruna" target="_blank">GitHub</a> | |
| <a rel="nofollow" href="https://www.pruna.ai/" target="_blank">pruna.ai</a> | |
| </div> | |
| </div> | |
| """, | |
| padding=False, | |
| elem_classes="page-footer-host", | |
| ) | |