Spaces:
Running
Running
Upload 4 files
Browse files- Apache License.txt +17 -0
- README.md +95 -0
- index.html +1753 -0
- 📘 Teacher & Student Guide EmpathyI.txt +135 -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,95 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: "💡 EmpathyInsights Pro – Advanced Empathy Map Guide Generator"
|
| 3 |
+
emoji: "💡"
|
| 4 |
+
colorFrom: "red"
|
| 5 |
+
colorTo: "green"
|
| 6 |
+
sdk: "static"
|
| 7 |
+
sdk_version: "0.1.0"
|
| 8 |
+
app_file: "index.html"
|
| 9 |
+
pinned: false
|
| 10 |
+
---
|
| 11 |
+
|
| 12 |
+
# 💡 EmpathyInsights Pro – Advanced Empathy Map Guide Generator
|
| 13 |
+
**Developed by Shift Mind AI Labs**
|
| 14 |
+
|
| 15 |
+
EmpathyInsights Pro is an open-source, privacy-first platform for generating comprehensive, professional empathy map guides—tailored to your user research or design context. Instantly create deeply structured, multilingual, and visually engaging explanations for all six core components of the Empathy Map—across 90+ languages, with full local privacy and advanced cache management.
|
| 16 |
+
|
| 17 |
+
---
|
| 18 |
+
|
| 19 |
+
## 🚀 Features
|
| 20 |
+
|
| 21 |
+
- **Full Empathy Map Structure:**
|
| 22 |
+
In-depth explanations for *Says, Thinks, Does, Feels, Pain Points, Gains*—with practical examples, data strategies, and best practices.
|
| 23 |
+
- **Context-Aware:**
|
| 24 |
+
Output is tailored to your research context, audience, and scenario description.
|
| 25 |
+
- **Professional HTML Output:**
|
| 26 |
+
Clean, responsive, color-themed output with inline CSS—ready for reports, presentations, or team sharing.
|
| 27 |
+
- **Multilingual UI & Output:**
|
| 28 |
+
90+ languages supported (OpenAI API key required, used only locally).
|
| 29 |
+
- **Instant Translation Cache:**
|
| 30 |
+
Revisit any language instantly; control cache from the UI.
|
| 31 |
+
- **No Data Sharing:**
|
| 32 |
+
API key and content never leave your device.
|
| 33 |
+
- **Accessibility:**
|
| 34 |
+
RTL/LTR support, keyboard shortcuts, mobile responsive.
|
| 35 |
+
|
| 36 |
+
---
|
| 37 |
+
|
| 38 |
+
## 🛠 How to Use
|
| 39 |
+
|
| 40 |
+
1. **Open the tool** in your browser or on Hugging Face Spaces.
|
| 41 |
+
2. **Select your preferred language** and enter your OpenAI API key (private, never sent to a server).
|
| 42 |
+
3. **Describe your user research scenario or context** (min 50 characters).
|
| 43 |
+
4. **Click “🧠 Generate Empathy Map Guide”** (or press Ctrl+Enter).
|
| 44 |
+
5. **View, copy, and use** your structured empathy map explanation—ready for sharing, reports, or design workshops.
|
| 45 |
+
6. **Switch languages or clear translation cache** anytime for instant, private access.
|
| 46 |
+
|
| 47 |
+
---
|
| 48 |
+
|
| 49 |
+
## 👩🏫 For Educators & Design Teams
|
| 50 |
+
|
| 51 |
+
- **Model research-based empathy:** Instantly generate examples for UX, marketing, or product courses.
|
| 52 |
+
- **Multilingual training:** Perfect for international teams, students, or ELL support.
|
| 53 |
+
- **Workshop facilitation:** Use as a live empathy map explainer or template in user interviews.
|
| 54 |
+
- **Portfolio and reflection:** Output is professional and editable—use in e-portfolios or peer reviews.
|
| 55 |
+
|
| 56 |
+
---
|
| 57 |
+
|
| 58 |
+
## 👨💼 For UX, Product, and Business Teams
|
| 59 |
+
|
| 60 |
+
- **Accelerate research analysis:** Get context-specific empathy map guides in any language.
|
| 61 |
+
- **Support design thinking:** Use as a workshop resource or stakeholder explainer.
|
| 62 |
+
- **Privacy & compliance:** All input/output and keys stay on your device—safe for NDA or client work.
|
| 63 |
+
|
| 64 |
+
---
|
| 65 |
+
|
| 66 |
+
## 🔐 Data Privacy
|
| 67 |
+
|
| 68 |
+
- Your OpenAI API key and all research data **never leave your browser**.
|
| 69 |
+
- No data is sent to Shift Mind AI Labs, Hugging Face, or any third party.
|
| 70 |
+
|
| 71 |
+
---
|
| 72 |
+
|
| 73 |
+
## 📄 License
|
| 74 |
+
|
| 75 |
+
Licensed under the [Apache License 2.0](./LICENSE).
|
| 76 |
+
|
| 77 |
+
---
|
| 78 |
+
|
| 79 |
+
## 🧠 About Shift Mind AI Labs
|
| 80 |
+
|
| 81 |
+
Shift Mind AI Labs creates open-source, ethical AI tools for global education, research, and digital empowerment.
|
| 82 |
+
|
| 83 |
+
🌐 https://www.shiftmind.io
|
| 84 |
+
✉️ info@shiftmind.io
|
| 85 |
+
|
| 86 |
+
---
|
| 87 |
+
|
| 88 |
+
## 🙌 Contributing
|
| 89 |
+
|
| 90 |
+
Feedback, feature ideas, and partnerships are welcome!
|
| 91 |
+
For pilots, integrations, or collaboration: **info@shiftmind.io**
|
| 92 |
+
|
| 93 |
+
---
|
| 94 |
+
|
| 95 |
+
*Bringing deep user empathy to every research team, class, and organization—instantly, securely, and in any language.*
|
index.html
ADDED
|
@@ -0,0 +1,1753 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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>EmpathyInsights Pro - Advanced User Understanding</title>
|
| 7 |
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
| 8 |
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
| 9 |
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
| 10 |
+
|
| 11 |
+
<style>
|
| 12 |
+
/* CSS Reset and Base Styles */
|
| 13 |
+
*, *::before, *::after {
|
| 14 |
+
box-sizing: border-box;
|
| 15 |
+
margin: 0;
|
| 16 |
+
padding: 0;
|
| 17 |
+
}
|
| 18 |
+
|
| 19 |
+
/* CSS Custom Properties */
|
| 20 |
+
:root {
|
| 21 |
+
/* Color System - Empathy/Understanding theme */
|
| 22 |
+
--color-primary: #0891b2;
|
| 23 |
+
--color-primary-hover: #0e7490;
|
| 24 |
+
--color-secondary: #06b6d4;
|
| 25 |
+
--color-accent: #67e8f9;
|
| 26 |
+
--color-success: #10b981;
|
| 27 |
+
--color-warning: #f59e0b;
|
| 28 |
+
--color-error: #ef4444;
|
| 29 |
+
|
| 30 |
+
/* Neutral Colors - Light Mode */
|
| 31 |
+
--color-background: #f8fafc;
|
| 32 |
+
--color-surface: #ffffff;
|
| 33 |
+
--color-surface-elevated: #ffffff;
|
| 34 |
+
--color-border: #e2e8f0;
|
| 35 |
+
--color-border-focus: #0891b2;
|
| 36 |
+
--color-text-primary: #1e293b;
|
| 37 |
+
--color-text-secondary: #64748b;
|
| 38 |
+
--color-text-muted: #94a3b8;
|
| 39 |
+
|
| 40 |
+
/* Typography */
|
| 41 |
+
--font-family-primary: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
| 42 |
+
|
| 43 |
+
/* Optimized Spacing System */
|
| 44 |
+
--spacing-xs: 0.25rem;
|
| 45 |
+
--spacing-sm: 0.5rem;
|
| 46 |
+
--spacing-md: 0.75rem;
|
| 47 |
+
--spacing-lg: 1rem;
|
| 48 |
+
--spacing-xl: 1.25rem;
|
| 49 |
+
--spacing-2xl: 1.5rem;
|
| 50 |
+
--spacing-3xl: 2rem;
|
| 51 |
+
|
| 52 |
+
/* Border Radius */
|
| 53 |
+
--radius-sm: 0.375rem;
|
| 54 |
+
--radius-md: 0.5rem;
|
| 55 |
+
--radius-lg: 0.75rem;
|
| 56 |
+
--radius-xl: 1rem;
|
| 57 |
+
|
| 58 |
+
/* Shadows */
|
| 59 |
+
--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
| 60 |
+
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
|
| 61 |
+
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
| 62 |
+
--shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
|
| 63 |
+
|
| 64 |
+
/* Transitions */
|
| 65 |
+
--transition-fast: 150ms ease-in-out;
|
| 66 |
+
--transition-normal: 250ms ease-in-out;
|
| 67 |
+
--transition-slow: 350ms ease-in-out;
|
| 68 |
+
|
| 69 |
+
/* Layout */
|
| 70 |
+
--container-max-width: 1000px;
|
| 71 |
+
--content-max-width: 900px;
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
/* RTL Support */
|
| 75 |
+
[dir="rtl"] {
|
| 76 |
+
text-align: right;
|
| 77 |
+
}
|
| 78 |
+
|
| 79 |
+
[dir="rtl"] .app-container {
|
| 80 |
+
direction: rtl;
|
| 81 |
+
}
|
| 82 |
+
|
| 83 |
+
[dir="rtl"] .api-key-compact {
|
| 84 |
+
left: auto;
|
| 85 |
+
right: var(--spacing-lg);
|
| 86 |
+
}
|
| 87 |
+
|
| 88 |
+
[dir="rtl"] .language-switcher {
|
| 89 |
+
right: auto;
|
| 90 |
+
left: var(--spacing-lg);
|
| 91 |
+
}
|
| 92 |
+
|
| 93 |
+
/* Dark Mode Support */
|
| 94 |
+
@media (prefers-color-scheme: dark) {
|
| 95 |
+
:root {
|
| 96 |
+
--color-background: #0f172a;
|
| 97 |
+
--color-surface: #1e293b;
|
| 98 |
+
--color-surface-elevated: #334155;
|
| 99 |
+
--color-border: #334155;
|
| 100 |
+
--color-text-primary: #f1f5f9;
|
| 101 |
+
--color-text-secondary: #cbd5e1;
|
| 102 |
+
--color-text-muted: #94a3b8;
|
| 103 |
+
}
|
| 104 |
+
}
|
| 105 |
+
|
| 106 |
+
/* Base Styles */
|
| 107 |
+
html {
|
| 108 |
+
font-size: 16px;
|
| 109 |
+
line-height: 1.5;
|
| 110 |
+
scroll-behavior: smooth;
|
| 111 |
+
}
|
| 112 |
+
|
| 113 |
+
body {
|
| 114 |
+
font-family: var(--font-family-primary);
|
| 115 |
+
background: linear-gradient(135deg, var(--color-background) 0%, #e2e8f0 100%);
|
| 116 |
+
color: var(--color-text-primary);
|
| 117 |
+
line-height: 1.6;
|
| 118 |
+
-webkit-font-smoothing: antialiased;
|
| 119 |
+
-moz-osx-font-smoothing: grayscale;
|
| 120 |
+
min-height: 100vh;
|
| 121 |
+
transition: all 0.3s ease;
|
| 122 |
+
padding: 15px;
|
| 123 |
+
}
|
| 124 |
+
|
| 125 |
+
/* Language Selection Landing */
|
| 126 |
+
.language-landing {
|
| 127 |
+
display: block;
|
| 128 |
+
max-width: 600px;
|
| 129 |
+
margin: 50px auto;
|
| 130 |
+
background: var(--color-surface);
|
| 131 |
+
border-radius: var(--radius-xl);
|
| 132 |
+
box-shadow: var(--shadow-lg);
|
| 133 |
+
padding: 40px;
|
| 134 |
+
text-align: center;
|
| 135 |
+
}
|
| 136 |
+
|
| 137 |
+
.language-landing h1 {
|
| 138 |
+
font-size: 2.5rem;
|
| 139 |
+
font-weight: 800;
|
| 140 |
+
background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-secondary) 100%);
|
| 141 |
+
-webkit-background-clip: text;
|
| 142 |
+
-webkit-text-fill-color: transparent;
|
| 143 |
+
background-clip: text;
|
| 144 |
+
margin-bottom: 15px;
|
| 145 |
+
}
|
| 146 |
+
|
| 147 |
+
.language-landing p {
|
| 148 |
+
font-size: 1.1rem;
|
| 149 |
+
color: var(--color-text-secondary);
|
| 150 |
+
margin-bottom: 30px;
|
| 151 |
+
}
|
| 152 |
+
|
| 153 |
+
.language-selector {
|
| 154 |
+
margin-bottom: 25px;
|
| 155 |
+
}
|
| 156 |
+
|
| 157 |
+
.language-selector label {
|
| 158 |
+
display: block;
|
| 159 |
+
margin-bottom: 10px;
|
| 160 |
+
font-weight: 600;
|
| 161 |
+
color: var(--color-text-primary);
|
| 162 |
+
font-size: 1.1rem;
|
| 163 |
+
}
|
| 164 |
+
|
| 165 |
+
.language-selector select {
|
| 166 |
+
width: 100%;
|
| 167 |
+
padding: 15px 20px;
|
| 168 |
+
border: 2px solid var(--color-border);
|
| 169 |
+
border-radius: var(--radius-lg);
|
| 170 |
+
font-size: 1.1rem;
|
| 171 |
+
font-family: inherit;
|
| 172 |
+
background: var(--color-surface);
|
| 173 |
+
transition: all 0.2s ease;
|
| 174 |
+
margin-bottom: 20px;
|
| 175 |
+
}
|
| 176 |
+
|
| 177 |
+
.language-selector select:focus {
|
| 178 |
+
outline: none;
|
| 179 |
+
border-color: var(--color-border-focus);
|
| 180 |
+
box-shadow: 0 0 0 3px rgba(8, 145, 178, 0.1);
|
| 181 |
+
}
|
| 182 |
+
|
| 183 |
+
.api-key-landing {
|
| 184 |
+
margin-bottom: 25px;
|
| 185 |
+
}
|
| 186 |
+
|
| 187 |
+
.api-key-landing label {
|
| 188 |
+
display: block;
|
| 189 |
+
margin-bottom: 10px;
|
| 190 |
+
font-weight: 600;
|
| 191 |
+
color: var(--color-text-primary);
|
| 192 |
+
font-size: 1.1rem;
|
| 193 |
+
}
|
| 194 |
+
|
| 195 |
+
.api-key-landing input {
|
| 196 |
+
width: 100%;
|
| 197 |
+
padding: 15px 20px;
|
| 198 |
+
border: 2px solid var(--color-border);
|
| 199 |
+
border-radius: var(--radius-lg);
|
| 200 |
+
font-size: 1.1rem;
|
| 201 |
+
background: var(--color-surface);
|
| 202 |
+
transition: all 0.2s ease;
|
| 203 |
+
font-family: 'Courier New', monospace;
|
| 204 |
+
}
|
| 205 |
+
|
| 206 |
+
.api-key-landing input:focus {
|
| 207 |
+
outline: none;
|
| 208 |
+
border-color: var(--color-border-focus);
|
| 209 |
+
box-shadow: 0 0 0 3px rgba(8, 145, 178, 0.1);
|
| 210 |
+
}
|
| 211 |
+
|
| 212 |
+
.start-btn {
|
| 213 |
+
background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-secondary) 100%);
|
| 214 |
+
color: white;
|
| 215 |
+
padding: 18px 40px;
|
| 216 |
+
border: none;
|
| 217 |
+
border-radius: var(--radius-lg);
|
| 218 |
+
font-size: 1.2rem;
|
| 219 |
+
font-weight: 700;
|
| 220 |
+
cursor: pointer;
|
| 221 |
+
transition: all 0.3s ease;
|
| 222 |
+
width: 100%;
|
| 223 |
+
}
|
| 224 |
+
|
| 225 |
+
.start-btn:hover {
|
| 226 |
+
transform: translateY(-2px);
|
| 227 |
+
box-shadow: 0 12px 24px -8px rgba(8, 145, 178, 0.4);
|
| 228 |
+
}
|
| 229 |
+
|
| 230 |
+
.start-btn:disabled {
|
| 231 |
+
opacity: 0.7;
|
| 232 |
+
cursor: not-allowed;
|
| 233 |
+
transform: none;
|
| 234 |
+
}
|
| 235 |
+
|
| 236 |
+
/* Cache Management Section */
|
| 237 |
+
.cache-management {
|
| 238 |
+
background: rgba(8, 145, 178, 0.05);
|
| 239 |
+
border: 1px solid rgba(8, 145, 178, 0.1);
|
| 240 |
+
border-radius: var(--radius-lg);
|
| 241 |
+
padding: 20px;
|
| 242 |
+
margin-bottom: 25px;
|
| 243 |
+
text-align: center;
|
| 244 |
+
}
|
| 245 |
+
|
| 246 |
+
.cache-management h3 {
|
| 247 |
+
color: var(--color-primary);
|
| 248 |
+
margin-bottom: 15px;
|
| 249 |
+
font-size: 1.1rem;
|
| 250 |
+
font-weight: 600;
|
| 251 |
+
}
|
| 252 |
+
|
| 253 |
+
.cache-status-display {
|
| 254 |
+
background: rgba(16, 185, 129, 0.1);
|
| 255 |
+
border: 1px solid rgba(16, 185, 129, 0.2);
|
| 256 |
+
color: var(--color-success);
|
| 257 |
+
padding: 12px 16px;
|
| 258 |
+
border-radius: var(--radius-md);
|
| 259 |
+
margin-bottom: 15px;
|
| 260 |
+
font-size: 0.9rem;
|
| 261 |
+
font-weight: 500;
|
| 262 |
+
}
|
| 263 |
+
|
| 264 |
+
.cache-status-display.no-cache {
|
| 265 |
+
background: rgba(100, 116, 139, 0.1);
|
| 266 |
+
border-color: rgba(100, 116, 139, 0.2);
|
| 267 |
+
color: var(--color-text-secondary);
|
| 268 |
+
}
|
| 269 |
+
|
| 270 |
+
.clear-cache-btn {
|
| 271 |
+
background: linear-gradient(135deg, var(--color-warning) 0%, #f59e0b 100%);
|
| 272 |
+
color: white;
|
| 273 |
+
padding: 12px 24px;
|
| 274 |
+
border: none;
|
| 275 |
+
border-radius: var(--radius-md);
|
| 276 |
+
font-size: 0.9rem;
|
| 277 |
+
font-weight: 600;
|
| 278 |
+
cursor: pointer;
|
| 279 |
+
transition: all 0.3s ease;
|
| 280 |
+
}
|
| 281 |
+
|
| 282 |
+
.clear-cache-btn:hover {
|
| 283 |
+
transform: translateY(-1px);
|
| 284 |
+
box-shadow: 0 6px 12px -4px rgba(245, 158, 11, 0.4);
|
| 285 |
+
}
|
| 286 |
+
|
| 287 |
+
.clear-cache-btn:disabled {
|
| 288 |
+
opacity: 0.5;
|
| 289 |
+
cursor: not-allowed;
|
| 290 |
+
transform: none;
|
| 291 |
+
}
|
| 292 |
+
|
| 293 |
+
/* Cache Status Indicator */
|
| 294 |
+
.cache-status {
|
| 295 |
+
background: rgba(16, 185, 129, 0.1);
|
| 296 |
+
border: 1px solid rgba(16, 185, 129, 0.2);
|
| 297 |
+
color: var(--color-success);
|
| 298 |
+
padding: 8px 12px;
|
| 299 |
+
border-radius: var(--radius-sm);
|
| 300 |
+
margin-bottom: 15px;
|
| 301 |
+
font-size: 0.85rem;
|
| 302 |
+
text-align: center;
|
| 303 |
+
font-weight: 500;
|
| 304 |
+
display: none;
|
| 305 |
+
}
|
| 306 |
+
|
| 307 |
+
.cache-status.cached {
|
| 308 |
+
display: block;
|
| 309 |
+
}
|
| 310 |
+
|
| 311 |
+
.cache-status.translating {
|
| 312 |
+
background: rgba(8, 145, 178, 0.1);
|
| 313 |
+
border-color: rgba(8, 145, 178, 0.2);
|
| 314 |
+
color: var(--color-primary);
|
| 315 |
+
}
|
| 316 |
+
|
| 317 |
+
/* Translation Loading Overlay */
|
| 318 |
+
.translation-overlay {
|
| 319 |
+
position: fixed;
|
| 320 |
+
top: 0;
|
| 321 |
+
left: 0;
|
| 322 |
+
width: 100%;
|
| 323 |
+
height: 100%;
|
| 324 |
+
background: rgba(8, 145, 178, 0.9);
|
| 325 |
+
display: none;
|
| 326 |
+
justify-content: center;
|
| 327 |
+
align-items: center;
|
| 328 |
+
z-index: 10000;
|
| 329 |
+
color: white;
|
| 330 |
+
text-align: center;
|
| 331 |
+
}
|
| 332 |
+
|
| 333 |
+
.translation-content {
|
| 334 |
+
background: rgba(255, 255, 255, 0.1);
|
| 335 |
+
padding: 40px;
|
| 336 |
+
border-radius: var(--radius-xl);
|
| 337 |
+
backdrop-filter: blur(10px);
|
| 338 |
+
}
|
| 339 |
+
|
| 340 |
+
.translation-spinner {
|
| 341 |
+
width: 50px;
|
| 342 |
+
height: 50px;
|
| 343 |
+
border: 4px solid rgba(255, 255, 255, 0.3);
|
| 344 |
+
border-radius: 50%;
|
| 345 |
+
border-top-color: white;
|
| 346 |
+
animation: spin 1s ease-in-out infinite;
|
| 347 |
+
margin: 0 auto 20px;
|
| 348 |
+
}
|
| 349 |
+
|
| 350 |
+
/* Main Application (Hidden Initially) */
|
| 351 |
+
.main-app {
|
| 352 |
+
display: none;
|
| 353 |
+
}
|
| 354 |
+
|
| 355 |
+
/* Layout Components */
|
| 356 |
+
.app-container {
|
| 357 |
+
max-width: var(--container-max-width);
|
| 358 |
+
margin: 0 auto;
|
| 359 |
+
background: var(--color-surface);
|
| 360 |
+
border-radius: 16px;
|
| 361 |
+
box-shadow: var(--shadow-lg);
|
| 362 |
+
overflow: hidden;
|
| 363 |
+
position: relative;
|
| 364 |
+
}
|
| 365 |
+
|
| 366 |
+
/* Language Switcher in Main App */
|
| 367 |
+
.language-switcher {
|
| 368 |
+
position: absolute;
|
| 369 |
+
top: var(--spacing-lg);
|
| 370 |
+
right: var(--spacing-lg);
|
| 371 |
+
display: flex;
|
| 372 |
+
gap: 10px;
|
| 373 |
+
align-items: center;
|
| 374 |
+
z-index: 10;
|
| 375 |
+
}
|
| 376 |
+
|
| 377 |
+
.language-switch-btn {
|
| 378 |
+
background: rgba(8, 145, 178, 0.05);
|
| 379 |
+
border: 1px solid rgba(8, 145, 178, 0.1);
|
| 380 |
+
border-radius: var(--radius-md);
|
| 381 |
+
padding: 8px 12px;
|
| 382 |
+
font-size: 12px;
|
| 383 |
+
cursor: pointer;
|
| 384 |
+
transition: all 0.2s ease;
|
| 385 |
+
color: var(--color-primary);
|
| 386 |
+
font-weight: 500;
|
| 387 |
+
}
|
| 388 |
+
|
| 389 |
+
.language-switch-btn:hover {
|
| 390 |
+
background: rgba(8, 145, 178, 0.1);
|
| 391 |
+
}
|
| 392 |
+
|
| 393 |
+
.mini-clear-cache {
|
| 394 |
+
background: rgba(245, 158, 11, 0.1);
|
| 395 |
+
border: 1px solid rgba(245, 158, 11, 0.2);
|
| 396 |
+
color: var(--color-warning);
|
| 397 |
+
padding: 6px 10px;
|
| 398 |
+
border-radius: var(--radius-sm);
|
| 399 |
+
font-size: 11px;
|
| 400 |
+
cursor: pointer;
|
| 401 |
+
transition: all 0.2s ease;
|
| 402 |
+
font-weight: 500;
|
| 403 |
+
}
|
| 404 |
+
|
| 405 |
+
.mini-clear-cache:hover {
|
| 406 |
+
background: rgba(245, 158, 11, 0.2);
|
| 407 |
+
}
|
| 408 |
+
|
| 409 |
+
/* Compact API Key in Top-Left */
|
| 410 |
+
.api-key-compact {
|
| 411 |
+
position: absolute;
|
| 412 |
+
top: var(--spacing-lg);
|
| 413 |
+
left: var(--spacing-lg);
|
| 414 |
+
z-index: 10;
|
| 415 |
+
background: rgba(8, 145, 178, 0.05);
|
| 416 |
+
border: 1px solid rgba(8, 145, 178, 0.1);
|
| 417 |
+
border-radius: var(--radius-lg);
|
| 418 |
+
padding: var(--spacing-md) var(--spacing-lg);
|
| 419 |
+
transition: all var(--transition-normal);
|
| 420 |
+
max-width: 280px;
|
| 421 |
+
}
|
| 422 |
+
|
| 423 |
+
.api-key-compact:hover {
|
| 424 |
+
background: rgba(8, 145, 178, 0.08);
|
| 425 |
+
}
|
| 426 |
+
|
| 427 |
+
.api-key-compact-label {
|
| 428 |
+
display: block;
|
| 429 |
+
font-size: 0.75rem;
|
| 430 |
+
font-weight: 600;
|
| 431 |
+
color: var(--color-primary);
|
| 432 |
+
margin-bottom: var(--spacing-xs);
|
| 433 |
+
text-transform: uppercase;
|
| 434 |
+
letter-spacing: 0.05em;
|
| 435 |
+
}
|
| 436 |
+
|
| 437 |
+
.api-key-compact-input {
|
| 438 |
+
width: 100%;
|
| 439 |
+
padding: var(--spacing-sm) var(--spacing-md);
|
| 440 |
+
border: 1px solid var(--color-border);
|
| 441 |
+
border-radius: var(--radius-sm);
|
| 442 |
+
font-size: 0.875rem;
|
| 443 |
+
background: var(--color-surface);
|
| 444 |
+
color: var(--color-text-primary);
|
| 445 |
+
transition: all var(--transition-fast);
|
| 446 |
+
font-family: 'Courier New', monospace;
|
| 447 |
+
}
|
| 448 |
+
|
| 449 |
+
.api-key-compact-input:focus {
|
| 450 |
+
outline: none;
|
| 451 |
+
border-color: var(--color-border-focus);
|
| 452 |
+
box-shadow: 0 0 0 2px rgb(8 145 178 / 0.1);
|
| 453 |
+
}
|
| 454 |
+
|
| 455 |
+
.api-key-compact-input::placeholder {
|
| 456 |
+
color: var(--color-text-muted);
|
| 457 |
+
font-size: 0.75rem;
|
| 458 |
+
}
|
| 459 |
+
|
| 460 |
+
/* Main Content */
|
| 461 |
+
.main-content {
|
| 462 |
+
padding: 20px 30px 30px;
|
| 463 |
+
}
|
| 464 |
+
|
| 465 |
+
/* Header */
|
| 466 |
+
.header {
|
| 467 |
+
text-align: center;
|
| 468 |
+
margin-bottom: 25px;
|
| 469 |
+
padding-bottom: 20px;
|
| 470 |
+
border-bottom: 2px solid var(--color-border);
|
| 471 |
+
}
|
| 472 |
+
|
| 473 |
+
.header h1 {
|
| 474 |
+
font-size: 2.5rem;
|
| 475 |
+
font-weight: 800;
|
| 476 |
+
background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-secondary) 100%);
|
| 477 |
+
-webkit-background-clip: text;
|
| 478 |
+
-webkit-text-fill-color: transparent;
|
| 479 |
+
background-clip: text;
|
| 480 |
+
margin-bottom: 8px;
|
| 481 |
+
}
|
| 482 |
+
|
| 483 |
+
.header .subtitle {
|
| 484 |
+
font-size: 1.1rem;
|
| 485 |
+
color: var(--color-text-secondary);
|
| 486 |
+
font-weight: 500;
|
| 487 |
+
}
|
| 488 |
+
|
| 489 |
+
.header .description {
|
| 490 |
+
font-size: 1rem;
|
| 491 |
+
color: var(--color-text-secondary);
|
| 492 |
+
margin-top: 12px;
|
| 493 |
+
max-width: 600px;
|
| 494 |
+
margin-left: auto;
|
| 495 |
+
margin-right: auto;
|
| 496 |
+
}
|
| 497 |
+
|
| 498 |
+
/* Empathy Map Components Overview */
|
| 499 |
+
.empathy-components {
|
| 500 |
+
display: grid;
|
| 501 |
+
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
| 502 |
+
gap: 12px;
|
| 503 |
+
margin-bottom: 20px;
|
| 504 |
+
}
|
| 505 |
+
|
| 506 |
+
.component-card {
|
| 507 |
+
background: rgba(8, 145, 178, 0.05);
|
| 508 |
+
border: 1px solid rgba(8, 145, 178, 0.1);
|
| 509 |
+
border-radius: 8px;
|
| 510 |
+
padding: 12px;
|
| 511 |
+
text-align: center;
|
| 512 |
+
}
|
| 513 |
+
|
| 514 |
+
.component-card h4 {
|
| 515 |
+
color: var(--color-primary);
|
| 516 |
+
font-size: 0.9rem;
|
| 517 |
+
font-weight: 600;
|
| 518 |
+
margin-bottom: 4px;
|
| 519 |
+
}
|
| 520 |
+
|
| 521 |
+
.component-card p {
|
| 522 |
+
font-size: 0.8rem;
|
| 523 |
+
color: var(--color-text-secondary);
|
| 524 |
+
}
|
| 525 |
+
|
| 526 |
+
/* Input Section */
|
| 527 |
+
.input-section {
|
| 528 |
+
background: var(--color-surface);
|
| 529 |
+
border: 1px solid var(--color-border);
|
| 530 |
+
border-radius: 12px;
|
| 531 |
+
padding: 20px;
|
| 532 |
+
margin-bottom: 20px;
|
| 533 |
+
transition: all 0.3s ease;
|
| 534 |
+
box-shadow: var(--shadow-sm);
|
| 535 |
+
}
|
| 536 |
+
|
| 537 |
+
.input-section:hover {
|
| 538 |
+
border-color: var(--color-primary);
|
| 539 |
+
box-shadow: 0 8px 25px -8px rgba(8, 145, 178, 0.3);
|
| 540 |
+
}
|
| 541 |
+
|
| 542 |
+
.input-section h3 {
|
| 543 |
+
font-size: 1.1rem;
|
| 544 |
+
font-weight: 700;
|
| 545 |
+
color: var(--color-primary);
|
| 546 |
+
margin-bottom: 8px;
|
| 547 |
+
display: flex;
|
| 548 |
+
align-items: center;
|
| 549 |
+
gap: 8px;
|
| 550 |
+
}
|
| 551 |
+
|
| 552 |
+
.input-section .description {
|
| 553 |
+
font-size: 0.9rem;
|
| 554 |
+
color: var(--color-text-secondary);
|
| 555 |
+
margin-bottom: 12px;
|
| 556 |
+
}
|
| 557 |
+
|
| 558 |
+
/* Form Elements */
|
| 559 |
+
label {
|
| 560 |
+
display: block;
|
| 561 |
+
margin-bottom: 6px;
|
| 562 |
+
font-weight: 600;
|
| 563 |
+
color: var(--color-text-primary);
|
| 564 |
+
font-size: 0.95rem;
|
| 565 |
+
}
|
| 566 |
+
|
| 567 |
+
textarea {
|
| 568 |
+
width: 100%;
|
| 569 |
+
padding: 12px 16px;
|
| 570 |
+
border: 2px solid var(--color-border);
|
| 571 |
+
border-radius: 8px;
|
| 572 |
+
font-size: 1rem;
|
| 573 |
+
font-family: inherit;
|
| 574 |
+
background: var(--color-surface);
|
| 575 |
+
transition: all 0.2s ease;
|
| 576 |
+
resize: vertical;
|
| 577 |
+
min-height: 120px;
|
| 578 |
+
}
|
| 579 |
+
|
| 580 |
+
textarea:focus {
|
| 581 |
+
outline: none;
|
| 582 |
+
border-color: var(--color-primary);
|
| 583 |
+
box-shadow: 0 0 0 3px rgba(8, 145, 178, 0.1);
|
| 584 |
+
}
|
| 585 |
+
|
| 586 |
+
/* Character Counter */
|
| 587 |
+
.char-counter {
|
| 588 |
+
font-size: 0.8rem;
|
| 589 |
+
color: var(--color-text-secondary);
|
| 590 |
+
text-align: right;
|
| 591 |
+
margin-top: 4px;
|
| 592 |
+
}
|
| 593 |
+
|
| 594 |
+
/* Generate Button */
|
| 595 |
+
.generate-btn {
|
| 596 |
+
background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-secondary) 100%);
|
| 597 |
+
color: white;
|
| 598 |
+
padding: 16px 32px;
|
| 599 |
+
border: none;
|
| 600 |
+
border-radius: 12px;
|
| 601 |
+
font-size: 1.1rem;
|
| 602 |
+
font-weight: 700;
|
| 603 |
+
cursor: pointer;
|
| 604 |
+
transition: all 0.3s ease;
|
| 605 |
+
display: block;
|
| 606 |
+
margin: 25px auto;
|
| 607 |
+
min-width: 280px;
|
| 608 |
+
position: relative;
|
| 609 |
+
overflow: hidden;
|
| 610 |
+
}
|
| 611 |
+
|
| 612 |
+
.generate-btn:hover {
|
| 613 |
+
transform: translateY(-2px);
|
| 614 |
+
box-shadow: 0 12px 24px -8px rgba(8, 145, 178, 0.4);
|
| 615 |
+
}
|
| 616 |
+
|
| 617 |
+
.generate-btn:active {
|
| 618 |
+
transform: translateY(0);
|
| 619 |
+
}
|
| 620 |
+
|
| 621 |
+
.generate-btn:disabled {
|
| 622 |
+
opacity: 0.7;
|
| 623 |
+
cursor: not-allowed;
|
| 624 |
+
transform: none;
|
| 625 |
+
}
|
| 626 |
+
|
| 627 |
+
/* Loading Spinner */
|
| 628 |
+
.spinner {
|
| 629 |
+
display: none;
|
| 630 |
+
width: 20px;
|
| 631 |
+
height: 20px;
|
| 632 |
+
border: 2px solid rgba(255, 255, 255, 0.3);
|
| 633 |
+
border-radius: 50%;
|
| 634 |
+
border-top-color: white;
|
| 635 |
+
animation: spin 1s ease-in-out infinite;
|
| 636 |
+
margin-right: 8px;
|
| 637 |
+
}
|
| 638 |
+
|
| 639 |
+
@keyframes spin {
|
| 640 |
+
to { transform: rotate(360deg); }
|
| 641 |
+
}
|
| 642 |
+
|
| 643 |
+
/* Output Section */
|
| 644 |
+
.output-section {
|
| 645 |
+
margin-top: 30px;
|
| 646 |
+
}
|
| 647 |
+
|
| 648 |
+
.output-section h2 {
|
| 649 |
+
font-size: 1.5rem;
|
| 650 |
+
font-weight: 700;
|
| 651 |
+
color: var(--color-primary);
|
| 652 |
+
margin-bottom: 15px;
|
| 653 |
+
display: flex;
|
| 654 |
+
align-items: center;
|
| 655 |
+
gap: 8px;
|
| 656 |
+
}
|
| 657 |
+
|
| 658 |
+
.output-area {
|
| 659 |
+
background: var(--color-surface);
|
| 660 |
+
border: 2px solid var(--color-border);
|
| 661 |
+
border-radius: 12px;
|
| 662 |
+
padding: 20px;
|
| 663 |
+
min-height: 300px;
|
| 664 |
+
transition: all 0.3s ease;
|
| 665 |
+
position: relative;
|
| 666 |
+
overflow-x: auto;
|
| 667 |
+
}
|
| 668 |
+
|
| 669 |
+
.output-area:empty::before {
|
| 670 |
+
content: "Your comprehensive empathy map explanation will appear here...";
|
| 671 |
+
color: var(--color-text-secondary);
|
| 672 |
+
font-style: italic;
|
| 673 |
+
}
|
| 674 |
+
|
| 675 |
+
/* Enhanced output styling */
|
| 676 |
+
.output-area h3 {
|
| 677 |
+
color: var(--color-primary);
|
| 678 |
+
border-bottom: 2px solid var(--color-primary);
|
| 679 |
+
padding-bottom: 8px;
|
| 680 |
+
margin: 20px 0 15px 0;
|
| 681 |
+
font-size: 1.2rem;
|
| 682 |
+
}
|
| 683 |
+
|
| 684 |
+
.output-area h4 {
|
| 685 |
+
color: var(--color-secondary);
|
| 686 |
+
margin: 15px 0 10px 0;
|
| 687 |
+
font-size: 1.1rem;
|
| 688 |
+
}
|
| 689 |
+
|
| 690 |
+
.output-area ul {
|
| 691 |
+
margin: 10px 0 15px 20px;
|
| 692 |
+
line-height: 1.7;
|
| 693 |
+
}
|
| 694 |
+
|
| 695 |
+
.output-area li {
|
| 696 |
+
margin-bottom: 5px;
|
| 697 |
+
}
|
| 698 |
+
|
| 699 |
+
.output-area p {
|
| 700 |
+
margin: 12px 0;
|
| 701 |
+
line-height: 1.7;
|
| 702 |
+
}
|
| 703 |
+
|
| 704 |
+
.output-area strong {
|
| 705 |
+
color: var(--color-primary);
|
| 706 |
+
}
|
| 707 |
+
|
| 708 |
+
/* Error Messages */
|
| 709 |
+
.error-message {
|
| 710 |
+
background: rgba(239, 68, 68, 0.1);
|
| 711 |
+
border: 1px solid rgba(239, 68, 68, 0.2);
|
| 712 |
+
color: var(--color-error);
|
| 713 |
+
padding: 12px 16px;
|
| 714 |
+
border-radius: 8px;
|
| 715 |
+
margin: 10px 0;
|
| 716 |
+
font-size: 0.9rem;
|
| 717 |
+
display: none;
|
| 718 |
+
}
|
| 719 |
+
|
| 720 |
+
/* Footer */
|
| 721 |
+
.footer {
|
| 722 |
+
text-align: center;
|
| 723 |
+
padding: 20px;
|
| 724 |
+
background: rgba(8, 145, 178, 0.05);
|
| 725 |
+
border-top: 1px solid var(--color-border);
|
| 726 |
+
color: var(--color-text-secondary);
|
| 727 |
+
font-size: 0.9rem;
|
| 728 |
+
}
|
| 729 |
+
|
| 730 |
+
/* Hidden sections */
|
| 731 |
+
.hidden {
|
| 732 |
+
display: none !important;
|
| 733 |
+
}
|
| 734 |
+
|
| 735 |
+
/* Responsive Design */
|
| 736 |
+
@media (max-width: 768px) {
|
| 737 |
+
body {
|
| 738 |
+
padding: 10px;
|
| 739 |
+
}
|
| 740 |
+
|
| 741 |
+
.language-landing {
|
| 742 |
+
margin: 20px auto;
|
| 743 |
+
padding: 30px 20px;
|
| 744 |
+
}
|
| 745 |
+
|
| 746 |
+
.api-key-compact {
|
| 747 |
+
position: static;
|
| 748 |
+
margin-bottom: var(--spacing-xl);
|
| 749 |
+
max-width: none;
|
| 750 |
+
}
|
| 751 |
+
|
| 752 |
+
.language-switcher {
|
| 753 |
+
position: relative;
|
| 754 |
+
top: auto;
|
| 755 |
+
right: auto;
|
| 756 |
+
margin-bottom: var(--spacing-xl);
|
| 757 |
+
justify-content: center;
|
| 758 |
+
}
|
| 759 |
+
|
| 760 |
+
.main-content {
|
| 761 |
+
padding: 15px 20px 20px;
|
| 762 |
+
}
|
| 763 |
+
|
| 764 |
+
.header h1 {
|
| 765 |
+
font-size: 2rem;
|
| 766 |
+
}
|
| 767 |
+
|
| 768 |
+
.input-section {
|
| 769 |
+
padding: 15px;
|
| 770 |
+
}
|
| 771 |
+
|
| 772 |
+
.empathy-components {
|
| 773 |
+
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
|
| 774 |
+
}
|
| 775 |
+
|
| 776 |
+
.generate-btn {
|
| 777 |
+
width: 100%;
|
| 778 |
+
margin: 20px 0;
|
| 779 |
+
}
|
| 780 |
+
|
| 781 |
+
.output-area {
|
| 782 |
+
padding: 15px;
|
| 783 |
+
}
|
| 784 |
+
}
|
| 785 |
+
|
| 786 |
+
@media (max-width: 480px) {
|
| 787 |
+
.language-landing h1 {
|
| 788 |
+
font-size: 2rem;
|
| 789 |
+
}
|
| 790 |
+
|
| 791 |
+
.header h1 {
|
| 792 |
+
font-size: 1.8rem;
|
| 793 |
+
}
|
| 794 |
+
|
| 795 |
+
.input-section {
|
| 796 |
+
padding: 12px;
|
| 797 |
+
}
|
| 798 |
+
|
| 799 |
+
.empathy-components {
|
| 800 |
+
grid-template-columns: 1fr 1fr;
|
| 801 |
+
}
|
| 802 |
+
}
|
| 803 |
+
|
| 804 |
+
/* Accessibility */
|
| 805 |
+
.sr-only {
|
| 806 |
+
position: absolute;
|
| 807 |
+
width: 1px;
|
| 808 |
+
height: 1px;
|
| 809 |
+
padding: 0;
|
| 810 |
+
margin: -1px;
|
| 811 |
+
overflow: hidden;
|
| 812 |
+
clip: rect(0, 0, 0, 0);
|
| 813 |
+
white-space: nowrap;
|
| 814 |
+
border: 0;
|
| 815 |
+
}
|
| 816 |
+
|
| 817 |
+
/* Focus styles for keyboard navigation */
|
| 818 |
+
.generate-btn:focus,
|
| 819 |
+
.api-key-compact-input:focus,
|
| 820 |
+
textarea:focus {
|
| 821 |
+
outline: 2px solid var(--color-primary);
|
| 822 |
+
outline-offset: 2px;
|
| 823 |
+
}
|
| 824 |
+
|
| 825 |
+
/* Reduced motion support */
|
| 826 |
+
@media (prefers-reduced-motion: reduce) {
|
| 827 |
+
*,
|
| 828 |
+
*::before,
|
| 829 |
+
*::after {
|
| 830 |
+
animation-duration: 0.01ms !important;
|
| 831 |
+
animation-iteration-count: 1 !important;
|
| 832 |
+
transition-duration: 0.01ms !important;
|
| 833 |
+
scroll-behavior: auto !important;
|
| 834 |
+
}
|
| 835 |
+
}
|
| 836 |
+
</style>
|
| 837 |
+
</head>
|
| 838 |
+
|
| 839 |
+
<body>
|
| 840 |
+
<!-- Translation Loading Overlay -->
|
| 841 |
+
<div class="translation-overlay" id="translationOverlay">
|
| 842 |
+
<div class="translation-content">
|
| 843 |
+
<div class="translation-spinner"></div>
|
| 844 |
+
<h2 id="translationTitle">Translating Interface...</h2>
|
| 845 |
+
<p id="translationMessage">Please wait while we translate the interface to your selected language.</p>
|
| 846 |
+
</div>
|
| 847 |
+
</div>
|
| 848 |
+
|
| 849 |
+
<!-- Language Selection Landing Page -->
|
| 850 |
+
<div class="language-landing" id="languageLanding">
|
| 851 |
+
<h1 data-translate="app_title">EmpathyInsights Pro</h1>
|
| 852 |
+
<p data-translate="welcome_message">Welcome! Please select your preferred language and enter your API key to get started with advanced empathy map analysis and user understanding insights.</p>
|
| 853 |
+
|
| 854 |
+
<!-- Cache Status Indicator -->
|
| 855 |
+
<div class="cache-status" id="cacheStatus">
|
| 856 |
+
💾 Translations cached - instant loading!
|
| 857 |
+
</div>
|
| 858 |
+
|
| 859 |
+
<!-- Cache Management Section -->
|
| 860 |
+
<div class="cache-management" id="cacheManagement">
|
| 861 |
+
<h3 data-translate="cache_management_title">🗂️ Translation Cache Management</h3>
|
| 862 |
+
<div class="cache-status-display" id="cacheStatusDisplay">
|
| 863 |
+
<span data-translate="cache_status_checking">Checking cache status...</span>
|
| 864 |
+
</div>
|
| 865 |
+
<button class="clear-cache-btn" id="clearCacheBtn" data-translate="clear_cache_button">
|
| 866 |
+
🗑️ Clear All Cached Translations
|
| 867 |
+
</button>
|
| 868 |
+
</div>
|
| 869 |
+
|
| 870 |
+
<div class="language-selector">
|
| 871 |
+
<label for="languageSelect" data-translate="select_language">🌐 Select Language</label>
|
| 872 |
+
<select id="languageSelect">
|
| 873 |
+
<option value="en">🇺🇸 English</option>
|
| 874 |
+
<option value="es">🇪🇸 Español (Spanish)</option>
|
| 875 |
+
<option value="fr">🇫🇷 Français (French)</option>
|
| 876 |
+
<option value="de">🇩🇪 Deutsch (German)</option>
|
| 877 |
+
<option value="zh">🇨🇳 中文 (Chinese)</option>
|
| 878 |
+
<option value="ja">🇯🇵 日本語 (Japanese)</option>
|
| 879 |
+
<option value="ko">🇰🇷 한국어 (Korean)</option>
|
| 880 |
+
<option value="pt">🇵🇹 Português (Portuguese)</option>
|
| 881 |
+
<option value="it">🇮🇹 Italiano (Italian)</option>
|
| 882 |
+
<option value="ar">🇸🇦 العربية (Arabic)</option>
|
| 883 |
+
<option value="ru">🇷🇺 Русский (Russian)</option>
|
| 884 |
+
<option value="hi">🇮🇳 हिन्दी (Hindi)</option>
|
| 885 |
+
<option value="bn">🇧🇩 বাংলা (Bengali)</option>
|
| 886 |
+
<option value="ur">🇵🇰 اردو (Urdu)</option>
|
| 887 |
+
<option value="tr">🇹🇷 Türkçe (Turkish)</option>
|
| 888 |
+
<option value="pl">🇵🇱 Polski (Polish)</option>
|
| 889 |
+
<option value="nl">🇳🇱 Nederlands (Dutch)</option>
|
| 890 |
+
<option value="sv">🇸🇪 Svenska (Swedish)</option>
|
| 891 |
+
<option value="da">🇩🇰 Dansk (Danish)</option>
|
| 892 |
+
<option value="no">🇳🇴 Norsk (Norwegian)</option>
|
| 893 |
+
<option value="fi">🇫🇮 Suomi (Finnish)</option>
|
| 894 |
+
<option value="is">🇮🇸 Íslenska (Icelandic)</option>
|
| 895 |
+
<option value="cs">🇨🇿 Čeština (Czech)</option>
|
| 896 |
+
<option value="sk">🇸🇰 Slovenčina (Slovak)</option>
|
| 897 |
+
<option value="hu">🇭🇺 Magyar (Hungarian)</option>
|
| 898 |
+
<option value="ro">🇷🇴 Română (Romanian)</option>
|
| 899 |
+
<option value="bg">🇧🇬 Български (Bulgarian)</option>
|
| 900 |
+
<option value="hr">🇭🇷 Hrvatski (Croatian)</option>
|
| 901 |
+
<option value="sr">🇷🇸 Српски (Serbian)</option>
|
| 902 |
+
<option value="sl">🇸🇮 Slovenščina (Slovenian)</option>
|
| 903 |
+
<option value="mk">🇲🇰 Македонски (Macedonian)</option>
|
| 904 |
+
<option value="sq">🇦🇱 Shqip (Albanian)</option>
|
| 905 |
+
<option value="lv">🇱🇻 Latviešu (Latvian)</option>
|
| 906 |
+
<option value="lt">🇱🇹 Lietuvių (Lithuanian)</option>
|
| 907 |
+
<option value="et">🇪🇪 Eesti (Estonian)</option>
|
| 908 |
+
<option value="mt">🇲🇹 Malti (Maltese)</option>
|
| 909 |
+
<option value="ga">🇮🇪 Gaeilge (Irish)</option>
|
| 910 |
+
<option value="cy">🏴 Cymraeg (Welsh)</option>
|
| 911 |
+
<option value="eu">🏴 Euskera (Basque)</option>
|
| 912 |
+
<option value="ca">🏴 Català (Catalan)</option>
|
| 913 |
+
<option value="gl">🏴 Galego (Galician)</option>
|
| 914 |
+
<option value="el">🇬🇷 Ελληνικά (Greek)</option>
|
| 915 |
+
<option value="he">🇮🇱 עברית (Hebrew)</option>
|
| 916 |
+
<option value="fa">🇮🇷 فارسی (Persian)</option>
|
| 917 |
+
<option value="ps">🇦🇫 پښتو (Pashto)</option>
|
| 918 |
+
<option value="ku">🏴 کوردی (Kurdish)</option>
|
| 919 |
+
<option value="az">🇦🇿 Azərbaycan (Azerbaijani)</option>
|
| 920 |
+
<option value="kk">🇰🇿 Қазақша (Kazakh)</option>
|
| 921 |
+
<option value="ky">🇰🇬 Кыргызча (Kyrgyz)</option>
|
| 922 |
+
<option value="uz">🇺🇿 O'zbek (Uzbek)</option>
|
| 923 |
+
<option value="tk">🇹🇲 Türkmen (Turkmen)</option>
|
| 924 |
+
<option value="tg">🇹🇯 Тоҷикӣ (Tajik)</option>
|
| 925 |
+
<option value="mn">🇲🇳 Монгол (Mongolian)</option>
|
| 926 |
+
<option value="ka">🇬🇪 ქართული (Georgian)</option>
|
| 927 |
+
<option value="hy">🇦🇲 Հայերեն (Armenian)</option>
|
| 928 |
+
<option value="th">🇹🇭 ไทย (Thai)</option>
|
| 929 |
+
<option value="vi">🇻🇳 Tiếng Việt (Vietnamese)</option>
|
| 930 |
+
<option value="lo">🇱🇦 ລາວ (Lao)</option>
|
| 931 |
+
<option value="km">🇰🇭 ខ្មែរ (Khmer)</option>
|
| 932 |
+
<option value="my">🇲🇲 မြန်မာ (Myanmar)</option>
|
| 933 |
+
<option value="si">🇱🇰 සිංහල (Sinhala)</option>
|
| 934 |
+
<option value="ta">🇱🇰 தமிழ் (Tamil)</option>
|
| 935 |
+
<option value="te">🇮🇳 తెలుగు (Telugu)</option>
|
| 936 |
+
<option value="kn">🇮🇳 ಕನ್ನಡ (Kannada)</option>
|
| 937 |
+
<option value="ml">🇮🇳 മലയാളം (Malayalam)</option>
|
| 938 |
+
<option value="gu">🇮🇳 ગુજરાતી (Gujarati)</option>
|
| 939 |
+
<option value="pa">🇮🇳 ਪੰਜਾਬੀ (Punjabi)</option>
|
| 940 |
+
<option value="or">🇮🇳 ଓଡ଼ିଆ (Odia)</option>
|
| 941 |
+
<option value="as">🇮🇳 অসমীয়া (Assamese)</option>
|
| 942 |
+
<option value="ne">🇳🇵 नेपाली (Nepali)</option>
|
| 943 |
+
<option value="dz">🇧🇹 རྫོང་ཁ (Dzongkha)</option>
|
| 944 |
+
<option value="bo">🏔️ བོད་ཡིག (Tibetan)</option>
|
| 945 |
+
<option value="id">🇮🇩 Bahasa Indonesia</option>
|
| 946 |
+
<option value="ms">🇲🇾 Bahasa Melayu (Malay)</option>
|
| 947 |
+
<option value="tl">🇵🇭 Filipino (Tagalog)</option>
|
| 948 |
+
<option value="ceb">🇵🇭 Cebuano</option>
|
| 949 |
+
<option value="haw">🏝️ ʻŌlelo Hawaiʻi (Hawaiian)</option>
|
| 950 |
+
<option value="mi">🇳🇿 Te Reo Māori (Maori)</option>
|
| 951 |
+
<option value="sm">🇼🇸 Gagana Samoa (Samoan)</option>
|
| 952 |
+
<option value="to">🇹🇴 Lea Fakatonga (Tongan)</option>
|
| 953 |
+
<option value="fj">🇫🇯 Na Vosa Vakaviti (Fijian)</option>
|
| 954 |
+
<option value="mg">🇲🇬 Malagasy</option>
|
| 955 |
+
<option value="sw">🇰🇪 Kiswahili (Swahili)</option>
|
| 956 |
+
<option value="zu">🇿🇦 isiZulu (Zulu)</option>
|
| 957 |
+
<option value="xh">🇿🇦 isiXhosa (Xhosa)</option>
|
| 958 |
+
<option value="af">🇿🇦 Afrikaans</option>
|
| 959 |
+
<option value="st">🇱🇸 Sesotho (Southern Sotho)</option>
|
| 960 |
+
<option value="tn">🇧🇼 Setswana (Tswana)</option>
|
| 961 |
+
<option value="ss">🇸🇿 siSwati (Swati)</option>
|
| 962 |
+
<option value="ve">🇿🇦 Tshivenḓa (Venda)</option>
|
| 963 |
+
<option value="ts">🇿🇦 Xitsonga (Tsonga)</option>
|
| 964 |
+
<option value="nr">🇿🇦 isiNdebele (Southern Ndebele)</option>
|
| 965 |
+
<option value="am">🇪🇹 አማርኛ (Amharic)</option>
|
| 966 |
+
<option value="ti">🇪🇷 ትግርኛ (Tigrinya)</option>
|
| 967 |
+
<option value="om">🇪🇹 Afaan Oromoo (Oromo)</option>
|
| 968 |
+
<option value="so">🇸🇴 Soomaali (Somali)</option>
|
| 969 |
+
<option value="ha">🇳🇬 Hausa</option>
|
| 970 |
+
<option value="yo">🇳🇬 Yorùbá (Yoruba)</option>
|
| 971 |
+
<option value="ig">🇳🇬 Igbo</option>
|
| 972 |
+
<option value="ff">🇸🇳 Fulfulde (Fulani)</option>
|
| 973 |
+
<option value="wo">🇸🇳 Wolof</option>
|
| 974 |
+
<option value="bm">🇲🇱 Bamanankan (Bambara)</option>
|
| 975 |
+
<option value="rn">🇧🇮 Kirundi (Rundi)</option>
|
| 976 |
+
<option value="rw">🇷🇼 Kinyarwanda (Rwanda)</option>
|
| 977 |
+
<option value="lg">🇺🇬 Luganda</option>
|
| 978 |
+
<option value="ny">🇲🇼 Chichewa (Nyanja)</option>
|
| 979 |
+
<option value="sn">🇿🇼 chiShona (Shona)</option>
|
| 980 |
+
<option value="nd">🇿🇼 isiNdebele (Northern Ndebele)</option>
|
| 981 |
+
</select>
|
| 982 |
+
</div>
|
| 983 |
+
|
| 984 |
+
<div class="api-key-landing">
|
| 985 |
+
<label for="apiKeyLanding" data-translate="api_key_label">🔑 OpenAI API Key</label>
|
| 986 |
+
<input type="password" id="apiKeyLanding" placeholder="Enter your OpenAI API key" data-translate-placeholder="api_key_placeholder">
|
| 987 |
+
</div>
|
| 988 |
+
|
| 989 |
+
<button class="start-btn" id="startBtn" data-translate="start_button">🚀 Start Empathy Analysis</button>
|
| 990 |
+
</div>
|
| 991 |
+
|
| 992 |
+
<!-- Main Application -->
|
| 993 |
+
<div class="main-app" id="mainApp">
|
| 994 |
+
<div class="app-container">
|
| 995 |
+
<!-- Language Switcher -->
|
| 996 |
+
<div class="language-switcher" id="languageSwitcher">
|
| 997 |
+
<div class="language-switch-btn" onclick="showLanguageLanding()">
|
| 998 |
+
<span data-translate="change_language">🌐 Change Language</span>
|
| 999 |
+
</div>
|
| 1000 |
+
<div class="mini-clear-cache" onclick="clearAllTranslationCache()" title="Clear translation cache">
|
| 1001 |
+
<span data-translate="clear_cache_mini">🗑️ Clear Cache</span>
|
| 1002 |
+
</div>
|
| 1003 |
+
</div>
|
| 1004 |
+
|
| 1005 |
+
<!-- Compact API Key in Top-Left -->
|
| 1006 |
+
<div class="api-key-compact">
|
| 1007 |
+
<label for="apiKey" class="api-key-compact-label" data-translate="api_key_short">API Key</label>
|
| 1008 |
+
<input
|
| 1009 |
+
type="password"
|
| 1010 |
+
id="apiKey"
|
| 1011 |
+
class="api-key-compact-input"
|
| 1012 |
+
data-translate-placeholder="api_key_placeholder"
|
| 1013 |
+
autocomplete="off"
|
| 1014 |
+
>
|
| 1015 |
+
</div>
|
| 1016 |
+
|
| 1017 |
+
<div class="main-content">
|
| 1018 |
+
<!-- Header -->
|
| 1019 |
+
<div class="header">
|
| 1020 |
+
<h1 data-translate="app_title">EmpathyInsights Pro</h1>
|
| 1021 |
+
<p class="subtitle" data-translate="app_subtitle">Advanced User Understanding & Experience Design</p>
|
| 1022 |
+
<p class="description" data-translate="app_description">Generate comprehensive empathy map explanations tailored to your specific context and user research needs</p>
|
| 1023 |
+
</div>
|
| 1024 |
+
|
| 1025 |
+
<!-- Empathy Map Components Overview -->
|
| 1026 |
+
<div class="empathy-components">
|
| 1027 |
+
<div class="component-card">
|
| 1028 |
+
<h4 data-translate="component_says">💬 Says</h4>
|
| 1029 |
+
<p data-translate="component_says_desc">Quotes & Statements</p>
|
| 1030 |
+
</div>
|
| 1031 |
+
<div class="component-card">
|
| 1032 |
+
<h4 data-translate="component_thinks">💭 Thinks</h4>
|
| 1033 |
+
<p data-translate="component_thinks_desc">Thoughts & Beliefs</p>
|
| 1034 |
+
</div>
|
| 1035 |
+
<div class="component-card">
|
| 1036 |
+
<h4 data-translate="component_does">🎯 Does</h4>
|
| 1037 |
+
<p data-translate="component_does_desc">Actions & Behaviors</p>
|
| 1038 |
+
</div>
|
| 1039 |
+
<div class="component-card">
|
| 1040 |
+
<h4 data-translate="component_feels">❤️ Feels</h4>
|
| 1041 |
+
<p data-translate="component_feels_desc">Emotions & Feelings</p>
|
| 1042 |
+
</div>
|
| 1043 |
+
<div class="component-card">
|
| 1044 |
+
<h4 data-translate="component_pain">😰 Pain Points</h4>
|
| 1045 |
+
<p data-translate="component_pain_desc">Frustrations & Obstacles</p>
|
| 1046 |
+
</div>
|
| 1047 |
+
<div class="component-card">
|
| 1048 |
+
<h4 data-translate="component_gains">🎁 Gains</h4>
|
| 1049 |
+
<p data-translate="component_gains_desc">Goals & Aspirations</p>
|
| 1050 |
+
</div>
|
| 1051 |
+
</div>
|
| 1052 |
+
|
| 1053 |
+
<!-- Input Section -->
|
| 1054 |
+
<div class="input-section">
|
| 1055 |
+
<h3 data-translate="input_title">📝 Context & User Research Input</h3>
|
| 1056 |
+
<p class="description" data-translate="input_description">Describe your user research context, target audience, product/service, or specific empathy mapping scenario</p>
|
| 1057 |
+
<textarea id="textInput" data-translate-placeholder="input_placeholder" required></textarea>
|
| 1058 |
+
<div class="char-counter" id="charCounter">0 characters</div>
|
| 1059 |
+
</div>
|
| 1060 |
+
|
| 1061 |
+
<!-- Error Message -->
|
| 1062 |
+
<div class="error-message" id="errorMessage"></div>
|
| 1063 |
+
|
| 1064 |
+
<!-- Generate Button -->
|
| 1065 |
+
<button class="generate-btn" id="generateEmpathyBtn">
|
| 1066 |
+
<span class="spinner" id="spinner"></span>
|
| 1067 |
+
<span id="buttonText" data-translate="generate_button">🧠 Generate Empathy Map Guide</span>
|
| 1068 |
+
</button>
|
| 1069 |
+
|
| 1070 |
+
<!-- Output Section -->
|
| 1071 |
+
<div class="output-section">
|
| 1072 |
+
<h2 data-translate="output_title">🗺️ Your Personalized Empathy Map Guide</h2>
|
| 1073 |
+
<div class="output-area" id="apiOutput"></div>
|
| 1074 |
+
</div>
|
| 1075 |
+
</div>
|
| 1076 |
+
|
| 1077 |
+
<!-- Footer -->
|
| 1078 |
+
<div class="footer">
|
| 1079 |
+
Created by Shift Mind AI Labs
|
| 1080 |
+
</div>
|
| 1081 |
+
</div>
|
| 1082 |
+
</div>
|
| 1083 |
+
|
| 1084 |
+
<script>
|
| 1085 |
+
// RTL languages list
|
| 1086 |
+
const rtlLanguages = ['ar', 'he', 'fa', 'ur', 'ps', 'ku'];
|
| 1087 |
+
|
| 1088 |
+
// Current language and API key
|
| 1089 |
+
let currentLanguage = 'en';
|
| 1090 |
+
let currentApiKey = '';
|
| 1091 |
+
|
| 1092 |
+
// Language names mapping
|
| 1093 |
+
const languageNames = {
|
| 1094 |
+
en: 'English', es: 'Spanish', fr: 'French', de: 'German', zh: 'Chinese',
|
| 1095 |
+
ja: 'Japanese', ko: 'Korean', pt: 'Portuguese', it: 'Italian', ar: 'Arabic',
|
| 1096 |
+
ru: 'Russian', hi: 'Hindi', bn: 'Bengali', ur: 'Urdu', tr: 'Turkish',
|
| 1097 |
+
pl: 'Polish', nl: 'Dutch', sv: 'Swedish', da: 'Danish', no: 'Norwegian',
|
| 1098 |
+
fi: 'Finnish', is: 'Icelandic', cs: 'Czech', sk: 'Slovak', hu: 'Hungarian',
|
| 1099 |
+
ro: 'Romanian', bg: 'Bulgarian', hr: 'Croatian', sr: 'Serbian', sl: 'Slovenian',
|
| 1100 |
+
mk: 'Macedonian', sq: 'Albanian', lv: 'Latvian', lt: 'Lithuanian', et: 'Estonian',
|
| 1101 |
+
mt: 'Maltese', ga: 'Irish', cy: 'Welsh', eu: 'Basque', ca: 'Catalan',
|
| 1102 |
+
gl: 'Galician', el: 'Greek', he: 'Hebrew', fa: 'Persian', ps: 'Pashto',
|
| 1103 |
+
ku: 'Kurdish', az: 'Azerbaijani', kk: 'Kazakh', ky: 'Kyrgyz', uz: 'Uzbek',
|
| 1104 |
+
tk: 'Turkmen', tg: 'Tajik', mn: 'Mongolian', ka: 'Georgian', hy: 'Armenian',
|
| 1105 |
+
th: 'Thai', vi: 'Vietnamese', lo: 'Lao', km: 'Khmer', my: 'Myanmar',
|
| 1106 |
+
si: 'Sinhala', ta: 'Tamil', te: 'Telugu', kn: 'Kannada', ml: 'Malayalam',
|
| 1107 |
+
gu: 'Gujarati', pa: 'Punjabi', or: 'Odia', as: 'Assamese', ne: 'Nepali',
|
| 1108 |
+
dz: 'Dzongkha', bo: 'Tibetan', id: 'Indonesian', ms: 'Malay', tl: 'Filipino',
|
| 1109 |
+
ceb: 'Cebuano', haw: 'Hawaiian', mi: 'Maori', sm: 'Samoan', to: 'Tongan',
|
| 1110 |
+
fj: 'Fijian', mg: 'Malagasy', sw: 'Swahili', zu: 'Zulu', xh: 'Xhosa',
|
| 1111 |
+
af: 'Afrikaans', st: 'Southern Sotho', tn: 'Tswana', ss: 'Swati', ve: 'Venda',
|
| 1112 |
+
ts: 'Tsonga', nr: 'Southern Ndebele', am: 'Amharic', ti: 'Tigrinya', om: 'Oromo',
|
| 1113 |
+
so: 'Somali', ha: 'Hausa', yo: 'Yoruba', ig: 'Igbo', ff: 'Fulani',
|
| 1114 |
+
wo: 'Wolof', bm: 'Bambara', rn: 'Rundi', rw: 'Rwanda', lg: 'Luganda',
|
| 1115 |
+
ny: 'Chichewa', sn: 'Shona', nd: 'Northern Ndebele'
|
| 1116 |
+
};
|
| 1117 |
+
|
| 1118 |
+
// Translation cache management
|
| 1119 |
+
const CACHE_PREFIX = 'empathy_insights_translations_';
|
| 1120 |
+
const CACHE_VERSION = '1.0';
|
| 1121 |
+
|
| 1122 |
+
// Check if translations are cached for a language
|
| 1123 |
+
function isLanguageCached(language) {
|
| 1124 |
+
const cacheKey = CACHE_PREFIX + language;
|
| 1125 |
+
const cached = localStorage.getItem(cacheKey);
|
| 1126 |
+
return cached !== null;
|
| 1127 |
+
}
|
| 1128 |
+
|
| 1129 |
+
// Save translations to cache
|
| 1130 |
+
function saveTranslationsToCache(language, translations) {
|
| 1131 |
+
const cacheKey = CACHE_PREFIX + language;
|
| 1132 |
+
const cacheData = {
|
| 1133 |
+
version: CACHE_VERSION,
|
| 1134 |
+
timestamp: Date.now(),
|
| 1135 |
+
translations: translations
|
| 1136 |
+
};
|
| 1137 |
+
localStorage.setItem(cacheKey, JSON.stringify(cacheData));
|
| 1138 |
+
console.log(`Translations cached for ${language}`);
|
| 1139 |
+
}
|
| 1140 |
+
|
| 1141 |
+
// Load translations from cache
|
| 1142 |
+
function loadTranslationsFromCache(language) {
|
| 1143 |
+
const cacheKey = CACHE_PREFIX + language;
|
| 1144 |
+
const cached = localStorage.getItem(cacheKey);
|
| 1145 |
+
|
| 1146 |
+
if (cached) {
|
| 1147 |
+
try {
|
| 1148 |
+
const cacheData = JSON.parse(cached);
|
| 1149 |
+
if (cacheData.version === CACHE_VERSION) {
|
| 1150 |
+
console.log(`Translations loaded from cache for ${language}`);
|
| 1151 |
+
return cacheData.translations;
|
| 1152 |
+
}
|
| 1153 |
+
} catch (error) {
|
| 1154 |
+
console.error('Error parsing cached translations:', error);
|
| 1155 |
+
}
|
| 1156 |
+
}
|
| 1157 |
+
return null;
|
| 1158 |
+
}
|
| 1159 |
+
|
| 1160 |
+
// Get all cached languages
|
| 1161 |
+
function getCachedLanguages() {
|
| 1162 |
+
const cachedLanguages = [];
|
| 1163 |
+
for (let i = 0; i < localStorage.length; i++) {
|
| 1164 |
+
const key = localStorage.key(i);
|
| 1165 |
+
if (key && key.startsWith(CACHE_PREFIX)) {
|
| 1166 |
+
const language = key.replace(CACHE_PREFIX, '');
|
| 1167 |
+
cachedLanguages.push(language);
|
| 1168 |
+
}
|
| 1169 |
+
}
|
| 1170 |
+
return cachedLanguages;
|
| 1171 |
+
}
|
| 1172 |
+
|
| 1173 |
+
// Clear all translation cache
|
| 1174 |
+
function clearAllTranslationCache() {
|
| 1175 |
+
const cachedLanguages = getCachedLanguages();
|
| 1176 |
+
|
| 1177 |
+
if (cachedLanguages.length === 0) {
|
| 1178 |
+
alert('No cached translations to clear.');
|
| 1179 |
+
return;
|
| 1180 |
+
}
|
| 1181 |
+
|
| 1182 |
+
const languageList = cachedLanguages.map(lang => languageNames[lang] || lang).join(', ');
|
| 1183 |
+
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.`;
|
| 1184 |
+
|
| 1185 |
+
if (confirm(confirmMessage)) {
|
| 1186 |
+
// Clear all translation caches
|
| 1187 |
+
cachedLanguages.forEach(language => {
|
| 1188 |
+
const cacheKey = CACHE_PREFIX + language;
|
| 1189 |
+
localStorage.removeItem(cacheKey);
|
| 1190 |
+
});
|
| 1191 |
+
|
| 1192 |
+
// Update cache status
|
| 1193 |
+
updateCacheStatus(currentLanguage);
|
| 1194 |
+
updateCacheStatusDisplay();
|
| 1195 |
+
|
| 1196 |
+
alert(`Cache cleared successfully!\n\n${cachedLanguages.length} language(s) removed from cache.`);
|
| 1197 |
+
|
| 1198 |
+
// Ask if user wants to reload current language translations
|
| 1199 |
+
if (currentLanguage !== 'en' && cachedLanguages.includes(currentLanguage)) {
|
| 1200 |
+
if (confirm('Would you like to reload the current language translations?')) {
|
| 1201 |
+
applyLanguage(currentLanguage);
|
| 1202 |
+
}
|
| 1203 |
+
}
|
| 1204 |
+
}
|
| 1205 |
+
}
|
| 1206 |
+
|
| 1207 |
+
// Update cache status indicator
|
| 1208 |
+
function updateCacheStatus(language) {
|
| 1209 |
+
const cacheStatus = document.getElementById('cacheStatus');
|
| 1210 |
+
const isCached = isLanguageCached(language);
|
| 1211 |
+
|
| 1212 |
+
if (language === 'en') {
|
| 1213 |
+
cacheStatus.classList.remove('cached', 'translating');
|
| 1214 |
+
return;
|
| 1215 |
+
}
|
| 1216 |
+
|
| 1217 |
+
if (isCached) {
|
| 1218 |
+
cacheStatus.textContent = '💾 Translations cached - instant loading!';
|
| 1219 |
+
cacheStatus.classList.add('cached');
|
| 1220 |
+
cacheStatus.classList.remove('translating');
|
| 1221 |
+
} else {
|
| 1222 |
+
cacheStatus.textContent = '🔄 First time translation - will be cached for future use';
|
| 1223 |
+
cacheStatus.classList.add('translating');
|
| 1224 |
+
cacheStatus.classList.remove('cached');
|
| 1225 |
+
}
|
| 1226 |
+
}
|
| 1227 |
+
|
| 1228 |
+
// Update cache status display in management section
|
| 1229 |
+
function updateCacheStatusDisplay() {
|
| 1230 |
+
const cacheStatusDisplay = document.getElementById('cacheStatusDisplay');
|
| 1231 |
+
const clearCacheBtn = document.getElementById('clearCacheBtn');
|
| 1232 |
+
const cachedLanguages = getCachedLanguages();
|
| 1233 |
+
|
| 1234 |
+
if (cachedLanguages.length === 0) {
|
| 1235 |
+
cacheStatusDisplay.textContent = '📭 No cached translations';
|
| 1236 |
+
cacheStatusDisplay.className = 'cache-status-display no-cache';
|
| 1237 |
+
clearCacheBtn.disabled = true;
|
| 1238 |
+
} else {
|
| 1239 |
+
const languageList = cachedLanguages.map(lang => languageNames[lang] || lang).join(', ');
|
| 1240 |
+
cacheStatusDisplay.textContent = `💾 ${cachedLanguages.length} language(s) cached: ${languageList}`;
|
| 1241 |
+
cacheStatusDisplay.className = 'cache-status-display';
|
| 1242 |
+
clearCacheBtn.disabled = false;
|
| 1243 |
+
}
|
| 1244 |
+
}
|
| 1245 |
+
|
| 1246 |
+
// Initialize the application
|
| 1247 |
+
function initializeApp() {
|
| 1248 |
+
// Load saved language and API key
|
| 1249 |
+
const savedLanguage = localStorage.getItem('empathy_insights_language') || 'en';
|
| 1250 |
+
const savedApiKey = localStorage.getItem('empathy_insights_api_key') || '';
|
| 1251 |
+
|
| 1252 |
+
currentLanguage = savedLanguage;
|
| 1253 |
+
currentApiKey = savedApiKey;
|
| 1254 |
+
|
| 1255 |
+
// Set language selector
|
| 1256 |
+
document.getElementById('languageSelect').value = currentLanguage;
|
| 1257 |
+
document.getElementById('apiKeyLanding').value = currentApiKey;
|
| 1258 |
+
|
| 1259 |
+
// Apply direction for current language
|
| 1260 |
+
applyDirection(currentLanguage);
|
| 1261 |
+
|
| 1262 |
+
// Update cache status
|
| 1263 |
+
updateCacheStatus(currentLanguage);
|
| 1264 |
+
updateCacheStatusDisplay();
|
| 1265 |
+
|
| 1266 |
+
// Show appropriate screen
|
| 1267 |
+
if (currentApiKey && currentLanguage) {
|
| 1268 |
+
showMainApp();
|
| 1269 |
+
} else {
|
| 1270 |
+
showLanguageLanding();
|
| 1271 |
+
}
|
| 1272 |
+
}
|
| 1273 |
+
|
| 1274 |
+
// Apply language direction
|
| 1275 |
+
function applyDirection(language) {
|
| 1276 |
+
currentLanguage = language;
|
| 1277 |
+
|
| 1278 |
+
// Set document language and direction
|
| 1279 |
+
document.documentElement.lang = language;
|
| 1280 |
+
document.documentElement.dir = rtlLanguages.includes(language) ? 'rtl' : 'ltr';
|
| 1281 |
+
|
| 1282 |
+
// Save language preference
|
| 1283 |
+
localStorage.setItem('empathy_insights_language', language);
|
| 1284 |
+
|
| 1285 |
+
// Update cache status
|
| 1286 |
+
updateCacheStatus(language);
|
| 1287 |
+
}
|
| 1288 |
+
|
| 1289 |
+
// API call function for translation
|
| 1290 |
+
async function translateText(text, targetLanguage) {
|
| 1291 |
+
if (!currentApiKey) {
|
| 1292 |
+
throw new Error('API key is required for translation');
|
| 1293 |
+
}
|
| 1294 |
+
|
| 1295 |
+
const languageName = languageNames[targetLanguage] || 'English';
|
| 1296 |
+
|
| 1297 |
+
const prompt = `Translate the following text to ${languageName}. Provide ONLY the exact translation without any explanations, additional information, or formatting:
|
| 1298 |
+
|
| 1299 |
+
"${text}"`;
|
| 1300 |
+
|
| 1301 |
+
const payload = {
|
| 1302 |
+
model: "gpt-4o-mini",
|
| 1303 |
+
messages: [{ role: "user", content: prompt }],
|
| 1304 |
+
max_tokens: 500,
|
| 1305 |
+
temperature: 0.1
|
| 1306 |
+
};
|
| 1307 |
+
|
| 1308 |
+
const response = await fetch("https://api.openai.com/v1/chat/completions", {
|
| 1309 |
+
method: "POST",
|
| 1310 |
+
headers: {
|
| 1311 |
+
"Content-Type": "application/json",
|
| 1312 |
+
"Authorization": `Bearer ${currentApiKey}`
|
| 1313 |
+
},
|
| 1314 |
+
body: JSON.stringify(payload)
|
| 1315 |
+
});
|
| 1316 |
+
|
| 1317 |
+
if (!response.ok) {
|
| 1318 |
+
const errorData = await response.json();
|
| 1319 |
+
throw new Error(errorData.error?.message || "Translation API request failed");
|
| 1320 |
+
}
|
| 1321 |
+
|
| 1322 |
+
const data = await response.json();
|
| 1323 |
+
return data.choices[0].message.content.trim();
|
| 1324 |
+
}
|
| 1325 |
+
|
| 1326 |
+
// Apply cached translations to UI
|
| 1327 |
+
function applyCachedTranslations(translations) {
|
| 1328 |
+
// Apply text translations
|
| 1329 |
+
Object.keys(translations.texts).forEach(originalText => {
|
| 1330 |
+
const translation = translations.texts[originalText];
|
| 1331 |
+
const elements = document.querySelectorAll(`[data-translate]`);
|
| 1332 |
+
|
| 1333 |
+
elements.forEach(element => {
|
| 1334 |
+
const originalElementText = element.getAttribute('data-original-text') || element.textContent;
|
| 1335 |
+
if (originalElementText === originalText) {
|
| 1336 |
+
element.textContent = translation;
|
| 1337 |
+
}
|
| 1338 |
+
});
|
| 1339 |
+
});
|
| 1340 |
+
|
| 1341 |
+
// Apply placeholder translations
|
| 1342 |
+
Object.keys(translations.placeholders).forEach(originalPlaceholder => {
|
| 1343 |
+
const translation = translations.placeholders[originalPlaceholder];
|
| 1344 |
+
const elements = document.querySelectorAll(`[data-translate-placeholder]`);
|
| 1345 |
+
|
| 1346 |
+
elements.forEach(element => {
|
| 1347 |
+
const originalElementPlaceholder = element.getAttribute('data-original-placeholder') || element.placeholder;
|
| 1348 |
+
if (originalElementPlaceholder === originalPlaceholder) {
|
| 1349 |
+
element.placeholder = translation;
|
| 1350 |
+
}
|
| 1351 |
+
});
|
| 1352 |
+
});
|
| 1353 |
+
}
|
| 1354 |
+
|
| 1355 |
+
// Translate all UI elements
|
| 1356 |
+
async function translateInterface(targetLanguage) {
|
| 1357 |
+
if (targetLanguage === 'en') {
|
| 1358 |
+
// No translation needed for English
|
| 1359 |
+
return;
|
| 1360 |
+
}
|
| 1361 |
+
|
| 1362 |
+
// Check if translations are cached
|
| 1363 |
+
const cachedTranslations = loadTranslationsFromCache(targetLanguage);
|
| 1364 |
+
if (cachedTranslations) {
|
| 1365 |
+
// Use cached translations
|
| 1366 |
+
console.log('Using cached translations for', targetLanguage);
|
| 1367 |
+
applyCachedTranslations(cachedTranslations);
|
| 1368 |
+
return;
|
| 1369 |
+
}
|
| 1370 |
+
|
| 1371 |
+
// Need to translate via API
|
| 1372 |
+
showTranslationOverlay();
|
| 1373 |
+
|
| 1374 |
+
try {
|
| 1375 |
+
// Get all elements with data-translate attribute
|
| 1376 |
+
const elements = document.querySelectorAll('[data-translate]');
|
| 1377 |
+
const placeholderElements = document.querySelectorAll('[data-translate-placeholder]');
|
| 1378 |
+
|
| 1379 |
+
// Collect all texts to translate
|
| 1380 |
+
const textsToTranslate = [];
|
| 1381 |
+
const placeholdersToTranslate = [];
|
| 1382 |
+
const elementMap = new Map();
|
| 1383 |
+
|
| 1384 |
+
elements.forEach(element => {
|
| 1385 |
+
const originalText = element.getAttribute('data-original-text') || element.textContent;
|
| 1386 |
+
if (!element.getAttribute('data-original-text')) {
|
| 1387 |
+
element.setAttribute('data-original-text', originalText);
|
| 1388 |
+
}
|
| 1389 |
+
textsToTranslate.push(originalText);
|
| 1390 |
+
elementMap.set(originalText, element);
|
| 1391 |
+
});
|
| 1392 |
+
|
| 1393 |
+
placeholderElements.forEach(element => {
|
| 1394 |
+
const originalPlaceholder = element.getAttribute('data-original-placeholder') || element.placeholder;
|
| 1395 |
+
if (!element.getAttribute('data-original-placeholder')) {
|
| 1396 |
+
element.setAttribute('data-original-placeholder', originalPlaceholder);
|
| 1397 |
+
}
|
| 1398 |
+
placeholdersToTranslate.push(originalPlaceholder);
|
| 1399 |
+
elementMap.set(originalPlaceholder, element);
|
| 1400 |
+
});
|
| 1401 |
+
|
| 1402 |
+
// Prepare cache structure
|
| 1403 |
+
const translationsCache = {
|
| 1404 |
+
texts: {},
|
| 1405 |
+
placeholders: {}
|
| 1406 |
+
};
|
| 1407 |
+
|
| 1408 |
+
// Translate texts in batches
|
| 1409 |
+
const batchSize = 10;
|
| 1410 |
+
const allTexts = [...textsToTranslate, ...placeholdersToTranslate];
|
| 1411 |
+
|
| 1412 |
+
for (let i = 0; i < allTexts.length; i += batchSize) {
|
| 1413 |
+
const batch = allTexts.slice(i, i + batchSize);
|
| 1414 |
+
|
| 1415 |
+
// Update progress
|
| 1416 |
+
updateTranslationProgress(i, allTexts.length);
|
| 1417 |
+
|
| 1418 |
+
// Translate batch
|
| 1419 |
+
const translations = await Promise.all(
|
| 1420 |
+
batch.map(text => translateText(text, targetLanguage))
|
| 1421 |
+
);
|
| 1422 |
+
|
| 1423 |
+
// Apply translations and cache them
|
| 1424 |
+
batch.forEach((originalText, index) => {
|
| 1425 |
+
const element = elementMap.get(originalText);
|
| 1426 |
+
const translation = translations[index];
|
| 1427 |
+
|
| 1428 |
+
if (element.hasAttribute('data-translate')) {
|
| 1429 |
+
element.textContent = translation;
|
| 1430 |
+
translationsCache.texts[originalText] = translation;
|
| 1431 |
+
} else if (element.hasAttribute('data-translate-placeholder')) {
|
| 1432 |
+
element.placeholder = translation;
|
| 1433 |
+
translationsCache.placeholders[originalText] = translation;
|
| 1434 |
+
}
|
| 1435 |
+
});
|
| 1436 |
+
}
|
| 1437 |
+
|
| 1438 |
+
// Save translations to cache
|
| 1439 |
+
saveTranslationsToCache(targetLanguage, translationsCache);
|
| 1440 |
+
|
| 1441 |
+
// Update cache status
|
| 1442 |
+
updateCacheStatus(targetLanguage);
|
| 1443 |
+
updateCacheStatusDisplay();
|
| 1444 |
+
|
| 1445 |
+
} catch (error) {
|
| 1446 |
+
console.error('Translation error:', error);
|
| 1447 |
+
showError('Translation failed: ' + error.message);
|
| 1448 |
+
} finally {
|
| 1449 |
+
hideTranslationOverlay();
|
| 1450 |
+
}
|
| 1451 |
+
}
|
| 1452 |
+
|
| 1453 |
+
// Show translation overlay
|
| 1454 |
+
function showTranslationOverlay() {
|
| 1455 |
+
document.getElementById('translationOverlay').style.display = 'flex';
|
| 1456 |
+
}
|
| 1457 |
+
|
| 1458 |
+
// Hide translation overlay
|
| 1459 |
+
function hideTranslationOverlay() {
|
| 1460 |
+
document.getElementById('translationOverlay').style.display = 'none';
|
| 1461 |
+
}
|
| 1462 |
+
|
| 1463 |
+
// Update translation progress
|
| 1464 |
+
function updateTranslationProgress(current, total) {
|
| 1465 |
+
const percentage = Math.round((current / total) * 100);
|
| 1466 |
+
document.getElementById('translationMessage').textContent =
|
| 1467 |
+
`Translating interface... ${percentage}% complete (will be cached for future use)`;
|
| 1468 |
+
}
|
| 1469 |
+
|
| 1470 |
+
// Apply language with API translation or cache
|
| 1471 |
+
async function applyLanguage(language) {
|
| 1472 |
+
applyDirection(language);
|
| 1473 |
+
|
| 1474 |
+
if (language !== 'en') {
|
| 1475 |
+
await translateInterface(language);
|
| 1476 |
+
}
|
| 1477 |
+
}
|
| 1478 |
+
|
| 1479 |
+
// Show language landing page
|
| 1480 |
+
function showLanguageLanding() {
|
| 1481 |
+
document.getElementById('languageLanding').style.display = 'block';
|
| 1482 |
+
document.getElementById('mainApp').style.display = 'none';
|
| 1483 |
+
}
|
| 1484 |
+
|
| 1485 |
+
// Show main application
|
| 1486 |
+
function showMainApp() {
|
| 1487 |
+
document.getElementById('languageLanding').style.display = 'none';
|
| 1488 |
+
document.getElementById('mainApp').style.display = 'block';
|
| 1489 |
+
|
| 1490 |
+
// Set API key in main app
|
| 1491 |
+
document.getElementById('apiKey').value = currentApiKey;
|
| 1492 |
+
}
|
| 1493 |
+
|
| 1494 |
+
// Start button click handler
|
| 1495 |
+
document.getElementById('startBtn').addEventListener('click', async function() {
|
| 1496 |
+
const selectedLanguage = document.getElementById('languageSelect').value;
|
| 1497 |
+
const apiKey = document.getElementById('apiKeyLanding').value.trim();
|
| 1498 |
+
|
| 1499 |
+
if (!apiKey) {
|
| 1500 |
+
alert('Please enter your OpenAI API key');
|
| 1501 |
+
return;
|
| 1502 |
+
}
|
| 1503 |
+
|
| 1504 |
+
currentLanguage = selectedLanguage;
|
| 1505 |
+
currentApiKey = apiKey;
|
| 1506 |
+
|
| 1507 |
+
// Save API key
|
| 1508 |
+
localStorage.setItem('empathy_insights_api_key', apiKey);
|
| 1509 |
+
|
| 1510 |
+
// Apply language with translation (cached or API)
|
| 1511 |
+
await applyLanguage(selectedLanguage);
|
| 1512 |
+
|
| 1513 |
+
// Show main app
|
| 1514 |
+
showMainApp();
|
| 1515 |
+
});
|
| 1516 |
+
|
| 1517 |
+
// Language selector change handler
|
| 1518 |
+
document.getElementById('languageSelect').addEventListener('change', async function() {
|
| 1519 |
+
const selectedLanguage = this.value;
|
| 1520 |
+
updateCacheStatus(selectedLanguage);
|
| 1521 |
+
|
| 1522 |
+
if (currentApiKey) {
|
| 1523 |
+
await applyLanguage(selectedLanguage);
|
| 1524 |
+
} else {
|
| 1525 |
+
applyDirection(selectedLanguage);
|
| 1526 |
+
}
|
| 1527 |
+
});
|
| 1528 |
+
|
| 1529 |
+
// Clear cache button handler
|
| 1530 |
+
document.getElementById('clearCacheBtn').addEventListener('click', clearAllTranslationCache);
|
| 1531 |
+
|
| 1532 |
+
// API key sync between landing and main app
|
| 1533 |
+
document.getElementById('apiKeyLanding').addEventListener('input', function() {
|
| 1534 |
+
currentApiKey = this.value;
|
| 1535 |
+
localStorage.setItem('empathy_insights_api_key', this.value);
|
| 1536 |
+
document.getElementById('apiKey').value = this.value;
|
| 1537 |
+
});
|
| 1538 |
+
|
| 1539 |
+
document.getElementById('apiKey').addEventListener('input', function() {
|
| 1540 |
+
currentApiKey = this.value;
|
| 1541 |
+
localStorage.setItem('empathy_insights_api_key', this.value);
|
| 1542 |
+
document.getElementById('apiKeyLanding').value = this.value;
|
| 1543 |
+
});
|
| 1544 |
+
|
| 1545 |
+
// Character counter
|
| 1546 |
+
const textInput = document.getElementById('textInput');
|
| 1547 |
+
const charCounter = document.getElementById('charCounter');
|
| 1548 |
+
|
| 1549 |
+
textInput.addEventListener('input', function() {
|
| 1550 |
+
const count = this.value.length;
|
| 1551 |
+
charCounter.textContent = `${count} characters`;
|
| 1552 |
+
|
| 1553 |
+
if (count > 5000) {
|
| 1554 |
+
charCounter.style.color = 'var(--color-warning)';
|
| 1555 |
+
} else {
|
| 1556 |
+
charCounter.style.color = 'var(--color-text-secondary)';
|
| 1557 |
+
}
|
| 1558 |
+
});
|
| 1559 |
+
|
| 1560 |
+
// Error handling
|
| 1561 |
+
function showError(message) {
|
| 1562 |
+
const errorDiv = document.getElementById('errorMessage');
|
| 1563 |
+
errorDiv.textContent = message;
|
| 1564 |
+
errorDiv.style.display = 'block';
|
| 1565 |
+
setTimeout(() => {
|
| 1566 |
+
errorDiv.style.display = 'none';
|
| 1567 |
+
}, 5000);
|
| 1568 |
+
}
|
| 1569 |
+
|
| 1570 |
+
// API call function - Updated to use current language
|
| 1571 |
+
async function callAPI(prompt) {
|
| 1572 |
+
const apiKey = document.getElementById('apiKey').value.trim();
|
| 1573 |
+
|
| 1574 |
+
if (!apiKey) {
|
| 1575 |
+
throw new Error('Please enter your OpenAI API key');
|
| 1576 |
+
}
|
| 1577 |
+
|
| 1578 |
+
const payload = {
|
| 1579 |
+
model: "gpt-4o-mini",
|
| 1580 |
+
messages: [{ role: "user", content: prompt }],
|
| 1581 |
+
max_tokens: 3500,
|
| 1582 |
+
temperature: 0.3
|
| 1583 |
+
};
|
| 1584 |
+
|
| 1585 |
+
const response = await fetch("https://api.openai.com/v1/chat/completions", {
|
| 1586 |
+
method: "POST",
|
| 1587 |
+
headers: {
|
| 1588 |
+
"Content-Type": "application/json",
|
| 1589 |
+
"Authorization": `Bearer ${apiKey}`
|
| 1590 |
+
},
|
| 1591 |
+
body: JSON.stringify(payload)
|
| 1592 |
+
});
|
| 1593 |
+
|
| 1594 |
+
if (!response.ok) {
|
| 1595 |
+
const errorData = await response.json();
|
| 1596 |
+
throw new Error(errorData.error?.message || "API request failed");
|
| 1597 |
+
}
|
| 1598 |
+
|
| 1599 |
+
const data = await response.json();
|
| 1600 |
+
return data.choices[0].message.content;
|
| 1601 |
+
}
|
| 1602 |
+
|
| 1603 |
+
// Build empathy map prompt - Updated to use current language dynamically
|
| 1604 |
+
function buildEmpathyMapPrompt() {
|
| 1605 |
+
const textInput = document.getElementById('textInput').value.trim();
|
| 1606 |
+
const languageName = languageNames[currentLanguage] || 'English';
|
| 1607 |
+
|
| 1608 |
+
return `Based on the following user research context and input:
|
| 1609 |
+
|
| 1610 |
+
---------------------
|
| 1611 |
+
${textInput}
|
| 1612 |
+
---------------------
|
| 1613 |
+
|
| 1614 |
+
Please generate a comprehensive, structured, and professionally formatted explanation of the Empathy Map Tool that directly reflects and addresses the specific context provided above. The output should be tailored to the user's scenario and formatted as clean HTML with inline CSS for professional presentation.
|
| 1615 |
+
|
| 1616 |
+
**Required Structure (in ${languageName}):**
|
| 1617 |
+
|
| 1618 |
+
1. **Concept & Overview**
|
| 1619 |
+
- Provide an in-depth description of the Empathy Map Tool
|
| 1620 |
+
- Explain its purpose, origins, and role in user experience design
|
| 1621 |
+
- Connect the explanation to the specific context provided in the input
|
| 1622 |
+
- Discuss its importance as a collaborative tool for gathering qualitative insights
|
| 1623 |
+
|
| 1624 |
+
2. **Contextual Application**
|
| 1625 |
+
- Explain how the empathy map applies to the specific scenario described in the input
|
| 1626 |
+
- Reference relevant aspects of the user research context
|
| 1627 |
+
- Provide personalized insights based on the target audience or product mentioned
|
| 1628 |
+
|
| 1629 |
+
3. **The Six Core Components (Detailed Analysis)**
|
| 1630 |
+
- **Says:** Direct quotes, statements, and verbal expressions
|
| 1631 |
+
- **Thinks:** Internal thoughts, beliefs, and mental models
|
| 1632 |
+
- **Does:** Observable actions, behaviors, and activities
|
| 1633 |
+
- **Feels:** Emotions, feelings, and emotional states
|
| 1634 |
+
- **Pain Points:** Frustrations, obstacles, and challenges
|
| 1635 |
+
- **Gains:** Goals, aspirations, and desired outcomes
|
| 1636 |
+
|
| 1637 |
+
For each component, provide:
|
| 1638 |
+
- Clear definition and purpose
|
| 1639 |
+
- Specific examples relevant to the user's context
|
| 1640 |
+
- Data collection strategies and techniques
|
| 1641 |
+
- Best practices for accurate representation
|
| 1642 |
+
|
| 1643 |
+
4. **Step-by-Step Process**
|
| 1644 |
+
- Detailed methodology for creating an empathy map
|
| 1645 |
+
- Data collection techniques (interviews, observations, surveys)
|
| 1646 |
+
- Workshop facilitation guidelines
|
| 1647 |
+
- Synthesis and analysis methods
|
| 1648 |
+
- Validation and iteration processes
|
| 1649 |
+
|
| 1650 |
+
5. **Benefits & Strategic Value**
|
| 1651 |
+
- Enhanced customer empathy and understanding
|
| 1652 |
+
- Improved product/service design decisions
|
| 1653 |
+
- Better team alignment and shared understanding
|
| 1654 |
+
- More effective user-centered design processes
|
| 1655 |
+
- Specific benefits for the context provided
|
| 1656 |
+
|
| 1657 |
+
6. **Implementation Best Practices**
|
| 1658 |
+
- Tips for successful empathy mapping sessions
|
| 1659 |
+
- Common pitfalls and how to avoid them
|
| 1660 |
+
- Integration with other UX research methods
|
| 1661 |
+
- Scaling empathy maps across organizations
|
| 1662 |
+
- Maintaining accuracy and avoiding assumptions
|
| 1663 |
+
|
| 1664 |
+
7. **Advanced Strategies & Insights**
|
| 1665 |
+
- Digital vs. physical empathy mapping approaches
|
| 1666 |
+
- Using empathy maps in different project phases
|
| 1667 |
+
- Combining with personas, journey maps, and other tools
|
| 1668 |
+
- Measuring the impact of empathy mapping
|
| 1669 |
+
- Continuous improvement and updates
|
| 1670 |
+
|
| 1671 |
+
**Formatting Requirements:**
|
| 1672 |
+
- Use clean HTML with inline CSS for professional presentation
|
| 1673 |
+
- Include proper headings (h3, h4) with attractive styling
|
| 1674 |
+
- Use bullet points and numbered lists for clarity
|
| 1675 |
+
- Apply consistent color scheme (blues/teals for empathy themes)
|
| 1676 |
+
- Ensure responsive design and readability
|
| 1677 |
+
- Make the content scannable with clear visual hierarchy
|
| 1678 |
+
|
| 1679 |
+
**Language:** Generate the entire response in ${languageName}.
|
| 1680 |
+
|
| 1681 |
+
**Tone:** Professional, educational, and directly relevant to the user's specific context. Focus on practical, actionable guidance that can be immediately applied to their empathy mapping needs.
|
| 1682 |
+
|
| 1683 |
+
Return only the complete HTML content with inline CSS - no additional text or explanations outside the HTML.`;
|
| 1684 |
+
}
|
| 1685 |
+
|
| 1686 |
+
// Validation function
|
| 1687 |
+
function validateInputs() {
|
| 1688 |
+
const textInput = document.getElementById('textInput').value.trim();
|
| 1689 |
+
|
| 1690 |
+
if (!textInput) {
|
| 1691 |
+
document.getElementById('textInput').focus();
|
| 1692 |
+
throw new Error('Please enter your user research context or scenario');
|
| 1693 |
+
}
|
| 1694 |
+
|
| 1695 |
+
if (textInput.length < 50) {
|
| 1696 |
+
document.getElementById('textInput').focus();
|
| 1697 |
+
throw new Error('Please provide at least 50 characters for meaningful analysis');
|
| 1698 |
+
}
|
| 1699 |
+
}
|
| 1700 |
+
|
| 1701 |
+
// Generate empathy map explanation
|
| 1702 |
+
document.getElementById('generateEmpathyBtn').addEventListener('click', async function() {
|
| 1703 |
+
const button = this;
|
| 1704 |
+
const buttonText = document.getElementById('buttonText');
|
| 1705 |
+
const spinner = document.getElementById('spinner');
|
| 1706 |
+
const outputArea = document.getElementById('apiOutput');
|
| 1707 |
+
|
| 1708 |
+
try {
|
| 1709 |
+
// Validate inputs
|
| 1710 |
+
validateInputs();
|
| 1711 |
+
|
| 1712 |
+
// Update button state
|
| 1713 |
+
button.disabled = true;
|
| 1714 |
+
spinner.style.display = 'inline-block';
|
| 1715 |
+
buttonText.textContent = 'Generating Guide...';
|
| 1716 |
+
|
| 1717 |
+
// Clear previous output
|
| 1718 |
+
outputArea.innerHTML = '';
|
| 1719 |
+
|
| 1720 |
+
// Build prompt and call API
|
| 1721 |
+
const prompt = buildEmpathyMapPrompt();
|
| 1722 |
+
const result = await callAPI(prompt);
|
| 1723 |
+
|
| 1724 |
+
// Display result
|
| 1725 |
+
outputArea.innerHTML = result;
|
| 1726 |
+
|
| 1727 |
+
} catch (error) {
|
| 1728 |
+
showError(error.message);
|
| 1729 |
+
outputArea.innerHTML = '';
|
| 1730 |
+
} finally {
|
| 1731 |
+
// Reset button state
|
| 1732 |
+
button.disabled = false;
|
| 1733 |
+
spinner.style.display = 'none';
|
| 1734 |
+
buttonText.textContent = '🧠 Generate Empathy Map Guide';
|
| 1735 |
+
}
|
| 1736 |
+
});
|
| 1737 |
+
|
| 1738 |
+
// Keyboard shortcut for generation
|
| 1739 |
+
document.addEventListener('keydown', function(e) {
|
| 1740 |
+
if (e.ctrlKey && e.key === 'Enter') {
|
| 1741 |
+
e.preventDefault();
|
| 1742 |
+
document.getElementById('generateEmpathyBtn').click();
|
| 1743 |
+
}
|
| 1744 |
+
});
|
| 1745 |
+
|
| 1746 |
+
// Initialize app when DOM is loaded
|
| 1747 |
+
document.addEventListener('DOMContentLoaded', function() {
|
| 1748 |
+
initializeApp();
|
| 1749 |
+
});
|
| 1750 |
+
</script>
|
| 1751 |
+
</body>
|
| 1752 |
+
</html>
|
| 1753 |
+
|
📘 Teacher & Student Guide EmpathyI.txt
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
📘 Teacher & Student Guide: EmpathyInsights Pro
|
| 2 |
+
1. Purpose & Classroom Impact
|
| 3 |
+
EmpathyInsights Pro enables teachers and students to create deep, structured empathy maps for any project, character study, social issue, or real-world case. This builds empathy, critical thinking, and perspective-taking—key skills for 21st-century learners across subjects.
|
| 4 |
+
|
| 5 |
+
2. How Teachers Can Use the Tool
|
| 6 |
+
A. Lesson Integration Ideas
|
| 7 |
+
Literature & Social Studies:
|
| 8 |
+
|
| 9 |
+
Analyze literary characters or historical figures using empathy maps.
|
| 10 |
+
|
| 11 |
+
Deepen discussions about motives, perspectives, and experiences.
|
| 12 |
+
|
| 13 |
+
SEL (Social-Emotional Learning):
|
| 14 |
+
|
| 15 |
+
Foster understanding of classmates’ feelings and points of view.
|
| 16 |
+
|
| 17 |
+
Explore empathy in conflict resolution or anti-bullying programs.
|
| 18 |
+
|
| 19 |
+
PBL/Inquiry Projects:
|
| 20 |
+
|
| 21 |
+
Map stakeholders in real-world problems (e.g., environmental, community, or civic issues).
|
| 22 |
+
|
| 23 |
+
Scaffold group work—students use empathy maps to assign roles or understand different interests.
|
| 24 |
+
|
| 25 |
+
Language Learning:
|
| 26 |
+
|
| 27 |
+
Practice cultural empathy by mapping experiences of people from different backgrounds.
|
| 28 |
+
|
| 29 |
+
B. Teaching Workflow
|
| 30 |
+
Introduce Empathy Mapping:
|
| 31 |
+
|
| 32 |
+
Explain the six core components: Says, Thinks, Does, Feels, Pain Points, Gains.
|
| 33 |
+
|
| 34 |
+
Discuss why understanding others’ experiences is essential.
|
| 35 |
+
|
| 36 |
+
Scenario/Character Selection:
|
| 37 |
+
|
| 38 |
+
Assign or let students choose a scenario, character, or real person to analyze.
|
| 39 |
+
|
| 40 |
+
Guide Input:
|
| 41 |
+
|
| 42 |
+
Support students in writing a specific, detailed context for the tool (minimum 50 characters).
|
| 43 |
+
|
| 44 |
+
Generate & Discuss:
|
| 45 |
+
|
| 46 |
+
Use EmpathyInsights Pro to generate a full empathy map guide.
|
| 47 |
+
|
| 48 |
+
Review each section together—highlighting nuanced findings.
|
| 49 |
+
|
| 50 |
+
Class Activities:
|
| 51 |
+
|
| 52 |
+
Group Work: Have groups use the guide to create posters, presentations, or skits.
|
| 53 |
+
|
| 54 |
+
Compare Perspectives: Different groups can map different stakeholders or characters and compare.
|
| 55 |
+
|
| 56 |
+
Reflection:
|
| 57 |
+
|
| 58 |
+
Ask students to reflect on how their understanding or feelings changed.
|
| 59 |
+
|
| 60 |
+
Use reflective journals or class discussions to deepen learning.
|
| 61 |
+
|
| 62 |
+
3. How Students Can Use the Tool
|
| 63 |
+
A. Independent & Group Projects
|
| 64 |
+
Literature Analysis:
|
| 65 |
+
|
| 66 |
+
Map a main character’s journey across a novel or play.
|
| 67 |
+
|
| 68 |
+
Current Events:
|
| 69 |
+
|
| 70 |
+
Analyze the perspectives of different groups in a news story.
|
| 71 |
+
|
| 72 |
+
Personal Growth:
|
| 73 |
+
|
| 74 |
+
Reflect on a time you experienced strong feelings; map your own empathy map.
|
| 75 |
+
|
| 76 |
+
STEAM/Design Thinking:
|
| 77 |
+
|
| 78 |
+
For innovation projects, map the “user” (real or imagined) to improve product design or solutions.
|
| 79 |
+
|
| 80 |
+
B. Step-by-Step Student Instructions
|
| 81 |
+
Access the Tool:
|
| 82 |
+
|
| 83 |
+
Open the HTML file or Hugging Face Space.
|
| 84 |
+
|
| 85 |
+
Select Language:
|
| 86 |
+
|
| 87 |
+
Choose your preferred language for both the UI and output.
|
| 88 |
+
|
| 89 |
+
Enter Scenario:
|
| 90 |
+
|
| 91 |
+
Type a detailed description of the person, group, or character you’re mapping.
|
| 92 |
+
|
| 93 |
+
Example: “A teenage refugee starting a new school in a different country.”
|
| 94 |
+
|
| 95 |
+
Generate Empathy Map:
|
| 96 |
+
|
| 97 |
+
Click “🧠 Generate Empathy Map Guide”.
|
| 98 |
+
|
| 99 |
+
Read & Apply:
|
| 100 |
+
|
| 101 |
+
Review each of the six sections.
|
| 102 |
+
|
| 103 |
+
Use them to write, present, or discuss your analysis.
|
| 104 |
+
|
| 105 |
+
Reflect:
|
| 106 |
+
|
| 107 |
+
What did you learn about perspective? What surprised you?
|
| 108 |
+
|
| 109 |
+
How does this help you understand or communicate better?
|
| 110 |
+
|
| 111 |
+
4. Sample Classroom Activities
|
| 112 |
+
Activity Type How to Use EmpathyInsights Pro
|
| 113 |
+
Literature Circles Each group maps a character’s feelings/thoughts/actions.
|
| 114 |
+
History Debates Map perspectives of different historical figures or nations.
|
| 115 |
+
SEL Check-ins Students map their own or peers’ experiences during an event.
|
| 116 |
+
Design Projects Teams map user needs for product or app development.
|
| 117 |
+
Group Reflection Compare maps—what patterns or surprises do you see?
|
| 118 |
+
|
| 119 |
+
5. Best Practices & Tips
|
| 120 |
+
Be specific: The richer your input, the more insightful the empathy map.
|
| 121 |
+
|
| 122 |
+
Encourage discussion: Use output as a springboard, not just a final answer.
|
| 123 |
+
|
| 124 |
+
Privacy-first: No student data leaves the browser—safe for all ages.
|
| 125 |
+
|
| 126 |
+
Use multilingual support: Great for ELLs or global classrooms.
|
| 127 |
+
|
| 128 |
+
6. Troubleshooting & Support
|
| 129 |
+
If the output is generic, revise your scenario for more detail.
|
| 130 |
+
|
| 131 |
+
Check API key if there’s an error or missing translation.
|
| 132 |
+
|
| 133 |
+
For technical help: info@shiftmind.io | www.shiftmind.io
|
| 134 |
+
|
| 135 |
+
EmpathyInsights Pro turns empathy from a buzzword into a practical, visible skill—empowering every classroom to build understanding and perspective, one map at a time.
|