Spaces:
Running
Running
Upload 4 files
Browse files- Apache License.txt +17 -0
- README.md +100 -0
- index.html +1854 -0
- 📘 Teacher & Student Guide ImpactAn.txt +73 -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,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: "🌱 ImpactAnalyzer Pro – Sustainability & Social Impact Assessment"
|
| 3 |
+
emoji: "🌱"
|
| 4 |
+
colorFrom: "green"
|
| 5 |
+
colorTo: "red"
|
| 6 |
+
sdk: "static"
|
| 7 |
+
sdk_version: "0.1.0"
|
| 8 |
+
app_file: "index.html"
|
| 9 |
+
pinned: false
|
| 10 |
+
---
|
| 11 |
+
|
| 12 |
+
# 🌱 ImpactAnalyzer Pro – Sustainability & Social Impact Assessment
|
| 13 |
+
**Developed by Shift Mind AI Labs**
|
| 14 |
+
|
| 15 |
+
ImpactAnalyzer Pro is an open-source, privacy-first platform that enables comprehensive, multilingual sustainability and social impact assessments for any idea, project, product, or initiative. The platform guides users through in-depth environmental, social, economic, ethical, lifecycle, and risk analyses—instantly and securely in 80+ languages.
|
| 16 |
+
|
| 17 |
+
---
|
| 18 |
+
|
| 19 |
+
## 🚀 Features
|
| 20 |
+
|
| 21 |
+
- **Comprehensive Impact Analysis:**
|
| 22 |
+
Generates full, structured reports covering environmental, social, economic, and ethical impacts.
|
| 23 |
+
- **Custom Project Input:**
|
| 24 |
+
Tailor the analysis to your specific idea or initiative—ideal for PBL, research, or innovation.
|
| 25 |
+
- **Modern, Multilingual UI:**
|
| 26 |
+
80+ language support (OpenAI API key required; all processing is in-browser).
|
| 27 |
+
- **Practical Recommendations:**
|
| 28 |
+
Actionable improvement plans, success metrics, and comparison with best practices.
|
| 29 |
+
- **Privacy-First:**
|
| 30 |
+
No login, no cloud storage—API key and content **never** leave your device.
|
| 31 |
+
|
| 32 |
+
---
|
| 33 |
+
|
| 34 |
+
## 🛠 How to Use
|
| 35 |
+
|
| 36 |
+
1. **Open the tool** (local HTML file or Hugging Face Space).
|
| 37 |
+
2. **Select your language** and enter your OpenAI API key.
|
| 38 |
+
3. **Describe your idea, project, or initiative** (see Guide below for tips).
|
| 39 |
+
4. **Click “🌱 Analyze Impact”**.
|
| 40 |
+
5. **Review, copy, and use** the generated full impact analysis report.
|
| 41 |
+
6. **Switch languages or clear cache** as needed for instant multilingual output.
|
| 42 |
+
|
| 43 |
+
---
|
| 44 |
+
|
| 45 |
+
## 👩🏫 For Teachers
|
| 46 |
+
|
| 47 |
+
- **Project-Based Learning (PBL):**
|
| 48 |
+
Guide students in analyzing the real-world impact of projects, products, or social initiatives.
|
| 49 |
+
- **STEM, Social Studies, Business, Civics:**
|
| 50 |
+
Deepen research assignments, innovation proposals, or policy critiques with comprehensive frameworks.
|
| 51 |
+
- **Assessment & Reflection:**
|
| 52 |
+
Use generated reports for formative/summative assessment, group work, or peer review.
|
| 53 |
+
- **Cross-Curricular Integration:**
|
| 54 |
+
Supports science, geography, business, ethics, and sustainability topics.
|
| 55 |
+
|
| 56 |
+
---
|
| 57 |
+
|
| 58 |
+
## 👨🎓 For Students
|
| 59 |
+
|
| 60 |
+
- **Research & Capstone Projects:**
|
| 61 |
+
Submit any idea or project for professional-level impact assessment.
|
| 62 |
+
- **Competition Prep:**
|
| 63 |
+
Prepare sustainability and social impact sections for hackathons or business competitions.
|
| 64 |
+
- **Skill Building:**
|
| 65 |
+
Develop systems thinking, critical analysis, and solution-focused research skills.
|
| 66 |
+
- **Global Learning:**
|
| 67 |
+
Instantly translate and share reports for international or ELL classrooms.
|
| 68 |
+
|
| 69 |
+
---
|
| 70 |
+
|
| 71 |
+
## 🔐 Data Privacy
|
| 72 |
+
|
| 73 |
+
- Your OpenAI API key and all project data **never leave your device**.
|
| 74 |
+
- No data is transmitted to Shift Mind AI Labs, Hugging Face, or any third party.
|
| 75 |
+
|
| 76 |
+
---
|
| 77 |
+
|
| 78 |
+
## 📄 License
|
| 79 |
+
|
| 80 |
+
Licensed under the [Apache License 2.0](./LICENSE).
|
| 81 |
+
|
| 82 |
+
---
|
| 83 |
+
|
| 84 |
+
## 🧠 About Shift Mind AI Labs
|
| 85 |
+
|
| 86 |
+
Shift Mind AI Labs develops open-source, ethical AI tools for education, innovation, and social good.
|
| 87 |
+
|
| 88 |
+
🌐 https://www.shiftmind.io
|
| 89 |
+
✉️ info@shiftmind.io
|
| 90 |
+
|
| 91 |
+
---
|
| 92 |
+
|
| 93 |
+
## 🙌 Contributing
|
| 94 |
+
|
| 95 |
+
Ideas, feedback, and collaboration welcome!
|
| 96 |
+
For pilots, research, or partnerships: **info@shiftmind.io**
|
| 97 |
+
|
| 98 |
+
---
|
| 99 |
+
|
| 100 |
+
*Empowering every classroom and innovator to measure, understand, and improve real-world impact—instantly, securely, in any language.*
|
index.html
ADDED
|
@@ -0,0 +1,1854 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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>ImpactAnalyzer Pro - Sustainability & Social Impact Assessment</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 - Sustainability/Impact theme */
|
| 22 |
+
--color-primary: #059669;
|
| 23 |
+
--color-primary-hover: #047857;
|
| 24 |
+
--color-secondary: #10b981;
|
| 25 |
+
--color-accent: #34d399;
|
| 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: #059669;
|
| 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: 1400px;
|
| 71 |
+
--content-max-width: 1200px;
|
| 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 |
+
/* Progress Bar */
|
| 126 |
+
.progress-bar {
|
| 127 |
+
position: fixed;
|
| 128 |
+
top: 0;
|
| 129 |
+
left: 0;
|
| 130 |
+
height: 4px;
|
| 131 |
+
background: var(--color-primary);
|
| 132 |
+
transition: width 0.3s ease;
|
| 133 |
+
z-index: 1000;
|
| 134 |
+
}
|
| 135 |
+
|
| 136 |
+
/* Language Selection Landing */
|
| 137 |
+
.language-landing {
|
| 138 |
+
display: block;
|
| 139 |
+
max-width: 600px;
|
| 140 |
+
margin: 50px auto;
|
| 141 |
+
background: var(--color-surface);
|
| 142 |
+
border-radius: var(--radius-xl);
|
| 143 |
+
box-shadow: var(--shadow-lg);
|
| 144 |
+
padding: 40px;
|
| 145 |
+
text-align: center;
|
| 146 |
+
}
|
| 147 |
+
|
| 148 |
+
.language-landing h1 {
|
| 149 |
+
font-size: 2.5rem;
|
| 150 |
+
font-weight: 800;
|
| 151 |
+
background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-secondary) 100%);
|
| 152 |
+
-webkit-background-clip: text;
|
| 153 |
+
-webkit-text-fill-color: transparent;
|
| 154 |
+
background-clip: text;
|
| 155 |
+
margin-bottom: 15px;
|
| 156 |
+
}
|
| 157 |
+
|
| 158 |
+
.language-landing p {
|
| 159 |
+
font-size: 1.1rem;
|
| 160 |
+
color: var(--color-text-secondary);
|
| 161 |
+
margin-bottom: 30px;
|
| 162 |
+
}
|
| 163 |
+
|
| 164 |
+
.language-selector {
|
| 165 |
+
margin-bottom: 25px;
|
| 166 |
+
}
|
| 167 |
+
|
| 168 |
+
.language-selector label {
|
| 169 |
+
display: block;
|
| 170 |
+
margin-bottom: 10px;
|
| 171 |
+
font-weight: 600;
|
| 172 |
+
color: var(--color-text-primary);
|
| 173 |
+
font-size: 1.1rem;
|
| 174 |
+
}
|
| 175 |
+
|
| 176 |
+
.language-selector select {
|
| 177 |
+
width: 100%;
|
| 178 |
+
padding: 15px 20px;
|
| 179 |
+
border: 2px solid var(--color-border);
|
| 180 |
+
border-radius: var(--radius-lg);
|
| 181 |
+
font-size: 1.1rem;
|
| 182 |
+
font-family: inherit;
|
| 183 |
+
background: var(--color-surface);
|
| 184 |
+
transition: all 0.2s ease;
|
| 185 |
+
margin-bottom: 20px;
|
| 186 |
+
}
|
| 187 |
+
|
| 188 |
+
.language-selector select:focus {
|
| 189 |
+
outline: none;
|
| 190 |
+
border-color: var(--color-border-focus);
|
| 191 |
+
box-shadow: 0 0 0 3px rgba(5, 150, 105, 0.1);
|
| 192 |
+
}
|
| 193 |
+
|
| 194 |
+
.api-key-landing {
|
| 195 |
+
margin-bottom: 25px;
|
| 196 |
+
}
|
| 197 |
+
|
| 198 |
+
.api-key-landing label {
|
| 199 |
+
display: block;
|
| 200 |
+
margin-bottom: 10px;
|
| 201 |
+
font-weight: 600;
|
| 202 |
+
color: var(--color-text-primary);
|
| 203 |
+
font-size: 1.1rem;
|
| 204 |
+
}
|
| 205 |
+
|
| 206 |
+
.api-key-landing input {
|
| 207 |
+
width: 100%;
|
| 208 |
+
padding: 15px 20px;
|
| 209 |
+
border: 2px solid var(--color-border);
|
| 210 |
+
border-radius: var(--radius-lg);
|
| 211 |
+
font-size: 1.1rem;
|
| 212 |
+
background: var(--color-surface);
|
| 213 |
+
transition: all 0.2s ease;
|
| 214 |
+
font-family: 'Courier New', monospace;
|
| 215 |
+
}
|
| 216 |
+
|
| 217 |
+
.api-key-landing input:focus {
|
| 218 |
+
outline: none;
|
| 219 |
+
border-color: var(--color-border-focus);
|
| 220 |
+
box-shadow: 0 0 0 3px rgba(5, 150, 105, 0.1);
|
| 221 |
+
}
|
| 222 |
+
|
| 223 |
+
.start-btn {
|
| 224 |
+
background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-secondary) 100%);
|
| 225 |
+
color: white;
|
| 226 |
+
padding: 18px 40px;
|
| 227 |
+
border: none;
|
| 228 |
+
border-radius: var(--radius-lg);
|
| 229 |
+
font-size: 1.2rem;
|
| 230 |
+
font-weight: 700;
|
| 231 |
+
cursor: pointer;
|
| 232 |
+
transition: all 0.3s ease;
|
| 233 |
+
width: 100%;
|
| 234 |
+
}
|
| 235 |
+
|
| 236 |
+
.start-btn:hover {
|
| 237 |
+
transform: translateY(-2px);
|
| 238 |
+
box-shadow: 0 12px 24px -8px rgba(5, 150, 105, 0.4);
|
| 239 |
+
}
|
| 240 |
+
|
| 241 |
+
.start-btn:disabled {
|
| 242 |
+
opacity: 0.7;
|
| 243 |
+
cursor: not-allowed;
|
| 244 |
+
transform: none;
|
| 245 |
+
}
|
| 246 |
+
|
| 247 |
+
/* Cache Management Section */
|
| 248 |
+
.cache-management {
|
| 249 |
+
background: rgba(5, 150, 105, 0.05);
|
| 250 |
+
border: 1px solid rgba(5, 150, 105, 0.1);
|
| 251 |
+
border-radius: var(--radius-lg);
|
| 252 |
+
padding: 20px;
|
| 253 |
+
margin-bottom: 25px;
|
| 254 |
+
text-align: center;
|
| 255 |
+
}
|
| 256 |
+
|
| 257 |
+
.cache-management h3 {
|
| 258 |
+
color: var(--color-primary);
|
| 259 |
+
margin-bottom: 15px;
|
| 260 |
+
font-size: 1.1rem;
|
| 261 |
+
font-weight: 600;
|
| 262 |
+
}
|
| 263 |
+
|
| 264 |
+
.cache-status-display {
|
| 265 |
+
background: rgba(16, 185, 129, 0.1);
|
| 266 |
+
border: 1px solid rgba(16, 185, 129, 0.2);
|
| 267 |
+
color: var(--color-success);
|
| 268 |
+
padding: 12px 16px;
|
| 269 |
+
border-radius: var(--radius-md);
|
| 270 |
+
margin-bottom: 15px;
|
| 271 |
+
font-size: 0.9rem;
|
| 272 |
+
font-weight: 500;
|
| 273 |
+
}
|
| 274 |
+
|
| 275 |
+
.cache-status-display.no-cache {
|
| 276 |
+
background: rgba(100, 116, 139, 0.1);
|
| 277 |
+
border-color: rgba(100, 116, 139, 0.2);
|
| 278 |
+
color: var(--color-text-secondary);
|
| 279 |
+
}
|
| 280 |
+
|
| 281 |
+
.clear-cache-btn {
|
| 282 |
+
background: linear-gradient(135deg, var(--color-warning) 0%, #f59e0b 100%);
|
| 283 |
+
color: white;
|
| 284 |
+
padding: 12px 24px;
|
| 285 |
+
border: none;
|
| 286 |
+
border-radius: var(--radius-md);
|
| 287 |
+
font-size: 0.9rem;
|
| 288 |
+
font-weight: 600;
|
| 289 |
+
cursor: pointer;
|
| 290 |
+
transition: all 0.3s ease;
|
| 291 |
+
}
|
| 292 |
+
|
| 293 |
+
.clear-cache-btn:hover {
|
| 294 |
+
transform: translateY(-1px);
|
| 295 |
+
box-shadow: 0 6px 12px -4px rgba(245, 158, 11, 0.4);
|
| 296 |
+
}
|
| 297 |
+
|
| 298 |
+
.clear-cache-btn:disabled {
|
| 299 |
+
opacity: 0.5;
|
| 300 |
+
cursor: not-allowed;
|
| 301 |
+
transform: none;
|
| 302 |
+
}
|
| 303 |
+
|
| 304 |
+
/* Cache Status Indicator */
|
| 305 |
+
.cache-status {
|
| 306 |
+
background: rgba(16, 185, 129, 0.1);
|
| 307 |
+
border: 1px solid rgba(16, 185, 129, 0.2);
|
| 308 |
+
color: var(--color-success);
|
| 309 |
+
padding: 8px 12px;
|
| 310 |
+
border-radius: var(--radius-sm);
|
| 311 |
+
margin-bottom: 15px;
|
| 312 |
+
font-size: 0.85rem;
|
| 313 |
+
text-align: center;
|
| 314 |
+
font-weight: 500;
|
| 315 |
+
display: none;
|
| 316 |
+
}
|
| 317 |
+
|
| 318 |
+
.cache-status.cached {
|
| 319 |
+
display: block;
|
| 320 |
+
}
|
| 321 |
+
|
| 322 |
+
.cache-status.translating {
|
| 323 |
+
background: rgba(5, 150, 105, 0.1);
|
| 324 |
+
border-color: rgba(5, 150, 105, 0.2);
|
| 325 |
+
color: var(--color-primary);
|
| 326 |
+
}
|
| 327 |
+
|
| 328 |
+
/* Translation Loading Overlay */
|
| 329 |
+
.translation-overlay {
|
| 330 |
+
position: fixed;
|
| 331 |
+
top: 0;
|
| 332 |
+
left: 0;
|
| 333 |
+
width: 100%;
|
| 334 |
+
height: 100%;
|
| 335 |
+
background: rgba(5, 150, 105, 0.9);
|
| 336 |
+
display: none;
|
| 337 |
+
justify-content: center;
|
| 338 |
+
align-items: center;
|
| 339 |
+
z-index: 10000;
|
| 340 |
+
color: white;
|
| 341 |
+
text-align: center;
|
| 342 |
+
}
|
| 343 |
+
|
| 344 |
+
.translation-content {
|
| 345 |
+
background: rgba(255, 255, 255, 0.1);
|
| 346 |
+
padding: 40px;
|
| 347 |
+
border-radius: var(--radius-xl);
|
| 348 |
+
backdrop-filter: blur(10px);
|
| 349 |
+
}
|
| 350 |
+
|
| 351 |
+
.translation-spinner {
|
| 352 |
+
width: 50px;
|
| 353 |
+
height: 50px;
|
| 354 |
+
border: 4px solid rgba(255, 255, 255, 0.3);
|
| 355 |
+
border-radius: 50%;
|
| 356 |
+
border-top-color: white;
|
| 357 |
+
animation: spin 1s ease-in-out infinite;
|
| 358 |
+
margin: 0 auto 20px;
|
| 359 |
+
}
|
| 360 |
+
|
| 361 |
+
/* Main Application (Hidden Initially) */
|
| 362 |
+
.main-app {
|
| 363 |
+
display: none;
|
| 364 |
+
}
|
| 365 |
+
|
| 366 |
+
/* Layout Components */
|
| 367 |
+
.app-container {
|
| 368 |
+
max-width: var(--container-max-width);
|
| 369 |
+
margin: 0 auto;
|
| 370 |
+
background: var(--color-surface);
|
| 371 |
+
border-radius: 16px;
|
| 372 |
+
box-shadow: var(--shadow-lg);
|
| 373 |
+
overflow: hidden;
|
| 374 |
+
position: relative;
|
| 375 |
+
}
|
| 376 |
+
|
| 377 |
+
/* Language Switcher in Main App */
|
| 378 |
+
.language-switcher {
|
| 379 |
+
position: absolute;
|
| 380 |
+
top: var(--spacing-lg);
|
| 381 |
+
right: var(--spacing-lg);
|
| 382 |
+
display: flex;
|
| 383 |
+
gap: 10px;
|
| 384 |
+
align-items: center;
|
| 385 |
+
z-index: 10;
|
| 386 |
+
}
|
| 387 |
+
|
| 388 |
+
.language-switch-btn {
|
| 389 |
+
background: rgba(5, 150, 105, 0.05);
|
| 390 |
+
border: 1px solid rgba(5, 150, 105, 0.1);
|
| 391 |
+
border-radius: var(--radius-md);
|
| 392 |
+
padding: 8px 12px;
|
| 393 |
+
font-size: 12px;
|
| 394 |
+
cursor: pointer;
|
| 395 |
+
transition: all 0.2s ease;
|
| 396 |
+
color: var(--color-primary);
|
| 397 |
+
font-weight: 500;
|
| 398 |
+
}
|
| 399 |
+
|
| 400 |
+
.language-switch-btn:hover {
|
| 401 |
+
background: rgba(5, 150, 105, 0.1);
|
| 402 |
+
}
|
| 403 |
+
|
| 404 |
+
.mini-clear-cache {
|
| 405 |
+
background: rgba(245, 158, 11, 0.1);
|
| 406 |
+
border: 1px solid rgba(245, 158, 11, 0.2);
|
| 407 |
+
color: var(--color-warning);
|
| 408 |
+
padding: 6px 10px;
|
| 409 |
+
border-radius: var(--radius-sm);
|
| 410 |
+
font-size: 11px;
|
| 411 |
+
cursor: pointer;
|
| 412 |
+
transition: all 0.2s ease;
|
| 413 |
+
font-weight: 500;
|
| 414 |
+
}
|
| 415 |
+
|
| 416 |
+
.mini-clear-cache:hover {
|
| 417 |
+
background: rgba(245, 158, 11, 0.2);
|
| 418 |
+
}
|
| 419 |
+
|
| 420 |
+
/* Compact API Key in Top-Left */
|
| 421 |
+
.api-key-compact {
|
| 422 |
+
position: absolute;
|
| 423 |
+
top: var(--spacing-lg);
|
| 424 |
+
left: var(--spacing-lg);
|
| 425 |
+
z-index: 10;
|
| 426 |
+
background: rgba(5, 150, 105, 0.05);
|
| 427 |
+
border: 1px solid rgba(5, 150, 105, 0.1);
|
| 428 |
+
border-radius: var(--radius-lg);
|
| 429 |
+
padding: var(--spacing-md) var(--spacing-lg);
|
| 430 |
+
transition: all var(--transition-normal);
|
| 431 |
+
max-width: 280px;
|
| 432 |
+
}
|
| 433 |
+
|
| 434 |
+
.api-key-compact:hover {
|
| 435 |
+
background: rgba(5, 150, 105, 0.08);
|
| 436 |
+
}
|
| 437 |
+
|
| 438 |
+
.api-key-compact-label {
|
| 439 |
+
display: block;
|
| 440 |
+
font-size: 0.75rem;
|
| 441 |
+
font-weight: 600;
|
| 442 |
+
color: var(--color-primary);
|
| 443 |
+
margin-bottom: var(--spacing-xs);
|
| 444 |
+
text-transform: uppercase;
|
| 445 |
+
letter-spacing: 0.05em;
|
| 446 |
+
}
|
| 447 |
+
|
| 448 |
+
.api-key-compact-input {
|
| 449 |
+
width: 100%;
|
| 450 |
+
padding: var(--spacing-sm) var(--spacing-md);
|
| 451 |
+
border: 1px solid var(--color-border);
|
| 452 |
+
border-radius: var(--radius-sm);
|
| 453 |
+
font-size: 0.875rem;
|
| 454 |
+
background: var(--color-surface);
|
| 455 |
+
color: var(--color-text-primary);
|
| 456 |
+
transition: all var(--transition-fast);
|
| 457 |
+
font-family: 'Courier New', monospace;
|
| 458 |
+
}
|
| 459 |
+
|
| 460 |
+
.api-key-compact-input:focus {
|
| 461 |
+
outline: none;
|
| 462 |
+
border-color: var(--color-border-focus);
|
| 463 |
+
box-shadow: 0 0 0 2px rgb(5 150 105 / 0.1);
|
| 464 |
+
}
|
| 465 |
+
|
| 466 |
+
.api-key-compact-input::placeholder {
|
| 467 |
+
color: var(--color-text-muted);
|
| 468 |
+
font-size: 0.75rem;
|
| 469 |
+
}
|
| 470 |
+
|
| 471 |
+
/* Main Content */
|
| 472 |
+
.main-content {
|
| 473 |
+
padding: 20px 30px 30px;
|
| 474 |
+
}
|
| 475 |
+
|
| 476 |
+
/* Header */
|
| 477 |
+
.header {
|
| 478 |
+
text-align: center;
|
| 479 |
+
margin-bottom: 25px;
|
| 480 |
+
padding-bottom: 20px;
|
| 481 |
+
border-bottom: 2px solid var(--color-border);
|
| 482 |
+
}
|
| 483 |
+
|
| 484 |
+
.header h1 {
|
| 485 |
+
font-size: 2.5rem;
|
| 486 |
+
font-weight: 800;
|
| 487 |
+
background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-secondary) 100%);
|
| 488 |
+
-webkit-background-clip: text;
|
| 489 |
+
-webkit-text-fill-color: transparent;
|
| 490 |
+
background-clip: text;
|
| 491 |
+
margin-bottom: 8px;
|
| 492 |
+
}
|
| 493 |
+
|
| 494 |
+
.header .subtitle {
|
| 495 |
+
font-size: 1.1rem;
|
| 496 |
+
color: var(--color-text-secondary);
|
| 497 |
+
font-weight: 500;
|
| 498 |
+
}
|
| 499 |
+
|
| 500 |
+
.header .description {
|
| 501 |
+
font-size: 1rem;
|
| 502 |
+
color: var(--color-text-secondary);
|
| 503 |
+
margin-top: 12px;
|
| 504 |
+
max-width: 700px;
|
| 505 |
+
margin-left: auto;
|
| 506 |
+
margin-right: auto;
|
| 507 |
+
}
|
| 508 |
+
|
| 509 |
+
/* Impact Categories */
|
| 510 |
+
.impact-categories {
|
| 511 |
+
display: grid;
|
| 512 |
+
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
| 513 |
+
gap: 15px;
|
| 514 |
+
margin-bottom: 25px;
|
| 515 |
+
}
|
| 516 |
+
|
| 517 |
+
.category-card {
|
| 518 |
+
background: rgba(5, 150, 105, 0.05);
|
| 519 |
+
border: 1px solid rgba(5, 150, 105, 0.1);
|
| 520 |
+
border-radius: 8px;
|
| 521 |
+
padding: 15px;
|
| 522 |
+
text-align: center;
|
| 523 |
+
}
|
| 524 |
+
|
| 525 |
+
.category-card h4 {
|
| 526 |
+
color: var(--color-primary);
|
| 527 |
+
font-size: 0.9rem;
|
| 528 |
+
font-weight: 600;
|
| 529 |
+
margin-bottom: 6px;
|
| 530 |
+
}
|
| 531 |
+
|
| 532 |
+
.category-card p {
|
| 533 |
+
font-size: 0.8rem;
|
| 534 |
+
color: var(--color-text-secondary);
|
| 535 |
+
}
|
| 536 |
+
|
| 537 |
+
/* Input Section */
|
| 538 |
+
.input-section {
|
| 539 |
+
background: var(--color-surface);
|
| 540 |
+
border: 1px solid var(--color-border);
|
| 541 |
+
border-radius: 12px;
|
| 542 |
+
padding: 20px;
|
| 543 |
+
margin-bottom: 25px;
|
| 544 |
+
transition: all 0.3s ease;
|
| 545 |
+
box-shadow: var(--shadow-sm);
|
| 546 |
+
}
|
| 547 |
+
|
| 548 |
+
.input-section:hover {
|
| 549 |
+
border-color: var(--color-primary);
|
| 550 |
+
box-shadow: 0 8px 25px -8px rgba(5, 150, 105, 0.3);
|
| 551 |
+
}
|
| 552 |
+
|
| 553 |
+
.input-section h3 {
|
| 554 |
+
font-size: 1.1rem;
|
| 555 |
+
font-weight: 700;
|
| 556 |
+
color: var(--color-primary);
|
| 557 |
+
margin-bottom: 8px;
|
| 558 |
+
display: flex;
|
| 559 |
+
align-items: center;
|
| 560 |
+
gap: 8px;
|
| 561 |
+
}
|
| 562 |
+
|
| 563 |
+
.input-section .description {
|
| 564 |
+
font-size: 0.9rem;
|
| 565 |
+
color: var(--color-text-secondary);
|
| 566 |
+
margin-bottom: 12px;
|
| 567 |
+
}
|
| 568 |
+
|
| 569 |
+
/* Form Elements */
|
| 570 |
+
label {
|
| 571 |
+
display: block;
|
| 572 |
+
margin-bottom: 6px;
|
| 573 |
+
font-weight: 600;
|
| 574 |
+
color: var(--color-text-primary);
|
| 575 |
+
font-size: 0.95rem;
|
| 576 |
+
}
|
| 577 |
+
|
| 578 |
+
textarea {
|
| 579 |
+
width: 100%;
|
| 580 |
+
padding: 12px 16px;
|
| 581 |
+
border: 2px solid var(--color-border);
|
| 582 |
+
border-radius: 8px;
|
| 583 |
+
font-size: 1rem;
|
| 584 |
+
font-family: inherit;
|
| 585 |
+
background: var(--color-surface);
|
| 586 |
+
transition: all 0.2s ease;
|
| 587 |
+
resize: vertical;
|
| 588 |
+
min-height: 150px;
|
| 589 |
+
}
|
| 590 |
+
|
| 591 |
+
textarea:focus {
|
| 592 |
+
outline: none;
|
| 593 |
+
border-color: var(--color-primary);
|
| 594 |
+
box-shadow: 0 0 0 3px rgba(5, 150, 105, 0.1);
|
| 595 |
+
}
|
| 596 |
+
|
| 597 |
+
/* Character Counter */
|
| 598 |
+
.char-counter {
|
| 599 |
+
font-size: 0.8rem;
|
| 600 |
+
color: var(--color-text-secondary);
|
| 601 |
+
text-align: right;
|
| 602 |
+
margin-top: 4px;
|
| 603 |
+
}
|
| 604 |
+
|
| 605 |
+
/* Generate Button */
|
| 606 |
+
.generate-btn {
|
| 607 |
+
background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-secondary) 100%);
|
| 608 |
+
color: white;
|
| 609 |
+
padding: 16px 32px;
|
| 610 |
+
border: none;
|
| 611 |
+
border-radius: 12px;
|
| 612 |
+
font-size: 1.1rem;
|
| 613 |
+
font-weight: 700;
|
| 614 |
+
cursor: pointer;
|
| 615 |
+
transition: all 0.3s ease;
|
| 616 |
+
display: block;
|
| 617 |
+
margin: 25px auto;
|
| 618 |
+
min-width: 280px;
|
| 619 |
+
position: relative;
|
| 620 |
+
overflow: hidden;
|
| 621 |
+
}
|
| 622 |
+
|
| 623 |
+
.generate-btn:hover {
|
| 624 |
+
transform: translateY(-2px);
|
| 625 |
+
box-shadow: 0 12px 24px -8px rgba(5, 150, 105, 0.4);
|
| 626 |
+
}
|
| 627 |
+
|
| 628 |
+
.generate-btn:active {
|
| 629 |
+
transform: translateY(0);
|
| 630 |
+
}
|
| 631 |
+
|
| 632 |
+
.generate-btn:disabled {
|
| 633 |
+
opacity: 0.7;
|
| 634 |
+
cursor: not-allowed;
|
| 635 |
+
transform: none;
|
| 636 |
+
}
|
| 637 |
+
|
| 638 |
+
/* Loading Spinner */
|
| 639 |
+
.spinner {
|
| 640 |
+
display: none;
|
| 641 |
+
width: 20px;
|
| 642 |
+
height: 20px;
|
| 643 |
+
border: 2px solid rgba(255, 255, 255, 0.3);
|
| 644 |
+
border-radius: 50%;
|
| 645 |
+
border-top-color: white;
|
| 646 |
+
animation: spin 1s ease-in-out infinite;
|
| 647 |
+
margin-right: 8px;
|
| 648 |
+
}
|
| 649 |
+
|
| 650 |
+
@keyframes spin {
|
| 651 |
+
to { transform: rotate(360deg); }
|
| 652 |
+
}
|
| 653 |
+
|
| 654 |
+
/* Output Section */
|
| 655 |
+
.output-section {
|
| 656 |
+
margin-top: 30px;
|
| 657 |
+
}
|
| 658 |
+
|
| 659 |
+
.output-section h2 {
|
| 660 |
+
font-size: 1.5rem;
|
| 661 |
+
font-weight: 700;
|
| 662 |
+
color: var(--color-primary);
|
| 663 |
+
margin-bottom: 15px;
|
| 664 |
+
display: flex;
|
| 665 |
+
align-items: center;
|
| 666 |
+
gap: 8px;
|
| 667 |
+
}
|
| 668 |
+
|
| 669 |
+
.output-area {
|
| 670 |
+
background: var(--color-surface);
|
| 671 |
+
border: 2px solid var(--color-border);
|
| 672 |
+
border-radius: 12px;
|
| 673 |
+
padding: 20px;
|
| 674 |
+
min-height: 300px;
|
| 675 |
+
transition: all 0.3s ease;
|
| 676 |
+
position: relative;
|
| 677 |
+
overflow-x: auto;
|
| 678 |
+
white-space: pre-wrap;
|
| 679 |
+
word-wrap: break-word;
|
| 680 |
+
line-height: 1.7;
|
| 681 |
+
}
|
| 682 |
+
|
| 683 |
+
.output-area:empty::before {
|
| 684 |
+
content: "Your comprehensive impact analysis will appear here...";
|
| 685 |
+
color: var(--color-text-secondary);
|
| 686 |
+
font-style: italic;
|
| 687 |
+
white-space: normal;
|
| 688 |
+
}
|
| 689 |
+
|
| 690 |
+
/* Enhanced output styling */
|
| 691 |
+
.output-area h3 {
|
| 692 |
+
color: var(--color-primary);
|
| 693 |
+
border-bottom: 2px solid var(--color-primary);
|
| 694 |
+
padding-bottom: 8px;
|
| 695 |
+
margin: 20px 0 15px 0;
|
| 696 |
+
font-size: 1.2rem;
|
| 697 |
+
}
|
| 698 |
+
|
| 699 |
+
.output-area h4 {
|
| 700 |
+
color: var(--color-secondary);
|
| 701 |
+
margin: 15px 0 10px 0;
|
| 702 |
+
font-size: 1.1rem;
|
| 703 |
+
}
|
| 704 |
+
|
| 705 |
+
.output-area ul {
|
| 706 |
+
margin: 10px 0 15px 20px;
|
| 707 |
+
line-height: 1.7;
|
| 708 |
+
}
|
| 709 |
+
|
| 710 |
+
.output-area li {
|
| 711 |
+
margin-bottom: 5px;
|
| 712 |
+
}
|
| 713 |
+
|
| 714 |
+
.output-area p {
|
| 715 |
+
margin: 12px 0;
|
| 716 |
+
line-height: 1.7;
|
| 717 |
+
}
|
| 718 |
+
|
| 719 |
+
.output-area strong {
|
| 720 |
+
color: var(--color-primary);
|
| 721 |
+
}
|
| 722 |
+
|
| 723 |
+
/* Error Messages */
|
| 724 |
+
.error-message {
|
| 725 |
+
background: rgba(239, 68, 68, 0.1);
|
| 726 |
+
border: 1px solid rgba(239, 68, 68, 0.2);
|
| 727 |
+
color: var(--color-error);
|
| 728 |
+
padding: 12px 16px;
|
| 729 |
+
border-radius: 8px;
|
| 730 |
+
margin: 10px 0;
|
| 731 |
+
font-size: 0.9rem;
|
| 732 |
+
display: none;
|
| 733 |
+
}
|
| 734 |
+
|
| 735 |
+
/* Footer */
|
| 736 |
+
.footer {
|
| 737 |
+
text-align: center;
|
| 738 |
+
padding: 20px;
|
| 739 |
+
background: rgba(5, 150, 105, 0.05);
|
| 740 |
+
border-top: 1px solid var(--color-border);
|
| 741 |
+
color: var(--color-text-secondary);
|
| 742 |
+
font-size: 0.9rem;
|
| 743 |
+
}
|
| 744 |
+
|
| 745 |
+
/* Hidden sections */
|
| 746 |
+
.hidden {
|
| 747 |
+
display: none !important;
|
| 748 |
+
}
|
| 749 |
+
|
| 750 |
+
/* Responsive Design */
|
| 751 |
+
@media (max-width: 768px) {
|
| 752 |
+
body {
|
| 753 |
+
padding: 10px;
|
| 754 |
+
}
|
| 755 |
+
|
| 756 |
+
.language-landing {
|
| 757 |
+
margin: 20px auto;
|
| 758 |
+
padding: 30px 20px;
|
| 759 |
+
}
|
| 760 |
+
|
| 761 |
+
.api-key-compact {
|
| 762 |
+
position: static;
|
| 763 |
+
margin-bottom: var(--spacing-xl);
|
| 764 |
+
max-width: none;
|
| 765 |
+
}
|
| 766 |
+
|
| 767 |
+
.language-switcher {
|
| 768 |
+
position: relative;
|
| 769 |
+
top: auto;
|
| 770 |
+
right: auto;
|
| 771 |
+
margin-bottom: var(--spacing-xl);
|
| 772 |
+
justify-content: center;
|
| 773 |
+
}
|
| 774 |
+
|
| 775 |
+
.main-content {
|
| 776 |
+
padding: 15px 20px 20px;
|
| 777 |
+
}
|
| 778 |
+
|
| 779 |
+
.header h1 {
|
| 780 |
+
font-size: 2rem;
|
| 781 |
+
}
|
| 782 |
+
|
| 783 |
+
.input-section {
|
| 784 |
+
padding: 15px;
|
| 785 |
+
}
|
| 786 |
+
|
| 787 |
+
.impact-categories {
|
| 788 |
+
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
| 789 |
+
}
|
| 790 |
+
|
| 791 |
+
.generate-btn {
|
| 792 |
+
width: 100%;
|
| 793 |
+
margin: 20px 0;
|
| 794 |
+
}
|
| 795 |
+
|
| 796 |
+
.output-area {
|
| 797 |
+
padding: 15px;
|
| 798 |
+
}
|
| 799 |
+
}
|
| 800 |
+
|
| 801 |
+
@media (max-width: 480px) {
|
| 802 |
+
.language-landing h1 {
|
| 803 |
+
font-size: 2rem;
|
| 804 |
+
}
|
| 805 |
+
|
| 806 |
+
.header h1 {
|
| 807 |
+
font-size: 1.8rem;
|
| 808 |
+
}
|
| 809 |
+
|
| 810 |
+
.input-section {
|
| 811 |
+
padding: 12px;
|
| 812 |
+
}
|
| 813 |
+
|
| 814 |
+
.impact-categories {
|
| 815 |
+
grid-template-columns: 1fr 1fr;
|
| 816 |
+
}
|
| 817 |
+
}
|
| 818 |
+
|
| 819 |
+
/* Accessibility */
|
| 820 |
+
.sr-only {
|
| 821 |
+
position: absolute;
|
| 822 |
+
width: 1px;
|
| 823 |
+
height: 1px;
|
| 824 |
+
padding: 0;
|
| 825 |
+
margin: -1px;
|
| 826 |
+
overflow: hidden;
|
| 827 |
+
clip: rect(0, 0, 0, 0);
|
| 828 |
+
white-space: nowrap;
|
| 829 |
+
border: 0;
|
| 830 |
+
}
|
| 831 |
+
|
| 832 |
+
/* Focus styles for keyboard navigation */
|
| 833 |
+
.generate-btn:focus,
|
| 834 |
+
.api-key-compact-input:focus,
|
| 835 |
+
textarea:focus {
|
| 836 |
+
outline: 2px solid var(--color-primary);
|
| 837 |
+
outline-offset: 2px;
|
| 838 |
+
}
|
| 839 |
+
|
| 840 |
+
/* Reduced motion support */
|
| 841 |
+
@media (prefers-reduced-motion: reduce) {
|
| 842 |
+
*,
|
| 843 |
+
*::before,
|
| 844 |
+
*::after {
|
| 845 |
+
animation-duration: 0.01ms !important;
|
| 846 |
+
animation-iteration-count: 1 !important;
|
| 847 |
+
transition-duration: 0.01ms !important;
|
| 848 |
+
scroll-behavior: auto !important;
|
| 849 |
+
}
|
| 850 |
+
}
|
| 851 |
+
</style>
|
| 852 |
+
</head>
|
| 853 |
+
|
| 854 |
+
<body>
|
| 855 |
+
<!-- Progress Bar -->
|
| 856 |
+
<div class="progress-bar" id="progressBar"></div>
|
| 857 |
+
|
| 858 |
+
<!-- Translation Loading Overlay -->
|
| 859 |
+
<div class="translation-overlay" id="translationOverlay">
|
| 860 |
+
<div class="translation-content">
|
| 861 |
+
<div class="translation-spinner"></div>
|
| 862 |
+
<h2 id="translationTitle">Translating Interface...</h2>
|
| 863 |
+
<p id="translationMessage">Please wait while we translate the interface to your selected language.</p>
|
| 864 |
+
</div>
|
| 865 |
+
</div>
|
| 866 |
+
|
| 867 |
+
<!-- Language Selection Landing Page -->
|
| 868 |
+
<div class="language-landing" id="languageLanding">
|
| 869 |
+
<h1 data-translate="app_title">ImpactAnalyzer Pro</h1>
|
| 870 |
+
<p data-translate="welcome_message">Welcome! Please select your preferred language and enter your API key to get started with comprehensive sustainability and social impact assessment.</p>
|
| 871 |
+
|
| 872 |
+
<!-- Cache Status Indicator -->
|
| 873 |
+
<div class="cache-status" id="cacheStatus">
|
| 874 |
+
💾 Translations cached - instant loading!
|
| 875 |
+
</div>
|
| 876 |
+
|
| 877 |
+
<!-- Cache Management Section -->
|
| 878 |
+
<div class="cache-management" id="cacheManagement">
|
| 879 |
+
<h3 data-translate="cache_management_title">🗂️ Translation Cache Management</h3>
|
| 880 |
+
<div class="cache-status-display" id="cacheStatusDisplay">
|
| 881 |
+
<span data-translate="cache_status_checking">Checking cache status...</span>
|
| 882 |
+
</div>
|
| 883 |
+
<button class="clear-cache-btn" id="clearCacheBtn" data-translate="clear_cache_button">
|
| 884 |
+
🗑️ Clear All Cached Translations
|
| 885 |
+
</button>
|
| 886 |
+
</div>
|
| 887 |
+
|
| 888 |
+
<div class="language-selector">
|
| 889 |
+
<label for="languageSelect" data-translate="select_language">🌐 Select Language</label>
|
| 890 |
+
<select id="languageSelect">
|
| 891 |
+
<option value="en">🇺🇸 English</option>
|
| 892 |
+
<option value="es">🇪🇸 Español (Spanish)</option>
|
| 893 |
+
<option value="fr">🇫🇷 Français (French)</option>
|
| 894 |
+
<option value="de">🇩🇪 Deutsch (German)</option>
|
| 895 |
+
<option value="zh">🇨🇳 中文 (Chinese)</option>
|
| 896 |
+
<option value="ja">🇯🇵 日本語 (Japanese)</option>
|
| 897 |
+
<option value="ko">🇰🇷 한국어 (Korean)</option>
|
| 898 |
+
<option value="pt">🇵🇹 Português (Portuguese)</option>
|
| 899 |
+
<option value="it">🇮🇹 Italiano (Italian)</option>
|
| 900 |
+
<option value="ar">🇸🇦 العربية (Arabic)</option>
|
| 901 |
+
<option value="ru">🇷🇺 Русский (Russian)</option>
|
| 902 |
+
<option value="hi">🇮🇳 हिन्दी (Hindi)</option>
|
| 903 |
+
<option value="bn">🇧🇩 বাংলা (Bengali)</option>
|
| 904 |
+
<option value="ur">🇵🇰 اردو (Urdu)</option>
|
| 905 |
+
<option value="tr">🇹🇷 Türkçe (Turkish)</option>
|
| 906 |
+
<option value="pl">🇵🇱 Polski (Polish)</option>
|
| 907 |
+
<option value="nl">🇳🇱 Nederlands (Dutch)</option>
|
| 908 |
+
<option value="sv">🇸🇪 Svenska (Swedish)</option>
|
| 909 |
+
<option value="da">🇩🇰 Dansk (Danish)</option>
|
| 910 |
+
<option value="no">🇳🇴 Norsk (Norwegian)</option>
|
| 911 |
+
<option value="fi">🇫🇮 Suomi (Finnish)</option>
|
| 912 |
+
<option value="is">🇮🇸 Íslenska (Icelandic)</option>
|
| 913 |
+
<option value="cs">🇨🇿 Čeština (Czech)</option>
|
| 914 |
+
<option value="sk">🇸🇰 Slovenčina (Slovak)</option>
|
| 915 |
+
<option value="hu">🇭🇺 Magyar (Hungarian)</option>
|
| 916 |
+
<option value="ro">🇷🇴 Română (Romanian)</option>
|
| 917 |
+
<option value="bg">🇧🇬 Български (Bulgarian)</option>
|
| 918 |
+
<option value="hr">🇭🇷 Hrvatski (Croatian)</option>
|
| 919 |
+
<option value="sr">🇷🇸 Српски (Serbian)</option>
|
| 920 |
+
<option value="sl">🇸🇮 Slovenščina (Slovenian)</option>
|
| 921 |
+
<option value="mk">🇲🇰 Македонски (Macedonian)</option>
|
| 922 |
+
<option value="sq">🇦🇱 Shqip (Albanian)</option>
|
| 923 |
+
<option value="lv">🇱🇻 Latviešu (Latvian)</option>
|
| 924 |
+
<option value="lt">🇱🇹 Lietuvių (Lithuanian)</option>
|
| 925 |
+
<option value="et">🇪🇪 Eesti (Estonian)</option>
|
| 926 |
+
<option value="mt">🇲🇹 Malti (Maltese)</option>
|
| 927 |
+
<option value="ga">🇮🇪 Gaeilge (Irish)</option>
|
| 928 |
+
<option value="cy">🏴 Cymraeg (Welsh)</option>
|
| 929 |
+
<option value="eu">���� Euskera (Basque)</option>
|
| 930 |
+
<option value="ca">🏴 Català (Catalan)</option>
|
| 931 |
+
<option value="gl">🏴 Galego (Galician)</option>
|
| 932 |
+
<option value="el">🇬🇷 Ελληνικά (Greek)</option>
|
| 933 |
+
<option value="he">🇮🇱 עברית (Hebrew)</option>
|
| 934 |
+
<option value="fa">🇮🇷 فارسی (Persian)</option>
|
| 935 |
+
<option value="ps">🇦🇫 پښتو (Pashto)</option>
|
| 936 |
+
<option value="ku">🏴 کوردی (Kurdish)</option>
|
| 937 |
+
<option value="az">🇦🇿 Azərbaycan (Azerbaijani)</option>
|
| 938 |
+
<option value="kk">🇰🇿 Қазақша (Kazakh)</option>
|
| 939 |
+
<option value="ky">🇰🇬 Кыргызча (Kyrgyz)</option>
|
| 940 |
+
<option value="uz">🇺🇿 O'zbek (Uzbek)</option>
|
| 941 |
+
<option value="tk">🇹🇲 Türkmen (Turkmen)</option>
|
| 942 |
+
<option value="tg">🇹🇯 Тоҷикӣ (Tajik)</option>
|
| 943 |
+
<option value="mn">🇲🇳 Монгол (Mongolian)</option>
|
| 944 |
+
<option value="ka">🇬🇪 ქართული (Georgian)</option>
|
| 945 |
+
<option value="hy">🇦🇲 Հայերեն (Armenian)</option>
|
| 946 |
+
<option value="th">🇹🇭 ไทย (Thai)</option>
|
| 947 |
+
<option value="vi">🇻🇳 Tiếng Việt (Vietnamese)</option>
|
| 948 |
+
<option value="lo">🇱🇦 ລາວ (Lao)</option>
|
| 949 |
+
<option value="km">🇰🇭 ខ្មែរ (Khmer)</option>
|
| 950 |
+
<option value="my">🇲🇲 မြန်မာ (Myanmar)</option>
|
| 951 |
+
<option value="si">🇱🇰 සිංහල (Sinhala)</option>
|
| 952 |
+
<option value="ta">🇱🇰 தமிழ் (Tamil)</option>
|
| 953 |
+
<option value="te">🇮🇳 తెలుగు (Telugu)</option>
|
| 954 |
+
<option value="kn">🇮🇳 ಕನ್ನಡ (Kannada)</option>
|
| 955 |
+
<option value="ml">🇮🇳 മലയാളം (Malayalam)</option>
|
| 956 |
+
<option value="gu">🇮🇳 ગુજરાતી (Gujarati)</option>
|
| 957 |
+
<option value="pa">🇮🇳 ਪੰਜਾਬੀ (Punjabi)</option>
|
| 958 |
+
<option value="or">🇮🇳 ଓଡ଼ିଆ (Odia)</option>
|
| 959 |
+
<option value="as">🇮🇳 অসমীয়া (Assamese)</option>
|
| 960 |
+
<option value="ne">🇳🇵 नेपाली (Nepali)</option>
|
| 961 |
+
<option value="dz">🇧🇹 རྫོང་ཁ (Dzongkha)</option>
|
| 962 |
+
<option value="bo">🏔️ བོད་ཡིག (Tibetan)</option>
|
| 963 |
+
<option value="id">🇮🇩 Bahasa Indonesia</option>
|
| 964 |
+
<option value="ms">🇲🇾 Bahasa Melayu (Malay)</option>
|
| 965 |
+
<option value="tl">🇵🇭 Filipino (Tagalog)</option>
|
| 966 |
+
<option value="ceb">🇵🇭 Cebuano</option>
|
| 967 |
+
<option value="haw">🏝️ ʻŌlelo Hawaiʻi (Hawaiian)</option>
|
| 968 |
+
<option value="mi">🇳🇿 Te Reo Māori (Maori)</option>
|
| 969 |
+
<option value="sm">🇼🇸 Gagana Samoa (Samoan)</option>
|
| 970 |
+
<option value="to">🇹🇴 Lea Fakatonga (Tongan)</option>
|
| 971 |
+
<option value="fj">🇫🇯 Na Vosa Vakaviti (Fijian)</option>
|
| 972 |
+
<option value="mg">🇲🇬 Malagasy</option>
|
| 973 |
+
<option value="sw">🇰🇪 Kiswahili (Swahili)</option>
|
| 974 |
+
<option value="zu">🇿🇦 isiZulu (Zulu)</option>
|
| 975 |
+
<option value="xh">🇿🇦 isiXhosa (Xhosa)</option>
|
| 976 |
+
<option value="af">🇿🇦 Afrikaans</option>
|
| 977 |
+
<option value="st">🇱🇸 Sesotho (Southern Sotho)</option>
|
| 978 |
+
<option value="tn">🇧🇼 Setswana (Tswana)</option>
|
| 979 |
+
<option value="ss">🇸🇿 siSwati (Swati)</option>
|
| 980 |
+
<option value="ve">🇿🇦 Tshivenḓa (Venda)</option>
|
| 981 |
+
<option value="ts">🇿🇦 Xitsonga (Tsonga)</option>
|
| 982 |
+
<option value="nr">🇿🇦 isiNdebele (Southern Ndebele)</option>
|
| 983 |
+
<option value="am">🇪🇹 አማርኛ (Amharic)</option>
|
| 984 |
+
<option value="ti">🇪🇷 ትግርኛ (Tigrinya)</option>
|
| 985 |
+
<option value="om">🇪🇹 Afaan Oromoo (Oromo)</option>
|
| 986 |
+
<option value="so">🇸🇴 Soomaali (Somali)</option>
|
| 987 |
+
<option value="ha">🇳🇬 Hausa</option>
|
| 988 |
+
<option value="yo">🇳🇬 Yorùbá (Yoruba)</option>
|
| 989 |
+
<option value="ig">🇳🇬 Igbo</option>
|
| 990 |
+
<option value="ff">🇸🇳 Fulfulde (Fulani)</option>
|
| 991 |
+
<option value="wo">🇸🇳 Wolof</option>
|
| 992 |
+
<option value="bm">🇲🇱 Bamanankan (Bambara)</option>
|
| 993 |
+
<option value="rn">🇧🇮 Kirundi (Rundi)</option>
|
| 994 |
+
<option value="rw">🇷🇼 Kinyarwanda (Rwanda)</option>
|
| 995 |
+
<option value="lg">🇺🇬 Luganda</option>
|
| 996 |
+
<option value="ny">🇲🇼 Chichewa (Nyanja)</option>
|
| 997 |
+
<option value="sn">🇿🇼 chiShona (Shona)</option>
|
| 998 |
+
<option value="nd">🇿🇼 isiNdebele (Northern Ndebele)</option>
|
| 999 |
+
</select>
|
| 1000 |
+
</div>
|
| 1001 |
+
|
| 1002 |
+
<div class="api-key-landing">
|
| 1003 |
+
<label for="apiKeyLanding" data-translate="api_key_label">🔑 OpenAI API Key</label>
|
| 1004 |
+
<input type="password" id="apiKeyLanding" placeholder="Enter your OpenAI API key" data-translate-placeholder="api_key_placeholder">
|
| 1005 |
+
</div>
|
| 1006 |
+
|
| 1007 |
+
<button class="start-btn" id="startBtn" data-translate="start_button">🌱 Start Impact Analysis</button>
|
| 1008 |
+
</div>
|
| 1009 |
+
|
| 1010 |
+
<!-- Main Application -->
|
| 1011 |
+
<div class="main-app" id="mainApp">
|
| 1012 |
+
<div class="app-container">
|
| 1013 |
+
<!-- Language Switcher -->
|
| 1014 |
+
<div class="language-switcher" id="languageSwitcher">
|
| 1015 |
+
<div class="language-switch-btn" onclick="showLanguageLanding()">
|
| 1016 |
+
<span data-translate="change_language">🌐 Change Language</span>
|
| 1017 |
+
</div>
|
| 1018 |
+
<div class="mini-clear-cache" onclick="clearAllTranslationCache()" title="Clear translation cache">
|
| 1019 |
+
<span data-translate="clear_cache_mini">🗑️ Clear Cache</span>
|
| 1020 |
+
</div>
|
| 1021 |
+
</div>
|
| 1022 |
+
|
| 1023 |
+
<!-- Compact API Key in Top-Left -->
|
| 1024 |
+
<div class="api-key-compact">
|
| 1025 |
+
<label for="apiKey" class="api-key-compact-label" data-translate="api_key_short">API Key</label>
|
| 1026 |
+
<input
|
| 1027 |
+
type="password"
|
| 1028 |
+
id="apiKey"
|
| 1029 |
+
class="api-key-compact-input"
|
| 1030 |
+
data-translate-placeholder="api_key_placeholder"
|
| 1031 |
+
autocomplete="off"
|
| 1032 |
+
>
|
| 1033 |
+
</div>
|
| 1034 |
+
|
| 1035 |
+
<div class="main-content">
|
| 1036 |
+
<!-- Header -->
|
| 1037 |
+
<div class="header">
|
| 1038 |
+
<h1 data-translate="app_title">ImpactAnalyzer Pro</h1>
|
| 1039 |
+
<p class="subtitle" data-translate="app_subtitle">Sustainability & Social Impact Assessment Platform</p>
|
| 1040 |
+
<p class="description" data-translate="app_description">Analyze the environmental and social impacts of your ideas, projects, and initiatives with comprehensive AI-powered assessment</p>
|
| 1041 |
+
</div>
|
| 1042 |
+
|
| 1043 |
+
<!-- Impact Categories Overview -->
|
| 1044 |
+
<div class="impact-categories">
|
| 1045 |
+
<div class="category-card">
|
| 1046 |
+
<h4 data-translate="environmental_impact">🌍 Environmental Impact</h4>
|
| 1047 |
+
<p data-translate="environmental_desc">Carbon footprint, resource usage, sustainability</p>
|
| 1048 |
+
</div>
|
| 1049 |
+
<div class="category-card">
|
| 1050 |
+
<h4 data-translate="social_impact">👥 Social Impact</h4>
|
| 1051 |
+
<p data-translate="social_desc">Community benefits, social equity, accessibility</p>
|
| 1052 |
+
</div>
|
| 1053 |
+
<div class="category-card">
|
| 1054 |
+
<h4 data-translate="economic_impact">💰 Economic Impact</h4>
|
| 1055 |
+
<p data-translate="economic_desc">Cost-effectiveness, economic sustainability</p>
|
| 1056 |
+
</div>
|
| 1057 |
+
<div class="category-card">
|
| 1058 |
+
<h4 data-translate="ethical_considerations">⚖️ Ethical Considerations</h4>
|
| 1059 |
+
<p data-translate="ethical_desc">Fairness, transparency, responsibility</p>
|
| 1060 |
+
</div>
|
| 1061 |
+
<div class="category-card">
|
| 1062 |
+
<h4 data-translate="lifecycle_assessment">🔄 Lifecycle Assessment</h4>
|
| 1063 |
+
<p data-translate="lifecycle_desc">Long-term effects, scalability, durability</p>
|
| 1064 |
+
</div>
|
| 1065 |
+
<div class="category-card">
|
| 1066 |
+
<h4 data-translate="risk_analysis">📊 Risk Analysis</h4>
|
| 1067 |
+
<p data-translate="risk_desc">Potential challenges, mitigation strategies</p>
|
| 1068 |
+
</div>
|
| 1069 |
+
</div>
|
| 1070 |
+
|
| 1071 |
+
<!-- Error Message -->
|
| 1072 |
+
<div class="error-message" id="errorMessage"></div>
|
| 1073 |
+
|
| 1074 |
+
<!-- Input Section -->
|
| 1075 |
+
<div class="input-section">
|
| 1076 |
+
<h3 data-translate="idea_input_title">💡 Idea & Project Input</h3>
|
| 1077 |
+
<p class="description" data-translate="idea_input_desc">Describe your idea, project, product, service, or initiative that you want to analyze for environmental and social impact</p>
|
| 1078 |
+
<textarea id="ideaInput" data-translate-placeholder="idea_input_placeholder" required></textarea>
|
| 1079 |
+
<div class="char-counter" id="charCounter">0 characters</div>
|
| 1080 |
+
</div>
|
| 1081 |
+
|
| 1082 |
+
<!-- Generate Button -->
|
| 1083 |
+
<button class="generate-btn" id="compareBtn">
|
| 1084 |
+
<span class="spinner" id="spinner"></span>
|
| 1085 |
+
<span id="buttonText" data-translate="analyze_button">🌱 Analyze Impact</span>
|
| 1086 |
+
</button>
|
| 1087 |
+
|
| 1088 |
+
<!-- Output Section -->
|
| 1089 |
+
<div class="output-section">
|
| 1090 |
+
<h2 data-translate="output_title">📈 Your Impact Analysis Report</h2>
|
| 1091 |
+
<div class="output-area" id="impactOutput"></div>
|
| 1092 |
+
</div>
|
| 1093 |
+
</div>
|
| 1094 |
+
|
| 1095 |
+
<!-- Footer -->
|
| 1096 |
+
<div class="footer">
|
| 1097 |
+
Created by Shift Mind AI Labs
|
| 1098 |
+
</div>
|
| 1099 |
+
</div>
|
| 1100 |
+
</div>
|
| 1101 |
+
|
| 1102 |
+
<script>
|
| 1103 |
+
// RTL languages list
|
| 1104 |
+
const rtlLanguages = ['ar', 'he', 'fa', 'ur', 'ps', 'ku'];
|
| 1105 |
+
|
| 1106 |
+
// Current language and API key
|
| 1107 |
+
let currentLanguage = 'en';
|
| 1108 |
+
let currentApiKey = '';
|
| 1109 |
+
|
| 1110 |
+
// Language names mapping
|
| 1111 |
+
const languageNames = {
|
| 1112 |
+
en: 'English', es: 'Spanish', fr: 'French', de: 'German', zh: 'Chinese',
|
| 1113 |
+
ja: 'Japanese', ko: 'Korean', pt: 'Portuguese', it: 'Italian', ar: 'Arabic',
|
| 1114 |
+
ru: 'Russian', hi: 'Hindi', bn: 'Bengali', ur: 'Urdu', tr: 'Turkish',
|
| 1115 |
+
pl: 'Polish', nl: 'Dutch', sv: 'Swedish', da: 'Danish', no: 'Norwegian',
|
| 1116 |
+
fi: 'Finnish', is: 'Icelandic', cs: 'Czech', sk: 'Slovak', hu: 'Hungarian',
|
| 1117 |
+
ro: 'Romanian', bg: 'Bulgarian', hr: 'Croatian', sr: 'Serbian', sl: 'Slovenian',
|
| 1118 |
+
mk: 'Macedonian', sq: 'Albanian', lv: 'Latvian', lt: 'Lithuanian', et: 'Estonian',
|
| 1119 |
+
mt: 'Maltese', ga: 'Irish', cy: 'Welsh', eu: 'Basque', ca: 'Catalan',
|
| 1120 |
+
gl: 'Galician', el: 'Greek', he: 'Hebrew', fa: 'Persian', ps: 'Pashto',
|
| 1121 |
+
ku: 'Kurdish', az: 'Azerbaijani', kk: 'Kazakh', ky: 'Kyrgyz', uz: 'Uzbek',
|
| 1122 |
+
tk: 'Turkmen', tg: 'Tajik', mn: 'Mongolian', ka: 'Georgian', hy: 'Armenian',
|
| 1123 |
+
th: 'Thai', vi: 'Vietnamese', lo: 'Lao', km: 'Khmer', my: 'Myanmar',
|
| 1124 |
+
si: 'Sinhala', ta: 'Tamil', te: 'Telugu', kn: 'Kannada', ml: 'Malayalam',
|
| 1125 |
+
gu: 'Gujarati', pa: 'Punjabi', or: 'Odia', as: 'Assamese', ne: 'Nepali',
|
| 1126 |
+
dz: 'Dzongkha', bo: 'Tibetan', id: 'Indonesian', ms: 'Malay', tl: 'Filipino',
|
| 1127 |
+
ceb: 'Cebuano', haw: 'Hawaiian', mi: 'Maori', sm: 'Samoan', to: 'Tongan',
|
| 1128 |
+
fj: 'Fijian', mg: 'Malagasy', sw: 'Swahili', zu: 'Zulu', xh: 'Xhosa',
|
| 1129 |
+
af: 'Afrikaans', st: 'Southern Sotho', tn: 'Tswana', ss: 'Swati', ve: 'Venda',
|
| 1130 |
+
ts: 'Tsonga', nr: 'Southern Ndebele', am: 'Amharic', ti: 'Tigrinya', om: 'Oromo',
|
| 1131 |
+
so: 'Somali', ha: 'Hausa', yo: 'Yoruba', ig: 'Igbo', ff: 'Fulani',
|
| 1132 |
+
wo: 'Wolof', bm: 'Bambara', rn: 'Rundi', rw: 'Rwanda', lg: 'Luganda',
|
| 1133 |
+
ny: 'Chichewa', sn: 'Shona', nd: 'Northern Ndebele'
|
| 1134 |
+
};
|
| 1135 |
+
|
| 1136 |
+
// Translation cache management
|
| 1137 |
+
const CACHE_PREFIX = 'impactanalyzer_translations_';
|
| 1138 |
+
const CACHE_VERSION = '1.0';
|
| 1139 |
+
|
| 1140 |
+
// Check if translations are cached for a language
|
| 1141 |
+
function isLanguageCached(language) {
|
| 1142 |
+
const cacheKey = CACHE_PREFIX + language;
|
| 1143 |
+
const cached = localStorage.getItem(cacheKey);
|
| 1144 |
+
return cached !== null;
|
| 1145 |
+
}
|
| 1146 |
+
|
| 1147 |
+
// Save translations to cache
|
| 1148 |
+
function saveTranslationsToCache(language, translations) {
|
| 1149 |
+
const cacheKey = CACHE_PREFIX + language;
|
| 1150 |
+
const cacheData = {
|
| 1151 |
+
version: CACHE_VERSION,
|
| 1152 |
+
timestamp: Date.now(),
|
| 1153 |
+
translations: translations
|
| 1154 |
+
};
|
| 1155 |
+
localStorage.setItem(cacheKey, JSON.stringify(cacheData));
|
| 1156 |
+
console.log(`Translations cached for ${language}`);
|
| 1157 |
+
}
|
| 1158 |
+
|
| 1159 |
+
// Load translations from cache
|
| 1160 |
+
function loadTranslationsFromCache(language) {
|
| 1161 |
+
const cacheKey = CACHE_PREFIX + language;
|
| 1162 |
+
const cached = localStorage.getItem(cacheKey);
|
| 1163 |
+
|
| 1164 |
+
if (cached) {
|
| 1165 |
+
try {
|
| 1166 |
+
const cacheData = JSON.parse(cached);
|
| 1167 |
+
if (cacheData.version === CACHE_VERSION) {
|
| 1168 |
+
console.log(`Translations loaded from cache for ${language}`);
|
| 1169 |
+
return cacheData.translations;
|
| 1170 |
+
}
|
| 1171 |
+
} catch (error) {
|
| 1172 |
+
console.error('Error parsing cached translations:', error);
|
| 1173 |
+
}
|
| 1174 |
+
}
|
| 1175 |
+
return null;
|
| 1176 |
+
}
|
| 1177 |
+
|
| 1178 |
+
// Get all cached languages
|
| 1179 |
+
function getCachedLanguages() {
|
| 1180 |
+
const cachedLanguages = [];
|
| 1181 |
+
for (let i = 0; i < localStorage.length; i++) {
|
| 1182 |
+
const key = localStorage.key(i);
|
| 1183 |
+
if (key && key.startsWith(CACHE_PREFIX)) {
|
| 1184 |
+
const language = key.replace(CACHE_PREFIX, '');
|
| 1185 |
+
cachedLanguages.push(language);
|
| 1186 |
+
}
|
| 1187 |
+
}
|
| 1188 |
+
return cachedLanguages;
|
| 1189 |
+
}
|
| 1190 |
+
|
| 1191 |
+
// Clear all translation cache
|
| 1192 |
+
function clearAllTranslationCache() {
|
| 1193 |
+
const cachedLanguages = getCachedLanguages();
|
| 1194 |
+
|
| 1195 |
+
if (cachedLanguages.length === 0) {
|
| 1196 |
+
alert('No cached translations to clear.');
|
| 1197 |
+
return;
|
| 1198 |
+
}
|
| 1199 |
+
|
| 1200 |
+
const languageList = cachedLanguages.map(lang => languageNames[lang] || lang).join(', ');
|
| 1201 |
+
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.`;
|
| 1202 |
+
|
| 1203 |
+
if (confirm(confirmMessage)) {
|
| 1204 |
+
// Clear all translation caches
|
| 1205 |
+
cachedLanguages.forEach(language => {
|
| 1206 |
+
const cacheKey = CACHE_PREFIX + language;
|
| 1207 |
+
localStorage.removeItem(cacheKey);
|
| 1208 |
+
});
|
| 1209 |
+
|
| 1210 |
+
// Update cache status
|
| 1211 |
+
updateCacheStatus(currentLanguage);
|
| 1212 |
+
updateCacheStatusDisplay();
|
| 1213 |
+
|
| 1214 |
+
alert(`Cache cleared successfully!\n\n${cachedLanguages.length} language(s) removed from cache.`);
|
| 1215 |
+
|
| 1216 |
+
// Ask if user wants to reload current language translations
|
| 1217 |
+
if (currentLanguage !== 'en' && cachedLanguages.includes(currentLanguage)) {
|
| 1218 |
+
if (confirm('Would you like to reload the current language translations?')) {
|
| 1219 |
+
applyLanguage(currentLanguage);
|
| 1220 |
+
}
|
| 1221 |
+
}
|
| 1222 |
+
}
|
| 1223 |
+
}
|
| 1224 |
+
|
| 1225 |
+
// Update cache status indicator
|
| 1226 |
+
function updateCacheStatus(language) {
|
| 1227 |
+
const cacheStatus = document.getElementById('cacheStatus');
|
| 1228 |
+
const isCached = isLanguageCached(language);
|
| 1229 |
+
|
| 1230 |
+
if (language === 'en') {
|
| 1231 |
+
cacheStatus.classList.remove('cached', 'translating');
|
| 1232 |
+
return;
|
| 1233 |
+
}
|
| 1234 |
+
|
| 1235 |
+
if (isCached) {
|
| 1236 |
+
cacheStatus.textContent = '💾 Translations cached - instant loading!';
|
| 1237 |
+
cacheStatus.classList.add('cached');
|
| 1238 |
+
cacheStatus.classList.remove('translating');
|
| 1239 |
+
} else {
|
| 1240 |
+
cacheStatus.textContent = '🔄 First time translation - will be cached for future use';
|
| 1241 |
+
cacheStatus.classList.add('translating');
|
| 1242 |
+
cacheStatus.classList.remove('cached');
|
| 1243 |
+
}
|
| 1244 |
+
}
|
| 1245 |
+
|
| 1246 |
+
// Update cache status display in management section
|
| 1247 |
+
function updateCacheStatusDisplay() {
|
| 1248 |
+
const cacheStatusDisplay = document.getElementById('cacheStatusDisplay');
|
| 1249 |
+
const clearCacheBtn = document.getElementById('clearCacheBtn');
|
| 1250 |
+
const cachedLanguages = getCachedLanguages();
|
| 1251 |
+
|
| 1252 |
+
if (cachedLanguages.length === 0) {
|
| 1253 |
+
cacheStatusDisplay.textContent = '📭 No cached translations';
|
| 1254 |
+
cacheStatusDisplay.className = 'cache-status-display no-cache';
|
| 1255 |
+
clearCacheBtn.disabled = true;
|
| 1256 |
+
} else {
|
| 1257 |
+
const languageList = cachedLanguages.map(lang => languageNames[lang] || lang).join(', ');
|
| 1258 |
+
cacheStatusDisplay.textContent = `💾 ${cachedLanguages.length} language(s) cached: ${languageList}`;
|
| 1259 |
+
cacheStatusDisplay.className = 'cache-status-display';
|
| 1260 |
+
clearCacheBtn.disabled = false;
|
| 1261 |
+
}
|
| 1262 |
+
}
|
| 1263 |
+
|
| 1264 |
+
// Initialize the application
|
| 1265 |
+
function initializeApp() {
|
| 1266 |
+
// Load saved language and API key
|
| 1267 |
+
const savedLanguage = localStorage.getItem('impactanalyzer_language') || 'en';
|
| 1268 |
+
const savedApiKey = localStorage.getItem('impact_analyzer_api_key') || '';
|
| 1269 |
+
|
| 1270 |
+
currentLanguage = savedLanguage;
|
| 1271 |
+
currentApiKey = savedApiKey;
|
| 1272 |
+
|
| 1273 |
+
// Set language selector
|
| 1274 |
+
document.getElementById('languageSelect').value = currentLanguage;
|
| 1275 |
+
document.getElementById('apiKeyLanding').value = currentApiKey;
|
| 1276 |
+
|
| 1277 |
+
// Apply direction for current language
|
| 1278 |
+
applyDirection(currentLanguage);
|
| 1279 |
+
|
| 1280 |
+
// Update cache status
|
| 1281 |
+
updateCacheStatus(currentLanguage);
|
| 1282 |
+
updateCacheStatusDisplay();
|
| 1283 |
+
|
| 1284 |
+
// Show appropriate screen
|
| 1285 |
+
if (currentApiKey && currentLanguage) {
|
| 1286 |
+
showMainApp();
|
| 1287 |
+
} else {
|
| 1288 |
+
showLanguageLanding();
|
| 1289 |
+
}
|
| 1290 |
+
}
|
| 1291 |
+
|
| 1292 |
+
// Apply language direction
|
| 1293 |
+
function applyDirection(language) {
|
| 1294 |
+
currentLanguage = language;
|
| 1295 |
+
|
| 1296 |
+
// Set document language and direction
|
| 1297 |
+
document.documentElement.lang = language;
|
| 1298 |
+
document.documentElement.dir = rtlLanguages.includes(language) ? 'rtl' : 'ltr';
|
| 1299 |
+
|
| 1300 |
+
// Save language preference
|
| 1301 |
+
localStorage.setItem('impactanalyzer_language', language);
|
| 1302 |
+
|
| 1303 |
+
// Update cache status
|
| 1304 |
+
updateCacheStatus(language);
|
| 1305 |
+
}
|
| 1306 |
+
|
| 1307 |
+
// API call function for translation
|
| 1308 |
+
async function translateText(text, targetLanguage) {
|
| 1309 |
+
if (!currentApiKey) {
|
| 1310 |
+
throw new Error('API key is required for translation');
|
| 1311 |
+
}
|
| 1312 |
+
|
| 1313 |
+
const languageName = languageNames[targetLanguage] || 'English';
|
| 1314 |
+
|
| 1315 |
+
const prompt = `Translate the following text to ${languageName}. Provide ONLY the exact translation without any explanations, additional information, or formatting:
|
| 1316 |
+
|
| 1317 |
+
"${text}"`;
|
| 1318 |
+
|
| 1319 |
+
const payload = {
|
| 1320 |
+
model: "gpt-4o-mini",
|
| 1321 |
+
messages: [{ role: "user", content: prompt }],
|
| 1322 |
+
max_tokens: 500,
|
| 1323 |
+
temperature: 0.1
|
| 1324 |
+
};
|
| 1325 |
+
|
| 1326 |
+
const response = await fetch("https://api.openai.com/v1/chat/completions", {
|
| 1327 |
+
method: "POST",
|
| 1328 |
+
headers: {
|
| 1329 |
+
"Content-Type": "application/json",
|
| 1330 |
+
"Authorization": `Bearer ${currentApiKey}`
|
| 1331 |
+
},
|
| 1332 |
+
body: JSON.stringify(payload)
|
| 1333 |
+
});
|
| 1334 |
+
|
| 1335 |
+
if (!response.ok) {
|
| 1336 |
+
const errorData = await response.json();
|
| 1337 |
+
throw new Error(errorData.error?.message || "Translation API request failed");
|
| 1338 |
+
}
|
| 1339 |
+
|
| 1340 |
+
const data = await response.json();
|
| 1341 |
+
return data.choices[0].message.content.trim();
|
| 1342 |
+
}
|
| 1343 |
+
|
| 1344 |
+
// Apply cached translations to UI
|
| 1345 |
+
function applyCachedTranslations(translations) {
|
| 1346 |
+
// Apply text translations
|
| 1347 |
+
Object.keys(translations.texts).forEach(originalText => {
|
| 1348 |
+
const translation = translations.texts[originalText];
|
| 1349 |
+
const elements = document.querySelectorAll(`[data-translate]`);
|
| 1350 |
+
|
| 1351 |
+
elements.forEach(element => {
|
| 1352 |
+
const originalElementText = element.getAttribute('data-original-text') || element.textContent;
|
| 1353 |
+
if (originalElementText === originalText) {
|
| 1354 |
+
element.textContent = translation;
|
| 1355 |
+
}
|
| 1356 |
+
});
|
| 1357 |
+
});
|
| 1358 |
+
|
| 1359 |
+
// Apply placeholder translations
|
| 1360 |
+
Object.keys(translations.placeholders).forEach(originalPlaceholder => {
|
| 1361 |
+
const translation = translations.placeholders[originalPlaceholder];
|
| 1362 |
+
const elements = document.querySelectorAll(`[data-translate-placeholder]`);
|
| 1363 |
+
|
| 1364 |
+
elements.forEach(element => {
|
| 1365 |
+
const originalElementPlaceholder = element.getAttribute('data-original-placeholder') || element.placeholder;
|
| 1366 |
+
if (originalElementPlaceholder === originalPlaceholder) {
|
| 1367 |
+
element.placeholder = translation;
|
| 1368 |
+
}
|
| 1369 |
+
});
|
| 1370 |
+
});
|
| 1371 |
+
}
|
| 1372 |
+
|
| 1373 |
+
// Translate all UI elements
|
| 1374 |
+
async function translateInterface(targetLanguage) {
|
| 1375 |
+
if (targetLanguage === 'en') {
|
| 1376 |
+
// No translation needed for English
|
| 1377 |
+
return;
|
| 1378 |
+
}
|
| 1379 |
+
|
| 1380 |
+
// Check if translations are cached
|
| 1381 |
+
const cachedTranslations = loadTranslationsFromCache(targetLanguage);
|
| 1382 |
+
if (cachedTranslations) {
|
| 1383 |
+
// Use cached translations
|
| 1384 |
+
console.log('Using cached translations for', targetLanguage);
|
| 1385 |
+
applyCachedTranslations(cachedTranslations);
|
| 1386 |
+
return;
|
| 1387 |
+
}
|
| 1388 |
+
|
| 1389 |
+
// Need to translate via API
|
| 1390 |
+
showTranslationOverlay();
|
| 1391 |
+
|
| 1392 |
+
try {
|
| 1393 |
+
// Get all elements with data-translate attribute
|
| 1394 |
+
const elements = document.querySelectorAll('[data-translate]');
|
| 1395 |
+
const placeholderElements = document.querySelectorAll('[data-translate-placeholder]');
|
| 1396 |
+
|
| 1397 |
+
// Collect all texts to translate
|
| 1398 |
+
const textsToTranslate = [];
|
| 1399 |
+
const placeholdersToTranslate = [];
|
| 1400 |
+
const elementMap = new Map();
|
| 1401 |
+
|
| 1402 |
+
elements.forEach(element => {
|
| 1403 |
+
const originalText = element.getAttribute('data-original-text') || element.textContent;
|
| 1404 |
+
if (!element.getAttribute('data-original-text')) {
|
| 1405 |
+
element.setAttribute('data-original-text', originalText);
|
| 1406 |
+
}
|
| 1407 |
+
textsToTranslate.push(originalText);
|
| 1408 |
+
elementMap.set(originalText, element);
|
| 1409 |
+
});
|
| 1410 |
+
|
| 1411 |
+
placeholderElements.forEach(element => {
|
| 1412 |
+
const originalPlaceholder = element.getAttribute('data-original-placeholder') || element.placeholder;
|
| 1413 |
+
if (!element.getAttribute('data-original-placeholder')) {
|
| 1414 |
+
element.setAttribute('data-original-placeholder', originalPlaceholder);
|
| 1415 |
+
}
|
| 1416 |
+
placeholdersToTranslate.push(originalPlaceholder);
|
| 1417 |
+
elementMap.set(originalPlaceholder, element);
|
| 1418 |
+
});
|
| 1419 |
+
|
| 1420 |
+
// Prepare cache structure
|
| 1421 |
+
const translationsCache = {
|
| 1422 |
+
texts: {},
|
| 1423 |
+
placeholders: {}
|
| 1424 |
+
};
|
| 1425 |
+
|
| 1426 |
+
// Translate texts in batches
|
| 1427 |
+
const batchSize = 10;
|
| 1428 |
+
const allTexts = [...textsToTranslate, ...placeholdersToTranslate];
|
| 1429 |
+
|
| 1430 |
+
for (let i = 0; i < allTexts.length; i += batchSize) {
|
| 1431 |
+
const batch = allTexts.slice(i, i + batchSize);
|
| 1432 |
+
|
| 1433 |
+
// Update progress
|
| 1434 |
+
updateTranslationProgress(i, allTexts.length);
|
| 1435 |
+
|
| 1436 |
+
// Translate batch
|
| 1437 |
+
const translations = await Promise.all(
|
| 1438 |
+
batch.map(text => translateText(text, targetLanguage))
|
| 1439 |
+
);
|
| 1440 |
+
|
| 1441 |
+
// Apply translations and cache them
|
| 1442 |
+
batch.forEach((originalText, index) => {
|
| 1443 |
+
const element = elementMap.get(originalText);
|
| 1444 |
+
const translation = translations[index];
|
| 1445 |
+
|
| 1446 |
+
if (element.hasAttribute('data-translate')) {
|
| 1447 |
+
element.textContent = translation;
|
| 1448 |
+
translationsCache.texts[originalText] = translation;
|
| 1449 |
+
} else if (element.hasAttribute('data-translate-placeholder')) {
|
| 1450 |
+
element.placeholder = translation;
|
| 1451 |
+
translationsCache.placeholders[originalText] = translation;
|
| 1452 |
+
}
|
| 1453 |
+
});
|
| 1454 |
+
}
|
| 1455 |
+
|
| 1456 |
+
// Save translations to cache
|
| 1457 |
+
saveTranslationsToCache(targetLanguage, translationsCache);
|
| 1458 |
+
|
| 1459 |
+
// Update cache status
|
| 1460 |
+
updateCacheStatus(targetLanguage);
|
| 1461 |
+
updateCacheStatusDisplay();
|
| 1462 |
+
|
| 1463 |
+
} catch (error) {
|
| 1464 |
+
console.error('Translation error:', error);
|
| 1465 |
+
showError('Translation failed: ' + error.message);
|
| 1466 |
+
} finally {
|
| 1467 |
+
hideTranslationOverlay();
|
| 1468 |
+
}
|
| 1469 |
+
}
|
| 1470 |
+
|
| 1471 |
+
// Show translation overlay
|
| 1472 |
+
function showTranslationOverlay() {
|
| 1473 |
+
document.getElementById('translationOverlay').style.display = 'flex';
|
| 1474 |
+
}
|
| 1475 |
+
|
| 1476 |
+
// Hide translation overlay
|
| 1477 |
+
function hideTranslationOverlay() {
|
| 1478 |
+
document.getElementById('translationOverlay').style.display = 'none';
|
| 1479 |
+
}
|
| 1480 |
+
|
| 1481 |
+
// Update translation progress
|
| 1482 |
+
function updateTranslationProgress(current, total) {
|
| 1483 |
+
const percentage = Math.round((current / total) * 100);
|
| 1484 |
+
document.getElementById('translationMessage').textContent =
|
| 1485 |
+
`Translating interface... ${percentage}% complete (will be cached for future use)`;
|
| 1486 |
+
}
|
| 1487 |
+
|
| 1488 |
+
// Apply language with API translation or cache
|
| 1489 |
+
async function applyLanguage(language) {
|
| 1490 |
+
applyDirection(language);
|
| 1491 |
+
|
| 1492 |
+
if (language !== 'en') {
|
| 1493 |
+
await translateInterface(language);
|
| 1494 |
+
}
|
| 1495 |
+
}
|
| 1496 |
+
|
| 1497 |
+
// Show language landing page
|
| 1498 |
+
function showLanguageLanding() {
|
| 1499 |
+
document.getElementById('languageLanding').style.display = 'block';
|
| 1500 |
+
document.getElementById('mainApp').style.display = 'none';
|
| 1501 |
+
}
|
| 1502 |
+
|
| 1503 |
+
// Show main application
|
| 1504 |
+
function showMainApp() {
|
| 1505 |
+
document.getElementById('languageLanding').style.display = 'none';
|
| 1506 |
+
document.getElementById('mainApp').style.display = 'block';
|
| 1507 |
+
|
| 1508 |
+
// Set API key in main app
|
| 1509 |
+
document.getElementById('apiKey').value = currentApiKey;
|
| 1510 |
+
}
|
| 1511 |
+
|
| 1512 |
+
// Start button click handler
|
| 1513 |
+
document.getElementById('startBtn').addEventListener('click', async function() {
|
| 1514 |
+
const selectedLanguage = document.getElementById('languageSelect').value;
|
| 1515 |
+
const apiKey = document.getElementById('apiKeyLanding').value.trim();
|
| 1516 |
+
|
| 1517 |
+
if (!apiKey) {
|
| 1518 |
+
alert('Please enter your OpenAI API key');
|
| 1519 |
+
return;
|
| 1520 |
+
}
|
| 1521 |
+
|
| 1522 |
+
currentLanguage = selectedLanguage;
|
| 1523 |
+
currentApiKey = apiKey;
|
| 1524 |
+
|
| 1525 |
+
// Save API key
|
| 1526 |
+
localStorage.setItem('impact_analyzer_api_key', apiKey);
|
| 1527 |
+
|
| 1528 |
+
// Apply language with translation (cached or API)
|
| 1529 |
+
await applyLanguage(selectedLanguage);
|
| 1530 |
+
|
| 1531 |
+
// Show main app
|
| 1532 |
+
showMainApp();
|
| 1533 |
+
});
|
| 1534 |
+
|
| 1535 |
+
// Language selector change handler
|
| 1536 |
+
document.getElementById('languageSelect').addEventListener('change', async function() {
|
| 1537 |
+
const selectedLanguage = this.value;
|
| 1538 |
+
updateCacheStatus(selectedLanguage);
|
| 1539 |
+
|
| 1540 |
+
if (currentApiKey) {
|
| 1541 |
+
await applyLanguage(selectedLanguage);
|
| 1542 |
+
} else {
|
| 1543 |
+
applyDirection(selectedLanguage);
|
| 1544 |
+
}
|
| 1545 |
+
});
|
| 1546 |
+
|
| 1547 |
+
// Clear cache button handler
|
| 1548 |
+
document.getElementById('clearCacheBtn').addEventListener('click', clearAllTranslationCache);
|
| 1549 |
+
|
| 1550 |
+
// API key sync between landing and main app
|
| 1551 |
+
document.getElementById('apiKeyLanding').addEventListener('input', function() {
|
| 1552 |
+
currentApiKey = this.value;
|
| 1553 |
+
localStorage.setItem('impact_analyzer_api_key', this.value);
|
| 1554 |
+
document.getElementById('apiKey').value = this.value;
|
| 1555 |
+
});
|
| 1556 |
+
|
| 1557 |
+
document.getElementById('apiKey').addEventListener('input', function() {
|
| 1558 |
+
currentApiKey = this.value;
|
| 1559 |
+
localStorage.setItem('impact_analyzer_api_key', this.value);
|
| 1560 |
+
document.getElementById('apiKeyLanding').value = this.value;
|
| 1561 |
+
});
|
| 1562 |
+
|
| 1563 |
+
// Character counter
|
| 1564 |
+
const ideaInput = document.getElementById('ideaInput');
|
| 1565 |
+
const charCounter = document.getElementById('charCounter');
|
| 1566 |
+
|
| 1567 |
+
ideaInput.addEventListener('input', function() {
|
| 1568 |
+
const count = this.value.length;
|
| 1569 |
+
charCounter.textContent = `${count} characters`;
|
| 1570 |
+
|
| 1571 |
+
if (count > 5000) {
|
| 1572 |
+
charCounter.style.color = 'var(--color-warning)';
|
| 1573 |
+
} else {
|
| 1574 |
+
charCounter.style.color = 'var(--color-text-secondary)';
|
| 1575 |
+
}
|
| 1576 |
+
});
|
| 1577 |
+
|
| 1578 |
+
// Scroll-based progress bar
|
| 1579 |
+
window.addEventListener('scroll', () => {
|
| 1580 |
+
const { scrollTop, scrollHeight } = document.documentElement;
|
| 1581 |
+
const scrolled = (scrollTop / (scrollHeight - window.innerHeight)) * 100;
|
| 1582 |
+
document.getElementById('progressBar').style.width = `${scrolled}%`;
|
| 1583 |
+
});
|
| 1584 |
+
|
| 1585 |
+
// Error handling
|
| 1586 |
+
function showError(message) {
|
| 1587 |
+
const errorDiv = document.getElementById('errorMessage');
|
| 1588 |
+
errorDiv.textContent = message;
|
| 1589 |
+
errorDiv.style.display = 'block';
|
| 1590 |
+
setTimeout(() => {
|
| 1591 |
+
errorDiv.style.display = 'none';
|
| 1592 |
+
}, 5000);
|
| 1593 |
+
}
|
| 1594 |
+
|
| 1595 |
+
// API call function - Updated to use current language
|
| 1596 |
+
async function callAPI(prompt) {
|
| 1597 |
+
const apiKey = document.getElementById('apiKey').value.trim();
|
| 1598 |
+
|
| 1599 |
+
if (!apiKey) {
|
| 1600 |
+
throw new Error('Please enter your OpenAI API key');
|
| 1601 |
+
}
|
| 1602 |
+
|
| 1603 |
+
const payload = {
|
| 1604 |
+
model: "gpt-4o-mini",
|
| 1605 |
+
messages: [{ role: "user", content: prompt }],
|
| 1606 |
+
max_tokens: 3500,
|
| 1607 |
+
temperature: 0.3
|
| 1608 |
+
};
|
| 1609 |
+
|
| 1610 |
+
const response = await fetch("https://api.openai.com/v1/chat/completions", {
|
| 1611 |
+
method: "POST",
|
| 1612 |
+
headers: {
|
| 1613 |
+
"Content-Type": "application/json",
|
| 1614 |
+
"Authorization": `Bearer ${apiKey}`
|
| 1615 |
+
},
|
| 1616 |
+
body: JSON.stringify(payload)
|
| 1617 |
+
});
|
| 1618 |
+
|
| 1619 |
+
if (!response.ok) {
|
| 1620 |
+
const errorData = await response.json();
|
| 1621 |
+
throw new Error(errorData.error?.message || "API request failed");
|
| 1622 |
+
}
|
| 1623 |
+
|
| 1624 |
+
const data = await response.json();
|
| 1625 |
+
return data.choices[0].message.content;
|
| 1626 |
+
}
|
| 1627 |
+
|
| 1628 |
+
// Build impact analysis prompt - Updated to use current language dynamically
|
| 1629 |
+
function buildImpactPrompt() {
|
| 1630 |
+
const languageName = languageNames[currentLanguage] || 'English';
|
| 1631 |
+
const idea = document.getElementById('ideaInput').value.trim();
|
| 1632 |
+
|
| 1633 |
+
return `Based on the following idea, project, or initiative:
|
| 1634 |
+
|
| 1635 |
+
---------------------
|
| 1636 |
+
${idea}
|
| 1637 |
+
---------------------
|
| 1638 |
+
|
| 1639 |
+
**Important: Generate the entire response in ${languageName}. All content, headings, explanations, and recommendations must be written in ${languageName}.**
|
| 1640 |
+
|
| 1641 |
+
Please provide a comprehensive, structured, and detailed analysis of the environmental and social impacts of this idea. The analysis should be professional, thorough, and actionable, formatted as clean text without any formatting symbols like asterisks (*) or hash signs (#).
|
| 1642 |
+
|
| 1643 |
+
**Required Analysis Structure:**
|
| 1644 |
+
|
| 1645 |
+
1. **Executive Summary**
|
| 1646 |
+
- Brief overview of the idea and its primary impacts
|
| 1647 |
+
- Key findings and overall assessment
|
| 1648 |
+
- Main recommendations for improvement
|
| 1649 |
+
|
| 1650 |
+
2. **Environmental Impact Assessment**
|
| 1651 |
+
- **Carbon Footprint & Climate Impact**
|
| 1652 |
+
- Greenhouse gas emissions (direct and indirect)
|
| 1653 |
+
- Energy consumption and renewable energy potential
|
| 1654 |
+
- Climate change mitigation or contribution
|
| 1655 |
+
|
| 1656 |
+
- **Resource Usage & Conservation**
|
| 1657 |
+
- Raw materials and natural resources required
|
| 1658 |
+
- Water usage and conservation opportunities
|
| 1659 |
+
- Land use and biodiversity considerations
|
| 1660 |
+
|
| 1661 |
+
- **Waste & Pollution Analysis**
|
| 1662 |
+
- Waste generation and management
|
| 1663 |
+
- Air, water, and soil pollution potential
|
| 1664 |
+
- Circular economy and recycling opportunities
|
| 1665 |
+
|
| 1666 |
+
- **Sustainability Metrics**
|
| 1667 |
+
- Long-term environmental viability
|
| 1668 |
+
- Ecosystem impact and restoration potential
|
| 1669 |
+
- Environmental compliance and standards
|
| 1670 |
+
|
| 1671 |
+
3. **Social Impact Assessment**
|
| 1672 |
+
- **Community Benefits & Engagement**
|
| 1673 |
+
- Direct benefits to local communities
|
| 1674 |
+
- Job creation and economic opportunities
|
| 1675 |
+
- Community participation and empowerment
|
| 1676 |
+
|
| 1677 |
+
- **Social Equity & Accessibility**
|
| 1678 |
+
- Inclusivity and equal access considerations
|
| 1679 |
+
- Impact on vulnerable or marginalized groups
|
| 1680 |
+
- Affordability and accessibility barriers
|
| 1681 |
+
|
| 1682 |
+
- **Health & Well-being**
|
| 1683 |
+
- Public health implications
|
| 1684 |
+
- Safety considerations and risk management
|
| 1685 |
+
- Quality of life improvements or concerns
|
| 1686 |
+
|
| 1687 |
+
- **Cultural & Social Considerations**
|
| 1688 |
+
- Cultural sensitivity and preservation
|
| 1689 |
+
- Social cohesion and community building
|
| 1690 |
+
- Educational and awareness opportunities
|
| 1691 |
+
|
| 1692 |
+
4. **Economic Impact & Viability**
|
| 1693 |
+
- **Cost-Benefit Analysis**
|
| 1694 |
+
- Implementation costs vs. long-term benefits
|
| 1695 |
+
- Return on investment for stakeholders
|
| 1696 |
+
- Economic sustainability assessment
|
| 1697 |
+
|
| 1698 |
+
- **Market & Economic Effects**
|
| 1699 |
+
- Market disruption or innovation potential
|
| 1700 |
+
- Economic development opportunities
|
| 1701 |
+
- Supply chain and economic ecosystem impact
|
| 1702 |
+
|
| 1703 |
+
5. **Ethical Considerations & Governance**
|
| 1704 |
+
- **Ethical Framework**
|
| 1705 |
+
- Fairness and justice considerations
|
| 1706 |
+
- Transparency and accountability measures
|
| 1707 |
+
- Stakeholder rights and responsibilities
|
| 1708 |
+
|
| 1709 |
+
- **Governance & Compliance**
|
| 1710 |
+
- Regulatory compliance requirements
|
| 1711 |
+
- Governance structures and oversight
|
| 1712 |
+
- Risk management and mitigation strategies
|
| 1713 |
+
|
| 1714 |
+
6. **Lifecycle Assessment**
|
| 1715 |
+
- **Short-term Impacts (0-2 years)**
|
| 1716 |
+
- Immediate environmental and social effects
|
| 1717 |
+
- Implementation challenges and opportunities
|
| 1718 |
+
|
| 1719 |
+
- **Medium-term Impacts (2-10 years)**
|
| 1720 |
+
- Scaling effects and broader adoption
|
| 1721 |
+
- Cumulative impact assessment
|
| 1722 |
+
|
| 1723 |
+
- **Long-term Impacts (10+ years)**
|
| 1724 |
+
- Generational and legacy effects
|
| 1725 |
+
- Systemic change potential
|
| 1726 |
+
|
| 1727 |
+
7. **Risk Analysis & Mitigation**
|
| 1728 |
+
- **Potential Negative Impacts**
|
| 1729 |
+
- Environmental risks and unintended consequences
|
| 1730 |
+
- Social risks and community concerns
|
| 1731 |
+
- Economic and financial risks
|
| 1732 |
+
|
| 1733 |
+
- **Mitigation Strategies**
|
| 1734 |
+
- Preventive measures and safeguards
|
| 1735 |
+
- Monitoring and evaluation systems
|
| 1736 |
+
- Adaptive management approaches
|
| 1737 |
+
|
| 1738 |
+
8. **Recommendations & Action Plan**
|
| 1739 |
+
- **Immediate Actions**
|
| 1740 |
+
- Priority improvements for environmental impact
|
| 1741 |
+
- Essential social safeguards and enhancements
|
| 1742 |
+
|
| 1743 |
+
- **Strategic Improvements**
|
| 1744 |
+
- Long-term sustainability enhancements
|
| 1745 |
+
- Stakeholder engagement strategies
|
| 1746 |
+
- Innovation and optimization opportunities
|
| 1747 |
+
|
| 1748 |
+
- **Success Metrics & Monitoring**
|
| 1749 |
+
- Key performance indicators (KPIs)
|
| 1750 |
+
- Monitoring and evaluation framework
|
| 1751 |
+
- Reporting and transparency measures
|
| 1752 |
+
|
| 1753 |
+
9. **Comparative Analysis**
|
| 1754 |
+
- **Alternative Approaches**
|
| 1755 |
+
- Comparison with existing solutions
|
| 1756 |
+
- Best practices and benchmarking
|
| 1757 |
+
|
| 1758 |
+
- **Innovation Potential**
|
| 1759 |
+
- Unique value proposition
|
| 1760 |
+
- Scalability and replication potential
|
| 1761 |
+
|
| 1762 |
+
10. **Conclusion & Overall Assessment**
|
| 1763 |
+
- **Impact Rating**
|
| 1764 |
+
- Environmental impact score and justification
|
| 1765 |
+
- Social impact score and justification
|
| 1766 |
+
- Overall sustainability rating
|
| 1767 |
+
|
| 1768 |
+
- **Final Recommendations**
|
| 1769 |
+
- Go/no-go recommendation with conditions
|
| 1770 |
+
- Priority areas for improvement
|
| 1771 |
+
- Next steps and implementation guidance
|
| 1772 |
+
|
| 1773 |
+
**Output Requirements:**
|
| 1774 |
+
- Use clear, professional language without technical jargon
|
| 1775 |
+
- Provide specific, actionable recommendations
|
| 1776 |
+
- Include quantitative estimates where possible
|
| 1777 |
+
- Ensure the analysis is balanced and objective
|
| 1778 |
+
- Format as clean text without any markdown symbols
|
| 1779 |
+
- Make the content comprehensive yet accessible
|
| 1780 |
+
- Focus on practical implementation guidance
|
| 1781 |
+
|
| 1782 |
+
**Tone:** Professional, analytical, and constructive. Provide honest assessment while offering practical solutions for improvement.
|
| 1783 |
+
|
| 1784 |
+
Generate the complete analysis as plain text without any formatting symbols.`;
|
| 1785 |
+
}
|
| 1786 |
+
|
| 1787 |
+
// Validation function
|
| 1788 |
+
function validateInputs() {
|
| 1789 |
+
const idea = document.getElementById('ideaInput').value.trim();
|
| 1790 |
+
|
| 1791 |
+
if (!idea) {
|
| 1792 |
+
document.getElementById('ideaInput').focus();
|
| 1793 |
+
throw new Error('Please enter your idea or project description for impact analysis');
|
| 1794 |
+
}
|
| 1795 |
+
|
| 1796 |
+
if (idea.length < 50) {
|
| 1797 |
+
document.getElementById('ideaInput').focus();
|
| 1798 |
+
throw new Error('Please provide at least 50 characters for meaningful impact analysis');
|
| 1799 |
+
}
|
| 1800 |
+
}
|
| 1801 |
+
|
| 1802 |
+
// Generate impact analysis
|
| 1803 |
+
document.getElementById('compareBtn').addEventListener('click', async function() {
|
| 1804 |
+
const button = this;
|
| 1805 |
+
const buttonText = document.getElementById('buttonText');
|
| 1806 |
+
const spinner = document.getElementById('spinner');
|
| 1807 |
+
const outputArea = document.getElementById('impactOutput');
|
| 1808 |
+
|
| 1809 |
+
try {
|
| 1810 |
+
// Validate inputs
|
| 1811 |
+
validateInputs();
|
| 1812 |
+
|
| 1813 |
+
// Update button state
|
| 1814 |
+
button.disabled = true;
|
| 1815 |
+
spinner.style.display = 'inline-block';
|
| 1816 |
+
buttonText.textContent = 'Analyzing Impact...';
|
| 1817 |
+
|
| 1818 |
+
// Clear previous output
|
| 1819 |
+
outputArea.textContent = '';
|
| 1820 |
+
|
| 1821 |
+
// Build prompt and call API
|
| 1822 |
+
const prompt = buildImpactPrompt();
|
| 1823 |
+
const result = await callAPI(prompt);
|
| 1824 |
+
|
| 1825 |
+
// Display result
|
| 1826 |
+
outputArea.textContent = result;
|
| 1827 |
+
|
| 1828 |
+
} catch (error) {
|
| 1829 |
+
showError(error.message);
|
| 1830 |
+
outputArea.textContent = '';
|
| 1831 |
+
} finally {
|
| 1832 |
+
// Reset button state
|
| 1833 |
+
button.disabled = false;
|
| 1834 |
+
spinner.style.display = 'none';
|
| 1835 |
+
buttonText.textContent = '🌱 Analyze Impact';
|
| 1836 |
+
}
|
| 1837 |
+
});
|
| 1838 |
+
|
| 1839 |
+
// Keyboard shortcut for generation
|
| 1840 |
+
document.addEventListener('keydown', function(e) {
|
| 1841 |
+
if (e.ctrlKey && e.key === 'Enter') {
|
| 1842 |
+
e.preventDefault();
|
| 1843 |
+
document.getElementById('compareBtn').click();
|
| 1844 |
+
}
|
| 1845 |
+
});
|
| 1846 |
+
|
| 1847 |
+
// Initialize app when DOM is loaded
|
| 1848 |
+
document.addEventListener('DOMContentLoaded', function() {
|
| 1849 |
+
initializeApp();
|
| 1850 |
+
});
|
| 1851 |
+
</script>
|
| 1852 |
+
</body>
|
| 1853 |
+
</html>
|
| 1854 |
+
|
📘 Teacher & Student Guide ImpactAn.txt
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
📘 Teacher & Student Guide: ImpactAnalyzer Pro
|
| 2 |
+
1. Purpose & Educational Value
|
| 3 |
+
ImpactAnalyzer Pro empowers teachers and students to analyze and improve the real-world impact of any idea or project, using a comprehensive framework covering environmental, social, economic, ethical, and risk dimensions.
|
| 4 |
+
|
| 5 |
+
2. Step-by-Step Instructions with Input Explanation and Sample
|
| 6 |
+
A. Access & Setup
|
| 7 |
+
Open the tool (local or Hugging Face Space).
|
| 8 |
+
|
| 9 |
+
Select your preferred language.
|
| 10 |
+
|
| 11 |
+
Enter your OpenAI API key (private, stored only in your browser).
|
| 12 |
+
|
| 13 |
+
B. Idea & Project Input
|
| 14 |
+
What to Write:
|
| 15 |
+
Describe the idea, project, product, service, or initiative you want to analyze.
|
| 16 |
+
|
| 17 |
+
Be clear about its purpose, who it’s for, and how it works.
|
| 18 |
+
|
| 19 |
+
Mention any specific features, locations, or technologies involved.
|
| 20 |
+
|
| 21 |
+
Why:
|
| 22 |
+
A detailed description ensures the AI can provide a highly relevant and actionable impact analysis.
|
| 23 |
+
|
| 24 |
+
Sample Input:
|
| 25 |
+
|
| 26 |
+
“A student-led campaign to eliminate single-use plastic bottles from our school by installing filtered water stations, encouraging reusable bottles, and launching awareness workshops for students and parents. The project will run for one academic year and aims to reduce plastic waste by 80%.”
|
| 27 |
+
|
| 28 |
+
C. Generating the Impact Analysis
|
| 29 |
+
Click “🌱 Analyze Impact”.
|
| 30 |
+
|
| 31 |
+
Wait for the AI to generate a comprehensive report (takes a few moments).
|
| 32 |
+
|
| 33 |
+
Review the output—organized by Executive Summary, Environmental Impact, Social Impact, Economic Viability, Ethics, Lifecycle, Risk, Recommendations, Comparative Analysis, and Conclusion.
|
| 34 |
+
|
| 35 |
+
D. Using the Report in Class or Projects
|
| 36 |
+
Reflection & Assessment:
|
| 37 |
+
Use the report to assess feasibility, identify risks, and improve your proposal.
|
| 38 |
+
|
| 39 |
+
Presentations:
|
| 40 |
+
Copy sections of the report for slide decks, written reports, or business pitches.
|
| 41 |
+
|
| 42 |
+
Peer Review:
|
| 43 |
+
Share with classmates or colleagues for feedback and comparison.
|
| 44 |
+
|
| 45 |
+
Revision:
|
| 46 |
+
Use actionable recommendations to revise or optimize your idea before implementation.
|
| 47 |
+
|
| 48 |
+
3. Classroom Applications & Project Ideas
|
| 49 |
+
Application Type How to Use in Class
|
| 50 |
+
STEM & Environmental Ed Analyze science fair, green tech, or sustainability projects
|
| 51 |
+
Social Studies/Civics Assess policy proposals, social enterprises, or campaigns
|
| 52 |
+
Business/Entrepreneurship Use for market analysis, business planning, or competitions
|
| 53 |
+
Ethics & PBL Examine real-world dilemmas and debate trade-offs
|
| 54 |
+
|
| 55 |
+
4. Best Practices & Tips
|
| 56 |
+
Be specific: The more detail in your input, the richer the analysis.
|
| 57 |
+
|
| 58 |
+
Iterate: Refine your idea, re-run analysis, and compare changes.
|
| 59 |
+
|
| 60 |
+
Leverage languages: Use multilingual output for international teams or ELLs.
|
| 61 |
+
|
| 62 |
+
Discuss limitations: Not all factors can be predicted—use as a starting point for critical discussion.
|
| 63 |
+
|
| 64 |
+
5. Troubleshooting & Support
|
| 65 |
+
API errors? Check your key and internet connection.
|
| 66 |
+
|
| 67 |
+
Output too general? Add more detail or clarify your idea in the input.
|
| 68 |
+
|
| 69 |
+
Translation issues? Clear cache and reload if needed.
|
| 70 |
+
|
| 71 |
+
Help: info@shiftmind.io | www.shiftmind.io
|
| 72 |
+
|
| 73 |
+
ImpactAnalyzer Pro helps every learner and educator unlock the true value and risks of their innovations—making sustainability and social impact practical, measurable, and accessible.
|