Skip to content

Commit e908370

Browse files
adrianweddclaude
andcommitted
🎨 FRONTEND REFACTOR: Modularize Evolution Observatory Dashboard
Broke down 745-line monolithic HTML file into modular components: **New Structure:** - evolution-observatory.html (94 lines): Clean semantic HTML structure - css/evolution-observatory.css (281 lines): Separated styling concerns - js/evolution-observatory.js (397 lines): Modular JavaScript functionality **Improvements:** - **Separation of Concerns**: HTML/CSS/JS properly separated - **Enhanced Accessibility**: Added ARIA labels and semantic elements - **Better Caching**: CSS and JS can be cached independently - **Improved Maintainability**: Easier to modify individual components - **Code Organization**: Clear structure for future enhancements - **Performance**: Faster loading with modular assets **Technical Enhancements:** - Semantic HTML5 elements (header, main, section, aside) - ARIA live regions for dynamic content updates - Improved error handling in WebSocket connections - Better responsive design patterns - Enhanced chart rendering with accessibility **Backward Compatibility:** - Preserved all existing functionality - Same API endpoints and WebSocket integration - Identical visual appearance and user experience - Original file backed up as evolution-observatory-monolithic.html.backup Resolves GitHub Issue #41 - Frontend separation of concerns 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 5fb29b2 commit e908370

4 files changed

Lines changed: 1485 additions & 710 deletions

File tree

