dryymatt's picture
Upload app.py
62e64a3 verified
import gradio as gr
import random
import html
# ═══════════════════════════════════════════════════════════════
# WIZARD ORACLE — "The Glyph Chamber"
# A single-screen divination interface. No chat bubbles. No chrome.
# You cast a spell (type + Enter), the wizard responds with
# a randomly generated oracle reading + a summoned glyph (ASCII art).
# Inspired by the minimalist command-palette vibe of catdoes.com
# but reimagined as a magical artifact.
# ═══════════════════════════════════════════════════════════════
GLYPHS = [
"""
/\\
/ \\
/ /\ \\
/ / \ \\
/_/ \_\\
| || |
|__||__|
""",
"""
.-.
(o o)
| O \\
\ /
`~'
""",
"""
/\
/||\
/ || \\
/ || \\
/___||___\\
""",
"""
.-"""-.
/ \\
| o o |
| < |
| \___/ |
\_______/
""",
"""
_____
/ \\
| () () |
\ ^ /
|||||
|||||
""",
"""
/\
/ \\
/ \\
/______\\
( ( ) )
\ \ / /
\ \/ /
\____/
""",
]
RUNES = ["ᚠ", "ᚢ", "ᚦ", "ᚨ", "ᚱ", "ᚲ", "ᚷ", "ᚹ", "ᚺ", "ᚾ", "ᛁ", "ᛃ", "ᛈ", "ᛇ", "ᛉ", "ᛊ", "ᛏ", "ᛒ", "ᛖ", "ᛗ", "ᛚ", "ᛜ", "ᛞ", "ᛟ"]
OMENS = [
"The threads of fate converge upon your query.",
"A shadow passes. Look to the eastern wind.",
"The crystal hums with unfamiliar resonance.",
"Beneath the surface, something stirs.",
"The stars align, but not as you expect.",
"A door opens where once was wall.",
"The old magic whispers: patience.",
"Your path forks. Neither is wrong.",
"The glyph burns cold. Truth approaches.",
"What you seek is also seeking you.",
"The veil thins. Speak your true name.",
"A single spark can unmake the dark.",
"The wizard nods. The answer is within you.",
"Time is a spiral. You have been here before.",
"The silence holds more than the words.",
]
WISDOM = [
"To ask is to begin.",
"Still waters hold the deepest truths.",
"The map is not the territory.",
"Every ending is a seed.",
"You are the spell you cast.",
"Light enters through the cracks.",
"The journey is the destination wearing a disguise.",
"What is broken can be reforged stronger.",
"Listen to the spaces between sounds.",
"The wizard sees you. That is enough.",
]
def summon(query):
if not query or not query.strip():
return "", ""
query = html.escape(query.strip())
# Build the oracle response
omen = random.choice(OMENS)
wisdom = random.choice(WISDOM)
glyph = random.choice(GLYPHS)
rune_line = " ".join(random.sample(RUNES, 5))
response_html = f"""
<div style="text-align:center; animation: fadeIn 0.6s ease-out;">
<div style="font-family: 'Courier New', monospace; font-size: 0.7rem; color: #555; letter-spacing: 0.3em; margin-bottom: 1rem;">
{rune_line}
</div>
<pre style="font-family: 'Courier New', monospace; font-size: 0.85rem; color: #aaa; line-height: 1.2; margin: 1.5rem 0;">{glyph}</pre>
<div style="font-size: 1.15rem; color: #e5e5e5; font-weight: 300; line-height: 1.6; max-width: 500px; margin: 0 auto;">
{omen}
</div>
<div style="font-size: 0.85rem; color: #666; font-style: italic; margin-top: 1.5rem; border-left: 1px solid #444; padding-left: 1rem; display: inline-block;">
{wisdom}
</div>
</div>
"""
return "", response_html
def clear_all():
return "", ""
# ═══════════════════════════════════════════════════════════════
# CSS — Full screen, pure void, single input line at bottom
# ═══════════════════════════════════════════════════════════════
css = """
@import url('https://fonts.googleapis.com/css2?family=Cinzel:wght@400;600&family=JetBrains+Mono:wght@300;400&display=swap');
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes pulse {
0%, 100% { opacity: 0.3; }
50% { opacity: 0.8; }
}
body {
margin: 0 !important;
padding: 0 !important;
background: #050505 !important;
color: #e5e5e5 !important;
overflow: hidden !important;
}
.gradio-container {
max-width: 100vw !important;
width: 100vw !important;
height: 100vh !important;
margin: 0 !important;
padding: 0 !important;
border-radius: 0 !important;
background: #050505 !important;
}
#chamber {
height: 100vh;
display: flex;
flex-direction: column;
justify-content: space-between;
padding: 2.5rem 3rem 2rem 3rem;
box-sizing: border-box;
position: relative;
}
#wizard-mark {
position: fixed;
top: 2rem;
left: 50%;
transform: translateX(-50%);
z-index: 100;
text-align: center;
pointer-events: none;
}
#wizard-mark .icon {
font-size: 2rem;
filter: grayscale(100%) brightness(0.6);
animation: pulse 4s ease-in-out infinite;
}
#wizard-mark .title {
font-family: 'Cinzel', serif !important;
font-size: 0.75rem !important;
color: #333 !important;
letter-spacing: 0.25em;
text-transform: uppercase;
margin-top: 0.5rem;
}
#output-area {
flex-grow: 1;
display: flex;
align-items: center;
justify-content: center;
overflow-y: auto;
padding: 4rem 0 2rem 0;
}
#input-zone {
display: flex;
align-items: center;
gap: 0.75rem;
padding-top: 1.5rem;
border-top: 1px solid #1a1a1a;
}
#spell-input {
background: transparent !important;
border: none !important;
border-bottom: 1px solid #2a2a2a !important;
color: #e5e5e5 !important;
font-family: 'JetBrains Mono', monospace !important;
font-size: 1rem !important;
padding: 0.75rem 0 !important;
border-radius: 0 !important;
box-shadow: none !important;
transition: border-color 0.3s ease;
}
#spell-input:focus {
border-bottom-color: #666 !important;
outline: none !important;
}
#spell-input::placeholder {
color: #333 !important;
font-style: italic;
}
#cast-btn {
background: transparent !important;
border: 1px solid #2a2a2a !important;
color: #444 !important;
font-family: 'JetBrains Mono', monospace !important;
font-size: 0.75rem !important;
padding: 0.6rem 1.2rem !important;
border-radius: 0 !important;
cursor: pointer;
transition: all 0.25s ease;
letter-spacing: 0.1em;
}
#cast-btn:hover {
border-color: #666 !important;
color: #e5e5e5 !important;
}
#clear-btn {
position: fixed;
top: 2rem;
right: 2.5rem;
background: transparent !important;
border: none !important;
color: #222 !important;
font-size: 0.7rem !important;
font-family: 'JetBrains Mono', monospace !important;
cursor: pointer;
z-index: 100;
letter-spacing: 0.05em;
transition: color 0.2s ease;
}
#clear-btn:hover {
color: #888 !important;
}
.scrollbar-hide::-webkit-scrollbar {
display: none;
}
"""
with gr.Blocks(css=css, theme=gr.themes.Base(), fill_height=True) as demo:
gr.HTML("""
<div id="wizard-mark">
<div class="icon">🧙‍♂️</div>
<div class="title">The Glyph Chamber</div>
</div>
""")
clear_btn = gr.Button("[ dismiss ]", elem_id="clear-btn")
with gr.Column(elem_id="chamber"):
output = gr.HTML(elem_id="output-area")
with gr.Row(elem_id="input-zone"):
spell = gr.Textbox(
placeholder="speak your intent...",
show_label=False,
container=False,
scale=10,
elem_id="spell-input"
)
cast_btn = gr.Button("CAST", scale=1, elem_id="cast-btn")
spell.submit(summon, [spell], [spell, output])
cast_btn.click(summon, [spell], [spell, output])
clear_btn.click(clear_all, outputs=[spell, output])
if __name__ == "__main__":
demo.launch()