wop commited on
Commit
dd73a3e
·
verified ·
1 Parent(s): e6e185b

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +242 -228
index.html CHANGED
@@ -1,244 +1,258 @@
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>Amber Chat Visualizer</title>
7
- <script src="https://cdn.tailwindcss.com"></script>
8
- <style>
9
- /* Softer Amber Palette */
10
- :root {
11
- --amber-50: #fffbeb;
12
- --amber-100: #fef3c7;
13
- --amber-200: #fde68a;
14
- --amber-300: #fcd34d;
15
- --amber-400: #fbbf24;
16
- --amber-500: #f59e0b;
17
- --amber-600: #d97706;
18
- --amber-700: #b45309;
19
- --amber-800: #92400e;
20
- --amber-900: #453a2a; /* Softer dark brown */
21
- --amber-950: #30251a; /* Softer deep brown */
22
- }
23
-
24
- body {
25
- background-color: #f8f5f0; /* Light cream background */
26
- color: #5d4e37; /* Soft brown text */
27
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
28
- }
29
-
30
- .custom-scrollbar::-webkit-scrollbar {
31
- width: 6px;
32
- }
33
- .custom-scrollbar::-webkit-scrollbar-track {
34
- background: transparent;
35
- }
36
- .custom-scrollbar::-webkit-scrollbar-thumb {
37
- background: rgba(245, 158, 11, 0.2);
38
- border-radius: 10px;
39
- }
40
-
41
- .editable:focus {
42
- outline: none;
43
- border-bottom: 1px solid var(--amber-500);
44
- background: rgba(245, 158, 11, 0.1);
45
- }
46
-
47
- /* Logic for mobile/desktop layout */
48
- .main-container {
49
- height: calc(100vh - 100px);
50
- }
51
-
52
- @media (max-width: 768px) {
53
- .main-container {
54
- flex-direction: column;
55
- overflow-y: auto;
56
- }
57
- .panel {
58
- height: 500px;
59
- width: 100% !important;
60
- flex-shrink: 0;
61
- }
62
- }
63
- </style>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  </head>
65
  <body class="flex flex-col h-screen overflow-hidden">
66
 
