AnesKAM commited on
Commit
d90adbc
·
verified ·
1 Parent(s): 55a86b0

Update results.html

Browse files
Files changed (1) hide show
  1. results.html +146 -343
results.html CHANGED
@@ -60,250 +60,127 @@
60
  transition: background 0.35s, color 0.35s;
61
  }
62
 
63
- /* ─── Background mesh ─── */
64
  .bg-mesh {
65
- position: fixed;
66
- inset: 0;
67
- z-index: 0;
68
- pointer-events: none;
69
- overflow: hidden;
70
  }
71
  .bg-mesh::before {
72
- content: '';
73
- position: absolute;
74
- top: -20%;
75
- right: -15%;
76
- width: 55vw;
77
- height: 55vw;
78
  background: radial-gradient(circle, rgba(91,94,244,0.13) 0%, transparent 70%);
79
- border-radius: 50%;
80
- animation: drift 18s ease-in-out infinite alternate;
81
  }
82
  .bg-mesh::after {
83
- content: '';
84
- position: absolute;
85
- bottom: -15%;
86
- left: -10%;
87
- width: 45vw;
88
- height: 45vw;
89
  background: radial-gradient(circle, rgba(224,66,122,0.1) 0%, transparent 70%);
90
- border-radius: 50%;
91
- animation: drift 22s ease-in-out infinite alternate-reverse;
92
  }
93
  @keyframes drift { from { transform: translate(0,0) scale(1); } to { transform: translate(4%,3%) scale(1.06); } }
94
 
95
- /* ─── Navbar ─── */
96
  .navbar {
97
- position: fixed;
98
- top: 14px;
99
- left: 50%;
100
- transform: translateX(-50%);
101
- width: 95%;
102
- max-width: 1280px;
103
- height: auto;
104
- min-height: 68px;
105
  background: var(--bg-nav);
106
  backdrop-filter: blur(28px) saturate(1.6);
107
  -webkit-backdrop-filter: blur(28px) saturate(1.6);
108
- border: 1px solid var(--border);
109
- border-radius: var(--radius-nav);
110
- display: flex;
111
- flex-wrap: wrap;
112
- align-items: center;
113
- justify-content: space-between;
114
- padding: 10px 18px;
115
  z-index: 1000;
116
  box-shadow: 0 4px 24px rgba(0,0,0,0.06), 0 1px 0 rgba(255,255,255,0.6) inset;
117
- gap: 12px;
118
- transition: background 0.35s, border-color 0.35s;
119
  }
120
 
121
- /* ─── Brand ─── */
122
  .brand {
123
- font-family: 'Syne', sans-serif;
124
- font-weight: 400;
125
- font-size: 21px;
126
- text-decoration: none;
127
- color: var(--text-main);
128
- display: flex;
129
- align-items: center;
130
- gap: 10px;
131
- letter-spacing: -0.01em;
132
- flex-shrink: 0;
133
  }
134
  .brand-icon {
135
- width: 36px;
136
- height: 36px;
137
  background: linear-gradient(135deg, var(--accent) 0%, var(--accent-2) 100%);
138
- border-radius: 10px;
139
- display: flex;
140
- align-items: center;
141
- justify-content: center;
142
- color: #fff;
143
- font-size: 15px;
144
- flex-shrink: 0;
145
- box-shadow: 0 4px 14px var(--accent-glow);
146
- }
147
- .brand span { transition: color 0.3s; }
148
-
149
- /* ─── Search bar ─── */
150
- .search-container {
151
- flex: 1;
152
- max-width: 580px;
153
- width: 100%;
154
  }
 
 
155
  .search-bar {
156
- display: flex;
157
- align-items: center;
158
- background: var(--bg-input);
159
- border: 1.5px solid var(--border);
160
- border-radius: var(--radius-pill);
161
- padding: 4px 4px 4px 16px;
162
- transition: var(--transition);
163
- width: 100%;
164
  }
165
  .search-bar:focus-within {
166
- border-color: var(--accent);
167
- background: var(--bg-input-focus);
168
  box-shadow: 0 0 0 4px var(--accent-glow);
169
  }
170
  .search-bar input {
171
- flex: 1;
172
- background: transparent;
173
- border: none;
174
- padding: 9px 0;
175
- color: var(--text-main);
176
- font-family: 'Tajawal', sans-serif;
177
- font-size: 14.5px;
178
- min-width: 0;
179
  }
180
  .search-bar input::placeholder { color: var(--text-faint); }
181
  .search-btn {
182
- background: none;
183
- border: none;
184
- color: var(--accent);
185
- cursor: pointer;
186
- width: 40px;
187
- height: 36px;
188
- border-radius: 0 var(--radius-pill) var(--radius-pill) 0;
189
- display: flex;
190
- align-items: center;
191
- justify-content: center;
192
- font-size: 15px;
193
- flex-shrink: 0;
194
- transition: var(--transition);
195
  }
196
  .search-btn:hover { color: var(--accent-2); transform: scale(1.12); }
197
 
198
- /* ─── Theme toggle ─── */
199
  #theme-toggle {
200
- background: var(--bg-input);
201
- border: 1.5px solid var(--border);
202
- color: var(--text-sub);
203
- cursor: pointer;
204
- width: 38px;
205
- height: 38px;
206
- border-radius: 50%;
207
- display: flex;
208
- align-items: center;
209
- justify-content: center;
210
- font-size: 15px;
211
- transition: var(--transition);
212
- flex-shrink: 0;
213
  }
214
  #theme-toggle:hover { border-color: var(--accent); color: var(--accent); background: var(--bg-input-focus); }
215
 
216
- /* ─── Tabs ─── */
217
  .tabs-bar {
218
- position: fixed;
219
- top: 98px;
220
- left: 50%;
221
- transform: translateX(-50%);
222
- width: 95%;
223
- max-width: 1280px;
224
- display: flex;
225
- gap: 6px;
226
- z-index: 999;
227
- overflow-x: auto;
228
- padding-bottom: 4px;
229
- scrollbar-width: none;
230
  }
