mbmal commited on
Commit
29e58e3
·
verified ·
1 Parent(s): 46e58e9

мне нужен портал проекта Технозаметки Малышева (канал в телеграме @tsingular)

Browse files

темный кибер стиль.
удобная CMS для добавления новых разделов и статей.
база данных на SQLite локальная
будут и новости технологий и обучения и каталог полезных ссылок, записи докладов, демо приложений и ИИ чат бот ассистент справа внизу, которому можно задать вопросы по порталу, записаться на консультацию.
продумай профессиональную красивую современную структуру в едином стиле.

Files changed (7) hide show
  1. README.md +7 -4
  2. components/ai-assistant.js +326 -0
  3. components/footer.js +153 -0
  4. components/navbar.js +192 -0
  5. index.html +134 -19
  6. script.js +207 -0
  7. style.css +289 -19
README.md CHANGED
@@ -1,10 +1,13 @@
1
  ---
2
- title: Singularity Nexus Portal
3
- emoji: 📉
4
- colorFrom: indigo
5
  colorTo: blue
 
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
1
  ---
2
+ title: Singularity Nexus Portal 🚀
3
+ colorFrom: green
 
4
  colorTo: blue
5
+ emoji: 🐳
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite-v3
10
  ---
11
 
12
+ # Welcome to your new DeepSite project!
13
+ This project was created with [DeepSite](https://huggingface.co/deepsite).
components/ai-assistant.js ADDED
@@ -0,0 +1,326 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class AIAssistant extends HTMLElement {
2
+ constructor() {
3
+ super();
4
+ this.isOpen = false;
5
+ this.messages = [];
6
+ }
7
+
8
+ connectedCallback() {
9
+ this.attachShadow({ mode: 'open' });
10
+ this.render();
11
+ this.setupEventListeners();
12
+ this.loadInitialMessage();
13
+ }
14
+
15
+ render() {
16
+ this.shadowRoot.innerHTML = `
17
+ <style>
18
+ :host {
19
+ display: block;
20
+ position: fixed;
21
+ bottom: 20px;
22
+ right: 20px;
23
+ z-index: 1000;
24
+ }
25
+
26
+ .ai-toggle-button {
27
+ width: 60px;
28
+ height: 60px;
29
+ border-radius: 50%;
30
+ background: linear-gradient(45deg, #00ff88, #00a2ff);
31
+ border: none;
32
+ color: #050508;
33
+ cursor: pointer;
34
+ box-shadow: 0 5px 20px rgba(0, 255, 136, 0.4);
35
+ transition: all 0.3s ease;
36
+ display: flex;
37
+ align-items: center;
38
+ justify-content: center;
39
+ font-size: 1.5rem;
40
+ }
41
+
42
+ .ai-toggle-button:hover {
43
+ transform: scale(1.1);
44
+ box-shadow: 0 8px 25px rgba(0, 255, 136, 0.6);
45
+ }
46
+
47
+ .ai-chat-window {
48
+ position: absolute;
49
+ bottom: 70px;
50
+ right: 0;
51
+ width: 350px;
52
+ height: 500px;
53
+ background: #0a0a0f;
54
+ border: 1px solid #00ff88;
55
+ border-radius: 12px;
56
+ box-shadow: 0 10px 40px rgba(0, 255, 136, 0.3);
57
+ display: none;
58
+ flex-direction: column;
59
+ }
60
+
61
+ .ai-chat-window.active {
62
+ display: flex;
63
+ }
64
+
65
+ .ai-chat-header {
66
+ padding: 16px;
67
+ background: linear-gradient(45deg, #00ff88, #00a2ff);
68
+ border-radius: 12px 12px 0 0;
69
+ color: #050508;
70
+ font-weight: 600;
71
+ display: flex;
72
+ justify-content: space-between;
73
+ align-items: center;
74
+ }
75
+
76
+ .ai-chat-messages {
77
+ flex: 1;
78
+ padding: 16px;
79
+ overflow-y: auto;
80
+ display: flex;
81
+ flex-direction: column;
82
+ gap: 12px;
83
+ }
84
+
85
+ .ai-message {
86
+ padding: 12px;
87
+ border-radius: 8px;
88
+ max-width: 80%;
89
+ word-wrap: break-word;
90
+ }
91
+
92
+ .ai-message.user {
93
+ align-self: flex-end;
94
+ background: linear-gradient(45deg, #00a2ff, #00ff88);
95
+ color: #050508;
96
+ }
97
+
98
+ .ai-message.assistant {
99
+ align-self: flex-start;
100
+ background: #1a1a2e;
101
+ border: 1px solid #2a2a3e;
102
+ }
103
+
104
+ .ai-chat-input {
105
+ padding: 16px;
106
+ border-top: 1px solid #2a2a3e;
107
+ display: flex;
108
+ gap: 8px;
109
+ }
110
+
111
+ .ai-chat-input input {
112
+ flex: 1;
113
+ padding: 8px 12px;
114
+ background: #1a1a2e;
115
+ border: 1px solid #2a2a3e;
116
+ border-radius: 6px;
117
+ color: white;
118
+ }
119
+
120
+ .ai-chat-input button {
121
+ padding: 8px 16px;
122
+ background: #00ff88;
123
+ border: none;
124
+ border-radius: 6px;
125
+ color: #050508;
126
+ font-weight: 600;
127
+ cursor: pointer;
128
+ }
129
+
130
+ @media (max-width: 768px) {
131
+ .ai-chat-window {
132
+ width: 300px;
133
+ height: 400px;
134
+ right: -50px;
135
+ }
136
+ }
137
+ </style>
138
+
139
+ <div class="ai-assistant-container">
140
+ <button class="ai-toggle-button">
141
+ <i data-feather="message-circle"></i>
142
+ </button>
143
+
144
+ <div class="ai-chat-window">
145
+ <div class="ai-chat-header">
146
+ <span>AI Ассистент Nexus</span>
147
+ <button class="close-button">
148
+ <i data-feather="x"></i>
149
+ </button>
150
+ </div>
151
+
152
+ <div class="ai-chat-messages" id="chat-messages">
153
+ <!-- Messages will be added here -->
154
+ </div>
155
+
156
+ <div class="ai-chat-input">
157
+ <input type="text" id="chat-input" placeholder="Задайте вопрос...">
158
+ <button id="send-button">
159
+ <i data-feather="send"></i>
160
+ </button>
161
+ </div>
162
+ </div>
163
+ </div>
164
+ `;
165
+
166
+ setTimeout(() => {
167
+ if (typeof feather !== 'undefined') {
168
+ feather.replace();
169
+ }
170
+ }, 100);
171
+ }
172
+
173
+ setupEventListeners() {
174
+ const toggleButton = this.shadowRoot.querySelector('.ai-toggle-button');
175
+ const closeButton = this.shadowRoot.querySelector('.close-button');
176
+ const sendButton = this.shadowRoot.querySelector('#send-button');
177
+ const chatInput = this.shadowRoot.querySelector('#chat-input');
178
+
179
+ if (toggleButton) {
180
+ toggleButton.addEventListener('click', () => {
181
+ this.toggleChat();
182
+ });
183
+ }
184
+
185
+ if (closeButton) {
186
+ closeButton.addEventListener('click', () => {
187
+ this.closeChat();
188
+ });
189
+ }
190
+
191
+ if (sendButton && chatInput) {
192
+ sendButton.addEventListener('click', () => {
193
+ this.sendMessage();
194
+ });
195
+
196
+ chatInput.addEventListener('keypress', (e) => {
197
+ if (e.key === 'Enter') {
198
+ this.sendMessage();
199
+ }
200
+ });
201
+ }
202
+ }
203
+
204
+ loadInitialMessage() {
205
+ const welcomeMessage = {
206
+ type: 'assistant',
207
+ text: 'Привет! Я ваш AI ассистент Nexus. Могу помочь с информацией о портале, записать на консультацию или ответить на вопросы о технологиях. Чем могу помочь?'
208
+ };
209
+
210
+ this.addMessage(welcomeMessage);
211
+ }
212
+
213
+ toggleChat() {
214
+ this.isOpen = !this.isOpen;
215
+ const chatWindow = this.shadowRoot.querySelector('.ai-chat-window');
216
+
217
+ if (chatWindow) {
218
+ chatWindow.classList.toggle('active', this.isOpen);
219
+ if (this.isOpen) {
220
+ const input = this.shadowRoot.querySelector('#chat-input');
221
+ if (input) {
222
+ input.focus();
223
+ }
224
+ }
225
+ }
226
+
227
+ closeChat() {
228
+ this.isOpen = false;
229
+ const chatWindow = this.shadowRoot.querySelector('.ai-chat-window');
230
+ if (chatWindow) {
231
+ chatWindow.classList.remove('active');
232
+ }
233
+ }
234
+
235
+ async sendMessage() {
236
+ const input = this.shadowRoot.querySelector('#chat-input');
237
+ if (!input || !input.value.trim()) return;
238
+
239
+ const userMessage = {
240
+ type: 'user',
241
+ text: input.value.trim()
242
+ };
243
+
244
+ this.addMessage(userMessage);
245
+ const userText = input.value;
246
+ input.value = '';
247
+
248
+ // Simulate AI response
249
+ this.simulateAIResponse(userText);
250
+ }
251
+
252
+ async simulateAIResponse(userMessage) {
253
+ // Show typing indicator
254
+ this.showTypingIndicator();
255
+
256
+ // Simulate API call delay
257
+ setTimeout(async () => {
258
+ this.hideTypingIndicator();
259
+
260
+ let responseText = '';
261
+
262
+ if (userMessage.toLowerCase().includes('консультация') || userMessage.toLowerCase().includes('запись')) {
263
+ responseText = 'Отлично! Для записи на консультацию перейдите в раздел "Консультации" или свяжитесь напрямую через Telegram @tsingular. Хотите, чтобы я открыл соответствующий раздел?';
264
+ } else if (userMessage.toLowerCase().includes('новости')) {
265
+ responseText = 'В разделе "Новости" вы найдете свежие технологические тренды, аналитику и инсайты от Алексея Малышева.';
266
+ } else if (userMessage.toLowerCase().includes('обучение')) {
267
+ responseText = 'Раздел "Обучение" содержит образовательные материалы, курсы и руководства по современным технологиям.';
268
+ } else {
269
+ responseText = 'Интересный вопрос! Я могу помочь с информацией о различных разделах портала, технологиях или ор��анизации консультации. Что именно вас интересует?';
270
+ }
271
+
272
+ const assistantMessage = {
273
+ type: 'assistant',
274
+ text: responseText
275
+ };
276
+
277
+ this.addMessage(assistantMessage);
278
+ }, 1500);
279
+ }
280
+
281
+ showTypingIndicator() {
282
+ const messagesContainer = this.shadowRoot.querySelector('#chat-messages');
283
+ if (messagesContainer) {
284
+ const typingElement = document.createElement('div');
285
+ typingElement.className = 'ai-message assistant typing-indicator';
286
+ typingElement.innerHTML = '<div class="typing-dots"><span></span><span></span><span></span></div>';
287
+ messagesContainer.appendChild(typingElement);
288
+ messagesContainer.scrollTop = messagesContainer.scrollHeight;
289
+ }
290
+
291
+ hideTypingIndicator() {
292
+ const messagesContainer = this.shadowRoot.querySelector('#chat-messages');
293
+ if (messagesContainer) {
294
+ const typingElement = messagesContainer.querySelector('.typing-indicator');
295
+ if (typingElement) {
296
+ typingElement.remove();
297
+ }
298
+ }
299
+ }
300
+
301
+ addMessage(message) {
302
+ const messagesContainer = this.shadowRoot.querySelector('#chat-messages');
303
+ if (messagesContainer) {
304
+ const messageElement = document.createElement('div');
305
+ messageElement.className = `ai-message ${message.type}`;
306
+ messageElement.textContent = message.text;
307
+ messagesContainer.appendChild(messageElement);
308
+ messagesContainer.scrollTop = messagesContainer.scrollHeight;
309
+ }
310
+ }
311
+ }
312
+
313
+ customElements.define('ai-assistant', AIAssistant);
314
+
315
+ // Global AI Assistant functions
316
+ function initializeAIAssistant() {
317
+ // AI Assistant is already initialized by the component
318
+ console.log('AI Assistant initialized');
319
+ }
320
+
321
+ function toggleAIAssistant() {
322
+ const assistant = document.querySelector('ai-assistant');
323
+ if (assistant) {
324
+ assistant.toggleChat();
325
+ }
326
+ }
components/footer.js ADDED
@@ -0,0 +1,153 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class CustomFooter extends HTMLElement {
2
+ constructor() {
3
+ super();
4
+ }
5
+
6
+ connectedCallback() {
7
+ this.attachShadow({ mode: 'open' });
8
+ this.render();
9
+ }
10
+
11
+ render() {
12
+ this.shadowRoot.innerHTML = `
13
+ <style>
14
+ :host {
15
+ display: block;
16
+ width: 100%;
17
+ }
18
+
19
+ .footer {
20
+ background: #050508;
21
+ border-top: 1px solid #00a2ff;
22
+ padding: 3rem 0 2rem;
23
+ margin-top: 4rem;
24
+ }
25
+
26
+ .footer-content {
27
+ max-width: 1200px;
28
+ margin: 0 auto;
29
+ padding: 0 1rem;
30
+ }
31
+
32
+ .footer-grid {
33
+ display: grid;
34
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
35
+ gap: 2rem;
36
+ margin-bottom: 2rem;
37
+ }
38
+
39
+ .footer-section h3 {
40
+ font-family: Orbitron, monospace;
41
+ color: #00ff88;
42
+ margin-bottom: 1rem;
43
+ font-size: 1.125rem;
44
+ }
45
+
46
+ .footer-links {
47
+ display: flex;
48
+ flex-direction: column;
49
+ gap: 0.5rem;
50
+ }
51
+
52
+ .footer-link {
53
+ color: #94a3b8;
54
+ text-decoration: none;
55
+ transition: color 0.3s ease;
56
+ }
57
+
58
+ .footer-link:hover {
59
+ color: #00ff88;
60
+ }
61
+
62
+ .footer-bottom {
63
+ border-top: 1px solid #1a1a2e;
64
+ padding-top: 2rem;
65
+ text-align: center;
66
+ color: #64748b;
67
+ }
68
+
69
+ .social-links {
70
+ display: flex;
71
+ gap: 1rem;
72
+ margin-top: 1rem;
73
+ }
74
+
75
+ .social-link {
76
+ width: 40px;
77
+ height: 40px;
78
+ border-radius: 8px;
79
+ background: #1a1a2e;
80
+ display: flex;
81
+ align-items: center;
82
+ justify-content: center;
83
+ transition: all 0.3s ease;
84
+ }
85
+
86
+ .social-link:hover {
87
+ background: #00ff88;
88
+ color: #050508;
89
+ transform: translateY(-2px);
90
+ }
91
+ </style>
92
+
93
+ <footer class="footer">
94
+ <div class="footer-content">
95
+ <div class="footer-grid">
96
+ <div class="footer-section">
97
+ <h3>Singularity Nexus</h3>
98
+ <p class="text-gray-400">
99
+ Технологический портал Алексея Малышева.
100
+ Исследования, инсайты и трансформации цифрового мира.
101
+ </p>
102
+ <div class="social-links">
103
+ <a href="https://t.me/tsingular" class="social-link" target="_blank">
104
+ <i data-feather="send"></i>
105
+ </a>
106
+ <a href="#" class="social-link">
107
+ <i data-feather="youtube"></i>
108
+ </a>
109
+ <a href="#" class="social-link">
110
+ <i data-feather="github"></i>
111
+ </a>
112
+ </div>
113
+ </div>
114
+
115
+ <div class="footer-section">
116
+ <h3>Разделы</h3>
117
+ <div class="footer-links">
118
+ <a href="/news" class="footer-link">Новости технологий</a>
119
+ <a href="/learning" class="footer-link">Образовательные курсы</a>
120
+ <a href="/resources" class="footer-link">Полезные ресурсы</a>
121
+ <a href="/talks" class="footer-link">Записи докладов</a>
122
+ <a href="/demos" class="footer-link">Демо проекты</a>
123
+ </div>
124
+ </div>
125
+
126
+ <div class="footer-section">
127
+ <h3>Поддержка</h3>
128
+ <div class="footer-links">
129
+ <a href="/consultation" class="footer-link">Консультации</a>
130
+ <a href="/about" class="footer-link">О проекте</a>
131
+ <a href="/contact" class="footer-link">Контакты</a>
132
+ <a href="/privacy" class="footer-link">Политика конфиденциальности</a>
133
+ </div>
134
+ </div>
135
+ </div>
136
+
137
+ <div class="footer-bottom">
138
+ <p>&copy; 2024 Singularity Nexus. Все права в цифровом пространстве.</p>
139
+ </div>
140
+ </div>
141
+ </footer>
142
+ `;
143
+
144
+ // Replace feather icons after rendering
145
+ setTimeout(() => {
146
+ if (typeof feather !== 'undefined') {
147
+ feather.replace();
148
+ }
149
+ }, 100);
150
+ }
151
+ }
152
+
153
+ customElements.define('custom-footer', CustomFooter);
components/navbar.js ADDED
@@ -0,0 +1,192 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class CustomNavbar extends HTMLElement {
2
+ constructor() {
3
+ super();
4
+ }
5
+
6
+ connectedCallback() {
7
+ this.attachShadow({ mode: 'open' });
8
+ this.render();
9
+ this.setupEventListeners();
10
+ }
11
+
12
+ render() {
13
+ this.shadowRoot.innerHTML = `
14
+ <style>
15
+ :host {
16
+ display: block;
17
+ width: 100%;
18
+ }
19
+
20
+ .navbar {
21
+ background: rgba(10, 10, 15, 0.95);
22
+ backdrop-filter: blur(10px);
23
+ border-bottom: 1px solid #00ff88;
24
+ padding: 1rem 0;
25
+ position: sticky;
26
+ top: 0;
27
+ z-index: 100;
28
+ }
29
+
30
+ .nav-container {
31
+ max-width: 1200px;
32
+ margin: 0 auto;
33
+ padding: 0 1rem;
34
+ display: flex;
35
+ justify-content: space-between;
36
+ align-items: center;
37
+ }
38
+
39
+ .nav-brand {
40
+ display: flex;
41
+ align-items: center;
42
+ gap: 0.5rem;
43
+ text-decoration: none;
44
+ font-family: Orbitron, monospace;
45
+ font-weight: 700;
46
+ font-size: 1.25rem;
47
+ background: linear-gradient(45deg, #00ff88, #00a2ff);
48
+ background-clip: text;
49
+ -webkit-background-clip: text;
50
+ -webkit-text-fill-color: transparent;
51
+ }
52
+
53
+ .nav-menu {
54
+ display: flex;
55
+ gap: 2rem;
56
+ align-items: center;
57
+ }
58
+
59
+ .nav-link {
60
+ color: #e2e8f0;
61
+ text-decoration: none;
62
+ font-weight: 500;
63
+ transition: all 0.3s ease;
64
+ position: relative;
65
+ }
66
+
67
+ .nav-link:hover {
68
+ color: #00ff88;
69
+ }
70
+
71
+ .nav-link.active {
72
+ color: #00ff88;
73
+ }
74
+
75
+ .nav-link.active::after {
76
+ content: '';
77
+ position: absolute;
78
+ bottom: -8px;
79
+ left: 0;
80
+ width: 100%;
81
+ height: 2px;
82
+ background: #00ff88;
83
+ box-shadow: 0 0 8px #00ff88;
84
+ }
85
+
86
+ .mobile-menu-button {
87
+ display: none;
88
+ background: none;
89
+ border: none;
90
+ color: #00ff88;
91
+ cursor: pointer;
92
+ }
93
+
94
+ @media (max-width: 768px) {
95
+ .nav-menu {
96
+ position: absolute;
97
+ top: 100%;
98
+ left: 0;
99
+ right: 0;
100
+ background: rgba(10, 10, 15, 0.95);
101
+ flex-direction: column;
102
+ padding: 1rem;
103
+ gap: 1rem;
104
+ display: none;
105
+ }
106
+
107
+ .nav-menu.active {
108
+ display: flex;
109
+ }
110
+
111
+ .mobile-menu-button {
112
+ display: block;
113
+ }
114
+ }
115
+ </style>
116
+
117
+ <nav class="navbar">
118
+ <div class="nav-container">
119
+ <a href="/" class="nav-brand">
120
+ <i data-feather="cpu"></i>
121
+ SINGULARITY
122
+ </a>
123
+
124
+ <button class="mobile-menu-button">
125
+ <i data-feather="menu"></i>
126
+ </button>
127
+
128
+ <div class="nav-menu">
129
+ <a href="/news" class="nav-link">
130
+ <i data-feather="zap" class="inline mr-1"></i>
131
+ Новости
132
+ </a>
133
+ <a href="/learning" class="nav-link">
134
+ <i data-feather="book-open" class="inline mr-1"></i>
135
+ Обучение
136
+ </a>
137
+ <a href="/resources" class="nav-link">
138
+ <i data-feather="link" class="inline mr-1"></i>
139
+ Ресурсы
140
+ </a>
141
+ <a href="/talks" class="nav-link">
142
+ <i data-feather="video" class="inline mr-1"></i>
143
+ Доклады
144
+ </a>
145
+ <a href="/demos" class="nav-link">
146
+ <i data-feather="code" class="inline mr-1"></i>
147
+ Демо
148
+ </a>
149
+ <a href="/admin" class="nav-link" data-auth="admin">
150
+ <i data-feather="settings" class="inline mr-1"></i>
151
+ Управление
152
+ </a>
153
+ </div>
154
+ </div>
155
+ </nav>
156
+ `;
157
+
158
+ // Replace feather icons after rendering
159
+ setTimeout(() => {
160
+ if (typeof feather !== 'undefined') {
161
+ feather.replace();
162
+ }
163
+ }, 100);
164
+ }
165
+
166
+ setupEventListeners() {
167
+ const mobileButton = this.shadowRoot.querySelector('.mobile-menu-button');
168
+ const navMenu = this.shadowRoot.querySelector('.nav-menu');
169
+
170
+ if (mobileButton) {
171
+ mobileButton.addEventListener('click', () => {
172
+ navMenu.classList.toggle('active');
173
+ mobileButton.innerHTML = navMenu.classList.contains('active') ?
174
+ '<i data-feather="x"></i>' :
175
+ '<i data-feather="menu"></i>';
176
+ feather.replace();
177
+ });
178
+ }
179
+
180
+ // Close mobile menu when clicking outside
181
+ document.addEventListener('click', (event) => {
182
+ if (!this.contains(event.target) && navMenu.classList.contains('active')) {
183
+ navMenu.classList.remove('active');
184
+ mobileButton.innerHTML = '<i data-feather="menu"></i>';
185
+ feather.replace();
186
+ }
187
+ });
188
+ }
189
+ }
190
+ }
191
+
192
+ customElements.define('custom-navbar', CustomNavbar);
index.html CHANGED
@@ -1,19 +1,134 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="ru" class="dark">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Singularity Nexus - Технозаметки Малышева</title>
7
+ <link rel="icon" type="image/x-icon" href="/static/favicon.ico">
8
+ <link rel="stylesheet" href="style.css">
9
+ <script src="https://cdn.tailwindcss.com"></script>
10
+ <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
11
+ <script src="https://unpkg.com/feather-icons"></script>
12
+ <script>
13
+ tailwind.config = {
14
+ darkMode: 'class',
15
+ theme: {
16
+ extend: {
17
+ colors: {
18
+ cyber: {
19
+ primary: '#00ff88',
20
+ secondary: '#00a2ff',
21
+ accent: '#ff0088',
22
+ dark: '#0a0a0f',
23
+ darker: '#050508',
24
+ gray: '#1a1a2e'
25
+ }
26
+ },
27
+ fontFamily: {
28
+ 'cyber': ['Orbitron', 'monospace'],
29
+ 'main': ['Inter', 'sans-serif']
30
+ }
31
+ }
32
+ }
33
+ }
34
+ </script>
35
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Orbitron:wght@400;500;700;900&display=swap" rel="stylesheet">
36
+ </head>
37
+ <body class="bg-cyber-dark text-white font-main min-h-screen">
38
+ <custom-navbar></custom-navbar>
39
+
40
+ <main class="container mx-auto px-4 py-8">
41
+ <!-- Hero Section -->
42
+ <section class="mb-16">
43
+ <div class="text-center">
44
+ <div class="cyber-glow mb-6">
45
+ <h1 class="text-5xl md:text-7xl font-cyber font-bold bg-gradient-to-r from-cyber-primary to-cyber-secondary bg-clip-text text-transparent">
46
+ SINGULARITY NEXUS
47
+ </h1>
48
+ </div>
49
+ <p class="text-xl md:text-2xl text-gray-300 mb-8 max-w-3xl mx-auto">
50
+ Портал технологических инсайтов и цифровых трансформаций от Алексея Малышева
51
+ </p>
52
+ <div class="flex flex-wrap justify-center gap-4">
53
+ <a href="/news" class="cyber-button-primary px-8 py-3">
54
+ <i data-feather="zap" class="inline mr-2"></i>
55
+ Новости
56
+ </a>
57
+ <a href="/learning" class="cyber-button-secondary px-8 py-3">
58
+ <i data-feather="book-open" class="inline mr-2"></i>
59
+ Обучение
60
+ </a>
61
+ <a href="/resources" class="cyber-button-accent px-8 py-3">
62
+ <i data-feather="link" class="inline mr-2"></i>
63
+ Ресурсы
64
+ </a>
65
+ </div>
66
+ </div>
67
+ </section>
68
+
69
+ <!-- Featured Content Grid -->
70
+ <section class="mb-16">
71
+ <h2 class="text-3xl font-cyber mb-8 text-center">Фокус внимания</h2>
72
+ <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
73
+ <div class="cyber-card group">
74
+ <div class="cyber-card-header">
75
+ <i data-feather="trending-up" class="text-cyber-primary"></i>
76
+ <h3 class="text-xl font-cyber">Актуальные новости</h3>
77
+ </div>
78
+ <p class="text-gray-400 mb-4">Свежие технологические тренды и инсайты</p>
79
+ <a href="/news" class="cyber-link">Исследовать →</a>
80
+ </div>
81
+
82
+ <div class="cyber-card group">
83
+ <div class="cyber-card-header">
84
+ <i data-feather="graduation-cap" class="text-cyber-secondary"></i>
85
+ <h3 class="text-xl font-cyber">Образовательные материалы</h3>
86
+ </div>
87
+ <p class="text-gray-400 mb-4">Глубокие погружения в технологии будущего</p>
88
+ <a href="/learning" class="cyber-link">Учиться →</a>
89
+ </div>
90
+
91
+ <div class="cyber-card group">
92
+ <div class="cyber-card-header">
93
+ <i data-feather="cpu" class="text-cyber-accent"></i>
94
+ <h3 class="text-xl font-cyber">Демо проекты</h3>
95
+ </div>
96
+ <p class="text-gray-400 mb-4">Интерактивные примеры и прототипы</p>
97
+ <a href="/demos" class="cyber-link">Тестировать →</a>
98
+ </div>
99
+ </div>
100
+ </section>
101
+
102
+ <!-- Latest Updates -->
103
+ <section class="mb-16">
104
+ <h2 class="text-3xl font-cyber mb-8">Последние обновления</h2>
105
+ <div id="latest-updates" class="cyber-timeline">
106
+ <!-- Updates will be loaded dynamically -->
107
+ </div>
108
+ </section>
109
+ </main>
110
+
111
+ <custom-footer></custom-footer>
112
+
113
+ <!-- AI Assistant -->
114
+ <ai-assistant></ai-assistant>
115
+
116
+ <!-- Component Scripts -->
117
+ <script src="components/navbar.js"></script>
118
+ <script src="components/footer.js"></script>
119
+ <script src="components/ai-assistant.js"></script>
120
+
121
+ <!-- Main Script -->
122
+ <script src="script.js"></script>
123
+
124
+ <script>
125
+ feather.replace();
126
+ // Initialize AI assistant
127
+ document.addEventListener('DOMContentLoaded', function() {
128
+ initializeAIAssistant();
129
+ loadLatestUpdates();
130
+ });
131
+ </script>
132
+ <script src="https://huggingface.co/deepsite/deepsite-badge.js"></script>
133
+ </body>
134
+ </html>
script.js ADDED
@@ -0,0 +1,207 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Main application JavaScript
2
+ class SingularityPortal {
3
+ constructor() {
4
+ this.apiBase = '/api';
5
+ this.currentUser = null;
6
+ this.init();
7
+ }
8
+
9
+ init() {
10
+ this.setupEventListeners();
11
+ this.checkAuthStatus();
12
+ this.loadInitialData();
13
+ }
14
+
15
+ setupEventListeners() {
16
+ // Global event listeners
17
+ document.addEventListener('keydown', this.handleKeyboardShortcuts.bind(this));
18
+ }
19
+
20
+ handleKeyboardShortcuts(event) {
21
+ if (event.ctrlKey && event.key === 'k') {
22
+ event.preventDefault();
23
+ this.toggleAIAssistant();
24
+ }
25
+ }
26
+
27
+ async checkAuthStatus() {
28
+ try {
29
+ const response = await fetch(`${this.apiBase}/auth/status`);
30
+ if (response.ok) {
31
+ this.currentUser = await response.json();
32
+ this.updateUIForAuth();
33
+ }
34
+ } catch (error) {
35
+ console.log('Auth check failed:', error);
36
+ }
37
+ }
38
+
39
+ updateUIForAuth() {
40
+ const authElements = document.querySelectorAll('[data-auth]');
41
+ authElements.forEach(element => {
42
+ const authType = element.getAttribute('data-auth');
43
+ if (authType === 'required' && !this.currentUser) {
44
+ element.style.display = 'none';
45
+ } else if (authType === 'admin' && (!this.currentUser || !this.currentUser.isAdmin)) {
46
+ element.style.display = 'none';
47
+ }
48
+ });
49
+ }
50
+
51
+ async loadInitialData() {
52
+ await this.loadLatestUpdates();
53
+ }
54
+
55
+ async loadLatestUpdates() {
56
+ try {
57
+ const response = await fetch(`${this.apiBase}/content/latest`);
58
+ if (response.ok) {
59
+ const updates = await response.json();
60
+ this.renderLatestUpdates(updates);
61
+ }
62
+ } catch (error) {
63
+ console.log('Failed to load latest updates:', error);
64
+ }
65
+ }
66
+
67
+ renderLatestUpdates(updates) {
68
+ const container = document.getElementById('latest-updates');
69
+ if (!container) return;
70
+
71
+ container.innerHTML = updates.map(update => `
72
+ <div class="cyber-timeline-item">
73
+ <div class="flex justify-between items-start mb-2">
74
+ <h4 class="font-cyber text-cyber-primary">${update.title}</h4>
75
+ <span class="text-sm text-gray-400">${this.formatDate(update.date)}</span>
76
+ </div>
77
+ <p class="text-gray-300">${update.description}</p>
78
+ <a href="${update.link}" class="cyber-link text-sm mt-2">Подробнее →</a>
79
+ </div>
80
+ `).join('');
81
+ }
82
+
83
+ formatDate(dateString) {
84
+ const date = new Date(dateString);
85
+ return date.toLocaleDateString('ru-RU');
86
+ }
87
+
88
+ toggleAIAssistant() {
89
+ const assistant = document.querySelector('ai-assistant');
90
+ if (assistant) {
91
+ assistant.toggleChat();
92
+ }
93
+ }
94
+ }
95
+
96
+ // Initialize the portal
97
+ let portal;
98
+
99
+ document.addEventListener('DOMContentLoaded', function() {
100
+ portal = new SingularityPortal();
101
+ feather.replace();
102
+ });
103
+
104
+ // Utility functions
105
+ const Utils = {
106
+ debounce(func, wait) {
107
+ let timeout;
108
+ return function executedFunction(...args) {
109
+ const later = () => {
110
+ clearTimeout(timeout);
111
+ func(...args);
112
+ };
113
+ clearTimeout(timeout);
114
+ timeout = setTimeout(later, wait);
115
+ };
116
+ },
117
+
118
+ generateId() {
119
+ return Date.now().toString(36) + Math.random().toString(36).substr(2);
120
+ },
121
+
122
+ formatFileSize(bytes) {
123
+ const sizes = ['Bytes', 'KB', 'MB', 'GB'];
124
+ if (bytes === 0) return '0 Bytes';
125
+ const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
126
+ return Math.round(bytes / Math.pow(1024, i) * 100) / 100 + ' ' + sizes[i];
127
+ }
128
+ };
129
+
130
+ // API service for backend communication
131
+ class APIService {
132
+ constructor() {
133
+ this.baseURL = '/api';
134
+ }
135
+
136
+ async request(endpoint, options = {}) {
137
+ const url = `${this.baseURL}${endpoint}`;
138
+ const config = {
139
+ headers: {
140
+ 'Content-Type': 'application/json',
141
+ },
142
+ ...options
143
+ };
144
+
145
+ try {
146
+ const response = await fetch(url, config);
147
+ if (!response.ok) {
148
+ throw new Error(`HTTP error! status: ${response.status}`);
149
+ }
150
+ return await response.json();
151
+ } catch (error) {
152
+ console.error('API request failed:', error);
153
+ throw error;
154
+ }
155
+ }
156
+
157
+ // Content management
158
+ async getContent(section, filters = {}) {
159
+ const query = new URLSearchParams(filters).toString();
160
+ return this.request(`/content/${section}?${query}`);
161
+ }
162
+
163
+ async createContent(contentData) {
164
+ return this.request('/content', {
165
+ method: 'POST',
166
+ body: JSON.stringify(contentData)
167
+ });
168
+ }
169
+
170
+ async updateContent(id, contentData) {
171
+ return this.request(`/content/${id}`, {
172
+ method: 'PUT',
173
+ body: JSON.stringify(contentData)
174
+ });
175
+ }
176
+
177
+ // AI Assistant communication
178
+ async sendMessageToAI(message, context = {}) {
179
+ return this.request('/ai/chat', {
180
+ method: 'POST',
181
+ body: JSON.stringify({ message, context })
182
+ });
183
+ }
184
+
185
+ // User management
186
+ async login(credentials) {
187
+ return this.request('/auth/login', {
188
+ method: 'POST',
189
+ body: JSON.stringify(credentials)
190
+ });
191
+ }
192
+
193
+ async register(userData) {
194
+ return this.request('/auth/register', {
195
+ method: 'POST',
196
+ body: JSON.stringify(userData)
197
+ });
198
+ }
199
+ }
200
+
201
+ // Initialize API service
202
+ const apiService = new APIService();
203
+
204
+ // Export for use in components
205
+ window.SingularityPortal = SingularityPortal;
206
+ window.APIService = APIService;
207
+ window.Utils = Utils;
style.css CHANGED
@@ -1,28 +1,298 @@
1
- body {
2
- padding: 2rem;
3
- font-family: -apple-system, BlinkMacSystemFont, "Arial", sans-serif;
 
 
4
  }
5
 
6
- h1 {
7
- font-size: 16px;
8
- margin-top: 0;
 
 
 
 
 
 
 
 
9
  }
10
 
11
- p {
12
- color: rgb(107, 114, 128);
13
- font-size: 15px;
14
- margin-bottom: 10px;
15
- margin-top: 5px;
16
  }
17
 
18
- .card {
19
- max-width: 620px;
20
- margin: 0 auto;
21
- padding: 16px;
22
- border: 1px solid lightgray;
23
- border-radius: 16px;
 
 
 
 
 
24
  }
25
 
26
- .card p:last-child {
27
- margin-bottom: 0;
 
28
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Cyber Style Global Styles */
2
+ .cyber-glow {
3
+ text-shadow: 0 0 10px rgba(0, 255, 136, 0.5),
4
+ 0 0 20px rgba(0, 255, 136, 0.3),
5
+ 0 0 40px rgba(0, 255, 136, 0.1);
6
  }
7
 
8
+ .cyber-button-primary {
9
+ background: linear-gradient(45deg, #00ff88, #00a2ff);
10
+ border: 1px solid #00ff88;
11
+ color: #050508;
12
+ font-weight: 600;
13
+ border-radius: 8px;
14
+ transition: all 0.3s ease;
15
+ text-decoration: none;
16
+ display: inline-flex;
17
+ align-items: center;
18
+ box-shadow: 0 0 15px rgba(0, 255, 136, 0.3);
19
  }
20
 
21
+ .cyber-button-primary:hover {
22
+ box-shadow: 0 0 25px rgba(0, 255, 136, 0.6);
23
+ transform: translateY(-2px);
 
 
24
  }
25
 
26
+ .cyber-button-secondary {
27
+ background: transparent;
28
+ border: 1px solid #00a2ff;
29
+ color: #00a2ff;
30
+ font-weight: 600;
31
+ border-radius: 8px;
32
+ transition: all 0.3s ease;
33
+ text-decoration: none;
34
+ display: inline-flex;
35
+ align-items: center;
36
+ box-shadow: 0 0 15px rgba(0, 162, 255, 0.3);
37
  }
38
 
39
+ .cyber-button-secondary:hover {
40
+ box-shadow: 0 0 25px rgba(0, 162, 255, 0.6);
41
+ transform: translateY(-2px);
42
  }
43
+
44
+ .cyber-button-accent {
45
+ background: transparent;
46
+ border: 1px solid #ff0088;
47
+ color: #ff0088;
48
+ font-weight: 600;
49
+ border-radius: 8px;
50
+ transition: all 0.3s ease;
51
+ text-decoration: none;
52
+ display: inline-flex;
53
+ align-items: center;
54
+ box-shadow: 0 0 15px rgba(255, 0, 136, 0.3);
55
+ }
56
+
57
+ .cyber-button-accent:hover {
58
+ box-shadow: 0 0 25px rgba(255, 0, 136, 0.6);
59
+ transform: translateY(-2px);
60
+ }
61
+
62
+ .cyber-card {
63
+ background: linear-gradient(145deg, #1a1a2e, #0a0a0f);
64
+ border: 1px solid #2a2a3e;
65
+ border-radius: 12px;
66
+ padding: 24px;
67
+ transition: all 0.3s ease;
68
+ position: relative;
69
+ overflow: hidden;
70
+ }
71
+
72
+ .cyber-card::before {
73
+ content: '';
74
+ position: absolute;
75
+ top: 0;
76
+ left: -100%;
77
+ width: 100%;
78
+ height: 100%;
79
+ background: linear-gradient(90deg, transparent, rgba(0, 255, 136, 0.1), transparent);
80
+ transition: left 0.5s ease;
81
+ }
82
+
83
+ .cyber-card:hover::before {
84
+ left: 100%;
85
+ }
86
+
87
+ .cyber-card:hover {
88
+ border-color: #00ff88;
89
+ transform: translateY(-5px);
90
+ box-shadow: 0 10px 30px rgba(0, 255, 136, 0.2);
91
+ }
92
+
93
+ .cyber-card-header {
94
+ display: flex;
95
+ align-items: center;
96
+ gap: 12px;
97
+ margin-bottom: 16px;
98
+ }
99
+
100
+ .cyber-card-header h3 {
101
+ background: linear-gradient(45deg, #00ff88, #00a2ff);
102
+ background-clip: text;
103
+ -webkit-background-clip: text;
104
+ -webkit-text-fill-color: transparent;
105
+ }
106
+
107
+ .cyber-link {
108
+ color: #00ff88;
109
+ text-decoration: none;
110
+ font-weight: 600;
111
+ transition: all 0.3s ease;
112
+ display: inline-flex;
113
+ align-items: center;
114
+ gap: 4px;
115
+ }
116
+
117
+ .cyber-link:hover {
118
+ color: #00a2ff;
119
+ gap: 8px;
120
+ }
121
+
122
+ .cyber-timeline {
123
+ position: relative;
124
+ padding-left: 30px;
125
+ }
126
+
127
+ .cyber-timeline::before {
128
+ content: '';
129
+ position: absolute;
130
+ left: 0;
131
+ top: 0;
132
+ bottom: 0;
133
+ width: 2px;
134
+ background: linear-gradient(to bottom, #00ff88, #00a2ff, #ff0088);
135
+ }
136
+
137
+ .cyber-timeline-item {
138
+ position: relative;
139
+ margin-bottom: 24px;
140
+ padding: 16px;
141
+ background: rgba(26, 26, 46, 0.5);
142
+ border-radius: 8px;
143
+ border-left: 3px solid #00ff88;
144
+ }
145
+
146
+ .cyber-timeline-item::before {
147
+ content: '';
148
+ position: absolute;
149
+ left: -38px;
150
+ top: 20px;
151
+ width: 12px;
152
+ height: 12px;
153
+ border-radius: 50%;
154
+ background: #00ff88;
155
+ box-shadow: 0 0 10px #00ff88;
156
+ }
157
+
158
+ /* AI Assistant Styles */
159
+ .ai-assistant-container {
160
+ position: fixed;
161
+ bottom: 20px;
162
+ right: 20px;
163
+ z-index: 1000;
164
+ }
165
+
166
+ .ai-toggle-button {
167
+ width: 60px;
168
+ height: 60px;
169
+ border-radius: 50%;
170
+ background: linear-gradient(45deg, #00ff88, #00a2ff);
171
+ border: none;
172
+ color: #050508;
173
+ cursor: pointer;
174
+ box-shadow: 0 5px 20px rgba(0, 255, 136, 0.4);
175
+ transition: all 0.3s ease;
176
+ display: flex;
177
+ align-items: center;
178
+ justify-content: center;
179
+ }
180
+
181
+ .ai-toggle-button:hover {
182
+ transform: scale(1.1);
183
+ box-shadow: 0 8px 25px rgba(0, 255, 136, 0.6);
184
+ }
185
+
186
+ .ai-chat-window {
187
+ position: absolute;
188
+ bottom: 70px;
189
+ right: 0;
190
+ width: 350px;
191
+ height: 500px;
192
+ background: #0a0a0f;
193
+ border: 1px solid #00ff88;
194
+ border-radius: 12px;
195
+ box-shadow: 0 10px 40px rgba(0, 255, 136, 0.3);
196
+ display: none;
197
+ flex-direction: column;
198
+ }
199
+
200
+ .ai-chat-window.active {
201
+ display: flex;
202
+ }
203
+
204
+ .ai-chat-header {
205
+ padding: 16px;
206
+ background: linear-gradient(45deg, #00ff88, #00a2ff);
207
+ border-radius: 12px 12px 0 0;
208
+ color: #050508;
209
+ font-weight: 600;
210
+ display: flex;
211
+ justify-content: space-between;
212
+ align-items: center;
213
+ }
214
+
215
+ .ai-chat-messages {
216
+ flex: 1;
217
+ padding: 16px;
218
+ overflow-y: auto;
219
+ display: flex;
220
+ flex-direction: column;
221
+ gap: 12px;
222
+ }
223
+
224
+ .ai-message {
225
+ padding: 12px;
226
+ border-radius: 8px;
227
+ max-width: 80%;
228
+ word-wrap: break-word;
229
+ }
230
+
231
+ .ai-message.user {
232
+ align-self: flex-end;
233
+ background: linear-gradient(45deg, #00a2ff, #00ff88);
234
+ color: #050508;
235
+ }
236
+
237
+ .ai-message.assistant {
238
+ align-self: flex-start;
239
+ background: #1a1a2e;
240
+ border: 1px solid #2a2a3e;
241
+ }
242
+
243
+ .ai-chat-input {
244
+ padding: 16px;
245
+ border-top: 1px solid #2a2a3e;
246
+ display: flex;
247
+ gap: 8px;
248
+ }
249
+
250
+ .ai-chat-input input {
251
+ flex: 1;
252
+ padding: 8px 12px;
253
+ background: #1a1a2e;
254
+ border: 1px solid #2a2a3e;
255
+ border-radius: 6px;
256
+ color: white;
257
+ }
258
+
259
+ .ai-chat-input button {
260
+ padding: 8px 16px;
261
+ background: #00ff88;
262
+ border: none;
263
+ border-radius: 6px;
264
+ color: #050508;
265
+ font-weight: 600;
266
+ cursor: pointer;
267
+ }
268
+
269
+ /* Responsive Design */
270
+ @media (max-width: 768px) {
271
+ .ai-chat-window {
272
+ width: 300px;
273
+ height: 400px;
274
+ right: -50px;
275
+ }
276
+
277
+ .cyber-card {
278
+ padding: 16px;
279
+ }
280
+ }
281
+
282
+ /* Scrollbar Styling */
283
+ ::-webkit-scrollbar {
284
+ width: 6px;
285
+ }
286
+
287
+ ::-webkit-scrollbar-track {
288
+ background: #1a1a2e;
289
+ }
290
+
291
+ ::-webkit-scrollbar-thumb {
292
+ background: linear-gradient(45deg, #00ff88, #00a2ff);
293
+ border-radius: 3px;
294
+ }
295
+
296
+ ::-webkit-scrollbar-thumb:hover {
297
+ background: linear-gradient(45deg, #00a2ff, #ff0088);
298
+ }