Hma47 commited on
Commit
9838fab
·
verified ·
1 Parent(s): e28ac3e

Upload 4 files

Browse files
Apache License.txt ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ Copyright 2025 Shift Mind AI Labs
6
+
7
+ Licensed under the Apache License, Version 2.0 (the "License");
8
+ you may not use this file except in compliance with the License.
9
+ You may obtain a copy of the License at
10
+
11
+ http://www.apache.org/licenses/LICENSE-2.0
12
+
13
+ Unless required by applicable law or agreed to in writing, software
14
+ distributed under the License is distributed on an "AS IS" BASIS,
15
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ See the License for the specific language governing permissions and
17
+ limitations under the License.
README.md ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: "🚀 CopyGenius Pro – Professional Content Creation Platform"
3
+ emoji: "🚀"
4
+ colorFrom: "purple"
5
+ colorTo: "indigo"
6
+ sdk: "static"
7
+ sdk_version: "0.1.0"
8
+ app_file: "index.html"
9
+ pinned: false
10
+ ---
11
+
12
+ # 🚀 CopyGenius Pro – Professional Content Creation Platform
13
+ **Developed by Shift Mind AI Labs**
14
+
15
+ CopyGenius Pro is an open-source, privacy-first content creation platform that helps you craft compelling, professional, and multilingual copy for any purpose. Instantly generate marketing, technical, educational, or creative content—tailored by content type, tone, and advanced writing techniques, in over 90 languages.
16
+
17
+ ---
18
+
19
+ ## 🚀 Features
20
+
21
+ - **14 Content Types:** Marketing, sales, technical, social media, email, blog, UX/UI, and more.
22
+ - **10 Tone Styles:** From formal to humorous, conversational to analytical.
23
+ - **20 Writing Techniques:** Storytelling, analogies, data-driven, motivational, and more.
24
+ - **92 Languages Supported:** Full multilingual UI and copy generation.
25
+ - **Editable Output:** Instantly customize and refine generated content.
26
+ - **Advanced Cache & Privacy:** API key and prompts are stored only in your browser. Translation cache for fast, private multilingual access.
27
+
28
+ ---
29
+
30
+ ## 🛠 How to Use
31
+
32
+ 1. **Open the tool** in your browser or on Hugging Face Spaces (no install, no account).
33
+ 2. **Select your preferred language** and enter your OpenAI API key.
34
+ 3. **Describe your content brief** (up to 5000 characters).
35
+ 4. **Choose content type, tone, and writing technique** from drop-downs.
36
+ 5. **Click “Generate Professional Copy”** (or press Ctrl+Enter).
37
+ 6. **Edit, copy, and use** your AI-generated content anywhere.
38
+ 7. **Switch language** or clear translation cache anytime.
39
+
40
+ ---
41
+
42
+ ## 👩‍🏫 For Educators: Classroom & Professional Uses
43
+
44
+ - **Model good writing:** Instantly generate exemplars for any assignment or genre.
45
+ - **Multilingual writing:** Support ELLs, bilingual programs, or global projects.
46
+ - **Creative brainstorming:** Rapidly draft, revise, and compare content approaches.
47
+ - **Portfolio & assessment:** Use editable outputs for student portfolios or writing assessment.
48
+
49
+ ---
50
+
51
+ ## 👨‍💼 For Business & Creators
52
+
53
+ - **Fast content generation:** Ads, emails, blog posts, social, landing pages, and more.
54
+ - **Tone & brand control:** Instantly match house style, audience, and campaign goals.
55
+ - **Cross-language marketing:** Generate copy in 92 languages—localize campaigns in seconds.
56
+ - **Privacy & IP protection:** All work stays on your device, ready for commercial use.
57
+
58
+ ---
59
+
60
+ ## 🔐 Data Privacy Notice
61
+
62
+ - Your OpenAI API key and all prompts/content **never leave your device**.
63
+ - No data is sent to Shift Mind AI Labs, Hugging Face, or any third party.
64
+
65
+ ---
66
+
67
+ ## 📄 License
68
+
69
+ Licensed under the [Apache License 2.0](./LICENSE).
70
+
71
+ ---
72
+
73
+ ## 🧠 About Shift Mind AI Labs
74
+
75
+ Shift Mind AI Labs creates open-source, ethical AI tools for global education, business, and digital empowerment.
76
+
77
+ 🌐 https://www.shiftmind.io
78
+ ✉️ info@shiftmind.io
79
+
80
+ ---
81
+
82
+ ## 🙌 Contributing
83
+
84
+ Pull requests, suggestions, and collaborations welcome!
85
+ For partnerships, research, or school/business pilots: **info@shiftmind.io**
86
+
87
+ ---
88
+
89
+ *Professional, multilingual content creation—secure, ethical, and instantly accessible.*
index.html ADDED
@@ -0,0 +1,1787 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en" dir="ltr">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>CopyGenius Pro - Professional Content Creation Platform</title>
7
+ <style>
8
+ :root {
9
+ --primary: #7c3aed;
10
+ --secondary: #a855f7;
11
+ --accent: #c084fc;
12
+ --background: #f8fafc;
13
+ --surface: #ffffff;
14
+ --text: #1e293b;
15
+ --text-secondary: #64748b;
16
+ --border: #e2e8f0;
17
+ --success: #10b981;
18
+ --warning: #f59e0b;
19
+ --error: #ef4444;
20
+ --shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
21
+ --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
22
+ }
23
+
24
+ * {
25
+ box-sizing: border-box;
26
+ margin: 0;
27
+ padding: 0;
28
+ }
29
+
30
+ body {
31
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
32
+ background: linear-gradient(135deg, #f1f5f9 0%, #e2e8f0 100%);
33
+ color: var(--text);
34
+ line-height: 1.6;
35
+ min-height: 100vh;
36
+ padding: 15px;
37
+ transition: all 0.3s ease;
38
+ }
39
+
40
+ /* RTL Support */
41
+ [dir="rtl"] {
42
+ text-align: right;
43
+ }
44
+
45
+ [dir="rtl"] .container {
46
+ direction: rtl;
47
+ }
48
+
49
+ [dir="rtl"] .api-key-section {
50
+ margin: 15px 15px 15px auto;
51
+ }
52
+
53
+ [dir="rtl"] .features-grid,
54
+ [dir="rtl"] .options-grid,
55
+ [dir="rtl"] .content-types {
56
+ direction: rtl;
57
+ }
58
+
59
+ [dir="rtl"] .generate-btn {
60
+ direction: rtl;
61
+ }
62
+
63
+ /* Language Selection Landing */
64
+ .language-landing {
65
+ display: block;
66
+ max-width: 600px;
67
+ margin: 50px auto;
68
+ background: var(--surface);
69
+ border-radius: 16px;
70
+ box-shadow: var(--shadow-lg);
71
+ padding: 40px;
72
+ text-align: center;
73
+ }
74
+
75
+ .language-landing h1 {
76
+ font-size: 2.5rem;
77
+ font-weight: 800;
78
+ background: linear-gradient(135deg, var(--primary) 0%, var(--secondary) 100%);
79
+ -webkit-background-clip: text;
80
+ -webkit-text-fill-color: transparent;
81
+ background-clip: text;
82
+ margin-bottom: 15px;
83
+ }
84
+
85
+ .language-landing p {
86
+ font-size: 1.1rem;
87
+ color: var(--text-secondary);
88
+ margin-bottom: 30px;
89
+ }
90
+
91
+ .language-selector {
92
+ margin-bottom: 25px;
93
+ }
94
+
95
+ .language-selector label {
96
+ display: block;
97
+ margin-bottom: 10px;
98
+ font-weight: 600;
99
+ color: var(--text);
100
+ font-size: 1.1rem;
101
+ }
102
+
103
+ .language-selector select {
104
+ width: 100%;
105
+ padding: 15px 20px;
106
+ border: 2px solid var(--border);
107
+ border-radius: 12px;
108
+ font-size: 1.1rem;
109
+ font-family: inherit;
110
+ background: var(--surface);
111
+ transition: all 0.2s ease;
112
+ margin-bottom: 20px;
113
+ }
114
+
115
+ .language-selector select:focus {
116
+ outline: none;
117
+ border-color: var(--primary);
118
+ box-shadow: 0 0 0 3px rgba(124, 58, 237, 0.1);
119
+ }
120
+
121
+ .api-key-landing {
122
+ margin-bottom: 25px;
123
+ }
124
+
125
+ .api-key-landing label {
126
+ display: block;
127
+ margin-bottom: 10px;
128
+ font-weight: 600;
129
+ color: var(--text);
130
+ font-size: 1.1rem;
131
+ }
132
+
133
+ .api-key-landing input {
134
+ width: 100%;
135
+ padding: 15px 20px;
136
+ border: 2px solid var(--border);
137
+ border-radius: 12px;
138
+ font-size: 1.1rem;
139
+ background: var(--surface);
140
+ transition: all 0.2s ease;
141
+ font-family: 'Courier New', monospace;
142
+ }
143
+
144
+ .api-key-landing input:focus {
145
+ outline: none;
146
+ border-color: var(--primary);
147
+ box-shadow: 0 0 0 3px rgba(124, 58, 237, 0.1);
148
+ }
149
+
150
+ .start-btn {
151
+ background: linear-gradient(135deg, var(--primary) 0%, var(--secondary) 100%);
152
+ color: white;
153
+ padding: 18px 40px;
154
+ border: none;
155
+ border-radius: 12px;
156
+ font-size: 1.2rem;
157
+ font-weight: 700;
158
+ cursor: pointer;
159
+ transition: all 0.3s ease;
160
+ width: 100%;
161
+ }
162
+
163
+ .start-btn:hover {
164
+ transform: translateY(-2px);
165
+ box-shadow: 0 12px 24px -8px rgba(124, 58, 237, 0.4);
166
+ }
167
+
168
+ .start-btn:disabled {
169
+ opacity: 0.7;
170
+ cursor: not-allowed;
171
+ transform: none;
172
+ }
173
+
174
+ /* Cache Management Section */
175
+ .cache-management {
176
+ background: rgba(124, 58, 237, 0.05);
177
+ border: 1px solid rgba(124, 58, 237, 0.1);
178
+ border-radius: 12px;
179
+ padding: 20px;
180
+ margin-bottom: 25px;
181
+ text-align: center;
182
+ }
183
+
184
+ .cache-management h3 {
185
+ color: var(--primary);
186
+ margin-bottom: 15px;
187
+ font-size: 1.1rem;
188
+ font-weight: 600;
189
+ }
190
+
191
+ .cache-status-display {
192
+ background: rgba(16, 185, 129, 0.1);
193
+ border: 1px solid rgba(16, 185, 129, 0.2);
194
+ color: var(--success);
195
+ padding: 12px 16px;
196
+ border-radius: 8px;
197
+ margin-bottom: 15px;
198
+ font-size: 0.9rem;
199
+ font-weight: 500;
200
+ }
201
+
202
+ .cache-status-display.no-cache {
203
+ background: rgba(100, 116, 139, 0.1);
204
+ border-color: rgba(100, 116, 139, 0.2);
205
+ color: var(--text-secondary);
206
+ }
207
+
208
+ .clear-cache-btn {
209
+ background: linear-gradient(135deg, var(--warning) 0%, #f59e0b 100%);
210
+ color: white;
211
+ padding: 12px 24px;
212
+ border: none;
213
+ border-radius: 8px;
214
+ font-size: 0.9rem;
215
+ font-weight: 600;
216
+ cursor: pointer;
217
+ transition: all 0.3s ease;
218
+ }
219
+
220
+ .clear-cache-btn:hover {
221
+ transform: translateY(-1px);
222
+ box-shadow: 0 6px 12px -4px rgba(245, 158, 11, 0.4);
223
+ }
224
+
225
+ .clear-cache-btn:disabled {
226
+ opacity: 0.5;
227
+ cursor: not-allowed;
228
+ transform: none;
229
+ }
230
+
231
+ /* Cache Status Indicator */
232
+ .cache-status {
233
+ background: rgba(16, 185, 129, 0.1);
234
+ border: 1px solid rgba(16, 185, 129, 0.2);
235
+ color: var(--success);
236
+ padding: 8px 12px;
237
+ border-radius: 6px;
238
+ margin-bottom: 15px;
239
+ font-size: 0.85rem;
240
+ text-align: center;
241
+ font-weight: 500;
242
+ display: none;
243
+ }
244
+
245
+ .cache-status.cached {
246
+ display: block;
247
+ }
248
+
249
+ .cache-status.translating {
250
+ background: rgba(124, 58, 237, 0.1);
251
+ border-color: rgba(124, 58, 237, 0.2);
252
+ color: var(--primary);
253
+ }
254
+
255
+ /* Translation Loading Overlay */
256
+ .translation-overlay {
257
+ position: fixed;
258
+ top: 0;
259
+ left: 0;
260
+ width: 100%;
261
+ height: 100%;
262
+ background: rgba(124, 58, 237, 0.9);
263
+ display: none;
264
+ justify-content: center;
265
+ align-items: center;
266
+ z-index: 10000;
267
+ color: white;
268
+ text-align: center;
269
+ }
270
+
271
+ .translation-content {
272
+ background: rgba(255, 255, 255, 0.1);
273
+ padding: 40px;
274
+ border-radius: 16px;
275
+ backdrop-filter: blur(10px);
276
+ }
277
+
278
+ .translation-spinner {
279
+ width: 50px;
280
+ height: 50px;
281
+ border: 4px solid rgba(255, 255, 255, 0.3);
282
+ border-radius: 50%;
283
+ border-top-color: white;
284
+ animation: spin 1s ease-in-out infinite;
285
+ margin: 0 auto 20px;
286
+ }
287
+
288
+ /* Main Application (Hidden Initially) */
289
+ .main-app {
290
+ display: none;
291
+ }
292
+
293
+ .container {
294
+ max-width: 1200px;
295
+ margin: 0 auto;
296
+ background: var(--surface);
297
+ border-radius: 16px;
298
+ box-shadow: var(--shadow-lg);
299
+ overflow: hidden;
300
+ position: relative;
301
+ }
302
+
303
+ /* API Key Section - Static Position Top Left */
304
+ .api-key-section {
305
+ background: rgba(124, 58, 237, 0.05);
306
+ border: 1px solid rgba(124, 58, 237, 0.1);
307
+ border-radius: 8px;
308
+ padding: 12px;
309
+ margin: 15px;
310
+ max-width: 280px;
311
+ }
312
+
313
+ .api-key-section label {
314
+ font-size: 12px;
315
+ font-weight: 600;
316
+ color: var(--primary);
317
+ margin-bottom: 6px;
318
+ display: block;
319
+ }
320
+
321
+ .api-key-section input {
322
+ width: 100%;
323
+ padding: 8px 12px;
324
+ border: 1px solid var(--border);
325
+ border-radius: 6px;
326
+ font-size: 14px;
327
+ background: var(--surface);
328
+ transition: all 0.2s ease;
329
+ font-family: 'Courier New', monospace;
330
+ }
331
+
332
+ .api-key-section input:focus {
333
+ outline: none;
334
+ border-color: var(--primary);
335
+ box-shadow: 0 0 0 3px rgba(124, 58, 237, 0.1);
336
+ }
337
+
338
+ /* Language Switcher in Main App */
339
+ .language-switcher {
340
+ position: absolute;
341
+ top: 15px;
342
+ right: 15px;
343
+ display: flex;
344
+ gap: 10px;
345
+ align-items: center;
346
+ }
347
+
348
+ [dir="rtl"] .language-switcher {
349
+ right: auto;
350
+ left: 15px;
351
+ }
352
+
353
+ .language-switch-btn {
354
+ background: rgba(124, 58, 237, 0.05);
355
+ border: 1px solid rgba(124, 58, 237, 0.1);
356
+ border-radius: 8px;
357
+ padding: 8px 12px;
358
+ font-size: 12px;
359
+ cursor: pointer;
360
+ transition: all 0.2s ease;
361
+ color: var(--primary);
362
+ font-weight: 500;
363
+ }
364
+
365
+ .language-switch-btn:hover {
366
+ background: rgba(124, 58, 237, 0.1);
367
+ }
368
+
369
+ .mini-clear-cache {
370
+ background: rgba(245, 158, 11, 0.1);
371
+ border: 1px solid rgba(245, 158, 11, 0.2);
372
+ color: var(--warning);
373
+ padding: 6px 10px;
374
+ border-radius: 6px;
375
+ font-size: 11px;
376
+ cursor: pointer;
377
+ transition: all 0.2s ease;
378
+ font-weight: 500;
379
+ }
380
+
381
+ .mini-clear-cache:hover {
382
+ background: rgba(245, 158, 11, 0.2);
383
+ }
384
+
385
+ /* Main Content */
386
+ .main-content {
387
+ padding: 20px 30px 30px;
388
+ }
389
+
390
+ /* Header */
391
+ .header {
392
+ text-align: center;
393
+ margin-bottom: 25px;
394
+ padding-bottom: 20px;
395
+ border-bottom: 2px solid var(--border);
396
+ }
397
+
398
+ .header h1 {
399
+ font-size: 2.5rem;
400
+ font-weight: 800;
401
+ background: linear-gradient(135deg, var(--primary) 0%, var(--secondary) 100%);
402
+ -webkit-background-clip: text;
403
+ -webkit-text-fill-color: transparent;
404
+ background-clip: text;
405
+ margin-bottom: 8px;
406
+ }
407
+
408
+ .header .subtitle {
409
+ font-size: 1.1rem;
410
+ color: var(--text-secondary);
411
+ font-weight: 500;
412
+ }
413
+
414
+ .header .description {
415
+ font-size: 1rem;
416
+ color: var(--text-secondary);
417
+ margin-top: 12px;
418
+ max-width: 700px;
419
+ margin-left: auto;
420
+ margin-right: auto;
421
+ }
422
+
423
+ /* Features Overview */
424
+ .features-overview {
425
+ background: rgba(124, 58, 237, 0.05);
426
+ border: 1px solid rgba(124, 58, 237, 0.1);
427
+ border-radius: 12px;
428
+ padding: 20px;
429
+ margin-bottom: 25px;
430
+ }
431
+
432
+ .features-overview h3 {
433
+ color: var(--primary);
434
+ font-size: 1.2rem;
435
+ font-weight: 700;
436
+ margin-bottom: 15px;
437
+ text-align: center;
438
+ }
439
+
440
+ .features-grid {
441
+ display: grid;
442
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
443
+ gap: 15px;
444
+ }
445
+
446
+ .feature-card {
447
+ background: rgba(124, 58, 237, 0.02);
448
+ border: 1px solid rgba(124, 58, 237, 0.1);
449
+ border-radius: 8px;
450
+ padding: 15px;
451
+ text-align: center;
452
+ transition: all 0.3s ease;
453
+ }
454
+
455
+ .feature-card:hover {
456
+ background: rgba(124, 58, 237, 0.05);
457
+ border-color: var(--primary);
458
+ transform: translateY(-2px);
459
+ }
460
+
461
+ .feature-card .icon {
462
+ font-size: 1.5rem;
463
+ margin-bottom: 8px;
464
+ }
465
+
466
+ .feature-card h4 {
467
+ color: var(--primary);
468
+ font-size: 0.9rem;
469
+ font-weight: 700;
470
+ margin-bottom: 6px;
471
+ }
472
+
473
+ .feature-card p {
474
+ font-size: 0.8rem;
475
+ color: var(--text-secondary);
476
+ line-height: 1.4;
477
+ }
478
+
479
+ /* Input Sections */
480
+ .input-section {
481
+ background: var(--surface);
482
+ border: 1px solid var(--border);
483
+ border-radius: 12px;
484
+ padding: 25px;
485
+ margin-bottom: 20px;
486
+ transition: all 0.3s ease;
487
+ box-shadow: var(--shadow);
488
+ }
489
+
490
+ .input-section:hover {
491
+ border-color: var(--primary);
492
+ box-shadow: 0 8px 25px -8px rgba(124, 58, 237, 0.3);
493
+ }
494
+
495
+ .input-section h3 {
496
+ font-size: 1.2rem;
497
+ font-weight: 700;
498
+ color: var(--primary);
499
+ margin-bottom: 20px;
500
+ display: flex;
501
+ align-items: center;
502
+ gap: 8px;
503
+ padding-bottom: 10px;
504
+ border-bottom: 2px solid var(--border);
505
+ }
506
+
507
+ /* Form Elements */
508
+ label {
509
+ display: block;
510
+ margin-bottom: 8px;
511
+ font-weight: 600;
512
+ color: var(--text);
513
+ font-size: 0.95rem;
514
+ }
515
+
516
+ textarea,
517
+ select,
518
+ input[type="text"] {
519
+ width: 100%;
520
+ padding: 12px 16px;
521
+ border: 2px solid var(--border);
522
+ border-radius: 8px;
523
+ font-size: 1rem;
524
+ font-family: inherit;
525
+ background: var(--surface);
526
+ transition: all 0.2s ease;
527
+ margin-bottom: 15px;
528
+ }
529
+
530
+ textarea:focus,
531
+ select:focus,
532
+ input[type="text"]:focus {
533
+ outline: none;
534
+ border-color: var(--primary);
535
+ box-shadow: 0 0 0 3px rgba(124, 58, 237, 0.1);
536
+ }
537
+
538
+ textarea {
539
+ min-height: 120px;
540
+ line-height: 1.6;
541
+ resize: vertical;
542
+ }
543
+
544
+ /* Options Grid */
545
+ .options-grid {
546
+ display: grid;
547
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
548
+ gap: 20px;
549
+ margin-bottom: 20px;
550
+ }
551
+
552
+ .option-group {
553
+ display: flex;
554
+ flex-direction: column;
555
+ }
556
+
557
+ /* Character Counter */
558
+ .char-counter {
559
+ font-size: 0.8rem;
560
+ color: var(--text-secondary);
561
+ text-align: right;
562
+ margin-top: -10px;
563
+ margin-bottom: 15px;
564
+ }
565
+
566
+ [dir="rtl"] .char-counter {
567
+ text-align: left;
568
+ }
569
+
570
+ /* Generate Button */
571
+ .generate-btn {
572
+ background: linear-gradient(135deg, var(--primary) 0%, var(--secondary) 100%);
573
+ color: white;
574
+ padding: 18px 40px;
575
+ border: none;
576
+ border-radius: 12px;
577
+ font-size: 1.2rem;
578
+ font-weight: 700;
579
+ cursor: pointer;
580
+ transition: all 0.3s ease;
581
+ display: block;
582
+ margin: 30px auto;
583
+ min-width: 320px;
584
+ position: relative;
585
+ overflow: hidden;
586
+ }
587
+
588
+ .generate-btn:hover {
589
+ transform: translateY(-2px);
590
+ box-shadow: 0 12px 24px -8px rgba(124, 58, 237, 0.4);
591
+ }
592
+
593
+ .generate-btn:active {
594
+ transform: translateY(0);
595
+ }
596
+
597
+ .generate-btn:disabled {
598
+ opacity: 0.7;
599
+ cursor: not-allowed;
600
+ transform: none;
601
+ }
602
+
603
+ /* Loading Spinner */
604
+ .spinner {
605
+ display: none;
606
+ width: 20px;
607
+ height: 20px;
608
+ border: 2px solid rgba(255, 255, 255, 0.3);
609
+ border-radius: 50%;
610
+ border-top-color: white;
611
+ animation: spin 1s ease-in-out infinite;
612
+ margin-right: 8px;
613
+ }
614
+
615
+ [dir="rtl"] .spinner {
616
+ margin-right: 0;
617
+ margin-left: 8px;
618
+ }
619
+
620
+ @keyframes spin {
621
+ to { transform: rotate(360deg); }
622
+ }
623
+
624
+ /* Output Section */
625
+ .output-section {
626
+ margin-top: 30px;
627
+ }
628
+
629
+ .output-section h2 {
630
+ font-size: 1.5rem;
631
+ font-weight: 700;
632
+ color: var(--primary);
633
+ margin-bottom: 15px;
634
+ display: flex;
635
+ align-items: center;
636
+ gap: 8px;
637
+ text-align: center;
638
+ justify-content: center;
639
+ }
640
+
641
+ .output-area {
642
+ background: var(--surface);
643
+ border: 2px solid var(--border);
644
+ border-radius: 12px;
645
+ padding: 25px;
646
+ min-height: 200px;
647
+ transition: all 0.3s ease;
648
+ position: relative;
649
+ overflow-x: auto;
650
+ font-family: 'Georgia', serif;
651
+ line-height: 1.8;
652
+ white-space: pre-wrap;
653
+ word-wrap: break-word;
654
+ }
655
+
656
+ .output-area:focus {
657
+ outline: none;
658
+ border-color: var(--primary);
659
+ box-shadow: 0 0 0 3px rgba(124, 58, 237, 0.1);
660
+ }
661
+
662
+ /* Edit Notice */
663
+ .edit-notice {
664
+ background: rgba(124, 58, 237, 0.1);
665
+ border: 1px solid rgba(124, 58, 237, 0.2);
666
+ color: var(--primary);
667
+ padding: 8px 12px;
668
+ border-radius: 6px;
669
+ margin-bottom: 10px;
670
+ font-size: 0.85rem;
671
+ text-align: center;
672
+ font-weight: 500;
673
+ }
674
+
675
+ /* Error Messages */
676
+ .error-message {
677
+ background: rgba(239, 68, 68, 0.1);
678
+ border: 1px solid rgba(239, 68, 68, 0.2);
679
+ color: var(--error);
680
+ padding: 12px 16px;
681
+ border-radius: 8px;
682
+ margin: 10px 0;
683
+ font-size: 0.9rem;
684
+ display: none;
685
+ }
686
+
687
+ /* Status Messages */
688
+ .status-message {
689
+ background: rgba(124, 58, 237, 0.1);
690
+ border: 1px solid rgba(124, 58, 237, 0.2);
691
+ color: var(--primary);
692
+ padding: 12px 16px;
693
+ border-radius: 8px;
694
+ margin: 10px 0;
695
+ font-size: 0.9rem;
696
+ text-align: center;
697
+ font-weight: 500;
698
+ display: none;
699
+ }
700
+
701
+ /* Footer */
702
+ .footer {
703
+ text-align: center;
704
+ padding: 20px;
705
+ background: rgba(124, 58, 237, 0.05);
706
+ border-top: 1px solid var(--border);
707
+ color: var(--text-secondary);
708
+ font-size: 0.9rem;
709
+ }
710
+
711
+ /* Responsive Design */
712
+ @media (max-width: 768px) {
713
+ body {
714
+ padding: 10px;
715
+ }
716
+
717
+ .language-landing {
718
+ margin: 20px auto;
719
+ padding: 30px 20px;
720
+ }
721
+
722
+ .api-key-section {
723
+ margin: 10px;
724
+ max-width: none;
725
+ }
726
+
727
+ .language-switcher {
728
+ position: relative;
729
+ top: auto;
730
+ right: auto;
731
+ margin-bottom: 15px;
732
+ justify-content: center;
733
+ }
734
+
735
+ .main-content {
736
+ padding: 15px 20px 20px;
737
+ }
738
+
739
+ .header h1 {
740
+ font-size: 2rem;
741
+ }
742
+
743
+ .input-section {
744
+ padding: 20px 15px;
745
+ }
746
+
747
+ .features-grid {
748
+ grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
749
+ }
750
+
751
+ .options-grid {
752
+ grid-template-columns: 1fr;
753
+ }
754
+
755
+ .generate-btn {
756
+ width: 100%;
757
+ margin: 25px 0;
758
+ padding: 16px 32px;
759
+ font-size: 1.1rem;
760
+ }
761
+
762
+ .output-area {
763
+ padding: 20px;
764
+ }
765
+ }
766
+
767
+ @media (max-width: 480px) {
768
+ .language-landing h1 {
769
+ font-size: 2rem;
770
+ }
771
+
772
+ .header h1 {
773
+ font-size: 1.8rem;
774
+ }
775
+
776
+ .features-grid {
777
+ grid-template-columns: 1fr;
778
+ }
779
+ }
780
+
781
+ /* Dark mode support */
782
+ @media (prefers-color-scheme: dark) {
783
+ :root {
784
+ --background: #0f172a;
785
+ --surface: #1e293b;
786
+ --text: #f1f5f9;
787
+ --text-secondary: #94a3b8;
788
+ --border: #334155;
789
+ }
790
+
791
+ body {
792
+ background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);
793
+ }
794
+ }
795
+ </style>
796
+ </head>
797
+ <body>
798
+ <!-- Translation Loading Overlay -->
799
+ <div class="translation-overlay" id="translationOverlay">
800
+ <div class="translation-content">
801
+ <div class="translation-spinner"></div>
802
+ <h2 id="translationTitle">Translating Interface...</h2>
803
+ <p id="translationMessage">Please wait while we translate the interface to your selected language.</p>
804
+ </div>
805
+ </div>
806
+
807
+ <!-- Language Selection Landing Page -->
808
+ <div class="language-landing" id="languageLanding">
809
+ <h1 data-translate="app_title">CopyGenius Pro</h1>
810
+ <p data-translate="welcome_message">Welcome! Please select your preferred language and enter your API key to get started.</p>
811
+
812
+ <!-- Cache Status Indicator -->
813
+ <div class="cache-status" id="cacheStatus">
814
+ 💾 Translations cached - instant loading!
815
+ </div>
816
+
817
+ <!-- Cache Management Section -->
818
+ <div class="cache-management" id="cacheManagement">
819
+ <h3 data-translate="cache_management_title">🗂️ Translation Cache Management</h3>
820
+ <div class="cache-status-display" id="cacheStatusDisplay">
821
+ <span data-translate="cache_status_checking">Checking cache status...</span>
822
+ </div>
823
+ <button class="clear-cache-btn" id="clearCacheBtn" data-translate="clear_cache_button">
824
+ 🗑️ Clear All Cached Translations
825
+ </button>
826
+ </div>
827
+
828
+ <div class="language-selector">
829
+ <label for="languageSelect" data-translate="select_language">🌐 Select Language</label>
830
+ <select id="languageSelect">
831
+ <option value="en">🇺🇸 English</option>
832
+ <option value="es">🇪🇸 Español (Spanish)</option>
833
+ <option value="fr">🇫🇷 Français (French)</option>
834
+ <option value="de">🇩🇪 Deutsch (German)</option>
835
+ <option value="zh">🇨🇳 中文 (Chinese)</option>
836
+ <option value="ja">🇯🇵 日本語 (Japanese)</option>
837
+ <option value="ko">🇰🇷 한국어 (Korean)</option>
838
+ <option value="pt">🇵🇹 Português (Portuguese)</option>
839
+ <option value="it">🇮🇹 Italiano (Italian)</option>
840
+ <option value="ar">🇸🇦 العربية (Arabic)</option>
841
+ <option value="ru">🇷🇺 Русский (Russian)</option>
842
+ <option value="hi">🇮🇳 हिन्दी (Hindi)</option>
843
+ <option value="bn">🇧🇩 বাংলা (Bengali)</option>
844
+ <option value="ur">🇵🇰 اردو (Urdu)</option>
845
+ <option value="tr">🇹🇷 Türkçe (Turkish)</option>
846
+ <option value="pl">🇵🇱 Polski (Polish)</option>
847
+ <option value="nl">🇳🇱 Nederlands (Dutch)</option>
848
+ <option value="sv">🇸🇪 Svenska (Swedish)</option>
849
+ <option value="da">🇩🇰 Dansk (Danish)</option>
850
+ <option value="no">🇳🇴 Norsk (Norwegian)</option>
851
+ <option value="fi">🇫🇮 Suomi (Finnish)</option>
852
+ <option value="is">🇮🇸 Íslenska (Icelandic)</option>
853
+ <option value="cs">🇨🇿 Čeština (Czech)</option>
854
+ <option value="sk">🇸🇰 Slovenčina (Slovak)</option>
855
+ <option value="hu">🇭🇺 Magyar (Hungarian)</option>
856
+ <option value="ro">🇷🇴 Română (Romanian)</option>
857
+ <option value="bg">🇧🇬 Български (Bulgarian)</option>
858
+ <option value="hr">🇭🇷 Hrvatski (Croatian)</option>
859
+ <option value="sr">🇷🇸 Српски (Serbian)</option>
860
+ <option value="sl">🇸🇮 Slovenščina (Slovenian)</option>
861
+ <option value="mk">🇲🇰 Македонски (Macedonian)</option>
862
+ <option value="sq">🇦🇱 Shqip (Albanian)</option>
863
+ <option value="lv">🇱🇻 Latviešu (Latvian)</option>
864
+ <option value="lt">🇱🇹 Lietuvių (Lithuanian)</option>
865
+ <option value="et">🇪🇪 Eesti (Estonian)</option>
866
+ <option value="mt">🇲🇹 Malti (Maltese)</option>
867
+ <option value="ga">🇮🇪 Gaeilge (Irish)</option>
868
+ <option value="cy">🏴󠁧󠁢󠁷󠁬󠁳󠁿 Cymraeg (Welsh)</option>
869
+ <option value="eu">🏴󠁥󠁳󠁰󠁶󠁿 Euskera (Basque)</option>
870
+ <option value="ca">🏴󠁥󠁳󠁣󠁴󠁿 Català (Catalan)</option>
871
+ <option value="gl">🏴󠁥󠁳󠁧󠁡󠁿 Galego (Galician)</option>
872
+ <option value="el">🇬🇷 Ελληνικά (Greek)</option>
873
+ <option value="he">🇮🇱 עברית (Hebrew)</option>
874
+ <option value="fa">🇮🇷 فارسی (Persian)</option>
875
+ <option value="ps">🇦🇫 پښتو (Pashto)</option>
876
+ <option value="ku">🏴󠁩󠁱󠁫󠁲󠁿 کوردی (Kurdish)</option>
877
+ <option value="az">🇦🇿 Azərbaycan (Azerbaijani)</option>
878
+ <option value="kk">🇰🇿 Қазақша (Kazakh)</option>
879
+ <option value="ky">🇰🇬 Кыргызча (Kyrgyz)</option>
880
+ <option value="uz">🇺🇿 O'zbek (Uzbek)</option>
881
+ <option value="tk">🇹🇲 Türkmen (Turkmen)</option>
882
+ <option value="tg">🇹🇯 Тоҷикӣ (Tajik)</option>
883
+ <option value="mn">🇲🇳 Монгол (Mongolian)</option>
884
+ <option value="ka">🇬🇪 ქართული (Georgian)</option>
885
+ <option value="hy">🇦🇲 Հայերեն (Armenian)</option>
886
+ <option value="th">🇹🇭 ไทย (Thai)</option>
887
+ <option value="vi">🇻🇳 Tiếng Việt (Vietnamese)</option>
888
+ <option value="lo">🇱🇦 ລາວ (Lao)</option>
889
+ <option value="km">🇰🇭 ខ្មែរ (Khmer)</option>
890
+ <option value="my">🇲🇲 မြန်မာ (Myanmar)</option>
891
+ <option value="si">🇱🇰 සිංහල (Sinhala)</option>
892
+ <option value="ta">🇱🇰 தமிழ் (Tamil)</option>
893
+ <option value="te">🇮🇳 తెలుగు (Telugu)</option>
894
+ <option value="kn">🇮🇳 ಕನ್ನಡ (Kannada)</option>
895
+ <option value="ml">🇮🇳 മലയാളം (Malayalam)</option>
896
+ <option value="gu">🇮🇳 ગુજરાતી (Gujarati)</option>
897
+ <option value="pa">🇮🇳 ਪੰਜਾਬੀ (Punjabi)</option>
898
+ <option value="or">🇮🇳 ଓଡ଼ିଆ (Odia)</option>
899
+ <option value="as">🇮🇳 অসমীয়া (Assamese)</option>
900
+ <option value="ne">🇳🇵 नेपाली (Nepali)</option>
901
+ <option value="dz">🇧🇹 རྫོང་ཁ (Dzongkha)</option>
902
+ <option value="bo">🏔️ བོད་ཡིག (Tibetan)</option>
903
+ <option value="id">🇮🇩 Bahasa Indonesia</option>
904
+ <option value="ms">🇲🇾 Bahasa Melayu (Malay)</option>
905
+ <option value="tl">🇵🇭 Filipino (Tagalog)</option>
906
+ <option value="ceb">🇵🇭 Cebuano</option>
907
+ <option value="haw">🏝️ ʻŌlelo Hawaiʻi (Hawaiian)</option>
908
+ <option value="mi">🇳🇿 Te Reo Māori (Maori)</option>
909
+ <option value="sm">🇼🇸 Gagana Samoa (Samoan)</option>
910
+ <option value="to">🇹🇴 Lea Fakatonga (Tongan)</option>
911
+ <option value="fj">🇫🇯 Na Vosa Vakaviti (Fijian)</option>
912
+ <option value="mg">🇲🇬 Malagasy</option>
913
+ <option value="sw">🇰🇪 Kiswahili (Swahili)</option>
914
+ <option value="zu">🇿🇦 isiZulu (Zulu)</option>
915
+ <option value="xh">🇿🇦 isiXhosa (Xhosa)</option>
916
+ <option value="af">🇿🇦 Afrikaans</option>
917
+ <option value="st">🇱🇸 Sesotho (Southern Sotho)</option>
918
+ <option value="tn">🇧🇼 Setswana (Tswana)</option>
919
+ <option value="ss">🇸🇿 siSwati (Swati)</option>
920
+ <option value="ve">🇿🇦 Tshivenḓa (Venda)</option>
921
+ <option value="ts">🇿🇦 Xitsonga (Tsonga)</option>
922
+ <option value="nr">🇿🇦 isiNdebele (Southern Ndebele)</option>
923
+ <option value="am">🇪🇹 አማርኛ (Amharic)</option>
924
+ <option value="ti">🇪🇷 ትግርኛ (Tigrinya)</option>
925
+ <option value="om">🇪🇹 Afaan Oromoo (Oromo)</option>
926
+ <option value="so">🇸🇴 Soomaali (Somali)</option>
927
+ <option value="ha">🇳🇬 Hausa</option>
928
+ <option value="yo">🇳🇬 Yorùbá (Yoruba)</option>
929
+ <option value="ig">🇳🇬 Igbo</option>
930
+ <option value="ff">🇸🇳 Fulfulde (Fulani)</option>
931
+ <option value="wo">🇸🇳 Wolof</option>
932
+ <option value="bm">🇲🇱 Bamanankan (Bambara)</option>
933
+ <option value="rn">🇧🇮 Kirundi (Rundi)</option>
934
+ <option value="rw">🇷🇼 Kinyarwanda (Rwanda)</option>
935
+ <option value="lg">🇺🇬 Luganda</option>
936
+ <option value="ny">🇲🇼 Chichewa (Nyanja)</option>
937
+ <option value="sn">🇿🇼 chiShona (Shona)</option>
938
+ <option value="nd">🇿🇼 isiNdebele (Northern Ndebele)</option>
939
+ </select>
940
+ </div>
941
+
942
+ <div class="api-key-landing">
943
+ <label for="apiKeyLanding" data-translate="api_key_label">🔑 OpenAI API Key</label>
944
+ <input type="password" id="apiKeyLanding" placeholder="Enter your OpenAI API key" data-translate-placeholder="api_key_placeholder">
945
+ </div>
946
+
947
+ <button class="start-btn" id="startBtn" data-translate="start_button">🚀 Start Creating Content</button>
948
+ </div>
949
+
950
+ <!-- Main Application -->
951
+ <div class="main-app" id="mainApp">
952
+ <div class="container">
953
+ <!-- Language Switcher -->
954
+ <div class="language-switcher" id="languageSwitcher">
955
+ <div class="language-switch-btn" onclick="showLanguageLanding()">
956
+ <span data-translate="change_language">🌐 Change Language</span>
957
+ </div>
958
+ <div class="mini-clear-cache" onclick="clearAllTranslationCache()" title="Clear translation cache">
959
+ <span data-translate="clear_cache_mini">🗑️ Clear Cache</span>
960
+ </div>
961
+ </div>
962
+
963
+ <!-- API Key Section - Static Position Top Left -->
964
+ <div class="api-key-section">
965
+ <label for="apiKey" data-translate="api_key_short">🔑 API Key</label>
966
+ <input type="password" id="apiKey" data-translate-placeholder="api_key_placeholder" autocomplete="off">
967
+ </div>
968
+
969
+ <div class="main-content">
970
+ <!-- Header -->
971
+ <div class="header">
972
+ <h1 data-translate="app_title">CopyGenius Pro</h1>
973
+ <p class="subtitle" data-translate="app_subtitle">Professional Content Creation Platform</p>
974
+ <p class="description" data-translate="app_description">Create compelling, professional copy with AI-powered content generation and advanced customization options</p>
975
+ </div>
976
+
977
+ <!-- Features Overview -->
978
+ <div class="features-overview">
979
+ <h3 data-translate="features_title">✨ Advanced Copywriting Features</h3>
980
+ <div class="features-grid">
981
+ <div class="feature-card">
982
+ <div class="icon">📝</div>
983
+ <h4 data-translate="feature_content_types">14 Content Types</h4>
984
+ <p data-translate="feature_content_desc">Marketing, sales, technical, and creative content</p>
985
+ </div>
986
+ <div class="feature-card">
987
+ <div class="icon">🎨</div>
988
+ <h4 data-translate="feature_tone_styles">10 Tone Styles</h4>
989
+ <p data-translate="feature_tone_desc">From formal to humorous, find the perfect voice</p>
990
+ </div>
991
+ <div class="feature-card">
992
+ <div class="icon">🔧</div>
993
+ <h4 data-translate="feature_writing_techniques">20 Writing Techniques</h4>
994
+ <p data-translate="feature_writing_desc">Storytelling, persuasion, data-driven approaches</p>
995
+ </div>
996
+ <div class="feature-card">
997
+ <div class="icon">🌐</div>
998
+ <h4 data-translate="feature_multilingual">Multi-Language</h4>
999
+ <p data-translate="feature_multilingual_desc">Generate copy in 92 different languages</p>
1000
+ </div>
1001
+ <div class="feature-card">
1002
+ <div class="icon">✏️</div>
1003
+ <h4 data-translate="feature_editable">Editable Output</h4>
1004
+ <p data-translate="feature_editable_desc">Customize and refine generated content</p>
1005
+ </div>
1006
+ </div>
1007
+ </div>
1008
+
1009
+ <!-- Content Input Section -->
1010
+ <div class="input-section">
1011
+ <h3 data-translate="content_brief_title">📝 Content Brief</h3>
1012
+ <div class="option-group">
1013
+ <label for="userPrompt" data-translate="content_brief_label">Enter Your Content Brief:</label>
1014
+ <textarea id="userPrompt" data-translate-placeholder="content_brief_placeholder" maxlength="5000"></textarea>
1015
+ <div class="char-counter"><span id="promptCount">0</span>/5,000 <span data-translate="characters">characters</span></div>
1016
+ </div>
1017
+ </div>
1018
+
1019
+ <!-- Content Type Selection -->
1020
+ <div class="input-section">
1021
+ <h3 data-translate="content_type_title">📋 Content Type</h3>
1022
+ <div class="options-grid">
1023
+ <div class="option-group">
1024
+ <label for="contentType" data-translate="content_type_label">Select Content Type:</label>
1025
+ <select id="contentType">
1026
+ <option value="Marketing and Advertising" data-translate="content_marketing">📢 Marketing and Advertising</option>
1027
+ <option value="Print Ads" data-translate="content_print">📰 Print Ads</option>
1028
+ <option value="Digital Ads" data-translate="content_digital">💻 Digital Ads</option>
1029
+ <option value="Social Media" data-translate="content_social">📱 Social Media</option>
1030
+ <option value="Email Marketing" data-translate="content_email">📧 Email Marketing</option>
1031
+ <option value="Blog Post" data-translate="content_blog">📝 Blog Post</option>
1032
+ <option value="SEO Content" data-translate="content_seo">🔍 SEO Content</option>
1033
+ <option value="Website Content" data-translate="content_website">🌐 Website Content</option>
1034
+ <option value="Sales and Promotional Materials" data-translate="content_sales">💰 Sales & Promotional Materials</option>
1035
+ <option value="Technical and Educational Content" data-translate="content_technical">🎓 Technical & Educational Content</option>
1036
+ <option value="Creative and Long-form Content" data-translate="content_creative">✨ Creative & Long-form Content</option>
1037
+ <option value="Branding and Strategy" data-translate="content_branding">🎯 Branding & Strategy</option>
1038
+ <option value="Copy for UX/UI" data-translate="content_ux">🖥️ Copy for UX/UI</option>
1039
+ <option value="Miscellaneous" data-translate="content_misc">📄 Miscellaneous</option>
1040
+ </select>
1041
+ </div>
1042
+ </div>
1043
+ </div>
1044
+
1045
+ <!-- Style and Technique Options -->
1046
+ <div class="input-section">
1047
+ <h3 data-translate="style_technique_title">🎨 Style & Technique</h3>
1048
+ <div class="options-grid">
1049
+ <div class="option-group">
1050
+ <label for="toneStyle" data-translate="tone_style_label">Tone / Style:</label>
1051
+ <select id="toneStyle">
1052
+ <option value="Formal" data-translate="tone_formal">🎩 Formal</option>
1053
+ <option value="Informal" data-translate="tone_informal">😊 Informal</option>
1054
+ <option value="Conversational" data-translate="tone_conversational">💬 Conversational</option>
1055
+ <option value="Persuasive" data-translate="tone_persuasive">🎯 Persuasive</option>
1056
+ <option value="Humorous" data-translate="tone_humorous">😄 Humorous</option>
1057
+ <option value="Serious" data-translate="tone_serious">🧐 Serious</option>
1058
+ <option value="Optimistic" data-translate="tone_optimistic">🌟 Optimistic</option>
1059
+ <option value="Analytical" data-translate="tone_analytical">📊 Analytical</option>
1060
+ <option value="Reflective" data-translate="tone_reflective">🤔 Reflective</option>
1061
+ <option value="Neutral" data-translate="tone_neutral">⚖️ Neutral</option>
1062
+ </select>
1063
+ </div>
1064
+ <div class="option-group">
1065
+ <label for="writingTech" data-translate="writing_technique_label">Writing Technique:</label>
1066
+ <select id="writingTech">
1067
+ <option value="Storytelling" data-translate="tech_storytelling">📚 Storytelling</option>
1068
+ <option value="Anecdotes" data-translate="tech_anecdotes">💭 Anecdotes</option>
1069
+ <option value="Metaphors" data-translate="tech_metaphors">🌉 Metaphors</option>
1070
+ <option value="Similes" data-translate="tech_similes">🔗 Similes</option>
1071
+ <option value="Conversational" data-translate="tech_conversational">💬 Conversational</option>
1072
+ <option value="Dialogue" data-translate="tech_dialogue">🗣️ Dialogue</option>
1073
+ <option value="Alliteration" data-translate="tech_alliteration">🎵 Alliteration</option>
1074
+ <option value="Repetition" data-translate="tech_repetition">🔄 Repetition</option>
1075
+ <option value="Analogies" data-translate="tech_analogies">🔍 Analogies</option>
1076
+ <option value="Bullet Points" data-translate="tech_bullets">📋 Bullet Points</option>
1077
+ <option value="Imagery" data-translate="tech_imagery">🖼️ Imagery</option>
1078
+ <option value="Logical Appeal" data-translate="tech_logical">🧠 Logical Appeal</option>
1079
+ <option value="Emotional Appeal" data-translate="tech_emotional">❤️ Emotional Appeal</option>
1080
+ <option value="Data-driven" data-translate="tech_data">📈 Data-driven</option>
1081
+ <option value="Persuasive" data-translate="tech_persuasive">🎯 Persuasive</option>
1082
+ <option value="Authoritative" data-translate="tech_authoritative">👑 Authoritative</option>
1083
+ <option value="Optimistic" data-translate="tech_optimistic">🌈 Optimistic</option>
1084
+ <option value="Sarcastic" data-translate="tech_sarcastic">😏 Sarcastic</option>
1085
+ <option value="Motivational" data-translate="tech_motivational">💪 Motivational</option>
1086
+ <option value="Empathetic" data-translate="tech_empathetic">🤗 Empathetic</option>
1087
+ </select>
1088
+ </div>
1089
+ </div>
1090
+ </div>
1091
+
1092
+ <!-- Error and Status Messages -->
1093
+ <div class="error-message" id="errorMessage"></div>
1094
+ <div class="status-message" id="statusMessage"></div>
1095
+
1096
+ <!-- Generate Button -->
1097
+ <button class="generate-btn" id="generateBtn">
1098
+ <span class="spinner" id="spinner"></span>
1099
+ <span id="buttonText" data-translate="generate_button">✨ Generate Professional Copy</span>
1100
+ </button>
1101
+
1102
+ <!-- Output Section -->
1103
+ <div class="output-section">
1104
+ <h2 data-translate="output_title">📄 Generated Copy</h2>
1105
+ <div class="edit-notice" data-translate="edit_notice">
1106
+ ✏️ This content is editable - click anywhere to customize and refine the copy
1107
+ </div>
1108
+ <div class="output-area" id="outputArea" contenteditable="true"></div>
1109
+ </div>
1110
+ </div>
1111
+
1112
+ <!-- Footer -->
1113
+ <div class="footer">
1114
+ Created by Shift Mind AI Labs
1115
+ </div>
1116
+ </div>
1117
+ </div>
1118
+
1119
+ <script>
1120
+ // RTL languages list
1121
+ const rtlLanguages = ['ar', 'he', 'fa', 'ur', 'ps', 'ku'];
1122
+
1123
+ // Current language and API key
1124
+ let currentLanguage = 'en';
1125
+ let currentApiKey = '';
1126
+
1127
+ // Language names mapping
1128
+ const languageNames = {
1129
+ en: 'English', es: 'Spanish', fr: 'French', de: 'German', zh: 'Chinese',
1130
+ ja: 'Japanese', ko: 'Korean', pt: 'Portuguese', it: 'Italian', ar: 'Arabic',
1131
+ ru: 'Russian', hi: 'Hindi', bn: 'Bengali', ur: 'Urdu', tr: 'Turkish',
1132
+ pl: 'Polish', nl: 'Dutch', sv: 'Swedish', da: 'Danish', no: 'Norwegian',
1133
+ fi: 'Finnish', is: 'Icelandic', cs: 'Czech', sk: 'Slovak', hu: 'Hungarian',
1134
+ ro: 'Romanian', bg: 'Bulgarian', hr: 'Croatian', sr: 'Serbian', sl: 'Slovenian',
1135
+ mk: 'Macedonian', sq: 'Albanian', lv: 'Latvian', lt: 'Lithuanian', et: 'Estonian',
1136
+ mt: 'Maltese', ga: 'Irish', cy: 'Welsh', eu: 'Basque', ca: 'Catalan',
1137
+ gl: 'Galician', el: 'Greek', he: 'Hebrew', fa: 'Persian', ps: 'Pashto',
1138
+ ku: 'Kurdish', az: 'Azerbaijani', kk: 'Kazakh', ky: 'Kyrgyz', uz: 'Uzbek',
1139
+ tk: 'Turkmen', tg: 'Tajik', mn: 'Mongolian', ka: 'Georgian', hy: 'Armenian',
1140
+ th: 'Thai', vi: 'Vietnamese', lo: 'Lao', km: 'Khmer', my: 'Myanmar',
1141
+ si: 'Sinhala', ta: 'Tamil', te: 'Telugu', kn: 'Kannada', ml: 'Malayalam',
1142
+ gu: 'Gujarati', pa: 'Punjabi', or: 'Odia', as: 'Assamese', ne: 'Nepali',
1143
+ dz: 'Dzongkha', bo: 'Tibetan', id: 'Indonesian', ms: 'Malay', tl: 'Filipino',
1144
+ ceb: 'Cebuano', haw: 'Hawaiian', mi: 'Maori', sm: 'Samoan', to: 'Tongan',
1145
+ fj: 'Fijian', mg: 'Malagasy', sw: 'Swahili', zu: 'Zulu', xh: 'Xhosa',
1146
+ af: 'Afrikaans', st: 'Southern Sotho', tn: 'Tswana', ss: 'Swati', ve: 'Venda',
1147
+ ts: 'Tsonga', nr: 'Southern Ndebele', am: 'Amharic', ti: 'Tigrinya', om: 'Oromo',
1148
+ so: 'Somali', ha: 'Hausa', yo: 'Yoruba', ig: 'Igbo', ff: 'Fulani',
1149
+ wo: 'Wolof', bm: 'Bambara', rn: 'Rundi', rw: 'Rwanda', lg: 'Luganda',
1150
+ ny: 'Chichewa', sn: 'Shona', nd: 'Northern Ndebele'
1151
+ };
1152
+
1153
+ // Translation cache management
1154
+ const CACHE_PREFIX = 'copygenius_translations_';
1155
+ const CACHE_VERSION = '1.0';
1156
+
1157
+ // Check if translations are cached for a language
1158
+ function isLanguageCached(language) {
1159
+ const cacheKey = CACHE_PREFIX + language;
1160
+ const cached = localStorage.getItem(cacheKey);
1161
+ return cached !== null;
1162
+ }
1163
+
1164
+ // Save translations to cache
1165
+ function saveTranslationsToCache(language, translations) {
1166
+ const cacheKey = CACHE_PREFIX + language;
1167
+ const cacheData = {
1168
+ version: CACHE_VERSION,
1169
+ timestamp: Date.now(),
1170
+ translations: translations
1171
+ };
1172
+ localStorage.setItem(cacheKey, JSON.stringify(cacheData));
1173
+ console.log(`Translations cached for ${language}`);
1174
+ }
1175
+
1176
+ // Load translations from cache
1177
+ function loadTranslationsFromCache(language) {
1178
+ const cacheKey = CACHE_PREFIX + language;
1179
+ const cached = localStorage.getItem(cacheKey);
1180
+
1181
+ if (cached) {
1182
+ try {
1183
+ const cacheData = JSON.parse(cached);
1184
+ if (cacheData.version === CACHE_VERSION) {
1185
+ console.log(`Translations loaded from cache for ${language}`);
1186
+ return cacheData.translations;
1187
+ }
1188
+ } catch (error) {
1189
+ console.error('Error parsing cached translations:', error);
1190
+ }
1191
+ }
1192
+ return null;
1193
+ }
1194
+
1195
+ // Get all cached languages
1196
+ function getCachedLanguages() {
1197
+ const cachedLanguages = [];
1198
+ for (let i = 0; i < localStorage.length; i++) {
1199
+ const key = localStorage.key(i);
1200
+ if (key && key.startsWith(CACHE_PREFIX)) {
1201
+ const language = key.replace(CACHE_PREFIX, '');
1202
+ cachedLanguages.push(language);
1203
+ }
1204
+ }
1205
+ return cachedLanguages;
1206
+ }
1207
+
1208
+ // Clear all translation cache
1209
+ function clearAllTranslationCache() {
1210
+ const cachedLanguages = getCachedLanguages();
1211
+
1212
+ if (cachedLanguages.length === 0) {
1213
+ alert('No cached translations to clear.');
1214
+ return;
1215
+ }
1216
+
1217
+ const languageList = cachedLanguages.map(lang => languageNames[lang] || lang).join(', ');
1218
+ const confirmMessage = `Are you sure you want to clear all cached translations?\n\nCached languages: ${languageList}\n\nThis will require re-downloading translations when switching languages.`;
1219
+
1220
+ if (confirm(confirmMessage)) {
1221
+ // Clear all translation caches
1222
+ cachedLanguages.forEach(language => {
1223
+ const cacheKey = CACHE_PREFIX + language;
1224
+ localStorage.removeItem(cacheKey);
1225
+ });
1226
+
1227
+ // Update cache status
1228
+ updateCacheStatus(currentLanguage);
1229
+ updateCacheStatusDisplay();
1230
+
1231
+ alert(`Cache cleared successfully!\n\n${cachedLanguages.length} language(s) removed from cache.`);
1232
+
1233
+ // Ask if user wants to reload current language translations
1234
+ if (currentLanguage !== 'en' && cachedLanguages.includes(currentLanguage)) {
1235
+ if (confirm('Would you like to reload the current language translations?')) {
1236
+ applyLanguage(currentLanguage);
1237
+ }
1238
+ }
1239
+ }
1240
+ }
1241
+
1242
+ // Update cache status indicator
1243
+ function updateCacheStatus(language) {
1244
+ const cacheStatus = document.getElementById('cacheStatus');
1245
+ const isCached = isLanguageCached(language);
1246
+
1247
+ if (language === 'en') {
1248
+ cacheStatus.classList.remove('cached', 'translating');
1249
+ return;
1250
+ }
1251
+
1252
+ if (isCached) {
1253
+ cacheStatus.textContent = '💾 Translations cached - instant loading!';
1254
+ cacheStatus.classList.add('cached');
1255
+ cacheStatus.classList.remove('translating');
1256
+ } else {
1257
+ cacheStatus.textContent = '🔄 First time translation - will be cached for future use';
1258
+ cacheStatus.classList.add('translating');
1259
+ cacheStatus.classList.remove('cached');
1260
+ }
1261
+ }
1262
+
1263
+ // Update cache status display in management section
1264
+ function updateCacheStatusDisplay() {
1265
+ const cacheStatusDisplay = document.getElementById('cacheStatusDisplay');
1266
+ const clearCacheBtn = document.getElementById('clearCacheBtn');
1267
+ const cachedLanguages = getCachedLanguages();
1268
+
1269
+ if (cachedLanguages.length === 0) {
1270
+ cacheStatusDisplay.textContent = '📭 No cached translations';
1271
+ cacheStatusDisplay.className = 'cache-status-display no-cache';
1272
+ clearCacheBtn.disabled = true;
1273
+ } else {
1274
+ const languageList = cachedLanguages.map(lang => languageNames[lang] || lang).join(', ');
1275
+ cacheStatusDisplay.textContent = `💾 ${cachedLanguages.length} language(s) cached: ${languageList}`;
1276
+ cacheStatusDisplay.className = 'cache-status-display';
1277
+ clearCacheBtn.disabled = false;
1278
+ }
1279
+ }
1280
+
1281
+ // Initialize the application
1282
+ function initializeApp() {
1283
+ // Load saved language and API key
1284
+ const savedLanguage = localStorage.getItem('copygenius_language') || 'en';
1285
+ const savedApiKey = localStorage.getItem('copygenius_api_key') || '';
1286
+
1287
+ currentLanguage = savedLanguage;
1288
+ currentApiKey = savedApiKey;
1289
+
1290
+ // Set language selector
1291
+ document.getElementById('languageSelect').value = currentLanguage;
1292
+ document.getElementById('apiKeyLanding').value = currentApiKey;
1293
+
1294
+ // Apply direction for current language
1295
+ applyDirection(currentLanguage);
1296
+
1297
+ // Update cache status
1298
+ updateCacheStatus(currentLanguage);
1299
+ updateCacheStatusDisplay();
1300
+
1301
+ // Show appropriate screen
1302
+ if (currentApiKey && currentLanguage) {
1303
+ showMainApp();
1304
+ } else {
1305
+ showLanguageLanding();
1306
+ }
1307
+ }
1308
+
1309
+ // Apply language direction
1310
+ function applyDirection(language) {
1311
+ currentLanguage = language;
1312
+
1313
+ // Set document language and direction
1314
+ document.documentElement.lang = language;
1315
+ document.documentElement.dir = rtlLanguages.includes(language) ? 'rtl' : 'ltr';
1316
+
1317
+ // Save language preference
1318
+ localStorage.setItem('copygenius_language', language);
1319
+
1320
+ // Update cache status
1321
+ updateCacheStatus(language);
1322
+ }
1323
+
1324
+ // API call function for translation
1325
+ async function translateText(text, targetLanguage) {
1326
+ if (!currentApiKey) {
1327
+ throw new Error('API key is required for translation');
1328
+ }
1329
+
1330
+ const languageName = languageNames[targetLanguage] || 'English';
1331
+
1332
+ const prompt = `Translate the following text to ${languageName}. Provide ONLY the exact translation without any explanations, additional information, or formatting:
1333
+
1334
+ "${text}"`;
1335
+
1336
+ const payload = {
1337
+ model: "gpt-4o-mini",
1338
+ messages: [{ role: "user", content: prompt }],
1339
+ max_tokens: 500,
1340
+ temperature: 0.1
1341
+ };
1342
+
1343
+ const response = await fetch("https://api.openai.com/v1/chat/completions", {
1344
+ method: "POST",
1345
+ headers: {
1346
+ "Content-Type": "application/json",
1347
+ "Authorization": `Bearer ${currentApiKey}`
1348
+ },
1349
+ body: JSON.stringify(payload)
1350
+ });
1351
+
1352
+ if (!response.ok) {
1353
+ const errorData = await response.json();
1354
+ throw new Error(errorData.error?.message || "Translation API request failed");
1355
+ }
1356
+
1357
+ const data = await response.json();
1358
+ return data.choices[0].message.content.trim();
1359
+ }
1360
+
1361
+ // Apply cached translations to UI
1362
+ function applyCachedTranslations(translations) {
1363
+ // Apply text translations
1364
+ Object.keys(translations.texts).forEach(originalText => {
1365
+ const translation = translations.texts[originalText];
1366
+ const elements = document.querySelectorAll(`[data-translate]`);
1367
+
1368
+ elements.forEach(element => {
1369
+ const originalElementText = element.getAttribute('data-original-text') || element.textContent;
1370
+ if (originalElementText === originalText) {
1371
+ element.textContent = translation;
1372
+ }
1373
+ });
1374
+ });
1375
+
1376
+ // Apply placeholder translations
1377
+ Object.keys(translations.placeholders).forEach(originalPlaceholder => {
1378
+ const translation = translations.placeholders[originalPlaceholder];
1379
+ const elements = document.querySelectorAll(`[data-translate-placeholder]`);
1380
+
1381
+ elements.forEach(element => {
1382
+ const originalElementPlaceholder = element.getAttribute('data-original-placeholder') || element.placeholder;
1383
+ if (originalElementPlaceholder === originalPlaceholder) {
1384
+ element.placeholder = translation;
1385
+ }
1386
+ });
1387
+ });
1388
+ }
1389
+
1390
+ // Translate all UI elements
1391
+ async function translateInterface(targetLanguage) {
1392
+ if (targetLanguage === 'en') {
1393
+ // No translation needed for English
1394
+ return;
1395
+ }
1396
+
1397
+ // Check if translations are cached
1398
+ const cachedTranslations = loadTranslationsFromCache(targetLanguage);
1399
+ if (cachedTranslations) {
1400
+ // Use cached translations
1401
+ console.log('Using cached translations for', targetLanguage);
1402
+ applyCachedTranslations(cachedTranslations);
1403
+ return;
1404
+ }
1405
+
1406
+ // Need to translate via API
1407
+ showTranslationOverlay();
1408
+
1409
+ try {
1410
+ // Get all elements with data-translate attribute
1411
+ const elements = document.querySelectorAll('[data-translate]');
1412
+ const placeholderElements = document.querySelectorAll('[data-translate-placeholder]');
1413
+
1414
+ // Collect all texts to translate
1415
+ const textsToTranslate = [];
1416
+ const placeholdersToTranslate = [];
1417
+ const elementMap = new Map();
1418
+
1419
+ elements.forEach(element => {
1420
+ const originalText = element.getAttribute('data-original-text') || element.textContent;
1421
+ if (!element.getAttribute('data-original-text')) {
1422
+ element.setAttribute('data-original-text', originalText);
1423
+ }
1424
+ textsToTranslate.push(originalText);
1425
+ elementMap.set(originalText, element);
1426
+ });
1427
+
1428
+ placeholderElements.forEach(element => {
1429
+ const originalPlaceholder = element.getAttribute('data-original-placeholder') || element.placeholder;
1430
+ if (!element.getAttribute('data-original-placeholder')) {
1431
+ element.setAttribute('data-original-placeholder', originalPlaceholder);
1432
+ }
1433
+ placeholdersToTranslate.push(originalPlaceholder);
1434
+ elementMap.set(originalPlaceholder, element);
1435
+ });
1436
+
1437
+ // Prepare cache structure
1438
+ const translationsCache = {
1439
+ texts: {},
1440
+ placeholders: {}
1441
+ };
1442
+
1443
+ // Translate texts in batches
1444
+ const batchSize = 10;
1445
+ const allTexts = [...textsToTranslate, ...placeholdersToTranslate];
1446
+
1447
+ for (let i = 0; i < allTexts.length; i += batchSize) {
1448
+ const batch = allTexts.slice(i, i + batchSize);
1449
+
1450
+ // Update progress
1451
+ updateTranslationProgress(i, allTexts.length);
1452
+
1453
+ // Translate batch
1454
+ const translations = await Promise.all(
1455
+ batch.map(text => translateText(text, targetLanguage))
1456
+ );
1457
+
1458
+ // Apply translations and cache them
1459
+ batch.forEach((originalText, index) => {
1460
+ const element = elementMap.get(originalText);
1461
+ const translation = translations[index];
1462
+
1463
+ if (element.hasAttribute('data-translate')) {
1464
+ element.textContent = translation;
1465
+ translationsCache.texts[originalText] = translation;
1466
+ } else if (element.hasAttribute('data-translate-placeholder')) {
1467
+ element.placeholder = translation;
1468
+ translationsCache.placeholders[originalText] = translation;
1469
+ }
1470
+ });
1471
+ }
1472
+
1473
+ // Save translations to cache
1474
+ saveTranslationsToCache(targetLanguage, translationsCache);
1475
+
1476
+ // Update cache status
1477
+ updateCacheStatus(targetLanguage);
1478
+ updateCacheStatusDisplay();
1479
+
1480
+ } catch (error) {
1481
+ console.error('Translation error:', error);
1482
+ showError('Translation failed: ' + error.message);
1483
+ } finally {
1484
+ hideTranslationOverlay();
1485
+ }
1486
+ }
1487
+
1488
+ // Show translation overlay
1489
+ function showTranslationOverlay() {
1490
+ document.getElementById('translationOverlay').style.display = 'flex';
1491
+ }
1492
+
1493
+ // Hide translation overlay
1494
+ function hideTranslationOverlay() {
1495
+ document.getElementById('translationOverlay').style.display = 'none';
1496
+ }
1497
+
1498
+ // Update translation progress
1499
+ function updateTranslationProgress(current, total) {
1500
+ const percentage = Math.round((current / total) * 100);
1501
+ document.getElementById('translationMessage').textContent =
1502
+ `Translating interface... ${percentage}% complete (will be cached for future use)`;
1503
+ }
1504
+
1505
+ // Apply language with API translation or cache
1506
+ async function applyLanguage(language) {
1507
+ applyDirection(language);
1508
+
1509
+ if (language !== 'en') {
1510
+ await translateInterface(language);
1511
+ }
1512
+ }
1513
+
1514
+ // Show language landing page
1515
+ function showLanguageLanding() {
1516
+ document.getElementById('languageLanding').style.display = 'block';
1517
+ document.getElementById('mainApp').style.display = 'none';
1518
+ }
1519
+
1520
+ // Show main application
1521
+ function showMainApp() {
1522
+ document.getElementById('languageLanding').style.display = 'none';
1523
+ document.getElementById('mainApp').style.display = 'block';
1524
+
1525
+ // Set API key in main app
1526
+ document.getElementById('apiKey').value = currentApiKey;
1527
+ }
1528
+
1529
+ // Start button click handler
1530
+ document.getElementById('startBtn').addEventListener('click', async function() {
1531
+ const selectedLanguage = document.getElementById('languageSelect').value;
1532
+ const apiKey = document.getElementById('apiKeyLanding').value.trim();
1533
+
1534
+ if (!apiKey) {
1535
+ alert('Please enter your OpenAI API key');
1536
+ return;
1537
+ }
1538
+
1539
+ currentLanguage = selectedLanguage;
1540
+ currentApiKey = apiKey;
1541
+
1542
+ // Save API key
1543
+ localStorage.setItem('copygenius_api_key', apiKey);
1544
+
1545
+ // Apply language with translation (cached or API)
1546
+ await applyLanguage(selectedLanguage);
1547
+
1548
+ // Show main app
1549
+ showMainApp();
1550
+ });
1551
+
1552
+ // Language selector change handler
1553
+ document.getElementById('languageSelect').addEventListener('change', async function() {
1554
+ const selectedLanguage = this.value;
1555
+ updateCacheStatus(selectedLanguage);
1556
+
1557
+ if (currentApiKey) {
1558
+ await applyLanguage(selectedLanguage);
1559
+ } else {
1560
+ applyDirection(selectedLanguage);
1561
+ }
1562
+ });
1563
+
1564
+ // Clear cache button handler
1565
+ document.getElementById('clearCacheBtn').addEventListener('click', clearAllTranslationCache);
1566
+
1567
+ // Character counter for prompt input
1568
+ const promptInput = document.getElementById('userPrompt');
1569
+ const promptCounter = document.getElementById('promptCount');
1570
+
1571
+ promptInput.addEventListener('input', function() {
1572
+ const currentLength = this.value.length;
1573
+ promptCounter.textContent = currentLength;
1574
+
1575
+ if (currentLength > 4500) {
1576
+ promptCounter.style.color = 'var(--warning)';
1577
+ } else if (currentLength > 4750) {
1578
+ promptCounter.style.color = 'var(--error)';
1579
+ } else {
1580
+ promptCounter.style.color = 'var(--text-secondary)';
1581
+ }
1582
+ });
1583
+
1584
+ // Error and status handling
1585
+ function showError(message) {
1586
+ const errorDiv = document.getElementById('errorMessage');
1587
+ errorDiv.textContent = message;
1588
+ errorDiv.style.display = 'block';
1589
+ setTimeout(() => {
1590
+ errorDiv.style.display = 'none';
1591
+ }, 5000);
1592
+ }
1593
+
1594
+ function showStatus(message, duration = 0) {
1595
+ const statusDiv = document.getElementById('statusMessage');
1596
+ statusDiv.textContent = message;
1597
+ statusDiv.style.display = 'block';
1598
+
1599
+ if (duration > 0) {
1600
+ setTimeout(() => {
1601
+ statusDiv.style.display = 'none';
1602
+ }, duration);
1603
+ }
1604
+ }
1605
+
1606
+ function hideStatus() {
1607
+ document.getElementById('statusMessage').style.display = 'none';
1608
+ }
1609
+
1610
+ // API call function for content generation
1611
+ async function callAPI(prompt) {
1612
+ const apiKey = currentApiKey;
1613
+
1614
+ if (!apiKey) {
1615
+ throw new Error('Please enter your OpenAI API key');
1616
+ }
1617
+
1618
+ const payload = {
1619
+ model: "gpt-4o-mini",
1620
+ messages: [{ role: "user", content: prompt }],
1621
+ max_tokens: 2000,
1622
+ temperature: 0.7
1623
+ };
1624
+
1625
+ const response = await fetch("https://api.openai.com/v1/chat/completions", {
1626
+ method: "POST",
1627
+ headers: {
1628
+ "Content-Type": "application/json",
1629
+ "Authorization": `Bearer ${apiKey}`
1630
+ },
1631
+ body: JSON.stringify(payload)
1632
+ });
1633
+
1634
+ if (!response.ok) {
1635
+ const errorData = await response.json();
1636
+ throw new Error(errorData.error?.message || "API request failed");
1637
+ }
1638
+
1639
+ const data = await response.json();
1640
+ return data.choices[0].message.content;
1641
+ }
1642
+
1643
+ // Build the combined prompt
1644
+ function buildCombinedPrompt(userPrompt) {
1645
+ const contentType = document.getElementById('contentType').value;
1646
+ const toneStyle = document.getElementById('toneStyle').value;
1647
+ const writingTech = document.getElementById('writingTech').value;
1648
+ const languageName = languageNames[currentLanguage] || 'English';
1649
+
1650
+ return `You are CopyGenius Pro, an expert copywriter and content strategist. Based on the following specifications, craft professional, compelling, and strategically effective copy that achieves the user's objectives.
1651
+
1652
+ **CONTENT SPECIFICATIONS:**
1653
+ - **Content Type**: ${contentType}
1654
+ - **Tone/Style**: ${toneStyle}
1655
+ - **Writing Technique**: ${writingTech}
1656
+ - **Output Language**: ${languageName}
1657
+
1658
+ **USER BRIEF:**
1659
+ ${userPrompt}
1660
+
1661
+ **REQUIREMENTS:**
1662
+ - Create copy that is engaging, persuasive, and appropriate for the specified content type
1663
+ - Apply the selected tone and writing technique consistently throughout
1664
+ - Ensure the copy is optimized for its intended purpose and audience
1665
+ - Use professional copywriting best practices
1666
+ - Make the content actionable and results-oriented
1667
+ - Maintain clarity and readability while being compelling
1668
+ - Write ENTIRELY in ${languageName} language
1669
+
1670
+ **OUTPUT:**
1671
+ Provide only the final, polished copy in ${languageName} without additional commentary or explanations. The copy should be ready for immediate use in the specified context.`;
1672
+ }
1673
+
1674
+ // Validation function
1675
+ function validateInputs() {
1676
+ const userPrompt = promptInput.value.trim();
1677
+
1678
+ if (!userPrompt) {
1679
+ throw new Error('Please enter your content brief.');
1680
+ }
1681
+
1682
+ if (!currentApiKey) {
1683
+ throw new Error('Please enter your OpenAI API key.');
1684
+ }
1685
+ }
1686
+
1687
+ // Generate copy function
1688
+ async function generateCopy() {
1689
+ const button = document.getElementById('generateBtn');
1690
+ const buttonText = document.getElementById('buttonText');
1691
+ const spinner = document.getElementById('spinner');
1692
+ const outputArea = document.getElementById('outputArea');
1693
+
1694
+ try {
1695
+ // Validate inputs
1696
+ validateInputs();
1697
+
1698
+ // Update button state
1699
+ button.disabled = true;
1700
+ spinner.style.display = 'inline-block';
1701
+ buttonText.textContent = 'Generating Copy...';
1702
+ showStatus("Creating professional copy...");
1703
+
1704
+ // Clear previous output
1705
+ outputArea.innerHTML = '';
1706
+
1707
+ const userPrompt = promptInput.value.trim();
1708
+ const prompt = buildCombinedPrompt(userPrompt);
1709
+
1710
+ const result = await callAPI(prompt);
1711
+
1712
+ // Format the output with basic HTML
1713
+ const formattedResult = result
1714
+ .replace(/\n\n/g, "</p><p>")
1715
+ .replace(/\n/g, "<br>")
1716
+ .replace(/^(.*)$/, "<p>$1</p>")
1717
+ .replace(/<p><\/p>/g, "")
1718
+ .replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
1719
+ .replace(/\*(.*?)\*/g, '<em>$1</em>');
1720
+
1721
+ outputArea.innerHTML = formattedResult;
1722
+ showStatus("Professional copy generated successfully!", 3000);
1723
+
1724
+ } catch (error) {
1725
+ console.error("Error:", error);
1726
+ showError(error.message);
1727
+ outputArea.innerHTML = '';
1728
+ } finally {
1729
+ // Reset button state
1730
+ button.disabled = false;
1731
+ spinner.style.display = 'none';
1732
+ buttonText.textContent = '✨ Generate Professional Copy';
1733
+ hideStatus();
1734
+ }
1735
+ }
1736
+
1737
+ // Event listeners
1738
+ document.getElementById('generateBtn').addEventListener('click', generateCopy);
1739
+
1740
+ // Keyboard shortcut for generation
1741
+ document.addEventListener('keydown', function(e) {
1742
+ if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') {
1743
+ e.preventDefault();
1744
+ generateCopy();
1745
+ }
1746
+ });
1747
+
1748
+ // Handle contenteditable placeholder
1749
+ const outputArea = document.getElementById('outputArea');
1750
+ outputArea.addEventListener('focus', function() {
1751
+ if (this.innerHTML === '') {
1752
+ this.innerHTML = '';
1753
+ }
1754
+ });
1755
+
1756
+ outputArea.addEventListener('blur', function() {
1757
+ if (this.innerHTML.trim() === '') {
1758
+ this.innerHTML = '';
1759
+ }
1760
+ });
1761
+
1762
+ // Handle input changes to clear status
1763
+ [promptInput].forEach(input => {
1764
+ input.addEventListener('input', function() {
1765
+ hideStatus();
1766
+ });
1767
+ });
1768
+
1769
+ // API key sync between landing and main app
1770
+ document.getElementById('apiKeyLanding').addEventListener('input', function() {
1771
+ currentApiKey = this.value;
1772
+ localStorage.setItem('copygenius_api_key', this.value);
1773
+ document.getElementById('apiKey').value = this.value;
1774
+ });
1775
+
1776
+ document.getElementById('apiKey').addEventListener('input', function() {
1777
+ currentApiKey = this.value;
1778
+ localStorage.setItem('copygenius_api_key', this.value);
1779
+ document.getElementById('apiKeyLanding').value = this.value;
1780
+ });
1781
+
1782
+ // Initialize the application when page loads
1783
+ document.addEventListener('DOMContentLoaded', initializeApp);
1784
+ </script>
1785
+ </body>
1786
+ </html>
1787
+
📘 Educator, Business & Student Gui.txt ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 📘 Educator, Business & Student Guide: CopyGenius Pro
2
+ 1. Overview & Purpose
3
+ CopyGenius Pro delivers instant, professional content generation—from marketing to technical, in any language. Designed for educators, business professionals, students, and creators, it adapts to every context, writing style, and audience.
4
+
5
+ 2. Step-by-Step Usage
6
+ A. Quick Start
7
+ Open the HTML file (or Hugging Face Space).
8
+
9
+ Select your language (from 92 supported).
10
+
11
+ Enter your OpenAI API key (stored only in your browser, never shared).
12
+
13
+ B. Input Content Brief
14
+ Write your assignment, product, or campaign brief (up to 5000 characters).
15
+
16
+ Examples:
17
+
18
+ “Write a persuasive LinkedIn post about sustainable AI in education.”
19
+
20
+ “Draft a formal sales email introducing our SaaS to K-12 schools.”
21
+
22
+ “Create a creative, optimistic blog intro for a travel startup.”
23
+
24
+ C. Customize Output
25
+ Select content type: Marketing, blog, social, email, technical, UX/UI, etc.
26
+
27
+ Pick tone/style: Formal, informal, persuasive, humorous, etc.
28
+
29
+ Choose writing technique: Storytelling, logical, motivational, empathetic, etc.
30
+
31
+ (All lists available in dropdown menus.)
32
+
33
+ D. Generate & Use
34
+ Click “Generate Professional Copy” (or press Ctrl+Enter).
35
+
36
+ Review, edit, and copy the result from the editable output area.
37
+
38
+ Content is ready for direct use—customize as needed.
39
+
40
+ E. Multilingual & Accessibility
41
+ Change UI and output language instantly.
42
+
43
+ All interface elements and outputs translate for fully multilingual workflow.
44
+
45
+ Use with RTL (Arabic, Hebrew, Urdu, etc.) or LTR languages.
46
+
47
+ 3. Classroom & Training Scenarios
48
+ Model writing: Generate examples for assignments, rubrics, or peer review.
49
+
50
+ Differentiation: Adjust level/tone for students’ needs.
51
+
52
+ Rapid feedback: Compare AI versions to student drafts for learning discussion.
53
+
54
+ Portfolio: Use editable outputs for digital portfolios or writing evidence.
55
+
56
+ 4. Business & Professional Use Cases
57
+ Campaigns: Generate ideas, test copy variants, or localize content.
58
+
59
+ Branding: Match tone/technique to brand identity instantly.
60
+
61
+ Team onboarding: Train new writers on style/tone expectations.
62
+
63
+ Documentation: Create technical, persuasive, or educational content fast.
64
+
65
+ 5. Tips & Best Practices
66
+ Be specific: The more detailed your brief, the more relevant the copy.
67
+
68
+ Experiment: Try different tones and techniques for varied results.
69
+
70
+ Privacy: Your content and keys stay on your device—ideal for sensitive projects.
71
+
72
+ Cache: Translation cache ensures fast multilingual switching.
73
+
74
+ 6. Troubleshooting & Support
75
+ API errors: Check your key and OpenAI quota.
76
+
77
+ Translation issues: Clear cache and reload.
78
+
79
+ Output not as expected? Adjust brief or options for new output.
80
+
81
+ Help: info@shiftmind.io | www.shiftmind.io
82
+
83
+ CopyGenius Pro empowers every user—educator, marketer, or creator—to generate world-class content instantly, securely, and ethically.
84
+