231
  .tabs-bar::-webkit-scrollbar { display: none; }
232
-
233
  .tab-pill {
234
- padding: 7px 16px;
235
- border-radius: var(--radius-pill);
236
- background: var(--bg-card);
237
- border: 1.5px solid var(--border);
238
- color: var(--text-sub);
239
- font-family: 'Tajawal', sans-serif;
240
- font-size: 13px;
241
- font-weight: 500;
242
- cursor: pointer;
243
- transition: var(--transition);
244
- display: flex;
245
- align-items: center;
246
- gap: 6px;
247
- white-space: nowrap;
248
- box-shadow: var(--shadow-card);
249
  }
250
  .tab-pill:hover { border-color: var(--border-hover); color: var(--accent); }
251
- .tab-pill.active {
252
- background: var(--accent);
253
- color: #fff;
254
- border-color: var(--accent);
255
- box-shadow: 0 4px 16px var(--accent-glow);
256
- }
257
  .tab-pill i { font-size: 11px; }
258
 
259
- /* ─── Page layout ─── */
260
  .page-wrapper {
261
- position: relative;
262
- z-index: 1;
263
- max-width: 1280px;
264
- margin: 170px auto 60px;
265
- padding: 0 16px;
266
- display: flex;
267
- flex-direction: column;
268
- gap: 24px;
269
  }
270
  .results-area { min-width: 0; width: 100%; }
271
 
272
- /* ─── Loading state ─── */
273
  #loading-text {
274
- color: var(--text-sub);
275
- font-size: 13.5px;
276
- margin-bottom: 18px;
277
- display: flex;
278
- align-items: center;
279
- gap: 8px;
280
  }
281
  #loading-text::before {
282
- content: '';
283
- display: inline-block;
284
- width: 14px;
285
- height: 14px;
286
- border: 2px solid var(--border);
287
- border-top-color: var(--accent);
288
- border-radius: 50%;
289
- animation: spin 0.8s linear infinite;
290
- flex-shrink: 0;
291
  }
292
  #loading-text.done::before { display: none; }
293
  @keyframes spin { to { transform: rotate(360deg); } }
294
 
295
- /* ─── Result cards ─── */
296
  .tavily-result {
297
- background: var(--bg-card);
298
- border: 1.5px solid var(--border);
299
- border-radius: var(--radius-card);
300
- padding: 18px 20px;
301
- margin-bottom: 12px;
302
- transition: var(--transition);
303
- box-shadow: var(--shadow-card);
304
- display: flex;
305
- gap: 14px;
306
- align-items: flex-start;
307
  animation: fadeSlideIn 0.35s ease both;
308
  }
309
  .tavily-result:nth-child(1) { animation-delay: 0.04s; }
@@ -311,68 +188,22 @@
311
  .tavily-result:nth-child(3) { animation-delay: 0.12s; }
312
  .tavily-result:nth-child(4) { animation-delay: 0.16s; }
313
  .tavily-result:nth-child(n+5) { animation-delay: 0.20s; }
314
-
315
  @keyframes fadeSlideIn {
316
  from { opacity: 0; transform: translateY(10px); }
317
  to { opacity: 1; transform: translateY(0); }
318
  }
 
319
 
320
- .tavily-result:hover {
321
- border-color: var(--border-hover);
322
- box-shadow: var(--shadow-hover);
323
- transform: translateY(-2px);
324
- }
325
-
326
- .tavily-favicon {
327
- width: 22px;
328
- height: 22px;
329
- border-radius: 5px;
330
- margin-top: 3px;
331
- flex-shrink: 0;
332
- object-fit: contain;
333
- }
334
- .favicon-placeholder {
335
- width: 22px;
336
- height: 22px;
337
- border-radius: 5px;
338
- background: var(--bg-input);
339
- display: flex;
340
- align-items: center;
341
- justify-content: center;
342
- color: var(--text-faint);
343
- font-size: 10px;
344
- flex-shrink: 0;
345
- margin-top: 3px;
346
- }
347
  .tavily-content { flex: 1; min-width: 0; }
348
- .tavily-domain {
349
- font-size: 11.5px;
350
- color: var(--text-faint);
351
- margin-bottom: 4px;
352
- display: flex;
353
- align-items: center;
354
- gap: 4px;
355
- }
356
  .tavily-domain i { font-size: 9px; }
357
- .tavily-title {
358
- font-family: 'Tajawal', sans-serif;
359
- font-size: 16px;
360
- font-weight: 700;
361
- color: var(--accent) !important;
362
- text-decoration: none;
363
- display: inline-block;
364
- margin-bottom: 6px;
365
- line-height: 1.4;
366
- transition: color 0.2s;
367
- }
368
  .tavily-title:hover { color: var(--accent-2) !important; }
369
- .tavily-snippet {
370
- font-size: 13.5px;
371
- color: var(--text-sub);
372
- line-height: 1.65;
373
- }
374
 
375
- /* ─── Google CSE overrides ─── */
376
  .gsc-adBlock, .gcsc-branding, .gsc-branding, .gsc-branding-text,
377
  .gsc-branding-img, .gsc-branding-img-noclear, .gs-watermark, .gsc-results-branding,
378
  .gcsc-find-more-on-google, .gcsc-find-more-on-google-root, .gsc-result-info,
@@ -381,73 +212,40 @@
381
  display: none !important; visibility: hidden !important; height: 0 !important;
382
  width: 0 !important; margin: 0 !important; padding: 0 !important;
383
  }
384
-
385
  .gsc-above-wrapper-area { border: none !important; padding: 0 !important; margin: 0 !important; height: 0 !important; }
386
  .gsc-control-cse, .gsc-control-wrapper-cse { background: transparent !important; border: none !important; padding: 0 !important; width: 100% !important; max-width: 100% !important; }
387
-
388
  .gsc-thumbnail-inside { display: block !important; padding: 0 !important; visibility: visible !important; height: auto !important; width: auto !important; margin-bottom: 5px; }
