HI7RAI commited on
Commit
d6dba8e
·
verified ·
1 Parent(s): 6a1c78f

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +718 -519
index.html CHANGED
@@ -3,12 +3,12 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>CSS3 Masterclass & Playground</title>
7
 
8
  <!-- Import Google Fonts -->
9
  <link rel="preconnect" href="https://fonts.googleapis.com">
10
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
11
- <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;800&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
12
 
13
  <!-- Import FontAwesome for Icons -->
14
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
@@ -16,660 +16,859 @@
16
  <style>
17
  /* --- CSS VARIABLES & RESET --- */
18
  :root {
19
- --primary: #00f2ea;
20
- --secondary: #ff0050;
21
- --bg-dark: #0f0c29;
22
- --bg-gradient: linear-gradient(135deg, #0f0c29, #302b63, #24243e);
23
- --glass-bg: rgba(255, 255, 255, 0.05);
24
- --glass-border: rgba(255, 255, 255, 0.1);
25
- --text-main: #ffffff;
26
- --text-muted: #a0a0a0;
27
- --card-radius: 16px;
28
- --transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
 
 
 
 
 
 
29
  }
30
 
31
  * {
32
  box-sizing: border-box;
33
  margin: 0;
34
  padding: 0;
 
35
  }
36
 
37
  body {
38
- font-family: 'Inter', sans-serif;
39
- background: var(--bg-gradient);
40
- background-attachment: fixed;
41
  color: var(--text-main);
42
- min-height: 100vh;
43
- line-height: 1.6;
44
- overflow-x: hidden;
45
- }
46
-
47
- /* --- UTILITIES --- */
48
- a { text-decoration: none; color: inherit; transition: var(--transition); }
49
- ul { list-style: none; }
50
-
51
- .container {
52
- max-width: 1200px;
53
- margin: 0 auto;
54
- padding: 0 20px;
55
- }
56
-
57
- .btn {
58
- display: inline-flex;
59
- align-items: center;
60
- gap: 8px;
61
- padding: 10px 20px;
62
- border-radius: 8px;
63
- font-weight: 600;
64
- cursor: pointer;
65
- border: none;
66
- transition: var(--transition);
67
- font-size: 0.9rem;
68
- }
69
-
70
- .btn-primary {
71
- background: var(--primary);
72
- color: #000;
73
- box-shadow: 0 0 15px rgba(0, 242, 234, 0.3);
74
  }
75
 
76
- .btn-primary:hover {
77
- transform: translateY(-2px);
78
- box-shadow: 0 0 25px rgba(0, 242, 234, 0.5);
79
- }
 
80
 
81
- .btn-outline {
82
- background: transparent;
83
- border: 1px solid var(--glass-border);
84
- color: var(--text-main);
85
- }
86
-
87
- .btn-outline:hover {
88
- background: var(--glass-bg);
89
- border-color: var(--primary);
90
- }
 
91
 
92
  /* --- HEADER --- */
93
  header {
94
- padding: 20px 0;
95
- position: sticky;
96
- top: 0;
97
- z-index: 100;
98
- backdrop-filter: blur(10px);
99
- background: rgba(15, 12, 41, 0.7);
100
- border-bottom: 1px solid var(--glass-border);
101
- }
102
-
103
- .nav-wrapper {
104
  display: flex;
105
- justify-content: space-between;
106
  align-items: center;
 
 
 
 
107
  }
108
 
109
  .logo {
110
- font-size: 1.5rem;
111
- font-weight: 800;
112
- background: linear-gradient(to right, var(--primary), var(--secondary));
113
- -webkit-background-clip: text;
114
- -webkit-text-fill-color: transparent;
115
- letter-spacing: -1px;
116
- }
117
-
118
- .nav-links {
119
  display: flex;
120
- gap: 20px;
121
- }
122
-
123
- .nav-links a:hover {
124
  color: var(--primary);
 
125
  }
126
 
127
  .anycoder-link {
128
  font-size: 0.8rem;
129
- opacity: 0.8;
130
- margin-left: auto;
131
- margin-right: 20px;
 
 
 
132
  }
133
-
134
  .anycoder-link:hover {
135
- opacity: 1;
136
- text-decoration: underline;
 
137
  }
138
 
139
- /* --- HERO SECTION --- */
140
- .hero {
141
- text-align: center;
142
- padding: 80px 0 40px;
 
143
  position: relative;
144
  }
145
 
146
- .hero h1 {
147
- font-size: clamp(2.5rem, 5vw, 4rem);
148
- margin-bottom: 20px;
149
- line-height: 1.1;
150
- }
151
-
152
- .hero p {
153
- color: var(--text-muted);
154
- font-size: 1.2rem;
155
- max-width: 600px;
156
- margin: 0 auto 40px;
157
- }
158
-
159
- /* --- 3D CUBE ANIMATION SHOWCASE --- */
160
- .scene {
161
- width: 200px;
162
- height: 200px;
163
- perspective: 600px;
164
- margin: 0 auto 50px;
165
  }
166
 
167
- .cube {
 
 
168
  width: 100%;
169
- height: 100%;
170
- position: relative;
171
- transform-style: preserve-3d;
172
- animation: rotateCube 10s infinite linear;
 
 
 
 
 
 
 
 
 
173
  }
 
174
 
175
- .cube__face {
176
- position: absolute;
177
- width: 200px;
178
- height: 200px;
179
- border: 2px solid var(--primary);
180
- background: rgba(0, 242, 234, 0.1);
181
  display: flex;
182
  align-items: center;
183
- justify-content: center;
184
- font-size: 2rem;
185
- font-weight: bold;
 
 
 
 
 
 
 
186
  color: var(--primary);
187
- box-shadow: 0 0 20px rgba(0, 242, 234, 0.2) inset;
188
- backface-visibility: visible;
189
  }
190
 
191
- .cube__face--front { transform: rotateY( 0deg) translateZ(100px); }
192
- .cube__face--right { transform: rotateY( 90deg) translateZ(100px); }
193
- .cube__face--back { transform: rotateY(180deg) translateZ(100px); }
194
- .cube__face--left { transform: rotateY(-90deg) translateZ(100px); }
195
- .cube__face--top { transform: rotateX( 90deg) translateZ(100px); }
196
- .cube__face--bottom { transform: rotateX(-90deg) translateZ(100px); }
 
 
 
 
 
197
 
198
- @keyframes rotateCube {
199
- 0% { transform: rotateX(0deg) rotateY(0deg); }
200
- 100% { transform: rotateX(360deg) rotateY(360deg); }
 
 
201
  }
 
202
 
203
- /* --- DASHBOARD GRID --- */
204
- .dashboard {
205
- display: grid;
206
- grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
207
- gap: 30px;
208
- padding-bottom: 80px;
209
  }
 
210
 
211
- .card {
212
- background: var(--glass-bg);
213
- border: 1px solid var(--glass-border);
214
- border-radius: var(--card-radius);
215
- padding: 25px;
216
- backdrop-filter: blur(12px);
217
- transition: var(--transition);
218
  display: flex;
219
  flex-direction: column;
 
 
 
220
  }
221
 
222
- .card:hover {
223
- transform: translateY(-5px);
224
- border-color: rgba(255, 255, 255, 0.3);
225
- box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
226
- }
227
-
228
- .card-header {
229
  display: flex;
230
  justify-content: space-between;
231
  align-items: center;
232
- margin-bottom: 20px;
233
- padding-bottom: 15px;
234
- border-bottom: 1px solid var(--glass-border);
235
  }
236
 
237
- .card-title {
238
- font-size: 1.2rem;
239
- font-weight: 600;
240
- display: flex;
241
- align-items: center;
242
- gap: 10px;
243
  }
 
244
 
245
- .card-title i { color: var(--secondary); }
246
-
247
- /* --- FLEXBOX PLAYGROUND --- */
248
- .flex-preview {
249
- background: rgba(0, 0, 0, 0.3);
250
- border-radius: 8px;
251
- padding: 10px;
252
- height: 200px;
253
- margin-bottom: 20px;
254
- display: flex;
255
- transition: all 0.3s ease;
256
- overflow: hidden;
257
  }
258
 
259
- .flex-item {
260
- width: 50px;
261
- height: 50px;
262
- background: var(--secondary);
263
- border-radius: 6px;
264
- display: flex;
265
- align-items: center;
266
- justify-content: center;
267
- font-weight: bold;
268
- box-shadow: 0 4px 6px rgba(0,0,0,0.2);
269
  }
 
270
 
271
- .flex-item:nth-child(even) { background: #ff5e00; }
272
-
273
- .controls {
274
- display: grid;
275
- gap: 15px;
 
 
276
  }
277
 
278
- .control-group {
279
- display: flex;
280
- flex-direction: column;
281
- gap: 5px;
 
 
 
 
 
 
 
282
  }
283
 
284
- .control-group label {
285
- font-size: 0.85rem;
286
- color: var(--text-muted);
 
 
 
 
 
 
 
 
287
  }
 
288
 
289
- select, input[type="range"] {
290
- width: 100%;
291
- background: rgba(255, 255, 255, 0.1);
292
- border: 1px solid var(--glass-border);
293
- color: white;
294
- padding: 8px;
295
- border-radius: 6px;
296
- outline: none;
297
  }
 
298
 
299
- select:focus { border-color: var(--primary); }
 
 
 
 
 
 
 
 
300
 
301
- /* --- GRADIENT GENERATOR --- */
302
- .gradient-preview {
303
- height: 150px;
304
- border-radius: 8px;
305
- margin-bottom: 20px;
306
- border: 1px solid var(--glass-border);
307
- transition: background 0.2s;
308
  }
 
309
 
310
- .color-inputs {
311
- display: flex;
312
- gap: 10px;
313
- margin-bottom: 15px;
 
 
 
314
  }
315
 
316
- input[type="color"] {
317
- -webkit-appearance: none;
318
- border: none;
319
- width: 50px;
320
- height: 50px;
321
- border-radius: 8px;
322
- cursor: pointer;
323
- background: none;
 
 
 
 
324
  }
 
 
 
 
 
 
 
 
325
 
326
- input[type="color"]::-webkit-color-swatch-wrapper { padding: 0; }
327
- input[type="color"]::-webkit-color-swatch { border: 1px solid var(--glass-border); border-radius: 8px; }
328
-
329
- .code-block {
330
- background: #000;
331
- padding: 15px;
332
- border-radius: 8px;
333
- font-family: 'JetBrains Mono', monospace;
334
- font-size: 0.8rem;
335
- color: #0f0;
336
- margin-top: auto;
337
- position: relative;
338
- word-break: break-all;
 
 
 
 
339
  }
340
-
341
- /* --- GLASSMORPHISM SHOWCASE --- */
342
- .glass-showcase {
343
- position: relative;
344
- height: 250px;
345
- border-radius: 12px;
346
- overflow: hidden;
347
- display: flex;
348
- align-items: center;
349
- justify-content: center;
350
- /* Background shapes for glass effect visibility */
351
- background:
352
- radial-gradient(circle at 20% 20%, rgba(255, 0, 80, 0.6) 0%, transparent 40%),
353
- radial-gradient(circle at 80% 80%, rgba(0, 242, 234, 0.6) 0%, transparent 40%);
354
  }
 
 
 
 
 
355
 
356
- .glass-card {
357
- background: rgba(255, 255, 255, 0.1);
358
- backdrop-filter: blur(16px);
359
- -webkit-backdrop-filter: blur(16px);
360
- border: 1px solid rgba(255, 255, 255, 0.2);
361
- padding: 30px;
362
- border-radius: 16px;
363
- width: 70%;
364
- text-align: center;
365
- box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1);
366
  }
 
 
 
 
367
 
368
- /* --- TOAST NOTIFICATION --- */
369
  .toast {
370
- position: fixed;
371
- bottom: 30px;
372
- right: 30px;
373
- background: var(--primary);
374
- color: #000;
375
- padding: 12px 24px;
376
- border-radius: 8px;
377
- font-weight: 600;
378
- transform: translateY(100px);
379
- opacity: 0;
380
- transition: all 0.4s cubic-bezier(0.68, -0.55, 0.27, 1.55);
381
- z-index: 1000;
382
- box-shadow: 0 5px 15px rgba(0,0,0,0.3);
383
- display: flex;
384
- align-items: center;
385
- gap: 10px;
 
386
  }
387
-
388
- .toast.active {
389
- transform: translateY(0);
390
- opacity: 1;
391
  }
392
-
393
- /* --- FOOTER --- */
394
- footer {
395
- text-align: center;
396
- padding: 40px 0;
397
- border-top: 1px solid var(--glass-border);
398
- color: var(--text-muted);
399
- font-size: 0.9rem;
400
  }
 
401
 
402
- /* --- RESPONSIVE --- */
403
- @media (max-width: 768px) {
404
- .hero h1 { font-size: 2.5rem; }
405
- .nav-links { display: none; } /* Simplified for mobile */
406
- .scene { width: 150px; height: 150px; }
407
- .cube__face { width: 150px; height: 150px; font-size: 1.5rem; }
408
- .cube__face--front { transform: rotateY( 0deg) translateZ(75px); }
409
- .cube__face--right { transform: rotateY( 90deg) translateZ(75px); }
410
- .cube__face--back { transform: rotateY(180deg) translateZ(75px); }
411
- .cube__face--left { transform: rotateY(-90deg) translateZ(75px); }
412
- .cube__face--top { transform: rotateX( 90deg) translateZ(75px); }
413
- .cube__face--bottom { transform: rotateX(-90deg) translateZ(75px); }
414
  }
 
 
 
 
415
  </style>
416
  </head>
417
  <body>
418
 
419
  <!-- Header -->
420
  <header>
421
- <div class="container nav-wrapper">
422
- <div class="logo">CSS3.io</div>
423
- <nav class="nav-links">
424
- <a href="#flexbox">Flexbox</a>
425
- <a href="#gradients">Gradients</a>
426
- <a href="#glass">Glassmorphism</a>
427
- </nav>
428
  <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="anycoder-link">
429
- Built with anycoder <i class="fas fa-external-link-alt"></i>
430
  </a>
 
 
 
 
 
 
431
  </div>
432
  </header>
433
 
434
- <!-- Main Content -->
435
- <main class="container">
436
-
437
- <!-- Hero Section -->
438
- <section class="hero">
439
- <h1>Master the Modern Web</h1>
440
- <p>Explore the power of CSS3 with our interactive playgrounds. Experiment with 3D transforms, flexible layouts, and advanced visual effects.</p>
441
-
442
- <!-- 3D Cube Animation -->
443
- <div class="scene">
444
- <div class="cube">
445
- <div class="cube__face cube__face--front">HTML</div>
446
- <div class="cube__face cube__face--back">CSS</div>
447
- <div class="cube__face cube__face--right">JS</div>
448
- <div class="cube__face cube__face--left">3D</div>
449
- <div class="cube__face cube__face--top">Web</div>
450
- <div class="cube__face cube__face--bottom">App</div>
451
- </div>
452
- </div>
453
-
454
- <button class="btn btn-primary" onclick="document.getElementById('playground').scrollIntoView({behavior: 'smooth'})">
455
- Start Experimenting <i class="fas fa-arrow-down"></i>
456
- </button>
457
- </section>
458
-
459
- <!-- Interactive Dashboard -->
460
- <div class="dashboard" id="playground">
461
 
462
- <!-- 1. Flexbox Playground -->
463
- <article class="card" id="flexbox">
464
- <div class="card-header">
465
- <div class="card-title"><i class="fas fa-arrows-alt-h"></i> Flexbox Generator</div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
466
  </div>
467
-
468
- <div class="flex-preview" id="flexContainer">
469
- <div class="flex-item">1</div>
470
- <div class="flex-item">2</div>
471
- <div class="flex-item">3</div>
472
- <div class="flex-item">4</div>
473
  </div>
 
474
 
475
- <div class="controls">
476
- <div class="control-group">
477
- <label>Justify Content</label>
478
- <select id="justifySelect">
479
- <option value="flex-start">Flex Start</option>
480
- <option value="center" selected>Center</option>
481
- <option value="flex-end">Flex End</option>
482
- <option value="space-between">Space Between</option>
483
- <option value="space-around">Space Around</option>
484
- </select>
485
- </div>
486
- <div class="control-group">
487
- <label>Align Items</label>
488
- <select id="alignSelect">
489
- <option value="stretch" selected>Stretch</option>
490
- <option value="flex-start">Flex Start</option>
491
- <option value="center">Center</option>
492
- <option value="flex-end">Flex End</option>
493
- </select>
494
- </div>
495
- <div class="control-group">
496
- <label>Direction</label>
497
- <select id="directionSelect">
498
- <option value="row" selected>Row</option>
499
- <option value="column">Column</option>
500
- <option value="row-reverse">Row Reverse</option>
501
- </select>
502
- </div>
503
- </div>
504
- </article>
505
 
506
- <!-- 2. Gradient Generator -->
507
- <article class="card" id="gradients">
508
- <div class="card-header">
509
- <div class="card-title"><i class="fas fa-palette"></i> Gradient Maker</div>
510
  </div>
511
-
512
- <div class="gradient-preview" id="gradientPreview"></div>
513
-
514
- <div class="controls">
515
- <div class="color-inputs">
516
- <input type="color" id="color1" value="#00f2ea">
517
- <input type="color" id="color2" value="#ff0050">
518
- </div>
519
-
520
- <div class="control-group">
521
- <label>Angle: <span id="angleValue">45</span>deg</label>
522
- <input type="range" id="angleRange" min="0" max="360" value="45">
523
  </div>
524
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
525
 
526
- <div class="code-block" id="gradientCode">
527
- background: linear-gradient(45deg, #00f2ea, #ff0050);
 
 
 
 
528
  </div>
529
-
530
- <div style="margin-top: 15px; text-align: right;">
531
- <button class="btn btn-outline" id="copyGradientBtn" style="font-size: 0.8rem;">
532
- <i class="fas fa-copy"></i> Copy CSS
533
- </button>
534
  </div>
535
- </article>
 
 
 
 
 
 
536
 
537
- <!-- 3. Glassmorphism Showcase -->
538
- <article class="card" id="glass">
539
- <div class="card-header">
540
- <div class="card-title"><i class="fas fa-layer-group"></i> Glassmorphism UI</div>
 
541
  </div>
542
-
543
- <div class="glass-showcase">
544
- <div class="glass-card">
545
- <h4>Frosty Effect</h4>
546
- <p style="font-size: 0.8rem; margin-top: 5px; opacity: 0.8;">
547
- Uses backdrop-filter: blur(16px)
548
- </p>
549
- </div>
550
  </div>
 
 
 
551
 
552
- <div class="code-block" style="margin-top: 20px;">
553
- background: rgba(255, 255, 255, 0.1);
554
- backdrop-filter: blur(16px);
555
- border: 1px solid rgba(255, 255, 255, 0.2);
556
- </div>
557
- </article>
558
 
559
- <!-- 4. Animation Timeline -->
560
- <article class="card">
561
- <div class="card-header">
562
- <div class="card-title"><i class="fas fa-film"></i> Keyframe Animation</div>
563
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
564
 
565
- <div style="height: 150px; display: flex; justify-content: center; align-items: center; background: rgba(0,0,0,0.2); border-radius: 8px; position: relative; overflow: hidden;">
566
- <div style="width: 40px; height: 40px; background: var(--primary); border-radius: 50%; animation: bounce 2s infinite ease-in-out;"></div>
567
- <div style="position: absolute; bottom: 10px; width: 80%; height: 2px; background: rgba(255,255,255,0.1);"></div>
568
- </div>
 
 
 
569
 
570
- <style>
571
- @keyframes bounce {
572
- 0%, 100% { transform: translateY(0); animation-timing-function: cubic-bezier(0.8,0,1,1); }
573
- 50% { transform: translateY(-60px); animation-timing-function: cubic-bezier(0,0,0.2,1); }
 
 
 
 
 
 
 
 
 
574
  }
575
- </style>
576
-
577
- <div class="code-block" style="margin-top: 20px;">
578
- @keyframes bounce {
579
- 50% { transform: translateY(-60px); }
580
- }
581
- </div>
582
- </article>
583
 
584
- </div>
585
- </main>
 
 
 
 
 
 
 
 
586
 
587
- <!-- Footer -->
588
- <footer>
589
- <p>&copy; 2023 CSS3 Masterclass. Built for modern web browsers.</p>
590
- </footer>
 
 
 
 
 
 
591
 
592
- <!-- Toast Notification -->
593
- <div class="toast" id="toast">
594
- <i class="fas fa-check-circle"></i> CSS Copied to Clipboard!
595
- </div>
596
 
597
- <!-- JavaScript Logic -->
598
- <script>
599
- document.addEventListener('DOMContentLoaded', () => {
600
 
601
- // --- 1. Flexbox Logic ---
602
- const flexContainer = document.getElementById('flexContainer');
603
- const justifySelect = document.getElementById('justifySelect');
604
- const alignSelect = document.getElementById('alignSelect');
605
- const directionSelect = document.getElementById('directionSelect');
606
-
607
- function updateFlex() {
608
- flexContainer.style.justifyContent = justifySelect.value;
609
- flexContainer.style.alignItems = alignSelect.value;
610
- flexContainer.style.flexDirection = directionSelect.value;
 
 
 
611
  }
612
 
613
- justifySelect.addEventListener('change', updateFlex);
614
- alignSelect.addEventListener('change', updateFlex);
615
- directionSelect.addEventListener('change', updateFlex);
 
 
616
 
617
- // Initialize Flexbox
618
- updateFlex();
 
 
 
 
 
 
619
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
620
 
621
- // --- 2. Gradient Logic ---
622
- const gradientPreview = document.getElementById('gradientPreview');
623
- const color1 = document.getElementById('color1');
624
- const color2 = document.getElementById('color2');
625
- const angleRange = document.getElementById('angleRange');
626
- const angleValue = document.getElementById('angleValue');
627
- const gradientCode = document.getElementById('gradientCode');
628
- const copyGradientBtn = document.getElementById('copyGradientBtn');
 
 
 
 
 
629
 
630
- function updateGradient() {
631
- const c1 = color1.value;
632
- const c2 = color2.value;
633
- const deg = angleRange.value;
634
-
635
- const cssString = `linear-gradient(${deg}deg, ${c1}, ${c2})`;
636
-
637
- gradientPreview.style.background = cssString;
638
- gradientCode.textContent = `background: ${cssString};`;
639
- angleValue.textContent = deg;
640
  }
 
641
 
642
- color1.addEventListener('input', updateGradient);
643
- color2.addEventListener('input', updateGradient);
644
- angleRange.addEventListener('input', updateGradient);
 
645
 
646
- // Copy Functionality
647
- copyGradientBtn.addEventListener('click', () => {
648
- const textToCopy = gradientCode.textContent;
649
- navigator.clipboard.writeText(textToCopy).then(() => {
650
- showToast();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
651
  });
652
- });
 
 
 
 
653
 
654
- // Initialize Gradient
655
- updateGradient();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
656
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
657
 
658
- // --- 3. Toast Notification Logic ---
659
- const toast = document.getElementById('toast');
660
- let toastTimeout;
 
 
 
661
 
662
- function showToast() {
663
- toast.classList.add('active');
664
-
665
- // Clear existing timeout if user clicks rapidly
666
- if (toastTimeout) clearTimeout(toastTimeout);
667
 
668
- toastTimeout = setTimeout(() => {
669
- toast.classList.remove('active');
670
- }, 3000);
671
- }
672
- });
673
- </script>
674
- </body>
675
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>AI Transformers Workbench</title>
7
 
8
  <!-- Import Google Fonts -->
9
  <link rel="preconnect" href="https://fonts.googleapis.com">
10
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
11
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
12
 
13
  <!-- Import FontAwesome for Icons -->
14
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
 
16
  <style>
17
  /* --- CSS VARIABLES & RESET --- */
18
  :root {
19
+ --bg-dark: #0f172a;
20
+ --bg-panel: #1e293b;
21
+ --bg-input: #0f172a;
22
+ --border: #334155;
23
+ --border-hover: #94a3b8;
24
+ --primary: #38bdf8; /* Sky Blue */
25
+ --secondary: #818cf8; /* Indigo */
26
+ --accent-glow: rgba(56, 189, 248, 0.15);
27
+ --success: #22c55e;
28
+ --danger: #ef4444;
29
+ --text-main: #f1f5f9;
30
+ --text-muted: #94a3b8;
31
+ --font-main: 'Inter', sans-serif;
32
+ --font-code: 'JetBrains Mono', monospace;
33
+ --header-height: 60px;
34
+ --transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
35
  }
36
 
37
  * {
38
  box-sizing: border-box;
39
  margin: 0;
40
  padding: 0;
41
+ outline: none;
42
  }
43
 
44
  body {
45
+ font-family: var(--font-main);
46
+ background-color: var(--bg-dark);
 
47
  color: var(--text-main);
48
+ height: 100vh;
49
+ display: flex;
50
+ flex-direction: column;
51
+ overflow: hidden;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  }
53
 
54
+ /* --- Scrollbar --- */
55
+ ::-webkit-scrollbar { width: 6px; height: 6px; }
56
+ ::-webkit-scrollbar-track { background: transparent; }
57
+ ::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
58
+ ::-webkit-scrollbar-thumb:hover { background: var(--text-muted); }
59
 
60
+ /* --- UTILITIES --- */
61
+ .hidden { display: none !important; }
62
+ .flex { display: flex; }
63
+ .flex-col { flex-direction: column; }
64
+ .items-center { align-items: center; }
65
+ .justify-between { justify-content: space-between; }
66
+ .gap-2 { gap: 8px; }
67
+ .gap-4 { gap: 16px; }
68
+ .text-sm { font-size: 0.875rem; }
69
+ .text-xs { font-size: 0.75rem; }
70
+ .font-mono { font-family: var(--font-code); }
71
 
72
  /* --- HEADER --- */
73
  header {
74
+ height: var(--header-height);
75
+ background-color: rgba(30, 41, 59, 0.8);
76
+ backdrop-filter: blur(12px);
77
+ border-bottom: 1px solid var(--border);
 
 
 
 
 
 
78
  display: flex;
 
79
  align-items: center;
80
+ justify-content: space-between;
81
+ padding: 0 20px;
82
+ flex-shrink: 0;
83
+ z-index: 50;
84
  }
85
 
86
  .logo {
87
+ font-weight: 700;
88
+ font-size: 1.2rem;
 
 
 
 
 
 
 
89
  display: flex;
90
+ align-items: center;
91
+ gap: 10px;
 
 
92
  color: var(--primary);
93
+ text-shadow: 0 0 10px rgba(56, 189, 248, 0.3);
94
  }
95
 
96
  .anycoder-link {
97
  font-size: 0.8rem;
98
+ color: var(--text-muted);
99
+ text-decoration: none;
100
+ transition: var(--transition);
101
+ padding: 5px 10px;
102
+ border-radius: 4px;
103
+ border: 1px solid transparent;
104
  }
 
105
  .anycoder-link:hover {
106
+ color: var(--primary);
107
+ border-color: var(--border);
108
+ background: var(--bg-panel);
109
  }
110
 
111
+ /* --- MAIN LAYOUT --- */
112
+ .main-container {
113
+ display: flex;
114
+ flex: 1;
115
+ overflow: hidden;
116
  position: relative;
117
  }
118
 
119
+ /* --- SIDEBAR (History) --- */
120
+ .sidebar {
121
+ width: 280px;
122
+ background-color: var(--bg-panel);
123
+ border-right: 1px solid var(--border);
124
+ display: flex;
125
+ flex-direction: column;
126
+ transition: var(--transition);
127
+ z-index: 40;
 
 
 
 
 
 
 
 
 
 
128
  }
129
 
130
+ .sidebar-header { padding: 15px; border-bottom: 1px solid var(--border); }
131
+
132
+ .btn-new-chat {
133
  width: 100%;
134
+ padding: 10px;
135
+ background: linear-gradient(135deg, var(--primary), var(--secondary));
136
+ color: #fff;
137
+ border: none;
138
+ border-radius: 6px;
139
+ cursor: pointer;
140
+ font-weight: 600;
141
+ display: flex;
142
+ align-items: center;
143
+ justify-content: center;
144
+ gap: 8px;
145
+ transition: var(--transition);
146
+ box-shadow: 0 4px 12px rgba(56, 189, 248, 0.2);
147
  }
148
+ .btn-new-chat:hover { transform: translateY(-2px); box-shadow: 0 6px 16px rgba(56, 189, 248, 0.3); }
149
 
150
+ .history-list { flex: 1; overflow-y: auto; padding: 10px; }
151
+
152
+ .history-item {
153
+ padding: 12px;
154
+ border-radius: 6px;
155
+ cursor: pointer;
156
  display: flex;
157
  align-items: center;
158
+ justify-content: space-between;
159
+ margin-bottom: 5px;
160
+ color: var(--text-muted);
161
+ transition: var(--transition);
162
+ border: 1px solid transparent;
163
+ }
164
+ .history-item:hover { background-color: rgba(255,255,255,0.05); color: var(--text-main); }
165
+ .history-item.active {
166
+ background: var(--accent-glow);
167
+ border-color: var(--primary);
168
  color: var(--primary);
 
 
169
  }
170
 
171
+ .history-name {
172
+ font-size: 0.9rem;
173
+ white-space: nowrap;
174
+ overflow: hidden;
175
+ text-overflow: ellipsis;
176
+ flex: 1;
177
+ margin-right: 8px;
178
+ padding: 2px 4px;
179
+ border-radius: 4px;
180
+ }
181
+ .history-name:focus { background: var(--bg-input); border: 1px solid var(--primary); color: var(--text-main); }
182
 
183
+ .history-actions i {
184
+ font-size: 0.8rem;
185
+ padding: 4px;
186
+ border-radius: 4px;
187
+ transition: 0.2s;
188
  }
189
+ .history-actions i:hover { color: var(--danger); background: rgba(239, 68, 68, 0.1); }
190
 
191
+ .sidebar-footer { padding: 15px; border-top: 1px solid var(--border); }
192
+ .btn-import {
193
+ width: 100%; padding: 8px; background: transparent;
194
+ border: 1px dashed var(--border); color: var(--text-muted);
195
+ border-radius: 6px; cursor: pointer; transition: var(--transition);
196
+ display: flex; align-items: center; justify-content: center; gap: 6px;
197
  }
198
+ .btn-import:hover { border-color: var(--primary); color: var(--primary); background: rgba(56, 189, 248, 0.05); }
199
 
200
+ /* --- CHAT AREA --- */
201
+ .chat-area {
202
+ flex: 1;
 
 
 
 
203
  display: flex;
204
  flex-direction: column;
205
+ background-color: var(--bg-dark);
206
+ position: relative;
207
+ min-width: 0;
208
  }
209
 
210
+ .chat-header {
211
+ padding: 10px 20px;
212
+ border-bottom: 1px solid var(--border);
 
 
 
 
213
  display: flex;
214
  justify-content: space-between;
215
  align-items: center;
216
+ background: rgba(15, 23, 42, 0.6);
217
+ backdrop-filter: blur(5px);
 
218
  }
219
 
220
+ .model-indicator { display: flex; align-items: center; gap: 10px; font-weight: 600; }
221
+ .badge {
222
+ font-size: 0.7rem; padding: 2px 8px; border-radius: 12px;
223
+ background: var(--bg-panel); border: 1px solid var(--border);
224
+ color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.5px;
225
+ transition: var(--transition);
226
  }
227
+ .badge.active { background: var(--success); color: #fff; border-color: var(--success); box-shadow: 0 0 8px rgba(34, 197, 94, 0.4); }
228
 
229
+ .chat-messages {
230
+ flex: 1; overflow-y: auto; padding: 20px;
231
+ display: flex; flex-direction: column; gap: 20px;
232
+ scroll-behavior: smooth;
 
 
 
 
 
 
 
 
233
  }
234
 
235
+ .message {
236
+ max-width: 85%; line-height: 1.6; position: relative;
237
+ animation: slideUp 0.3s ease;
 
 
 
 
 
 
 
238
  }
239
+ @keyframes slideUp { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
240
 
241
+ .message.user { align-self: flex-end; }
242
+ .message.ai { align-self: flex-start; }
243
+ .message.system {
244
+ align-self: center; max-width: 90%; font-size: 0.85rem;
245
+ color: var(--text-muted); text-align: center;
246
+ background: rgba(255,255,255,0.05); padding: 4px 12px;
247
+ border-radius: 20px; border: 1px solid var(--border);
248
  }
249
 
250
+ .bubble {
251
+ padding: 12px 18px; border-radius: 12px; position: relative;
252
+ word-wrap: break-word; white-space: pre-wrap; font-size: 0.95rem;
253
+ }
254
+ .message.user .bubble {
255
+ background-color: var(--primary); color: #0f172a;
256
+ border-bottom-right-radius: 2px;
257
+ }
258
+ .message.ai .bubble {
259
+ background-color: var(--bg-panel); border: 1px solid var(--border);
260
+ border-bottom-left-radius: 2px; color: var(--text-main);
261
  }
262
 
263
+ /* Copy/Paste Actions */
264
+ .msg-actions {
265
+ position: absolute; top: -25px; right: 0;
266
+ display: none; gap: 6px;
267
+ }
268
+ .message:hover .msg-actions { display: flex; }
269
+ .action-btn {
270
+ background: var(--bg-panel); border: 1px solid var(--border);
271
+ color: var(--text-muted); padding: 4px 8px; border-radius: 4px;
272
+ font-size: 0.75rem; cursor: pointer; display: flex; align-items: center; gap: 4px;
273
+ transition: var(--transition);
274
  }
275
+ .action-btn:hover { color: var(--primary); border-color: var(--primary); transform: translateY(-2px); }
276
 
277
+ .input-area {
278
+ padding: 20px; border-top: 1px solid var(--border);
279
+ background-color: var(--bg-panel);
 
 
 
 
 
280
  }
281
+ .input-wrapper { position: relative; max-width: 900px; margin: 0 auto; }
282
 
283
+ .chat-input {
284
+ width: 100%; background-color: var(--bg-input);
285
+ border: 1px solid var(--border); border-radius: 8px;
286
+ padding: 15px 50px 15px 15px; color: var(--text-main);
287
+ font-family: var(--font-main); resize: none;
288
+ min-height: 54px; max-height: 200px; line-height: 1.5;
289
+ transition: var(--transition);
290
+ }
291
+ .chat-input:focus { border-color: var(--primary); box-shadow: 0 0 0 3px rgba(56, 189, 248, 0.1); }
292
 
293
+ .send-btn {
294
+ position: absolute; right: 12px; bottom: 12px; background: none;
295
+ border: none; color: var(--text-muted); cursor: pointer;
296
+ font-size: 1.2rem; transition: var(--transition);
 
 
 
297
  }
298
+ .send-btn:hover { color: var(--primary); transform: scale(1.1); }
299
 
300
+ /* --- RIGHT PANEL (Tools) --- */
301
+ .right-panel {
302
+ width: 320px;
303
+ background-color: var(--bg-panel);
304
+ border-left: 1px solid var(--border);
305
+ display: flex; flex-direction: column;
306
+ overflow-y: auto; transition: var(--transition);
307
  }
308
 
309
+ .panel-section { padding: 20px; border-bottom: 1px solid var(--border); }
310
+ .panel-title {
311
+ font-size: 0.75rem; text-transform: uppercase; color: var(--text-muted);
312
+ margin-bottom: 12px; font-weight: 700; letter-spacing: 0.5px;
313
+ display: flex; align-items: center; gap: 8px;
314
+ }
315
+
316
+ /* Model Cards */
317
+ .model-card {
318
+ background: var(--bg-input); border: 1px solid var(--border);
319
+ border-radius: 8px; padding: 12px; margin-bottom: 10px;
320
+ cursor: pointer; transition: var(--transition);
321
  }
322
+ .model-card:hover { border-color: var(--text-muted); transform: translateY(-2px); }
323
+ .model-card.active {
324
+ border-color: var(--primary); background: var(--accent-glow);
325
+ box-shadow: 0 0 0 1px rgba(56, 189, 248, 0.3);
326
+ }
327
+ .model-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 6px; }
328
+ .model-name { font-weight: 600; font-size: 0.95rem; }
329
+ .model-meta { font-size: 0.8rem; color: var(--text-muted); line-height: 1.4; }
330
 
331
+ .showcase-stats { display: flex; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
332
+ .stat { font-size: 0.7rem; background: rgba(255,255,255,0.05); padding: 2px 6px; border-radius: 4px; color: var(--text-muted); }
333
+
334
+ /* Forms & Config */
335
+ .form-group { display: flex; flex-direction: column; gap: 6px; margin-bottom: 12px; }
336
+ .form-group label { font-size: 0.8rem; color: var(--text-muted); }
337
+ .form-input {
338
+ background: var(--bg-input); border: 1px solid var(--border);
339
+ color: var(--text-main); padding: 8px 12px; border-radius: 6px;
340
+ font-family: var(--font-code); font-size: 0.85rem; width: 100%;
341
+ }
342
+ .form-input:focus { border-color: var(--primary); }
343
+
344
+ .btn-download, .btn-secondary {
345
+ width: 100%; padding: 10px; border-radius: 6px; cursor: pointer;
346
+ font-weight: 600; display: flex; align-items: center; justify-content: center; gap: 8px;
347
+ transition: var(--transition);
348
  }
349
+ .btn-download {
350
+ background-color: var(--primary); color: #0f172a; border: none;
 
 
 
 
 
 
 
 
 
 
 
 
351
  }
352
+ .btn-download:hover { box-shadow: 0 0 15px rgba(56, 189, 248, 0.4); }
353
+ .btn-secondary {
354
+ background-color: transparent; border: 1px solid var(--border); color: var(--text-main);
355
+ }
356
+ .btn-secondary:hover { background: var(--bg-input); border-color: var(--text-muted); }
357
 
358
+ /* Terminal */
359
+ .terminal {
360
+ background: #000; color: #22c55e; font-family: var(--font-code);
361
+ font-size: 0.75rem; padding: 12px; border-radius: 6px;
362
+ height: 180px; overflow-y: auto; border: 1px solid #333;
363
+ box-shadow: inset 0 0 10px rgba(0,0,0,0.8);
 
 
 
 
364
  }
365
+ .terminal-line { margin-bottom: 4px; word-break: break-all; }
366
+ .terminal-line.error { color: var(--danger); }
367
+ .terminal-line.info { color: #94a3b8; }
368
+ .terminal-line.command { color: var(--text-main); font-weight: bold; }
369
 
370
+ /* Toast */
371
  .toast {
372
+ position: fixed; bottom: 24px; right: 24px;
373
+ background: var(--bg-panel); border: 1px solid var(--primary);
374
+ color: var(--text-main); padding: 12px 20px; border-radius: 8px;
375
+ box-shadow: 0 10px 30px rgba(0,0,0,0.5);
376
+ transform: translateY(100px); opacity: 0;
377
+ transition: var(--transition); z-index: 1000;
378
+ display: flex; align-items: center; gap: 10px;
379
+ }
380
+ .toast.show { transform: translateY(0); opacity: 1; }
381
+
382
+ /* --- FOCUS MODE & RESPONSIVE --- */
383
+ body.focus-mode .sidebar, body.focus-mode .right-panel { display: none; }
384
+ body.focus-mode .chat-area { max-width: 900px; margin: 0 auto; border-left: 1px solid var(--border); border-right: 1px solid var(--border); }
385
+
386
+ @media (max-width: 1024px) {
387
+ .right-panel { position: absolute; right: 0; height: 100%; transform: translateX(100%); z-index: 60; box-shadow: -5px 0 15px rgba(0,0,0,0.5); }
388
+ .right-panel.open { transform: translateX(0); }
389
  }
390
+ @media (max-width: 768px) {
391
+ .sidebar { position: absolute; left: 0; height: 100%; transform: translateX(-100%); box-shadow: 5px 0 15px rgba(0,0,0,0.5); }
392
+ .sidebar.open { transform: translateX(0); }
393
+ .message { max-width: 95%; }
394
  }
395
+
396
+ /* Mobile Overlay */
397
+ .mobile-overlay {
398
+ position: fixed; top: 0; left: 0; width: 100%; height: 100%;
399
+ background: rgba(0,0,0,0.5); z-index: 30; display: none;
 
 
 
400
  }
401
+ .mobile-overlay.active { display: block; }
402
 
403
+ /* Loading Animation */
404
+ .typing-indicator span {
405
+ display: inline-block; width: 6px; height: 6px;
406
+ background-color: var(--text-muted); border-radius: 50%;
407
+ animation: typing 1.4s infinite ease-in-out both; margin: 0 2px;
 
 
 
 
 
 
 
408
  }
409
+ .typing-indicator span:nth-child(1) { animation-delay: -0.32s; }
410
+ .typing-indicator span:nth-child(2) { animation-delay: -0.16s; }
411
+ @keyframes typing { 0%, 80%, 100% { transform: scale(0); } 40% { transform: scale(1); } }
412
+
413
  </style>
414
  </head>
415
  <body>
416
 
417
  <!-- Header -->
418
  <header>
419
+ <div class="logo">
420
+ <i class="fa-solid fa-cube"></i>
421
+ <span>Transformers<span style="color:var(--text-muted); font-weight:400; font-size:0.9em;">WebApp</span></span>
422
+ </div>
423
+
424
+ <div class="flex items-center gap-4">
 
425
  <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="anycoder-link">
426
+ Built with anycoder <i class="fa-solid fa-arrow-up-right-from-square" style="font-size: 0.7em;"></i>
427
  </a>
428
+ <button class="action-btn" id="toggle-terminal-btn" title="Toggle Settings Panel">
429
+ <i class="fa-solid fa-sliders"></i>
430
+ </button>
431
+ <button class="action-btn hidden" id="toggle-sidebar-btn" title="Toggle History">
432
+ <i class="fa-solid fa-bars"></i>
433
+ </button>
434
  </div>
435
  </header>
436
 
437
+ <div class="main-container">
438
+ <!-- Mobile Overlay -->
439
+ <div class="mobile-overlay" id="mobile-overlay"></div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
440
 
441
+ <!-- Sidebar -->
442
+ <aside class="sidebar" id="sidebar">
443
+ <div class="sidebar-header">
444
+ <button class="btn-new-chat" onclick="createNewConversation()">
445
+ <i class="fa-solid fa-plus"></i> New Conversation
446
+ </button>
447
+ </div>
448
+ <div class="history-list" id="history-list">
449
+ <!-- History Items Injected via JS -->
450
+ </div>
451
+ <div class="sidebar-footer">
452
+ <button class="btn-import" onclick="importConversation()">
453
+ <i class="fa-solid fa-file-import"></i> Import JSON
454
+ </button>
455
+ </div>
456
+ </aside>
457
+
458
+ <!-- Main Chat Area -->
459
+ <main class="chat-area">
460
+ <div class="chat-header">
461
+ <div class="model-indicator">
462
+ <i class="fa-solid fa-microchip" style="color: var(--primary);"></i>
463
+ <span id="current-model-display">Llama-3-8B</span>
464
+ <span class="badge" id="focus-mode-badge">Focus: OFF</span>
465
  </div>
466
+ <div>
467
+ <button class="action-btn" onclick="toggleFocusMode()" title="Toggle Focus Mode">
468
+ <i class="fa-solid fa-crosshairs"></i> Focus
469
+ </button>
 
 
470
  </div>
471
+ </div>
472
 
473
+ <div class="chat-messages" id="chat-messages">
474
+ <!-- Messages Injected via JS -->
475
+ </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
476
 
477
+ <div class="input-area">
478
+ <div class="input-wrapper">
479
+ <textarea class="chat-input" id="user-input" placeholder="Type a message... (Shift+Enter for new line)"></textarea>
480
+ <button class="send-btn" onclick="sendMessage()"><i class="fa-solid fa-paper-plane"></i></button>
481
  </div>
482
+ <!-- Editable Suggestions Area -->
483
+ <div class="mt-2 text-xs text-muted flex justify-between" style="margin-top:8px;">
484
+ <span>Suggestions:</span>
485
+ <div id="suggestions" class="flex gap-2">
486
+ <span class="cursor-pointer hover:text-primary" onclick="fillInput('Explain quantum entanglement')">Explain quantum entanglement</span>
487
+ <span class="cursor-pointer hover:text-primary" onclick="fillInput('Generate a Python class for User')">Generate Python Class</span>
 
 
 
 
 
 
488
  </div>
489
  </div>
490
+ </div>
491
+ </main>
492
+
493
+ <!-- Right Panel (Models & Tools) -->
494
+ <aside class="right-panel" id="right-panel">
495
+ <!-- Model Showcase -->
496
+ <div class="panel-section">
497
+ <div class="panel-title"><i class="fa-solid fa-layer-group"></i> Model Showcase</div>
498
+ <div id="model-list">
499
+ <!-- Models injected JS -->
500
+ </div>
501
+ </div>
502
 
503
+ <!-- Configuration & Downloads -->
504
+ <div class="panel-section">
505
+ <div class="panel-title"><i class="fa-solid fa-gears"></i> Configuration & API</div>
506
+ <div class="form-group">
507
+ <label>WebApp Folder Path (:/)</label>
508
+ <input type="text" class="form-input" value=":/app/models" id="app-path">
509
  </div>
510
+ <div class="form-group">
511
+ <label>Download Destination</label>
512
+ <input type="text" class="form-input" value="~/Downloads/" id="dl-path">
 
 
513
  </div>
514
+ <button class="btn-download" onclick="startDownloadProcess()">
515
+ <i class="fa-solid fa-cloud-arrow-down"></i> Fetch & Download Models
516
+ </button>
517
+ <button class="btn-secondary" style="margin-top:8px;" onclick="simulateAutoConfig()">
518
+ <i class="fa-solid fa-wand-magic-sparkles"></i> Auto Config App
519
+ </button>
520
+ </div>
521
 
522
+ <!-- Simulated Terminal -->
523
+ <div class="panel-section">
524
+ <div class="panel-title">
525
+ <i class="fa-solid fa-terminal"></i> System Terminal (Bash)
526
+ <span style="margin-left:auto; font-size:0.6em; cursor:pointer;" onclick="clearTerminal()">Clear</span>
527
  </div>
528
+ <div class="terminal" id="terminal-output">
529
+ <div class="terminal-line info">> System initialized...</div>
530
+ <div class="terminal-line info">> Ready for commands.</div>
 
 
 
 
 
531
  </div>
532
+ </div>
533
+ </aside>
534
+ </div>
535
 
536
+ <!-- Toast Notification -->
537
+ <div class="toast" id="toast">
538
+ <i class="fa-solid fa-circle-check" style="color:var(--primary)"></i>
539
+ <span id="toast-msg">Operation Successful</span>
540
+ </div>
 
541
 
542
+ <script>
543
+ // --- STATE MANAGEMENT ---
544
+ const state = {
545
+ conversations: [],
546
+ currentConversationId: null,
547
+ models: [
548
+ { id: 'llama-3', name: 'Llama-3-8B', type: 'Instruct', size: '4.7GB', desc: 'General purpose assistant.' },
549
+ { id: 'mistral', name: 'Mistral-7B', type: 'Creative', size: '4.1GB', desc: 'Good for creative writing.' },
550
+ { id: 'falcon', name: 'Falcon-40B', type: 'Logic', size: '80GB', desc: 'Advanced reasoning.' },
551
+ { id: 'bert', name: 'BERT-Large', type: 'NLP', size: '1.2GB', desc: 'Text classification & embeddings.' }
552
+ ],
553
+ currentModel: 'llama-3',
554
+ focusMode: false,
555
+ appPath: ':/app/models',
556
+ dlPath: '~/Downloads/'
557
+ };
558
+
559
+ // --- INITIALIZATION ---
560
+ document.addEventListener('DOMContentLoaded', () => {
561
+ loadFromStorage();
562
+
563
+ if (state.conversations.length === 0) {
564
+ createNewConversation(true);
565
+ } else {
566
+ loadConversation(state.conversations[0].id);
567
+ }
568
+
569
+ renderModelList();
570
+ renderHistoryList();
571
+ checkResponsive();
572
+
573
+ // Auto-refresh simulation (AJAX polling visual)
574
+ setInterval(() => {
575
+ if(Math.random() > 0.95) {
576
+ logTerminal(`> Checking HuggingFace API for updates...`, 'info');
577
+ }
578
+ }, 15000);
579
+
580
+ // Textarea auto-resize
581
+ const ta = document.getElementById('user-input');
582
+ ta.addEventListener('input', function() {
583
+ this.style.height = 'auto';
584
+ this.style.height = (this.scrollHeight) + 'px';
585
+ });
586
 
587
+ // Handle Enter key
588
+ ta.addEventListener('keydown', function(e) {
589
+ if (e.key === 'Enter' && !e.shiftKey) {
590
+ e.preventDefault();
591
+ sendMessage();
592
+ }
593
+ });
594
 
595
+ // Handle window resize
596
+ window.addEventListener('resize', checkResponsive);
597
+
598
+ // Button Listeners
599
+ document.getElementById('toggle-terminal-btn').addEventListener('click', () => {
600
+ const panel = document.getElementById('right-panel');
601
+ if (window.innerWidth <= 1024) {
602
+ panel.classList.toggle('open');
603
+ } else {
604
+ if (panel.style.width === '0px') {
605
+ panel.style.width = '320px'; panel.style.opacity = '1'; panel.style.padding = '0';
606
+ } else {
607
+ panel.style.width = '0px'; panel.style.opacity = '0'; panel.style.overflow = 'hidden'; panel.style.padding = '0';
608
  }
609
+ }
610
+ });
 
 
 
 
 
 
611
 
612
+ document.getElementById('toggle-sidebar-btn').addEventListener('click', () => {
613
+ document.getElementById('sidebar').classList.toggle('open');
614
+ document.getElementById('mobile-overlay').classList.toggle('active');
615
+ });
616
+
617
+ document.getElementById('mobile-overlay').addEventListener('click', () => {
618
+ document.getElementById('sidebar').classList.remove('open');
619
+ document.getElementById('mobile-overlay').classList.remove('active');
620
+ });
621
+ });
622
 
623
+ function checkResponsive() {
624
+ const toggleBtn = document.getElementById('toggle-sidebar-btn');
625
+ if (window.innerWidth <= 768) {
626
+ toggleBtn.classList.remove('hidden');
627
+ } else {
628
+ toggleBtn.classList.add('hidden');
629
+ document.getElementById('sidebar').classList.remove('open');
630
+ document.getElementById('mobile-overlay').classList.remove('active');
631
+ }
632
+ }
633
 
634
+ // --- CORE LOGIC ---
 
 
 
635
 
636
+ function createNewConversation(isFirst = false) {
637
+ const newId = Date.now().toString();
638
+ const currentModelObj = state.models.find(m => m.id === state.currentModel);
639
 
640
+ const newConv = {
641
+ id: newId,
642
+ name: isFirst ? 'New Conversation' : `Conversation ${state.conversations.length + 1}`,
643
+ model: state.currentModel,
644
+ messages: []
645
+ };
646
+
647
+ // Pre-suggestion based on model
648
+ if (currentModelObj) {
649
+ newConv.messages.push({
650
+ role: 'system',
651
+ content: `Switched to ${currentModelObj.name}. ${currentModelObj.desc} Suggestion: Try asking for a summary or creative story.`
652
+ });
653
  }
654
 
655
+ state.conversations.unshift(newConv);
656
+ state.currentConversationId = newId;
657
+ saveToStorage();
658
+ renderHistoryList();
659
+ renderChat();
660
 
661
+ if(!isFirst) showToast("New Conversation Created");
662
+
663
+ // Close sidebar on mobile if open
664
+ if(window.innerWidth <= 768) {
665
+ document.getElementById('sidebar').classList.remove('open');
666
+ document.getElementById('mobile-overlay').classList.remove('active');
667
+ }
668
+ }
669
 
670
+ function loadConversation(id) {
671
+ state.currentConversationId = id;
672
+ const conv = state.conversations.find(c => c.id === id);
673
+ if (conv) {
674
+ // Update current model to match the conversation's model
675
+ if (conv.model && state.models.find(m => m.id === conv.model)) {
676
+ state.currentModel = conv.model;
677
+ document.getElementById('current-model-display').innerText = state.models.find(m => m.id === conv.model).name;
678
+ renderModelList();
679
+ }
680
+ renderChat();
681
+ renderHistoryList();
682
+ }
683
+ }
684
 
685
+ function deleteConversation(id, e) {
686
+ e.stopPropagation();
687
+ if(confirm("Delete this conversation?")) {
688
+ state.conversations = state.conversations.filter(c => c.id !== id);
689
+ if (state.conversations.length === 0) {
690
+ createNewConversation();
691
+ } else {
692
+ loadConversation(state.conversations[0].id);
693
+ }
694
+ saveToStorage();
695
+ renderHistoryList();
696
+ }
697
+ }
698
 
699
+ function updateConversationName(id, newName) {
700
+ const conv = state.conversations.find(c => c.id === id);
701
+ if (conv) {
702
+ conv.name = newName;
703
+ saveToStorage();
704
+ renderHistoryList();
 
 
 
 
705
  }
706
+ }
707
 
708
+ function sendMessage() {
709
+ const input = document.getElementById('user-input');
710
+ const text = input.value.trim();
711
+ if (!text) return;
712
 
713
+ const conv = state.conversations.find(c => c.id === state.currentConversationId);
714
+ if (!conv) return;
715
+
716
+ // Add User Message
717
+ conv.messages.push({ role: 'user', content: text });
718
+ input.value = '';
719
+ input.style.height = 'auto';
720
+ saveToStorage();
721
+ renderChat();
722
+
723
+ // Show typing indicator
724
+ const typingId = 'typing-' + Date.now();
725
+ addTypingIndicator(typingId);
726
+
727
+ // Simulate AI Response
728
+ setTimeout(() => {
729
+ removeTypingIndicator(typingId);
730
+ const aiResponse = generateSimulatedResponse(text);
731
+ conv.messages.push({ role: 'ai', content: aiResponse });
732
+ saveToStorage();
733
+ renderChat();
734
+ }, 1000 + Math.random() * 1000);
735
+ }
736
+
737
+ function switchModel(modelId) {
738
+ state.currentModel = modelId;
739
+ const model = state.models.find(m => m.id === modelId);
740
+
741
+ // Update UI
742
+ document.getElementById('current-model-display').innerText = model.name;
743
+ renderModelList();
744
+
745
+ // Add intro suggestion to current chat
746
+ const conv = state.conversations.find(c => c.id === state.currentConversationId);
747
+ if (conv) {
748
+ conv.model = modelId;
749
+ conv.messages.push({
750
+ role: 'system',
751
+ content: `Model switched to ${model.name}. Intro suggestion: This model is optimized for ${model.type} tasks.`
752
  });
753
+ saveToStorage();
754
+ renderChat();
755
+ }
756
+ showToast(`Switched to ${model.name}`);
757
+ }
758
 
759
+ function toggleFocusMode() {
760
+ state.focusMode = !state.focusMode;
761
+ const badge = document.getElementById('focus-mode-badge');
762
+ const body = document.body;
763
+
764
+ if (state.focusMode) {
765
+ badge.classList.add('active');
766
+ badge.innerText = 'Focus: ON';
767
+ body.classList.add('focus-mode');
768
+ showToast("Focus Mode Enabled");
769
+ } else {
770
+ badge.classList.remove('active');
771
+ badge.innerText = 'Focus: OFF';
772
+ body.classList.remove('focus-mode');
773
+ showToast("Focus Mode Disabled");
774
+ }
775
+ }
776
 
777
+ function importConversation() {
778
+ const input = document.createElement('input');
779
+ input.type = 'file';
780
+ input.accept = '.json';
781
+ input.onchange = e => {
782
+ const file = e.target.files[0];
783
+ if (file) {
784
+ const reader = new FileReader();
785
+ reader.onload = function(e) {
786
+ try {
787
+ const imported = JSON.parse(e.target.result);
788
+ // Ensure it has basic structure
789
+ if(!imported.messages) imported.messages = [];
790
+ if(!imported.name) imported.name = file.name;
791
+
792
+ imported.id = Date.now().toString();
793
+ state.conversations.unshift(imported);
794
+ saveToStorage();
795
+ renderHistoryList();
796
+ loadConversation(imported.id);
797
+ showToast("Conversation Imported Successfully");
798
+ logTerminal(`> Imported ${file.name} to repository.`, 'info');
799
+ } catch (err) {
800
+ showToast("Invalid JSON file");
801
+ logTerminal(`> Error importing file: ${err.message}`, 'error');
802
+ }
803
+ };
804
+ reader.readAsText(file);
805
+ }
806
+ };
807
+ input.click();
808
+ }
809
+
810
+ // --- RENDER FUNCTIONS ---
811
+
812
+ function renderHistoryList() {
813
+ const list = document.getElementById('history-list');
814
+ list.innerHTML = '';
815
+ state.conversations.forEach(conv => {
816
+ const div = document.createElement('div');
817
+ div.className = `history-item ${conv.id === state.currentConversationId ? 'active' : ''}`;
818
+ div.onclick = () => loadConversation(conv.id);
819
+ div.innerHTML = `
820
+ <div class="history-name" contenteditable="true" onblur="updateConversationName('${conv.id}', this.innerText)">${conv.name}</div>
821
+ <div class="history-actions">
822
+ <i class="fa-solid fa-trash" onclick="deleteConversation('${conv.id}', event)"></i>
823
+ </div>
824
+ `;
825
+ list.appendChild(div);
826
+ });
827
+ }
828
 
829
+ function renderChat() {
830
+ const container = document.getElementById('chat-messages');
831
+ const conv = state.conversations.find(c => c.id === state.currentConversationId);
832
+ container.innerHTML = '';
833
+
834
+ if (!conv) return;
835
 
836
+ conv.messages.forEach(msg => {
837
+ const div = document.createElement('div');
838
+ div.className = `message ${msg.role}`;
 
 
839
 
840
+ let contentHtml = escapeHtml(msg.content);
841
+ // Simple code block formatting
842
+ if(contentHtml.includes('```')) {
843
+ contentHtml = contentHtml.replace(/```([\s\S]*?)```/g, '<div style="background:#000; padding:8px; border-radius:4px; margin:5px 0; font-family:monospace; overflow-x:auto;"><code>$1</code></div>');
844
+ }
845
+
846
+ div.innerHTML = `
847
+ <div class="msg-actions">
848
+ <button class="action-btn" onclick="copyMessage(this)" title="Copy">
849
+ <i class="fa-regular fa-copy"></i>
850
+ </button>
851
+ <button class="action-btn" onclick="pasteToInput(this)" title="Paste to Input">
852
+ <i class="fa-solid fa-paste"></i>
853
+ </button>
854
+ </div>
855
+ <div class="bubble">${contentHtml}</div>
856
+ `;
857
+ container.appendChild(div);
858
+ });
859
+
860
+ container.scrollTop = container.scrollHeight;
861
+ }
862
+
863
+ function renderModelList() {
864
+ const list = document.getElementById('model-list');
865
+ list.innerHTML = '';
866
+ state.models.forEach(model => {
867
+ const div = document.createElement('div');
868
+ div.className = `model-card ${model.id === state.currentModel ? 'active' : ''}`;
869
+ div.onclick = () => switchModel(model.id);
870
+ div.innerHTML = `
871
+ <div class="model-header">
872
+ <span class="model-name">${model.name}</span>
873
+ <i class="fa-solid fa-check" style="opacity: ${model.id === state.currentModel ? 1 : 0}; color: var(--primary);"></i>
874
+ </div