jev-chess 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +148 -0
- package/README.md +109 -0
- package/dist/chessEngine.d.ts +36 -0
- package/dist/chessEngine.d.ts.map +1 -0
- package/dist/chessEngine.js +173 -0
- package/dist/chessEngine.js.map +1 -0
- package/dist/classicMatches.d.ts +50 -0
- package/dist/classicMatches.d.ts.map +1 -0
- package/dist/classicMatches.js +223 -0
- package/dist/classicMatches.js.map +1 -0
- package/dist/demo.d.ts +2 -0
- package/dist/demo.d.ts.map +1 -0
- package/dist/demo.js +142 -0
- package/dist/demo.js.map +1 -0
- package/dist/gameReviewer.d.ts +11 -0
- package/dist/gameReviewer.d.ts.map +1 -0
- package/dist/gameReviewer.js +89 -0
- package/dist/gameReviewer.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/moveEvaluator.d.ts +11 -0
- package/dist/moveEvaluator.d.ts.map +1 -0
- package/dist/moveEvaluator.js +103 -0
- package/dist/moveEvaluator.js.map +1 -0
- package/dist/moveResolver.d.ts +15 -0
- package/dist/moveResolver.d.ts.map +1 -0
- package/dist/moveResolver.js +97 -0
- package/dist/moveResolver.js.map +1 -0
- package/dist/personaEngine.d.ts +15 -0
- package/dist/personaEngine.d.ts.map +1 -0
- package/dist/personaEngine.js +151 -0
- package/dist/personaEngine.js.map +1 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +1490 -0
- package/dist/server.js.map +1 -0
- package/dist/typeSafeClient.d.ts +13 -0
- package/dist/typeSafeClient.d.ts.map +1 -0
- package/dist/typeSafeClient.js +336 -0
- package/dist/typeSafeClient.js.map +1 -0
- package/dist/types.d.ts +100 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/web/main.d.ts +2 -0
- package/dist/web/main.d.ts.map +1 -0
- package/dist/web/main.js +620 -0
- package/dist/web/main.js.map +1 -0
- package/package.json +35 -0
- package/public/app.js +45 -0
- package/public/index.html +790 -0
- package/src/chessEngine.ts +191 -0
- package/src/classicMatches.ts +291 -0
- package/src/demo.ts +160 -0
- package/src/gameReviewer.ts +113 -0
- package/src/index.ts +8 -0
- package/src/moveEvaluator.ts +122 -0
- package/src/moveResolver.ts +120 -0
- package/src/personaEngine.ts +193 -0
- package/src/server.ts +1509 -0
- package/src/typeSafeClient.ts +321 -0
- package/src/types.ts +118 -0
- package/src/web/main.ts +615 -0
- package/tests/chess.test.ts +206 -0
- package/tsconfig.json +21 -0
|
@@ -0,0 +1,790 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Jev Chess — TypeSafe AI System One Studio</title>
|
|
7
|
+
<meta name="description" content="Chess studio powered by TypeSafe System One AI: natural language moves, parallel evaluation, persona opponents, and classic match replay.">
|
|
8
|
+
<meta name="theme-color" content="#0d1117">
|
|
9
|
+
<link rel="canonical" href="https://h3manth.com/fun/jev-chess/">
|
|
10
|
+
|
|
11
|
+
<!-- Open Graph -->
|
|
12
|
+
<meta property="og:title" content="Jev Chess — TypeSafe AI System One Studio">
|
|
13
|
+
<meta property="og:description" content="Chess studio powered by TypeSafe System One AI: natural language moves, parallel evaluation, persona opponents, and classic match replay.">
|
|
14
|
+
<meta property="og:url" content="https://h3manth.com/fun/jev-chess/">
|
|
15
|
+
<meta property="og:type" content="website">
|
|
16
|
+
|
|
17
|
+
<style>
|
|
18
|
+
:root {
|
|
19
|
+
--bg: #0d1117;
|
|
20
|
+
--card-bg: #161b22;
|
|
21
|
+
--card-border: #30363d;
|
|
22
|
+
--text: #c9d1d9;
|
|
23
|
+
--text-bright: #f0f6fc;
|
|
24
|
+
--accent: #58a6ff;
|
|
25
|
+
--accent-hover: #79c0ff;
|
|
26
|
+
--success: #3fb950;
|
|
27
|
+
--warning: #d29922;
|
|
28
|
+
--danger: #f85149;
|
|
29
|
+
--board-light: #f0d9b5;
|
|
30
|
+
--board-dark: #b58863;
|
|
31
|
+
--sq-highlight: rgba(255, 255, 0, 0.45);
|
|
32
|
+
--sq-selected: rgba(88, 166, 255, 0.6);
|
|
33
|
+
--sq-target: rgba(63, 185, 80, 0.5);
|
|
34
|
+
}
|
|
35
|
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
36
|
+
body {
|
|
37
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
38
|
+
background: var(--bg);
|
|
39
|
+
color: var(--text);
|
|
40
|
+
min-height: 100vh;
|
|
41
|
+
display: flex;
|
|
42
|
+
flex-direction: column;
|
|
43
|
+
}
|
|
44
|
+
header {
|
|
45
|
+
background: var(--card-bg);
|
|
46
|
+
border-bottom: 1px solid var(--card-border);
|
|
47
|
+
padding: 12px 24px;
|
|
48
|
+
display: flex;
|
|
49
|
+
align-items: center;
|
|
50
|
+
justify-content: space-between;
|
|
51
|
+
}
|
|
52
|
+
.brand {
|
|
53
|
+
display: flex;
|
|
54
|
+
align-items: center;
|
|
55
|
+
gap: 12px;
|
|
56
|
+
}
|
|
57
|
+
.brand h1 {
|
|
58
|
+
font-size: 1.15rem;
|
|
59
|
+
font-weight: 700;
|
|
60
|
+
color: var(--text-bright);
|
|
61
|
+
letter-spacing: -0.02em;
|
|
62
|
+
}
|
|
63
|
+
.status-dot {
|
|
64
|
+
width: 8px;
|
|
65
|
+
height: 8px;
|
|
66
|
+
border-radius: 50%;
|
|
67
|
+
display: inline-block;
|
|
68
|
+
flex-shrink: 0;
|
|
69
|
+
}
|
|
70
|
+
.status-dot.live {
|
|
71
|
+
background: var(--success);
|
|
72
|
+
box-shadow: 0 0 8px rgba(63, 185, 80, 0.7);
|
|
73
|
+
}
|
|
74
|
+
.status-dot.sim {
|
|
75
|
+
background: var(--warning);
|
|
76
|
+
box-shadow: 0 0 6px rgba(210, 153, 34, 0.5);
|
|
77
|
+
}
|
|
78
|
+
.badge-status {
|
|
79
|
+
display: inline-flex;
|
|
80
|
+
align-items: center;
|
|
81
|
+
gap: 7px;
|
|
82
|
+
font-size: 0.75rem;
|
|
83
|
+
padding: 4px 10px;
|
|
84
|
+
border-radius: 999px;
|
|
85
|
+
background: rgba(63, 185, 80, 0.12);
|
|
86
|
+
color: var(--success);
|
|
87
|
+
border: 1px solid rgba(63, 185, 80, 0.3);
|
|
88
|
+
font-weight: 600;
|
|
89
|
+
cursor: pointer;
|
|
90
|
+
user-select: none;
|
|
91
|
+
}
|
|
92
|
+
.badge-sim {
|
|
93
|
+
background: rgba(210, 153, 34, 0.12);
|
|
94
|
+
color: var(--warning);
|
|
95
|
+
border-color: rgba(210, 153, 34, 0.3);
|
|
96
|
+
}
|
|
97
|
+
main {
|
|
98
|
+
flex: 1;
|
|
99
|
+
max-width: 1400px;
|
|
100
|
+
width: 100%;
|
|
101
|
+
margin: 0 auto;
|
|
102
|
+
padding: 24px;
|
|
103
|
+
display: grid;
|
|
104
|
+
grid-template-columns: 500px 1fr;
|
|
105
|
+
gap: 28px;
|
|
106
|
+
}
|
|
107
|
+
@media (max-width: 1080px) {
|
|
108
|
+
main { grid-template-columns: 1fr; }
|
|
109
|
+
}
|
|
110
|
+
/* Chessboard Container */
|
|
111
|
+
.board-card {
|
|
112
|
+
background: var(--card-bg);
|
|
113
|
+
border: 1px solid var(--card-border);
|
|
114
|
+
border-radius: 12px;
|
|
115
|
+
padding: 20px;
|
|
116
|
+
display: flex;
|
|
117
|
+
flex-direction: column;
|
|
118
|
+
align-items: center;
|
|
119
|
+
gap: 16px;
|
|
120
|
+
height: fit-content;
|
|
121
|
+
}
|
|
122
|
+
.board-header {
|
|
123
|
+
width: 100%;
|
|
124
|
+
display: flex;
|
|
125
|
+
justify-content: space-between;
|
|
126
|
+
align-items: center;
|
|
127
|
+
font-size: 0.9rem;
|
|
128
|
+
}
|
|
129
|
+
.turn-indicator {
|
|
130
|
+
font-weight: 600;
|
|
131
|
+
color: var(--text-bright);
|
|
132
|
+
display: flex;
|
|
133
|
+
align-items: center;
|
|
134
|
+
gap: 8px;
|
|
135
|
+
}
|
|
136
|
+
.turn-dot {
|
|
137
|
+
width: 12px;
|
|
138
|
+
height: 12px;
|
|
139
|
+
border-radius: 50%;
|
|
140
|
+
border: 1px solid #666;
|
|
141
|
+
}
|
|
142
|
+
.turn-dot.white { background: #fff; }
|
|
143
|
+
.turn-dot.black { background: #111; }
|
|
144
|
+
#board {
|
|
145
|
+
width: 460px;
|
|
146
|
+
height: 460px;
|
|
147
|
+
display: grid;
|
|
148
|
+
grid-template-columns: repeat(8, 1fr);
|
|
149
|
+
grid-template-rows: repeat(8, 1fr);
|
|
150
|
+
border: 2px solid #444;
|
|
151
|
+
border-radius: 4px;
|
|
152
|
+
overflow: hidden;
|
|
153
|
+
user-select: none;
|
|
154
|
+
box-shadow: 0 8px 24px rgba(0,0,0,0.5);
|
|
155
|
+
}
|
|
156
|
+
.square {
|
|
157
|
+
position: relative;
|
|
158
|
+
display: flex;
|
|
159
|
+
align-items: center;
|
|
160
|
+
justify-content: center;
|
|
161
|
+
font-size: 36px;
|
|
162
|
+
cursor: pointer;
|
|
163
|
+
transition: background 0.1s;
|
|
164
|
+
}
|
|
165
|
+
.square.light { background: var(--board-light); color: #222; }
|
|
166
|
+
.square.dark { background: var(--board-dark); color: #111; }
|
|
167
|
+
.square.selected { background: var(--sq-selected) !important; }
|
|
168
|
+
.square.target::after {
|
|
169
|
+
content: "";
|
|
170
|
+
width: 14px;
|
|
171
|
+
height: 14px;
|
|
172
|
+
border-radius: 50%;
|
|
173
|
+
background: var(--sq-target);
|
|
174
|
+
pointer-events: none;
|
|
175
|
+
}
|
|
176
|
+
.square.last-from, .square.last-to { background: var(--sq-highlight) !important; }
|
|
177
|
+
.coord-label {
|
|
178
|
+
position: absolute;
|
|
179
|
+
font-size: 10px;
|
|
180
|
+
font-weight: 700;
|
|
181
|
+
pointer-events: none;
|
|
182
|
+
opacity: 0.6;
|
|
183
|
+
}
|
|
184
|
+
.coord-rank { top: 2px; left: 3px; }
|
|
185
|
+
.coord-file { bottom: 2px; right: 3px; }
|
|
186
|
+
.board-actions {
|
|
187
|
+
display: flex;
|
|
188
|
+
gap: 8px;
|
|
189
|
+
width: 100%;
|
|
190
|
+
}
|
|
191
|
+
.btn {
|
|
192
|
+
flex: 1;
|
|
193
|
+
background: #21262d;
|
|
194
|
+
border: 1px solid var(--card-border);
|
|
195
|
+
color: var(--text-bright);
|
|
196
|
+
padding: 8px 14px;
|
|
197
|
+
border-radius: 6px;
|
|
198
|
+
font-size: 0.85rem;
|
|
199
|
+
font-weight: 600;
|
|
200
|
+
cursor: pointer;
|
|
201
|
+
transition: all 0.15s;
|
|
202
|
+
display: flex;
|
|
203
|
+
align-items: center;
|
|
204
|
+
justify-content: center;
|
|
205
|
+
gap: 6px;
|
|
206
|
+
}
|
|
207
|
+
.btn:hover { background: #30363d; border-color: #8b949e; }
|
|
208
|
+
.btn-primary {
|
|
209
|
+
background: #238636;
|
|
210
|
+
border-color: rgba(240, 246, 252, 0.1);
|
|
211
|
+
}
|
|
212
|
+
.btn-primary:hover { background: #2ea043; }
|
|
213
|
+
.btn-accent {
|
|
214
|
+
background: #1f6feb;
|
|
215
|
+
border-color: rgba(240, 246, 252, 0.1);
|
|
216
|
+
}
|
|
217
|
+
.btn-accent:hover { background: #388bfd; }
|
|
218
|
+
|
|
219
|
+
/* Studio Panels */
|
|
220
|
+
.studio {
|
|
221
|
+
display: flex;
|
|
222
|
+
flex-direction: column;
|
|
223
|
+
gap: 20px;
|
|
224
|
+
}
|
|
225
|
+
.panel {
|
|
226
|
+
background: var(--card-bg);
|
|
227
|
+
border: 1px solid var(--card-border);
|
|
228
|
+
border-radius: 12px;
|
|
229
|
+
padding: 18px 20px;
|
|
230
|
+
}
|
|
231
|
+
.panel-title {
|
|
232
|
+
font-size: 0.95rem;
|
|
233
|
+
font-weight: 700;
|
|
234
|
+
color: var(--text-bright);
|
|
235
|
+
margin-bottom: 12px;
|
|
236
|
+
display: flex;
|
|
237
|
+
align-items: center;
|
|
238
|
+
justify-content: space-between;
|
|
239
|
+
}
|
|
240
|
+
.panel-subtitle {
|
|
241
|
+
font-size: 0.8rem;
|
|
242
|
+
color: #8b949e;
|
|
243
|
+
font-weight: normal;
|
|
244
|
+
}
|
|
245
|
+
/* Natural Language Input */
|
|
246
|
+
.nl-input-row {
|
|
247
|
+
display: flex;
|
|
248
|
+
gap: 8px;
|
|
249
|
+
margin-bottom: 10px;
|
|
250
|
+
}
|
|
251
|
+
.nl-input {
|
|
252
|
+
flex: 1;
|
|
253
|
+
background: #0d1117;
|
|
254
|
+
border: 1px solid var(--card-border);
|
|
255
|
+
color: var(--text-bright);
|
|
256
|
+
padding: 10px 14px;
|
|
257
|
+
border-radius: 6px;
|
|
258
|
+
font-size: 0.9rem;
|
|
259
|
+
outline: none;
|
|
260
|
+
}
|
|
261
|
+
.nl-input:focus { border-color: var(--accent); }
|
|
262
|
+
.quick-chips {
|
|
263
|
+
display: flex;
|
|
264
|
+
flex-wrap: wrap;
|
|
265
|
+
gap: 6px;
|
|
266
|
+
margin-bottom: 12px;
|
|
267
|
+
}
|
|
268
|
+
.chip {
|
|
269
|
+
background: #21262d;
|
|
270
|
+
border: 1px solid var(--card-border);
|
|
271
|
+
color: #8b949e;
|
|
272
|
+
font-size: 0.75rem;
|
|
273
|
+
padding: 4px 10px;
|
|
274
|
+
border-radius: 16px;
|
|
275
|
+
cursor: pointer;
|
|
276
|
+
transition: all 0.15s;
|
|
277
|
+
}
|
|
278
|
+
.chip:hover { color: var(--text-bright); border-color: var(--accent); }
|
|
279
|
+
.resolution-banner {
|
|
280
|
+
background: #0d1117;
|
|
281
|
+
border: 1px solid var(--card-border);
|
|
282
|
+
border-radius: 6px;
|
|
283
|
+
padding: 10px 14px;
|
|
284
|
+
font-size: 0.85rem;
|
|
285
|
+
display: flex;
|
|
286
|
+
justify-content: space-between;
|
|
287
|
+
align-items: center;
|
|
288
|
+
}
|
|
289
|
+
/* Intelligence Metrics Grid */
|
|
290
|
+
.metrics-grid {
|
|
291
|
+
display: grid;
|
|
292
|
+
grid-template-columns: repeat(2, 1fr);
|
|
293
|
+
gap: 12px;
|
|
294
|
+
}
|
|
295
|
+
.metric-card {
|
|
296
|
+
background: #0d1117;
|
|
297
|
+
border: 1px solid var(--card-border);
|
|
298
|
+
border-radius: 8px;
|
|
299
|
+
padding: 12px;
|
|
300
|
+
display: flex;
|
|
301
|
+
flex-direction: column;
|
|
302
|
+
gap: 6px;
|
|
303
|
+
}
|
|
304
|
+
.metric-name {
|
|
305
|
+
font-size: 0.75rem;
|
|
306
|
+
color: #8b949e;
|
|
307
|
+
text-transform: uppercase;
|
|
308
|
+
letter-spacing: 0.05em;
|
|
309
|
+
font-weight: 600;
|
|
310
|
+
}
|
|
311
|
+
.metric-value {
|
|
312
|
+
font-size: 1.15rem;
|
|
313
|
+
font-weight: 700;
|
|
314
|
+
color: var(--text-bright);
|
|
315
|
+
display: flex;
|
|
316
|
+
align-items: baseline;
|
|
317
|
+
gap: 6px;
|
|
318
|
+
}
|
|
319
|
+
.metric-sub {
|
|
320
|
+
font-size: 0.75rem;
|
|
321
|
+
color: #8b949e;
|
|
322
|
+
font-weight: normal;
|
|
323
|
+
}
|
|
324
|
+
.progress-bar {
|
|
325
|
+
height: 6px;
|
|
326
|
+
background: #21262d;
|
|
327
|
+
border-radius: 3px;
|
|
328
|
+
overflow: hidden;
|
|
329
|
+
margin-top: 4px;
|
|
330
|
+
}
|
|
331
|
+
.progress-fill {
|
|
332
|
+
height: 100%;
|
|
333
|
+
background: var(--accent);
|
|
334
|
+
width: 0%;
|
|
335
|
+
transition: width 0.3s;
|
|
336
|
+
}
|
|
337
|
+
/* Persona Selector */
|
|
338
|
+
.persona-select-grid {
|
|
339
|
+
display: grid;
|
|
340
|
+
grid-template-columns: repeat(4, 1fr);
|
|
341
|
+
gap: 8px;
|
|
342
|
+
margin-bottom: 12px;
|
|
343
|
+
}
|
|
344
|
+
.persona-card {
|
|
345
|
+
background: #0d1117;
|
|
346
|
+
border: 1px solid var(--card-border);
|
|
347
|
+
border-radius: 8px;
|
|
348
|
+
padding: 10px;
|
|
349
|
+
cursor: pointer;
|
|
350
|
+
text-align: center;
|
|
351
|
+
transition: all 0.15s;
|
|
352
|
+
}
|
|
353
|
+
.persona-card:hover { border-color: #8b949e; }
|
|
354
|
+
.persona-card.active {
|
|
355
|
+
border-color: var(--accent);
|
|
356
|
+
background: rgba(88, 166, 255, 0.08);
|
|
357
|
+
}
|
|
358
|
+
.persona-name { font-size: 0.85rem; font-weight: 700; color: var(--text-bright); }
|
|
359
|
+
.persona-title { font-size: 0.7rem; color: #8b949e; margin-top: 2px; }
|
|
360
|
+
.persona-breakdown {
|
|
361
|
+
background: #0d1117;
|
|
362
|
+
border: 1px solid var(--card-border);
|
|
363
|
+
border-radius: 6px;
|
|
364
|
+
padding: 10px 14px;
|
|
365
|
+
font-size: 0.8rem;
|
|
366
|
+
color: var(--text);
|
|
367
|
+
line-height: 1.5;
|
|
368
|
+
}
|
|
369
|
+
.history-list {
|
|
370
|
+
max-height: 110px;
|
|
371
|
+
overflow-y: auto;
|
|
372
|
+
font-family: ui-monospace, monospace;
|
|
373
|
+
font-size: 0.85rem;
|
|
374
|
+
color: #8b949e;
|
|
375
|
+
display: flex;
|
|
376
|
+
flex-wrap: wrap;
|
|
377
|
+
gap: 8px;
|
|
378
|
+
padding-top: 6px;
|
|
379
|
+
}
|
|
380
|
+
.history-item { color: var(--text-bright); }
|
|
381
|
+
|
|
382
|
+
/* Classic Matches Styles */
|
|
383
|
+
.match-select {
|
|
384
|
+
width: 100%;
|
|
385
|
+
background: #0d1117;
|
|
386
|
+
border: 1px solid var(--card-border);
|
|
387
|
+
color: var(--text-bright);
|
|
388
|
+
padding: 9px 12px;
|
|
389
|
+
border-radius: 6px;
|
|
390
|
+
font-size: 0.85rem;
|
|
391
|
+
outline: none;
|
|
392
|
+
cursor: pointer;
|
|
393
|
+
}
|
|
394
|
+
.match-select:focus { border-color: var(--accent); }
|
|
395
|
+
.match-meta-box {
|
|
396
|
+
background: #0d1117;
|
|
397
|
+
border: 1px solid var(--card-border);
|
|
398
|
+
border-radius: 8px;
|
|
399
|
+
padding: 12px 14px;
|
|
400
|
+
margin-top: 10px;
|
|
401
|
+
font-size: 0.82rem;
|
|
402
|
+
line-height: 1.5;
|
|
403
|
+
}
|
|
404
|
+
.match-meta-header {
|
|
405
|
+
display: flex;
|
|
406
|
+
justify-content: space-between;
|
|
407
|
+
align-items: baseline;
|
|
408
|
+
margin-bottom: 4px;
|
|
409
|
+
}
|
|
410
|
+
.match-players {
|
|
411
|
+
font-weight: 700;
|
|
412
|
+
color: var(--text-bright);
|
|
413
|
+
font-size: 0.9rem;
|
|
414
|
+
}
|
|
415
|
+
.match-tags {
|
|
416
|
+
display: flex;
|
|
417
|
+
gap: 6px;
|
|
418
|
+
margin-top: 6px;
|
|
419
|
+
flex-wrap: wrap;
|
|
420
|
+
}
|
|
421
|
+
.match-tag {
|
|
422
|
+
font-size: 0.7rem;
|
|
423
|
+
padding: 2px 7px;
|
|
424
|
+
border-radius: 4px;
|
|
425
|
+
background: #21262d;
|
|
426
|
+
color: #8b949e;
|
|
427
|
+
}
|
|
428
|
+
.match-tag.result {
|
|
429
|
+
color: var(--accent);
|
|
430
|
+
background: rgba(88, 166, 255, 0.1);
|
|
431
|
+
}
|
|
432
|
+
.replay-bar {
|
|
433
|
+
display: flex;
|
|
434
|
+
align-items: center;
|
|
435
|
+
gap: 8px;
|
|
436
|
+
margin-top: 12px;
|
|
437
|
+
}
|
|
438
|
+
.replay-btn {
|
|
439
|
+
background: #21262d;
|
|
440
|
+
border: 1px solid var(--card-border);
|
|
441
|
+
color: var(--text-bright);
|
|
442
|
+
padding: 7px 12px;
|
|
443
|
+
border-radius: 6px;
|
|
444
|
+
font-size: 0.8rem;
|
|
445
|
+
font-weight: 600;
|
|
446
|
+
cursor: pointer;
|
|
447
|
+
transition: all 0.15s;
|
|
448
|
+
}
|
|
449
|
+
.replay-btn:hover { background: #30363d; border-color: #8b949e; }
|
|
450
|
+
.replay-progress-wrap {
|
|
451
|
+
flex: 1;
|
|
452
|
+
display: flex;
|
|
453
|
+
flex-direction: column;
|
|
454
|
+
gap: 4px;
|
|
455
|
+
}
|
|
456
|
+
.replay-progress-text {
|
|
457
|
+
display: flex;
|
|
458
|
+
justify-content: space-between;
|
|
459
|
+
font-size: 0.75rem;
|
|
460
|
+
color: #8b949e;
|
|
461
|
+
font-family: ui-monospace, monospace;
|
|
462
|
+
}
|
|
463
|
+
.classification-panel {
|
|
464
|
+
background: #0d1117;
|
|
465
|
+
border: 1px solid var(--card-border);
|
|
466
|
+
border-radius: 8px;
|
|
467
|
+
padding: 14px;
|
|
468
|
+
margin-top: 12px;
|
|
469
|
+
display: flex;
|
|
470
|
+
flex-direction: column;
|
|
471
|
+
gap: 12px;
|
|
472
|
+
}
|
|
473
|
+
.archetype-banner {
|
|
474
|
+
display: inline-flex;
|
|
475
|
+
align-items: center;
|
|
476
|
+
gap: 6px;
|
|
477
|
+
padding: 4px 10px;
|
|
478
|
+
border-radius: 999px;
|
|
479
|
+
background: rgba(88, 166, 255, 0.12);
|
|
480
|
+
border: 1px solid rgba(88, 166, 255, 0.3);
|
|
481
|
+
color: var(--accent);
|
|
482
|
+
font-size: 0.75rem;
|
|
483
|
+
font-weight: 700;
|
|
484
|
+
letter-spacing: 0.05em;
|
|
485
|
+
align-self: flex-start;
|
|
486
|
+
}
|
|
487
|
+
.class-grid {
|
|
488
|
+
display: grid;
|
|
489
|
+
grid-template-columns: repeat(3, 1fr);
|
|
490
|
+
gap: 8px;
|
|
491
|
+
}
|
|
492
|
+
.class-stat {
|
|
493
|
+
background: #161b22;
|
|
494
|
+
border: 1px solid var(--card-border);
|
|
495
|
+
border-radius: 6px;
|
|
496
|
+
padding: 8px 10px;
|
|
497
|
+
display: flex;
|
|
498
|
+
flex-direction: column;
|
|
499
|
+
gap: 4px;
|
|
500
|
+
}
|
|
501
|
+
.class-stat-name { font-size: 0.7rem; color: #8b949e; text-transform: uppercase; font-weight: 600; }
|
|
502
|
+
.class-stat-val { font-size: 0.95rem; font-weight: 700; color: var(--text-bright); }
|
|
503
|
+
.class-stat-desc { font-size: 0.72rem; color: #8b949e; }
|
|
504
|
+
.breakdown-row {
|
|
505
|
+
display: flex;
|
|
506
|
+
gap: 6px;
|
|
507
|
+
font-size: 0.75rem;
|
|
508
|
+
flex-wrap: wrap;
|
|
509
|
+
}
|
|
510
|
+
.breakdown-pill {
|
|
511
|
+
background: #161b22;
|
|
512
|
+
border: 1px solid var(--card-border);
|
|
513
|
+
border-radius: 4px;
|
|
514
|
+
padding: 4px 8px;
|
|
515
|
+
color: var(--text);
|
|
516
|
+
}
|
|
517
|
+
</style>
|
|
518
|
+
</head>
|
|
519
|
+
<body>
|
|
520
|
+
<header>
|
|
521
|
+
<div class="brand">
|
|
522
|
+
<div>
|
|
523
|
+
<h1>Jev Chess Studio</h1>
|
|
524
|
+
<div style="font-size: 0.75rem; color: #8b949e;">TypeSafe AI System One Architecture</div>
|
|
525
|
+
</div>
|
|
526
|
+
</div>
|
|
527
|
+
<div style="display: flex; align-items: center; gap: 10px;">
|
|
528
|
+
<button class="btn" onclick="openKeyModal()" style="padding: 5px 12px; font-size: 0.8rem; background: #21262d; border: 1px solid var(--card-border);">
|
|
529
|
+
<span id="keyBtnLabel">API Key</span>
|
|
530
|
+
</button>
|
|
531
|
+
<div id="backendBadge" class="badge-status badge-sim" onclick="openKeyModal()" title="Click to manage TypeSafe API Key">
|
|
532
|
+
<span id="backendStatusDot" class="status-dot sim"></span>
|
|
533
|
+
<span id="backendStatusText">Simulation Mode (jev-latest calibrated)</span>
|
|
534
|
+
</div>
|
|
535
|
+
</div>
|
|
536
|
+
</header>
|
|
537
|
+
|
|
538
|
+
<!-- TypeSafe API Key Modal -->
|
|
539
|
+
<div id="keyModal" style="display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.75); backdrop-filter: blur(5px); z-index: 999; align-items: center; justify-content: center;">
|
|
540
|
+
<div style="background: #161b22; border: 1px solid #30363d; border-radius: 12px; width: 480px; max-width: 92vw; padding: 24px; box-shadow: 0 20px 48px rgba(0,0,0,0.7);">
|
|
541
|
+
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px;">
|
|
542
|
+
<h3 style="color: #f0f6fc; font-size: 1.15rem; font-weight: 700;">
|
|
543
|
+
TypeSafe API Configuration
|
|
544
|
+
</h3>
|
|
545
|
+
<button onclick="closeKeyModal()" style="background: none; border: none; color: #8b949e; font-size: 1.2rem; cursor: pointer; padding: 4px;">✕</button>
|
|
546
|
+
</div>
|
|
547
|
+
|
|
548
|
+
<p style="font-size: 0.85rem; color: #8b949e; margin-bottom: 16px; line-height: 1.45;">
|
|
549
|
+
Connect directly to TypeSafe's flagship System One model (<strong style="color: #f0f6fc;">jev-latest</strong>). When active, all natural language move parsing, evaluations, and AI personas run directly against TypeSafe's live inference endpoints.
|
|
550
|
+
</p>
|
|
551
|
+
|
|
552
|
+
<div style="margin-bottom: 14px;">
|
|
553
|
+
<label style="display: block; font-size: 0.8rem; font-weight: 600; color: #c9d1d9; margin-bottom: 6px;">
|
|
554
|
+
TypeSafe API Key
|
|
555
|
+
</label>
|
|
556
|
+
<div style="display: flex; gap: 6px;">
|
|
557
|
+
<input id="keyInput" type="password" placeholder="ts_..." style="flex: 1; background: #0d1117; border: 1px solid #30363d; border-radius: 6px; padding: 10px; color: #f0f6fc; font-family: ui-monospace, monospace; font-size: 0.9rem; outline: none;" onkeydown="if(event.key==='Enter') saveApiKey()" />
|
|
558
|
+
<button id="toggleVisibilityBtn" class="btn" onclick="toggleKeyVisibility()" style="flex: 0 0 60px; padding: 0;" title="Toggle Visibility">Show</button>
|
|
559
|
+
</div>
|
|
560
|
+
</div>
|
|
561
|
+
|
|
562
|
+
<div id="modalStatus" style="font-size: 0.82rem; margin-bottom: 16px; min-height: 20px;"></div>
|
|
563
|
+
|
|
564
|
+
<div style="display: flex; gap: 8px; flex-direction: column;">
|
|
565
|
+
<button class="btn btn-accent" onclick="saveApiKey()" style="padding: 10px; font-weight: 700;">
|
|
566
|
+
Connect to Live API (jev-latest)
|
|
567
|
+
</button>
|
|
568
|
+
<div style="display: flex; gap: 8px;">
|
|
569
|
+
<button class="btn" onclick="clearApiKey()" style="flex: 1;">
|
|
570
|
+
Revert to Simulation Mode
|
|
571
|
+
</button>
|
|
572
|
+
<button class="btn" onclick="closeKeyModal()" style="flex: 1;">
|
|
573
|
+
Cancel
|
|
574
|
+
</button>
|
|
575
|
+
</div>
|
|
576
|
+
</div>
|
|
577
|
+
|
|
578
|
+
<div style="margin-top: 16px; text-align: center; font-size: 0.75rem; color: #8b949e;">
|
|
579
|
+
Obtain an API key at <a href="https://console.typesafe.ai/" target="_blank" style="color: #58a6ff; text-decoration: underline;">console.typesafe.ai</a>
|
|
580
|
+
</div>
|
|
581
|
+
</div>
|
|
582
|
+
</div>
|
|
583
|
+
|
|
584
|
+
<main>
|
|
585
|
+
<!-- Left: Chessboard -->
|
|
586
|
+
<div class="board-card">
|
|
587
|
+
<div class="board-header">
|
|
588
|
+
<div class="turn-indicator">
|
|
589
|
+
<div id="turnDot" class="turn-dot white"></div>
|
|
590
|
+
<span id="turnLabel">White to move</span>
|
|
591
|
+
</div>
|
|
592
|
+
<div id="materialBalance" style="color: #8b949e; font-size: 0.8rem;">Material: Equal</div>
|
|
593
|
+
</div>
|
|
594
|
+
|
|
595
|
+
<div id="board"></div>
|
|
596
|
+
|
|
597
|
+
<div class="board-actions">
|
|
598
|
+
<button class="btn" onclick="resetGame()">Reset Game</button>
|
|
599
|
+
<button class="btn" onclick="undoMove()">Undo</button>
|
|
600
|
+
<button class="btn btn-primary" onclick="makePersonaMove()">Ask Opponent Move</button>
|
|
601
|
+
</div>
|
|
602
|
+
|
|
603
|
+
<div style="width: 100%;">
|
|
604
|
+
<div style="font-size: 0.75rem; color: #8b949e; margin-bottom: 4px; text-transform: uppercase; letter-spacing: 0.05em; font-weight: 600;">Move History</div>
|
|
605
|
+
<div id="historyList" class="history-list"></div>
|
|
606
|
+
</div>
|
|
607
|
+
</div>
|
|
608
|
+
|
|
609
|
+
<!-- Right: Studio Intelligence Panels -->
|
|
610
|
+
<div class="studio">
|
|
611
|
+
<!-- Natural Language Move Resolver -->
|
|
612
|
+
<div class="panel">
|
|
613
|
+
<div class="panel-title">
|
|
614
|
+
<span>Natural Language Move Intent</span>
|
|
615
|
+
<span class="panel-subtitle">Select Instead of Generate (Choice)</span>
|
|
616
|
+
</div>
|
|
617
|
+
<div class="nl-input-row">
|
|
618
|
+
<input id="nlInput" class="nl-input" type="text" placeholder="e.g. Develop knight towards center, Castle kingside..." onkeydown="if(event.key==='Enter') resolveAndPlayMove()" />
|
|
619
|
+
<button class="btn btn-accent" onclick="resolveAndPlayMove()">Resolve & Play</button>
|
|
620
|
+
</div>
|
|
621
|
+
<div class="quick-chips">
|
|
622
|
+
<div class="chip" onclick="setChip('Develop knight towards center and attack pawn')">Develop knight to f3</div>
|
|
623
|
+
<div class="chip" onclick="setChip('Push the queen pawn two squares forward')">Push d-pawn two squares</div>
|
|
624
|
+
<div class="chip" onclick="setChip('Castle to safety on the kingside')">Castle kingside</div>
|
|
625
|
+
<div class="chip" onclick="setChip('Attack with bishop on f7')">Sacrifice bishop on f7</div>
|
|
626
|
+
<div class="chip" onclick="setChip('Teleport rook across board')">Illegal Teleport (Test Fallback)</div>
|
|
627
|
+
</div>
|
|
628
|
+
<div id="resolutionResult" class="resolution-banner" style="display: none;">
|
|
629
|
+
<span id="resText">...</span>
|
|
630
|
+
<span id="resConf" style="font-weight: 700; color: var(--accent);"></span>
|
|
631
|
+
</div>
|
|
632
|
+
</div>
|
|
633
|
+
|
|
634
|
+
<!-- Live Move Intelligence -->
|
|
635
|
+
<div class="panel">
|
|
636
|
+
<div class="panel-title">
|
|
637
|
+
<span>System One Move Intelligence</span>
|
|
638
|
+
<span id="lastMoveBadge" style="font-size: 0.78rem; font-weight: 600; padding: 3px 10px; border-radius: 4px; background: #21262d; color: var(--text-bright); border: 1px solid var(--card-border);">Waiting for move...</span>
|
|
639
|
+
</div>
|
|
640
|
+
<div class="metrics-grid">
|
|
641
|
+
<div class="metric-card">
|
|
642
|
+
<div class="metric-name">Tactical Sharpness (Score)</div>
|
|
643
|
+
<div class="metric-value">
|
|
644
|
+
<span id="mSharp">--</span>
|
|
645
|
+
<span class="metric-sub">/ 3.0</span>
|
|
646
|
+
</div>
|
|
647
|
+
<div class="progress-bar"><div id="mSharpBar" class="progress-fill"></div></div>
|
|
648
|
+
</div>
|
|
649
|
+
|
|
650
|
+
<div class="metric-card">
|
|
651
|
+
<div class="metric-name">Strategic Motif (Choice)</div>
|
|
652
|
+
<div class="metric-value" style="font-size: 1rem;" id="mTheme">--</div>
|
|
653
|
+
<div class="metric-sub" id="mThemeConf">Confidence: --</div>
|
|
654
|
+
</div>
|
|
655
|
+
|
|
656
|
+
<div class="metric-card">
|
|
657
|
+
<div class="metric-name">King Threat (Noul)</div>
|
|
658
|
+
<div class="metric-value"><span id="mKing">--</span></div>
|
|
659
|
+
<div class="progress-bar"><div id="mKingBar" class="progress-fill" style="background: var(--danger);"></div></div>
|
|
660
|
+
</div>
|
|
661
|
+
|
|
662
|
+
<div class="metric-card">
|
|
663
|
+
<div class="metric-name">Psychological Pressure (Noul)</div>
|
|
664
|
+
<div class="metric-value"><span id="mPressure">--</span></div>
|
|
665
|
+
<div class="progress-bar"><div id="mPressureBar" class="progress-fill" style="background: var(--warning);"></div></div>
|
|
666
|
+
</div>
|
|
667
|
+
</div>
|
|
668
|
+
</div>
|
|
669
|
+
|
|
670
|
+
<!-- Persona AI Opponent -->
|
|
671
|
+
<div class="panel">
|
|
672
|
+
<div class="panel-title">
|
|
673
|
+
<span>Persona AI Opponent</span>
|
|
674
|
+
<span class="panel-subtitle">Composite Scoring: weights · dimensions</span>
|
|
675
|
+
</div>
|
|
676
|
+
<div class="persona-select-grid">
|
|
677
|
+
<div class="persona-card active" onclick="selectPersona('tal', this)">
|
|
678
|
+
<div class="persona-name">Tal</div>
|
|
679
|
+
<div class="persona-title">Aggression & Chaos</div>
|
|
680
|
+
</div>
|
|
681
|
+
<div class="persona-card" onclick="selectPersona('petrosian', this)">
|
|
682
|
+
<div class="persona-name">Petrosian</div>
|
|
683
|
+
<div class="persona-title">Iron Prophylaxis</div>
|
|
684
|
+
</div>
|
|
685
|
+
<div class="persona-card" onclick="selectPersona('capablanca', this)">
|
|
686
|
+
<div class="persona-name">Capablanca</div>
|
|
687
|
+
<div class="persona-title">Simplification</div>
|
|
688
|
+
</div>
|
|
689
|
+
<div class="persona-card" onclick="selectPersona('coffeehouse', this)">
|
|
690
|
+
<div class="persona-name">Coffeehouse</div>
|
|
691
|
+
<div class="persona-title">Romantic Gambits</div>
|
|
692
|
+
</div>
|
|
693
|
+
</div>
|
|
694
|
+
<div id="personaRationale" class="persona-breakdown">
|
|
695
|
+
Select an opponent archetype and click "Ask Opponent Move" to watch TypeSafe score candidate moves across atomic dimensions.
|
|
696
|
+
</div>
|
|
697
|
+
</div>
|
|
698
|
+
|
|
699
|
+
<!-- Classic Matches & Game Classification -->
|
|
700
|
+
<div class="panel">
|
|
701
|
+
<div class="panel-title">
|
|
702
|
+
<span>Classic Matches & Replay Studio</span>
|
|
703
|
+
<span class="panel-subtitle">Historic Games & System One Classification</span>
|
|
704
|
+
</div>
|
|
705
|
+
|
|
706
|
+
<select id="matchSelect" class="match-select" onchange="onMatchSelectChange(this.value)">
|
|
707
|
+
<option value="">Loading classic games...</option>
|
|
708
|
+
</select>
|
|
709
|
+
|
|
710
|
+
<div id="matchMetaBox" class="match-meta-box" style="display: none;">
|
|
711
|
+
<div class="match-meta-header">
|
|
712
|
+
<span id="matchPlayers" class="match-players"></span>
|
|
713
|
+
<span id="matchYearEvent" style="color: #8b949e; font-size: 0.75rem;"></span>
|
|
714
|
+
</div>
|
|
715
|
+
<div id="matchDesc" style="color: var(--text); margin-top: 4px;"></div>
|
|
716
|
+
<div class="match-tags">
|
|
717
|
+
<span id="matchEco" class="match-tag"></span>
|
|
718
|
+
<span id="matchOpening" class="match-tag"></span>
|
|
719
|
+
<span id="matchResult" class="match-tag result"></span>
|
|
720
|
+
</div>
|
|
721
|
+
</div>
|
|
722
|
+
|
|
723
|
+
<!-- Replay Toolbar -->
|
|
724
|
+
<div class="replay-bar">
|
|
725
|
+
<button class="replay-btn" onclick="stepFirst()" title="First Position">|<</button>
|
|
726
|
+
<button class="replay-btn" onclick="stepPrev()" title="Previous Move"><</button>
|
|
727
|
+
<button class="replay-btn" onclick="stepNext()" title="Next Move">></button>
|
|
728
|
+
<button class="replay-btn" onclick="stepLast()" title="Final Position">>|</button>
|
|
729
|
+
<button id="autoPlayBtn" class="replay-btn" onclick="toggleAutoPlay()">Auto Play</button>
|
|
730
|
+
<button class="replay-btn" onclick="jumpToTurningPoint()" style="color: var(--accent);">Turning Point</button>
|
|
731
|
+
</div>
|
|
732
|
+
|
|
733
|
+
<div class="replay-progress-wrap" style="margin-top: 10px;">
|
|
734
|
+
<div class="replay-progress-text">
|
|
735
|
+
<span id="replayMoveLabel">Move 0 / 0</span>
|
|
736
|
+
<span id="replayTurnLabel">Initial Position</span>
|
|
737
|
+
</div>
|
|
738
|
+
<div class="progress-bar"><div id="replayProgressBar" class="progress-fill" style="width: 0%;"></div></div>
|
|
739
|
+
</div>
|
|
740
|
+
|
|
741
|
+
<!-- Classify Button -->
|
|
742
|
+
<div style="margin-top: 14px;">
|
|
743
|
+
<button id="classifyBtn" class="btn btn-accent" style="width: 100%;" onclick="classifyCurrentMatch()">
|
|
744
|
+
Classify Match with System One
|
|
745
|
+
</button>
|
|
746
|
+
</div>
|
|
747
|
+
|
|
748
|
+
<!-- Classification Results Card -->
|
|
749
|
+
<div id="classificationCard" class="classification-panel" style="display: none;">
|
|
750
|
+
<div style="display: flex; justify-content: space-between; align-items: center;">
|
|
751
|
+
<div id="classArchetype" class="archetype-banner">ARCHETYPE</div>
|
|
752
|
+
<span id="classSacrifice" style="font-size: 0.75rem; color: #8b949e;"></span>
|
|
753
|
+
</div>
|
|
754
|
+
|
|
755
|
+
<div class="class-grid">
|
|
756
|
+
<div class="class-stat">
|
|
757
|
+
<span class="class-stat-name">Brilliance</span>
|
|
758
|
+
<span id="classBrillianceScore" class="class-stat-val">--</span>
|
|
759
|
+
<span id="classBrillianceLevel" class="class-stat-desc">--</span>
|
|
760
|
+
</div>
|
|
761
|
+
<div class="class-stat">
|
|
762
|
+
<span class="class-stat-name">Sharpness</span>
|
|
763
|
+
<span id="classSharpnessScore" class="class-stat-val">--</span>
|
|
764
|
+
<span id="classSharpnessLevel" class="class-stat-desc">--</span>
|
|
765
|
+
</div>
|
|
766
|
+
<div class="class-stat">
|
|
767
|
+
<span class="class-stat-name">Turning Point</span>
|
|
768
|
+
<span id="classTurningMove" class="class-stat-val" style="color: var(--accent);">--</span>
|
|
769
|
+
<span id="classTurningNum" class="class-stat-desc">Move --</span>
|
|
770
|
+
</div>
|
|
771
|
+
</div>
|
|
772
|
+
|
|
773
|
+
<div style="font-size: 0.75rem; color: #8b949e; text-transform: uppercase; font-weight: 600; letter-spacing: 0.05em;">Strategic Profile</div>
|
|
774
|
+
<div class="breakdown-row">
|
|
775
|
+
<div class="breakdown-pill">Tactical: <strong id="bdTactical" style="color: var(--text-bright);">0%</strong></div>
|
|
776
|
+
<div class="breakdown-pill">Pawns: <strong id="bdPawn" style="color: var(--text-bright);">0%</strong></div>
|
|
777
|
+
<div class="breakdown-pill">Piece Play: <strong id="bdPiece" style="color: var(--text-bright);">0%</strong></div>
|
|
778
|
+
<div class="breakdown-pill">Prophylaxis: <strong id="bdProphyl" style="color: var(--text-bright);">0%</strong></div>
|
|
779
|
+
</div>
|
|
780
|
+
|
|
781
|
+
<div id="classVerdict" style="background: #161b22; border: 1px solid var(--card-border); border-radius: 6px; padding: 10px 12px; font-size: 0.8rem; color: var(--text); line-height: 1.5;">
|
|
782
|
+
</div>
|
|
783
|
+
</div>
|
|
784
|
+
</div>
|
|
785
|
+
</div>
|
|
786
|
+
</main>
|
|
787
|
+
|
|
788
|
+
<script src="app.js"></script>
|
|
789
|
+
</body>
|
|
790
|
+
</html>
|