389
-
390
- /* إخفاء العناوين المكررة داخل حاوية الصورة المصغرة */
391
- .gsc-thumbnail-inside .gs-title,
392
- .gsc-thumbnail-inside .gs-snippet,
393
- .gsc-thumbnail-inside .gs-visibleUrl {
394
- display: none !important;
395
- visibility: hidden !important;
396
- }
397
-
398
- .gs-title, .gs-title *, a.gs-title {
399
- color: var(--accent) !important;
400
- text-decoration: none !important;
401
- font-size: 16px !important;
402
- font-weight: 700 !important;
403
- font-family: 'Tajawal', sans-serif !important;
404
- display: inline-block !important;
405
- visibility: visible !important;
406
- }
407
  .gs-title:hover, .gs-title *:hover, a.gs-title:hover { color: var(--accent-2) !important; }
408
-
409
  .gs-snippet { color: var(--text-sub) !important; line-height: 1.65 !important; font-size: 13.5px !important; font-family: 'Tajawal', sans-serif !important; display: block !important; }
410
-
411
  .gsc-result { background: var(--bg-card) !important; border: 1.5px solid var(--border) !important; border-radius: var(--radius-card) !important; padding: 18px 20px !important; margin-bottom: 12px !important; box-shadow: var(--shadow-card) !important; flex-direction: column !important; }
412
  .gsc-result:hover { border-color: var(--border-hover) !important; box-shadow: var(--shadow-hover) !important; }
413
 
414
- /* ─── Sidebar ─── */
415
  .sidebar { width: 100%; order: 2; margin-top: 12px; }
416
 
417
- /* ─── AI Answer widget ─── */
418
  .ai-widget-wrap { position: relative; border-radius: var(--radius-card); }
419
  .ai-glow-ring {
420
- position: absolute;
421
- inset: -2px;
422
  border-radius: calc(var(--radius-card) + 2px);
423
  background: conic-gradient(
424
  from var(--angle, 0deg),
425
- var(--accent),
426
- var(--accent-2),
427
- #a78bfa,
428
- var(--accent),
429
- var(--accent-2),
430
- var(--accent)
431
  );
432
- z-index: 0;
433
- animation: spin-glow 4s linear infinite;
434
- filter: blur(1px);
435
  }
436
  @property --angle { syntax: '<angle>'; initial-value: 0deg; inherits: false; }
437
  @keyframes spin-glow { to { --angle: 360deg; } }
438
  @supports not (background: conic-gradient(from 0deg, red, blue)) {
439
  .ai-glow-ring { background: linear-gradient(135deg, var(--accent), var(--accent-2)); animation: none; }
440
  }
441
-
442
  .ai-widget {
443
- position: relative;
444
- z-index: 1;
445
- background: var(--bg-card);
446
- border-radius: var(--radius-card);
447
- padding: 18px 18px 16px;
448
  box-shadow: var(--shadow-card);
449
  }
450
-
451
  .ai-widget-header { display: flex; align-items: center; gap: 9px; margin-bottom: 14px; }
452
  .ai-widget-icon { width: 30px; height: 30px; border-radius: 8px; background: linear-gradient(135deg, var(--accent), var(--accent-2)); display: flex; align-items: center; justify-content: center; color: #fff; font-size: 12px; flex-shrink: 0; }
453
  .ai-widget-title { font-family: 'Syne', sans-serif; font-size: 13.5px; font-weight: 600; color: var(--text-main); }
@@ -463,24 +261,27 @@
463
  .ai-widget-footer { font-size: 10.5px; color: var(--text-faint); margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--border); display: flex; align-items: center; gap: 5px; }
464
  .ai-widget-footer i { color: var(--accent); font-size: 10px; }
465
 
466
- .sidebar-toggle {
467
- display: none; width: 100%; background: var(--bg-card); border: 1.5px solid var(--border); border-radius: var(--radius-card); padding: 14px 18px; text-align: right; font-family: 'Tajawal', sans-serif; font-size: 14px; font-weight: 600; color: var(--text-main); cursor: pointer; margin-bottom: 12px; transition: var(--transition); align-items: center; justify-content: space-between; box-shadow: var(--shadow-card);
 
 
 
 
 
 
468
  }
469
- .sidebar-toggle:hover { border-color: var(--border-hover); }
470
- .sidebar-content { display: block; }
471
 
472
- /* ─── Mobile AI block (inside main, shown only on mobile) ─── */
 
473
  .ai-mobile-wrap { display: none; position: relative; border-radius: var(--radius-card); margin-bottom: 16px; }
474
 
475
- /* ─── No results ─── */
476
  .empty-state { text-align: center; padding: 60px 20px; color: var(--text-sub); }
477
  .empty-state i { font-size: 40px; margin-bottom: 16px; color: var(--text-faint); display: block; }
478
  .empty-state p { font-size: 15px; }
479
-
480
- /* ─── Consistent results container ─── */
481
  #results-container { width: 100%; min-height: 200px; position: relative; }
482
 