67
- <!-- Header -->
68
- <header class="flex items-center justify-between px-6 py-4 border-b border-amber-200/50 bg-white shadow-sm">
69
- <div class="flex items-center space-x-3">
70
- <div class="bg-amber-100 p-2 rounded-lg">
71
- <svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 text-amber-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
72
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 10h.01M12 10h.01M16 10h.01M9 16H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-5l-5 5v-5z" />
73
- </svg>
74
- </div>
75
- <h1 class="text-xl font-bold tracking-tight text-amber-700">Amber Chat <span class="text-amber-500 font-light">Visualizer</span></h1>
76
- </div>
77
- <div class="flex items-center gap-4 text-xs font-mono text-amber-600">
78
- <span class="hidden sm:inline">JSON + VISUAL SYNC</span>
79
- <button onclick="copyJson()" class="p-2 hover:bg-amber-100 rounded-full transition-colors text-amber-600">
80
- <svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
81
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 5H6a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2v-1M8 5a2 2 0 002 2h2a2 2 0 002-2M8 5a2 2 0 012-2h2a2 2 0 012 2m0 0h2a2 2 0 012 2v3m2 4H10m0 0l3-3m-3 3l3 3" />
82
- </svg>
83
- </button>
84
- </div>
85
- </header>
86
-
87
- <!-- Main Content -->
88
- <main class="main-container flex-1 flex overflow-hidden">
89
-
90
- <!-- Editor Panel -->
91
- <section class="panel w-1/2 flex flex-col bg-white/60 border-r border-amber-200/30">
92
- <div class="px-4 py-2 bg-white/80 border-b border-amber-200/30 flex justify-between items-center">
93
- <span class="text-[10px] font-mono uppercase tracking-widest text-amber-600">source.json</span>
94
- <span id="json-error" class="text-[10px] text-red-500 hidden">Invalid JSON</span>
95
- </div>
96
- <textarea id="json-editor"
97
- class="flex-1 p-6 bg-transparent text-amber-700 font-mono text-sm outline-none resize-none custom-scrollbar"
98
- spellcheck="false"></textarea>
99
- </section>
100
-
101
- <!-- Preview Panel -->
102
- <section id="chat-preview" class="panel w-1/2 overflow-y-auto p-6 md:p-12 bg-amber-50/50 custom-scrollbar">
103
- <!-- Bubbles injected here -->
104
- </section>
105
-
106
- </main>
107
-
108
- <!-- Footer -->
109
- <footer class="h-10 border-t border-amber-200/30 flex items-center justify-between px-6 bg-white text-[10px] uppercase tracking-widest text-amber-600">
110
- <div>Click text to edit visually</div>
111
- <div>Soft Amber Mode</div>
112
- </footer>
113
-
114
- <script>
115
- const jsonEditor = document.getElementById('json-editor');
116
- const chatPreview = document.getElementById('chat-preview');
117
- const errorLabel = document.getElementById('json-error');
118
-
119
- let data = {
120
- "messages": [
121
- { "role": "system", "content": "You are a helpful assistant." },
122
- { "role": "user", "content": "Tell me about this yellow theme." },
123
- { "role": "assistant", "content": "This is a soft amber theme. By using warmer tones and reducing contrast, it aims to be much easier on your eyes during long coding sessions." }
124
- ]
125
- };
126
-
127
- // Initialize
128
- jsonEditor.value = JSON.stringify(data, null, 2);
129
- renderChat();
130
-
131
- // Listen for JSON changes
132
- jsonEditor.addEventListener('input', (e) => {
133
- try {
134
- const parsed = JSON.parse(e.target.value);
135
- if (parsed.messages && Array.isArray(parsed.messages)) {
136
- data = parsed;
137
- renderChat();
138
- errorLabel.classList.add('hidden');
139
- }
140
- } catch (err) {
141
- errorLabel.classList.remove('hidden');
142
- }
143
- });
144
-
145
- function renderChat() {
146
- chatPreview.innerHTML = '';
147
- data.messages.forEach((msg, index) => {
148
- const bubble = createBubble(msg, index);
149
- chatPreview.appendChild(bubble);
150
- });
151
- }
152
-
153
- function createBubble(msg, index) {
154
- const isUser = msg.role.toLowerCase() === 'user';
155
- const isAssistant = msg.role.toLowerCase() === 'assistant';
156
- const isSystem = msg.role.toLowerCase() === 'system';
157
-
158
- const container = document.createElement('div');
159
- container.className = `flex flex-col mb-8 w-full ${isUser ? 'items-end' : 'items-start'}`;
160
-
161
- // Role label
162
- const label = document.createElement('div');
163
- label.contentEditable = true;
164
- label.className = `text-[10px] font-bold uppercase tracking-widest mb-1 px-1 outline-none ${isUser ? 'text-amber-600' : 'text-amber-500'}`;
165
- label.innerText = msg.role;
166
- label.onblur = (e) => updateData(index, 'role', e.target.innerText);
167
-
168
- // Bubble body
169
- const body = document.createElement('div');
170
- const bubbleClasses = isUser
171
- ? 'bg-amber-200 text-amber-900 rounded-br-none font-medium'
172
- : isSystem
173
- ? 'bg-amber-100/50 border border-amber-200/50 text-amber-700 italic text-center w-full max-w-none text-sm'
174
- : 'bg-white border border-amber-200/50 text-amber-800 rounded-bl-none';
175
-
176
- body.className = `max-w-[90%] md:max-w-[85%] rounded-2xl px-5 py-3 shadow-sm ${bubbleClasses}`;
177
-
178
- // Handle thought tags
179
- const content = msg.content || "";
180
- const thinkMatch = content.match([\s\S]?)</think>/);
181
- const thoughtText = thinkMatch ? thinkMatch[1] : "";
182
- const cleanText = content.replace(/[\s\S]?</think>/, '').trim();
183
-
184
- if (isAssistant || thoughtText) {
185
- const details = document.createElement('details');
186
- details.open = !!thoughtText;
187
- details.className = 'mb-3 bg-amber-50/50 rounded-lg border border-amber-200/50 overflow-hidden';
188
-
189
- const summary = document.createElement('summary');
190
- summary.className = 'cursor-pointer p-2 text-[10px] font-bold text-amber-600 hover:bg-amber-100/50 flex items-center select-none outline-none';
191
- summary.innerHTML = `<span class="mr-1">▶</span> THOUGHT PROCESS`;
192
-
193
- const thoughtDiv = document.createElement('div');
194
- thoughtDiv.contentEditable = true;
195
- thoughtDiv.className = 'p-3 text-xs text-amber-600/70 border-t border-amber-200/50 outline-none leading-relaxed';
196
- thoughtDiv.innerText = thoughtText;
197
- thoughtDiv.onblur = (e) => updateData(index, 'thought', e.target.innerText);
198
-
199
- details.appendChild(summary);
200
- details.appendChild(thoughtDiv);
201
- body.appendChild(details);
202
- }
203
 