Lines changed: 282 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,282 @@
1+
/* Evolution Observatory Styles */
2+
* {
3+
margin: 0;
4+
padding: 0;
5+
box-sizing: border-box;
6+
}
7+
8+
body {
9+
font-family: 'SF Pro Display', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
10+
background: linear-gradient(135deg, #0a0f1c 0%, #1a1f2e 50%, #2a2f3e 100%);
11+
color: #ffffff;
12+
min-height: 100vh;
13+
overflow-x: hidden;
14+
}
15+
16+
.header {
17+
background: rgba(255, 255, 255, 0.1);
18+
backdrop-filter: blur(20px);
19+
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
20+
padding: 1rem 2rem;
21+
display: flex;
22+
justify-content: space-between;
23+
align-items: center;
24+
}
25+
26+
.header h1 {
27+
font-size: 2rem;
28+
font-weight: 700;
29+
background: linear-gradient(45deg, #667eea, #764ba2, #f093fb);
30+
-webkit-background-clip: text;
31+
-webkit-text-fill-color: transparent;
32+
background-clip: text;
33+
}
34+
35+
.status-indicator {
36+
display: flex;
37+
align-items: center;
38+
gap: 0.5rem;
39+
padding: 0.5rem 1rem;
40+
background: rgba(0, 255, 0, 0.1);
41+
border-radius: 20px;
42+
border: 1px solid rgba(0, 255, 0, 0.3);
43+
}
44+
45+
.status-dot {
46+
width: 8px;
47+
height: 8px;
48+
background: #00ff00;
49+
border-radius: 50%;
50+
animation: pulse 2s infinite;
51+
}
52+
53+
@keyframes pulse {
54+
0%, 100% { opacity: 1; }
55+
50% { opacity: 0.3; }
56+
}
57+
58+
.main-container {
59+
display: grid;
60+
grid-template-columns: 1fr 1fr;
61+
grid-template-rows: auto auto auto;
62+
gap: 2rem;
63+
padding: 2rem;
64+
height: calc(100vh - 100px);
65+
}
66+
67+
.panel {
68+
background: rgba(255, 255, 255, 0.05);
69+
backdrop-filter: blur(20px);
70+
border-radius: 20px;
71+
border: 1px solid rgba(255, 255, 255, 0.1);
72+
padding: 2rem;
73+
position: relative;
74+
overflow: hidden;
75+
}
76+
77+
.panel::before {
78+
content: '';
79+
position: absolute;
80+
top: 0;
81+
left: 0;
82+
right: 0;
83+
height: 1px;
84+
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
85+
}
86+
87+
.panel h2 {
88+
font-size: 1.5rem;
89+
font-weight: 600;
90+
margin-bottom: 1.5rem;
91+
display: flex;
92+
align-items: center;
93+
gap: 0.5rem;
94+
}
95+
96+
.evolution-graph {
97+
grid-column: 1 / -1;
98+
height: 300px;
99+
}
100+
101+
.species-panel {
102+
min-height: 250px;
103+
}
104+
105+
.metrics-panel {
106+
min-height: 250px;
107+
}
108+
109+
.strategy-list {
110+
max-height: 300px;
111+
overflow-y: auto;
112+
}
113+
114+
.strategy-item {
115+
display: flex;
116+
justify-content: space-between;
117+
align-items: center;
118+
padding: 1rem;
119+
margin: 0.5rem 0;
120+
background: rgba(255, 255, 255, 0.05);
121+
border-radius: 10px;
122+
border-left: 4px solid;
123+
transition: all 0.3s ease;
124+
}
125+
126+
.strategy-item:hover {
127+
transform: translateX(5px);
128+
background: rgba(255, 255, 255, 0.1);
129+
}
130+
131+
.strategy-high { border-left-color: #00ff88; }
132+
.strategy-medium { border-left-color: #ffaa00; }
133+
.strategy-low { border-left-color: #ff4444; }
134+
135+
.fitness-bar {
136+
width: 100px;
137+
height: 6px;
138+
background: rgba(255, 255, 255, 0.1);
139+
border-radius: 3px;
140+
overflow: hidden;
141+
}
142+
143+
.fitness-fill {
144+
height: 100%;
145+
background: linear-gradient(90deg, #ff4444, #ffaa00, #00ff88);
146+
border-radius: 3px;
147+
transition: width 0.5s ease;
148+
}
149+
150+
.metric-grid {
151+
display: grid;
152+
grid-template-columns: 1fr 1fr;
153+
gap: 1rem;
154+
}
155+
156+
.metric-card {
157+
background: rgba(255, 255, 255, 0.05);
158+
padding: 1rem;
159+
border-radius: 10px;
160+
text-align: center;
161+
}
162+
163+
.metric-value {
164+
font-size: 2rem;
165+
font-weight: 700;
166+
color: #667eea;
167+
display: block;
168+
}
169+
170+
.metric-label {
171+
font-size: 0.9rem;
172+
color: rgba(255, 255, 255, 0.7);
173+
}
174+
175+
.species-item {
176+
display: flex;
177+
justify-content: space-between;
178+
align-items: center;
179+
padding: 1rem;
180+
margin: 0.5rem 0;
181+
background: rgba(255, 255, 255, 0.05);
182+
border-radius: 10px;
183+
border: 1px solid rgba(255, 255, 255, 0.1);
184+
}
185+
186+
.species-name {
187+
font-weight: 600;
188+
}
189+
190+
.species-stats {
191+
display: flex;
192+
gap: 1rem;
193+
font-size: 0.9rem;
194+
color: rgba(255, 255, 255, 0.7);
195+
}
196+
197+
.evolution-controls {
198+
position: fixed;
199+
bottom: 2rem;
200+
right: 2rem;
201+
display: flex;
202+
gap: 1rem;
203+
}
204+
205+
.control-btn {
206+
padding: 1rem 2rem;
207+
background: rgba(103, 126, 234, 0.2);
208+
border: 1px solid #667eea;
209+
color: white;
210+
border-radius: 15px;
211+
cursor: pointer;
212+
font-size: 1rem;
213+
font-weight: 600;
214+
transition: all 0.3s ease;
215+
}
216+
217+
.control-btn:hover {
218+
background: rgba(103, 126, 234, 0.4);
219+
transform: translateY(-2px);
220+
}
221+
222+
.chart-container {
223+
height: 200px;
224+
position: relative;
225+
margin-top: 1rem;
226+
}
227+
228+
.dna-strand {
229+
position: absolute;
230+
top: 10px;
231+
right: 10px;
232+
font-size: 2rem;
233+
opacity: 0.3;
234+
animation: rotate 10s infinite linear;
235+
}
236+
237+
@keyframes rotate {
238+
from { transform: rotate(0deg); }
239+
to { transform: rotate(360deg); }
240+
}
241+
242+
.emergence-indicator {
243+
position: absolute;
244+
top: 1rem;
245+
right: 1rem;
246+
padding: 0.5rem 1rem;
247+
background: rgba(255, 0, 255, 0.1);
248+
border: 1px solid rgba(255, 0, 255, 0.3);
249+
border-radius: 20px;
250+
font-size: 0.8rem;
251+
color: #ff00ff;
252+
animation: glow 2s infinite alternate;
253+
}
254+
255+
@keyframes glow {
256+
from { box-shadow: 0 0 5px rgba(255, 0, 255, 0.3); }
257+
to { box-shadow: 0 0 20px rgba(255, 0, 255, 0.6); }
258+
}
259+
260+
.loading {
261+
display: flex;
262+
justify-content: center;
263+
align-items: center;
264+
height: 100px;
265+
font-size: 1.1rem;
266+
color: rgba(255, 255, 255, 0.7);
267+
}
268+
269+
.spinner {
270+
width: 20px;
271+
height: 20px;
272+
border: 2px solid rgba(255, 255, 255, 0.1);
273+
border-top: 2px solid #667eea;
274+
border-radius: 50%;
275+
animation: spin 1s linear infinite;
276+
margin-right: 0.5rem;
277+
}
278+
279+
@keyframes spin {
280+
0% { transform: rotate(0deg); }
281+
100% { transform: rotate(360deg); }
282+
}

0 commit comments

Comments
 (0)