naruto / Index.html
nruto's picture
Upload Index.html
070df34 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AI Chat Assistant</title>
<style>
:root {
--primary-color: #2dd4bf;
--secondary-color: #1e293b;
--bg-color: #0f172a;
--text-primary: #f8fafc;
--text-secondary: #94a3b8;
--accent-color: #818cf8;
--border-color: #334155;
--hover-color: #1e293b;
--gradient-1: linear-gradient(135deg, #2dd4bf20, #818cf820);
--gradient-2: linear-gradient(45deg, #2dd4bf, #818cf8);
--glow-shadow: 0 0 20px rgba(45, 212, 191, 0.2);
--message-user-bg: linear-gradient(135deg, #2dd4bf, #818cf8);
--message-ai-bg: rgba(30, 41, 59, 0.5);
--message-user-gradient: linear-gradient(135deg, #2563eb, #1d4ed8);
--message-user-text: #ffffff;
--message-user-shadow: 0 4px 15px rgba(45, 212, 191, 0.2);
}
body {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
margin: 0;
padding: 0;
background-color: var(--bg-color);
color: var(--text-primary);
display: grid;
grid-template-columns: 260px 1fr;
min-height: 100vh;
background: var(--bg-color);
background-image:
radial-gradient(circle at 10% 20%, rgba(0, 255, 170, 0.05) 0%, transparent 20%),
radial-gradient(circle at 90% 80%, rgba(0, 200, 255, 0.05) 0%, transparent 20%);
transition: all 0.3s ease;
}
/* Sidebar Styles */
.sidebar {
background-color: var(--secondary-color);
backdrop-filter: blur(10px);
border-right: 1px solid rgba(255, 255, 255, 0.1);
padding: 16px;
display: flex;
flex-direction: column;
gap: 16px;
animation: slideIn 0.5s ease;
}
.new-chat-btn {
background: var(--message-user-bg);
color: white;
border: none;
padding: 12px;
border-radius: 12px;
cursor: pointer;
font-weight: 600;
transition: all 0.3s ease;
box-shadow: var(--message-user-shadow);
display: flex;
align-items: center;
gap: 8px;
}
.new-chat-btn:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(45, 212, 191, 0.3);
background: var(--accent-color);
}
.chat-list {
flex-grow: 1;
overflow-y: auto;
}
.chat-item {
padding: 10px;
border-radius: 6px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: space-between;
color: var(--text-secondary);
transition: all 0.3s ease;
background: transparent;
border: 1px solid transparent;
}
.chat-item:hover {
background: var(--hover-color);
border-color: var(--primary-color);
transform: translateX(5px);
}
.chat-item.active {
background: var(--hover-color);
border-left: 2px solid var(--primary-color);
}
.delete-chat {
opacity: 0;
transition: opacity 0.2s ease;
color: var(--text-secondary);
background: none;
border: none;
cursor: pointer;
padding: 4px;
}
.chat-item:hover .delete-chat {
opacity: 1;
}
/* Main Chat Area */
.main-container {
display: flex;
flex-direction: column;
height: 100vh;
}
.chat-header {
padding: 16px;
border-bottom: 1px solid var(--border-color);
display: flex;
align-items: center;
justify-content: center;
position: relative;
background: rgba(26, 31, 44, 0.8);
backdrop-filter: blur(10px);
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.chat-title {
font-size: 1.1rem;
color: var(--primary-color);
margin: 0;
text-align: center;
font-weight: 500;
max-width: 60%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
letter-spacing: 0.5px;
}
.chat-messages {
flex-grow: 1;
overflow-y: auto;
padding: 20px;
scroll-behavior: smooth;
height: calc(100vh - 140px);
font-size: 16px !important;
}
.message {
max-width: 80%;
padding: 12px 16px;
margin-bottom: 16px;
font-size: 16px !important;
line-height: 1.5;
border-radius: 18px;
position: relative;
display: inline-flex;
gap: 12px;
align-items: flex-start;
width: fit-content;
}
.message.user-message {
margin-left: auto;
background: linear-gradient(135deg, #2dd4bf, #0ea5e9);
border-bottom-right-radius: 4px;
flex-direction: row-reverse;
box-shadow: 0 2px 8px rgba(45, 212, 191, 0.2);
float: right;
clear: both;
}
.message.ai-message {
margin-right: auto;
background: var(--secondary-color);
border-bottom-left-radius: 4px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
float: left;
clear: both;
}
.avatar {
width: 32px;
height: 32px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-weight: 600;
font-size: 14px;
flex-shrink: 0;
margin-top: 4px;
}
.user-avatar {
background: white;
color: var(--primary-color);
box-shadow: 0 2px 8px rgba(45, 212, 191, 0.2);
}
.ai-avatar {
background: white;
color: var(--secondary-color);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.message-content {
font-size: 16px !important;
line-height: 1.5;
padding: 0 4px;
word-wrap: break-word;
white-space: pre-wrap;
}
.user-message .message-content {
color: white;
text-align: left;
}
.ai-message .message-content {
color: var(--text-primary);
}
/* Input Area */
.input-container {
padding: 20px;
border-top: 1px solid var(--border-color);
max-width: 900px;
margin: 0 auto;
width: calc(100% - 40px);
position: relative;
}
.input-wrapper {
display: flex;
gap: 12px;
background: var(--message-ai-bg);
border: 1px solid rgba(45, 212, 191, 0.2);
padding: 12px 16px;
border-radius: 12px;
transition: all 0.3s ease;
}
.input-wrapper:focus-within {
border-color: var(--primary-color);
box-shadow: 0 0 15px rgba(45, 212, 191, 0.2);
}
#user-input {
flex-grow: 1;
padding: 8px 0;
border: none;
background: transparent;
font-size: 16px;
color: var(--text-primary);
outline: none;
resize: none;
min-height: 24px;
max-height: 200px;
line-height: 1.5;
}
.send-button {
background: var(--message-user-bg);
border: none;
border-radius: 8px;
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.3s ease;
padding: 0;
margin: auto 0;
box-shadow: var(--message-user-shadow);
}
.send-button:hover {
transform: translateY(-2px) scale(1.05);
box-shadow: 0 6px 20px rgba(45, 212, 191, 0.3);
background: var(--accent-color);
}
.send-button:active {
transform: translateY(0);
}
.send-button svg {
width: 16px;
height: 16px;
stroke: white;
}
.send-button.disabled {
background-color: var(--text-secondary);
cursor: not-allowed;
opacity: 0.5;
}
/* Keep existing code block and other styles... */
/* Code Block Styles within Messages */
.message .code-block {
position: relative;
background: #1e1e1e;
border-radius: 8px;
margin: 12px 0;
font-family: 'Fira Code', 'Consolas', monospace;
border: 1px solid rgba(255, 255, 255, 0.1);
}
.code-block pre {
margin: 0;
padding: 16px;
padding-top: 32px; /* Space for the copy button and language label */
overflow-x: auto;
color: #e0e0e0;
font-size: 14px;
line-height: 1.5;
}
.code-block .copy-button {
position: absolute;
top: 8px;
right: 8px;
background: rgba(255, 255, 255, 0.1);
color: #fff;
border: none;
border-radius: 4px;
padding: 4px 8px;
font-size: 12px;
cursor: pointer;
display: flex;
align-items: center;
gap: 4px;
transition: all 0.2s ease;
opacity: 0;
}
.code-block:hover .copy-button {
opacity: 1;
}
.code-block .copy-button:hover {
background: rgba(255, 255, 255, 0.2);
}
.code-block .copy-button svg {
width: 14px;
height: 14px;
}
.code-block .language-label {
position: absolute;
top: 8px;
left: 8px;
color: #888;
font-size: 12px;
font-family: 'Inter', sans-serif;
}
/* Syntax Highlighting */
.code-block .keyword { color: #569CD6; }
.code-block .string { color: #CE9178; }
.code-block .comment { color: #6A9955; }
.code-block .number { color: #B5CEA8; }
.code-block .function { color: #DCDCAA; }
.code-block .operator { color: #D4D4D4; }
.code-block .class { color: #4EC9B0; }
.code-block .property { color: #9CDCFE; }
/* Thinking Animation Styles */
.thinking {
display: flex;
align-items: center;
gap: 12px;
}
.loading-dots {
display: flex;
gap: 4px;
}
.loading-dots span {
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--primary-color);
animation: pulse 1.5s infinite ease-in-out;
}
.loading-dots span:nth-child(2) { animation-delay: 0.2s; }
.loading-dots span:nth-child(3) { animation-delay: 0.4s; }
@keyframes pulse {
0%, 100% { transform: scale(0.5); opacity: 0.5; }
50% { transform: scale(1); opacity: 1; }
}
/* Scrollbar styling */
::-webkit-scrollbar {
width: 6px;
}
::-webkit-scrollbar-track {
background: transparent;
}
::-webkit-scrollbar-thumb {
background: var(--primary-color);
border-radius: 3px;
}
/* Add smooth animations */
@keyframes slideIn {
from {
transform: translateX(-100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
@keyframes messageSlide {
from {
transform: translateY(20px);
opacity: 0;
}
to {
transform: translateY(0);
opacity: 1;
}
}
/* Add glow effect to messages */
.message {
position: relative;
overflow: hidden;
}
.message.user-message::after {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(
45deg,
transparent,
rgba(45, 212, 191, 0.1),
transparent
);
animation: shine 2s infinite;
}
@keyframes shine {
0% {
transform: translateX(-100%) translateY(-100%);
}
50%, 100% {
transform: translateX(100%) translateY(100%);
}
}
/* Add hover effect for avatars */
.avatar:hover {
transform: scale(1.05);
transition: transform 0.2s ease;
}
/* Scroll Buttons */
.scroll-button {
position: fixed;
right: 30px;
width: 45px;
height: 45px;
border-radius: 50%;
background: #2dd4bf;
color: white;
border: none;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
visibility: hidden;
transition: opacity 0.3s;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
.scroll-button.visible {
opacity: 1;
visibility: visible;
}
.scroll-top-button {
bottom: 100px;
}
.scroll-bottom-button {
bottom: 40px;
}
/* Add a glow effect to the buttons */
.scroll-button::after {
content: '';
position: absolute;
width: 100%;
height: 100%;
border-radius: 50%;
background: inherit;
filter: blur(8px);
opacity: 0;
transition: opacity 0.3s ease;
z-index: -1;
}
.scroll-button:hover::after {
opacity: 0.5;
}
/* Add smooth scrolling to the container */
.chat-messages {
scroll-behavior: smooth;
}
/* Add a subtle animation for new messages */
@keyframes messageAppear {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.message {
animation: messageAppear 0.3s ease-out;
}
/* Add this to clear floats */
.chat-messages::after {
content: '';
display: table;
clear: both;
}
/* Responsive Design */
@media (max-width: 768px) {
body {
grid-template-columns: 1fr; /* Change to single column layout */
}
.sidebar {
position: fixed;
left: -100%;
top: 0;
bottom: 0;
width: 280px;
z-index: 1000;
transition: left 0.3s ease;
padding: 12px;
background: var(--secondary-color);
backdrop-filter: blur(10px);
box-shadow: none;
}
.sidebar.active {
left: 0;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.3);
}
.menu-button {
position: fixed;
left: 15px;
top: 15px;
z-index: 1001;
background: var(--primary-color);
border: none;
border-radius: 8px;
width: 36px;
height: 36px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
color: white;
}
.chat-header {
padding: 15px 70px;
height: 50px;
display: flex;
align-items: center;
justify-content: center;
}
.chat-title {
font-size: 16px;
max-width: 80%;
}
.main-container {
padding-top: 0;
height: 100vh;
margin-left: 0;
width: 100%;
position: relative;
z-index: 1;
}
.message {
max-width: 90%;
padding: 10px 12px;
}
.input-container {
padding: 12px;
width: calc(100% - 24px);
}
.scroll-button {
right: 10px;
width: 40px;
height: 40px;
}
/* Adjust code blocks for mobile */
.code-block {
max-width: 100%;
overflow-x: auto;
}
.code-block pre {
padding: 12px;
font-size: 12px;
}
.chat-list {
padding-bottom: 20px;
height: calc(100vh - 80px);
overflow-y: auto;
}
.chat-item {
padding: 12px 10px;
font-size: 14px;
margin-bottom: 4px;
}
.chat-item span {
max-width: 200px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* Adjust new chat button for mobile */
.new-chat-btn {
margin: 0 0 12px 0;
width: calc(100% - 24px);
padding: 12px;
font-size: 14px;
}
}
/* Add overlay for mobile menu */
.overlay {
display: none;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 999;
}
.overlay.active {
display: block;
}
/* Enhanced Background */
body {
background: linear-gradient(135deg, #0f172a 0%, #1e1b4b 100%);
position: relative;
overflow: hidden;
}
/* Animated background elements */
.background-effects {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 0;
pointer-events: none;
}
.background-effects::before,
.background-effects::after {
content: '';
position: absolute;
width: 300px;
height: 300px;
border-radius: 50%;
filter: blur(100px);
opacity: 0.15;
animation: floatAround 20s infinite ease-in-out;
}
.background-effects::before {
background: #00ffaa;
top: -150px;
left: -150px;
}
.background-effects::after {
background: #00c8ff;
bottom: -150px;
right: -150px;
animation-delay: -10s;
}
@keyframes floatAround {
0%, 100% { transform: translate(0, 0); }
25% { transform: translate(100px, 100px); }
50% { transform: translate(0, 200px); }
75% { transform: translate(-100px, 100px); }
}
/* Welcome Message Styles */
.welcome-message {
background: rgba(255, 255, 255, 0.05);
border-radius: 12px;
padding: 20px;
margin: 10px 20px 24px 20px;
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.1);
animation: fadeIn 0.5s ease-out;
max-width: calc(100% - 40px);
}
.welcome-message h3 {
color: var(--primary-color);
margin: 0 0 12px 0;
font-size: 1.2rem;
}
.welcome-message p {
margin: 0 0 16px 0;
line-height: 1.5;
font-size: 0.95rem;
}
.quick-actions {
display: flex;
gap: 8px;
flex-wrap: wrap;
margin-top: 16px;
}
.quick-action-btn {
background: rgba(255, 255, 255, 0.1);
border: none;
padding: 8px 16px;
border-radius: 20px;
color: var(--text-primary);
cursor: pointer;
transition: all 0.3s ease;
font-size: 14px;
white-space: nowrap;
position: relative;
overflow: hidden;
}
.quick-action-btn:hover {
background: var(--primary-color);
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(45, 212, 191, 0.3);
}
.quick-action-btn:active {
transform: translateY(0);
}
/* Add ripple effect */
.quick-action-btn::after {
content: '';
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
pointer-events: none;
background-image: radial-gradient(circle, #fff 10%, transparent 10.01%);
background-repeat: no-repeat;
background-position: 50%;
transform: scale(10, 10);
opacity: 0;
transition: transform .5s, opacity 1s;
}
.quick-action-btn:active::after {
transform: scale(0, 0);
opacity: .3;
transition: 0s;
}
/* Add glow effect on hover */
.quick-action-btn:hover::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
border-radius: 20px;
background: var(--primary-color);
z-index: -1;
filter: blur(8px);
opacity: 0.5;
transition: opacity 0.3s ease;
}
/* Mobile adjustments for hover effects */
@media (max-width: 768px) {
.quick-action-btn {
padding: 10px 16px; /* Slightly larger touch target */
}
.quick-action-btn:active {
background: var(--primary-color);
transform: scale(0.98);
}
}
/* Mobile Responsive Styles */
@media (max-width: 768px) {
.welcome-message {
margin: 10px 10px 20px 10px;
padding: 15px;
max-width: calc(100% - 20px);
}
.welcome-message h3 {
font-size: 1.1rem;
margin-bottom: 10px;
}
.welcome-message p {
font-size: 0.9rem;
margin-bottom: 12px;
}
.quick-actions {
gap: 6px;
margin-top: 12px;
}
.quick-action-btn {
padding: 6px 12px;
font-size: 13px;
flex: 1 1 calc(50% - 6px); /* Two buttons per row on mobile */
text-align: center;
min-width: calc(50% - 6px);
max-width: calc(50% - 6px);
}
}
/* Add fade in animation */
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* Enhanced Input Area */
.input-container {
position: relative;
backdrop-filter: blur(10px);
}
.input-wrapper {
position: relative;
}
.input-actions {
position: absolute;
right: 50px;
top: 50%;
transform: translateY(-50%);
display: flex;
gap: 8px;
}
.input-action-btn {
background: none;
border: none;
color: var(--text-secondary);
cursor: pointer;
padding: 4px;
transition: all 0.2s ease;
}
.input-action-btn:hover {
color: var(--primary-color);
}
/* Settings Button */
.settings-button {
position: absolute;
right: 20px;
top: 50%;
transform: translateY(-50%);
width: 40px;
height: 40px;
border-radius: 10px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
color: var(--text-secondary);
transition: all 0.3s ease;
background: rgba(255, 255, 255, 0.1);
}
.settings-button:hover {
background: var(--primary-color);
color: white;
transform: translateY(-50%) scale(1.05);
}
/* Settings Modal */
.settings-modal {
display: none;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 1000;
backdrop-filter: blur(5px);
}
.settings-modal.active {
display: flex;
align-items: center;
justify-content: center;
}
.settings-content {
background: var(--secondary-color);
border-radius: 12px;
width: 90%;
max-width: 500px;
position: relative;
animation: modalSlide 0.3s ease;
}
.settings-header {
padding: 20px;
border-bottom: 1px solid var(--border-color);
display: flex;
justify-content: space-between;
align-items: center;
}
.settings-header h2 {
margin: 0;
color: var(--text-primary);
}
.close-settings {
background: none;
border: none;
color: var(--text-secondary);
font-size: 24px;
cursor: pointer;
padding: 0;
}
.settings-body {
padding: 20px;
}
.settings-section {
margin-bottom: 24px;
}
.settings-section h3 {
margin: 0 0 12px 0;
color: var(--text-primary);
}
.theme-options {
display: flex;
gap: 8px;
}
.theme-btn {
padding: 8px 16px;
border-radius: 8px;
border: 1px solid var(--border-color);
background: transparent;
color: var(--text-primary);
cursor: pointer;
transition: all 0.3s ease;
}
.theme-btn.active {
background: var(--primary-color);
border-color: var(--primary-color);
}
.language-select {
width: 100%;
padding: 8px;
border-radius: 8px;
background: var(--bg-color);
color: var(--text-primary);
border: 1px solid var(--border-color);
}
@keyframes modalSlide {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* Mobile Responsive */
@media (max-width: 768px) {
.settings-button {
right: 15px;
width: 36px;
height: 36px;
}
.settings-content {
width: 95%;
margin: 20px;
}
}
/* Landing Page Styles */
.landing-page {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(135deg, #0f172a 0%, #1e1b4b 100%);
z-index: 9999;
overflow-y: auto;
transition: opacity 0.5s ease, transform 0.5s ease;
-webkit-overflow-scrolling: touch; /* Smooth scrolling on iOS */
}
.landing-page.hidden {
opacity: 0;
transform: translateY(-20px);
pointer-events: none;
}
.landing-container {
max-width: 1200px;
margin: 0 auto;
padding: 40px 20px;
}
.hero-section {
text-align: center;
padding: 60px 0;
animation: fadeIn 1s ease-out;
}
.hero-title {
font-size: 3.5rem;
margin-bottom: 20px;
background: linear-gradient(135deg, #2dd4bf, #818cf8);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
}
.hero-subtitle {
font-size: 1.2rem;
color: var(--text-secondary);
margin-bottom: 40px;
}
.features-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 30px;
padding: 40px 0;
}
.feature-card {
background: rgba(255, 255, 255, 0.05);
border-radius: 15px;
padding: 30px;
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.1);
transition: transform 0.3s ease;
}
.feature-card:hover {
transform: translateY(-5px);
}
.feature-icon {
font-size: 2rem;
margin-bottom: 20px;
color: var(--primary-color);
}
.feature-title {
font-size: 1.5rem;
margin-bottom: 15px;
color: var(--primary-color);
}
.feature-description {
color: var(--text-secondary);
}
.cta-button {
display: inline-block;
background: linear-gradient(135deg, #2dd4bf, #818cf8);
color: white;
padding: 15px 40px;
border-radius: 30px;
text-decoration: none;
font-weight: 600;
font-size: 1.1rem;
transition: all 0.3s ease;
border: none;
cursor: pointer;
margin-top: 40px;
}
.cta-button:hover {
transform: translateY(-2px);
box-shadow: 0 10px 20px rgba(45, 212, 191, 0.2);
}
/* Mobile Responsive */
@media (max-width: 768px) {
.hero-title {
font-size: 2.5rem;
}
.hero-subtitle {
font-size: 1rem;
padding: 0 20px;
}
.features-grid {
grid-template-columns: 1fr;
padding: 20px;
}
.feature-card {
padding: 20px;
}
}
/* Update existing landing page styles */
.landing-page {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(135deg, #0f172a 0%, #1e1b4b 100%);
z-index: 9999;
overflow-y: auto;
transition: opacity 0.5s ease, transform 0.5s ease;
-webkit-overflow-scrolling: touch; /* Smooth scrolling on iOS */
}
/* Mobile responsive adjustments */
@media (max-width: 768px) {
.landing-container {
padding: 20px 15px;
}
.hero-section {
padding: 40px 0;
}
.hero-title {
font-size: 2.2rem;
padding: 0 10px;
margin-bottom: 15px;
}
.hero-subtitle {
font-size: 1rem;
padding: 0 15px;
margin-bottom: 30px;
}
.features-grid {
grid-template-columns: 1fr;
gap: 15px;
padding: 20px 0;
}
.feature-card {
padding: 20px;
margin: 0 10px;
}
.feature-title {
font-size: 1.2rem;
}
.feature-description {
font-size: 0.9rem;
}
.cta-button {
padding: 12px 30px;
font-size: 1rem;
margin-top: 30px;
width: 80%;
max-width: 300px;
}
}
/* Small mobile devices */
@media (max-width: 380px) {
.hero-title {
font-size: 1.8rem;
}
.feature-card {
padding: 15px;
}
.cta-button {
padding: 10px 25px;
font-size: 0.9rem;
}
}
/* Mobile responsive fixes */
@media (max-width: 768px) {
body {
grid-template-columns: 1fr; /* Single column layout for mobile */
}
.main-container {
width: 100%;
height: 100vh;
position: relative;
overflow: hidden;
}
.chat-messages {
height: calc(100vh - 180px); /* Adjust for header and input */
padding: 10px;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
position: relative;
margin-bottom: 60px; /* Space for input container */
}
.welcome-message {
position: relative;
width: calc(100% - 20px);
margin: 10px auto;
z-index: 1;
}
.input-container {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background: var(--bg-color);
padding: 10px;
border-top: 1px solid var(--border-color);
z-index: 100;
width: 100%;
max-width: 100%;
margin: 0;
box-sizing: border-box;
}
.input-wrapper {
max-width: 100%;
margin: 0;
}
#user-input {
font-size: 16px; /* Prevent zoom on mobile */
padding: 8px;
}
.message {
max-width: 85%;
margin-bottom: 10px;
}
/* Fix scroll buttons for mobile */
.scroll-button {
width: 36px;
height: 36px;
right: 10px;
z-index: 101;
}
.scroll-top-button {
bottom: 80px;
}
.scroll-bottom-button {
bottom: 130px;
}
/* Adjust chat header for mobile */
.chat-header {
padding: 10px;
height: auto;
z-index: 99;
}
/* Quick action buttons adjustment */
.quick-actions {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 8px;
padding: 0 5px;
}
.quick-action-btn {
width: 100%;
padding: 8px;
font-size: 14px;
text-align: center;
white-space: normal;
}
}
/* Small screen adjustments */
@media (max-width: 380px) {
.chat-messages {
height: calc(100vh - 160px);
}
.message {
max-width: 90%;
padding: 8px 12px;
}
.input-container {
padding: 8px;
}
}
</style>
</head>
<body>
<div class="landing-page" id="landing-page">
<div class="landing-container">
<section class="hero-section">
<h1 class="hero-title">Welcome to Rxple AI</h1>
<p class="hero-subtitle">Experience the future of AI-powered conversations with our advanced chatbot</p>
</section>
<div class="features-grid">
<div class="feature-card">
<div class="feature-icon">🤖</div>
<h3 class="feature-title">Advanced AI Technology</h3>
<p class="feature-description">
Powered by state-of-the-art language models, our AI understands context and provides accurate, relevant responses.
</p>
</div>
<div class="feature-card">
<div class="feature-icon">💡</div>
<h3 class="feature-title">Smart Assistance</h3>
<p class="feature-description">
Get help with coding, writing, analysis, and more. Our AI adapts to your needs and learning style.
</p>
</div>
<div class="feature-card">
<div class="feature-icon">🔒</div>
<h3 class="feature-title">Secure & Private</h3>
<p class="feature-description">
Your conversations are private and secure. We prioritize your data protection and privacy.
</p>
</div>
<div class="feature-card">
<div class="feature-icon"></div>
<h3 class="feature-title">Real-time Responses</h3>
<p class="feature-description">
Get instant answers to your questions with our lightning-fast response system.
</p>
</div>
<div class="feature-card">
<div class="feature-icon">📱</div>
<h3 class="feature-title">Mobile Friendly</h3>
<p class="feature-description">
Access our AI assistant from any device with a seamless, responsive design.
</p>
</div>
<div class="feature-card">
<div class="feature-icon">🔄</div>
<h3 class="feature-title">Continuous Learning</h3>
<p class="feature-description">
Our AI constantly improves and updates its knowledge to provide better assistance.
</p>
</div>
</div>
<section class="hero-section">
<button class="cta-button" onclick="startChat()">Start Chatting with AI</button>
</section>
</div>
</div>
<aside class="sidebar">
<button class="new-chat-btn" onclick="createNewChat()">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="12" y1="5" x2="12" y2="19"></line>
<line x1="5" y1="12" x2="19" y2="12"></line>
</svg>
New Chat
</button>
<div class="chat-list" id="chat-list">
<!-- Chat items will be added here dynamically -->
</div>
</aside>
<main class="main-container">
<div class="chat-header">
<div class="settings-button" id="settings-button" title="Settings">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6z"/>
<path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"/>
</svg>
</div>
<h1 class="chat-title" id="current-chat-title">New Chat</h1>
</div>
<div class="chat-messages" id="chat-messages"></div>
<button id="scroll-top" class="scroll-button scroll-top-button" title="Scroll to top">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M18 15l-6-6-6 6"/>
</svg>
</button>
<button id="scroll-bottom" class="scroll-button scroll-bottom-button" title="Scroll to bottom">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M6 9l6 6 6-6"/>
</svg>
</button>
<div class="input-container">
<div class="input-wrapper">
<input
type="text"
id="user-input"
placeholder="Send a message..."
autocomplete="off"
autofocus
>
<button class="send-button" id="send-button" onclick="sendMessage()">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M22 2L11 13M22 2L15 22L11 13L2 9L22 2Z"></path>
</svg>
</button>
</div>
</div>
</main>
<button class="menu-button" id="menu-button" style="display: none;">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="3" y1="12" x2="21" y2="12"></line>
<line x1="3" y1="6" x2="21" y2="6"></line>
<line x1="3" y1="18" x2="21" y2="18"></line>
</svg>
</button>
<div class="overlay" id="overlay"></div>
<div class="background-effects"></div>
<div class="welcome-message">
<h3>👋 Welcome to AI Chat Assistant</h3>
<p>I'm here to help you with any questions or tasks. Here are some things I can do:</p>
<div class="quick-actions">
<button class="quick-action-btn" onclick="sendQuickAction('Tell me a joke')">Tell me a joke</button>
<button class="quick-action-btn" onclick="sendQuickAction('Write a poem')">Write a poem</button>
<button class="quick-action-btn" onclick="sendQuickAction('Explain quantum physics')">Explain quantum physics</button>
<button class="quick-action-btn" onclick="sendQuickAction('Help with coding')">Help with coding</button>
</div>
</div>
<div class="settings-modal" id="settings-modal">
<div class="settings-content">
<div class="settings-header">
<h2>Settings</h2>
<button class="close-settings">&times;</button>
</div>
<div class="settings-body">
<div class="settings-section">
<h3>Theme</h3>
<div class="theme-options">
<button class="theme-btn active" data-theme="dark">Dark</button>
<button class="theme-btn" data-theme="light">Light</button>
<button class="theme-btn" data-theme="system">System</button>
</div>
</div>
<div class="settings-section">
<h3>Language</h3>
<select class="language-select">
<option value="en">English</option>
<option value="es">Español</option>
<option value="fr">Français</option>
</select>
</div>
</div>
</div>
</div>
<script>
// Global variables
const MISTRAL_API_KEY = 'UgKksYvcKnoxvJ13q5UBjL3AdU8Mu1DQ';
const chatMessages = document.getElementById('chat-messages');
const userInput = document.getElementById('user-input');
const sendButton = document.getElementById('send-button');
const scrollTopBtn = document.getElementById('scroll-top');
const scrollBottomBtn = document.getElementById('scroll-bottom');
let lastScrollTop = 0;
let scrollCount = 0;
let scrollTimeout;
let chats = [];
let currentChatId = null;
// Initialize everything when the page loads
document.addEventListener('DOMContentLoaded', () => {
initializeScrollButtons();
// Only create one initial chat if no chats exist
if (chats.length === 0) {
createNewChat();
}
// Add event listeners
userInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
sendMessage();
}
});
userInput.addEventListener('input', () => {
const isEmpty = userInput.value.trim() === '';
sendButton.classList.toggle('disabled', isEmpty);
});
// Initialize send button state
sendButton.classList.add('disabled');
});
// Remove all the duplicate function declarations and keep only one version of each:
// - createNewChat
// - updateChatList
// - deleteChat
// - switchChat
// - updateChatTitle
// - clearMessages
// - formatMessage
// - escapeHtml
// - handleCopyClick
// - sendMessage
// - removeMessage
// - initializeScrollButtons
// - handleScroll
// - scrollToTop
// - scrollToBottom
// Update the addMessage function to include both chat and scroll functionality
function addMessage(text, sender, save = true) {
const messageDiv = document.createElement('div');
messageDiv.className = `message ${sender}-message`;
const avatar = document.createElement('div');
avatar.className = `avatar ${sender}-avatar`;
avatar.textContent = sender === 'user' ? 'U' : 'AI';
const content = document.createElement('div');
content.className = 'message-content';
if (text === 'Thinking...') {
content.innerHTML = `
<div class="thinking">
<span>Thinking</span>
<div class="loading-dots">
<span></span>
<span></span>
<span></span>
</div>
</div>`;
} else {
content.innerHTML = formatMessage(text);
// Add copy functionality to any code blocks
content.querySelectorAll('.copy-button').forEach(button => {
button.addEventListener('click', handleCopyClick);
});
}
messageDiv.appendChild(avatar);
messageDiv.appendChild(content);
const id = Date.now();
messageDiv.id = `message-${id}`;
chatMessages.appendChild(messageDiv);
// Save message to current chat
if (save && currentChatId) {
const chat = chats.find(c => c.id === currentChatId);
if (chat) {
chat.messages.push({ content: text, sender });
// Auto-generate title from first user message
if (chat.title === 'New Chat' && sender === 'user') {
const title = text.slice(0, 30) + (text.length > 30 ? '...' : '');
updateChatTitle(title);
}
}
}
// Improved scroll handling
const shouldScroll = chatMessages.scrollTop + chatMessages.clientHeight >= chatMessages.scrollHeight - 100;
// Wait for content to be rendered
setTimeout(() => {
if (shouldScroll) {
chatMessages.scrollTo({
top: chatMessages.scrollHeight,
behavior: 'smooth'
});
}
handleScroll();
}, 100);
// Scroll to bottom after adding message
setTimeout(() => {
chatMessages.scrollTop = chatMessages.scrollHeight;
}, 100);
return id;
}
function formatMessage(text) {
const codeBlockRegex = /```(\w*)\n([\s\S]*?)```/g;
let formattedText = text;
// Process code blocks
formattedText = formattedText.replace(codeBlockRegex, (match, language, code) => {
const highlightedCode = highlightSyntax(code.trim(), language);
return `
<div class="code-block" data-language="${language || 'plaintext'}">
<span class="language-label">${language || 'plaintext'}</span>
<pre><code>${highlightedCode}</code></pre>
<button class="copy-button" data-code="${encodeURIComponent(code.trim())}">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M8 4v12a2 2 0 002 2h8a2 2 0 002-2V7.242a2 2 0 00-.602-1.43L16.083 2.57A2 2 0 0014.685 2H10a2 2 0 00-2 2z"/>
<path d="M16 18v2a2 2 0 01-2 2H6a2 2 0 01-2-2V9a2 2 0 012-2h2"/>
</svg>
Copy
</button>
</div>
`;
});
return formattedText;
}
function highlightSyntax(code, language) {
// Basic syntax highlighting
return code
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
// Keywords
.replace(/\b(function|const|let|var|if|else|return|class|import|export|default|new|this|for|while|break|continue)\b/g, '<span class="keyword">$1</span>')
// Strings
.replace(/(".*?"|'.*?'|`.*?`)/g, '<span class="string">$1</span>')
// Comments
.replace(/(\/\/.*|\/\*[\s\S]*?\*\/)/g, '<span class="comment">$1</span>')
// Numbers
.replace(/\b(\d+)\b/g, '<span class="number">$1</span>')
// Functions
.replace(/(\w+)\(/g, '<span class="function">$1</span>(')
// Classes
.replace(/\b([A-Z]\w*)\b/g, '<span class="class">$1</span>')
// Properties
.replace(/\.(\w+)\b/g, '.<span class="property">$1</span>');
}
function handleCopyClick(event) {
const button = event.target.closest('.copy-button');
if (!button) return;
const code = decodeURIComponent(button.dataset.code);
navigator.clipboard.writeText(code).then(() => {
const originalText = button.innerHTML;
button.innerHTML = `
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M20 6L9 17l-5-5"/>
</svg>
Copied!
`;
button.style.background = '#10B981';
setTimeout(() => {
button.innerHTML = originalText;
button.style.background = '';
}, 2000);
}).catch(err => {
console.error('Failed to copy:', err);
button.textContent = 'Failed';
});
}
async function sendMessage() {
const message = userInput.value.trim();
if (!message) return;
try {
addMessage(message, 'user');
userInput.value = '';
scrollToBottom(true); // Immediate scroll after user message
const loadingId = addMessage('Thinking...', 'ai');
scrollToBottom(true); // Immediate scroll for loading message
const response = await fetch('https://api.mistral.ai/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${MISTRAL_API_KEY}`,
'Accept': 'application/json'
},
body: JSON.stringify({
model: "mistral-small",
messages: [
{
role: "system",
content: "You are a helpful AI assistant. Provide clear and concise responses."
},
{
role: "user",
content: message
}
],
max_tokens: 1000,
temperature: 0.7
})
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({}));
throw new Error(
`API Error (${response.status}): ${errorData.error?.message || 'Unknown error'}`
);
}
const data = await response.json();
removeMessage(loadingId);
if (data.choices && data.choices[0] && data.choices[0].message) {
removeMessage(loadingId);
addMessage(data.choices[0].message.content, 'ai');
scrollToBottom(); // Smooth scroll for AI response
} else {
console.error('Unexpected API response:', data);
addMessage('Sorry, I received an unexpected response format.', 'ai');
scrollToBottom();
}
} catch (error) {
console.error('Error details:', error);
removeMessage(loadingId);
addMessage(`Sorry, I encountered an error: ${error.message}`, 'ai');
scrollToBottom();
} finally {
userInput.disabled = false;
sendButton.classList.remove('disabled');
userInput.focus();
}
}
function removeMessage(id) {
const message = document.getElementById(`message-${id}`);
if (message) {
message.remove();
}
}
function initializeScrollButtons() {
const scrollTopBtn = document.getElementById('scroll-top');
const scrollBottomBtn = document.getElementById('scroll-bottom');
const chatMessages = document.getElementById('chat-messages');
chatMessages.addEventListener('scroll', () => {
// Show top button when scrolled down
if (chatMessages.scrollTop > 500) {
scrollTopBtn.classList.add('visible');
} else {
scrollTopBtn.classList.remove('visible');
}
// Show bottom button when not at bottom
const isAtBottom = chatMessages.scrollHeight - chatMessages.scrollTop - chatMessages.clientHeight < 100;
if (!isAtBottom) {
scrollBottomBtn.classList.add('visible');
} else {
scrollBottomBtn.classList.remove('visible');
}
});
// Scroll to top
scrollTopBtn.addEventListener('click', () => {
chatMessages.scrollTo({ top: 0, behavior: 'smooth' });
});
// Scroll to bottom
scrollBottomBtn.addEventListener('click', () => {
chatMessages.scrollTo({ top: chatMessages.scrollHeight, behavior: 'smooth' });
});
}
function handleScroll() {
const scrollTop = chatMessages.scrollTop;
const scrollHeight = chatMessages.scrollHeight;
const clientHeight = chatMessages.clientHeight;
if (scrollTop > 100) {
scrollTopBtn.classList.add('visible');
} else {
scrollTopBtn.classList.remove('visible');
}
if (scrollTop < lastScrollTop) {
scrollCount++;
if (scrollCount >= 2) {
scrollBottomBtn.classList.add('visible');
}
} else {
scrollCount = 0;
scrollBottomBtn.classList.remove('visible');
}
clearTimeout(scrollTimeout);
scrollTimeout = setTimeout(() => {
scrollCount = 0;
}, 1000);
lastScrollTop = scrollTop;
if (scrollHeight - scrollTop - clientHeight < 20) {
scrollBottomBtn.classList.remove('visible');
}
}
function scrollToTop() {
chatMessages.scrollTo({
top: 0,
behavior: 'smooth'
});
}
function scrollToBottom(immediate = false) {
const chatMessages = document.getElementById('chat-messages');
if (chatMessages) {
const scrollOptions = {
top: chatMessages.scrollHeight,
behavior: immediate ? 'auto' : 'smooth'
};
// For mobile Safari
if (chatMessages.scrollTo) {
chatMessages.scrollTo(scrollOptions);
} else {
chatMessages.scrollTop = chatMessages.scrollHeight;
}
}
}
// Initialize with a new chat
createNewChat();
function createNewChat() {
const chatId = Date.now();
const chat = {
id: chatId,
title: 'New Chat',
messages: []
};
chats.push(chat);
currentChatId = chatId;
// Clear existing messages
clearMessages();
// Update chat list and title
updateChatList();
updateChatTitle('New Chat');
// Add welcome message for every new chat
const welcomeMessage = document.createElement('div');
welcomeMessage.className = 'welcome-message';
welcomeMessage.innerHTML = `
<h3>👋 Welcome to Rxple AI Chat Assistant</h3>
<p>I'm here to help you with any questions or tasks. Here are some things I can do:</p>
<div class="quick-actions">
<button class="quick-action-btn" onclick="sendQuickAction('Tell me a joke')">Tell me a joke</button>
<button class="quick-action-btn" onclick="sendQuickAction('Write a poem')">Write a poem</button>
<button class="quick-action-btn" onclick="sendQuickAction('Explain quantum physics')">Explain quantum physics</button>
<button class="quick-action-btn" onclick="sendQuickAction('Help with coding')">Help with coding</button>
</div>
`;
chatMessages.appendChild(welcomeMessage);
}
function updateChatList() {
const chatList = document.getElementById('chat-list');
chatList.innerHTML = '';
chats.forEach(chat => {
const chatItem = document.createElement('div');
chatItem.className = `chat-item ${chat.id === currentChatId ? 'active' : ''}`;
chatItem.innerHTML = `
<span>${chat.title}</span>
<button class="delete-chat" onclick="deleteChat(${chat.id})">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M3 6h18"></path>
<path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"></path>
<path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path>
</svg>
</button>
`;
chatItem.onclick = (e) => {
if (!e.target.closest('.delete-chat')) {
switchChat(chat.id);
}
};
chatList.appendChild(chatItem);
});
}
function deleteChat(chatId) {
if (confirm('Are you sure you want to delete this chat?')) {
chats = chats.filter(chat => chat.id !== chatId);
if (currentChatId === chatId) {
if (chats.length > 0) {
switchChat(chats[0].id);
} else {
createNewChat();
}
}
updateChatList();
}
}
function switchChat(chatId) {
currentChatId = chatId;
const chat = chats.find(c => c.id === chatId);
clearMessages();
chat.messages.forEach(msg => {
addMessage(msg.content, msg.sender, false);
});
updateChatTitle(chat.title);
updateChatList();
}
function updateChatTitle(title) {
document.getElementById('current-chat-title').textContent = title;
if (currentChatId) {
const chat = chats.find(c => c.id === currentChatId);
if (chat) {
chat.title = title;
updateChatList();
}
}
}
function clearMessages() {
chatMessages.innerHTML = '';
}
// Mobile menu functionality
const menuButton = document.getElementById('menu-button');
const sidebar = document.querySelector('.sidebar');
const overlay = document.getElementById('overlay');
function checkScreenSize() {
if (window.innerWidth <= 768) {
menuButton.style.display = 'flex';
menuButton.style.opacity = sidebar.classList.contains('active') ? '0' : '1';
} else {
menuButton.style.display = 'none';
menuButton.style.opacity = '1';
sidebar.classList.remove('active');
overlay.classList.remove('active');
}
}
menuButton.addEventListener('click', () => {
sidebar.classList.toggle('active');
overlay.classList.toggle('active');
// Hide menu button when sidebar is open
menuButton.style.opacity = sidebar.classList.contains('active') ? '0' : '1';
});
overlay.addEventListener('click', () => {
sidebar.classList.remove('active');
overlay.classList.remove('active');
// Show menu button when sidebar is closed
menuButton.style.opacity = '1';
});
// Check screen size on load and resize
window.addEventListener('load', checkScreenSize);
window.addEventListener('resize', checkScreenSize);
// Close sidebar when clicking outside on mobile
document.addEventListener('click', (e) => {
if (window.innerWidth <= 768 &&
!e.target.closest('.sidebar') &&
!e.target.closest('.menu-button') &&
sidebar.classList.contains('active')) {
sidebar.classList.remove('active');
overlay.classList.remove('active');
}
});
// Update scroll button positions for mobile
function updateScrollButtonPositions() {
const inputHeight = document.querySelector('.input-container').offsetHeight;
const scrollTopBtn = document.getElementById('scroll-top');
const scrollBottomBtn = document.getElementById('scroll-bottom');
if (window.innerWidth <= 768) {
scrollBottomBtn.style.bottom = `${inputHeight + 20}px`;
scrollTopBtn.style.bottom = `${inputHeight + 80}px`;
} else {
scrollBottomBtn.style.bottom = '40px';
scrollTopBtn.style.bottom = '100px';
}
}
// Update positions on load and resize
window.addEventListener('load', updateScrollButtonPositions);
window.addEventListener('resize', updateScrollButtonPositions);
// Add transition to menu button in your styles
const style = document.createElement('style');
style.textContent = `
.menu-button {
transition: opacity 0.3s ease;
}
`;
document.head.appendChild(style);
function sendQuickAction(text) {
userInput.value = text;
sendMessage();
}
// Settings functionality
const settingsButton = document.getElementById('settings-button');
const settingsModal = document.getElementById('settings-modal');
const closeSettings = document.querySelector('.close-settings');
settingsButton.addEventListener('click', () => {
settingsModal.classList.add('active');
});
closeSettings.addEventListener('click', () => {
settingsModal.classList.remove('active');
});
// Close modal when clicking outside
settingsModal.addEventListener('click', (e) => {
if (e.target === settingsModal) {
settingsModal.classList.remove('active');
}
});
// Theme switching functionality
const themeButtons = document.querySelectorAll('.theme-btn');
themeButtons.forEach(button => {
button.addEventListener('click', () => {
themeButtons.forEach(btn => btn.classList.remove('active'));
button.classList.add('active');
// Add theme switching logic here
});
});
function startChat() {
document.getElementById('landing-page').classList.add('hidden');
// Remove the createNewChat() call here since it's already initialized
}
// Add this to handle mobile viewport height issues
function setMobileHeight() {
const vh = window.innerHeight * 0.01;
document.documentElement.style.setProperty('--vh', `${vh}px`);
}
window.addEventListener('load', setMobileHeight);
window.addEventListener('resize', setMobileHeight);
</script>
</body>
</html>