204
- const mainText = document.createElement('div');
205
- mainText.contentEditable = true;
206
- mainText.className = 'outline-none whitespace-pre-wrap leading-relaxed text-sm md:text-base';
207
- mainText.innerText = cleanText;
208
- mainText.onblur = (e) => updateData(index, 'content', e.target.innerText);
209
 
210
- body.appendChild(mainText);
211
- container.appendChild(label);
212
- container.appendChild(body);
213
- return container;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
214
  }
215
 
216
- function updateData(index, field, value) {
217
- const msg = data.messages[index];
218
- if (field === 'role') {
219
- msg.role = value;
220
- } else if (field === 'thought') {
221
- const currentContent = msg.content || "";
222
- const cleanPart = currentContent.replace(/[\s\S]*?<\/think>/, '').trim();
223
- msg.content = `${value}
224
- ${cleanPart}`;
225
- } else if (field === 'content') {
226
- const currentContent = msg.content || "";
227
- const thinkMatch = currentContent.match([\s\S]*?)</think>/);
228
- const thinkPart = thinkMatch ? `${thinkMatch[1]}` : "";
229
- msg.content = thinkPart + value;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
230
  }
231
 
232
- jsonEditor.value = JSON.stringify(data, null, 2);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
233
  }
234
 
235
- function copyJson() {
236
- jsonEditor.select();
237
- document.execCommand('copy');
238
- const btn = document.querySelector('button[onclick="copyJson()"]');
239
- const original = btn.innerHTML;
240
- btn.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 text-green-500" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" /></svg>`;
241
- setTimeout(() => btn.innerHTML = original, 2000);
242
  }
243
- </script></body>
 
244
  </html>
 
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>Amber Chat Visualizer — Dark Theme</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <style>
9
+ /* Dark Amber Palette */
10
+ :root {
11
+ --bg-dark: #1a1a1a; /* deep gray background */
12
+ --bg-panel: #2a2a2a; /* panels slightly lighter */
13
+ --amber-light: #f0c04a; /* soft amber highlight */
14
+ --amber-muted: #d9b54a; /* for subtle accents */
15
+ --text-light: #e0e0e0; /* main text */
16
+ --text-muted: #b0a074; /* secondary text */
17
+ --border: rgba(240,192,74,0.15);
18
+ --scroll-thumb: rgba(240,192,74,0.25);
19
+ --bubble-user: rgba(240,192,74,0.15);
20
+ --bubble-assistant: rgba(255,255,255,0.05);
21
+ --bubble-system: rgba(240,192,74,0.08);
22
+ }
23
+
24
+ body {
25
+ background-color: var(--bg-dark);
26
+ color: var(--text-light);
27
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
28
+ }
29
+
30
+ .custom-scrollbar::-webkit-scrollbar { width: 6px; }
31
+ .custom-scrollbar::-webkit-scrollbar-track { background: transparent; }
32
+ .custom-scrollbar::-webkit-scrollbar-thumb {
33
+ background: var(--scroll-thumb);
34
+ border-radius: 10px;
35
+ }
36
+
37
+ .editable:focus {
38
+ outline: none;
39
+ background: rgba(240,192,74,0.05);
40
+ border-bottom: 1px solid var(--amber-light);
41
+ }
42
+
43
+ .main-container { height: calc(100vh - 100px); }
44
+ @media (max-width:768px){
45
+ .main-container { flex-direction: column; overflow-y: auto; }
46
+ .panel { height: 500px; width: 100% !important; flex-shrink: 0; }
47
+ }
48
+
49
+ header, footer {
50
+ background: rgba(30,30,30,0.9);
51
+ border-color: var(--border);
52
+ backdrop-filter: blur(6px);
53
+ }
54
+
55
+ .panel {
56
+ background: var(--bg-panel);
57
+ border-color: var(--border);
58
+ }
59
+
60
+ /* Chat bubbles */
61
+ .bubble-user {
62
+ background: var(--bubble-user);
63
+ color: var(--text-light);
64
+ border-radius: 16px;
65
+ padding: 0.75rem 1.25rem;
66
+ max-width: 90%;
67
+ box-shadow: 0 4px 12px rgba(0,0,0,0.2);
68
+ }
69
+ .bubble-assistant {
70
+ background: var(--bubble-assistant);
71
+ color: var(--text-light);
72
+ border-radius: 16px;
73
+ padding: 0.75rem 1.25rem;
74
+ max-width: 90%;
75
+ box-shadow: 0 4px 12px rgba(0,0,0,0.1);
76
+ }
77
+ .bubble-system {
78
+ background: var(--bubble-system);
79
+ color: var(--amber-muted);
80
+ font-style: italic;
81
+ border-left: 3px solid var(--amber-muted);
82
+ padding-left: 12px;
83
+ border-radius: 6px;
84
+ }
85
+
86
+ /* Thought boxes */
87
+ .thought-box {
88
+ background: rgba(240,192,74,0.05);
89
+ border: 1px solid var(--border);
90
+ padding: 8px;
91
+ border-radius: 8px;
92
+ }
93
+ details > summary {
94
+ cursor: pointer;
95
+ padding: 4px;
96
+ font-size: 10px;
97
+ font-weight: bold;
98
+ color: var(--amber-light);
99
+ list-style: none;
100
+ }
101
+ details > summary::-webkit-details-marker { display: none; }
102
+
103
+ </style>
104
  </head>
105
  <body class="flex flex-col h-screen overflow-hidden">
106
 
107
+ <header class="flex items-center justify-between px-6 py-4 border-b shadow-sm">
108
+ <div class="flex items-center space-x-3">
109
+ <div class="p-2 rounded-lg bg-amber-light/20">
110
+ <svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 text-amber-light" fill="none" viewBox="0 0 24 24" stroke="currentColor">
111
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 10h.01M12 10h.01M16 10h.01M9 16H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-5l-5 5v-5z"/>
112
+ </svg>
113
+ </div>
114
+ <h1 class="text-xl font-bold tracking-tight" style="color:var(--amber-light)">Amber Chat <span class="text-amber-muted font-light">Visualizer</span></h1>
115
+ </div>
116
+ <div class="flex items-center gap-4 text-xs font-mono text-amber-muted">
117
+ <span class="hidden sm:inline">JSON + VISUAL SYNC</span>
118
+ <button onclick="copyJson()" class="p-2 hover:bg-amber-light/10 rounded-full transition-colors">
119
+ <svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
120
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 5H6a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2v-1M8 5a2 2 0 002 2h2a2 2 0 002-2"/>
121
+ </svg>
122
+ </button>
123
+ </div>
124
+ </header>
125
+
126
+ <main class="main-container flex-1 flex overflow-hidden">
127
+ <section class="panel w-1/2 flex flex-col border-r">
128
+ <div class="px-4 py-2 bg-transparent border-b flex justify-between items-center">
129
+ <span class="text-[10px] font-mono uppercase tracking-widest text-amber-muted">source.json</span>
130
+ <span id="json-error" class="text-[10px] text-red-500 hidden">Invalid JSON</span>
131
+ </div>
132
+ <textarea id="json-editor"
133
+ class="flex-1 p-6 bg-transparent text-amber-light font-mono text-sm outline-none resize-none custom-scrollbar" spellcheck="false"></textarea>
134
+ </section>
135
+
136
+ <section id="chat-preview" class="panel w-1/2 overflow-y-auto p-6 md:p-12 custom-scrollbar">
137
+ <!-- bubbles injected -->
138
+ </section>
139
+ </main>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140
 
141
+ <footer class="h-10 flex items-center justify-between px-6 border-t text-[10px] uppercase tracking-widest text-amber-muted">
142
+ <div>Click text to edit visually</div>
143
+ <div>Dark Amber Mode</div>
144
+ </footer>
 
145
 
146
+ <script>
147
+ const jsonEditor = document.getElementById('json-editor');
148
+ const chatPreview = document.getElementById('chat-preview');
149
+ const errorLabel = document.getElementById('json-error');
150
+
151
+ let data = {
152
+ "messages":[
153
+ { "role":"system","content":"You are a helpful assistant."},
154
+ { "role":"user","content":"Tell me about this dark theme."},
155
+ { "role":"assistant","content":"<think>The user wants a calmer dark version.</think>This is a dark amber theme: deep charcoal backgrounds, soft amber highlights, low-contrast bubbles for comfortable nighttime reading."}
156
+ ]
157
+ };
158
+
159
+ jsonEditor.value = JSON.stringify(data,null,2);
160
+ renderChat();
161
+
162
+ jsonEditor.addEventListener('input', (e)=>{
163
+ try{
164
+ const parsed = JSON.parse(e.target.value);
165
+ if(parsed.messages && Array.isArray(parsed.messages)){
166
+ data=parsed; renderChat(); errorLabel.classList.add('hidden');
167
+ }
168
+ }catch(err){ errorLabel.classList.remove('hidden'); }
169
+ });
170
+
171
+ function renderChat(){
172
+ chatPreview.innerHTML='';
173
+ data.messages.forEach((msg,i)=>{ chatPreview.appendChild(createBubble(msg,i)); });
174
  }
175
 
176
+ function createBubble(msg,index){
177
+ const isUser=msg.role.toLowerCase()==='user';
178
+ const isAssistant=msg.role.toLowerCase()==='assistant';
179
+ const isSystem=msg.role.toLowerCase()==='system';
180
+
181
+ const container=document.createElement('div');
182
+ container.className=`flex flex-col mb-6 w-full ${isUser?'items-end':'items-start'}`;
183
+
184
+ const label=document.createElement('div');
185
+ label.contentEditable=true;
186
+ label.className='text-[10px] font-semibold uppercase tracking-widest mb-1 px-1 outline-none';
187
+ label.style.color=isUser?'var(--amber-light)':'var(--amber-muted)';
188
+ label.innerText=msg.role;
189
+ label.onblur=(e)=>updateData(index,'role',e.target.innerText);
190
+
191
+ const body=document.createElement('div');
192
+ let bubbleClass='';
193
+ if(isUser) bubbleClass='bubble-user';
194
+ else if(isSystem) bubbleClass='bubble-system';
195
+ else bubbleClass='bubble-assistant';
196
+ body.className=bubbleClass;
197
+
198
+ const content=msg.content||"";
199
+ const thinkMatch=content.match(/<think>([\s\S]*?)<\/think>/);
200
+ const thoughtText=thinkMatch?thinkMatch[1]:"";
201
+ const cleanText=content.replace(/<think>[\s\S]*?<\/think>/,'').trim();
202
+
203
+ if(isAssistant||thoughtText){
204
+ const details=document.createElement('details');
205
+ details.open=!!thoughtText;
206
+ details.className='thought-box';
207
+ const summary=document.createElement('summary');
208
+ summary.innerHTML='<span class="mr-2">▶</span> THOUGHT PROCESS';
209
+ const thoughtDiv=document.createElement('div');
210
+ thoughtDiv.contentEditable=true;
211
+ thoughtDiv.className='p-2 text-xs';
212
+ thoughtDiv.innerText=thoughtText;
213
+ thoughtDiv.onblur=(e)=>updateData(index,'thought',e.target.innerText);
214
+ details.appendChild(summary);
215
+ details.appendChild(thoughtDiv);
216
+ body.appendChild(details);
217
+ }
218
+
219
+ const mainText=document.createElement('div');
220
+ mainText.contentEditable=true;
221
+ mainText.className='outline-none whitespace-pre-wrap leading-relaxed';
222
+ mainText.innerText=cleanText;
223
+ mainText.onblur=(e)=>updateData(index,'content',e.target.innerText);
224
+
225
+ body.appendChild(mainText);
226
+ container.appendChild(label);
227
+ container.appendChild(body);
228
+ return container;
229
  }
230
 
231
+ function updateData(index,field,value){
232
+ const msg=data.messages[index];
233
+ if(field==='role') msg.role=value;
234
+ else if(field==='thought'){
235
+ const current=msg.content||"";
236
+ const clean=current.replace(/<think>[\s\S]*?<\/think>/,'').trim();
237
+ msg.content=`<think>${value}</think>${clean}`;
238
+ }
239
+ else if(field==='content'){
240
+ const current=msg.content||"";
241
+ const thinkMatch=current.match(/<think>([\s\S]*?)<\/think>/);
242
+ const thinkPart=thinkMatch?`<think>${thinkMatch[1]}</think>`:'';
243
+ msg.content=thinkPart+value;
244
+ }
245
+ jsonEditor.value=JSON.stringify(data,null,2);
246
  }
247
 
248
+ function copyJson(){
249
+ jsonEditor.select();
250
+ document.execCommand('copy');
251
+ const btn=document.querySelector('button[onclick="copyJson()"]');
252
+ const orig=btn.innerHTML;
253
+ btn.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 text-green-500" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/></svg>';
254
+ setTimeout(()=>btn.innerHTML=orig,1400);
255
  }
256
+ </script>
257
+ </body>
258
  </html>