Hma47's picture
Upload 4 files
fb74069 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Cultural Intelligence Explorer - Global Edition with AI Analysis</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!-- Tailwind CSS -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- React & ReactDOM -->
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<!-- @babel/standalone -->
<script crossorigin src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<!-- Font Awesome for icons -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
html, body {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100%;
margin: 0;
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
}
.glass {
background: rgba(255, 255, 255, 0.9);
backdrop-filter: blur(15px);
border-radius: 1.5rem;
box-shadow: 0 8px 32px rgba(31, 38, 135, 0.37);
border: 1px solid rgba(255, 255, 255, 0.18);
}
.country-dropdown {
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
border-radius: 1rem;
padding: 1.5rem;
color: white;
margin-bottom: 2rem;
}
.dropdown-container {
position: relative;
width: 100%;
}
.dropdown-input {
width: 100%;
padding: 1rem;
border: 2px solid rgba(255,255,255,0.3);
border-radius: 0.75rem;
background: rgba(255,255,255,0.9);
color: #333;
font-size: 1rem;
cursor: pointer;
}
.dropdown-input:focus {
outline: none;
border-color: #fbbf24;
box-shadow: 0 0 0 3px rgba(251, 191, 36, 0.3);
}
.dropdown-list {
position: absolute;
top: 100%;
left: 0;
right: 0;
background: white;
border: 1px solid #e5e7eb;
border-radius: 0.75rem;
max-height: 300px;
overflow-y: auto;
z-index: 1000;
box-shadow: 0 10px 25px rgba(0,0,0,0.15);
}
.dropdown-item {
padding: 0.75rem 1rem;
cursor: pointer;
border-bottom: 1px solid #f3f4f6;
display: flex;
align-items: center;
gap: 0.75rem;
transition: background-color 0.2s;
}
.dropdown-item:hover {
background-color: #f8fafc;
}
.dropdown-item:last-child {
border-bottom: none;
}
.dropdown-item.highlighted {
background-color: #eff6ff;
}
.theme-card {
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
border-radius: 0.75rem;
padding: 1rem;
color: white;
cursor: pointer;
transition: all 0.3s ease;
border: 2px solid transparent;
text-align: center;
}
.theme-card:hover {
transform: scale(1.05);
border-color: rgba(255,255,255,0.5);
}
.theme-card.selected {
border-color: #fbbf24;
box-shadow: 0 0 15px rgba(251, 191, 36, 0.4);
}
.insight-section {
background: linear-gradient(135deg, #a8edea 0%, #fed6e3 100%);
border-radius: 1rem;
padding: 1.5rem;
margin: 1rem 0;
border-left: 4px solid #667eea;
}
.reflection-card {
background: rgba(255, 255, 255, 0.95);
border-radius: 1rem;
padding: 1.5rem;
margin: 1rem 0;
box-shadow: 0 4px 15px rgba(0,0,0,0.1);
border: 1px solid rgba(102, 126, 234, 0.2);
}
.analysis-table {
background: rgba(255, 255, 255, 0.98);
border-radius: 1rem;
overflow: hidden;
box-shadow: 0 8px 25px rgba(0,0,0,0.1);
border: 1px solid rgba(102, 126, 234, 0.2);
}
.analysis-table table {
width: 100%;
border-collapse: collapse;
}
.analysis-table th {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 1rem;
text-align: left;
font-weight: 600;
border-bottom: 2px solid rgba(255,255,255,0.2);
}
.analysis-table td {
padding: 1rem;
border-bottom: 1px solid #e5e7eb;
vertical-align: top;
}
.analysis-table tr:last-child td {
border-bottom: none;
}
.analysis-table tr:nth-child(even) {
background-color: #f8fafc;
}
.analysis-table tr:hover {
background-color: #eff6ff;
}
.insight-badge {
display: inline-block;
background: linear-gradient(135deg, #10b981 0%, #059669 100%);
color: white;
padding: 0.25rem 0.75rem;
border-radius: 1rem;
font-size: 0.75rem;
font-weight: 600;
margin: 0.25rem 0.25rem 0.25rem 0;
}
.comparison-badge {
display: inline-block;
background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
color: white;
padding: 0.25rem 0.75rem;
border-radius: 1rem;
font-size: 0.75rem;
font-weight: 600;
margin: 0.25rem 0.25rem 0.25rem 0;
}
.progress-bar {
background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
height: 6px;
border-radius: 3px;
transition: width 0.5s ease;
}
.typing-indicator {
display: inline-flex;
align-items: center;
gap: 4px;
}
.typing-dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: #667eea;
animation: typing 1.4s infinite ease-in-out;
}
.typing-dot:nth-child(1) { animation-delay: -0.32s; }
.typing-dot:nth-child(2) { animation-delay: -0.16s; }
@keyframes typing {
0%, 80%, 100% { transform: scale(0); opacity: 0.5; }
40% { transform: scale(1); opacity: 1; }
}
.fade-in {
animation: fadeIn 0.6s ease-in;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
.slide-in {
animation: slideIn 0.5s ease-out;
}
@keyframes slideIn {
from { opacity: 0; transform: translateX(-30px); }
to { opacity: 1; transform: translateX(0); }
}
/* Accessibility improvements */
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
button:focus, input:focus, textarea:focus, select:focus {
outline: 3px solid #fbbf24;
outline-offset: 2px;
}
.theme-card:focus {
outline: 3px solid #fbbf24;
outline-offset: 2px;
}
/* Responsive design */
@media (max-width: 768px) {
.theme-grid {
grid-template-columns: repeat(2, 1fr);
}
.analysis-table {
overflow-x: auto;
}
.analysis-table table {
min-width: 600px;
}
}
@media (max-width: 640px) {
.theme-grid {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
const { useState, useEffect, useCallback, useRef } = React;
// Comprehensive list of world countries with flags and regions
const WORLD_COUNTRIES = [
// Africa
{ id: 'algeria', name: 'Algeria', flag: '🇩🇿', region: 'North Africa' },
{ id: 'angola', name: 'Angola', flag: '🇦🇴', region: 'Central Africa' },
{ id: 'benin', name: 'Benin', flag: '🇧🇯', region: 'West Africa' },
{ id: 'botswana', name: 'Botswana', flag: '🇧🇼', region: 'Southern Africa' },
{ id: 'burkina-faso', name: 'Burkina Faso', flag: '🇧🇫', region: 'West Africa' },
{ id: 'burundi', name: 'Burundi', flag: '🇧🇮', region: 'East Africa' },
{ id: 'cameroon', name: 'Cameroon', flag: '🇨🇲', region: 'Central Africa' },
{ id: 'cape-verde', name: 'Cape Verde', flag: '🇨🇻', region: 'West Africa' },
{ id: 'chad', name: 'Chad', flag: '🇹🇩', region: 'Central Africa' },
{ id: 'comoros', name: 'Comoros', flag: '🇰🇲', region: 'East Africa' },
{ id: 'congo', name: 'Congo', flag: '🇨🇬', region: 'Central Africa' },
{ id: 'drc', name: 'Democratic Republic of Congo', flag: '🇨🇩', region: 'Central Africa' },
{ id: 'djibouti', name: 'Djibouti', flag: '🇩🇯', region: 'East Africa' },
{ id: 'egypt', name: 'Egypt', flag: '🇪🇬', region: 'North Africa' },
{ id: 'equatorial-guinea', name: 'Equatorial Guinea', flag: '🇬🇶', region: 'Central Africa' },
{ id: 'eritrea', name: 'Eritrea', flag: '🇪🇷', region: 'East Africa' },
{ id: 'eswatini', name: 'Eswatini', flag: '🇸🇿', region: 'Southern Africa' },
{ id: 'ethiopia', name: 'Ethiopia', flag: '🇪🇹', region: 'East Africa' },
{ id: 'gabon', name: 'Gabon', flag: '🇬🇦', region: 'Central Africa' },
{ id: 'gambia', name: 'Gambia', flag: '🇬🇲', region: 'West Africa' },
{ id: 'ghana', name: 'Ghana', flag: '🇬🇭', region: 'West Africa' },
{ id: 'guinea', name: 'Guinea', flag: '🇬🇳', region: 'West Africa' },
{ id: 'guinea-bissau', name: 'Guinea-Bissau', flag: '🇬🇼', region: 'West Africa' },
{ id: 'ivory-coast', name: 'Ivory Coast', flag: '🇨🇮', region: 'West Africa' },
{ id: 'kenya', name: 'Kenya', flag: '🇰🇪', region: 'East Africa' },
{ id: 'lesotho', name: 'Lesotho', flag: '🇱🇸', region: 'Southern Africa' },
{ id: 'liberia', name: 'Liberia', flag: '🇱🇷', region: 'West Africa' },
{ id: 'libya', name: 'Libya', flag: '🇱🇾', region: 'North Africa' },
{ id: 'madagascar', name: 'Madagascar', flag: '🇲🇬', region: 'East Africa' },
{ id: 'malawi', name: 'Malawi', flag: '🇲🇼', region: 'Southern Africa' },
{ id: 'mali', name: 'Mali', flag: '🇲🇱', region: 'West Africa' },
{ id: 'mauritania', name: 'Mauritania', flag: '🇲🇷', region: 'West Africa' },
{ id: 'mauritius', name: 'Mauritius', flag: '🇲🇺', region: 'East Africa' },
{ id: 'morocco', name: 'Morocco', flag: '🇲🇦', region: 'North Africa' },
{ id: 'mozambique', name: 'Mozambique', flag: '🇲🇿', region: 'Southern Africa' },
{ id: 'namibia', name: 'Namibia', flag: '🇳🇦', region: 'Southern Africa' },
{ id: 'niger', name: 'Niger', flag: '🇳🇪', region: 'West Africa' },
{ id: 'nigeria', name: 'Nigeria', flag: '🇳🇬', region: 'West Africa' },
{ id: 'rwanda', name: 'Rwanda', flag: '🇷🇼', region: 'East Africa' },
{ id: 'sao-tome', name: 'São Tomé and Príncipe', flag: '🇸🇹', region: 'Central Africa' },
{ id: 'senegal', name: 'Senegal', flag: '🇸🇳', region: 'West Africa' },
{ id: 'seychelles', name: 'Seychelles', flag: '🇸🇨', region: 'East Africa' },
{ id: 'sierra-leone', name: 'Sierra Leone', flag: '🇸🇱', region: 'West Africa' },
{ id: 'somalia', name: 'Somalia', flag: '🇸🇴', region: 'East Africa' },
{ id: 'south-africa', name: 'South Africa', flag: '🇿🇦', region: 'Southern Africa' },
{ id: 'south-sudan', name: 'South Sudan', flag: '🇸🇸', region: 'East Africa' },
{ id: 'sudan', name: 'Sudan', flag: '🇸🇩', region: 'North Africa' },
{ id: 'tanzania', name: 'Tanzania', flag: '🇹🇿', region: 'East Africa' },
{ id: 'togo', name: 'Togo', flag: '🇹🇬', region: 'West Africa' },
{ id: 'tunisia', name: 'Tunisia', flag: '🇹🇳', region: 'North Africa' },
{ id: 'uganda', name: 'Uganda', flag: '🇺🇬', region: 'East Africa' },
{ id: 'zambia', name: 'Zambia', flag: '🇿🇲', region: 'Southern Africa' },
{ id: 'zimbabwe', name: 'Zimbabwe', flag: '🇿🇼', region: 'Southern Africa' },
// Asia
{ id: 'afghanistan', name: 'Afghanistan', flag: '🇦🇫', region: 'Central Asia' },
{ id: 'armenia', name: 'Armenia', flag: '🇦🇲', region: 'Western Asia' },
{ id: 'azerbaijan', name: 'Azerbaijan', flag: '🇦🇿', region: 'Western Asia' },
{ id: 'bahrain', name: 'Bahrain', flag: '🇧🇭', region: 'Western Asia' },
{ id: 'bangladesh', name: 'Bangladesh', flag: '🇧🇩', region: 'South Asia' },
{ id: 'bhutan', name: 'Bhutan', flag: '🇧🇹', region: 'South Asia' },
{ id: 'brunei', name: 'Brunei', flag: '🇧🇳', region: 'Southeast Asia' },
{ id: 'cambodia', name: 'Cambodia', flag: '🇰🇭', region: 'Southeast Asia' },
{ id: 'china', name: 'China', flag: '🇨🇳', region: 'East Asia' },
{ id: 'cyprus', name: 'Cyprus', flag: '🇨🇾', region: 'Western Asia' },
{ id: 'georgia', name: 'Georgia', flag: '🇬🇪', region: 'Western Asia' },
{ id: 'india', name: 'India', flag: '🇮🇳', region: 'South Asia' },
{ id: 'indonesia', name: 'Indonesia', flag: '🇮🇩', region: 'Southeast Asia' },
{ id: 'iran', name: 'Iran', flag: '🇮🇷', region: 'Western Asia' },
{ id: 'iraq', name: 'Iraq', flag: '🇮🇶', region: 'Western Asia' },
{ id: 'israel', name: 'Israel', flag: '🇮🇱', region: 'Western Asia' },
{ id: 'japan', name: 'Japan', flag: '🇯🇵', region: 'East Asia' },
{ id: 'jordan', name: 'Jordan', flag: '🇯🇴', region: 'Western Asia' },
{ id: 'kazakhstan', name: 'Kazakhstan', flag: '🇰🇿', region: 'Central Asia' },
{ id: 'kuwait', name: 'Kuwait', flag: '🇰🇼', region: 'Western Asia' },
{ id: 'kyrgyzstan', name: 'Kyrgyzstan', flag: '🇰🇬', region: 'Central Asia' },
{ id: 'laos', name: 'Laos', flag: '🇱🇦', region: 'Southeast Asia' },
{ id: 'lebanon', name: 'Lebanon', flag: '🇱🇧', region: 'Western Asia' },
{ id: 'malaysia', name: 'Malaysia', flag: '🇲🇾', region: 'Southeast Asia' },
{ id: 'maldives', name: 'Maldives', flag: '🇲🇻', region: 'South Asia' },
{ id: 'mongolia', name: 'Mongolia', flag: '🇲🇳', region: 'East Asia' },
{ id: 'myanmar', name: 'Myanmar', flag: '🇲🇲', region: 'Southeast Asia' },
{ id: 'nepal', name: 'Nepal', flag: '🇳🇵', region: 'South Asia' },
{ id: 'north-korea', name: 'North Korea', flag: '🇰🇵', region: 'East Asia' },
{ id: 'oman', name: 'Oman', flag: '🇴🇲', region: 'Western Asia' },
{ id: 'pakistan', name: 'Pakistan', flag: '🇵🇰', region: 'South Asia' },
{ id: 'palestine', name: 'Palestine', flag: '🇵🇸', region: 'Western Asia' },
{ id: 'philippines', name: 'Philippines', flag: '🇵🇭', region: 'Southeast Asia' },
{ id: 'qatar', name: 'Qatar', flag: '🇶🇦', region: 'Western Asia' },
{ id: 'saudi-arabia', name: 'Saudi Arabia', flag: '🇸🇦', region: 'Western Asia' },
{ id: 'singapore', name: 'Singapore', flag: '🇸🇬', region: 'Southeast Asia' },
{ id: 'south-korea', name: 'South Korea', flag: '🇰🇷', region: 'East Asia' },
{ id: 'sri-lanka', name: 'Sri Lanka', flag: '🇱🇰', region: 'South Asia' },
{ id: 'syria', name: 'Syria', flag: '🇸🇾', region: 'Western Asia' },
{ id: 'taiwan', name: 'Taiwan', flag: '🇹🇼', region: 'East Asia' },
{ id: 'tajikistan', name: 'Tajikistan', flag: '🇹🇯', region: 'Central Asia' },
{ id: 'thailand', name: 'Thailand', flag: '🇹🇭', region: 'Southeast Asia' },
{ id: 'timor-leste', name: 'Timor-Leste', flag: '🇹🇱', region: 'Southeast Asia' },
{ id: 'turkey', name: 'Turkey', flag: '🇹🇷', region: 'Western Asia' },
{ id: 'turkmenistan', name: 'Turkmenistan', flag: '🇹🇲', region: 'Central Asia' },
{ id: 'uae', name: 'United Arab Emirates', flag: '🇦🇪', region: 'Western Asia' },
{ id: 'uzbekistan', name: 'Uzbekistan', flag: '🇺🇿', region: 'Central Asia' },
{ id: 'vietnam', name: 'Vietnam', flag: '🇻🇳', region: 'Southeast Asia' },
{ id: 'yemen', name: 'Yemen', flag: '🇾🇪', region: 'Western Asia' },
// Europe
{ id: 'albania', name: 'Albania', flag: '🇦🇱', region: 'Southern Europe' },
{ id: 'andorra', name: 'Andorra', flag: '🇦🇩', region: 'Southern Europe' },
{ id: 'austria', name: 'Austria', flag: '🇦🇹', region: 'Central Europe' },
{ id: 'belarus', name: 'Belarus', flag: '🇧🇾', region: 'Eastern Europe' },
{ id: 'belgium', name: 'Belgium', flag: '🇧🇪', region: 'Western Europe' },
{ id: 'bosnia', name: 'Bosnia and Herzegovina', flag: '🇧🇦', region: 'Southern Europe' },
{ id: 'bulgaria', name: 'Bulgaria', flag: '🇧🇬', region: 'Eastern Europe' },
{ id: 'croatia', name: 'Croatia', flag: '🇭🇷', region: 'Southern Europe' },
{ id: 'czech-republic', name: 'Czech Republic', flag: '🇨🇿', region: 'Central Europe' },
{ id: 'denmark', name: 'Denmark', flag: '🇩🇰', region: 'Northern Europe' },
{ id: 'estonia', name: 'Estonia', flag: '🇪🇪', region: 'Northern Europe' },
{ id: 'finland', name: 'Finland', flag: '🇫🇮', region: 'Northern Europe' },
{ id: 'france', name: 'France', flag: '🇫🇷', region: 'Western Europe' },
{ id: 'germany', name: 'Germany', flag: '🇩🇪', region: 'Central Europe' },
{ id: 'greece', name: 'Greece', flag: '🇬🇷', region: 'Southern Europe' },
{ id: 'hungary', name: 'Hungary', flag: '🇭🇺', region: 'Central Europe' },
{ id: 'iceland', name: 'Iceland', flag: '🇮🇸', region: 'Northern Europe' },
{ id: 'ireland', name: 'Ireland', flag: '🇮🇪', region: 'Northern Europe' },
{ id: 'italy', name: 'Italy', flag: '🇮🇹', region: 'Southern Europe' },
{ id: 'kosovo', name: 'Kosovo', flag: '🇽🇰', region: 'Southern Europe' },
{ id: 'latvia', name: 'Latvia', flag: '🇱🇻', region: 'Northern Europe' },
{ id: 'liechtenstein', name: 'Liechtenstein', flag: '🇱🇮', region: 'Central Europe' },
{ id: 'lithuania', name: 'Lithuania', flag: '🇱🇹', region: 'Northern Europe' },
{ id: 'luxembourg', name: 'Luxembourg', flag: '🇱🇺', region: 'Western Europe' },
{ id: 'malta', name: 'Malta', flag: '🇲🇹', region: 'Southern Europe' },
{ id: 'moldova', name: 'Moldova', flag: '🇲🇩', region: 'Eastern Europe' },
{ id: 'monaco', name: 'Monaco', flag: '🇲🇨', region: 'Western Europe' },
{ id: 'montenegro', name: 'Montenegro', flag: '🇲🇪', region: 'Southern Europe' },
{ id: 'netherlands', name: 'Netherlands', flag: '🇳🇱', region: 'Western Europe' },
{ id: 'north-macedonia', name: 'North Macedonia', flag: '🇲🇰', region: 'Southern Europe' },
{ id: 'norway', name: 'Norway', flag: '🇳🇴', region: 'Northern Europe' },
{ id: 'poland', name: 'Poland', flag: '🇵🇱', region: 'Central Europe' },
{ id: 'portugal', name: 'Portugal', flag: '🇵🇹', region: 'Southern Europe' },
{ id: 'romania', name: 'Romania', flag: '🇷🇴', region: 'Eastern Europe' },
{ id: 'russia', name: 'Russia', flag: '🇷🇺', region: 'Eastern Europe' },
{ id: 'san-marino', name: 'San Marino', flag: '🇸🇲', region: 'Southern Europe' },
{ id: 'serbia', name: 'Serbia', flag: '🇷🇸', region: 'Southern Europe' },
{ id: 'slovakia', name: 'Slovakia', flag: '🇸🇰', region: 'Central Europe' },
{ id: 'slovenia', name: 'Slovenia', flag: '🇸🇮', region: 'Central Europe' },
{ id: 'spain', name: 'Spain', flag: '🇪🇸', region: 'Southern Europe' },
{ id: 'sweden', name: 'Sweden', flag: '🇸🇪', region: 'Northern Europe' },
{ id: 'switzerland', name: 'Switzerland', flag: '🇨🇭', region: 'Central Europe' },
{ id: 'ukraine', name: 'Ukraine', flag: '🇺🇦', region: 'Eastern Europe' },
{ id: 'united-kingdom', name: 'United Kingdom', flag: '🇬🇧', region: 'Northern Europe' },
{ id: 'vatican', name: 'Vatican City', flag: '🇻🇦', region: 'Southern Europe' },
// North America
{ id: 'antigua', name: 'Antigua and Barbuda', flag: '🇦🇬', region: 'Caribbean' },
{ id: 'bahamas', name: 'Bahamas', flag: '🇧🇸', region: 'Caribbean' },
{ id: 'barbados', name: 'Barbados', flag: '🇧🇧', region: 'Caribbean' },
{ id: 'belize', name: 'Belize', flag: '🇧🇿', region: 'Central America' },
{ id: 'canada', name: 'Canada', flag: '🇨🇦', region: 'North America' },
{ id: 'costa-rica', name: 'Costa Rica', flag: '🇨🇷', region: 'Central America' },
{ id: 'cuba', name: 'Cuba', flag: '🇨🇺', region: 'Caribbean' },
{ id: 'dominica', name: 'Dominica', flag: '🇩🇲', region: 'Caribbean' },
{ id: 'dominican-republic', name: 'Dominican Republic', flag: '🇩🇴', region: 'Caribbean' },
{ id: 'el-salvador', name: 'El Salvador', flag: '🇸🇻', region: 'Central America' },
{ id: 'grenada', name: 'Grenada', flag: '🇬🇩', region: 'Caribbean' },
{ id: 'guatemala', name: 'Guatemala', flag: '🇬🇹', region: 'Central America' },
{ id: 'haiti', name: 'Haiti', flag: '🇭🇹', region: 'Caribbean' },
{ id: 'honduras', name: 'Honduras', flag: '🇭🇳', region: 'Central America' },
{ id: 'jamaica', name: 'Jamaica', flag: '🇯🇲', region: 'Caribbean' },
{ id: 'mexico', name: 'Mexico', flag: '🇲🇽', region: 'North America' },
{ id: 'nicaragua', name: 'Nicaragua', flag: '🇳🇮', region: 'Central America' },
{ id: 'panama', name: 'Panama', flag: '🇵🇦', region: 'Central America' },
{ id: 'saint-kitts', name: 'Saint Kitts and Nevis', flag: '🇰🇳', region: 'Caribbean' },
{ id: 'saint-lucia', name: 'Saint Lucia', flag: '🇱🇨', region: 'Caribbean' },
{ id: 'saint-vincent', name: 'Saint Vincent and the Grenadines', flag: '🇻🇨', region: 'Caribbean' },
{ id: 'trinidad', name: 'Trinidad and Tobago', flag: '🇹🇹', region: 'Caribbean' },
{ id: 'usa', name: 'United States', flag: '🇺🇸', region: 'North America' },
// South America
{ id: 'argentina', name: 'Argentina', flag: '🇦🇷', region: 'South America' },
{ id: 'bolivia', name: 'Bolivia', flag: '🇧🇴', region: 'South America' },
{ id: 'brazil', name: 'Brazil', flag: '🇧🇷', region: 'South America' },
{ id: 'chile', name: 'Chile', flag: '🇨🇱', region: 'South America' },
{ id: 'colombia', name: 'Colombia', flag: '🇨🇴', region: 'South America' },
{ id: 'ecuador', name: 'Ecuador', flag: '🇪🇨', region: 'South America' },
{ id: 'guyana', name: 'Guyana', flag: '🇬🇾', region: 'South America' },
{ id: 'paraguay', name: 'Paraguay', flag: '🇵🇾', region: 'South America' },
{ id: 'peru', name: 'Peru', flag: '🇵🇪', region: 'South America' },
{ id: 'suriname', name: 'Suriname', flag: '🇸🇷', region: 'South America' },
{ id: 'uruguay', name: 'Uruguay', flag: '🇺🇾', region: 'South America' },
{ id: 'venezuela', name: 'Venezuela', flag: '🇻🇪', region: 'South America' },
// Oceania
{ id: 'australia', name: 'Australia', flag: '🇦🇺', region: 'Oceania' },
{ id: 'fiji', name: 'Fiji', flag: '🇫🇯', region: 'Oceania' },
{ id: 'kiribati', name: 'Kiribati', flag: '🇰🇮', region: 'Oceania' },
{ id: 'marshall-islands', name: 'Marshall Islands', flag: '🇲🇭', region: 'Oceania' },
{ id: 'micronesia', name: 'Micronesia', flag: '🇫🇲', region: 'Oceania' },
{ id: 'nauru', name: 'Nauru', flag: '🇳🇷', region: 'Oceania' },
{ id: 'new-zealand', name: 'New Zealand', flag: '🇳🇿', region: 'Oceania' },
{ id: 'palau', name: 'Palau', flag: '🇵🇼', region: 'Oceania' },
{ id: 'papua-new-guinea', name: 'Papua New Guinea', flag: '🇵🇬', region: 'Oceania' },
{ id: 'samoa', name: 'Samoa', flag: '🇼🇸', region: 'Oceania' },
{ id: 'solomon-islands', name: 'Solomon Islands', flag: '🇸🇧', region: 'Oceania' },
{ id: 'tonga', name: 'Tonga', flag: '🇹🇴', region: 'Oceania' },
{ id: 'tuvalu', name: 'Tuvalu', flag: '🇹🇻', region: 'Oceania' },
{ id: 'vanuatu', name: 'Vanuatu', flag: '🇻🇺', region: 'Oceania' }
];
const THEMES = [
{
id: 'family',
name: 'Family Life',
icon: '👨‍👩‍👧‍👦',
description: 'Family structures, relationships, and traditions'
},
{
id: 'education',
name: 'Education',
icon: '📚',
description: 'Learning systems, values, and approaches to knowledge'
},
{
id: 'traditions',
name: 'Traditions & Festivals',
icon: '🎭',
description: 'Cultural celebrations, rituals, and customs'
},
{
id: 'communication',
name: 'Communication',
icon: '💬',
description: 'Language, non-verbal cues, and social interactions'
},
{
id: 'work',
name: 'Work & Business',
icon: '💼',
description: 'Professional culture, work ethics, and business practices'
},
{
id: 'food',
name: 'Food & Dining',
icon: '🍽️',
description: 'Culinary traditions, dining etiquette, and food culture'
},
{
id: 'values',
name: 'Core Values',
icon: '⭐',
description: 'Fundamental beliefs, principles, and worldviews'
},
{
id: 'challenges',
name: 'Modern Challenges',
icon: '🌍',
description: 'Contemporary issues and cultural adaptations'
}
];
const REFLECTION_PROMPTS = [
{
id: 'similarities',
question: 'What similarities did you discover between this culture and your own?',
icon: '🤝'
},
{
id: 'differences',
question: 'What differences surprised you the most?',
icon: '🔍'
},
{
id: 'assumptions',
question: 'What assumptions about this culture were challenged?',
icon: '💭'
},
{
id: 'learning',
question: 'What valuable lesson or practice could you adopt from this culture?',
icon: '💡'
},
{
id: 'empathy',
question: 'How has this exploration changed your perspective on cultural diversity?',
icon: '❤️'
}
];
// Country Dropdown Component
function CountryDropdown({ selectedCountry, onCountrySelect }) {
const [isOpen, setIsOpen] = useState(false);
const [searchTerm, setSearchTerm] = useState('');
const [highlightedIndex, setHighlightedIndex] = useState(-1);
const dropdownRef = useRef(null);
const inputRef = useRef(null);
const filteredCountries = WORLD_COUNTRIES.filter(country =>
country.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
country.region.toLowerCase().includes(searchTerm.toLowerCase())
);
useEffect(() => {
function handleClickOutside(event) {
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
setIsOpen(false);
setHighlightedIndex(-1);
}
}
document.addEventListener('mousedown', handleClickOutside);
return () => document.removeEventListener('mousedown', handleClickOutside);
}, []);
const handleInputChange = (e) => {
setSearchTerm(e.target.value);
setIsOpen(true);
setHighlightedIndex(-1);
};
const handleKeyDown = (e) => {
if (!isOpen) {
if (e.key === 'Enter' || e.key === 'ArrowDown') {
setIsOpen(true);
setHighlightedIndex(0);
}
return;
}
switch (e.key) {
case 'ArrowDown':
e.preventDefault();
setHighlightedIndex(prev =>
prev < filteredCountries.length - 1 ? prev + 1 : 0
);
break;
case 'ArrowUp':
e.preventDefault();
setHighlightedIndex(prev =>
prev > 0 ? prev - 1 : filteredCountries.length - 1
);
break;
case 'Enter':
e.preventDefault();
if (highlightedIndex >= 0 && filteredCountries[highlightedIndex]) {
handleCountrySelect(filteredCountries[highlightedIndex]);
}
break;
case 'Escape':
setIsOpen(false);
setHighlightedIndex(-1);
inputRef.current?.blur();
break;
}
};
const handleCountrySelect = (country) => {
onCountrySelect(country);
setSearchTerm('');
setIsOpen(false);
setHighlightedIndex(-1);
};
const displayValue = selectedCountry
? `${selectedCountry.flag} ${selectedCountry.name}`
: searchTerm;
return (
<div className="dropdown-container" ref={dropdownRef}>
<input
ref={inputRef}
type="text"
className="dropdown-input"
placeholder={selectedCountry ? `${selectedCountry.flag} ${selectedCountry.name}` : "Search for a country..."}
value={isOpen ? searchTerm : displayValue}
onChange={handleInputChange}
onKeyDown={handleKeyDown}
onFocus={() => setIsOpen(true)}
autoComplete="off"
aria-expanded={isOpen}
aria-haspopup="listbox"
role="combobox"
/>
{isOpen && (
<div className="dropdown-list" role="listbox">
{filteredCountries.length > 0 ? (
filteredCountries.map((country, index) => (
<div
key={country.id}
className={`dropdown-item ${index === highlightedIndex ? 'highlighted' : ''}`}
onClick={() => handleCountrySelect(country)}
role="option"
aria-selected={selectedCountry?.id === country.id}
>
<span className="text-xl">{country.flag}</span>
<div>
<div className="font-semibold text-gray-800">{country.name}</div>
<div className="text-sm text-gray-500">{country.region}</div>
</div>
</div>
))
) : (
<div className="dropdown-item text-gray-500">
No countries found matching "{searchTerm}"
</div>
)}
</div>
)}
</div>
);
}
function CulturalIntelligenceExplorer() {
// Core state
const [phase, setPhase] = useState(1); // 1: Selection, 2: Insights, 3: Reflection, 4: Analysis
const [selectedCountry, setSelectedCountry] = useState(null);
const [selectedTheme, setSelectedTheme] = useState(null);
const [apiKey, setApiKey] = useState('');
const [showApiKeyModal, setShowApiKeyModal] = useState(false);
// AI and insights state
const [insights, setInsights] = useState(null);
const [isGeneratingInsights, setIsGeneratingInsights] = useState(false);
const [aiError, setAiError] = useState('');
// Reflection state
const [reflections, setReflections] = useState({});
const [explorationHistory, setExplorationHistory] = useState([]);
// Analysis state
const [analysis, setAnalysis] = useState(null);
const [isGeneratingAnalysis, setIsGeneratingAnalysis] = useState(false);
// Load data from localStorage
useEffect(() => {
try {
const savedApiKey = localStorage.getItem('cultural-explorer-api-key');
const savedHistory = localStorage.getItem('cultural-explorer-history');
if (savedApiKey) {
setApiKey(savedApiKey);
}
if (savedHistory) {
setExplorationHistory(JSON.parse(savedHistory));
}
} catch (error) {
console.error('Error loading saved data:', error);
}
}, []);
// Save data to localStorage
useEffect(() => {
try {
if (apiKey) {
localStorage.setItem('cultural-explorer-api-key', apiKey);
}
} catch (error) {
console.error('Error saving API key:', error);
}
}, [apiKey]);
useEffect(() => {
try {
localStorage.setItem('cultural-explorer-history', JSON.stringify(explorationHistory));
} catch (error) {
console.error('Error saving history:', error);
}
}, [explorationHistory]);
const handleCountrySelect = (country) => {
setSelectedCountry(country);
};
const handleThemeSelect = (theme) => {
setSelectedTheme(theme);
};
const proceedToInsights = () => {
if (!selectedCountry) {
alert('Please select a country to explore');
return;
}
if (!apiKey) {
setShowApiKeyModal(true);
return;
}
setPhase(2);
generateInsights();
};
const generateInsights = async () => {
if (!apiKey || !selectedCountry) return;
setIsGeneratingInsights(true);
setAiError('');
try {
const prompt = createInsightPrompt();
const response = await callOpenAI(prompt);
setInsights(response);
} catch (error) {
console.error('Error generating insights:', error);
setAiError(`Failed to generate insights: ${error.message}`);
} finally {
setIsGeneratingInsights(false);
}
};
const createInsightPrompt = () => {
const country = selectedCountry;
const theme = selectedTheme;
return `You are a cultural intelligence educator helping students develop empathy and global citizenship. Provide comprehensive, respectful insights about ${country.name} culture.
${theme ? `Focus specifically on: ${theme.name} - ${theme.description}` : 'Provide a general cultural overview.'}
Structure your response with the following sections:
**CULTURAL OVERVIEW:**
Provide a respectful, nuanced introduction to ${country.name} culture, avoiding stereotypes.
**KEY CULTURAL VALUES:**
List and explain 4-5 core values that guide this culture.
**DAILY LIFE INSIGHTS:**
Describe how these values manifest in everyday life.
${theme ? `**${theme.name.toUpperCase()} FOCUS:**
Provide detailed insights about ${theme.description} in ${country.name} culture.` : ''}
**HISTORICAL CONTEXT:**
Brief background on how history shaped current cultural practices.
**MODERN ADAPTATIONS:**
How this culture navigates contemporary global challenges while preserving traditions.
**COMMON MISCONCEPTIONS:**
Address 2-3 common stereotypes or misconceptions about this culture.
**CULTURAL WISDOM:**
Share a meaningful lesson or perspective this culture offers to the world.
Keep the tone educational, respectful, and engaging. Use specific examples while avoiding overgeneralization. Aim for 800-1000 words total.`;
};
const callOpenAI = async (prompt) => {
if (!apiKey) {
throw new Error('API key not provided');
}
const response = await fetch('https://api.openai.com/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${apiKey.trim()}`
},
body: JSON.stringify({
model: 'gpt-4o-mini',
messages: [
{ role: 'system', content: 'You are a cultural intelligence educator focused on promoting empathy, understanding, and global citizenship.' },
{ role: 'user', content: prompt }
],
max_tokens: 1200,
temperature: 0.7
})
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({}));
throw new Error(`OpenAI API error: ${response.status} ${response.statusText}${errorData.error ? ` - ${errorData.error.message}` : ''}`);
}
const data = await response.json();
if (!data.choices || !data.choices[0] || !data.choices[0].message) {
throw new Error('Invalid response format from OpenAI API');
}
return data.choices[0].message.content;
};
const proceedToReflection = () => {
setPhase(3);
};
const handleReflectionChange = (promptId, value) => {
setReflections(prev => ({
...prev,
[promptId]: value
}));
};
const proceedToAnalysis = () => {
setPhase(4);
generateAnalysis();
};
const generateAnalysis = async () => {
if (!apiKey || !selectedCountry || !insights) return;
setIsGeneratingAnalysis(true);
setAiError('');
try {
const prompt = createAnalysisPrompt();
const response = await callOpenAI(prompt);
setAnalysis(response);
} catch (error) {
console.error('Error generating analysis:', error);
setAiError(`Failed to generate analysis: ${error.message}`);
} finally {
setIsGeneratingAnalysis(false);
}
};
const createAnalysisPrompt = () => {
const country = selectedCountry;
const theme = selectedTheme;
const reflectionText = Object.entries(reflections)
.map(([key, value]) => {
const prompt = REFLECTION_PROMPTS.find(p => p.id === key);
return `${prompt?.question}: ${value}`;
})
.join('\n\n');
return `You are a cultural intelligence educator analyzing a student's cultural exploration journey. Based on the cultural insights and student reflections below, provide a comprehensive analysis in a structured tabular format.
**CULTURAL CONTEXT:**
Country: ${country.name} (${country.region})
${theme ? `Focus Theme: ${theme.name} - ${theme.description}` : 'General cultural exploration'}
**CULTURAL INSIGHTS PROVIDED:**
${insights}
**STUDENT REFLECTIONS:**
${reflectionText}
**ANALYSIS REQUIREMENTS:**
Create a detailed analysis table with the following structure. Format your response as a structured table with clear rows and columns:
| Analysis Category | Cultural Theme Insights | Student Reflection Analysis | Comparison & Growth Indicators |
|-------------------|------------------------|----------------------------|-------------------------------|
| Cultural Understanding | [Key cultural insights from the theme] | [Analysis of student's understanding] | [Evidence of learning and growth] |
| Personal Connection | [How culture relates to universal themes] | [Student's personal connections made] | [Depth of empathy development] |
| Assumption Challenges | [Cultural misconceptions addressed] | [Student's assumption changes] | [Critical thinking evidence] |
| Learning Integration | [Key cultural lessons identified] | [Student's learning takeaways] | [Application potential] |
| Perspective Transformation | [Cultural wisdom shared] | [Student's perspective shifts] | [Global citizenship development] |
For each row, provide:
- 2-3 specific insights from the cultural theme
- Detailed analysis of the student's reflection quality and depth
- Evidence of learning, growth, and cultural intelligence development
- Specific examples and quotes from student responses where relevant
Keep the analysis educational, encouraging, and focused on cultural intelligence development. Highlight strengths and areas for continued growth.`;
};
const completeExploration = () => {
const exploration = {
id: Date.now(),
timestamp: new Date().toISOString(),
country: selectedCountry,
theme: selectedTheme,
insights: insights,
reflections: reflections,
analysis: analysis
};
setExplorationHistory(prev => [...prev, exploration]);
// Reset for new exploration
setPhase(1);
setSelectedCountry(null);
setSelectedTheme(null);
setInsights(null);
setReflections({});
setAnalysis(null);
setAiError('');
};
const validateApiKey = async (key) => {
try {
const response = await fetch('https://api.openai.com/v1/models', {
headers: {
'Authorization': `Bearer ${key.trim()}`
}
});
if (!response.ok) {
throw new Error('Invalid API key');
}
return true;
} catch (error) {
throw new Error('Invalid API key. Please check and try again.');
}
};
const handleApiKeySubmit = async (key) => {
try {
await validateApiKey(key);
setApiKey(key);
setShowApiKeyModal(false);
setPhase(2);
generateInsights();
} catch (error) {
setAiError(error.message);
}
};
const formatInsights = (content) => {
// Convert markdown-style formatting to HTML
let formatted = content
.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
.replace(/^• (.+)$/gm, '<li>$1</li>')
.replace(/^- (.+)$/gm, '<li>$1</li>')
.split('\n\n')
.map(paragraph => {
if (paragraph.includes('<li>')) {
return `<ul class="list-disc list-inside space-y-1">${paragraph}</ul>`;
}
return paragraph.trim() ? `<p class="mb-3">${paragraph.trim()}</p>` : '';
})
.join('');
return formatted;
};
const parseAnalysisTable = (content) => {
// Parse the AI response into a structured table format
const lines = content.split('\n').filter(line => line.trim());
const tableData = [];
let currentRow = null;
let inTable = false;
for (const line of lines) {
if (line.includes('|') && line.includes('Analysis Category')) {
inTable = true;
continue;
}
if (line.includes('|') && line.includes('---')) {
continue;
}
if (inTable && line.includes('|')) {
const cells = line.split('|').map(cell => cell.trim()).filter(cell => cell);
if (cells.length >= 4) {
tableData.push({
category: cells[0],
cultural: cells[1],
reflection: cells[2],
comparison: cells[3]
});
}
}
}
// If no table found, create a simple structure from the content
if (tableData.length === 0) {
const sections = content.split('\n\n');
sections.forEach((section, index) => {
if (section.trim()) {
tableData.push({
category: `Analysis ${index + 1}`,
cultural: section.substring(0, 200) + '...',
reflection: 'Detailed analysis provided',
comparison: 'Growth indicators identified'
});
}
});
}
return tableData;
};
const getProgressPercentage = () => {
return (phase / 4) * 100;
};
// API Key Modal Component
const ApiKeyModal = () => {
const [keyInput, setKeyInput] = useState('');
const [isValidating, setIsValidating] = useState(false);
const handleSubmit = async (e) => {
e.preventDefault();
if (!keyInput.trim()) return;
setIsValidating(true);
try {
await handleApiKeySubmit(keyInput);
} catch (error) {
// Error is handled in parent component
} finally {
setIsValidating(false);
}
};
return (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4">
<div className="glass p-6 max-w-md w-full">
<h3 className="text-xl font-bold text-gray-800 mb-4">🔑 OpenAI API Key Required</h3>
<p className="text-gray-600 mb-4">
To generate cultural insights, please provide your OpenAI API key.
This will be stored locally and used only for this application.
</p>
<form onSubmit={handleSubmit}>
<input
type="password"
value={keyInput}
onChange={(e) => setKeyInput(e.target.value)}
placeholder="sk-..."
className="w-full px-3 py-2 border rounded-lg mb-4"
autoFocus
/>
<div className="flex gap-2">
<button
type="submit"
disabled={!keyInput.trim() || isValidating}
className="flex-1 bg-blue-600 text-white py-2 rounded-lg hover:bg-blue-700 transition disabled:opacity-50"
>
{isValidating ? 'Validating...' : 'Continue'}
</button>
<button
type="button"
onClick={() => setShowApiKeyModal(false)}
className="px-4 py-2 bg-gray-300 text-gray-700 rounded-lg hover:bg-gray-400 transition"
>
Cancel
</button>
</div>
</form>
{aiError && (
<div className="mt-3 text-red-600 text-sm">{aiError}</div>
)}
<p className="text-xs text-gray-500 mt-3">
Get your API key at <a href="https://platform.openai.com/api-keys" target="_blank" rel="noopener noreferrer" className="text-blue-600 underline">OpenAI</a>
</p>
</div>
</div>
);
};
return (
<div className="min-h-screen py-6">
<div className="max-w-6xl mx-auto px-4">
{/* Header */}
<div className="glass p-6 mb-6 text-center">
<h1 className="text-4xl font-bold text-gray-800 mb-2">
🌍 Cultural Intelligence Explorer
</h1>
<p className="text-gray-600 mb-4">
Develop empathy and global citizenship through cultural exploration
</p>
<p className="text-sm text-blue-600 font-semibold">
Global Edition with AI Analysis - Explore any country in the world!
</p>
{/* Progress Bar */}
<div className="max-w-md mx-auto mt-4">
<div className="flex justify-between text-xs text-gray-500 mb-2">
<span className={phase >= 1 ? 'text-blue-600 font-semibold' : ''}>Selection</span>
<span className={phase >= 2 ? 'text-blue-600 font-semibold' : ''}>Insights</span>
<span className={phase >= 3 ? 'text-blue-600 font-semibold' : ''}>Reflection</span>
<span className={phase >= 4 ? 'text-blue-600 font-semibold' : ''}>Analysis</span>
</div>
<div className="w-full bg-gray-200 rounded-full h-2">
<div
className="progress-bar rounded-full h-2"
style={{ width: `${getProgressPercentage()}%` }}
></div>
</div>
</div>
</div>
{/* Phase 1: Cultural Selection */}
{phase === 1 && (
<div className="fade-in">
<div className="glass p-6 mb-6">
<h2 className="text-2xl font-bold text-gray-800 mb-4">
🎯 Phase 1: Choose Your Cultural Journey
</h2>
<p className="text-gray-600 mb-6">
Select any country in the world to explore and optionally choose a specific theme to focus on.
</p>
{/* Country Selection */}
<div className="mb-8">
<div className="country-dropdown">
<h3 className="text-xl font-semibold mb-4">🌎 Select a Country</h3>
<p className="text-sm opacity-90 mb-4">
Search from {WORLD_COUNTRIES.length} countries worldwide
</p>
<CountryDropdown
selectedCountry={selectedCountry}
onCountrySelect={handleCountrySelect}
/>
</div>
</div>
{/* Theme Selection */}
<div className="mb-8">
<h3 className="text-xl font-semibold text-gray-700 mb-4">
Choose a Focus Theme (Optional)
</h3>
<div className="grid grid-cols-2 md:grid-cols-4 gap-3 theme-grid">
{THEMES.map(theme => (
<div
key={theme.id}
className={`theme-card ${selectedTheme?.id === theme.id ? 'selected' : ''}`}
onClick={() => handleThemeSelect(selectedTheme?.id === theme.id ? null : theme)}
tabIndex={0}
role="button"
aria-pressed={selectedTheme?.id === theme.id}
onKeyPress={(e) => e.key === 'Enter' && handleThemeSelect(selectedTheme?.id === theme.id ? null : theme)}
>
<div className="text-2xl mb-2">{theme.icon}</div>
<h4 className="font-semibold text-sm">{theme.name}</h4>
<p className="text-xs opacity-80 mt-1">{theme.description}</p>
</div>
))}
</div>
</div>
{/* Selection Summary */}
{selectedCountry && (
<div className="bg-blue-50 border border-blue-200 rounded-lg p-4 mb-6">
<h4 className="font-semibold text-blue-800 mb-2">Your Selection:</h4>
<p className="text-blue-700">
<strong>{selectedCountry.flag} {selectedCountry.name}</strong> ({selectedCountry.region})
{selectedTheme && (
<span> - Focus: {selectedTheme.icon} {selectedTheme.name}</span>
)}
</p>
</div>
)}
{/* Continue Button */}
<div className="text-center">
<button
onClick={proceedToInsights}
disabled={!selectedCountry}
className="bg-gradient-to-r from-blue-600 to-purple-600 text-white px-8 py-3 rounded-lg font-semibold hover:from-blue-700 hover:to-purple-700 transition disabled:opacity-50 disabled:cursor-not-allowed"
>
Explore Culture 🚀
</button>
</div>
</div>
</div>
)}
{/* Phase 2: AI Cultural Insights */}
{phase === 2 && (
<div className="fade-in">
<div className="glass p-6 mb-6">
<div className="flex items-center justify-between mb-6">
<div>
<h2 className="text-2xl font-bold text-gray-800">
🧠 Phase 2: Cultural Insights
</h2>
<p className="text-gray-600">
Exploring {selectedCountry?.flag} {selectedCountry?.name} ({selectedCountry?.region})
{selectedTheme && ` - ${selectedTheme.icon} ${selectedTheme.name}`}
</p>
</div>
<button
onClick={() => setPhase(1)}
className="text-blue-600 hover:text-blue-800 transition"
>
← Back to Selection
</button>
</div>
{isGeneratingInsights && (
<div className="text-center py-12">
<div className="typing-indicator mb-4">
<span className="text-lg text-gray-600 mr-3">Generating cultural insights</span>
<div className="typing-dot"></div>
<div className="typing-dot"></div>
<div className="typing-dot"></div>
</div>
<p className="text-gray-500">This may take a moment...</p>
</div>
)}
{aiError && (
<div className="bg-red-50 border border-red-200 rounded-lg p-4 mb-6">
<h4 className="font-semibold text-red-800 mb-2">Error:</h4>
<p className="text-red-700">{aiError}</p>
<button
onClick={generateInsights}
className="mt-3 bg-red-600 text-white px-4 py-2 rounded hover:bg-red-700 transition"
>
Try Again
</button>
</div>
)}
{insights && (
<div className="slide-in">
<div className="insight-section">
<div
className="prose prose-lg max-w-none"
dangerouslySetInnerHTML={{ __html: formatInsights(insights) }}
/>
</div>
<div className="text-center mt-8">
<button
onClick={proceedToReflection}
className="bg-gradient-to-r from-green-600 to-blue-600 text-white px-8 py-3 rounded-lg font-semibold hover:from-green-700 hover:to-blue-700 transition"
>
Reflect on Learning 💭
</button>
</div>
</div>
)}
</div>
</div>
)}
{/* Phase 3: Reflection & Comparison */}
{phase === 3 && (
<div className="fade-in">
<div className="glass p-6 mb-6">
<div className="flex items-center justify-between mb-6">
<div>
<h2 className="text-2xl font-bold text-gray-800">
💭 Phase 3: Reflection & Growth
</h2>
<p className="text-gray-600">
Reflect on your cultural exploration and personal insights
</p>
</div>
<button
onClick={() => setPhase(2)}
className="text-blue-600 hover:text-blue-800 transition"
>
← Back to Insights
</button>
</div>
<div className="space-y-6">
{REFLECTION_PROMPTS.map(prompt => (
<div key={prompt.id} className="reflection-card">
<div className="flex items-start gap-3 mb-3">
<span className="text-2xl">{prompt.icon}</span>
<h3 className="font-semibold text-gray-800 flex-1">
{prompt.question}
</h3>
</div>
<textarea
value={reflections[prompt.id] || ''}
onChange={(e) => handleReflectionChange(prompt.id, e.target.value)}
placeholder="Share your thoughts and insights..."
className="w-full px-4 py-3 border border-gray-300 rounded-lg resize-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
rows={4}
/>
</div>
))}
</div>
<div className="text-center mt-8">
<button
onClick={proceedToAnalysis}
className="bg-gradient-to-r from-purple-600 to-pink-600 text-white px-8 py-3 rounded-lg font-semibold hover:from-purple-700 hover:to-pink-700 transition"
>
Generate AI Analysis 📊
</button>
</div>
</div>
</div>
)}
{/* Phase 4: AI Analysis & Comparison */}
{phase === 4 && (
<div className="fade-in">
<div className="glass p-6 mb-6">
<div className="flex items-center justify-between mb-6">
<div>
<h2 className="text-2xl font-bold text-gray-800">
📊 Phase 4: AI Analysis & Insights
</h2>
<p className="text-gray-600">
AI-powered comparison between cultural themes and your reflections
</p>
</div>
<button
onClick={() => setPhase(3)}
className="text-blue-600 hover:text-blue-800 transition"
>
← Back to Reflection
</button>
</div>
{isGeneratingAnalysis && (
<div className="text-center py-12">
<div className="typing-indicator mb-4">
<span className="text-lg text-gray-600 mr-3">Analyzing your cultural journey</span>
<div className="typing-dot"></div>
<div className="typing-dot"></div>
<div className="typing-dot"></div>
</div>
<p className="text-gray-500">Creating personalized insights...</p>
</div>
)}
{aiError && (
<div className="bg-red-50 border border-red-200 rounded-lg p-4 mb-6">
<h4 className="font-semibold text-red-800 mb-2">Error:</h4>
<p className="text-red-700">{aiError}</p>
<button
onClick={generateAnalysis}
className="mt-3 bg-red-600 text-white px-4 py-2 rounded hover:bg-red-700 transition"
>
Try Again
</button>
</div>
)}
{analysis && (
<div className="slide-in">
<div className="mb-6">
<h3 className="text-xl font-semibold text-gray-800 mb-4">
🎯 Cultural Intelligence Analysis
</h3>
<div className="bg-blue-50 border border-blue-200 rounded-lg p-4 mb-6">
<p className="text-blue-700">
<strong>Analysis for:</strong> {selectedCountry?.flag} {selectedCountry?.name}
{selectedTheme && ` - ${selectedTheme.icon} ${selectedTheme.name}`}
</p>
</div>
</div>
<div className="analysis-table mb-8">
<table>
<thead>
<tr>
<th className="w-1/4">Analysis Category</th>
<th className="w-1/4">Cultural Theme Insights</th>
<th className="w-1/4">Your Reflection Analysis</th>
<th className="w-1/4">Growth Indicators</th>
</tr>
</thead>
<tbody>
{parseAnalysisTable(analysis).map((row, index) => (
<tr key={index}>
<td className="font-semibold text-gray-800">
{row.category}
<div className="mt-2">
<span className="insight-badge">Cultural Insight</span>
</div>
</td>
<td className="text-gray-700">
{row.cultural}
</td>
<td className="text-gray-700">
{row.reflection}
<div className="mt-2">
<span className="comparison-badge">Personal Growth</span>
</div>
</td>
<td className="text-gray-700">
{row.comparison}
</td>
</tr>
))}
</tbody>
</table>
</div>
<div className="text-center mt-8">
<button
onClick={completeExploration}
className="bg-gradient-to-r from-green-600 to-teal-600 text-white px-8 py-3 rounded-lg font-semibold hover:from-green-700 hover:to-teal-700 transition"
>
Complete Exploration ✨
</button>
</div>
</div>
)}
</div>
</div>
)}
{/* Exploration History */}
{explorationHistory.length > 0 && (
<div className="glass p-6">
<h3 className="text-xl font-bold text-gray-800 mb-4">
📚 Your Cultural Journey
</h3>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{explorationHistory.slice(-6).map(exploration => (
<div key={exploration.id} className="bg-white rounded-lg p-4 border border-gray-200">
<div className="flex items-center gap-2 mb-2">
<span className="text-xl">{exploration.country.flag}</span>
<h4 className="font-semibold text-gray-800">{exploration.country.name}</h4>
</div>
<p className="text-xs text-gray-500 mb-1">{exploration.country.region}</p>
{exploration.theme && (
<p className="text-sm text-gray-600 mb-2">
{exploration.theme.icon} {exploration.theme.name}
</p>
)}
<div className="flex gap-1 mb-2">
<span className="insight-badge text-xs">Insights</span>
<span className="comparison-badge text-xs">Analysis</span>
</div>
<p className="text-xs text-gray-500">
{new Date(exploration.timestamp).toLocaleDateString()}
</p>
</div>
))}
</div>
<p className="text-center text-gray-500 mt-4">
{explorationHistory.length} culture{explorationHistory.length !== 1 ? 's' : ''} explored with AI analysis
</p>
</div>
)}
</div>
{/* API Key Modal */}
{showApiKeyModal && <ApiKeyModal />}
</div>
);
}
ReactDOM.createRoot(document.getElementById("root")).render(<CulturalIntelligenceExplorer />);
</script>
</body>
</html>