BladeSzaSza commited on
Commit
0892623
·
1 Parent(s): 39d4d52

Cleanup: Remove unused files, Svelte frontend, old UI, and update docs for Streamlit-only architecture

Browse files
Files changed (3) hide show
  1. ui/__init__.py +0 -1
  2. ui/interfaces.py +0 -458
  3. ui/themes.py +0 -428
ui/__init__.py DELETED
@@ -1 +0,0 @@
1
- # UI module initialization
 
 
ui/interfaces.py DELETED
@@ -1,458 +0,0 @@
1
- import gradio as gr
2
- from typing import Callable, Any, Optional
3
- import numpy as np
4
-
5
- def create_voice_interface(pipeline: Any, game_mechanics: Any) -> gr.Column:
6
- """Create voice-controlled interface for monster generation"""
7
-
8
- with gr.Column() as voice_interface:
9
- gr.Markdown("""
10
- ### 🎙️ Voice Control Interface
11
- Speak your monster description or use the microphone to create your digital companion!
12
- """)
13
-
14
- with gr.Row():
15
- with gr.Column(scale=1):
16
- # Voice input
17
- voice_input = gr.Audio(
18
- label="🎤 Voice Description",
19
- sources=["microphone", "upload"],
20
- type="filepath",
21
- elem_classes=["cyber-input"],
22
- info="Describe your monster using voice"
23
- )
24
-
25
- # Voice control buttons
26
- with gr.Row():
27
- start_recording = gr.Button(
28
- "🔴 Start Recording",
29
- elem_classes=["cyber-button"],
30
- size="sm"
31
- )
32
- stop_recording = gr.Button(
33
- "⏹️ Stop Recording",
34
- elem_classes=["cyber-button"],
35
- size="sm"
36
- )
37
-
38
- # Real-time transcription display
39
- transcription_display = gr.Textbox(
40
- label="📝 Transcription",
41
- placeholder="Your voice will be transcribed here...",
42
- interactive=False,
43
- lines=3,
44
- elem_classes=["cyber-output"]
45
- )
46
-
47
- # Voice commands
48
- gr.Markdown("""
49
- **Voice Commands:**
50
- - "Create a [type] monster" - Generate specific type
51
- - "Make it [color/trait]" - Add characteristics
52
- - "Give it [ability]" - Add special abilities
53
- """)
54
-
55
- with gr.Column(scale=1):
56
- # Preview and generation status
57
- generation_status = gr.Markdown(
58
- value="🟢 Ready for voice input",
59
- elem_classes=["cyber-message"]
60
- )
61
-
62
- # Audio visualization
63
- audio_viz = gr.HTML(
64
- value="""
65
- <div class="audio-visualizer">
66
- <div class="bar"></div>
67
- <div class="bar"></div>
68
- <div class="bar"></div>
69
- <div class="bar"></div>
70
- <div class="bar"></div>
71
- </div>
72
- """,
73
- elem_classes=["cyber-container"]
74
- )
75
-
76
- # Quick voice templates
77
- gr.Markdown("**Quick Templates:**")
78
- template_buttons = []
79
- templates = [
80
- ("🔥 Fire Type", "Create a fierce fire-breathing dragon monster"),
81
- ("💧 Water Type", "Create a graceful aquatic monster"),
82
- ("⚡ Electric Type", "Create a sparking electric monster"),
83
- ("🌿 Nature Type", "Create a peaceful nature guardian monster")
84
- ]
85
-
86
- for label, prompt in templates:
87
- btn = gr.Button(label, size="sm", elem_classes=["cyber-button"])
88
- template_buttons.append((btn, prompt))
89
-
90
- # Voice interface specific styling
91
- gr.HTML("""
92
- <style>
93
- .audio-visualizer {
94
- display: flex;
95
- justify-content: center;
96
- align-items: center;
97
- height: 100px;
98
- gap: 5px;
99
- }
100
-
101
- .audio-visualizer .bar {
102
- width: 10px;
103
- height: 30px;
104
- background: linear-gradient(to top, #00ff41, #8A2BE2);
105
- animation: audio-wave 1s ease-in-out infinite;
106
- border-radius: 5px;
107
- }
108
-
109
- .audio-visualizer .bar:nth-child(1) { animation-delay: 0s; }
110
- .audio-visualizer .bar:nth-child(2) { animation-delay: 0.1s; }
111
- .audio-visualizer .bar:nth-child(3) { animation-delay: 0.2s; }
112
- .audio-visualizer .bar:nth-child(4) { animation-delay: 0.3s; }
113
- .audio-visualizer .bar:nth-child(5) { animation-delay: 0.4s; }
114
-
115
- @keyframes audio-wave {
116
- 0%, 100% { height: 30px; }
117
- 50% { height: 60px; }
118
- }
119
- </style>
120
- """)
121
-
122
- return voice_interface
123
-
124
- def create_visual_interface(pipeline: Any, game_mechanics: Any) -> gr.Column:
125
- """Create visual/camera-based interface for monster generation"""
126
-
127
- with gr.Column() as visual_interface:
128
- gr.Markdown("""
129
- ### 👁️ Visual Control Interface
130
- Use images, drawings, or camera input to inspire your monster creation!
131
- """)
132
-
133
- with gr.Row():
134
- with gr.Column(scale=1):
135
- # Image input options
136
- with gr.Tabs():
137
- with gr.TabItem("📷 Camera"):
138
- camera_input = gr.Image(
139
- label="Camera Capture",
140
- sources=["webcam"],
141
- type="pil",
142
- elem_classes=["cyber-input", "camera-feed"]
143
- )
144
-
145
- with gr.TabItem("🖼️ Upload"):
146
- image_upload = gr.File(
147
- label="Upload Reference Images",
148
- file_count="multiple",
149
- file_types=["image"],
150
- elem_classes=["cyber-input"]
151
- )
152
-
153
- uploaded_gallery = gr.Gallery(
154
- label="Uploaded References",
155
- columns=3,
156
- rows=1,
157
- height="150px",
158
- elem_classes=["cyber-container"]
159
- )
160
-
161
- with gr.TabItem("✏️ Draw"):
162
- sketch_pad = gr.Sketchpad(
163
- label="Draw Your Monster",
164
- type="pil",
165
- elem_classes=["cyber-input", "sketch-pad"]
166
- )
167
-
168
- # Visual style options
169
- gr.Markdown("**Visual Style Options:**")
170
-
171
- style_modifier = gr.CheckboxGroup(
172
- choices=[
173
- "🎨 Artistic",
174
- "🤖 Mechanical",
175
- "✨ Magical",
176
- "🌊 Organic",
177
- "💎 Crystalline"
178
- ],
179
- label="Style Modifiers",
180
- elem_classes=["cyber-checkbox"]
181
- )
182
-
183
- color_palette = gr.Radio(
184
- choices=[
185
- "🌈 Vibrant",
186
- "🌑 Dark",
187
- "❄️ Cool",
188
- "🔥 Warm",
189
- "🎨 Custom"
190
- ],
191
- label="Color Palette",
192
- value="🌈 Vibrant",
193
- elem_classes=["cyber-radio"]
194
- )
195
-
196
- with gr.Column(scale=1):
197
- # Image analysis display
198
- image_analysis = gr.Markdown(
199
- value="📊 Image Analysis Results",
200
- elem_classes=["cyber-message"]
201
- )
202
-
203
- # Detected features
204
- detected_features = gr.JSON(
205
- label="🔍 Detected Features",
206
- elem_classes=["cyber-stats"]
207
- )
208
-
209
- # Generation preview
210
- preview_placeholder = gr.HTML(
211
- value="""
212
- <div class="preview-container">
213
- <div class="scanning-overlay">
214
- <div class="scan-line"></div>
215
- </div>
216
- <p>Preview will appear here...</p>
217
- </div>
218
- """,
219
- elem_classes=["cyber-container"]
220
- )
221
-
222
- # Confidence meter
223
- confidence_display = gr.HTML(
224
- value="""
225
- <div class="confidence-meter">
226
- <label>Generation Confidence:</label>
227
- <div class="meter-bar">
228
- <div class="meter-fill" style="width: 0%"></div>
229
- </div>
230
- <span class="meter-value">0%</span>
231
- </div>
232
- """,
233
- elem_classes=["cyber-container"]
234
- )
235
-
236
- # Visual interface specific styling
237
- gr.HTML("""
238
- <style>
239
- .camera-feed {
240
- border: 3px solid #00ff41;
241
- border-radius: 10px;
242
- overflow: hidden;
243
- position: relative;
244
- }
245
-
246
- .camera-feed::after {
247
- content: 'LIVE';
248
- position: absolute;
249
- top: 10px;
250
- right: 10px;
251
- background: red;
252
- color: white;
253
- padding: 5px 10px;
254
- border-radius: 5px;
255
- font-size: 12px;
256
- animation: blink 1s infinite;
257
- }
258
-
259
- @keyframes blink {
260
- 0%, 100% { opacity: 1; }
261
- 50% { opacity: 0.5; }
262
- }
263
-
264
- .sketch-pad {
265
- background: rgba(0, 0, 0, 0.9);
266
- border: 2px solid #8A2BE2;
267
- }
268
-
269
- .preview-container {
270
- position: relative;
271
- height: 200px;
272
- display: flex;
273
- align-items: center;
274
- justify-content: center;
275
- overflow: hidden;
276
- }
277
-
278
- .scanning-overlay {
279
- position: absolute;
280
- top: 0;
281
- left: 0;
282
- right: 0;
283
- bottom: 0;
284
- pointer-events: none;
285
- }
286
-
287
- .scan-line {
288
- position: absolute;
289
- top: 0;
290
- left: 0;
291
- right: 0;
292
- height: 2px;
293
- background: linear-gradient(90deg, transparent, #00ff41, transparent);
294
- animation: scan-vertical 2s linear infinite;
295
- }
296
-
297
- @keyframes scan-vertical {
298
- 0% { top: 0; }
299
- 100% { top: 100%; }
300
- }
301
-
302
- .confidence-meter {
303
- padding: 15px;
304
- }
305
-
306
- .confidence-meter label {
307
- color: #8A2BE2;
308
- font-size: 14px;
309
- margin-bottom: 5px;
310
- display: block;
311
- }
312
-
313
- .meter-bar {
314
- background: rgba(0, 0, 0, 0.5);
315
- border: 1px solid #00ff41;
316
- height: 20px;
317
- border-radius: 10px;
318
- overflow: hidden;
319
- margin: 10px 0;
320
- }
321
-
322
- .meter-fill {
323
- height: 100%;
324
- background: linear-gradient(90deg, #00ff41, #8A2BE2);
325
- transition: width 0.5s ease;
326
- }
327
-
328
- .meter-value {
329
- color: #00ff41;
330
- font-weight: bold;
331
- font-size: 18px;
332
- }
333
- </style>
334
- """)
335
-
336
- return visual_interface
337
-
338
- def create_monster_status_display() -> gr.Column:
339
- """Create monster status display component"""
340
-
341
- with gr.Column() as status_display:
342
- # 3D Model viewer
343
- model_viewer = gr.Model3D(
344
- label="Your Digital Monster",
345
- height=400,
346
- elem_classes=["monster-display"]
347
- )
348
-
349
- # Status indicators
350
- with gr.Row():
351
- hp_bar = gr.HTML(
352
- value=create_status_bar("HP", 100, 100, "#ff4444"),
353
- elem_classes=["status-bar"]
354
- )
355
-
356
- hunger_bar = gr.HTML(
357
- value=create_status_bar("Hunger", 80, 100, "#ffaa44"),
358
- elem_classes=["status-bar"]
359
- )
360
-
361
- happiness_bar = gr.HTML(
362
- value=create_status_bar("Happiness", 90, 100, "#44ff44"),
363
- elem_classes=["status-bar"]
364
- )
365
-
366
- # Communication display
367
- communication = gr.Textbox(
368
- label="Monster Says",
369
- value="🤖💚9️⃣0️⃣",
370
- interactive=False,
371
- elem_classes=["cyber-dialogue"]
372
- )
373
-
374
- # Evolution progress
375
- evolution_display = gr.HTML(
376
- value="""
377
- <div class="evolution-progress">
378
- <h4>Evolution Progress</h4>
379
- <div class="progress-ring">
380
- <svg width="120" height="120">
381
- <circle cx="60" cy="60" r="50" stroke="#333" stroke-width="10" fill="none"/>
382
- <circle cx="60" cy="60" r="50" stroke="#8A2BE2" stroke-width="10" fill="none"
383
- stroke-dasharray="314" stroke-dashoffset="157"
384
- transform="rotate(-90 60 60)"/>
385
- </svg>
386
- <div class="progress-text">50%</div>
387
- </div>
388
- </div>
389
- """,
390
- elem_classes=["evolution-display"]
391
- )
392
-
393
- return status_display
394
-
395
- def create_status_bar(label: str, current: int, max_val: int, color: str) -> str:
396
- """Create HTML status bar"""
397
- percentage = (current / max_val) * 100
398
-
399
- return f"""
400
- <div class="status-bar-container">
401
- <label>{label}</label>
402
- <div class="status-bar-bg">
403
- <div class="status-bar-fill" style="width: {percentage}%; background: {color};"></div>
404
- </div>
405
- <span class="status-value">{current}/{max_val}</span>
406
- </div>
407
- """
408
-
409
- def create_training_interface() -> gr.Column:
410
- """Create training interface component"""
411
-
412
- with gr.Column() as training_interface:
413
- gr.Markdown("""
414
- ### 💪 Training Center
415
- Train your monster to improve its stats and prepare for evolution!
416
- """)
417
-
418
- # Training schedule
419
- with gr.Row():
420
- with gr.Column():
421
- training_schedule = gr.DataFrame(
422
- headers=["Time", "Activity", "Stat Focus", "Intensity"],
423
- datatype=["str", "str", "str", "number"],
424
- value=[
425
- ["Morning", "Strength Training", "Attack", 7],
426
- ["Afternoon", "Agility Course", "Speed", 5],
427
- ["Evening", "Meditation", "Special", 3]
428
- ],
429
- elem_classes=["cyber-table"]
430
- )
431
-
432
- with gr.Column():
433
- # Training mini-game
434
- training_game = gr.HTML(
435
- value="""
436
- <div class="training-game">
437
- <h4>Quick Training</h4>
438
- <div class="game-area">
439
- <div class="target" id="training-target"></div>
440
- </div>
441
- <p>Click the targets to train!</p>
442
- </div>
443
- """,
444
- elem_classes=["cyber-container"]
445
- )
446
-
447
- # Training rewards
448
- rewards_display = gr.Markdown(
449
- """
450
- **Today's Rewards:**
451
- - 🏆 +15 Attack
452
- - 🛡️ +10 Defense
453
- - ⚡ +5 Speed
454
- """,
455
- elem_classes=["cyber-message"]
456
- )
457
-
458
- return training_interface
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ui/themes.py DELETED
@@ -1,428 +0,0 @@
1
- import gradio as gr
2
- from gradio.themes.base import Base
3
- from gradio.themes.utils import colors, fonts, sizes
4
-
5
- def get_cyberpunk_theme():
6
- """Create cyberpunk-themed Gradio theme"""
7
-
8
- theme = gr.themes.Base(
9
- primary_hue=colors.green,
10
- secondary_hue=colors.purple,
11
- neutral_hue=colors.gray,
12
- font=[fonts.GoogleFont("Orbitron"), "monospace", "sans-serif"],
13
- ).set(
14
- # Background colors
15
- body_background_fill="linear-gradient(135deg, #0a0a0a, #1a0033, #001122)",
16
- body_background_fill_dark="linear-gradient(135deg, #050505, #0d001a, #000811)",
17
-
18
- # Text colors
19
- body_text_color="#00ff41",
20
- body_text_color_dark="#00ff41",
21
- body_text_color_subdued="#8A2BE2",
22
- body_text_color_subdued_dark="#8A2BE2",
23
-
24
- # Component colors
25
- background_fill_primary="rgba(0, 255, 65, 0.1)",
26
- background_fill_primary_dark="rgba(0, 255, 65, 0.05)",
27
- background_fill_secondary="rgba(138, 43, 226, 0.1)",
28
- background_fill_secondary_dark="rgba(138, 43, 226, 0.05)",
29
-
30
- # Borders
31
- border_color_primary="#00ff41",
32
- border_color_primary_dark="#00ff41",
33
- border_color_accent="#8A2BE2",
34
- border_color_accent_dark="#8A2BE2",
35
-
36
- # Shadows
37
- shadow_drop="0 0 20px rgba(0, 255, 65, 0.5)",
38
- shadow_drop_lg="0 0 30px rgba(138, 43, 226, 0.5)",
39
-
40
- # Buttons
41
- button_primary_background_fill="linear-gradient(45deg, #00ff41, #8A2BE2)",
42
- button_primary_background_fill_hover="linear-gradient(45deg, #00ff41, #9932CC)",
43
- button_primary_background_fill_dark="linear-gradient(45deg, #00cc33, #7B68EE)",
44
- button_primary_text_color="#000000",
45
- button_primary_text_color_dark="#000000",
46
-
47
- # Inputs
48
- input_background_fill="rgba(0, 0, 0, 0.8)",
49
- input_background_fill_dark="rgba(0, 0, 0, 0.9)",
50
- input_border_color="#00ff41",
51
- input_border_color_dark="#00ff41",
52
- input_border_color_focus="#8A2BE2",
53
- input_border_color_focus_dark="#8A2BE2",
54
-
55
- # Other elements
56
- block_background_fill="rgba(0, 0, 0, 0.6)",
57
- block_background_fill_dark="rgba(0, 0, 0, 0.8)",
58
- block_border_color="#00ff41",
59
- block_border_color_dark="#00ff41",
60
- block_border_width="2px",
61
- block_shadow="0 0 15px rgba(0, 255, 65, 0.3)",
62
-
63
- # Radius
64
- radius_lg="8px",
65
- radius_md="6px",
66
- radius_sm="4px",
67
- )
68
-
69
- return theme
70
-
71
- # Custom CSS for additional cyberpunk styling
72
- CYBERPUNK_CSS = """
73
- /* Import cyberpunk font */
74
- @import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&display=swap');
75
-
76
- /* Global styles */
77
- * {
78
- font-family: 'Orbitron', monospace !important;
79
- }
80
-
81
- /* Animated background */
82
- .gradio-container {
83
- background: linear-gradient(135deg, #0a0a0a, #1a0033, #001122);
84
- background-size: 400% 400%;
85
- animation: gradient-shift 15s ease infinite;
86
- }
87
-
88
- @keyframes gradient-shift {
89
- 0% { background-position: 0% 50%; }
90
- 50% { background-position: 100% 50%; }
91
- 100% { background-position: 0% 50%; }
92
- }
93
-
94
- /* Cyber header */
95
- .cyber-header {
96
- background: linear-gradient(135deg, rgba(0,0,0,0.9), rgba(26,0,51,0.9));
97
- border: 2px solid #00ff41;
98
- border-radius: 10px;
99
- padding: 30px;
100
- margin-bottom: 30px;
101
- position: relative;
102
- overflow: hidden;
103
- box-shadow: 0 0 30px rgba(0,255,65,0.5), inset 0 0 30px rgba(0,255,65,0.1);
104
- }
105
-
106
- .cyber-header::before {
107
- content: '';
108
- position: absolute;
109
- top: -2px;
110
- left: -2px;
111
- right: -2px;
112
- bottom: -2px;
113
- background: linear-gradient(45deg, #00ff41, #8A2BE2, #00ff41);
114
- z-index: -1;
115
- animation: border-glow 3s linear infinite;
116
- filter: blur(5px);
117
- }
118
-
119
- @keyframes border-glow {
120
- 0%, 100% { opacity: 1; }
121
- 50% { opacity: 0.5; }
122
- }
123
-
124
- /* Glitch text effect */
125
- .glitch-text {
126
- position: relative;
127
- color: #00ff41;
128
- font-size: 3em;
129
- font-weight: 900;
130
- text-transform: uppercase;
131
- text-shadow:
132
- 0 0 10px #00ff41,
133
- 0 0 20px #00ff41,
134
- 0 0 40px #00ff41;
135
- animation: text-glow 2s ease-in-out infinite alternate;
136
- }
137
-
138
- @keyframes text-glow {
139
- from { text-shadow: 0 0 10px #00ff41, 0 0 20px #00ff41, 0 0 40px #00ff41; }
140
- to { text-shadow: 0 0 20px #00ff41, 0 0 30px #00ff41, 0 0 50px #00ff41; }
141
- }
142
-
143
- .glitch-text::before,
144
- .glitch-text::after {
145
- content: attr(data-text);
146
- position: absolute;
147
- top: 0;
148
- left: 0;
149
- width: 100%;
150
- height: 100%;
151
- }
152
-
153
- .glitch-text::before {
154
- animation: glitch-1 0.5s infinite;
155
- color: #8A2BE2;
156
- z-index: -1;
157
- }
158
-
159
- .glitch-text::after {
160
- animation: glitch-2 0.5s infinite;
161
- color: #00ff41;
162
- z-index: -2;
163
- }
164
-
165
- @keyframes glitch-1 {
166
- 0% { clip: rect(44px, 450px, 56px, 0); transform: translate(0); }
167
- 20% { clip: rect(20px, 450px, 30px, 0); transform: translate(-2px, 2px); }
168
- 40% { clip: rect(85px, 450px, 95px, 0); transform: translate(2px, -2px); }
169
- 60% { clip: rect(10px, 450px, 20px, 0); transform: translate(-1px, 1px); }
170
- 80% { clip: rect(60px, 450px, 70px, 0); transform: translate(1px, -1px); }
171
- 100% { clip: rect(44px, 450px, 56px, 0); transform: translate(0); }
172
- }
173
-
174
- @keyframes glitch-2 {
175
- 0% { clip: rect(65px, 450px, 75px, 0); transform: translate(0); }
176
- 20% { clip: rect(30px, 450px, 40px, 0); transform: translate(2px, -2px); }
177
- 40% { clip: rect(90px, 450px, 100px, 0); transform: translate(-2px, 2px); }
178
- 60% { clip: rect(15px, 450px, 25px, 0); transform: translate(1px, -1px); }
179
- 80% { clip: rect(70px, 450px, 80px, 0); transform: translate(-1px, 1px); }
180
- 100% { clip: rect(65px, 450px, 75px, 0); transform: translate(0); }
181
- }
182
-
183
- /* Cyber subtitle */
184
- .cyber-subtitle {
185
- color: #8A2BE2;
186
- font-size: 1.2em;
187
- text-transform: uppercase;
188
- letter-spacing: 2px;
189
- text-shadow: 0 0 10px #8A2BE2;
190
- }
191
-
192
- /* Pulse line */
193
- .pulse-line {
194
- height: 2px;
195
- background: linear-gradient(90deg, transparent, #00ff41, transparent);
196
- margin: 20px 0;
197
- animation: pulse-width 2s ease-in-out infinite;
198
- }
199
-
200
- @keyframes pulse-width {
201
- 0%, 100% { transform: scaleX(0.5); opacity: 0.5; }
202
- 50% { transform: scaleX(1); opacity: 1; }
203
- }
204
-
205
- /* Cyber containers */
206
- .cyber-container {
207
- background: rgba(0, 0, 0, 0.8);
208
- border: 2px solid #00ff41;
209
- border-radius: 8px;
210
- padding: 20px;
211
- position: relative;
212
- box-shadow:
213
- 0 0 20px rgba(0, 255, 65, 0.3),
214
- inset 0 0 20px rgba(0, 255, 65, 0.1);
215
- animation: container-pulse 4s ease-in-out infinite;
216
- }
217
-
218
- @keyframes container-pulse {
219
- 0%, 100% {
220
- border-color: #00ff41;
221
- box-shadow: 0 0 20px rgba(0, 255, 65, 0.3), inset 0 0 20px rgba(0, 255, 65, 0.1);
222
- }
223
- 50% {
224
- border-color: #8A2BE2;
225
- box-shadow: 0 0 30px rgba(138, 43, 226, 0.5), inset 0 0 20px rgba(138, 43, 226, 0.1);
226
- }
227
- }
228
-
229
- /* Cyber buttons */
230
- .cyber-button {
231
- background: linear-gradient(45deg, #00ff41, #8A2BE2);
232
- border: none;
233
- color: #000;
234
- font-weight: bold;
235
- text-transform: uppercase;
236
- letter-spacing: 1px;
237
- padding: 12px 24px;
238
- border-radius: 6px;
239
- position: relative;
240
- overflow: hidden;
241
- transition: all 0.3s ease;
242
- box-shadow: 0 0 20px rgba(0, 255, 65, 0.5);
243
- }
244
-
245
- .cyber-button::before {
246
- content: '';
247
- position: absolute;
248
- top: 50%;
249
- left: 50%;
250
- width: 0;
251
- height: 0;
252
- background: rgba(255, 255, 255, 0.3);
253
- border-radius: 50%;
254
- transform: translate(-50%, -50%);
255
- transition: width 0.6s, height 0.6s;
256
- }
257
-
258
- .cyber-button:hover::before {
259
- width: 300px;
260
- height: 300px;
261
- }
262
-
263
- .cyber-button:hover {
264
- transform: translateY(-2px);
265
- box-shadow: 0 5px 30px rgba(0, 255, 65, 0.7);
266
- }
267
-
268
- /* Generate button special */
269
- .generate-button {
270
- font-size: 1.2em;
271
- animation: generate-pulse 2s ease-in-out infinite;
272
- }
273
-
274
- @keyframes generate-pulse {
275
- 0%, 100% { box-shadow: 0 0 20px rgba(0, 255, 65, 0.5); }
276
- 50% { box-shadow: 0 0 40px rgba(0, 255, 65, 0.8), 0 0 60px rgba(138, 43, 226, 0.5); }
277
- }
278
-
279
- /* Cyber inputs */
280
- .cyber-input input,
281
- .cyber-input textarea {
282
- background: rgba(0, 0, 0, 0.9) !important;
283
- border: 2px solid #00ff41 !important;
284
- color: #00ff41 !important;
285
- font-family: 'Orbitron', monospace !important;
286
- transition: all 0.3s ease;
287
- }
288
-
289
- .cyber-input input:focus,
290
- .cyber-input textarea:focus {
291
- border-color: #8A2BE2 !important;
292
- box-shadow: 0 0 20px rgba(138, 43, 226, 0.5) !important;
293
- outline: none !important;
294
- }
295
-
296
- /* Monster display */
297
- .monster-display {
298
- background: rgba(0, 0, 0, 0.9);
299
- border: 2px solid #00ff41;
300
- border-radius: 10px;
301
- padding: 20px;
302
- position: relative;
303
- overflow: hidden;
304
- }
305
-
306
- .monster-display::before {
307
- content: '';
308
- position: absolute;
309
- top: 0;
310
- left: -100%;
311
- width: 100%;
312
- height: 100%;
313
- background: linear-gradient(90deg, transparent, rgba(0, 255, 65, 0.2), transparent);
314
- animation: scan-line 3s linear infinite;
315
- }
316
-
317
- @keyframes scan-line {
318
- 0% { left: -100%; }
319
- 100% { left: 100%; }
320
- }
321
-
322
- /* Evolution display */
323
- .evolution-display {
324
- background: linear-gradient(135deg, rgba(138, 43, 226, 0.2), rgba(0, 255, 65, 0.2));
325
- border: 2px solid #8A2BE2;
326
- border-radius: 8px;
327
- padding: 15px;
328
- margin: 10px 0;
329
- animation: evolution-glow 2s ease-in-out infinite;
330
- }
331
-
332
- @keyframes evolution-glow {
333
- 0%, 100% { box-shadow: 0 0 20px rgba(138, 43, 226, 0.5); }
334
- 50% { box-shadow: 0 0 40px rgba(138, 43, 226, 0.8); }
335
- }
336
-
337
- /* Cyber dialogue */
338
- .cyber-dialogue {
339
- font-size: 1.5em;
340
- text-align: center;
341
- color: #00ff41;
342
- text-shadow: 0 0 10px currentColor;
343
- }
344
-
345
- /* Cyber stats */
346
- .cyber-stats {
347
- font-family: 'Orbitron', monospace;
348
- color: #00ff41;
349
- }
350
-
351
- .cyber-stats .label {
352
- color: #8A2BE2;
353
- }
354
-
355
- /* Tab styling */
356
- .cyber-tabs .tab-nav {
357
- background: rgba(0, 0, 0, 0.8);
358
- border-bottom: 2px solid #00ff41;
359
- }
360
-
361
- .cyber-tabs .tab-nav button {
362
- color: #00ff41 !important;
363
- background: transparent !important;
364
- border: none !important;
365
- transition: all 0.3s ease;
366
- }
367
-
368
- .cyber-tabs .tab-nav button:hover {
369
- background: rgba(0, 255, 65, 0.1) !important;
370
- text-shadow: 0 0 10px #00ff41;
371
- }
372
-
373
- .cyber-tabs .tab-nav button.selected {
374
- background: rgba(0, 255, 65, 0.2) !important;
375
- border-bottom: 3px solid #00ff41 !important;
376
- }
377
-
378
- /* Loading animation */
379
- .loading {
380
- display: inline-block;
381
- width: 20px;
382
- height: 20px;
383
- border: 3px solid rgba(0, 255, 65, 0.3);
384
- border-radius: 50%;
385
- border-top-color: #00ff41;
386
- animation: spin 1s ease-in-out infinite;
387
- }
388
-
389
- @keyframes spin {
390
- to { transform: rotate(360deg); }
391
- }
392
-
393
- /* Scrollbar styling */
394
- ::-webkit-scrollbar {
395
- width: 10px;
396
- height: 10px;
397
- }
398
-
399
- ::-webkit-scrollbar-track {
400
- background: rgba(0, 0, 0, 0.5);
401
- border: 1px solid #00ff41;
402
- }
403
-
404
- ::-webkit-scrollbar-thumb {
405
- background: linear-gradient(45deg, #00ff41, #8A2BE2);
406
- border-radius: 5px;
407
- }
408
-
409
- ::-webkit-scrollbar-thumb:hover {
410
- background: linear-gradient(45deg, #00ff41, #9932CC);
411
- }
412
-
413
- /* Mobile responsiveness */
414
- @media (max-width: 768px) {
415
- .glitch-text {
416
- font-size: 2em;
417
- }
418
-
419
- .cyber-container {
420
- padding: 15px;
421
- }
422
-
423
- .cyber-button {
424
- padding: 10px 20px;
425
- font-size: 0.9em;
426
- }
427
- }
428
- """