Spaces:
Running
Running
Upload 4 files
Browse files- Apache License.txt +17 -0
- README.md +89 -0
- index.html +1787 -0
- 📘 Educator, Business & Student Gui.txt +84 -0
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 |
+
|