483
- /* ─── Responsive ─── */
484
  @media (max-width: 767px) {
485
  .navbar { top: 10px; border-radius: 16px; padding: 10px 14px; gap: 10px; }
486
  .brand { font-size: 18px; }
@@ -531,7 +332,7 @@
531
  <main class="results-area" role="main">
532
  <div id="loading-text">جاري جلب النتائج…</div>
533
 
534
- <!-- بطاقة الذكاء الاصطناعي للموبايل فقط -->
535
  <div class="ai-mobile-wrap" id="ai-mobile-wrap">
536
  <div class="ai-glow-ring"></div>
537
  <div class="ai-widget">
@@ -545,9 +346,10 @@
545
  <div class="ai-skeleton"></div>
546
  <div class="ai-skeleton"></div>
547
  </div>
 
548
  <div class="ai-widget-footer">
549
  <i class="fa-solid fa-bolt"></i>
550
- مدعوم بواسطة AnesNT Core
551
  </div>
552
  </div>
553
  </div>
@@ -556,10 +358,6 @@
556
  </main>
557
 
558
  <aside class="sidebar" aria-label="إجابة الذكاء الاصطناعي">
559
- <button class="sidebar-toggle" id="sidebarToggle" aria-expanded="false">
560
- <span><i class="fa-solid fa-robot" style="margin-left:8px; color:var(--accent);"></i> إجابة الذكاء الاصطناعي</span>
561
- <i class="fa-solid fa-chevron-down" style="font-size:12px; color:var(--text-sub);"></i>
562
- </button>
563
  <div class="sidebar-content" id="sidebarContent">
564
  <div class="ai-widget-wrap">
565
  <div class="ai-glow-ring"></div>
@@ -574,9 +372,10 @@
574
  <div class="ai-skeleton"></div>
575
  <div class="ai-skeleton"></div>
576
  </div>
 
577
  <div class="ai-widget-footer">
578
  <i class="fa-solid fa-bolt"></i>
579
- مدعوم بواسطة AnesNT Core
580
  </div>
581
  </div>
582
  </div>
@@ -589,7 +388,7 @@
589
  // ════════════════════════════════════
590
  // Config
591
  // ════════════════════════════════════
592
- const TAVILY_API_KEYS =[
593
  "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",
594
  "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",
595
  "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"
@@ -623,23 +422,12 @@
623
  let query = params.get('q') || '';
624
  let currentTab = params.get('tab') || 'all';
625
 
626
- const inputEl = document.getElementById('main-input');
627
  const resultsEl = document.getElementById('results-container');
628
  const loadingEl = document.getElementById('loading-text');
629
 
630
- // Sidebar toggle (mobile)
631
- const sidebarToggle = document.getElementById('sidebarToggle');
632
- const sidebarContent = document.getElementById('sidebarContent');
633
- sidebarToggle?.addEventListener('click', () => {
634
- const open = sidebarContent.classList.toggle('active');
635
- sidebarToggle.setAttribute('aria-expanded', open);
636
- const chevron = sidebarToggle.querySelector('.fa-chevron-down, .fa-chevron-up');
637
- chevron?.classList.toggle('fa-chevron-down', !open);
638
- chevron?.classList.toggle('fa-chevron-up', open);
639
- });
640
-
641
  // ════════════════════════════════════
642
- // Tab management
643
  // ════════════════════════════════════
644
  function setActiveTab(tab) {
645
  document.querySelectorAll('.tab-pill').forEach(btn => {
@@ -651,12 +439,14 @@
651
  setActiveTab(currentTab);
652
 
653
  // ════════════════════════════════════
654
- // AI Answer (sidebar + mobile)
655
  // ════════════════════════════════════
656
- const aiBody = document.getElementById('ai-answer-body');
657
- const aiBodyMobile = document.getElementById('ai-answer-body-mobile');
 
 
658
 
659
- function setAIState(state, text = '') {
660
  [aiBody, aiBodyMobile].forEach(el => {
661
  if (!el) return;
662
  if (state === 'loading') {
@@ -664,31 +454,53 @@
664
  el.innerHTML = '<div class="ai-skeleton"></div><div class="ai-skeleton"></div><div class="ai-skeleton"></div>';
665
  } else {
666
  el.className = 'ai-answer-body';
667
- el.textContent = text;
668
  }
669
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
670
  }
671
 
672
- async function fetchAIAnswer(q) {
673
  if (!q) return;
674
  setAIState('loading');
675
  try {
676
- const res = await fetch('https://api.anthropic.com/v1/messages', {
677
  method: 'POST',
678
  headers: { 'Content-Type': 'application/json' },
679
  body: JSON.stringify({
680
- model: 'claude-sonnet-4-20250514',
681
- max_tokens: 1000,
682
- messages:[{
683
- role: 'user',
684
- content: `أجب على هذا السؤال أو البحث بشكل موجز ومفيد باللغة العربية في ٣-٤ جمل فقط: "${q}"`
685
- }]
686
  })
687
  });
 
688
  const data = await res.json();
689
- const text = data?.content?.find(b => b.type === 'text')?.text || '';
690
- setAIState('done', text || 'تعذّر تحميل الإجابة في الوقت الحالي.');
691
- } catch {
 
 
 
 
 
 
 
 
692
  setAIState('done', 'تعذّر تحميل الإجابة في الوقت الحالي.');
693
  }
694
  }
@@ -705,13 +517,9 @@
705
  }
706
 
707
  function escapeHTML(str) {
708
- if(!str) return '';
709
  return str.replace(/[&<>'"]/g, tag => ({
710
- '&': '&amp;',
711
- '<': '&lt;',
712
- '>': '&gt;',
713
- "'": '&#39;',
714
- '"': '&quot;'
715
  }[tag] || tag));
716
  }
717
 
@@ -785,7 +593,7 @@
785
  }
786
 
787
  // ════════════════════════════════════
788
- // Tavily
789
  // ════════════════════════════════════
790
  async function fetchTavilyResults(q, idx = 0) {
791
  if (idx >= TAVILY_API_KEYS.length) {
@@ -811,7 +619,7 @@
811
  renderTavilyResults(data.results || []);
812
  showLoading(false);
813
  } catch (e) {
814
- console.warn(`Tavily API key #${idx+1} failed:`, e);
815
  if (idx + 1 < TAVILY_API_KEYS.length) {
816
  return fetchTavilyResults(q, idx + 1);
817
  }
@@ -827,16 +635,15 @@
827
  }
828
  const html = results.map(r => {
829
  const domain = getDomain(r.url);
830
- const favicon = r.favicon
831
  ? `<img class="tavily-favicon" src="${r.favicon}" alt="" loading="lazy" onerror="this.style.display='none';this.nextElementSibling.style.display='flex';">`
832
  : '';
833
- const placeholder = r.favicon
834
- ? `<span class="favicon-placeholder" style="display:none;"><i class="fa-solid fa-globe"></i></span>`
835
  : `<span class="favicon-placeholder"><i class="fa-solid fa-globe"></i></span>`;
836
  return `
837
  <article class="tavily-result">
838
- ${favicon}
839
- ${placeholder}
840
  <div class="tavily-content">
841
  <div class="tavily-domain"><i class="fa-solid fa-link"></i> ${escapeHTML(domain)}</div>
842
  <a class="tavily-title" href="${r.url}" target="_blank" rel="noopener noreferrer">${escapeHTML(r.title || 'بدون عنوان')}</a>
@@ -850,7 +657,6 @@
850
  // ════════════════════════════════════
851
  // Event Listeners
852
  // ════════════════════════════════════
853
- // Search form submit
854
  document.getElementById('search-form').addEventListener('submit', (e) => {
855
  e.preventDefault();
856
  const q = inputEl.value.trim();
@@ -861,13 +667,10 @@
861
  window.history.pushState({}, '', url);
862
  query = q;
863
  document.title = `${query} – SurfGO`;
864
- // Update AI answer
865
  fetchAIAnswer(q);
866
- // Reload results
867
  loadTabResults(currentTab);
868
  });
869
 
870
- // Tab clicks
871
  document.querySelectorAll('.tab-pill').forEach(btn => {
872
  btn.addEventListener('click', () => {
873
  const tab = btn.dataset.tab;
 
60
  transition: background 0.35s, color 0.35s;
61
  }
62
 
 
63
  .bg-mesh {
64
+ position: fixed; inset: 0; z-index: 0;
65
+ pointer-events: none; overflow: hidden;
 
 
 
66
  }
67
  .bg-mesh::before {
68
+ content: ''; position: absolute; top: -20%; right: -15%;
69
+ width: 55vw; height: 55vw;
 
 
 
 
70
  background: radial-gradient(circle, rgba(91,94,244,0.13) 0%, transparent 70%);
71
+ border-radius: 50%; animation: drift 18s ease-in-out infinite alternate;
 
72
  }
73
  .bg-mesh::after {
74
+ content: ''; position: absolute; bottom: -15%; left: -10%;
75
+ width: 45vw; height: 45vw;
 
 
 
 
76
  background: radial-gradient(circle, rgba(224,66,122,0.1) 0%, transparent 70%);
77
+ border-radius: 50%; animation: drift 22s ease-in-out infinite alternate-reverse;
 
78
  }
79
  @keyframes drift { from { transform: translate(0,0) scale(1); } to { transform: translate(4%,3%) scale(1.06); } }
80
 
 
81
  .navbar {
82
+ position: fixed; top: 14px; left: 50%; transform: translateX(-50%);
83
+ width: 95%; max-width: 1280px; height: auto; min-height: 68px;
 
 
 
 
 
 
84
  background: var(--bg-nav);
85
  backdrop-filter: blur(28px) saturate(1.6);
86
  -webkit-backdrop-filter: blur(28px) saturate(1.6);
87
+ border: 1px solid var(--border); border-radius: var(--radius-nav);
88
+ display: flex; flex-wrap: wrap; align-items: center;
89
+ justify-content: space-between; padding: 10px 18px;
 
 
 
 
90
  z-index: 1000;
91
  box-shadow: 0 4px 24px rgba(0,0,0,0.06), 0 1px 0 rgba(255,255,255,0.6) inset;
92
+ gap: 12px; transition: background 0.35s, border-color 0.35s;
 
93
  }
94
 
 
95
  .brand {
96
+ font-family: 'Syne', sans-serif; font-weight: 400; font-size: 21px;
97
+ text-decoration: none; color: var(--text-main);
98
+ display: flex; align-items: center; gap: 10px;
99
+ letter-spacing: -0.01em; flex-shrink: 0;
 
 
 
 
 
 
100
  }
101
  .brand-icon {
102
+ width: 36px; height: 36px;
 
103
  background: linear-gradient(135deg, var(--accent) 0%, var(--accent-2) 100%);
104
+ border-radius: 10px; display: flex; align-items: center;
105
+ justify-content: center; color: #fff; font-size: 15px;
106
+ flex-shrink: 0; box-shadow: 0 4px 14px var(--accent-glow);
 
 
 
 
 
 
 
 
 
 
 
 
 
107
  }
108
+
109
+ .search-container { flex: 1; max-width: 580px; width: 100%; }
110
  .search-bar {
111
+ display: flex; align-items: center; background: var(--bg-input);
112
+ border: 1.5px solid var(--border); border-radius: var(--radius-pill);
113
+ padding: 4px 4px 4px 16px; transition: var(--transition); width: 100%;
 
 
 
 
 
114
  }
115
  .search-bar:focus-within {
116
+ border-color: var(--accent); background: var(--bg-input-focus);
 
117
  box-shadow: 0 0 0 4px var(--accent-glow);
118
  }
119
  .search-bar input {
120
+ flex: 1; background: transparent; border: none; padding: 9px 0;
121
+ color: var(--text-main); font-family: 'Tajawal', sans-serif;
122
+ font-size: 14.5px; min-width: 0;
 
 
 
 
 
123
  }
124
  .search-bar input::placeholder { color: var(--text-faint); }
125
  .search-btn {
126
+ background: none; border: none; color: var(--accent); cursor: pointer;
127
+ width: 40px; height: 36px; border-radius: 0 var(--radius-pill) var(--radius-pill) 0;
128
+ display: flex; align-items: center; justify-content: center;
129
+ font-size: 15px; flex-shrink: 0; transition: var(--transition);
 
 
 
 
 
 
 
 
 
130
  }
131
  .search-btn:hover { color: var(--accent-2); transform: scale(1.12); }
132
 
 
133
  #theme-toggle {
134
+ background: var(--bg-input); border: 1.5px solid var(--border);
135
+ color: var(--text-sub); cursor: pointer; width: 38px; height: 38px;
136
+ border-radius: 50%; display: flex; align-items: center;
137
+ justify-content: center; font-size: 15px;
138
+ transition: var(--transition); flex-shrink: 0;
 
 
 
 
 
 
 
 
139
  }
140
  #theme-toggle:hover { border-color: var(--accent); color: var(--accent); background: var(--bg-input-focus); }
141
 
 
142
  .tabs-bar {
143
+ position: fixed; top: 98px; left: 50%; transform: translateX(-50%);
144
+ width: 95%; max-width: 1280px; display: flex; gap: 6px; z-index: 999;
145
+ overflow-x: auto; padding-bottom: 4px; scrollbar-width: none;
 
 
 
 
 
 
 
 
 
146
  }
147
  .tabs-bar::-webkit-scrollbar { display: none; }
 
148
  .tab-pill {
149
+ padding: 7px 16px; border-radius: var(--radius-pill);
150
+ background: var(--bg-card); border: 1.5px solid var(--border);
151
+ color: var(--text-sub); font-family: 'Tajawal', sans-serif;
152
+ font-size: 13px; font-weight: 500; cursor: pointer;
153
+ transition: var(--transition); display: flex; align-items: center;
154
+ gap: 6px; white-space: nowrap; box-shadow: var(--shadow-card);
 
 
 
 
 
 
 
 
 
155
  }
156
  .tab-pill:hover { border-color: var(--border-hover); color: var(--accent); }
157
+ .tab-pill.active { background: var(--accent); color: #fff; border-color: var(--accent); box-shadow: 0 4px 16px var(--accent-glow); }
 
 
 
 
 
158
  .tab-pill i { font-size: 11px; }
159
 
 
160
  .page-wrapper {
161
+ position: relative; z-index: 1; max-width: 1280px;
162
+ margin: 170px auto 60px; padding: 0 16px;
163
+ display: flex; flex-direction: column; gap: 24px;
 
 
 
 
 
164
  }
165
  .results-area { min-width: 0; width: 100%; }
166
 
 
167
  #loading-text {
168
+ color: var(--text-sub); font-size: 13.5px; margin-bottom: 18px;
169
+ display: flex; align-items: center; gap: 8px;
 
 
 
 
170
  }
171
  #loading-text::before {
172
+ content: ''; display: inline-block; width: 14px; height: 14px;
173
+ border: 2px solid var(--border); border-top-color: var(--accent);
174
+ border-radius: 50%; animation: spin 0.8s linear infinite; flex-shrink: 0;
 
 
 
 
 
 
175
  }
176
  #loading-text.done::before { display: none; }
177
  @keyframes spin { to { transform: rotate(360deg); } }
178
 
 
179
  .tavily-result {
180
+ background: var(--bg-card); border: 1.5px solid var(--border);
181
+ border-radius: var(--radius-card); padding: 18px 20px; margin-bottom: 12px;
182
+ transition: var(--transition); box-shadow: var(--shadow-card);
183
+ display: flex; gap: 14px; align-items: flex-start;
 
 
 
 
 
 
184
  animation: fadeSlideIn 0.35s ease both;
185
  }
186
  .tavily-result:nth-child(1) { animation-delay: 0.04s; }
 
188
  .tavily-result:nth-child(3) { animation-delay: 0.12s; }
189
  .tavily-result:nth-child(4) { animation-delay: 0.16s; }
190
  .tavily-result:nth-child(n+5) { animation-delay: 0.20s; }
 
191
  @keyframes fadeSlideIn {
192
  from { opacity: 0; transform: translateY(10px); }
193
  to { opacity: 1; transform: translateY(0); }
194
  }
195
+ .tavily-result:hover { border-color: var(--border-hover); box-shadow: var(--shadow-hover); transform: translateY(-2px); }
196
 
197
+ .tavily-favicon { width: 22px; height: 22px; border-radius: 5px; margin-top: 3px; flex-shrink: 0; object-fit: contain; }
198
+ .favicon-placeholder { width: 22px; height: 22px; border-radius: 5px; background: var(--bg-input); display: flex; align-items: center; justify-content: center; color: var(--text-faint); font-size: 10px; flex-shrink: 0; margin-top: 3px; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
199
  .tavily-content { flex: 1; min-width: 0; }
200
+ .tavily-domain { font-size: 11.5px; color: var(--text-faint); margin-bottom: 4px; display: flex; align-items: center; gap: 4px; }
 
 
 
 
 
 
 
201
  .tavily-domain i { font-size: 9px; }
202
+ .tavily-title { font-family: 'Tajawal', sans-serif; font-size: 16px; font-weight: 700; color: var(--accent) !important; text-decoration: none; display: inline-block; margin-bottom: 6px; line-height: 1.4; transition: color 0.2s; }
 
 
 
 
 
 
 
 
 
 
203
  .tavily-title:hover { color: var(--accent-2) !important; }
204
+ .tavily-snippet { font-size: 13.5px; color: var(--text-sub); line-height: 1.65; }
 
 
 
 
205
 
206
+ /* Google CSE overrides */
207
  .gsc-adBlock, .gcsc-branding, .gsc-branding, .gsc-branding-text,
208
  .gsc-branding-img, .gsc-branding-img-noclear, .gs-watermark, .gsc-results-branding,
209
  .gcsc-find-more-on-google, .gcsc-find-more-on-google-root, .gsc-result-info,
 
212
  display: none !important; visibility: hidden !important; height: 0 !important;
213
  width: 0 !important; margin: 0 !important; padding: 0 !important;
214
  }
 
215
  .gsc-above-wrapper-area { border: none !important; padding: 0 !important; margin: 0 !important; height: 0 !important; }
216
  .gsc-control-cse, .gsc-control-wrapper-cse { background: transparent !important; border: none !important; padding: 0 !important; width: 100% !important; max-width: 100% !important; }
 
217
  .gsc-thumbnail-inside { display: block !important; padding: 0 !important; visibility: visible !important; height: auto !important; width: auto !important; margin-bottom: 5px; }
218
+ .gsc-thumbnail-inside .gs-title, .gsc-thumbnail-inside .gs-snippet, .gsc-thumbnail-inside .gs-visibleUrl { display: none !important; visibility: hidden !important; }
219
+ .gs-title, .gs-title *, a.gs-title { color: var(--accent) !important; text-decoration: none !important; font-size: 16px !important; font-weight: 700 !important; font-family: 'Tajawal', sans-serif !important; display: inline-block !important; visibility: visible !important; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
220
  .gs-title:hover, .gs-title *:hover, a.gs-title:hover { color: var(--accent-2) !important; }
 
221
  .gs-snippet { color: var(--text-sub) !important; line-height: 1.65 !important; font-size: 13.5px !important; font-family: 'Tajawal', sans-serif !important; display: block !important; }
 
222
  .gsc-result { background: var(--bg-card) !important; border: 1.5px solid var(--border) !important; border-radius: var(--radius-card) !important; padding: 18px 20px !important; margin-bottom: 12px !important; box-shadow: var(--shadow-card) !important; flex-direction: column !important; }
223
  .gsc-result:hover { border-color: var(--border-hover) !important; box-shadow: var(--shadow-hover) !important; }
224
 
225
+ /* Sidebar */
226
  .sidebar { width: 100%; order: 2; margin-top: 12px; }
227
 
228
+ /* AI Widget */
229
  .ai-widget-wrap { position: relative; border-radius: var(--radius-card); }
230
  .ai-glow-ring {
231
+ position: absolute; inset: -2px;
 
232
  border-radius: calc(var(--radius-card) + 2px);
233
  background: conic-gradient(
234
  from var(--angle, 0deg),
235
+ var(--accent), var(--accent-2), #a78bfa, var(--accent), var(--accent-2), var(--accent)
 
 
 
 
 
236
  );
237
+ z-index: 0; animation: spin-glow 4s linear infinite; filter: blur(1px);
 
 
238
  }
239
  @property --angle { syntax: '<angle>'; initial-value: 0deg; inherits: false; }
240
  @keyframes spin-glow { to { --angle: 360deg; } }
241
  @supports not (background: conic-gradient(from 0deg, red, blue)) {
242
  .ai-glow-ring { background: linear-gradient(135deg, var(--accent), var(--accent-2)); animation: none; }
243
  }
 
244
  .ai-widget {
245
+ position: relative; z-index: 1; background: var(--bg-card);
246
+ border-radius: var(--radius-card); padding: 18px 18px 16px;
 
 
 
247
  box-shadow: var(--shadow-card);
248
  }
 
249
  .ai-widget-header { display: flex; align-items: center; gap: 9px; margin-bottom: 14px; }
250
  .ai-widget-icon { width: 30px; height: 30px; border-radius: 8px; background: linear-gradient(135deg, var(--accent), var(--accent-2)); display: flex; align-items: center; justify-content: center; color: #fff; font-size: 12px; flex-shrink: 0; }
251
  .ai-widget-title { font-family: 'Syne', sans-serif; font-size: 13.5px; font-weight: 600; color: var(--text-main); }
 
261
  .ai-widget-footer { font-size: 10.5px; color: var(--text-faint); margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--border); display: flex; align-items: center; gap: 5px; }
262
  .ai-widget-footer i { color: var(--accent); font-size: 10px; }
263
 
264
+ /* AI sources list */
265
+ .ai-sources { margin-top: 10px; display: flex; flex-wrap: wrap; gap: 6px; }
266
+ .ai-source-chip {
267
+ font-size: 11px; padding: 3px 10px; border-radius: 20px;
268
+ background: var(--bg-input); border: 1px solid var(--border);
269
+ color: var(--text-faint); text-decoration: none;
270
+ display: flex; align-items: center; gap: 5px;
271
+ transition: var(--transition);
272
  }
273
+ .ai-source-chip:hover { border-color: var(--accent); color: var(--accent); }
274
+ .ai-source-chip i { font-size: 9px; }
275
 
276
+ .sidebar-toggle { display: none; }
277
+ .sidebar-content { display: block; }
278
  .ai-mobile-wrap { display: none; position: relative; border-radius: var(--radius-card); margin-bottom: 16px; }
279
 
 
280
  .empty-state { text-align: center; padding: 60px 20px; color: var(--text-sub); }
281
  .empty-state i { font-size: 40px; margin-bottom: 16px; color: var(--text-faint); display: block; }
282
  .empty-state p { font-size: 15px; }
 
 
283
  #results-container { width: 100%; min-height: 200px; position: relative; }
284
 
 
285
  @media (max-width: 767px) {
286
  .navbar { top: 10px; border-radius: 16px; padding: 10px 14px; gap: 10px; }
287
  .brand { font-size: 18px; }
 
332
  <main class="results-area" role="main">
333
  <div id="loading-text">جاري جلب النتائج…</div>
334
 
335
+ <!-- AI card mobile only -->
336
  <div class="ai-mobile-wrap" id="ai-mobile-wrap">
337
  <div class="ai-glow-ring"></div>
338
  <div class="ai-widget">
 
346
  <div class="ai-skeleton"></div>
347
  <div class="ai-skeleton"></div>
348
  </div>
349
+ <div class="ai-sources" id="ai-sources-mobile"></div>
350
  <div class="ai-widget-footer">
351
  <i class="fa-solid fa-bolt"></i>
352
+ مدعوم بواسطة AnesNT
353
  </div>
354
  </div>
355
  </div>
 
358
  </main>
359
 
360
  <aside class="sidebar" aria-label="إجابة الذكاء الاصطناعي">
 
 
 
 
361
  <div class="sidebar-content" id="sidebarContent">
362
  <div class="ai-widget-wrap">
363
  <div class="ai-glow-ring"></div>
 
372
  <div class="ai-skeleton"></div>
373
  <div class="ai-skeleton"></div>
374
  </div>
375
+ <div class="ai-sources" id="ai-sources-desktop"></div>
376
  <div class="ai-widget-footer">
377
  <i class="fa-solid fa-bolt"></i>
378
+ مدعوم بواسطة AnesNT
379
  </div>
380
  </div>
381
  </div>
 
388
  // ════════════════════════════════════
389
  // Config
390
  // ════════════════════════════════════
391
+ const TAVILY_API_KEYS = [
392
  "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",
393
  "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",
394
  "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"
 
422
  let query = params.get('q') || '';
423
  let currentTab = params.get('tab') || 'all';
424
 
425
+ const inputEl = document.getElementById('main-input');
426
  const resultsEl = document.getElementById('results-container');
427
  const loadingEl = document.getElementById('loading-text');
428
 
 
 
 
 
 
 
 
 
 
 
 
429
  // ════════════════════════════════════
430
+ // Tabs
431
  // ════════════════════════════════════
432
  function setActiveTab(tab) {
433
  document.querySelectorAll('.tab-pill').forEach(btn => {
 
439
  setActiveTab(currentTab);
440
 
441
  // ════════════════════════════════════
442
+ // AI Answer Tavily include_answer
443
  // ════════════════════════════════════
444
+ const aiBody = document.getElementById('ai-answer-body');
445
+ const aiBodyMobile = document.getElementById('ai-answer-body-mobile');
446
+ const aiSrcDesktop = document.getElementById('ai-sources-desktop');
447
+ const aiSrcMobile = document.getElementById('ai-sources-mobile');
448
 
449
+ function setAIState(state, text = '', sources = []) {
450
  [aiBody, aiBodyMobile].forEach(el => {
451
  if (!el) return;
452
  if (state === 'loading') {
 
454
  el.innerHTML = '<div class="ai-skeleton"></div><div class="ai-skeleton"></div><div class="ai-skeleton"></div>';
455
  } else {
456
  el.className = 'ai-answer-body';
457
+ el.textContent = text || 'لا توجد إجابة متاحة لهذا البحث.';
458
  }
459
  });
460
+
461
+ // Render source chips
462
+ const chipsHTML = sources.slice(0, 5).map(s => {
463
+ let domain = '';
464
+ try { domain = new URL(s.url).hostname.replace('www.', ''); } catch { domain = s.url; }
465
+ return `<a class="ai-source-chip" href="${s.url}" target="_blank" rel="noopener">
466
+ <i class="fa-solid fa-link"></i>${domain}
467
+ </a>`;
468
+ }).join('');
469
+
470
+ [aiSrcDesktop, aiSrcMobile].forEach(el => {
471
+ if (!el) return;
472
+ el.innerHTML = chipsHTML;
473
+ });
474
  }
475
 
476
+ async function fetchAIAnswer(q, idx = 0) {
477
  if (!q) return;
478
  setAIState('loading');
479
  try {
480
+ const res = await fetch('https://api.tavily.com/search', {
481
  method: 'POST',
482
  headers: { 'Content-Type': 'application/json' },
483
  body: JSON.stringify({
484
+ api_key: TAVILY_API_KEYS[idx],
485
+ query: q,
486
+ include_answer: 'advanced',
487
+ search_depth: 'advanced',
488
+ max_results: 5
 
489
  })
490
  });
491
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
492
  const data = await res.json();
493
+ if (data.error) throw new Error(data.error);
494
+
495
+ const answer = data.answer || '';
496
+ const sources = data.results || [];
497
+ setAIState('done', answer, sources);
498
+
499
+ } catch (e) {
500
+ console.warn(`Tavily AI key #${idx + 1} failed:`, e);
501
+ if (idx + 1 < TAVILY_API_KEYS.length) {
502
+ return fetchAIAnswer(q, idx + 1);
503
+ }
504
  setAIState('done', 'تعذّر تحميل الإجابة في الوقت الحالي.');
505
  }
506
  }
 
517
  }
518
 
519
  function escapeHTML(str) {
520
+ if (!str) return '';
521
  return str.replace(/[&<>'"]/g, tag => ({
522
+ '&': '&amp;', '<': '&lt;', '>': '&gt;', "'": '&#39;', '"': '&quot;'
 
 
 
 
523
  }[tag] || tag));
524
  }
525
 
 
593
  }
594
 
595
  // ════════════════════════════════════
596
+ // Tavily Search Results
597
  // ════════════════════════════════════
598
  async function fetchTavilyResults(q, idx = 0) {
599
  if (idx >= TAVILY_API_KEYS.length) {
 
619
  renderTavilyResults(data.results || []);
620
  showLoading(false);
621
  } catch (e) {
622
+ console.warn(`Tavily API key #${idx + 1} failed:`, e);
623
  if (idx + 1 < TAVILY_API_KEYS.length) {
624
  return fetchTavilyResults(q, idx + 1);
625
  }
 
635
  }
636
  const html = results.map(r => {
637
  const domain = getDomain(r.url);
638
+ const favicon = r.favicon
639
  ? `<img class="tavily-favicon" src="${r.favicon}" alt="" loading="lazy" onerror="this.style.display='none';this.nextElementSibling.style.display='flex';">`
640
  : '';
641
+ const placeholder = r.favicon
642
+ ? `<span class="favicon-placeholder" style="display:none;"><i class="fa-solid fa-globe"></i></span>`
643
  : `<span class="favicon-placeholder"><i class="fa-solid fa-globe"></i></span>`;
644
  return `
645
  <article class="tavily-result">
646
+ ${favicon}${placeholder}
 
647
  <div class="tavily-content">
648
  <div class="tavily-domain"><i class="fa-solid fa-link"></i> ${escapeHTML(domain)}</div>
649
  <a class="tavily-title" href="${r.url}" target="_blank" rel="noopener noreferrer">${escapeHTML(r.title || 'بدون عنوان')}</a>
 
657
  // ════════════════════════════════════
658
  // Event Listeners
659
  // ════════════════════════════════════
 
660
  document.getElementById('search-form').addEventListener('submit', (e) => {
661
  e.preventDefault();
662
  const q = inputEl.value.trim();
 
667
  window.history.pushState({}, '', url);
668
  query = q;
669
  document.title = `${query} – SurfGO`;
 
670
  fetchAIAnswer(q);
 
671
  loadTabResults(currentTab);
672
  });
673
 
 
674
  document.querySelectorAll('.tab-pill').forEach(btn => {
675
  btn.addEventListener('click', () => {
676
  const tab = btn.dataset.tab;