Spaces:
Sleeping
Sleeping
| <html data-theme="dark" dir="rtl" lang="ar"> | |
| <head> | |
| <meta charset="utf-8"/> | |
| <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/> | |
| <title>SurfGO | Research Lab</title> | |
| <link rel="preconnect" href="https://fonts.googleapis.com"/> | |
| <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin/> | |
| <link href="https://fonts.googleapis.com/css2?family=Cairo:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&family=Syne:wght@400;500;600;700&display=swap" rel="stylesheet"/> | |
| <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css" rel="stylesheet"/> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/9.1.6/marked.min.js"></script> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/atom-one-dark.min.css" id="hljs-theme"/> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.9/katex.min.css"/> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.9/katex.min.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.9/contrib/auto-render.min.js"></script> | |
| <style> | |
| :root { | |
| --bg-base: #f8fafc; | |
| --bg-nav: rgba(255,255,255,0.92); | |
| --bg-card: #ffffff; | |
| --bg-input: #f1f5f9; | |
| --border: rgba(99,102,241,0.15); | |
| --border-hover: rgba(99,102,241,0.5); | |
| --accent: #4f46e5; | |
| --accent-2: #ec4899; | |
| --accent-glow: rgba(79,70,229,0.12); | |
| --text-main: #0f172a; | |
| --text-sub: #64748b; | |
| --text-faint: #94a3b8; | |
| --shadow: 0 4px 20px rgba(0,0,0,0.06); | |
| --r-card: 16px; | |
| --r-pill: 100px; | |
| --ease: 0.22s cubic-bezier(0.4,0,0.2,1); | |
| } | |
| [data-theme="dark"] { | |
| --bg-base: #0b0e14; | |
| --bg-nav: rgba(13,18,30,0.95); | |
| --bg-card: #131720; | |
| --bg-input: #1b2235; | |
| --border: rgba(148,163,184,0.09); | |
| --border-hover: rgba(99,102,241,0.45); | |
| --accent: #818cf8; | |
| --accent-2: #f472b6; | |
| --accent-glow: rgba(129,140,248,0.12); | |
| --text-main: #e8edf5; | |
| --text-sub: #8b98b0; | |
| --text-faint: #4f5f7a; | |
| --shadow: 0 4px 28px rgba(0,0,0,0.45); | |
| } | |
| *{margin:0;padding:0;box-sizing:border-box;outline:none;} | |
| body{ | |
| font-family:'Cairo',sans-serif; | |
| background:var(--bg-base); | |
| color:var(--text-main); | |
| height:100vh; | |
| overflow:hidden; | |
| transition:background-color 0.3s,color 0.3s; | |
| } | |
| .bg-mesh{position:fixed;inset:0;z-index:0;pointer-events:none;overflow:hidden;} | |
| .bg-mesh::before{ | |
| content:'';position:absolute;top:-25%;right:-15%;width:55vw;height:55vw; | |
| background:radial-gradient(circle,var(--accent-glow) 0%,transparent 70%); | |
| border-radius:50%;animation:drift 20s ease-in-out infinite alternate;filter:blur(70px); | |
| } | |
| .bg-mesh::after{ | |
| content:'';position:absolute;bottom:-20%;left:-10%;width:45vw;height:45vw; | |
| background:radial-gradient(circle,rgba(236,72,153,0.07) 0%,transparent 70%); | |
| border-radius:50%;animation:drift 26s ease-in-out infinite alternate-reverse;filter:blur(70px); | |
| } | |
| @keyframes drift{from{transform:translate(0,0) scale(1);}to{transform:translate(4%,3%) scale(1.04);}} | |
| /* NAV */ | |
| .navbar{ | |
| position:fixed;top:14px;left:50%;transform:translateX(-50%); | |
| width:96%;max-width:1200px;height:62px; | |
| background:var(--bg-nav); | |
| backdrop-filter:blur(20px) saturate(180%); | |
| -webkit-backdrop-filter:blur(20px) saturate(180%); | |
| border:1px solid var(--border);border-radius:14px; | |
| display:flex;align-items:center;justify-content:space-between;padding:0 20px; | |
| z-index:100;box-shadow:var(--shadow); | |
| } | |
| .brand{font-family:'Syne',sans-serif;font-weight:700;font-size:20px;text-decoration:none;color:var(--text-main);display:flex;align-items:center;gap:10px;} | |
| .brand-icon{ | |
| width:34px;height:34px;border-radius:9px; | |
| background:linear-gradient(135deg,var(--accent),var(--accent-2)); | |
| display:flex;align-items:center;justify-content:center;color:#fff;font-size:15px; | |
| box-shadow:0 3px 10px var(--accent-glow); | |
| } | |
| .nav-center{display:flex;align-items:center;gap:12px;} | |
| .nav-badge{ | |
| font-family:'Cairo',sans-serif;font-size:11px;font-weight:600;color:var(--accent); | |
| background:var(--accent-glow);border:1px solid var(--border); | |
| padding:4px 12px;border-radius:var(--r-pill);letter-spacing:0.3px; | |
| } | |
| .nav-actions{display:flex;align-items:center;gap:10px;} | |
| .nav-link{ | |
| display:flex;align-items:center;gap:7px; | |
| background:transparent;border:1px solid var(--border);border-radius:var(--r-pill); | |
| padding:6px 14px;text-decoration:none;font-size:13px;font-weight:500;color:var(--text-sub);transition:var(--ease); | |
| font-family:'Cairo',sans-serif; | |
| } | |
| .nav-link:hover{border-color:var(--accent);color:var(--accent);background:var(--bg-input);} | |
| #theme-toggle{ | |
| background:var(--bg-input);border:1px solid var(--border);color:var(--text-sub);cursor:pointer; | |
| width:36px;height:36px;border-radius:50%;display:flex;align-items:center;justify-content:center; | |
| font-size:14px;transition:var(--ease); | |
| } | |
| #theme-toggle:hover{border-color:var(--accent);color:var(--accent);transform:rotate(18deg);} | |
| /* LAYOUT */ | |
| .page{ | |
| position:relative;z-index:1;width:100%;max-width:1200px; | |
| height:calc(100vh - 28px);margin:90px auto 14px; | |
| padding:0 14px;display:flex;flex-direction:column;gap:14px; | |
| } | |
| .grid{ | |
| display:grid;grid-template-columns:1fr 310px;gap:14px; | |
| flex:1;min-height:0; | |
| } | |
| /* CHAT */ | |
| .chat-col{display:flex;flex-direction:column;gap:10px;min-height:0;} | |
| .chat-box{ | |
| background:var(--bg-card);border:1px solid var(--border);border-radius:var(--r-card); | |
| flex:1;overflow-y:auto;padding:18px;scroll-behavior:smooth;box-shadow:var(--shadow); | |
| } | |
| .chat-box::-webkit-scrollbar{width:5px;} | |
| .chat-box::-webkit-scrollbar-track{background:transparent;} | |
| .chat-box::-webkit-scrollbar-thumb{background:var(--border-hover);border-radius:10px;} | |
| .chat-box::-webkit-scrollbar-thumb:hover{background:var(--accent);} | |
| .chat-empty{ | |
| height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center; | |
| gap:10px;color:var(--text-faint);text-align:center; | |
| } | |
| .chat-empty i{font-size:34px;color:var(--border-hover);opacity:0.6;} | |
| .chat-empty h3{font-size:16px;color:var(--text-main);font-weight:600;margin-bottom:3px;} | |
| .chat-empty p{font-size:13px;} | |
| /* MESSAGES */ | |
| .message{display:flex;gap:10px;margin-bottom:18px;animation:up 0.28s ease-out;} | |
| .message.user{flex-direction:row-reverse;} | |
| .avatar{ | |
| width:30px;height:30px;border-radius:9px;display:flex;align-items:center; | |
| justify-content:center;font-size:12px;flex-shrink:0;margin-top:3px; | |
| } | |
| .avatar.ai{background:linear-gradient(135deg,var(--accent),var(--accent-2));color:#fff;box-shadow:0 3px 8px var(--accent-glow);} | |
| .avatar.user-av{background:var(--bg-input);border:1px solid var(--border);color:var(--text-sub);} | |
| .msg-body{max-width:88%;display:flex;flex-direction:column;gap:7px;align-items:flex-start;} | |
| .message.user .msg-body{align-items:flex-end;} | |
| .bubble{padding:11px 15px;font-size:14px;line-height:1.7;word-wrap:break-word;} | |
| .bubble.ai{ | |
| background:var(--bg-input);border:1px solid var(--border);color:var(--text-main); | |
| border-radius:4px 16px 16px 16px;width:100%; | |
| } | |
| .bubble.user-b{ | |
| background:linear-gradient(135deg,var(--accent),var(--accent-2));color:#fff; | |
| border-radius:16px 4px 16px 16px;box-shadow:0 4px 14px var(--accent-glow); | |
| } | |
| .bubble.ai h1,.bubble.ai h2,.bubble.ai h3{font-family:'Cairo',sans-serif;font-weight:700;color:var(--text-main);margin:14px 0 7px;} | |
| .bubble.ai h1{font-size:1.3rem;}.bubble.ai h2{font-size:1.15rem;}.bubble.ai h3{font-size:1.05rem;} | |
| .bubble.ai p{margin-bottom:8px;} | |
| .bubble.ai ul,.bubble.ai ol{padding-right:20px;margin-bottom:8px;} | |
| .bubble.ai li{margin-bottom:3px;} | |
| .bubble.ai a{color:var(--accent);text-decoration:none;border-bottom:1px dotted var(--accent);} | |
| .bubble.ai strong{font-weight:700;color:var(--text-main);} | |
| .bubble.ai blockquote{ | |
| border-right:3px solid var(--accent);border-left:none;padding:8px 13px;margin:8px 0; | |
| color:var(--text-sub);background:rgba(129,140,248,0.05);border-radius:8px 0 0 8px;font-style:italic; | |
| } | |
| .bubble.ai pre{ | |
| background:#1a1d27;border-radius:8px;padding:0;overflow:hidden;margin:10px 0; | |
| border:1px solid var(--border); | |
| } | |
| .code-header{ | |
| display:flex;align-items:center;justify-content:space-between;padding:7px 13px; | |
| background:rgba(255,255,255,0.04);border-bottom:1px solid rgba(255,255,255,0.08); | |
| } | |
| .code-lang{font-family:'JetBrains Mono',monospace;font-size:10px;color:#9ca3af;text-transform:uppercase;letter-spacing:0.5px;} | |
| .copy-btn{ | |
| background:rgba(255,255,255,0.09);border:none;border-radius:4px;color:#e5e7eb; | |
| font-size:10px;padding:3px 8px;cursor:pointer;font-family:'Cairo',sans-serif; | |
| display:flex;align-items:center;gap:4px;transition:0.2s; | |
| } | |
| .copy-btn:hover{background:var(--accent);color:#fff;} | |
| .bubble.ai pre code{ | |
| font-family:'JetBrains Mono',monospace;font-size:13px;display:block; | |
| padding:13px;overflow-x:auto;color:#e5e7eb; | |
| } | |
| .bubble.ai code:not(pre code){ | |
| font-family:'JetBrains Mono',monospace;font-size:0.88em; | |
| background:rgba(129,140,248,0.13);color:var(--accent);padding:2px 5px;border-radius:4px; | |
| } | |
| .bubble.ai table{ | |
| width:100%;border-collapse:collapse;margin:10px 0;font-size:13px; | |
| border-radius:8px;overflow:hidden;border:1px solid var(--border); | |
| } | |
| .bubble.ai th{background:var(--bg-input);color:var(--accent);padding:9px;font-weight:600;text-align:right;border-bottom:1px solid var(--border);} | |
| .bubble.ai td{padding:9px;border-bottom:1px solid var(--border);color:var(--text-sub);} | |
| .bubble.ai tr:last-child td{border-bottom:none;} | |
| /* THINKING */ | |
| .think-box{background:rgba(129,140,248,0.04);border:1px dashed var(--border);border-radius:8px;overflow:hidden;margin-bottom:7px;} | |
| .think-header{display:flex;align-items:center;gap:7px;padding:7px 11px;cursor:pointer;user-select:none;font-size:11px;font-weight:600;color:var(--accent);text-transform:uppercase;letter-spacing:0.5px;} | |
| .think-header i.chevron{margin-right:auto;font-size:10px;transition:transform 0.3s;} | |
| .think-body{max-height:0;overflow:hidden;transition:max-height 0.4s cubic-bezier(0,1,0,1);font-size:11.5px;color:var(--text-sub);white-space:pre-wrap;padding:0 11px;line-height:1.65;font-family:'JetBrains Mono',monospace;} | |
| .think-body.open{max-height:400px;padding:7px 11px 11px;transition:max-height 0.4s ease-in-out;} | |
| /* SOURCES IN SIDEBAR */ | |
| .src-link{ | |
| display:flex;align-items:center;gap:7px;padding:7px 10px;border-radius:7px; | |
| background:var(--bg-input);text-decoration:none;color:var(--text-sub);font-size:11.5px;transition:var(--ease); | |
| margin-bottom:4px; | |
| } | |
| .src-link:hover{background:var(--border);color:var(--accent);} | |
| .src-link i{font-size:10px;flex-shrink:0;} | |
| .src-link span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;} | |
| /* CHIPS */ | |
| .chips{display:flex;flex-wrap:wrap;gap:7px;margin-top:8px;} | |
| .chip{ | |
| background:var(--bg-input);border:1px solid var(--border);border-radius:20px; | |
| padding:4px 11px;font-size:11px;color:var(--text-sub);cursor:pointer;transition:var(--ease); | |
| } | |
| .chip:hover{border-color:var(--accent);color:var(--accent);background:var(--bg-card);transform:translateY(-1px);} | |
| /* TYPING */ | |
| .typing{display:flex;gap:4px;align-items:center;padding:4px 0;} | |
| .dot{width:6px;height:6px;background:var(--accent);border-radius:50%;animation:bounce 1.2s infinite;opacity:0.5;} | |
| .dot:nth-child(2){animation-delay:0.15s;}.dot:nth-child(3){animation-delay:0.3s;} | |
| @keyframes bounce{0%,60%,100%{transform:translateY(0);opacity:0.4;}30%{transform:translateY(-5px);opacity:1;}} | |
| /* INPUT */ | |
| .input-wrap{ | |
| background:var(--bg-card);border:1px solid var(--border);border-radius:var(--r-card); | |
| padding:13px;box-shadow:var(--shadow);transition:border-color 0.2s,box-shadow 0.2s;flex-shrink:0; | |
| } | |
| .input-wrap:focus-within{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-glow);} | |
| .input-row{display:flex;align-items:flex-end;gap:9px;} | |
| textarea.field{ | |
| flex:1;background:transparent;border:none;color:var(--text-main); | |
| font-family:'Cairo',sans-serif;font-size:15px;resize:none; | |
| line-height:1.5;max-height:120px;min-height:24px;padding:2px 0;text-align:right; | |
| } | |
| textarea.field::placeholder{color:var(--text-faint);} | |
| .send{ | |
| width:40px;height:40px; | |
| background:linear-gradient(135deg,var(--accent),var(--accent-2)); | |
| border:none;border-radius:10px;color:#fff;font-size:14px;cursor:pointer; | |
| display:flex;align-items:center;justify-content:center;flex-shrink:0; | |
| box-shadow:0 4px 12px var(--accent-glow);transition:var(--ease); | |
| } | |
| .send:hover{transform:scale(1.06);} | |
| .send:disabled{opacity:0.5;cursor:not-allowed;transform:none;} | |
| .input-foot{ | |
| display:flex;align-items:center;justify-content:space-between; | |
| margin-top:7px;padding-top:7px;border-top:1px solid var(--border); | |
| } | |
| .hint{font-size:10px;color:var(--text-faint);display:flex;align-items:center;gap:4px;} | |
| .hint i{font-size:9px;color:var(--accent);} | |
| .chars{font-size:10px;color:var(--text-faint);} | |
| /* SIDEBAR */ | |
| .sidebar{display:flex;flex-direction:column;gap:11px;min-height:0;overflow:hidden;} | |
| .widget{ | |
| background:var(--bg-card);border:1px solid var(--border);border-radius:var(--r-card); | |
| padding:14px;box-shadow:var(--shadow);display:flex;flex-direction:column; | |
| } | |
| .widget.sources-widget{flex:1;min-height:0;overflow:hidden;} | |
| .w-head{display:flex;align-items:center;gap:7px;margin-bottom:11px;} | |
| .w-icon{ | |
| width:26px;height:26px;border-radius:7px; | |
| background:linear-gradient(135deg,var(--accent),var(--accent-2)); | |
| display:flex;align-items:center;justify-content:center;color:#fff;font-size:11px; | |
| } | |
| .w-title{font-family:'Cairo',sans-serif;font-size:13px;font-weight:600;color:var(--text-main);} | |
| .sw-list{display:flex;flex-direction:column;gap:4px;overflow-y:auto;padding-left:2px;flex:1;} | |
| .sw-list::-webkit-scrollbar{width:4px;} | |
| .sw-empty{text-align:center;color:var(--text-faint);font-size:11px;padding:12px 0;line-height:1.6;} | |
| .sw-empty i{display:block;font-size:18px;margin-bottom:5px;opacity:0.45;} | |
| .qlist{display:flex;flex-direction:column;gap:5px;} | |
| .qbtn{ | |
| background:var(--bg-input);border:1px solid var(--border);border-radius:8px; | |
| color:var(--text-sub);font-family:'Cairo',sans-serif;font-size:11.5px;padding:9px 11px; | |
| cursor:pointer;text-align:right;transition:var(--ease);display:flex;align-items:center;gap:7px; | |
| } | |
| .qbtn:hover{border-color:var(--accent);color:var(--accent);background:var(--bg-card);} | |
| .qbtn i{font-size:10px;color:var(--accent);flex-shrink:0;} | |
| .clear-btn{ | |
| width:100%;background:transparent;border:1px solid var(--border);border-radius:8px; | |
| color:var(--text-sub);font-family:'Cairo',sans-serif;font-size:12px;font-weight:500; | |
| padding:9px;cursor:pointer;transition:var(--ease); | |
| display:flex;align-items:center;justify-content:center;gap:5px;flex-shrink:0;margin-top:auto; | |
| } | |
| .clear-btn:hover{border-color:var(--accent-2);color:var(--accent-2);background:rgba(244,114,182,0.05);} | |
| .err-bubble{background:rgba(239,68,68,0.1);border:1px solid rgba(239,68,68,0.3);border-radius:8px;padding:9px 13px;color:#ef4444;font-size:13px;} | |
| @keyframes up{from{opacity:0;transform:translateY(8px);}to{opacity:1;transform:translateY(0);}} | |
| /* RESULT CARDS IN CHAT (like google results) */ | |
| .result-card{ | |
| background:var(--bg-card);border:1px solid var(--border);border-radius:10px; | |
| padding:10px 13px;margin:4px 0;text-decoration:none;display:block; | |
| color:var(--text-main);transition:var(--ease); | |
| } | |
| .result-card:hover{border-color:var(--accent);transform:translateY(-1px);} | |
| .result-card .rc-source{font-size:11px;color:var(--text-faint);margin-bottom:3px;display:flex;align-items:center;gap:5px;} | |
| .result-card .rc-title{font-size:13px;font-weight:600;color:var(--accent);margin-bottom:4px;} | |
| .result-card .rc-desc{font-size:12px;color:var(--text-sub);line-height:1.5;} | |
| @media(max-width:768px){ | |
| .grid{grid-template-columns:1fr;} | |
| .sidebar{display:none;} | |
| .page{margin-top:76px;height:calc(100vh - 90px);} | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="bg-mesh" aria-hidden="true"></div> | |
| <nav class="navbar"> | |
| <div class="nav-actions"> | |
| <a class="nav-link" href="https://surfgo.web.app" target="_blank" rel="noopener"> | |
| <i class="fa-solid fa-magnifying-glass"></i> <span>بحث</span> | |
| </a> | |
| <button id="theme-toggle" aria-label="تبديل الثيم"></button> | |
| </div> | |
| <div class="nav-center"> | |
| <span class="nav-badge"><i class="fa-solid fa-flask" style="margin-left:4px"></i> مختبر البحث</span> | |
| </div> | |
| <a class="brand" href="/"> | |
| SurfGO | |
| <div class="brand-icon"><i class="fa-solid fa-bolt"></i></div> | |
| </a> | |
| </nav> | |
| <div class="page"> | |
| <div class="grid"> | |
| <!-- Chat Column --> | |
| <div class="chat-col"> | |
| <div class="chat-box" id="chatBox"> | |
| <div class="chat-empty" id="chatEmpty"> | |
| <i class="fa-solid fa-robot"></i> | |
| <div> | |
| <h3>كيف يمكنني مساعدتك في البحث؟</h3> | |
| <p>اسأل عن أي موضوع وسأبحث وأحلله لك.</p> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="input-wrap"> | |
| <div class="input-row"> | |
| <button class="send" id="sendBtn"><i class="fa-solid fa-paper-plane"></i></button> | |
| <textarea class="field" id="inp" placeholder="اسأل سؤالاً (مثل: اشرح الذكاء الاصطناعي)..." rows="1"></textarea> | |
| </div> | |
| <div class="input-foot"> | |
| <span class="chars" id="chars">0 / 2000</span> | |
| <span class="hint"><i class="fa-solid fa-bolt"></i> AnesNT Core · بحث تلقائي مفعّل</span> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Sidebar --> | |
| <aside class="sidebar"> | |
| <div class="widget sources-widget"> | |
| <div class="w-head"> | |
| <div class="w-icon"><i class="fa-solid fa-link"></i></div> | |
| <span class="w-title">المصادر المستخدمة</span> | |
| </div> | |
| <div class="sw-list" id="swList"> | |
| <div class="sw-empty"> | |
| <i class="fa-solid fa-globe"></i> | |
| ستظهر المصادر هنا بعد البحث | |
| </div> | |
| </div> | |
| </div> | |
| <div class="widget"> | |
| <div class="w-head"> | |
| <div class="w-icon"><i class="fa-solid fa-wand-magic-sparkles"></i></div> | |
| <span class="w-title">أسئلة سريعة</span> | |
| </div> | |
| <div class="qlist"> | |
| <button class="qbtn" data-q="ما أبرز تطورات الذكاء الاصطناعي في 2025؟"> | |
| <i class="fa-solid fa-robot"></i> تطورات الذكاء الاصطناعي 2025 | |
| </button> | |
| <button class="qbtn" data-q="أفضل ممارسات الأمن السيبراني لتطبيقات الويب"> | |
| <i class="fa-solid fa-shield-halved"></i> الأمن السيبراني | |
| </button> | |
| <button class="qbtn" data-q="اشرح التشابك الكمي ببساطة"> | |
| <i class="fa-solid fa-atom"></i> الفيزياء الكمية | |
| </button> | |
| <button class="qbtn" data-q="قارن بين Python وJavaScript لعلم البيانات"> | |
| <i class="fa-solid fa-code"></i> Python مقابل JS | |
| </button> | |
| </div> | |
| </div> | |
| <button class="clear-btn" id="clearBtn"> | |
| <i class="fa-solid fa-trash-can"></i> مسح المحادثة | |
| </button> | |
| </aside> | |
| </div> | |
| </div> | |
| <script> | |
| (function(){ | |
| 'use strict'; | |
| /* ═══ Theme ═══ */ | |
| const themeBtn = document.getElementById('theme-toggle'); | |
| const root = document.documentElement; | |
| function setTheme(t){ | |
| root.setAttribute('data-theme',t); | |
| localStorage.setItem('sg-theme',t); | |
| themeBtn.innerHTML = t==='dark'?'<i class="fa-solid fa-sun"></i>':'<i class="fa-solid fa-moon"></i>'; | |
| document.getElementById('hljs-theme').href = t==='dark' | |
| ?'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/atom-one-dark.min.css' | |
| :'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/atom-one-light.min.css'; | |
| } | |
| setTheme(localStorage.getItem('sg-theme')||'dark'); | |
| themeBtn.addEventListener('click',()=>setTheme(root.getAttribute('data-theme')==='dark'?'light':'dark')); | |
| /* ═══ Marked Setup ═══ */ | |
| marked.setOptions({breaks:true,gfm:true}); | |
| const renderer = new marked.Renderer(); | |
| renderer.code = function(code,lang){ | |
| const language = hljs.getLanguage(lang)?lang:'plaintext'; | |
| const highlighted = hljs.highlight(code,{language}).value; | |
| const enc = encodeURIComponent(code); | |
| return `<pre><div class="code-header"><span class="code-lang">${language}</span><button class="copy-btn" data-enc="${enc}"><i class="fa-regular fa-copy"></i> نسخ</button></div><code class="hljs language-${language}">${highlighted}</code></pre>`; | |
| }; | |
| marked.use({renderer}); | |
| /* ═══ DOM ═══ */ | |
| const chatBox = document.getElementById('chatBox'); | |
| const chatEmpty = document.getElementById('chatEmpty'); | |
| const inp = document.getElementById('inp'); | |
| const sendBtn = document.getElementById('sendBtn'); | |
| const charsEl = document.getElementById('chars'); | |
| const swList = document.getElementById('swList'); | |
| const clearBtn = document.getElementById('clearBtn'); | |
| let allSources = []; | |
| let conversationHistory = []; | |
| /* ═══ Input ═══ */ | |
| inp.addEventListener('input',()=>{ | |
| inp.style.height='auto'; | |
| inp.style.height=Math.min(inp.scrollHeight,120)+'px'; | |
| charsEl.textContent=`${inp.value.length} / 2000`; | |
| }); | |
| inp.addEventListener('keydown',e=>{if(e.key==='Enter'&&!e.shiftKey){e.preventDefault();go();}}); | |
| sendBtn.addEventListener('click',go); | |
| document.querySelectorAll('.qbtn').forEach(b=>b.addEventListener('click',()=>{inp.value=b.dataset.q;inp.dispatchEvent(new Event('input'));go();})); | |
| clearBtn.addEventListener('click',()=>{ | |
| chatBox.innerHTML='';chatBox.appendChild(chatEmpty);chatEmpty.style.display='flex'; | |
| allSources=[];conversationHistory=[];renderSW([]); | |
| }); | |
| chatBox.addEventListener('click',e=>{ | |
| if(e.target.closest('.copy-btn')){ | |
| const btn=e.target.closest('.copy-btn'); | |
| const code=decodeURIComponent(btn.dataset.enc); | |
| navigator.clipboard.writeText(code).then(()=>{ | |
| const orig=btn.innerHTML;btn.innerHTML='<i class="fa-solid fa-check"></i> تم النسخ'; | |
| setTimeout(()=>{btn.innerHTML=orig;},2000); | |
| }); | |
| } | |
| if(e.target.closest('.think-header')){ | |
| const h=e.target.closest('.think-header');const b=h.nextElementSibling;const ic=h.querySelector('.chevron'); | |
| b.classList.toggle('open');ic.style.transform=b.classList.contains('open')?'rotate(180deg)':''; | |
| } | |
| if(e.target.closest('.chip')){const q=e.target.closest('.chip').textContent.trim();inp.value=q;inp.dispatchEvent(new Event('input'));go();} | |
| }); | |
| /* ═══ Utils ═══ */ | |
| const esc=s=>s.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); | |
| const scrollB=()=>{chatBox.scrollTop=chatBox.scrollHeight;}; | |
| const hideEmpty=()=>{chatEmpty.style.display='none';}; | |
| function renderSW(srcs){ | |
| if(!srcs.length){ | |
| swList.innerHTML='<div class="sw-empty"><i class="fa-solid fa-globe"></i>ستظهر المصادر هنا بعد البحث</div>';return; | |
| } | |
| swList.innerHTML=srcs.map(s=>` | |
| <a class="src-link" href="${esc(s.url)}" target="_blank" rel="noopener" title="${esc(s.title||s.url)}"> | |
| <i class="fa-solid fa-arrow-up-right-from-square"></i> | |
| <span>${esc(s.title||s.url)}</span> | |
| </a>`).join(''); | |
| } | |
| function addUser(text){ | |
| hideEmpty(); | |
| const d=document.createElement('div');d.className='message user'; | |
| d.innerHTML=`<div class="avatar user-av"><i class="fa-solid fa-user"></i></div><div class="msg-body"><div class="bubble user-b">${esc(text)}</div></div>`; | |
| chatBox.appendChild(d);scrollB(); | |
| } | |
| function addTyping(){ | |
| const d=document.createElement('div');d.className='message';d.id='typing'; | |
| d.innerHTML=`<div class="avatar ai"><i class="fa-solid fa-robot"></i></div><div class="msg-body"><div class="bubble ai"><div class="typing"><div class="dot"></div><div class="dot"></div><div class="dot"></div></div></div></div>`; | |
| chatBox.appendChild(d);scrollB(); | |
| } | |
| function rmTyping(){document.getElementById('typing')?.remove();} | |
| function makeSugg(content){ | |
| const suggs=[];const l=content.toLowerCase(); | |
| if(l.includes('كود')||l.includes('برمجة')||l.includes('function')||l.includes('code')) suggs.push('أعد هيكلة هذا الكود'); | |
| if(l.includes('اشرح')||l.includes('explain')) suggs.push('أعطني مثالاً عملياً','قارن مع بدائل'); | |
| if(!suggs.length) suggs.push('أخبرني أكثر','لخص هذا'); | |
| return suggs.slice(0,3); | |
| } | |
| /* ═══ Main Function ═══ */ | |
| async function go(){ | |
| const query=inp.value.trim(); | |
| if(!query||sendBtn.disabled) return; | |
| addUser(query); | |
| conversationHistory.push({role:'user',content:query}); | |
| inp.value='';inp.style.height='auto';charsEl.textContent='0 / 2000'; | |
| sendBtn.disabled=true;addTyping(); | |
| try{ | |
| const response = await fetch('https://api.anthropic.com/v1/messages',{ | |
| method:'POST', | |
| headers:{'Content-Type':'application/json'}, | |
| body:JSON.stringify({ | |
| model:'claude-sonnet-4-20250514', | |
| max_tokens:1000, | |
| system:`أنت مساعد بحث ذكي اسمه SurfGO. تجيب بالعربية دائماً ما لم يُطلب غير ذلك. كن واضحاً ومفيداً ومنظماً في إجاباتك. استخدم Markdown للتنسيق عند الحاجة.`, | |
| messages:conversationHistory | |
| }) | |
| }); | |
| if(!response.ok) throw new Error(`خطأ في الخادم: ${response.status}`); | |
| const data = await response.json(); | |
| rmTyping(); | |
| const fullContent = data.content | |
| .filter(b=>b.type==='text') | |
| .map(b=>b.text) | |
| .join(''); | |
| conversationHistory.push({role:'assistant',content:fullContent}); | |
| const aiDiv=document.createElement('div');aiDiv.className='message'; | |
| aiDiv.innerHTML=` | |
| <div class="avatar ai"><i class="fa-solid fa-robot"></i></div> | |
| <div class="msg-body"> | |
| <div class="bubble ai md-body"></div> | |
| </div>`; | |
| chatBox.appendChild(aiDiv); | |
| const mdBody=aiDiv.querySelector('.md-body'); | |
| mdBody.innerHTML=marked.parse(fullContent); | |
| if(window.renderMathInElement) renderMathInElement(mdBody,{delimiters:[{left:'$$',right:'$$',display:true},{left:'$',right:'$',display:false}],throwOnError:false}); | |
| const msgBody=aiDiv.querySelector('.msg-body'); | |
| const suggs=makeSugg(fullContent); | |
| if(suggs.length){ | |
| const cd=document.createElement('div');cd.className='chips'; | |
| cd.innerHTML=suggs.map(s=>`<button class="chip">${esc(s)}</button>`).join(''); | |
| msgBody.appendChild(cd); | |
| } | |
| scrollB(); | |
| }catch(e){ | |
| rmTyping(); | |
| const errDiv=document.createElement('div');errDiv.className='message'; | |
| errDiv.innerHTML=`<div class="avatar ai"><i class="fa-solid fa-circle-exclamation"></i></div><div class="msg-body"><div class="err-bubble">${esc(e.message)}</div></div>`; | |
| chatBox.appendChild(errDiv);scrollB(); | |
| }finally{ | |
| sendBtn.disabled=false;inp.focus(); | |
| } | |
| } | |
| })(); | |
| </script> | |
| </body> | |
| </html> |