"""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 = """ """ 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. " 'Model card' ), ) -> None: gr.HTML( f"""

{title}

{tagline}

""", padding=False, elem_classes="app-header-host", ) def render_footer() -> None: gr.HTML( """ """, padding=False, elem_classes="page-footer-host", )