Spaces:
Running
import gradio as gr
Browse filesfrom huggingface_hub import InferenceClient
import time
# ======================================================
# CSS FUTURISTE IA – BLANC SHADING + NEON
# ======================================================
css = """
body {
background:
radial-gradient(circle at top, rgba(0,246,255,.15), transparent),
#07090f !important;
}
.gradio-container {
max-width: 1100px !important;
margin: auto;
}
/* CHAT FRAME */
.pro-chat {
background: rgba(12,14,25,.92);
backdrop-filter: blur(14px);
border-radius: 20px;
border: 1px solid rgba(255,255,255,.15);
box-shadow: 0 0 50px rgba(0,246,255,.12);
}
/* MESSAGE (BLANC SHADING) */
.pro-chat .message {
background: linear-gradient(
135deg,
rgba(255,255,255,.06),
rgba(255,255,255,.02)
) !important;
border-radius: 16px;
border: 1px solid rgba(255,255,255,.18);
padding: 12px 16px;
color: #00f6ff !important; /* BLANC */
text-shadow: 0 0 6px rgba(255,255,255,.35);
}
/* USER */
.pro-chat .user {
border-left: 3px solid rgba(255,255,255,.6);
}
/* BOT */
.pro-chat .bot {
border-left: 3px solid rgba(0,246,255,.8);
}
/* INPUT */
.pro-input textarea {
background: rgba(8,10,20,.95) !important;
border-radius: 18px !important;
border: 1px solid rgba(255,255,255,.25) !important;
color: #f9fafb !important;
padding: 16px !important;
font-size: 15px;
caret-color: #00f6ff;
}
/* SEND BUTTON */
.pro-send {
background: linear-gradient(135deg,#00f6ff,#a855f7) !important;
border-radius: 18px !important;
color: black !important;
font-weight: 700 !important;
box-shadow: 0 0 25px rgba(0,246,255,.6);
transition: .3s;
}
.pro-send:hover {
transform: scale(1.05);
box-shadow:
0 0 35px #00f6ff,
0 0 60px #a855f7;
}
/* TYPING DOTS */
.typing {
color: #f9fafb;
font-style: italic;
opacity: .7;
}
footer { display:none !important; }
"""
# ======================================================
# IA RESPONSE + TYPING ANIMATION
# ======================================================
def respond(
message,
history,
system_message,
max_tokens,
temperature,
top_p,
hf_token: gr.OAuthToken,
):
client = InferenceClient(
token=hf_token.token,
model="darkc0de/XortronCriminalComputingConfig"
)
messages = [{"role": "system", "content": system_message}]
for user, bot in history:
messages.append({"role": "user", "content": user})
messages.append({"role": "assistant", "content": bot})
messages.append({"role": "user", "content": message})
# 👇 Animation "IA écrit..."
typing = history + [[message, "⟡ AI is thinking…"]]
yield typing
time.sleep(0.6)
response = ""
for chunk in client.chat_completion(
messages,
max_tokens=max_tokens,
stream=True,
temperature=temperature,
top_p=top_p,
):
if chunk.choices and chunk.choices[0].delta.content:
response += chunk.choices[0].delta.content
yield history + [[message, response]]
# ======================================================
# UI FUTURISTE IA
# ======================================================
with gr.Blocks(css=css) as demo:
with gr.Sidebar():
gr.Markdown("## 🔐 HuggingFace Login")
gr.LoginButton()
system = gr.Textbox(
value="You are a futuristic artificial intelligence core.",
label="System prompt"
)
max_tokens = gr.Slider(1, 2048, 512, label="Max tokens")
temperature = gr.Slider(0.1, 4.0, 0.7, label="Temperature")
top_p = gr.Slider(0.1, 1.0, 0.95, label="Top-p")
gr.Markdown("## 🤖 FUTURISTIC AI CORE")
chat = gr.Chatbot(
elem_classes="pro-chat",
height=520
)
with gr.Row():
msg = gr.Textbox(
placeholder="Transmit your message to the AI core…",
show_label=False,
elem_classes="pro-input"
)
send = gr.Button("⚡", elem_classes="pro-send")
send.click(
respond,
inputs=[msg, chat, system, max_tokens, temperature, top_p],
outputs=chat
)
if __name__ == "__main__":
demo.launch()
- README.md +8 -5
- components/typing-indicator.js +38 -0
- index.html +110 -19
- script.js +91 -0
- style.css +49 -19
|
@@ -1,10 +1,13 @@
|
|
| 1 |
---
|
| 2 |
-
title: Quantum Chat Core
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
sdk: static
|
| 7 |
pinned: false
|
|
|
|
|
|
|
| 8 |
---
|
| 9 |
|
| 10 |
-
|
|
|
|
|
|
| 1 |
---
|
| 2 |
+
title: Quantum Chat Core ✨
|
| 3 |
+
colorFrom: pink
|
| 4 |
+
colorTo: green
|
| 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).
|
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
class TypingIndicator extends HTMLElement {
|
| 2 |
+
connectedCallback() {
|
| 3 |
+
this.attachShadow({ mode: 'open' });
|
| 4 |
+
this.shadowRoot.innerHTML = `
|
| 5 |
+
<style>
|
| 6 |
+
@keyframes pulse {
|
| 7 |
+
0%, 100% { opacity: 1; }
|
| 8 |
+
50% { opacity: 0.5; }
|
| 9 |
+
}
|
| 10 |
+
.container {
|
| 11 |
+
display: flex;
|
| 12 |
+
gap: 4px;
|
| 13 |
+
}
|
| 14 |
+
.dot {
|
| 15 |
+
width: 8px;
|
| 16 |
+
height: 8px;
|
| 17 |
+
background-color: #38bdf8;
|
| 18 |
+
border-radius: 50%;
|
| 19 |
+
display: inline-block;
|
| 20 |
+
animation: pulse 1.5s infinite ease-in-out;
|
| 21 |
+
}
|
| 22 |
+
.dot:nth-child(2) {
|
| 23 |
+
animation-delay: 0.2s;
|
| 24 |
+
}
|
| 25 |
+
.dot:nth-child(3) {
|
| 26 |
+
animation-delay: 0.4s;
|
| 27 |
+
}
|
| 28 |
+
</style>
|
| 29 |
+
<div class="container">
|
| 30 |
+
<span class="dot"></span>
|
| 31 |
+
<span class="dot"></span>
|
| 32 |
+
<span class="dot"></span>
|
| 33 |
+
</div>
|
| 34 |
+
`;
|
| 35 |
+
}
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
customElements.define('typing-indicator', TypingIndicator);
|
|
@@ -1,19 +1,110 @@
|
|
| 1 |
-
<!
|
| 2 |
-
<html>
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>Quantum Chat Core</title>
|
| 7 |
+
<link rel="stylesheet" href="style.css">
|
| 8 |
+
<script src="https://cdn.tailwindcss.com"></script>
|
| 9 |
+
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
|
| 10 |
+
<script src="https://unpkg.com/feather-icons"></script>
|
| 11 |
+
<script>
|
| 12 |
+
tailwind.config = {
|
| 13 |
+
theme: {
|
| 14 |
+
extend: {
|
| 15 |
+
colors: {
|
| 16 |
+
quantum: {
|
| 17 |
+
100: '#e0f2fe',
|
| 18 |
+
200: '#bae6fd',
|
| 19 |
+
300: '#7dd3fc',
|
| 20 |
+
400: '#38bdf8',
|
| 21 |
+
500: '#0ea5e9',
|
| 22 |
+
600: '#0284c7',
|
| 23 |
+
700: '#0369a1',
|
| 24 |
+
800: '#075985',
|
| 25 |
+
900: '#0c4a6e',
|
| 26 |
+
},
|
| 27 |
+
neon: {
|
| 28 |
+
100: '#f0f9ff',
|
| 29 |
+
200: '#e0f2fe',
|
| 30 |
+
300: '#bae6fd',
|
| 31 |
+
400: '#7dd3fc',
|
| 32 |
+
500: '#38bdf8',
|
| 33 |
+
600: '#0ea5e9',
|
| 34 |
+
700: '#0284c7',
|
| 35 |
+
800: '#075985',
|
| 36 |
+
900: '#0c4a6e',
|
| 37 |
+
}
|
| 38 |
+
}
|
| 39 |
+
}
|
| 40 |
+
}
|
| 41 |
+
}
|
| 42 |
+
</script>
|
| 43 |
+
</head>
|
| 44 |
+
<body class="bg-gradient-to-br from-gray-900 to-gray-800 min-h-screen">
|
| 45 |
+
<div class="container mx-auto px-4 py-12">
|
| 46 |
+
<div class="max-w-4xl mx-auto">
|
| 47 |
+
<!-- Header -->
|
| 48 |
+
<div class="text-center mb-12">
|
| 49 |
+
<h1 class="text-4xl font-bold text-quantum-400 mb-2">Quantum Chat Core</h1>
|
| 50 |
+
<p class="text-neon-300">Conversations with the future</p>
|
| 51 |
+
</div>
|
| 52 |
+
|
| 53 |
+
<!-- Chat Container -->
|
| 54 |
+
<div class="bg-gray-800 bg-opacity-90 backdrop-blur-lg rounded-2xl border border-gray-700 shadow-xl shadow-quantum-900/20 overflow-hidden">
|
| 55 |
+
<!-- Chat Messages -->
|
| 56 |
+
<div id="chat-messages" class="h-96 overflow-y-auto p-6 space-y-4">
|
| 57 |
+
<div class="message bot bg-gray-700 bg-opacity-50 rounded-xl p-4 border-l-4 border-quantum-500">
|
| 58 |
+
<div class="flex items-start space-x-3">
|
| 59 |
+
<div class="flex-shrink-0 w-8 h-8 rounded-full bg-quantum-600 flex items-center justify-center">
|
| 60 |
+
<i data-feather="cpu" class="text-white w-4 h-4"></i>
|
| 61 |
+
</div>
|
| 62 |
+
<div class="text-neon-100">
|
| 63 |
+
<p>Hello! I'm your quantum AI assistant. How can I help you today?</p>
|
| 64 |
+
</div>
|
| 65 |
+
</div>
|
| 66 |
+
</div>
|
| 67 |
+
</div>
|
| 68 |
+
|
| 69 |
+
<!-- Input Area -->
|
| 70 |
+
<div class="border-t border-gray-700 p-4 bg-gray-800">
|
| 71 |
+
<div class="flex space-x-2">
|
| 72 |
+
<input type="text" id="user-input" placeholder="Type your message..."
|
| 73 |
+
class="flex-1 bg-gray-900 bg-opacity-70 border border-gray-700 rounded-xl px-4 py-3 text-neon-100 focus:outline-none focus:ring-2 focus:ring-quantum-500 focus:border-transparent placeholder-gray-500">
|
| 74 |
+
<button id="send-button" class="bg-gradient-to-r from-quantum-500 to-neon-500 text-white rounded-xl px-6 py-3 font-medium hover:opacity-90 transition-all transform hover:scale-105 shadow-lg shadow-quantum-500/30">
|
| 75 |
+
<i data-feather="send" class="w-5 h-5"></i>
|
| 76 |
+
</button>
|
| 77 |
+
</div>
|
| 78 |
+
</div>
|
| 79 |
+
</div>
|
| 80 |
+
|
| 81 |
+
<!-- Settings Panel -->
|
| 82 |
+
<div class="mt-8 bg-gray-800 bg-opacity-70 backdrop-blur-sm rounded-xl border border-gray-700 p-6">
|
| 83 |
+
<h2 class="text-xl font-semibold text-quantum-300 mb-4">AI Configuration</h2>
|
| 84 |
+
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
|
| 85 |
+
<div>
|
| 86 |
+
<label class="block text-neon-200 mb-2">System Prompt</label>
|
| 87 |
+
<textarea class="w-full bg-gray-900 bg-opacity-70 border border-gray-700 rounded-lg px-4 py-2 text-neon-100 focus:outline-none focus:ring-2 focus:ring-quantum-500 focus:border-transparent" rows="3">You are a futuristic artificial intelligence core.</textarea>
|
| 88 |
+
</div>
|
| 89 |
+
<div>
|
| 90 |
+
<label class="block text-neon-200 mb-2">Max Tokens</label>
|
| 91 |
+
<input type="range" min="1" max="2048" value="512" class="w-full accent-quantum-500">
|
| 92 |
+
<div class="text-right text-neon-300">512</div>
|
| 93 |
+
</div>
|
| 94 |
+
<div>
|
| 95 |
+
<label class="block text-neon-200 mb-2">Temperature</label>
|
| 96 |
+
<input type="range" min="0.1" max="4.0" step="0.1" value="0.7" class="w-full accent-quantum-500">
|
| 97 |
+
<div class="text-right text-neon-300">0.7</div>
|
| 98 |
+
</div>
|
| 99 |
+
</div>
|
| 100 |
+
</div>
|
| 101 |
+
</div>
|
| 102 |
+
</div>
|
| 103 |
+
|
| 104 |
+
<script src="script.js"></script>
|
| 105 |
+
<script>
|
| 106 |
+
feather.replace();
|
| 107 |
+
</script>
|
| 108 |
+
<script src="https://huggingface.co/deepsite/deepsite-badge.js"></script>
|
| 109 |
+
</body>
|
| 110 |
+
</html>
|
|
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
document.addEventListener('DOMContentLoaded', function() {
|
| 2 |
+
const chatMessages = document.getElementById('chat-messages');
|
| 3 |
+
const userInput = document.getElementById('user-input');
|
| 4 |
+
const sendButton = document.getElementById('send-button');
|
| 5 |
+
|
| 6 |
+
function addMessage(role, content) {
|
| 7 |
+
const messageDiv = document.createElement('div');
|
| 8 |
+
messageDiv.className = `message ${role} ${role === 'user' ? 'bg-gray-700 rounded-xl p-4 border-l-4 border-neon-500' : 'bg-gray-700 bg-opacity-50 rounded-xl p-4 border-l-4 border-quantum-500'}`;
|
| 9 |
+
|
| 10 |
+
const messageContent = `
|
| 11 |
+
<div class="flex items-start space-x-3">
|
| 12 |
+
<div class="flex-shrink-0 w-8 h-8 rounded-full ${role === 'user' ? 'bg-neon-600' : 'bg-quantum-600'} flex items-center justify-center">
|
| 13 |
+
<i data-feather="${role === 'user' ? 'user' : 'cpu'}" class="text-white w-4 h-4"></i>
|
| 14 |
+
</div>
|
| 15 |
+
<div class="text-neon-100">
|
| 16 |
+
<p>${content}</p>
|
| 17 |
+
</div>
|
| 18 |
+
</div>
|
| 19 |
+
`;
|
| 20 |
+
|
| 21 |
+
messageDiv.innerHTML = messageContent;
|
| 22 |
+
chatMessages.appendChild(messageDiv);
|
| 23 |
+
chatMessages.scrollTop = chatMessages.scrollHeight;
|
| 24 |
+
feather.replace();
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
function simulateTyping() {
|
| 28 |
+
const typingDiv = document.createElement('div');
|
| 29 |
+
typingDiv.className = 'message bot bg-gray-700 bg-opacity-50 rounded-xl p-4 border-l-4 border-quantum-500';
|
| 30 |
+
|
| 31 |
+
const typingContent = `
|
| 32 |
+
<div class="flex items-start space-x-3">
|
| 33 |
+
<div class="flex-shrink-0 w-8 h-8 rounded-full bg-quantum-600 flex items-center justify-center">
|
| 34 |
+
<i data-feather="cpu" class="text-white w-4 h-4"></i>
|
| 35 |
+
</div>
|
| 36 |
+
<div class="text-neon-100">
|
| 37 |
+
<div class="typing-indicator">
|
| 38 |
+
<span></span>
|
| 39 |
+
<span></span>
|
| 40 |
+
<span></span>
|
| 41 |
+
</div>
|
| 42 |
+
</div>
|
| 43 |
+
</div>
|
| 44 |
+
`;
|
| 45 |
+
|
| 46 |
+
typingDiv.innerHTML = typingContent;
|
| 47 |
+
chatMessages.appendChild(typingDiv);
|
| 48 |
+
chatMessages.scrollTop = chatMessages.scrollHeight;
|
| 49 |
+
feather.replace();
|
| 50 |
+
return typingDiv;
|
| 51 |
+
}
|
| 52 |
+
|
| 53 |
+
function removeTypingIndicator(typingElement) {
|
| 54 |
+
if (typingElement && typingElement.parentNode) {
|
| 55 |
+
typingElement.remove();
|
| 56 |
+
}
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
sendButton.addEventListener('click', function() {
|
| 60 |
+
const message = userInput.value.trim();
|
| 61 |
+
if (message) {
|
| 62 |
+
addMessage('user', message);
|
| 63 |
+
userInput.value = '';
|
| 64 |
+
|
| 65 |
+
const typingElement = simulateTyping();
|
| 66 |
+
|
| 67 |
+
// Simulate AI response after a delay
|
| 68 |
+
setTimeout(() => {
|
| 69 |
+
removeTypingIndicator(typingElement);
|
| 70 |
+
|
| 71 |
+
// Generate a mock response (in a real app, this would be from an API)
|
| 72 |
+
const responses = [
|
| 73 |
+
"I've processed your quantum query and found interesting patterns in the data.",
|
| 74 |
+
"The neural network suggests several possible interpretations of your request.",
|
| 75 |
+
"Analyzing temporal dimensions... your input resonates with 87.3% probability.",
|
| 76 |
+
"The quantum algorithm has converged on this response after evaluating multiple possibilities.",
|
| 77 |
+
"Fascinating perspective! My cognitive modules are processing the implications."
|
| 78 |
+
];
|
| 79 |
+
|
| 80 |
+
const randomResponse = responses[Math.floor(Math.random() * responses.length)];
|
| 81 |
+
addMessage('bot', randomResponse);
|
| 82 |
+
}, 1500 + Math.random() * 2000);
|
| 83 |
+
}
|
| 84 |
+
});
|
| 85 |
+
|
| 86 |
+
userInput.addEventListener('keypress', function(e) {
|
| 87 |
+
if (e.key === 'Enter') {
|
| 88 |
+
sendButton.click();
|
| 89 |
+
}
|
| 90 |
+
});
|
| 91 |
+
});
|
|
@@ -1,28 +1,58 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
}
|
| 5 |
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
}
|
| 10 |
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
|
|
|
|
|
|
| 16 |
}
|
| 17 |
|
| 18 |
-
.
|
| 19 |
-
|
| 20 |
-
margin: 0 auto;
|
| 21 |
-
padding: 16px;
|
| 22 |
-
border: 1px solid lightgray;
|
| 23 |
-
border-radius: 16px;
|
| 24 |
}
|
| 25 |
|
| 26 |
-
.
|
| 27 |
-
|
| 28 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
@keyframes pulse {
|
| 2 |
+
0%, 100% {
|
| 3 |
+
opacity: 1;
|
| 4 |
+
}
|
| 5 |
+
50% {
|
| 6 |
+
opacity: 0.5;
|
| 7 |
+
}
|
| 8 |
}
|
| 9 |
|
| 10 |
+
.typing-indicator {
|
| 11 |
+
display: flex;
|
| 12 |
+
gap: 4px;
|
| 13 |
}
|
| 14 |
|
| 15 |
+
.typing-indicator span {
|
| 16 |
+
width: 8px;
|
| 17 |
+
height: 8px;
|
| 18 |
+
background-color: #38bdf8;
|
| 19 |
+
border-radius: 50%;
|
| 20 |
+
display: inline-block;
|
| 21 |
+
animation: pulse 1.5s infinite ease-in-out;
|
| 22 |
}
|
| 23 |
|
| 24 |
+
.typing-indicator span:nth-child(2) {
|
| 25 |
+
animation-delay: 0.2s;
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
}
|
| 27 |
|
| 28 |
+
.typing-indicator span:nth-child(3) {
|
| 29 |
+
animation-delay: 0.4s;
|
| 30 |
}
|
| 31 |
+
|
| 32 |
+
.message {
|
| 33 |
+
transition: all 0.3s ease;
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
+
.message:hover {
|
| 37 |
+
transform: translateY(-2px);
|
| 38 |
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
/* Custom scrollbar */
|
| 42 |
+
::-webkit-scrollbar {
|
| 43 |
+
width: 8px;
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
::-webkit-scrollbar-track {
|
| 47 |
+
background: rgba(255, 255, 255, 0.05);
|
| 48 |
+
border-radius: 10px;
|
| 49 |
+
}
|
| 50 |
+
|
| 51 |
+
::-webkit-scrollbar-thumb {
|
| 52 |
+
background: rgba(59, 130, 246, 0.5);
|
| 53 |
+
border-radius: 10px;
|
| 54 |
+
}
|
| 55 |
+
|
| 56 |
+
::-webkit-scrollbar-thumb:hover {
|
| 57 |
+
background: rgba(59, 130, 246, 0.7);
|
| 58 |
+
}
|