@arcai/chatbot 1.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,214 @@
1
+ import EventEmitter from 'eventemitter3';
2
+ import { defaultStyles } from './styles';
3
+ import { botIcon, sendIcon, closeIcon } from './icons';
4
+ export class Chatbot extends EventEmitter {
5
+ constructor(config) {
6
+ super();
7
+ this.messages = [];
8
+ this.isOpen = false;
9
+ this.config = {
10
+ ...config,
11
+ position: config.position || 'bottom-right',
12
+ primaryColor: config.primaryColor || '#2563eb',
13
+ textColor: config.textColor || '#1e293b',
14
+ bgImage: config.bgImage || '',
15
+ opacity: config.opacity || 100,
16
+ glassmorphism: config.glassmorphism || false,
17
+ floatAnimation: config.floatAnimation || 'float-up-down',
18
+ showAvatar: config.showAvatar ?? true,
19
+ showThoughts: config.showThoughts ?? true,
20
+ thoughtInterval: config.thoughtInterval || 8,
21
+ customThoughts: config.customThoughts || [
22
+ "I'm here to help!",
23
+ "Have any questions?",
24
+ "Need assistance?",
25
+ ],
26
+ onMessage: config.onMessage || this.defaultMessageHandler,
27
+ };
28
+ this.injectStyles();
29
+ this.container = this.createContainer();
30
+ this.chat = this.createChat();
31
+ document.body.appendChild(this.container);
32
+ if (this.config.showThoughts) {
33
+ this.startThoughtCycle();
34
+ }
35
+ }
36
+ injectStyles() {
37
+ const style = document.createElement('style');
38
+ style.textContent = defaultStyles;
39
+ document.head.appendChild(style);
40
+ // Inject custom CSS variables
41
+ const customStyles = document.createElement('style');
42
+ customStyles.textContent = `
43
+ :root {
44
+ --arcai-primary-color: ${this.config.primaryColor};
45
+ --arcai-primary-color-dark: ${this.adjustColor(this.config.primaryColor, -20)};
46
+ }
47
+ `;
48
+ document.head.appendChild(customStyles);
49
+ }
50
+ createContainer() {
51
+ const container = document.createElement('div');
52
+ container.className = `arcai-widget ${this.config.position}`;
53
+ const launcher = document.createElement('button');
54
+ launcher.className = `arcai-launcher ${this.config.floatAnimation}`;
55
+ launcher.innerHTML = botIcon;
56
+ launcher.onclick = () => this.toggle();
57
+ container.appendChild(launcher);
58
+ return container;
59
+ }
60
+ createChat() {
61
+ const chat = document.createElement('div');
62
+ chat.className = 'arcai-chat';
63
+ // Header
64
+ const header = document.createElement('div');
65
+ header.className = `arcai-header ${this.config.glassmorphism ? 'glassmorphism' : ''}`;
66
+ if (this.config.bgImage) {
67
+ header.style.backgroundImage = `url(${this.config.bgImage})`;
68
+ header.style.backgroundSize = 'cover';
69
+ header.style.backgroundPosition = 'center';
70
+ header.style.backgroundColor = `rgba(37, 99, 235, ${this.config.opacity / 100})`;
71
+ }
72
+ const title = document.createElement('div');
73
+ title.className = 'arcai-title';
74
+ title.innerHTML = `${botIcon} <span>Chat Assistant</span>`;
75
+ const closeBtn = document.createElement('button');
76
+ closeBtn.className = 'arcai-close';
77
+ closeBtn.innerHTML = closeIcon;
78
+ closeBtn.onclick = () => this.close();
79
+ header.appendChild(title);
80
+ header.appendChild(closeBtn);
81
+ // Messages
82
+ const messages = document.createElement('div');
83
+ messages.className = 'arcai-messages';
84
+ // Input
85
+ const input = document.createElement('div');
86
+ input.className = 'arcai-input';
87
+ const form = document.createElement('form');
88
+ form.className = 'arcai-input-form';
89
+ form.onsubmit = (e) => {
90
+ e.preventDefault();
91
+ const inputField = form.querySelector('input');
92
+ if (inputField?.value.trim()) {
93
+ this.sendMessage(inputField.value);
94
+ inputField.value = '';
95
+ }
96
+ };
97
+ const inputField = document.createElement('input');
98
+ inputField.className = 'arcai-input-field';
99
+ inputField.placeholder = 'Type your message...';
100
+ const sendBtn = document.createElement('button');
101
+ sendBtn.className = 'arcai-send';
102
+ sendBtn.type = 'submit';
103
+ sendBtn.innerHTML = sendIcon;
104
+ form.appendChild(inputField);
105
+ form.appendChild(sendBtn);
106
+ input.appendChild(form);
107
+ chat.appendChild(header);
108
+ chat.appendChild(messages);
109
+ chat.appendChild(input);
110
+ this.container.appendChild(chat);
111
+ return chat;
112
+ }
113
+ async sendMessage(content) {
114
+ const message = {
115
+ id: Math.random().toString(36).substr(2, 9),
116
+ role: 'user',
117
+ content,
118
+ timestamp: new Date(),
119
+ };
120
+ this.messages.push(message);
121
+ this.renderMessage(message);
122
+ try {
123
+ const response = await this.config.onMessage(content);
124
+ const botMessage = {
125
+ id: Math.random().toString(36).substr(2, 9),
126
+ role: 'bot',
127
+ content: response,
128
+ timestamp: new Date(),
129
+ };
130
+ this.messages.push(botMessage);
131
+ this.renderMessage(botMessage);
132
+ }
133
+ catch (error) {
134
+ console.error('Error sending message:', error);
135
+ }
136
+ }
137
+ renderMessage(message) {
138
+ const messagesContainer = this.chat.querySelector('.arcai-messages');
139
+ if (!messagesContainer)
140
+ return;
141
+ const messageEl = document.createElement('div');
142
+ messageEl.className = `arcai-message ${message.role}`;
143
+ if (this.config.showAvatar) {
144
+ const avatar = document.createElement('div');
145
+ avatar.className = 'arcai-avatar';
146
+ avatar.innerHTML = botIcon;
147
+ messageEl.appendChild(avatar);
148
+ }
149
+ const bubble = document.createElement('div');
150
+ bubble.className = 'arcai-bubble';
151
+ bubble.textContent = message.content;
152
+ messageEl.appendChild(bubble);
153
+ messagesContainer.appendChild(messageEl);
154
+ messagesContainer.scrollTop = messagesContainer.scrollHeight;
155
+ }
156
+ showThought() {
157
+ const thought = this.config.customThoughts[Math.floor(Math.random() * this.config.customThoughts.length)];
158
+ const thoughtEl = document.createElement('div');
159
+ thoughtEl.className = 'arcai-thought';
160
+ thoughtEl.textContent = thought;
161
+ const launcher = this.container.querySelector('.arcai-launcher');
162
+ if (launcher) {
163
+ launcher.appendChild(thoughtEl);
164
+ setTimeout(() => {
165
+ thoughtEl.remove();
166
+ }, 4000);
167
+ }
168
+ }
169
+ startThoughtCycle() {
170
+ if (this.thoughtTimeout) {
171
+ clearTimeout(this.thoughtTimeout);
172
+ }
173
+ const showNextThought = () => {
174
+ if (!this.isOpen) {
175
+ this.showThought();
176
+ }
177
+ this.thoughtTimeout = setTimeout(showNextThought, this.config.thoughtInterval * 1000);
178
+ };
179
+ setTimeout(showNextThought, 2000);
180
+ }
181
+ adjustColor(color, amount) {
182
+ const hex = color.replace('#', '');
183
+ const num = parseInt(hex, 16);
184
+ const r = Math.min(255, Math.max(0, (num >> 16) + amount));
185
+ const g = Math.min(255, Math.max(0, ((num >> 8) & 0x00ff) + amount));
186
+ const b = Math.min(255, Math.max(0, (num & 0x0000ff) + amount));
187
+ return `#${((r << 16) | (g << 8) | b).toString(16).padStart(6, '0')}`;
188
+ }
189
+ async defaultMessageHandler(message) {
190
+ return `I received your message: "${message}". This is a default response. Please configure a custom message handler for more meaningful interactions.`;
191
+ }
192
+ open() {
193
+ this.isOpen = true;
194
+ this.chat.classList.add('open');
195
+ }
196
+ close() {
197
+ this.isOpen = false;
198
+ this.chat.classList.remove('open');
199
+ }
200
+ toggle() {
201
+ if (this.isOpen) {
202
+ this.close();
203
+ }
204
+ else {
205
+ this.open();
206
+ }
207
+ }
208
+ destroy() {
209
+ if (this.thoughtTimeout) {
210
+ clearTimeout(this.thoughtTimeout);
211
+ }
212
+ this.container.remove();
213
+ }
214
+ }
@@ -0,0 +1 @@
1
+ export declare const defaultStyles = "\n/* Dark mode support */\n.arcai-widget[data-theme=\"dark\"] {\n --arcai-bg: #1a1a1a;\n --arcai-text: #ffffff;\n --arcai-border: #333333;\n}\n\n.arcai-widget[data-theme=\"light\"] {\n --arcai-bg: #ffffff;\n --arcai-text: #1a1a1a;\n --arcai-border: #e5e5e5;\n}\n\n.arcai-widget {\n position: fixed;\n z-index: 9999;\n transform: none;\n font-family: system-ui, -apple-system, sans-serif;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.arcai-widget.bottom-right {\n bottom: 20px;\n right: 20px;\n transform-origin: bottom right;\n}\n\n.arcai-widget.bottom-left {\n bottom: 20px;\n left: 20px;\n transform-origin: bottom left;\n}\n\n.arcai-widget.top-right {\n top: 20px;\n right: 20px;\n transform-origin: top right;\n}\n\n.arcai-widget.top-left {\n top: 20px;\n left: 20px;\n transform-origin: top left;\n}\n\n.arcai-widget.outside-left {\n left: -28px; /* Half of launcher width */\n top: 50%;\n transform: translateY(-50%);\n transform-origin: center left;\n}\n\n.arcai-widget.outside-left:hover {\n left: 20px;\n}\n\n.arcai-widget.outside-left .arcai-chat {\n left: 80px;\n bottom: auto;\n top: 50%;\n transform: translateY(-50%);\n}\n\n.arcai-widget.outside-right {\n right: -28px;\n top: 50%;\n transform: translateY(-50%);\n transform-origin: center right;\n}\n\n.arcai-widget.outside-right:hover {\n right: 20px;\n}\n\n.arcai-widget.outside-right .arcai-chat {\n right: 80px;\n bottom: auto;\n top: 50%;\n transform: translateY(-50%);\n}\n\n.arcai-launcher {\n width: 56px;\n height: 56px;\n border-radius: 50%;\n background: var(--arcai-primary-color, #2563eb);\n color: white;\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: transform 0.2s, box-shadow 0.2s;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n position: relative;\n z-index: 2;\n}\n\n.arcai-launcher:hover {\n transform: translateY(-2px);\n box-shadow: 0 6px 16px rgba(0, 0, 0, 0.12);\n}\n\n.arcai-launcher.float-up-down {\n animation: arcaiFloatUpDown 3s ease-in-out infinite;\n}\n\n.arcai-launcher.float-left-right {\n animation: arcaiFloatLeftRight 3s ease-in-out infinite;\n}\n\n.arcai-launcher.float-diagonal {\n animation: arcaiFloatDiagonal 4s ease-in-out infinite;\n}\n\n.arcai-launcher.float-circle {\n animation: arcaiFloatCircle 5s ease-in-out infinite;\n}\n\n/* Sound effect animations */\n@keyframes arcaiSoundWave {\n 0% { transform: scale(1); opacity: 0.8; }\n 100% { transform: scale(2); opacity: 0; }\n}\n\n.arcai-sound-wave {\n position: absolute;\n border: 2px solid var(--arcai-primary-color);\n width: 100%;\n height: 100%;\n border-radius: 50%;\n animation: arcaiSoundWave 1s ease-out infinite;\n}\n\n/* Typing indicator */\n.arcai-typing {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 8px;\n background: var(--arcai-bg);\n border-radius: 12px;\n margin-bottom: 8px;\n}\n\n.arcai-typing-dot {\n width: 6px;\n height: 6px;\n background: var(--arcai-primary-color);\n border-radius: 50%;\n animation: arcaiDotPulse 1.4s infinite;\n}\n\n.arcai-typing-dot:nth-child(2) { animation-delay: 0.2s; }\n.arcai-typing-dot:nth-child(3) { animation-delay: 0.4s; }\n\n@keyframes arcaiDotPulse {\n 0%, 60%, 100% { transform: scale(1); opacity: 1; }\n 30% { transform: scale(1.2); opacity: 0.4; }\n}\n\n/* Suggested messages */\n.arcai-suggestions {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n margin-top: 12px;\n}\n\n.arcai-suggestion {\n padding: 6px 12px;\n background: var(--arcai-primary-color);\n color: white;\n border-radius: 16px;\n font-size: 14px;\n cursor: pointer;\n transition: all 0.2s;\n border: none;\n}\n\n.arcai-suggestion:hover {\n transform: translateY(-1px);\n filter: brightness(1.1);\n}\n\n/* Attachment handling */\n.arcai-attachments {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n margin-top: 8px;\n}\n\n.arcai-attachment {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 4px 8px;\n background: var(--arcai-bg);\n border-radius: 4px;\n font-size: 12px;\n}\n\n.arcai-attachment-remove {\n cursor: pointer;\n opacity: 0.6;\n transition: opacity 0.2s;\n}\n\n.arcai-attachment-remove:hover {\n opacity: 1;\n}\n\n.arcai-chat {\n position: fixed;\n width: 380px;\n height: 600px;\n background: white;\n border-radius: 12px;\n box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n opacity: 0;\n transform: translateY(20px);\n transition: opacity 0.3s, transform 0.3s;\n z-index: 1;\n}\n\n.arcai-chat.open {\n opacity: 1;\n transform: translateY(0);\n}\n\n.arcai-header {\n padding: 16px;\n background: var(--arcai-primary-color, #2563eb);\n color: white;\n display: flex;\n align-items: center;\n justify-content: space-between;\n}\n\n.arcai-header.glassmorphism {\n backdrop-filter: blur(8px);\n background: rgba(37, 99, 235, 0.8);\n}\n\n.arcai-title {\n display: flex;\n align-items: center;\n gap: 8px;\n font-weight: 500;\n}\n\n.arcai-close {\n background: none;\n border: none;\n color: white;\n cursor: pointer;\n padding: 4px;\n border-radius: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.arcai-close:hover {\n background: rgba(255, 255, 255, 0.1);\n}\n\n.arcai-messages {\n flex: 1;\n overflow-y: auto;\n padding: 16px;\n background: #f8fafc;\n}\n\n.arcai-message {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n margin-bottom: 16px;\n opacity: 0;\n transform: translateY(10px);\n animation: arcaiMessageSlideUp 0.3s forwards;\n}\n\n.arcai-message.user {\n flex-direction: row-reverse;\n}\n\n.arcai-avatar {\n width: 32px;\n height: 32px;\n border-radius: 50%;\n background: #e2e8f0;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.arcai-bubble {\n background: white;\n padding: 12px 16px;\n border-radius: 12px;\n max-width: 70%;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);\n}\n\n.arcai-message.user .arcai-bubble {\n background: var(--arcai-primary-color, #2563eb);\n color: white;\n}\n\n.arcai-input {\n padding: 16px;\n background: white;\n border-top: 1px solid #e2e8f0;\n}\n\n.arcai-input-form {\n display: flex;\n gap: 8px;\n}\n\n.arcai-input-field {\n flex: 1;\n padding: 8px 16px;\n border: 1px solid #e2e8f0;\n border-radius: 24px;\n outline: none;\n font-size: 14px;\n}\n\n.arcai-input-field:focus {\n border-color: var(--arcai-primary-color, #2563eb);\n box-shadow: 0 0 0 2px rgba(37, 99, 235, 0.1);\n}\n\n.arcai-send {\n width: 36px;\n height: 36px;\n border-radius: 50%;\n background: var(--arcai-primary-color, #2563eb);\n color: white;\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background-color 0.2s;\n}\n\n.arcai-send:hover {\n background: var(--arcai-primary-color-dark, #1d4ed8);\n}\n\n.arcai-thought {\n position: absolute;\n bottom: 100%;\n right: 0;\n margin-bottom: 12px;\n background: white;\n padding: 12px 16px;\n border-radius: 12px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n max-width: 240px;\n opacity: 0;\n transform: translateY(10px);\n animation: arcaiThoughtBubble 4s ease-in-out forwards;\n}\n\n.arcai-thought::after {\n content: '';\n position: absolute;\n bottom: -6px;\n right: 24px;\n width: 12px;\n height: 12px;\n background: white;\n transform: rotate(45deg);\n}\n\n@keyframes arcaiFloatUpDown {\n 0%, 100% { transform: translateY(0); }\n 50% { transform: translateY(-10px); }\n}\n\n@keyframes arcaiFloatLeftRight {\n 0%, 100% { transform: translateX(0); }\n 50% { transform: translateX(10px); }\n}\n\n@keyframes arcaiFloatDiagonal {\n 0%, 100% { transform: translate(0, 0); }\n 50% { transform: translate(5px, -5px); }\n}\n\n@keyframes arcaiFloatCircle {\n 0% { transform: translate(0, 0); }\n 25% { transform: translate(5px, -5px); }\n 50% { transform: translate(10px, 0); }\n 75% { transform: translate(5px, 5px); }\n 100% { transform: translate(0, 0); }\n}\n\n@keyframes arcaiMessageSlideUp {\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes arcaiThoughtBubble {\n 0% {\n opacity: 0;\n transform: scale(0.8) translateY(10px);\n }\n 10% {\n opacity: 1;\n transform: scale(1) translateY(0);\n }\n 90% {\n opacity: 1;\n transform: scale(1) translateY(0);\n }\n 100% {\n opacity: 0;\n transform: scale(0.8) translateY(-10px);\n }\n}";
package/dist/styles.js ADDED
@@ -0,0 +1,434 @@
1
+ export const defaultStyles = `
2
+ /* Dark mode support */
3
+ .arcai-widget[data-theme="dark"] {
4
+ --arcai-bg: #1a1a1a;
5
+ --arcai-text: #ffffff;
6
+ --arcai-border: #333333;
7
+ }
8
+
9
+ .arcai-widget[data-theme="light"] {
10
+ --arcai-bg: #ffffff;
11
+ --arcai-text: #1a1a1a;
12
+ --arcai-border: #e5e5e5;
13
+ }
14
+
15
+ .arcai-widget {
16
+ position: fixed;
17
+ z-index: 9999;
18
+ transform: none;
19
+ font-family: system-ui, -apple-system, sans-serif;
20
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
21
+ }
22
+
23
+ .arcai-widget.bottom-right {
24
+ bottom: 20px;
25
+ right: 20px;
26
+ transform-origin: bottom right;
27
+ }
28
+
29
+ .arcai-widget.bottom-left {
30
+ bottom: 20px;
31
+ left: 20px;
32
+ transform-origin: bottom left;
33
+ }
34
+
35
+ .arcai-widget.top-right {
36
+ top: 20px;
37
+ right: 20px;
38
+ transform-origin: top right;
39
+ }
40
+
41
+ .arcai-widget.top-left {
42
+ top: 20px;
43
+ left: 20px;
44
+ transform-origin: top left;
45
+ }
46
+
47
+ .arcai-widget.outside-left {
48
+ left: -28px; /* Half of launcher width */
49
+ top: 50%;
50
+ transform: translateY(-50%);
51
+ transform-origin: center left;
52
+ }
53
+
54
+ .arcai-widget.outside-left:hover {
55
+ left: 20px;
56
+ }
57
+
58
+ .arcai-widget.outside-left .arcai-chat {
59
+ left: 80px;
60
+ bottom: auto;
61
+ top: 50%;
62
+ transform: translateY(-50%);
63
+ }
64
+
65
+ .arcai-widget.outside-right {
66
+ right: -28px;
67
+ top: 50%;
68
+ transform: translateY(-50%);
69
+ transform-origin: center right;
70
+ }
71
+
72
+ .arcai-widget.outside-right:hover {
73
+ right: 20px;
74
+ }
75
+
76
+ .arcai-widget.outside-right .arcai-chat {
77
+ right: 80px;
78
+ bottom: auto;
79
+ top: 50%;
80
+ transform: translateY(-50%);
81
+ }
82
+
83
+ .arcai-launcher {
84
+ width: 56px;
85
+ height: 56px;
86
+ border-radius: 50%;
87
+ background: var(--arcai-primary-color, #2563eb);
88
+ color: white;
89
+ border: none;
90
+ cursor: pointer;
91
+ display: flex;
92
+ align-items: center;
93
+ justify-content: center;
94
+ transition: transform 0.2s, box-shadow 0.2s;
95
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
96
+ position: relative;
97
+ z-index: 2;
98
+ }
99
+
100
+ .arcai-launcher:hover {
101
+ transform: translateY(-2px);
102
+ box-shadow: 0 6px 16px rgba(0, 0, 0, 0.12);
103
+ }
104
+
105
+ .arcai-launcher.float-up-down {
106
+ animation: arcaiFloatUpDown 3s ease-in-out infinite;
107
+ }
108
+
109
+ .arcai-launcher.float-left-right {
110
+ animation: arcaiFloatLeftRight 3s ease-in-out infinite;
111
+ }
112
+
113
+ .arcai-launcher.float-diagonal {
114
+ animation: arcaiFloatDiagonal 4s ease-in-out infinite;
115
+ }
116
+
117
+ .arcai-launcher.float-circle {
118
+ animation: arcaiFloatCircle 5s ease-in-out infinite;
119
+ }
120
+
121
+ /* Sound effect animations */
122
+ @keyframes arcaiSoundWave {
123
+ 0% { transform: scale(1); opacity: 0.8; }
124
+ 100% { transform: scale(2); opacity: 0; }
125
+ }
126
+
127
+ .arcai-sound-wave {
128
+ position: absolute;
129
+ border: 2px solid var(--arcai-primary-color);
130
+ width: 100%;
131
+ height: 100%;
132
+ border-radius: 50%;
133
+ animation: arcaiSoundWave 1s ease-out infinite;
134
+ }
135
+
136
+ /* Typing indicator */
137
+ .arcai-typing {
138
+ display: flex;
139
+ align-items: center;
140
+ gap: 4px;
141
+ padding: 8px;
142
+ background: var(--arcai-bg);
143
+ border-radius: 12px;
144
+ margin-bottom: 8px;
145
+ }
146
+
147
+ .arcai-typing-dot {
148
+ width: 6px;
149
+ height: 6px;
150
+ background: var(--arcai-primary-color);
151
+ border-radius: 50%;
152
+ animation: arcaiDotPulse 1.4s infinite;
153
+ }
154
+
155
+ .arcai-typing-dot:nth-child(2) { animation-delay: 0.2s; }
156
+ .arcai-typing-dot:nth-child(3) { animation-delay: 0.4s; }
157
+
158
+ @keyframes arcaiDotPulse {
159
+ 0%, 60%, 100% { transform: scale(1); opacity: 1; }
160
+ 30% { transform: scale(1.2); opacity: 0.4; }
161
+ }
162
+
163
+ /* Suggested messages */
164
+ .arcai-suggestions {
165
+ display: flex;
166
+ flex-wrap: wrap;
167
+ gap: 8px;
168
+ margin-top: 12px;
169
+ }
170
+
171
+ .arcai-suggestion {
172
+ padding: 6px 12px;
173
+ background: var(--arcai-primary-color);
174
+ color: white;
175
+ border-radius: 16px;
176
+ font-size: 14px;
177
+ cursor: pointer;
178
+ transition: all 0.2s;
179
+ border: none;
180
+ }
181
+
182
+ .arcai-suggestion:hover {
183
+ transform: translateY(-1px);
184
+ filter: brightness(1.1);
185
+ }
186
+
187
+ /* Attachment handling */
188
+ .arcai-attachments {
189
+ display: flex;
190
+ flex-wrap: wrap;
191
+ gap: 8px;
192
+ margin-top: 8px;
193
+ }
194
+
195
+ .arcai-attachment {
196
+ display: flex;
197
+ align-items: center;
198
+ gap: 4px;
199
+ padding: 4px 8px;
200
+ background: var(--arcai-bg);
201
+ border-radius: 4px;
202
+ font-size: 12px;
203
+ }
204
+
205
+ .arcai-attachment-remove {
206
+ cursor: pointer;
207
+ opacity: 0.6;
208
+ transition: opacity 0.2s;
209
+ }
210
+
211
+ .arcai-attachment-remove:hover {
212
+ opacity: 1;
213
+ }
214
+
215
+ .arcai-chat {
216
+ position: fixed;
217
+ width: 380px;
218
+ height: 600px;
219
+ background: white;
220
+ border-radius: 12px;
221
+ box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12);
222
+ display: flex;
223
+ flex-direction: column;
224
+ overflow: hidden;
225
+ opacity: 0;
226
+ transform: translateY(20px);
227
+ transition: opacity 0.3s, transform 0.3s;
228
+ z-index: 1;
229
+ }
230
+
231
+ .arcai-chat.open {
232
+ opacity: 1;
233
+ transform: translateY(0);
234
+ }
235
+
236
+ .arcai-header {
237
+ padding: 16px;
238
+ background: var(--arcai-primary-color, #2563eb);
239
+ color: white;
240
+ display: flex;
241
+ align-items: center;
242
+ justify-content: space-between;
243
+ }
244
+
245
+ .arcai-header.glassmorphism {
246
+ backdrop-filter: blur(8px);
247
+ background: rgba(37, 99, 235, 0.8);
248
+ }
249
+
250
+ .arcai-title {
251
+ display: flex;
252
+ align-items: center;
253
+ gap: 8px;
254
+ font-weight: 500;
255
+ }
256
+
257
+ .arcai-close {
258
+ background: none;
259
+ border: none;
260
+ color: white;
261
+ cursor: pointer;
262
+ padding: 4px;
263
+ border-radius: 4px;
264
+ display: flex;
265
+ align-items: center;
266
+ justify-content: center;
267
+ }
268
+
269
+ .arcai-close:hover {
270
+ background: rgba(255, 255, 255, 0.1);
271
+ }
272
+
273
+ .arcai-messages {
274
+ flex: 1;
275
+ overflow-y: auto;
276
+ padding: 16px;
277
+ background: #f8fafc;
278
+ }
279
+
280
+ .arcai-message {
281
+ display: flex;
282
+ align-items: flex-start;
283
+ gap: 8px;
284
+ margin-bottom: 16px;
285
+ opacity: 0;
286
+ transform: translateY(10px);
287
+ animation: arcaiMessageSlideUp 0.3s forwards;
288
+ }
289
+
290
+ .arcai-message.user {
291
+ flex-direction: row-reverse;
292
+ }
293
+
294
+ .arcai-avatar {
295
+ width: 32px;
296
+ height: 32px;
297
+ border-radius: 50%;
298
+ background: #e2e8f0;
299
+ display: flex;
300
+ align-items: center;
301
+ justify-content: center;
302
+ flex-shrink: 0;
303
+ }
304
+
305
+ .arcai-bubble {
306
+ background: white;
307
+ padding: 12px 16px;
308
+ border-radius: 12px;
309
+ max-width: 70%;
310
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
311
+ }
312
+
313
+ .arcai-message.user .arcai-bubble {
314
+ background: var(--arcai-primary-color, #2563eb);
315
+ color: white;
316
+ }
317
+
318
+ .arcai-input {
319
+ padding: 16px;
320
+ background: white;
321
+ border-top: 1px solid #e2e8f0;
322
+ }
323
+
324
+ .arcai-input-form {
325
+ display: flex;
326
+ gap: 8px;
327
+ }
328
+
329
+ .arcai-input-field {
330
+ flex: 1;
331
+ padding: 8px 16px;
332
+ border: 1px solid #e2e8f0;
333
+ border-radius: 24px;
334
+ outline: none;
335
+ font-size: 14px;
336
+ }
337
+
338
+ .arcai-input-field:focus {
339
+ border-color: var(--arcai-primary-color, #2563eb);
340
+ box-shadow: 0 0 0 2px rgba(37, 99, 235, 0.1);
341
+ }
342
+
343
+ .arcai-send {
344
+ width: 36px;
345
+ height: 36px;
346
+ border-radius: 50%;
347
+ background: var(--arcai-primary-color, #2563eb);
348
+ color: white;
349
+ border: none;
350
+ cursor: pointer;
351
+ display: flex;
352
+ align-items: center;
353
+ justify-content: center;
354
+ transition: background-color 0.2s;
355
+ }
356
+
357
+ .arcai-send:hover {
358
+ background: var(--arcai-primary-color-dark, #1d4ed8);
359
+ }
360
+
361
+ .arcai-thought {
362
+ position: absolute;
363
+ bottom: 100%;
364
+ right: 0;
365
+ margin-bottom: 12px;
366
+ background: white;
367
+ padding: 12px 16px;
368
+ border-radius: 12px;
369
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
370
+ max-width: 240px;
371
+ opacity: 0;
372
+ transform: translateY(10px);
373
+ animation: arcaiThoughtBubble 4s ease-in-out forwards;
374
+ }
375
+
376
+ .arcai-thought::after {
377
+ content: '';
378
+ position: absolute;
379
+ bottom: -6px;
380
+ right: 24px;
381
+ width: 12px;
382
+ height: 12px;
383
+ background: white;
384
+ transform: rotate(45deg);
385
+ }
386
+
387
+ @keyframes arcaiFloatUpDown {
388
+ 0%, 100% { transform: translateY(0); }
389
+ 50% { transform: translateY(-10px); }
390
+ }
391
+
392
+ @keyframes arcaiFloatLeftRight {
393
+ 0%, 100% { transform: translateX(0); }
394
+ 50% { transform: translateX(10px); }
395
+ }
396
+
397
+ @keyframes arcaiFloatDiagonal {
398
+ 0%, 100% { transform: translate(0, 0); }
399
+ 50% { transform: translate(5px, -5px); }
400
+ }
401
+
402
+ @keyframes arcaiFloatCircle {
403
+ 0% { transform: translate(0, 0); }
404
+ 25% { transform: translate(5px, -5px); }
405
+ 50% { transform: translate(10px, 0); }
406
+ 75% { transform: translate(5px, 5px); }
407
+ 100% { transform: translate(0, 0); }
408
+ }
409
+
410
+ @keyframes arcaiMessageSlideUp {
411
+ to {
412
+ opacity: 1;
413
+ transform: translateY(0);
414
+ }
415
+ }
416
+
417
+ @keyframes arcaiThoughtBubble {
418
+ 0% {
419
+ opacity: 0;
420
+ transform: scale(0.8) translateY(10px);
421
+ }
422
+ 10% {
423
+ opacity: 1;
424
+ transform: scale(1) translateY(0);
425
+ }
426
+ 90% {
427
+ opacity: 1;
428
+ transform: scale(1) translateY(0);
429
+ }
430
+ 100% {
431
+ opacity: 0;
432
+ transform: scale(0.8) translateY(-10px);
433
+ }
434
+ }`;