Spaces:
Sleeping
Sleeping
| """Guild-dark theme: dark green + gold, matching the original backstory forge. | |
| Exports the CSS string and a head-HTML builder (meta tags + JSON-LD). | |
| In Gradio 6, css/head are passed to demo.launch(), not gr.Blocks(). | |
| """ | |
| import html as _html | |
| import json | |
| # Palette | |
| BG = "#2A4032" # deep green page background | |
| PANEL = "#3D5A47" # card/panel green | |
| GOLD = "#D4AF37" # headings, accents | |
| CREAM = "#F2E6CE" # body text | |
| CREAM_DIM = "rgba(242, 230, 206, 0.85)" | |
| RED = "#A7343B" # Loreify CTA red (matches loreify.ai accent) | |
| RED_DARK = "#7E2429" | |
| CSS = """ | |
| @import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&family=Inter:wght@400;500;600;700&display=swap'); | |
| :root { | |
| --lf-bg: #2A4032; | |
| --lf-panel: #3D5A47; | |
| --lf-panel-deep: #24382C; | |
| --lf-gold: #D4AF37; | |
| --lf-cream: #F2E6CE; | |
| --lf-cream-dim: rgba(242, 230, 206, 0.85); | |
| --lf-red: #A7343B; | |
| --lf-red-dark: #7E2429; | |
| } | |
| body, gradio-app, .gradio-container { | |
| background-color: var(--lf-bg) !important; | |
| color: var(--lf-cream); | |
| font-family: 'Inter', system-ui, sans-serif; | |
| } | |
| .gradio-container { max-width: 72rem !important; margin: 0 auto !important; } | |
| /* ---------- typography ---------- */ | |
| /* !important: Gradio's dark-theme prose styles (?__theme=dark on the HF | |
| embed) otherwise override heading colors to white. */ | |
| .lf-page h1 { | |
| font-family: 'Press Start 2P', monospace; | |
| color: var(--lf-gold) !important; | |
| font-size: 1.35rem; | |
| line-height: 1.6; | |
| margin: 1.25rem 0 0.75rem 0; | |
| -webkit-font-smoothing: none; | |
| word-wrap: break-word; | |
| } | |
| .lf-page h2 { | |
| font-family: 'Press Start 2P', monospace; | |
| color: var(--lf-gold) !important; | |
| font-size: 0.95rem; | |
| line-height: 1.6; | |
| margin: 2rem 0 0.75rem 0; | |
| -webkit-font-smoothing: none; | |
| } | |
| .lf-page h3 { color: var(--lf-gold) !important; } | |
| /* native control accents (radios, checkboxes) — gold, not Gradio orange */ | |
| .gradio-container input[type="radio"], | |
| .gradio-container input[type="checkbox"] { accent-color: var(--lf-gold); } | |
| .gradio-container input[type="radio"]:checked, | |
| .gradio-container input[type="checkbox"]:checked { | |
| background-color: var(--lf-gold) !important; | |
| border-color: var(--lf-gold) !important; | |
| } | |
| .lf-page h3 { color: var(--lf-gold); font-size: 1.05rem; margin: 1.25rem 0 0.5rem 0; font-weight: 700; } | |
| .lf-page p, .lf-page li { color: var(--lf-cream-dim); line-height: 1.7; font-size: 1rem; } | |
| .lf-page ul, .lf-page ol { padding-left: 1.25rem; margin: 0.75rem 0; } | |
| .lf-page li::marker { color: var(--lf-gold); } | |
| .lf-page a { color: var(--lf-gold); text-decoration: underline; } | |
| .lf-page strong { color: var(--lf-gold); } | |
| .lf-tagline { font-size: 1.1rem !important; color: var(--lf-cream) !important; } | |
| /* ---------- panels the tool lives in ---------- */ | |
| .lf-panel, .lf-page .block, .gradio-container .form { | |
| background-color: var(--lf-panel) !important; | |
| border: 1px solid rgba(212, 175, 55, 0.35) !important; | |
| border-radius: 8px; | |
| } | |
| .lf-page label span, .lf-page .label-wrap span { color: var(--lf-cream) !important; } | |
| .lf-page input, .lf-page textarea, .lf-page select { | |
| background-color: var(--lf-panel-deep) !important; | |
| color: var(--lf-cream) !important; | |
| border-color: rgba(212, 175, 55, 0.35) !important; | |
| } | |
| /* primary action buttons — gold everywhere, not Gradio's default orange */ | |
| .gradio-container button.primary, .lf-page .lf-generate button { | |
| background: var(--lf-gold) !important; | |
| color: #21301F !important; | |
| border: none !important; | |
| font-weight: 700; | |
| } | |
| .gradio-container button.primary:hover { filter: brightness(1.08); } | |
| /* wide content (stat tables, battle boards) scrolls inside its container */ | |
| .lf-output { overflow-x: auto; } | |
| .lf-output table { min-width: 480px; } | |
| /* ---------- Loreify CTA blocks ---------- */ | |
| .lf-cta { | |
| background: linear-gradient(160deg, rgba(167, 52, 59, 0.16), rgba(167, 52, 59, 0.05)); | |
| border: 1px solid rgba(212, 175, 55, 0.45); | |
| border-radius: 8px; | |
| padding: 1.25rem 1.5rem; | |
| margin: 1.5rem 0; | |
| text-align: center; | |
| } | |
| .lf-cta p { color: var(--lf-cream); font-size: 1.05rem; margin: 0 0 0.9rem 0; } | |
| .lf-cta .lf-cta-btn { | |
| display: inline-block; | |
| background: var(--lf-red); | |
| color: #FFFBE0 !important; | |
| border: 2px solid var(--lf-red-dark); | |
| border-radius: 6px; | |
| padding: 0.7rem 1.5rem; | |
| font-weight: 700; | |
| font-size: 1rem; | |
| text-decoration: none !important; | |
| box-shadow: 1px 2px 4px rgba(0,0,0,0.25); | |
| } | |
| .lf-cta .lf-cta-btn:hover { background: var(--lf-red-dark); } | |
| .lf-cta .lf-cta-sub { font-size: 0.85rem; color: var(--lf-cream-dim); margin-top: 0.6rem; margin-bottom: 0; } | |
| /* ---------- output / example cards ---------- */ | |
| .lf-output, .lf-example { | |
| background: var(--lf-panel); | |
| border: 1px solid rgba(212, 175, 55, 0.45); | |
| border-radius: 8px; | |
| padding: 1.25rem 1.5rem; | |
| margin: 0.75rem 0; | |
| } | |
| .lf-output h3, .lf-example h3 { margin-top: 0.75rem; } | |
| /* related tools + footer */ | |
| .lf-related { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 1rem; margin: 1rem 0; } | |
| .lf-related a.lf-related-card { | |
| display: block; background: var(--lf-panel); | |
| border: 1px solid rgba(212, 175, 55, 0.4); border-radius: 8px; | |
| padding: 1rem; text-decoration: none; | |
| } | |
| .lf-related a.lf-related-card:hover { border-color: var(--lf-gold); } | |
| .lf-related .lf-related-title { color: var(--lf-gold); font-weight: 700; margin-bottom: 0.35rem; } | |
| .lf-related .lf-related-desc { color: var(--lf-cream-dim); font-size: 0.9rem; } | |
| .lf-disclaimer { font-size: 0.82rem; color: rgba(242, 230, 206, 0.6); margin: 2rem 0 1rem 0; line-height: 1.6; } | |
| /* FAQ */ | |
| .lf-faq details { | |
| background: var(--lf-panel); border: 1px solid rgba(212, 175, 55, 0.35); | |
| border-radius: 8px; padding: 0.85rem 1.1rem; margin: 0.6rem 0; | |
| } | |
| .lf-faq summary { color: var(--lf-gold); font-weight: 700; cursor: pointer; font-size: 1rem; } | |
| .lf-faq details p { margin: 0.7rem 0 0.2rem 0; } | |
| /* mobile */ | |
| @media (max-width: 640px) { | |
| .lf-page h1 { font-size: 1.05rem; } | |
| .lf-page h2 { font-size: 0.85rem; } | |
| .lf-cta { padding: 1rem; } | |
| } | |
| footer { display: none !important; } | |
| /* offscreen-but-in-DOM (e.g. clipboard source textarea) */ | |
| .lf-offscreen { | |
| position: absolute !important; | |
| left: -99999px !important; | |
| top: 0 !important; | |
| height: 1px !important; | |
| width: 1px !important; | |
| overflow: hidden !important; | |
| opacity: 0; | |
| pointer-events: none; | |
| } | |
| """ | |
| def build_head(config, jsonld_extra: dict | None = None) -> str: | |
| """Meta description + WebApplication JSON-LD for the page head.""" | |
| desc = _html.escape(config.tagline, quote=True) | |
| data = { | |
| "@context": "https://schema.org", | |
| "@type": "WebApplication", | |
| "name": config.h1, | |
| "description": config.tagline, | |
| "url": config.space_url, | |
| "applicationCategory": "GameApplication", | |
| "operatingSystem": "Any", | |
| "offers": {"@type": "Offer", "price": "0", "priceCurrency": "USD"}, | |
| } | |
| if jsonld_extra: | |
| data.update(jsonld_extra) | |
| return ( | |
| f'<meta name="description" content="{desc}">\n' | |
| f'<script type="application/ld+json">{json.dumps(data)}</script>' | |
| ) | |