Spaces:
				
			
			
	
			
			
		Runtime error
		
	
	
	
			
			
	
	
	
	
		
		
		Runtime error
		
	Pawel
#1
pinned
by
						
pzarzycki
	
							
						- opened
							
					
- .gitattributes +0 -4
- .gitignore +2 -69
- Dockerfile +6 -3
- app.py +135 -787
- rag_utils.py +0 -31
- religions.csv +0 -109
- requirements.txt +2 -5
- static/design-tokens.css +0 -79
- static/images/Abstract Color Gradient.png +0 -3
- static/images/icon1.png +0 -3
- static/images/icon2.png +0 -3
- static/images/icon3.png +0 -3
- static/landing.css +0 -524
- static/script.js +33 -415
- static/style.css +191 -455
- static/video/Animation (Light theme).mp4 +0 -3
- templates/index.html +24 -136
- templates/landing.html +0 -109
    	
        .gitattributes
    CHANGED
    
    | @@ -33,7 +33,3 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text | |
| 33 | 
             
            *.zip filter=lfs diff=lfs merge=lfs -text
         | 
| 34 | 
             
            *.zst filter=lfs diff=lfs merge=lfs -text
         | 
| 35 | 
             
            *tfevents* filter=lfs diff=lfs merge=lfs -text
         | 
| 36 | 
            -
            *.png filter=lfs diff=lfs merge=lfs -text
         | 
| 37 | 
            -
            *.mp4 filter=lfs diff=lfs merge=lfs -text
         | 
| 38 | 
            -
            static/images/*.png filter=lfs diff=lfs merge=lfs -text
         | 
| 39 | 
            -
            static/video/*.mp4 filter=lfs diff=lfs merge=lfs -text
         | 
|  | |
| 33 | 
             
            *.zip filter=lfs diff=lfs merge=lfs -text
         | 
| 34 | 
             
            *.zst filter=lfs diff=lfs merge=lfs -text
         | 
| 35 | 
             
            *tfevents* filter=lfs diff=lfs merge=lfs -text
         | 
|  | |
|  | |
|  | |
|  | 
    	
        .gitignore
    CHANGED
    
    | @@ -1,70 +1,3 @@ | |
| 1 | 
            -
             | 
| 2 | 
             
            users_data.json
         | 
| 3 | 
            -
             | 
| 4 | 
            -
            # Environment Variables - Contains API Keys
         | 
| 5 | 
            -
            .env
         | 
| 6 | 
            -
             | 
| 7 | 
            -
            # Firebase Service Account Key - NEVER COMMIT THIS!
         | 
| 8 | 
            -
            serviceAccountKey.json
         | 
| 9 | 
            -
            *serviceAccountKey*.json
         | 
| 10 | 
            -
            firebase-adminsdk-*.json
         | 
| 11 | 
            -
             | 
| 12 | 
            -
            # Python Virtual Environment
         | 
| 13 | 
            -
            .venv/
         | 
| 14 | 
            -
            venv/
         | 
| 15 | 
            -
            env/
         | 
| 16 | 
            -
            ENV/
         | 
| 17 | 
            -
             | 
| 18 | 
            -
            # Python Cache
         | 
| 19 | 
            -
            __pycache__/
         | 
| 20 | 
            -
            *.py[cod]
         | 
| 21 | 
            -
            *$py.class
         | 
| 22 | 
            -
            *.so
         | 
| 23 | 
            -
             | 
| 24 | 
            -
            # Flask
         | 
| 25 | 
            -
            instance/
         | 
| 26 | 
            -
            .webassets-cache
         | 
| 27 | 
            -
             | 
| 28 | 
            -
            # IDE/Editor
         | 
| 29 | 
            -
            .vscode/
         | 
| 30 | 
            -
            .idea/
         | 
| 31 | 
            -
            *.swp
         | 
| 32 | 
            -
            *.swo
         | 
| 33 | 
            -
            *~
         | 
| 34 | 
            -
            .DS_Store
         | 
| 35 | 
            -
             | 
| 36 | 
            -
            # Logs
         | 
| 37 | 
            -
            *.log
         | 
| 38 | 
            -
             | 
| 39 | 
            -
            # Distribution / packaging
         | 
| 40 | 
            -
            .Python
         | 
| 41 | 
            -
            build/
         | 
| 42 | 
            -
            develop-eggs/
         | 
| 43 | 
            -
            dist/
         | 
| 44 | 
            -
            downloads/
         | 
| 45 | 
            -
            eggs/
         | 
| 46 | 
            -
            .eggs/
         | 
| 47 | 
            -
            lib/
         | 
| 48 | 
            -
            lib64/
         | 
| 49 | 
            -
            parts/
         | 
| 50 | 
            -
            sdist/
         | 
| 51 | 
            -
            var/
         | 
| 52 | 
            -
            wheels/
         | 
| 53 | 
            -
            *.egg-info/
         | 
| 54 | 
            -
            .installed.cfg
         | 
| 55 | 
            -
            *.egg
         | 
| 56 | 
            -
             | 
| 57 | 
            -
            # Testing
         | 
| 58 | 
            -
            .pytest_cache/
         | 
| 59 | 
            -
            .coverage
         | 
| 60 | 
            -
            htmlcov/
         | 
| 61 | 
            -
             | 
| 62 | 
            -
            # RAG test data
         | 
| 63 | 
            -
            rag_data/
         | 
| 64 | 
            -
             | 
| 65 | 
            -
            # Other
         | 
| 66 | 
            -
            *.bak
         | 
| 67 | 
            -
            *.tmp
         | 
| 68 | 
            -
             | 
| 69 | 
            -
            docs/
         | 
| 70 | 
            -
            etc/
         | 
|  | |
| 1 | 
            +
            .venv
         | 
| 2 | 
             
            users_data.json
         | 
| 3 | 
            +
            .vscode
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
    	
        Dockerfile
    CHANGED
    
    | @@ -11,8 +11,11 @@ RUN pip install --no-cache-dir --upgrade -r requirements.txt | |
| 11 |  | 
| 12 | 
             
            COPY --chown=user . /app
         | 
| 13 |  | 
| 14 | 
            -
            #  | 
| 15 | 
            -
             | 
|  | |
|  | |
|  | |
| 16 |  | 
| 17 | 
             
            # Run with Gunicorn
         | 
| 18 | 
            -
            CMD ["gunicorn", "-w", "1", "-b", "0.0.0.0: | 
|  | |
| 11 |  | 
| 12 | 
             
            COPY --chown=user . /app
         | 
| 13 |  | 
| 14 | 
            +
            # Install Flask
         | 
| 15 | 
            +
            RUN pip install flask gunicorn pymupdf tiktoken
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            # Expose default port
         | 
| 18 | 
            +
            EXPOSE 7860
         | 
| 19 |  | 
| 20 | 
             
            # Run with Gunicorn
         | 
| 21 | 
            +
            CMD ["gunicorn", "-w", "1", "-b", "0.0.0.0:7860", "app:app"]
         | 
    	
        app.py
    CHANGED
    
    | @@ -1,5 +1,6 @@ | |
| 1 | 
             
            """
         | 
| 2 | 
             
            Concept: Flask + HTML Integration - Spiritual Path Assessment Tool
         | 
|  | |
| 3 | 
             
            This app helps users discover which religious or spiritual path aligns with their 
         | 
| 4 | 
             
            beliefs, values, lifestyle, and background through an interactive questionnaire.
         | 
| 5 | 
             
            """
         | 
| @@ -9,294 +10,109 @@ from flask import Flask, render_template, request, jsonify, session, redirect, u | |
| 9 | 
             
            from werkzeug.security import generate_password_hash, check_password_hash
         | 
| 10 | 
             
            import json
         | 
| 11 | 
             
            import os
         | 
| 12 | 
            -
            import re
         | 
| 13 | 
            -
            import secrets
         | 
| 14 | 
             
            from dotenv import load_dotenv
         | 
| 15 | 
             
            from together import Together
         | 
| 16 | 
            -
            from rag_utils import load_religions_from_csv, prepare_religion_rag_context
         | 
| 17 | 
            -
            from openai import OpenAI
         | 
| 18 | 
            -
            import firebase_admin
         | 
| 19 | 
            -
            from firebase_admin import credentials, auth, firestore
         | 
| 20 |  | 
| 21 | 
             
            load_dotenv()
         | 
| 22 |  | 
| 23 | 
             
            app = Flask(__name__)
         | 
| 24 | 
            -
            app.secret_key =  | 
| 25 | 
            -
             | 
| 26 | 
            -
            # Session configuration for production deployment
         | 
| 27 | 
            -
            app.config['SESSION_COOKIE_SECURE'] = os.getenv('FLASK_ENV') == 'production'
         | 
| 28 | 
            -
            app.config['SESSION_COOKIE_HTTPONLY'] = True
         | 
| 29 | 
            -
            app.config['SESSION_COOKIE_SAMESITE'] = 'Lax'
         | 
| 30 | 
            -
            app.config['PERMANENT_SESSION_LIFETIME'] = 3600  # 1 hour
         | 
| 31 | 
            -
             | 
| 32 | 
            -
            # Initialize Firebase Admin SDK
         | 
| 33 | 
            -
            try:
         | 
| 34 | 
            -
                firebase_cred_path = os.getenv('FIREBASE_CREDENTIALS_PATH', 'serviceAccountKey.json')
         | 
| 35 | 
            -
                if os.path.exists(firebase_cred_path):
         | 
| 36 | 
            -
                    cred = credentials.Certificate(firebase_cred_path)
         | 
| 37 | 
            -
                    firebase_admin.initialize_app(cred)
         | 
| 38 | 
            -
                    db = firestore.client()
         | 
| 39 | 
            -
                    print("✅ Firebase initialized successfully")
         | 
| 40 | 
            -
                else:
         | 
| 41 | 
            -
                    print(f"⚠️ Firebase credentials not found at {firebase_cred_path}")
         | 
| 42 | 
            -
                    db = None
         | 
| 43 | 
            -
            except Exception as e:
         | 
| 44 | 
            -
                print(f"⚠️ Firebase initialization failed: {e}")
         | 
| 45 | 
            -
                db = None
         | 
| 46 | 
            -
             | 
| 47 | 
            -
            # Firebase Web Config (for frontend)
         | 
| 48 | 
            -
            FIREBASE_CONFIG = {
         | 
| 49 | 
            -
                'apiKey': os.getenv('FIREBASE_WEB_API_KEY'),
         | 
| 50 | 
            -
                'authDomain': os.getenv('FIREBASE_AUTH_DOMAIN'),
         | 
| 51 | 
            -
                'projectId': os.getenv('FIREBASE_PROJECT_ID'),
         | 
| 52 | 
            -
                'storageBucket': os.getenv('FIREBASE_STORAGE_BUCKET', f"{os.getenv('FIREBASE_PROJECT_ID')}.appspot.com"),
         | 
| 53 | 
            -
                'messagingSenderId': os.getenv('FIREBASE_MESSAGING_SENDER_ID'),
         | 
| 54 | 
            -
                'appId': os.getenv('FIREBASE_APP_ID')
         | 
| 55 | 
            -
            }
         | 
| 56 |  | 
| 57 | 
             
            # File to store user data - defaults to current directory (writable in Docker)
         | 
| 58 | 
            -
            # Keep for backward compatibility during transition
         | 
| 59 | 
             
            USERS_FILE = os.getenv("USERS_FILE", "users_data.json")
         | 
| 60 |  | 
| 61 | 
             
            # Together API for chatbot
         | 
| 62 | 
             
            TOGETHER_API_KEY = os.getenv("TOGETHER_API_KEY")
         | 
| 63 | 
             
            client = Together(api_key=TOGETHER_API_KEY) if TOGETHER_API_KEY else None
         | 
| 64 |  | 
| 65 | 
            -
            #  | 
| 66 | 
            -
            OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
         | 
| 67 | 
            -
            openai_client = OpenAI(api_key=OPENAI_API_KEY) if OPENAI_API_KEY else None
         | 
| 68 | 
            -
             | 
| 69 | 
            -
            # Load detailed religion data at startup
         | 
| 70 | 
            -
            RELIGIONS_CSV = load_religions_from_csv('religions.csv')
         | 
| 71 | 
            -
             | 
| 72 | 
            -
             | 
| 73 | 
            -
            # Aliases map inconsistent keys to canonical ones
         | 
| 74 | 
            -
            TRADITION_ALIASES = {
         | 
| 75 | 
            -
                "secular": "humanism",
         | 
| 76 | 
            -
                "secularism": "humanism",
         | 
| 77 | 
            -
                "spiritualism": "spiritual_not_religious",
         | 
| 78 | 
            -
                "wicca": "paganism",
         | 
| 79 | 
            -
                "zen": "buddhism",
         | 
| 80 | 
            -
                "pantheism": "paganism",
         | 
| 81 | 
            -
                "unitarian": "spiritual_not_religious",
         | 
| 82 | 
            -
                "deism": "agnosticism"
         | 
| 83 | 
            -
            }
         | 
| 84 | 
            -
             | 
| 85 | 
            -
            def canon(key):
         | 
| 86 | 
            -
                """Normalize tradition key to canonical form"""
         | 
| 87 | 
            -
                return TRADITION_ALIASES.get(key, key)
         | 
| 88 | 
            -
             | 
| 89 | 
            -
            # Question importance weights (higher = more significant)
         | 
| 90 | 
            -
            QUESTION_WEIGHTS = {
         | 
| 91 | 
            -
                1: 5,  # Nature of the divine (most fundamental)
         | 
| 92 | 
            -
                2: 3,  # Spiritual connection style
         | 
| 93 | 
            -
                3: 4,  # Afterlife beliefs
         | 
| 94 | 
            -
                4: 4,  # Moral/ethical foundation
         | 
| 95 | 
            -
                5: 3,  # Prayer practices
         | 
| 96 | 
            -
                6: 3,  # Ritual/practice style
         | 
| 97 | 
            -
                7: 3,  # Human-nature relationship
         | 
| 98 | 
            -
                8: 3,  # View on suffering
         | 
| 99 | 
            -
                9: 2   # Community importance
         | 
| 100 | 
            -
            }
         | 
| 101 | 
            -
             | 
| 102 | 
            -
            # Assessment Questions ----------------------------
         | 
| 103 | 
             
            QUESTIONS = [
         | 
| 104 | 
             
                {
         | 
| 105 | 
             
                    "id": 1,
         | 
| 106 | 
             
                    "question": "What is your view on the nature of the divine?",
         | 
| 107 | 
             
                    "options": {
         | 
| 108 | 
            -
                        "One supreme God who created everything": {
         | 
| 109 | 
            -
             | 
| 110 | 
            -
                        },
         | 
| 111 | 
            -
                        " | 
| 112 | 
            -
             | 
| 113 | 
            -
                        },
         | 
| 114 | 
            -
                        "A universal energy or force": {
         | 
| 115 | 
            -
                            "taoism": 5, "buddhism": 4, "new_age": 4, "spiritual_not_religious": 3
         | 
| 116 | 
            -
                        },
         | 
| 117 | 
            -
                        "No divine being, focus on human potential": {
         | 
| 118 | 
            -
                            "humanism": 5, "atheism": 5, "stoicism": 3, "confucianism": 2
         | 
| 119 | 
            -
                        },
         | 
| 120 | 
            -
                        "Uncertain or unknowable": {
         | 
| 121 | 
            -
                            "agnosticism": 5, "spiritual_not_religious": 2
         | 
| 122 | 
            -
                        }
         | 
| 123 | 
             
                    }
         | 
| 124 | 
             
                },
         | 
| 125 | 
             
                {
         | 
| 126 | 
             
                    "id": 2,
         | 
| 127 | 
             
                    "question": "How do you prefer to connect with spirituality?",
         | 
| 128 | 
             
                    "options": {
         | 
| 129 | 
            -
                        "Through organized worship and community": {
         | 
| 130 | 
            -
             | 
| 131 | 
            -
                        },
         | 
| 132 | 
            -
                        "Through  | 
| 133 | 
            -
             | 
| 134 | 
            -
                        },
         | 
| 135 | 
            -
                        "Through nature and natural cycles": {
         | 
| 136 | 
            -
                            "paganism": 5, "indigenous": 5, "shintoism": 4
         | 
| 137 | 
            -
                        },
         | 
| 138 | 
            -
                        "Through reason and philosophy": {
         | 
| 139 | 
            -
                            "stoicism": 5, "humanism": 4, "confucianism": 3
         | 
| 140 | 
            -
                        },
         | 
| 141 | 
            -
                        "I don't feel the need for spiritual connection": {
         | 
| 142 | 
            -
                            "atheism": 5, "humanism": 2
         | 
| 143 | 
            -
                        }
         | 
| 144 | 
             
                    }
         | 
| 145 | 
             
                },
         | 
| 146 | 
             
                {
         | 
| 147 | 
             
                    "id": 3,
         | 
| 148 | 
             
                    "question": "What is your belief about the afterlife?",
         | 
| 149 | 
             
                    "options": {
         | 
| 150 | 
            -
                        "Heaven or Hell based on faith/deeds": {
         | 
| 151 | 
            -
             | 
| 152 | 
            -
                        },
         | 
| 153 | 
            -
                        " | 
| 154 | 
            -
             | 
| 155 | 
            -
                        },
         | 
| 156 | 
            -
                        "Ancestral realm or spiritual world": {
         | 
| 157 | 
            -
                            "indigenous": 4, "paganism": 3, "shintoism": 3, "confucianism": 2
         | 
| 158 | 
            -
                        },
         | 
| 159 | 
            -
                        "No afterlife, this life is all there is": {
         | 
| 160 | 
            -
                            "atheism": 5, "humanism": 4, "stoicism": 2
         | 
| 161 | 
            -
                        },
         | 
| 162 | 
            -
                        "Unsure or open to possibilities": {
         | 
| 163 | 
            -
                            "agnosticism": 4, "new_age": 3, "spiritual_not_religious": 3
         | 
| 164 | 
            -
                        }
         | 
| 165 | 
             
                    }
         | 
| 166 | 
             
                },
         | 
| 167 | 
             
                {
         | 
| 168 | 
             
                    "id": 4,
         | 
| 169 | 
             
                    "question": "What guides your moral and ethical decisions?",
         | 
| 170 | 
             
                    "options": {
         | 
| 171 | 
            -
                        "Sacred texts and religious teachings": {
         | 
| 172 | 
            -
             | 
| 173 | 
            -
                        },
         | 
| 174 | 
            -
                        " | 
| 175 | 
            -
             | 
| 176 | 
            -
                        },
         | 
| 177 | 
            -
                        "Harmony with nature and balance": {
         | 
| 178 | 
            -
                            "taoism": 5, "indigenous": 4, "shintoism": 3, "paganism": 3
         | 
| 179 | 
            -
                        },
         | 
| 180 | 
            -
                        "Reason, empathy, and human rights": {
         | 
| 181 | 
            -
                            "humanism": 5, "atheism": 3, "stoicism": 3
         | 
| 182 | 
            -
                        },
         | 
| 183 | 
            -
                        "Personal intuition and inner wisdom": {
         | 
| 184 | 
            -
                            "spiritual_not_religious": 5, "new_age": 4
         | 
| 185 | 
            -
                        },
         | 
| 186 | 
            -
                        "Virtue, duty, and social harmony": {
         | 
| 187 | 
            -
                            "confucianism": 5, "stoicism": 4
         | 
| 188 | 
            -
                        }
         | 
| 189 | 
             
                    }
         | 
| 190 | 
             
                },
         | 
| 191 | 
             
                {
         | 
| 192 | 
             
                    "id": 5,
         | 
| 193 | 
            -
                    "question": " | 
| 194 | 
             
                    "options": {
         | 
| 195 | 
            -
                        " | 
| 196 | 
            -
             | 
| 197 | 
            -
                        },
         | 
| 198 | 
            -
                        " | 
| 199 | 
            -
             | 
| 200 | 
            -
                        },
         | 
| 201 | 
            -
                        "Daily meditation or mindfulness practice": {
         | 
| 202 | 
            -
                            "buddhism": 5, "hinduism": 4, "jainism": 4
         | 
| 203 | 
            -
                        },
         | 
| 204 | 
            -
                        "Occasional prayer or reflection when needed": {
         | 
| 205 | 
            -
                            "christianity": 2, "judaism": 2, "spiritual_not_religious": 3, "new_age": 2
         | 
| 206 | 
            -
                        },
         | 
| 207 | 
            -
                        "Meditation for inner peace, not religious practice": {
         | 
| 208 | 
            -
                            "stoicism": 3, "humanism": 2, "buddhism": 2
         | 
| 209 | 
            -
                        },
         | 
| 210 | 
            -
                        "I don't pray or meditate": {
         | 
| 211 | 
            -
                            "atheism": 4, "humanism": 3
         | 
| 212 | 
            -
                        }
         | 
| 213 | 
             
                    }
         | 
| 214 | 
             
                },
         | 
| 215 | 
             
                {
         | 
| 216 | 
             
                    "id": 6,
         | 
| 217 | 
            -
                    "question": "What role do rituals and ceremonies play in your life?",
         | 
| 218 | 
            -
                    "options": {
         | 
| 219 | 
            -
                        "Essential - weekly services and holy day observances": {
         | 
| 220 | 
            -
                            "christianity": 4, "islam": 4, "judaism": 5, "hinduism": 3
         | 
| 221 | 
            -
                        },
         | 
| 222 | 
            -
                        "Important - seasonal celebrations and nature rituals": {
         | 
| 223 | 
            -
                            "paganism": 5, "indigenous": 5, "shintoism": 4
         | 
| 224 | 
            -
                        },
         | 
| 225 | 
            -
                        "Helpful - personal rituals that feel meaningful": {
         | 
| 226 | 
            -
                            "new_age": 4, "spiritual_not_religious": 4, "hinduism": 2
         | 
| 227 | 
            -
                        },
         | 
| 228 | 
            -
                        "Minimal - prefer contemplation and philosophy": {
         | 
| 229 | 
            -
                            "stoicism": 4, "humanism": 3, "confucianism": 2, "agnosticism": 2
         | 
| 230 | 
            -
                        },
         | 
| 231 | 
            -
                        "None - I don't practice rituals": {
         | 
| 232 | 
            -
                            "atheism": 4, "humanism": 2
         | 
| 233 | 
            -
                        }
         | 
| 234 | 
            -
                    }
         | 
| 235 | 
            -
                },
         | 
| 236 | 
            -
                {
         | 
| 237 | 
            -
                    "id": 7,
         | 
| 238 | 
             
                    "question": "How do you view the relationship between humans and nature?",
         | 
| 239 | 
             
                    "options": {
         | 
| 240 | 
            -
                        "Humans are stewards of God's creation": {
         | 
| 241 | 
            -
             | 
| 242 | 
            -
                        },
         | 
| 243 | 
            -
                        " | 
| 244 | 
            -
             | 
| 245 | 
            -
                        },
         | 
| 246 | 
            -
                        "Nature itself is divine and should be revered": {
         | 
| 247 | 
            -
                            "paganism": 5, "indigenous": 4, "shintoism": 5, "taoism": 3
         | 
| 248 | 
            -
                        },
         | 
| 249 | 
            -
                        "Nature follows natural laws we can study": {
         | 
| 250 | 
            -
                            "atheism": 4, "humanism": 4, "stoicism": 2
         | 
| 251 | 
            -
                        },
         | 
| 252 | 
            -
                        "We should live in harmony with natural flow": {
         | 
| 253 | 
            -
                            "taoism": 5, "buddhism": 3, "shintoism": 3, "indigenous": 3
         | 
| 254 | 
            -
                        }
         | 
| 255 | 
             
                    }
         | 
| 256 | 
             
                },
         | 
| 257 | 
             
                {
         | 
| 258 | 
            -
                    "id":  | 
| 259 | 
             
                    "question": "What is your view on suffering and its purpose?",
         | 
| 260 | 
             
                    "options": {
         | 
| 261 | 
            -
                        "A test of faith or part of God's plan": {
         | 
| 262 | 
            -
             | 
| 263 | 
            -
                        },
         | 
| 264 | 
            -
                        " | 
| 265 | 
            -
             | 
| 266 | 
            -
                        },
         | 
| 267 | 
            -
                        "Karma from past actions and choices": {
         | 
| 268 | 
            -
                            "hinduism": 5, "sikhism": 4, "buddhism": 3, "jainism": 3
         | 
| 269 | 
            -
                        },
         | 
| 270 | 
            -
                        "Natural part of life without cosmic meaning": {
         | 
| 271 | 
            -
                            "atheism": 5, "humanism": 3, "stoicism": 2
         | 
| 272 | 
            -
                        },
         | 
| 273 | 
            -
                        "An opportunity for spiritual growth": {
         | 
| 274 | 
            -
                            "new_age": 4, "spiritual_not_religious": 3, "christianity": 2
         | 
| 275 | 
            -
                        },
         | 
| 276 | 
            -
                        "To be accepted with virtue and equanimity": {
         | 
| 277 | 
            -
                            "stoicism": 5, "buddhism": 2, "confucianism": 2
         | 
| 278 | 
            -
                        }
         | 
| 279 | 
             
                    }
         | 
| 280 | 
             
                },
         | 
| 281 | 
             
                {
         | 
| 282 | 
            -
                    "id":  | 
| 283 | 
             
                    "question": "How important is community in your spiritual life?",
         | 
| 284 | 
             
                    "options": {
         | 
| 285 | 
            -
                        "Very important  | 
| 286 | 
            -
             | 
| 287 | 
            -
                        },
         | 
| 288 | 
            -
                        " | 
| 289 | 
            -
             | 
| 290 | 
            -
                        },
         | 
| 291 | 
            -
                        "Community of like-minded spiritual seekers": {
         | 
| 292 | 
            -
                            "paganism": 4, "spiritual_not_religious": 4, "new_age": 3
         | 
| 293 | 
            -
                        },
         | 
| 294 | 
            -
                        "Not important - spirituality is deeply personal": {
         | 
| 295 | 
            -
                            "spiritual_not_religious": 3, "agnosticism": 3, "taoism": 2
         | 
| 296 | 
            -
                        },
         | 
| 297 | 
            -
                        "Prefer secular community over religious": {
         | 
| 298 | 
            -
                            "humanism": 4, "atheism": 4, "stoicism": 2
         | 
| 299 | 
            -
                        }
         | 
| 300 | 
             
                    }
         | 
| 301 | 
             
                }
         | 
| 302 | 
             
            ]
         | 
| @@ -316,60 +132,11 @@ RELIGIONS = { | |
| 316 | 
             
                "new_age": {"name": "New Age Spirituality", "description": "Eclectic approach emphasizing personal growth.", "practices": "Meditation, energy work, crystals, yoga", "core_beliefs": "Personal transformation, universal consciousness"},
         | 
| 317 | 
             
                "spiritual_not_religious": {"name": "Spiritual But Not Religious", "description": "Personal spirituality without organized religion.", "practices": "Personal practices, meditation, self-reflection", "core_beliefs": "Individual journey, authenticity, diverse wisdom"},
         | 
| 318 | 
             
                "sikhism": {"name": "Sikhism", "description": "One God emphasizing service, equality, and meditation.", "practices": "Prayer, meditation, community service, 5 Ks", "core_beliefs": "One God, equality, honest living, sharing"},
         | 
| 319 | 
            -
                "indigenous": {"name": "Indigenous Spirituality", "description": "Traditional practices honoring ancestors and land.", "practices": "Ceremonies, storytelling, seasonal rituals", "core_beliefs": "Land connection, ancestor veneration, reciprocity"} | 
| 320 | 
            -
                "jainism": {"name": "Jainism", "description": "Ancient path emphasizing non-violence and spiritual purification.", "practices": "Meditation, fasting, non-violence, self-discipline", "core_beliefs": "Ahimsa (non-violence), karma liberation, asceticism"},
         | 
| 321 | 
            -
                "shintoism": {"name": "Shinto", "description": "Japanese tradition honoring kami spirits and natural harmony.", "practices": "Shrine visits, purification rituals, festivals", "core_beliefs": "Kami reverence, purity, harmony with nature"},
         | 
| 322 | 
            -
                "stoicism": {"name": "Stoicism", "description": "Philosophy emphasizing virtue, reason, and acceptance of fate.", "practices": "Contemplation, virtue practice, rational thinking", "core_beliefs": "Virtue, reason, acceptance, inner peace"},
         | 
| 323 | 
            -
                "confucianism": {"name": "Confucianism", "description": "Philosophy emphasizing moral cultivation and social harmony.", "practices": "Ritual propriety, study, self-cultivation", "core_beliefs": "Filial piety, benevolence, social harmony"}
         | 
| 324 | 
             
            }
         | 
| 325 |  | 
| 326 | 
            -
             | 
| 327 | 
            -
            # ============================================================================
         | 
| 328 | 
            -
            # FIRESTORE HELPER FUNCTIONS
         | 
| 329 | 
            -
            # ============================================================================
         | 
| 330 | 
            -
             | 
| 331 | 
            -
            def get_user_by_uid(uid):
         | 
| 332 | 
            -
                """Get user data from Firestore by Firebase UID"""
         | 
| 333 | 
            -
                if not db:
         | 
| 334 | 
            -
                    return None
         | 
| 335 | 
            -
                try:
         | 
| 336 | 
            -
                    user_ref = db.collection('users').document(uid)
         | 
| 337 | 
            -
                    user_doc = user_ref.get()
         | 
| 338 | 
            -
                    if user_doc.exists:
         | 
| 339 | 
            -
                        return user_doc.to_dict()
         | 
| 340 | 
            -
                    return None
         | 
| 341 | 
            -
                except Exception as e:
         | 
| 342 | 
            -
                    print(f"Error getting user {uid}: {e}")
         | 
| 343 | 
            -
                    return None
         | 
| 344 | 
            -
             | 
| 345 | 
            -
            def create_or_update_user(uid, user_data):
         | 
| 346 | 
            -
                """Create or update user in Firestore"""
         | 
| 347 | 
            -
                if not db:
         | 
| 348 | 
            -
                    return False
         | 
| 349 | 
            -
                try:
         | 
| 350 | 
            -
                    user_ref = db.collection('users').document(uid)
         | 
| 351 | 
            -
                    user_ref.set(user_data, merge=True)
         | 
| 352 | 
            -
                    return True
         | 
| 353 | 
            -
                except Exception as e:
         | 
| 354 | 
            -
                    print(f"Error saving user {uid}: {e}")
         | 
| 355 | 
            -
                    return False
         | 
| 356 | 
            -
             | 
| 357 | 
            -
             | 
| 358 | 
            -
             | 
| 359 | 
            -
            def verify_firebase_token(id_token):
         | 
| 360 | 
            -
                """Verify Firebase ID token and return decoded token"""
         | 
| 361 | 
            -
                try:
         | 
| 362 | 
            -
                    decoded_token = auth.verify_id_token(id_token)
         | 
| 363 | 
            -
                    return decoded_token
         | 
| 364 | 
            -
                except Exception as e:
         | 
| 365 | 
            -
                    print(f"Token verification error: {e}")
         | 
| 366 | 
            -
                    return None
         | 
| 367 | 
            -
             | 
| 368 | 
            -
            # ============================================================================
         | 
| 369 | 
            -
            # LEGACY JSON FILE FUNCTIONS (for backward compatibility)
         | 
| 370 | 
            -
            # ============================================================================
         | 
| 371 | 
            -
             | 
| 372 | 
             
            def load_users():
         | 
|  | |
| 373 | 
             
                try:
         | 
| 374 | 
             
                    if os.path.exists(USERS_FILE):
         | 
| 375 | 
             
                        with open(USERS_FILE, 'r') as f:
         | 
| @@ -396,8 +163,6 @@ def initialize_default_user(): | |
| 396 | 
             
                if not users:  # Only create if no users exist
         | 
| 397 | 
             
                    users['test'] = {
         | 
| 398 | 
             
                        'password': generate_password_hash('test'),
         | 
| 399 | 
            -
                        'email': '[email protected]',
         | 
| 400 | 
            -
                        'verified': True,
         | 
| 401 | 
             
                        'answers': [],
         | 
| 402 | 
             
                        'results': []
         | 
| 403 | 
             
                    }
         | 
| @@ -405,115 +170,48 @@ def initialize_default_user(): | |
| 405 | 
             
                    print("✅ Default test user created (username: test, password: test)")
         | 
| 406 |  | 
| 407 | 
             
            def calculate_results(answers):
         | 
| 408 | 
            -
                """
         | 
| 409 | 
            -
                Calculate which spiritual paths align with user's answers
         | 
| 410 | 
            -
                Uses weighted scoring with canonical tradition keys and tie-breakers
         | 
| 411 | 
            -
                """
         | 
| 412 | 
             
                scores = {}
         | 
| 413 | 
            -
                coverage = {}  # Track number of questions contributing to each tradition (for tie-breaking)
         | 
| 414 |  | 
| 415 | 
            -
                # Calculate weighted scores
         | 
| 416 | 
             
                for answer in answers:
         | 
| 417 | 
             
                    question = next((q for q in QUESTIONS if q["id"] == answer["question_id"]), None)
         | 
| 418 | 
             
                    if question and answer["answer"] in question["options"]:
         | 
| 419 | 
            -
                         | 
| 420 | 
            -
                         | 
| 421 | 
            -
             | 
| 422 | 
            -
                        # Track which traditions are scored in this question (for tie-breaker)
         | 
| 423 | 
            -
                        touched_this_question = set()
         | 
| 424 | 
            -
                        
         | 
| 425 | 
            -
                        for tradition_key, base_points in points_map.items():
         | 
| 426 | 
            -
                            # Normalize tradition key to canonical form
         | 
| 427 | 
            -
                            canonical_key = canon(tradition_key)
         | 
| 428 | 
            -
                            
         | 
| 429 | 
            -
                            # Calculate weighted score
         | 
| 430 | 
            -
                            weighted_score = base_points * question_weight
         | 
| 431 | 
            -
                            scores[canonical_key] = scores.get(canonical_key, 0) + weighted_score
         | 
| 432 | 
            -
                            touched_this_question.add(canonical_key)
         | 
| 433 | 
            -
                        
         | 
| 434 | 
            -
                        # Update coverage count for tie-breaking
         | 
| 435 | 
            -
                        for key in touched_this_question:
         | 
| 436 | 
            -
                            coverage[key] = coverage.get(key, 0) + 1
         | 
| 437 | 
            -
                
         | 
| 438 | 
            -
                # Calculate maximum possible score for percentage calculation
         | 
| 439 | 
            -
                max_possible_score = 0
         | 
| 440 | 
            -
                for answer in answers:
         | 
| 441 | 
            -
                    question = next((q for q in QUESTIONS if q["id"] == answer["question_id"]), None)
         | 
| 442 | 
            -
                    if question:
         | 
| 443 | 
            -
                        # Find the highest point value among all options for this question
         | 
| 444 | 
            -
                        max_option_points = 0
         | 
| 445 | 
            -
                        for option_scores in question["options"].values():
         | 
| 446 | 
            -
                            if option_scores:
         | 
| 447 | 
            -
                                max_option_points = max(max_option_points, max(option_scores.values()))
         | 
| 448 | 
            -
                        
         | 
| 449 | 
            -
                        question_weight = QUESTION_WEIGHTS.get(answer["question_id"], 1)
         | 
| 450 | 
            -
                        max_possible_score += max_option_points * question_weight
         | 
| 451 |  | 
| 452 | 
            -
                # Sort by score | 
| 453 | 
            -
                 | 
| 454 | 
            -
                sorted_scores = sorted(
         | 
| 455 | 
            -
                    scores.items(),
         | 
| 456 | 
            -
                    key=lambda x: (x[1], coverage.get(x[0], 0)),
         | 
| 457 | 
            -
                    reverse=True
         | 
| 458 | 
            -
                )
         | 
| 459 |  | 
| 460 | 
            -
                #  | 
| 461 | 
             
                recommendations = []
         | 
| 462 | 
            -
                for  | 
| 463 | 
            -
                    if  | 
| 464 | 
            -
                         | 
| 465 | 
            -
                         | 
| 466 | 
            -
                        
         | 
| 467 | 
            -
                         | 
| 468 | 
            -
                        if max_possible_score > 0:
         | 
| 469 | 
            -
                            tradition_info["percentage"] = round((score / max_possible_score) * 100)
         | 
| 470 | 
            -
                        else:
         | 
| 471 | 
            -
                            tradition_info["percentage"] = 0
         | 
| 472 | 
            -
                        
         | 
| 473 | 
            -
                        recommendations.append(tradition_info)
         | 
| 474 | 
            -
                        
         | 
| 475 | 
            -
                        # Stop after top 3
         | 
| 476 | 
            -
                        if len(recommendations) == 3:
         | 
| 477 | 
            -
                            break
         | 
| 478 |  | 
| 479 | 
             
                return recommendations
         | 
| 480 |  | 
| 481 | 
             
            @app.route("/")
         | 
| 482 | 
            -
            def  | 
| 483 | 
            -
                 | 
| 484 | 
            -
             | 
| 485 | 
            -
            @app.route("/assessment")
         | 
| 486 | 
            -
            def assessment():
         | 
| 487 | 
            -
                # Check for Firebase user first, then legacy username
         | 
| 488 | 
            -
                user_id = session.get('user_id')
         | 
| 489 | 
            -
                username = session.get('username')
         | 
| 490 | 
            -
                
         | 
| 491 | 
            -
                if not user_id and not username:
         | 
| 492 | 
             
                    return redirect(url_for('login'))
         | 
| 493 |  | 
| 494 | 
            -
                 | 
| 495 | 
            -
                 | 
| 496 | 
            -
             | 
| 497 | 
            -
                    user_data = get_user_by_uid(user_id) or {}
         | 
| 498 | 
            -
                    display_name = session.get('email', 'User')
         | 
| 499 | 
            -
                    has_results = 'results' in user_data and user_data['results']
         | 
| 500 | 
            -
                else:
         | 
| 501 | 
            -
                    # Legacy user
         | 
| 502 | 
            -
                    users = load_users()
         | 
| 503 | 
            -
                    user_data = users.get(username, {})
         | 
| 504 | 
            -
                    display_name = username
         | 
| 505 | 
            -
                    has_results = 'results' in user_data and user_data['results']
         | 
| 506 |  | 
| 507 | 
             
                return render_template(
         | 
| 508 | 
             
                    "index.html", 
         | 
| 509 | 
             
                    title="Spiritual Path Finder", 
         | 
| 510 | 
            -
                    message=f"Welcome, { | 
| 511 | 
            -
                    username= | 
| 512 | 
             
                    logged_in=True,
         | 
| 513 | 
             
                    questions=QUESTIONS,
         | 
| 514 | 
             
                    has_results=has_results,
         | 
| 515 | 
            -
                    results=user_data.get('results', []) if has_results else [] | 
| 516 | 
            -
                    firebase_config=FIREBASE_CONFIG
         | 
| 517 | 
             
                )
         | 
| 518 |  | 
| 519 | 
             
            @app.route("/login", methods=["GET", "POST"])
         | 
| @@ -523,318 +221,85 @@ def login(): | |
| 523 | 
             
                        data = request.get_json()
         | 
| 524 | 
             
                        if not data:
         | 
| 525 | 
             
                            return jsonify({"success": False, "message": "Invalid request"}), 400
         | 
|  | |
|  | |
|  | |
| 526 |  | 
| 527 | 
            -
                         | 
| 528 | 
            -
             | 
| 529 |  | 
| 530 | 
            -
                         | 
| 531 | 
            -
             | 
| 532 | 
            -
                             | 
| 533 | 
            -
             | 
| 534 | 
            -
             | 
| 535 | 
            -
                            
         | 
| 536 | 
            -
                            uid = decoded_token['uid']
         | 
| 537 | 
            -
                            email = decoded_token.get('email', '')
         | 
| 538 | 
            -
                            
         | 
| 539 | 
            -
                            # Check if user exists in Firestore, create if not
         | 
| 540 | 
            -
                            user_data = get_user_by_uid(uid)
         | 
| 541 | 
            -
                            if not user_data:
         | 
| 542 | 
            -
                                # Create new user document
         | 
| 543 | 
            -
                                create_or_update_user(uid, {
         | 
| 544 | 
            -
                                    'email': email,
         | 
| 545 | 
            -
                                    'answers': [],
         | 
| 546 | 
            -
                                    'results': [],
         | 
| 547 | 
            -
                                    'created_at': firestore.SERVER_TIMESTAMP
         | 
| 548 | 
            -
                                })
         | 
| 549 | 
            -
                            
         | 
| 550 | 
            -
                            # Store UID in session
         | 
| 551 | 
            -
                            session['user_id'] = uid
         | 
| 552 | 
            -
                            session['email'] = email
         | 
| 553 | 
            -
                            session.permanent = True
         | 
| 554 | 
            -
                            return jsonify({"success": True})
         | 
| 555 | 
            -
                        else:
         | 
| 556 | 
            -
                            # Legacy username/password flow (backward compatibility)
         | 
| 557 | 
            -
                            username = data.get('username', '').strip()
         | 
| 558 | 
            -
                            password = data.get('password', '')
         | 
| 559 | 
            -
                            
         | 
| 560 | 
            -
                            if not username or not password:
         | 
| 561 | 
            -
                                return jsonify({"success": False, "message": "Username and password required"}), 400
         | 
| 562 | 
            -
                            
         | 
| 563 | 
            -
                            users = load_users()
         | 
| 564 | 
            -
                            if username not in users:
         | 
| 565 | 
            -
                                return jsonify({"success": False, "message": "Invalid credentials"}), 401
         | 
| 566 | 
            -
                            
         | 
| 567 | 
            -
                            user_data = users[username]
         | 
| 568 | 
            -
                            
         | 
| 569 | 
            -
                            # Check if email is verified
         | 
| 570 | 
            -
                            if not user_data.get('verified', True):
         | 
| 571 | 
            -
                                return jsonify({"success": False, "message": "Please verify your email first. Check your inbox."}), 403
         | 
| 572 | 
            -
                            
         | 
| 573 | 
            -
                            stored = user_data['password']
         | 
| 574 | 
            -
                            
         | 
| 575 | 
            -
                            # Try hash-based verification first
         | 
| 576 | 
            -
                            if stored.startswith(('scrypt:', 'pbkdf2:')):
         | 
| 577 | 
             
                                if check_password_hash(stored, password):
         | 
| 578 | 
             
                                    session['username'] = username
         | 
| 579 | 
            -
                                    session.permanent = True
         | 
| 580 | 
             
                                    return jsonify({"success": True})
         | 
| 581 | 
            -
                             | 
| 582 | 
            -
             | 
|  | |
|  | |
|  | |
| 583 | 
             
                                users[username]['password'] = generate_password_hash(password)
         | 
| 584 | 
             
                                if not save_users(users):
         | 
| 585 | 
             
                                    return jsonify({"success": False, "message": "Error saving data"}), 500
         | 
| 586 | 
             
                                session['username'] = username
         | 
| 587 | 
            -
                                session.permanent = True
         | 
| 588 | 
             
                                return jsonify({"success": True})
         | 
| 589 | 
            -
             | 
| 590 | 
            -
             | 
| 591 | 
             
                    except Exception as e:
         | 
| 592 | 
             
                        print(f"Login error: {e}")
         | 
| 593 | 
             
                        return jsonify({"success": False, "message": "Server error"}), 500
         | 
| 594 |  | 
| 595 | 
            -
                 | 
| 596 | 
            -
                return render_template("index.html", logged_in=False, is_signup=False, firebase_config=FIREBASE_CONFIG)
         | 
| 597 |  | 
| 598 | 
             
            @app.route("/signup", methods=["GET", "POST"])
         | 
| 599 | 
             
            def signup():
         | 
| 600 | 
            -
                if request.method == "POST":
         | 
| 601 | 
            -
                    try:
         | 
| 602 | 
            -
                        data = request.get_json()
         | 
| 603 | 
            -
                        if not data:
         | 
| 604 | 
            -
                            return jsonify({"success": False, "message": "Invalid request"}), 400
         | 
| 605 | 
            -
                        
         | 
| 606 | 
            -
                        # Firebase authentication - verify ID token from frontend
         | 
| 607 | 
            -
                        id_token = data.get('idToken')
         | 
| 608 | 
            -
                        
         | 
| 609 | 
            -
                        if id_token:
         | 
| 610 | 
            -
                            # Firebase signup flow (user already created by Firebase Auth on frontend)
         | 
| 611 | 
            -
                            decoded_token = verify_firebase_token(id_token)
         | 
| 612 | 
            -
                            if not decoded_token:
         | 
| 613 | 
            -
                                return jsonify({"success": False, "message": "Invalid authentication token"}), 401
         | 
| 614 | 
            -
                            
         | 
| 615 | 
            -
                            uid = decoded_token['uid']
         | 
| 616 | 
            -
                            email = decoded_token.get('email', '')
         | 
| 617 | 
            -
                            
         | 
| 618 | 
            -
                            # Create user document in Firestore
         | 
| 619 | 
            -
                            user_data = {
         | 
| 620 | 
            -
                                'email': email,
         | 
| 621 | 
            -
                                'answers': [],
         | 
| 622 | 
            -
                                'results': [],
         | 
| 623 | 
            -
                                'created_at': firestore.SERVER_TIMESTAMP
         | 
| 624 | 
            -
                            }
         | 
| 625 | 
            -
                            
         | 
| 626 | 
            -
                            if create_or_update_user(uid, user_data):
         | 
| 627 | 
            -
                                session['user_id'] = uid
         | 
| 628 | 
            -
                                session['email'] = email
         | 
| 629 | 
            -
                                session.permanent = True
         | 
| 630 | 
            -
                                return jsonify({
         | 
| 631 | 
            -
                                    "success": True,
         | 
| 632 | 
            -
                                    "message": "Account created successfully!"
         | 
| 633 | 
            -
                                })
         | 
| 634 | 
            -
                            else:
         | 
| 635 | 
            -
                                return jsonify({"success": False, "message": "Error creating user profile"}), 500
         | 
| 636 | 
            -
                        else:
         | 
| 637 | 
            -
                            # Legacy username/password flow (backward compatibility)
         | 
| 638 | 
            -
                            username = data.get('username', '').strip()
         | 
| 639 | 
            -
                            password = data.get('password', '')
         | 
| 640 | 
            -
                            email = data.get('email', '').strip().lower()
         | 
| 641 | 
            -
                            
         | 
| 642 | 
            -
                            if not username or not password:
         | 
| 643 | 
            -
                                return jsonify({"success": False, "message": "Username and password required"}), 400
         | 
| 644 | 
            -
                            
         | 
| 645 | 
            -
                            if not email:
         | 
| 646 | 
            -
                                return jsonify({"success": False, "message": "Email is required"}), 400
         | 
| 647 | 
            -
                            
         | 
| 648 | 
            -
                            if not validate_email(email):
         | 
| 649 | 
            -
                                return jsonify({"success": False, "message": "Invalid email format"}), 400
         | 
| 650 | 
            -
                            
         | 
| 651 | 
            -
                            users = load_users()
         | 
| 652 | 
            -
                            
         | 
| 653 | 
            -
                            if username in users:
         | 
| 654 | 
            -
                                return jsonify({"success": False, "message": "Username already exists"}), 409
         | 
| 655 | 
            -
                            
         | 
| 656 | 
            -
                            # Check if email already exists
         | 
| 657 | 
            -
                            for user_data in users.values():
         | 
| 658 | 
            -
                                if user_data.get('email') == email:
         | 
| 659 | 
            -
                                    return jsonify({"success": False, "message": "Email already registered"}), 409
         | 
| 660 | 
            -
                            
         | 
| 661 | 
            -
                            # Generate verification token
         | 
| 662 | 
            -
                            token = secrets.token_urlsafe(32)
         | 
| 663 | 
            -
                            VERIFICATION_TOKENS[token] = {
         | 
| 664 | 
            -
                                'username': username,
         | 
| 665 | 
            -
                                'email': email,
         | 
| 666 | 
            -
                                'password': password,
         | 
| 667 | 
            -
                                'timestamp': os.path.getmtime(USERS_FILE) if os.path.exists(USERS_FILE) else 0
         | 
| 668 | 
            -
                            }
         | 
| 669 | 
            -
                            
         | 
| 670 | 
            -
                            # Send verification email
         | 
| 671 | 
            -
                            send_verification_email(email, token)
         | 
| 672 | 
            -
                            
         | 
| 673 | 
            -
                            # Create user with verified status (auto-verify in dev mode)
         | 
| 674 | 
            -
                            users[username] = {
         | 
| 675 | 
            -
                                'password': generate_password_hash(password),
         | 
| 676 | 
            -
                                'email': email,
         | 
| 677 | 
            -
                                'verified': True,  # Auto-verify in dev mode
         | 
| 678 | 
            -
                                'answers': [],
         | 
| 679 | 
            -
                                'results': []
         | 
| 680 | 
            -
                            }
         | 
| 681 | 
            -
                            
         | 
| 682 | 
            -
                            if not save_users(users):
         | 
| 683 | 
            -
                                return jsonify({"success": False, "message": "Error saving user data"}), 500
         | 
| 684 | 
            -
                                
         | 
| 685 | 
            -
                            return jsonify({
         | 
| 686 | 
            -
                                "success": True, 
         | 
| 687 | 
            -
                                "message": "Account created! Please check your email to verify your account.",
         | 
| 688 | 
            -
                                "verification_sent": True
         | 
| 689 | 
            -
                            })
         | 
| 690 | 
            -
                    except Exception as e:
         | 
| 691 | 
            -
                        print(f"Signup error: {e}")
         | 
| 692 | 
            -
                        return jsonify({"success": False, "message": "Server error"}), 500
         | 
| 693 | 
            -
                
         | 
| 694 | 
            -
                # Pass Firebase config to template
         | 
| 695 | 
            -
                return render_template("index.html", logged_in=False, is_signup=True, firebase_config=FIREBASE_CONFIG)
         | 
| 696 | 
            -
             | 
| 697 | 
            -
            @app.route("/forgot-password", methods=["GET", "POST"])
         | 
| 698 | 
            -
            def forgot_password():
         | 
| 699 | 
             
                if request.method == "POST":
         | 
| 700 | 
             
                    try:
         | 
| 701 | 
             
                        data = request.get_json()
         | 
| 702 | 
             
                        if not data:
         | 
| 703 | 
             
                            return jsonify({"success": False, "message": "Invalid request"}), 400
         | 
| 704 |  | 
| 705 | 
            -
                         | 
|  | |
| 706 |  | 
| 707 | 
            -
                        if not  | 
| 708 | 
            -
                            return jsonify({"success": False, "message": " | 
| 709 | 
            -
                        
         | 
| 710 | 
            -
                        if not validate_email(email):
         | 
| 711 | 
            -
                            return jsonify({"success": False, "message": "Invalid email format"}), 400
         | 
| 712 |  | 
| 713 | 
             
                        users = load_users()
         | 
| 714 |  | 
| 715 | 
            -
                         | 
| 716 | 
            -
             | 
| 717 | 
            -
                        for username, user_data in users.items():
         | 
| 718 | 
            -
                            if user_data.get('email') == email:
         | 
| 719 | 
            -
                                user_found = username
         | 
| 720 | 
            -
                                break
         | 
| 721 | 
            -
                        
         | 
| 722 | 
            -
                        if not user_found:
         | 
| 723 | 
            -
                            # Don't reveal that email doesn't exist (security best practice)
         | 
| 724 | 
            -
                            return jsonify({
         | 
| 725 | 
            -
                                "success": True, 
         | 
| 726 | 
            -
                                "message": "If that email exists, a reset link has been sent."
         | 
| 727 | 
            -
                            })
         | 
| 728 |  | 
| 729 | 
            -
                        #  | 
| 730 | 
            -
                         | 
| 731 | 
            -
             | 
| 732 | 
            -
                            ' | 
| 733 | 
            -
                            ' | 
| 734 | 
            -
                            'type': 'password_reset',
         | 
| 735 | 
            -
                            'timestamp': os.path.getmtime(USERS_FILE) if os.path.exists(USERS_FILE) else 0
         | 
| 736 | 
             
                        }
         | 
| 737 |  | 
| 738 | 
            -
                         | 
| 739 | 
            -
             | 
| 740 | 
            -
             | 
| 741 | 
            -
                         | 
| 742 | 
            -
             | 
| 743 | 
            -
                            "message": "Password reset link sent to your email. Please check your inbox."
         | 
| 744 | 
            -
                        })
         | 
| 745 | 
             
                    except Exception as e:
         | 
| 746 | 
            -
                        print(f" | 
| 747 | 
             
                        return jsonify({"success": False, "message": "Server error"}), 500
         | 
| 748 |  | 
| 749 | 
            -
                return render_template("index.html", logged_in=False, is_signup= | 
| 750 | 
            -
             | 
| 751 | 
            -
            @app.route("/reset-password")
         | 
| 752 | 
            -
            def reset_password_page():
         | 
| 753 | 
            -
                """Handle password reset via token - show form to enter new password"""
         | 
| 754 | 
            -
                token = request.args.get('token')
         | 
| 755 | 
            -
                if not token or token not in VERIFICATION_TOKENS:
         | 
| 756 | 
            -
                    return render_template("index.html", logged_in=False, is_signup=False, 
         | 
| 757 | 
            -
                                         reset_error="Invalid or expired reset token"), 400
         | 
| 758 | 
            -
                
         | 
| 759 | 
            -
                token_data = VERIFICATION_TOKENS[token]
         | 
| 760 | 
            -
                if token_data.get('type') != 'password_reset':
         | 
| 761 | 
            -
                    return render_template("index.html", logged_in=False, is_signup=False, 
         | 
| 762 | 
            -
                                         reset_error="Invalid token type"), 400
         | 
| 763 | 
            -
                
         | 
| 764 | 
            -
                # Store token in session temporarily for password reset form
         | 
| 765 | 
            -
                session['reset_token'] = token
         | 
| 766 | 
            -
                return render_template("index.html", logged_in=False, is_signup=False, 
         | 
| 767 | 
            -
                                     show_reset_form=True, reset_token=token)
         | 
| 768 | 
            -
             | 
| 769 | 
            -
            @app.route("/reset-password-submit", methods=["POST"])
         | 
| 770 | 
            -
            def reset_password_submit():
         | 
| 771 | 
            -
                """Handle password reset submission"""
         | 
| 772 | 
            -
                try:
         | 
| 773 | 
            -
                    data = request.get_json()
         | 
| 774 | 
            -
                    token = data.get('token')
         | 
| 775 | 
            -
                    new_password = data.get('password', '')
         | 
| 776 | 
            -
                    
         | 
| 777 | 
            -
                    if not token or token not in VERIFICATION_TOKENS:
         | 
| 778 | 
            -
                        return jsonify({"success": False, "message": "Invalid or expired token"}), 400
         | 
| 779 | 
            -
                    
         | 
| 780 | 
            -
                    if not new_password:
         | 
| 781 | 
            -
                        return jsonify({"success": False, "message": "Password is required"}), 400
         | 
| 782 | 
            -
                    
         | 
| 783 | 
            -
                    token_data = VERIFICATION_TOKENS[token]
         | 
| 784 | 
            -
                    if token_data.get('type') != 'password_reset':
         | 
| 785 | 
            -
                        return jsonify({"success": False, "message": "Invalid token type"}), 400
         | 
| 786 | 
            -
                    
         | 
| 787 | 
            -
                    # Reset password
         | 
| 788 | 
            -
                    users = load_users()
         | 
| 789 | 
            -
                    username = token_data['username']
         | 
| 790 | 
            -
                    if username in users:
         | 
| 791 | 
            -
                        users[username]['password'] = generate_password_hash(new_password)
         | 
| 792 | 
            -
                        save_users(users)
         | 
| 793 | 
            -
                        del VERIFICATION_TOKENS[token]
         | 
| 794 | 
            -
                        session.pop('reset_token', None)
         | 
| 795 | 
            -
                        return jsonify({"success": True, "message": "Password reset successfully"})
         | 
| 796 | 
            -
                    
         | 
| 797 | 
            -
                    return jsonify({"success": False, "message": "User not found"}), 404
         | 
| 798 | 
            -
                except Exception as e:
         | 
| 799 | 
            -
                    print(f"Password reset submit error: {e}")
         | 
| 800 | 
            -
                    return jsonify({"success": False, "message": "Server error"}), 500
         | 
| 801 | 
            -
             | 
| 802 | 
            -
            @app.route("/verify-email")
         | 
| 803 | 
            -
            def verify_email():
         | 
| 804 | 
            -
                """Handle email verification"""
         | 
| 805 | 
            -
                token = request.args.get('token')
         | 
| 806 | 
            -
                if not token or token not in VERIFICATION_TOKENS:
         | 
| 807 | 
            -
                    return render_template("index.html", logged_in=False, is_signup=False, 
         | 
| 808 | 
            -
                                         verify_error="Invalid or expired verification token"), 400
         | 
| 809 | 
            -
                
         | 
| 810 | 
            -
                token_data = VERIFICATION_TOKENS[token]
         | 
| 811 | 
            -
                users = load_users()
         | 
| 812 | 
            -
                username = token_data['username']
         | 
| 813 | 
            -
                
         | 
| 814 | 
            -
                if username in users:
         | 
| 815 | 
            -
                    users[username]['verified'] = True
         | 
| 816 | 
            -
                    save_users(users)
         | 
| 817 | 
            -
                    del VERIFICATION_TOKENS[token]
         | 
| 818 | 
            -
                    return render_template("index.html", logged_in=False, is_signup=False, 
         | 
| 819 | 
            -
                                         verify_success=True)
         | 
| 820 | 
            -
                
         | 
| 821 | 
            -
                return render_template("index.html", logged_in=False, is_signup=False, 
         | 
| 822 | 
            -
                                     verify_error="User not found"), 404
         | 
| 823 |  | 
| 824 | 
             
            @app.route("/logout")
         | 
| 825 | 
             
            def logout():
         | 
| 826 | 
            -
                # Clear both Firebase and legacy session data
         | 
| 827 | 
            -
                session.pop('user_id', None)
         | 
| 828 | 
            -
                session.pop('email', None)
         | 
| 829 | 
             
                session.pop('username', None)
         | 
| 830 | 
            -
                return redirect(url_for(' | 
| 831 |  | 
| 832 | 
             
            @app.route("/submit_assessment", methods=["POST"])
         | 
| 833 | 
             
            def submit_assessment():
         | 
| 834 | 
            -
                 | 
| 835 | 
            -
                username = session.get('username')
         | 
| 836 | 
            -
                
         | 
| 837 | 
            -
                if not user_id and not username:
         | 
| 838 | 
             
                    return jsonify({"success": False, "message": "Not logged in"})
         | 
| 839 |  | 
| 840 | 
             
                data = request.json
         | 
| @@ -846,63 +311,34 @@ def submit_assessment(): | |
| 846 | 
             
                # Calculate results
         | 
| 847 | 
             
                results = calculate_results(answers)
         | 
| 848 |  | 
| 849 | 
            -
                # Save to  | 
| 850 | 
            -
                 | 
| 851 | 
            -
             | 
| 852 | 
            -
                     | 
| 853 | 
            -
                     | 
| 854 | 
            -
             | 
| 855 | 
            -
             | 
| 856 | 
            -
                        'updated_at': firestore.SERVER_TIMESTAMP
         | 
| 857 | 
            -
                    })
         | 
| 858 | 
             
                    return jsonify({"success": True, "results": results})
         | 
| 859 | 
            -
                else:
         | 
| 860 | 
            -
                    # Legacy user - save to JSON
         | 
| 861 | 
            -
                    users = load_users()
         | 
| 862 | 
            -
                    if username in users:
         | 
| 863 | 
            -
                        users[username]['answers'] = answers
         | 
| 864 | 
            -
                        users[username]['results'] = results
         | 
| 865 | 
            -
                        save_users(users)
         | 
| 866 | 
            -
                        return jsonify({"success": True, "results": results})
         | 
| 867 |  | 
| 868 | 
             
                return jsonify({"success": False, "message": "User not found"})
         | 
| 869 |  | 
| 870 | 
             
            @app.route("/reset_assessment", methods=["POST"])
         | 
| 871 | 
             
            def reset_assessment():
         | 
| 872 | 
            -
                 | 
| 873 | 
            -
                username = session.get('username')
         | 
| 874 | 
            -
                
         | 
| 875 | 
            -
                if not user_id and not username:
         | 
| 876 | 
             
                    return jsonify({"success": False, "message": "Not logged in"})
         | 
| 877 |  | 
| 878 | 
            -
                 | 
| 879 | 
            -
                if  | 
| 880 | 
            -
                     | 
| 881 | 
            -
                     | 
| 882 | 
            -
                     | 
| 883 | 
            -
                        'answers': [],
         | 
| 884 | 
            -
                        'results': [],
         | 
| 885 | 
            -
                        'updated_at': firestore.SERVER_TIMESTAMP
         | 
| 886 | 
            -
                    })
         | 
| 887 | 
             
                    return jsonify({"success": True})
         | 
| 888 | 
            -
                else:
         | 
| 889 | 
            -
                    # Legacy user - reset in JSON
         | 
| 890 | 
            -
                    users = load_users()
         | 
| 891 | 
            -
                    if username in users:
         | 
| 892 | 
            -
                        users[username]['answers'] = []
         | 
| 893 | 
            -
                        users[username]['results'] = []
         | 
| 894 | 
            -
                        save_users(users)
         | 
| 895 | 
            -
                        return jsonify({"success": True})
         | 
| 896 |  | 
| 897 | 
             
                return jsonify({"success": False, "message": "User not found"})
         | 
| 898 |  | 
| 899 | 
             
            @app.route("/chat", methods=["POST"])
         | 
| 900 | 
             
            def chat():
         | 
| 901 | 
            -
                 | 
| 902 | 
            -
                RAG-enhanced chat endpoint for spiritual guidance
         | 
| 903 | 
            -
                Uses retrieval-augmented generation with religion-specific context
         | 
| 904 | 
            -
                """
         | 
| 905 | 
            -
                if 'user_id' not in session and 'username' not in session:
         | 
| 906 | 
             
                    return jsonify({"success": False, "message": "Not logged in"})
         | 
| 907 |  | 
| 908 | 
             
                if not client:
         | 
| @@ -916,65 +352,37 @@ def chat(): | |
| 916 | 
             
                if not user_message or not religion_name:
         | 
| 917 | 
             
                    return jsonify({"success": False, "message": "Message and religion required"})
         | 
| 918 |  | 
| 919 | 
            -
                # Find religion  | 
| 920 | 
             
                religion_data = None
         | 
| 921 | 
            -
                religion_key = None
         | 
| 922 | 
            -
                
         | 
| 923 | 
             
                for key, value in RELIGIONS.items():
         | 
| 924 | 
             
                    if value['name'] == religion_name:
         | 
| 925 | 
            -
                         | 
| 926 | 
            -
                        # Use CSV data if available
         | 
| 927 | 
            -
                        if key in RELIGIONS_CSV:
         | 
| 928 | 
            -
                            religion_data = RELIGIONS_CSV[key]
         | 
| 929 | 
            -
                        else:
         | 
| 930 | 
            -
                            religion_data = value
         | 
| 931 | 
             
                        break
         | 
| 932 |  | 
| 933 | 
             
                if not religion_data:
         | 
| 934 | 
             
                    return jsonify({"success": False, "message": "Religion not found"})
         | 
| 935 |  | 
| 936 | 
            -
                #  | 
| 937 | 
            -
                 | 
| 938 | 
            -
             | 
| 939 | 
            -
             | 
| 940 | 
            -
                    context_chunks = prepare_religion_rag_context(csv_data)
         | 
| 941 | 
            -
                    context = f"""REFERENCE DATA FOR {csv_data['name']}:
         | 
| 942 | 
            -
             | 
| 943 | 
            -
            {context_chunks[0]}"""
         | 
| 944 | 
            -
                else:
         | 
| 945 | 
            -
                    # Fallback to basic data
         | 
| 946 | 
            -
                    basic_context = prepare_religion_rag_context(religion_data)
         | 
| 947 | 
            -
                    context = f"""REFERENCE DATA FOR {religion_data['name']}:
         | 
| 948 | 
            -
             | 
| 949 | 
            -
            {basic_context[0]}"""
         | 
| 950 | 
            -
                
         | 
| 951 | 
            -
                system_prompt = f"""You're a knowledgeable spiritual guide. Use the reference data below to answer questions.
         | 
| 952 | 
            -
             | 
| 953 | 
            -
            {context}
         | 
| 954 |  | 
| 955 | 
            -
             | 
| 956 | 
            -
            - Keep responses concise, minimal. 30-60 words, depending on the context
         | 
| 957 | 
            -
            - ALWAYS complete your sentences - never cut off mid-sentence
         | 
| 958 | 
            -
            - Be respectful and accurate
         | 
| 959 | 
            -
            - If unsure, say so
         | 
| 960 | 
            -
            - Use * for bullet points if listing
         | 
| 961 | 
            -
            - End responses with complete thoughts, not incomplete phrases
         | 
| 962 | 
            -
            - If you need to cut information, end with "..." but complete the current sentence"""
         | 
| 963 | 
            -
             | 
| 964 | 
            -
                # Build conversation
         | 
| 965 | 
             
                messages = [{"role": "system", "content": system_prompt}]
         | 
| 966 |  | 
| 967 | 
            -
                # Add  | 
| 968 | 
            -
                for msg in chat_history[- | 
| 969 | 
             
                    messages.append({"role": msg["role"], "content": msg["content"]})
         | 
| 970 |  | 
|  | |
| 971 | 
             
                messages.append({"role": "user", "content": user_message})
         | 
| 972 |  | 
| 973 | 
             
                try:
         | 
|  | |
| 974 | 
             
                    response = client.chat.completions.create(
         | 
| 975 | 
             
                        model="meta-llama/Meta-Llama-3-8B-Instruct-Lite",
         | 
| 976 | 
             
                        messages=messages,
         | 
| 977 | 
            -
                        max_tokens= | 
| 978 | 
             
                        temperature=0.7,
         | 
| 979 | 
             
                    )
         | 
| 980 |  | 
| @@ -991,68 +399,8 @@ INSTRUCTIONS: | |
| 991 | 
             
                        "message": f"Chat error: {str(e)}"
         | 
| 992 | 
             
                    })
         | 
| 993 |  | 
| 994 | 
            -
            @app.route("/transcribe", methods=["POST"])
         | 
| 995 | 
            -
            def transcribe():
         | 
| 996 | 
            -
                """Convert audio to text using Whisper"""
         | 
| 997 | 
            -
                if 'username' not in session:
         | 
| 998 | 
            -
                    return jsonify({"success": False, "message": "Not logged in"})
         | 
| 999 | 
            -
                
         | 
| 1000 | 
            -
                if not openai_client:
         | 
| 1001 | 
            -
                    return jsonify({"success": False, "message": "Whisper not configured"})
         | 
| 1002 | 
            -
                
         | 
| 1003 | 
            -
                audio_file = request.files.get('audio')
         | 
| 1004 | 
            -
                if not audio_file:
         | 
| 1005 | 
            -
                    return jsonify({"success": False, "message": "No audio file"})
         | 
| 1006 | 
            -
                
         | 
| 1007 | 
            -
                try:
         | 
| 1008 | 
            -
                    # Convert FileStorage to bytes
         | 
| 1009 | 
            -
                    audio_bytes = audio_file.read()
         | 
| 1010 | 
            -
                    
         | 
| 1011 | 
            -
                    transcript = openai_client.audio.transcriptions.create(
         | 
| 1012 | 
            -
                        model="whisper-1",
         | 
| 1013 | 
            -
                        file=("recording.webm", audio_bytes, "audio/webm")
         | 
| 1014 | 
            -
                    )
         | 
| 1015 | 
            -
                    return jsonify({"success": True, "text": transcript.text})
         | 
| 1016 | 
            -
                except Exception as e:
         | 
| 1017 | 
            -
                    return jsonify({"success": False, "message": str(e)})
         | 
| 1018 | 
            -
             | 
| 1019 | 
            -
            @app.route("/debug")
         | 
| 1020 | 
            -
            def debug():
         | 
| 1021 | 
            -
                """
         | 
| 1022 | 
            -
                Debug endpoint to check API configuration and environment
         | 
| 1023 | 
            -
                """
         | 
| 1024 | 
            -
                return jsonify({
         | 
| 1025 | 
            -
                    "api_key_set": bool(TOGETHER_API_KEY),
         | 
| 1026 | 
            -
                    "client_available": client is not None,
         | 
| 1027 | 
            -
                    "environment": os.environ.get("ENVIRONMENT", "unknown"),
         | 
| 1028 | 
            -
                    "together_api_key_length": len(TOGETHER_API_KEY) if TOGETHER_API_KEY else 0,
         | 
| 1029 | 
            -
                    "flask_debug": app.debug,
         | 
| 1030 | 
            -
                    "users_file": USERS_FILE
         | 
| 1031 | 
            -
                })
         | 
| 1032 | 
            -
             | 
| 1033 | 
            -
            @app.route("/session-debug")
         | 
| 1034 | 
            -
            def session_debug():
         | 
| 1035 | 
            -
                """
         | 
| 1036 | 
            -
                Debug endpoint to check session and user data
         | 
| 1037 | 
            -
                """
         | 
| 1038 | 
            -
                users = load_users()
         | 
| 1039 | 
            -
                return jsonify({
         | 
| 1040 | 
            -
                    "session_data": dict(session),
         | 
| 1041 | 
            -
                    "username_in_session": 'username' in session,
         | 
| 1042 | 
            -
                    "current_username": session.get('username', 'None'),
         | 
| 1043 | 
            -
                    "users_file_exists": os.path.exists(USERS_FILE),
         | 
| 1044 | 
            -
                    "users_file_path": os.path.abspath(USERS_FILE),
         | 
| 1045 | 
            -
                    "users_count": len(users),
         | 
| 1046 | 
            -
                    "user_list": list(users.keys()),
         | 
| 1047 | 
            -
                    "session_cookie_config": {
         | 
| 1048 | 
            -
                        "secure": app.config.get('SESSION_COOKIE_SECURE'),
         | 
| 1049 | 
            -
                        "httponly": app.config.get('SESSION_COOKIE_HTTPONLY'),
         | 
| 1050 | 
            -
                        "samesite": app.config.get('SESSION_COOKIE_SAMESITE')
         | 
| 1051 | 
            -
                    }
         | 
| 1052 | 
            -
                })
         | 
| 1053 | 
            -
             | 
| 1054 | 
             
            # Initialize default test user on startup
         | 
| 1055 | 
             
            initialize_default_user()
         | 
| 1056 |  | 
| 1057 | 
             
            if __name__ == "__main__":
         | 
| 1058 | 
            -
                app.run(debug=True, port= | 
|  | |
| 1 | 
             
            """
         | 
| 2 | 
             
            Concept: Flask + HTML Integration - Spiritual Path Assessment Tool
         | 
| 3 | 
            +
             | 
| 4 | 
             
            This app helps users discover which religious or spiritual path aligns with their 
         | 
| 5 | 
             
            beliefs, values, lifestyle, and background through an interactive questionnaire.
         | 
| 6 | 
             
            """
         | 
|  | |
| 10 | 
             
            from werkzeug.security import generate_password_hash, check_password_hash
         | 
| 11 | 
             
            import json
         | 
| 12 | 
             
            import os
         | 
|  | |
|  | |
| 13 | 
             
            from dotenv import load_dotenv
         | 
| 14 | 
             
            from together import Together
         | 
|  | |
|  | |
|  | |
|  | |
| 15 |  | 
| 16 | 
             
            load_dotenv()
         | 
| 17 |  | 
| 18 | 
             
            app = Flask(__name__)
         | 
| 19 | 
            +
            app.secret_key = 'spiritual-journey-finder-2024'
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 20 |  | 
| 21 | 
             
            # File to store user data - defaults to current directory (writable in Docker)
         | 
|  | |
| 22 | 
             
            USERS_FILE = os.getenv("USERS_FILE", "users_data.json")
         | 
| 23 |  | 
| 24 | 
             
            # Together API for chatbot
         | 
| 25 | 
             
            TOGETHER_API_KEY = os.getenv("TOGETHER_API_KEY")
         | 
| 26 | 
             
            client = Together(api_key=TOGETHER_API_KEY) if TOGETHER_API_KEY else None
         | 
| 27 |  | 
| 28 | 
            +
            # Assessment Questions
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 29 | 
             
            QUESTIONS = [
         | 
| 30 | 
             
                {
         | 
| 31 | 
             
                    "id": 1,
         | 
| 32 | 
             
                    "question": "What is your view on the nature of the divine?",
         | 
| 33 | 
             
                    "options": {
         | 
| 34 | 
            +
                        "One supreme God who created everything": {"christianity": 3, "islam": 3, "judaism": 3},
         | 
| 35 | 
            +
                        "Multiple gods and goddesses": {"hinduism": 3, "paganism": 3},
         | 
| 36 | 
            +
                        "A universal energy or force": {"buddhism": 2, "taoism": 3, "new_age": 3},
         | 
| 37 | 
            +
                        "No divine being, focus on human potential": {"humanism": 3, "atheism": 3},
         | 
| 38 | 
            +
                        "Uncertain or unknowable": {"agnosticism": 3}
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 39 | 
             
                    }
         | 
| 40 | 
             
                },
         | 
| 41 | 
             
                {
         | 
| 42 | 
             
                    "id": 2,
         | 
| 43 | 
             
                    "question": "How do you prefer to connect with spirituality?",
         | 
| 44 | 
             
                    "options": {
         | 
| 45 | 
            +
                        "Through organized worship and community": {"christianity": 2, "islam": 2, "judaism": 2},
         | 
| 46 | 
            +
                        "Through personal meditation and reflection": {"buddhism": 3, "hinduism": 2, "taoism": 2},
         | 
| 47 | 
            +
                        "Through nature and natural cycles": {"paganism": 3, "indigenous": 3},
         | 
| 48 | 
            +
                        "Through reason and philosophy": {"humanism": 2, "stoicism": 3},
         | 
| 49 | 
            +
                        "I don't feel the need for spiritual connection": {"atheism": 3}
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 50 | 
             
                    }
         | 
| 51 | 
             
                },
         | 
| 52 | 
             
                {
         | 
| 53 | 
             
                    "id": 3,
         | 
| 54 | 
             
                    "question": "What is your belief about the afterlife?",
         | 
| 55 | 
             
                    "options": {
         | 
| 56 | 
            +
                        "Heaven or Hell based on faith/deeds": {"christianity": 3, "islam": 3},
         | 
| 57 | 
            +
                        "Reincarnation until enlightenment": {"hinduism": 3, "buddhism": 3},
         | 
| 58 | 
            +
                        "Ancestral realm or spiritual world": {"indigenous": 2, "paganism": 2},
         | 
| 59 | 
            +
                        "No afterlife, this life is all there is": {"atheism": 3, "humanism": 2},
         | 
| 60 | 
            +
                        "Unsure or open to possibilities": {"agnosticism": 2, "new_age": 2}
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 61 | 
             
                    }
         | 
| 62 | 
             
                },
         | 
| 63 | 
             
                {
         | 
| 64 | 
             
                    "id": 4,
         | 
| 65 | 
             
                    "question": "What guides your moral and ethical decisions?",
         | 
| 66 | 
             
                    "options": {
         | 
| 67 | 
            +
                        "Sacred texts and religious teachings": {"christianity": 3, "islam": 3, "judaism": 3},
         | 
| 68 | 
            +
                        "Universal principles of compassion and mindfulness": {"buddhism": 3, "jainism": 3},
         | 
| 69 | 
            +
                        "Harmony with nature and balance": {"taoism": 3, "indigenous": 2},
         | 
| 70 | 
            +
                        "Reason, empathy, and human rights": {"humanism": 3, "secularism": 3},
         | 
| 71 | 
            +
                        "Personal intuition and inner wisdom": {"new_age": 2, "spiritualism": 3}
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 72 | 
             
                    }
         | 
| 73 | 
             
                },
         | 
| 74 | 
             
                {
         | 
| 75 | 
             
                    "id": 5,
         | 
| 76 | 
            +
                    "question": "What role does ritual or practice play in your life?",
         | 
| 77 | 
             
                    "options": {
         | 
| 78 | 
            +
                        "Regular prayer and worship are essential": {"islam": 3, "christianity": 2, "judaism": 2},
         | 
| 79 | 
            +
                        "Daily meditation or mindfulness practice": {"buddhism": 3, "hinduism": 2, "zen": 3},
         | 
| 80 | 
            +
                        "Seasonal celebrations and ceremonies": {"paganism": 3, "wicca": 3},
         | 
| 81 | 
            +
                        "Minimal to no ritual, prefer intellectual engagement": {"humanism": 2, "deism": 2},
         | 
| 82 | 
            +
                        "Flexible, whatever feels meaningful to me": {"new_age": 2, "spiritual_not_religious": 3}
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 83 | 
             
                    }
         | 
| 84 | 
             
                },
         | 
| 85 | 
             
                {
         | 
| 86 | 
             
                    "id": 6,
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 87 | 
             
                    "question": "How do you view the relationship between humans and nature?",
         | 
| 88 | 
             
                    "options": {
         | 
| 89 | 
            +
                        "Humans are stewards of God's creation": {"christianity": 2, "islam": 2, "judaism": 2},
         | 
| 90 | 
            +
                        "All life is interconnected and sacred": {"buddhism": 2, "hinduism": 2, "jainism": 3},
         | 
| 91 | 
            +
                        "Nature itself is divine": {"paganism": 3, "pantheism": 3, "indigenous": 3},
         | 
| 92 | 
            +
                        "Nature follows natural laws we can understand": {"atheism": 2, "humanism": 2},
         | 
| 93 | 
            +
                        "We should live in harmony with natural flow": {"taoism": 3, "shintoism": 2}
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 94 | 
             
                    }
         | 
| 95 | 
             
                },
         | 
| 96 | 
             
                {
         | 
| 97 | 
            +
                    "id": 7,
         | 
| 98 | 
             
                    "question": "What is your view on suffering and its purpose?",
         | 
| 99 | 
             
                    "options": {
         | 
| 100 | 
            +
                        "A test of faith or part of God's plan": {"christianity": 2, "islam": 2},
         | 
| 101 | 
            +
                        "Result of attachment and desire": {"buddhism": 3, "stoicism": 2},
         | 
| 102 | 
            +
                        "Karma from past actions": {"hinduism": 3, "sikhism": 2},
         | 
| 103 | 
            +
                        "Random or result of natural causes": {"atheism": 3, "secular": 2},
         | 
| 104 | 
            +
                        "An opportunity for growth and learning": {"new_age": 2, "spiritualism": 2}
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 105 | 
             
                    }
         | 
| 106 | 
             
                },
         | 
| 107 | 
             
                {
         | 
| 108 | 
            +
                    "id": 8,
         | 
| 109 | 
             
                    "question": "How important is community in your spiritual life?",
         | 
| 110 | 
             
                    "options": {
         | 
| 111 | 
            +
                        "Very important, prefer group worship": {"christianity": 2, "islam": 2, "sikhism": 3},
         | 
| 112 | 
            +
                        "Somewhat important, but personal practice matters more": {"buddhism": 2, "hinduism": 2},
         | 
| 113 | 
            +
                        "Community of like-minded seekers": {"paganism": 2, "unitarian": 3},
         | 
| 114 | 
            +
                        "Not important, spirituality is personal": {"spiritual_not_religious": 3, "deism": 2},
         | 
| 115 | 
            +
                        "Prefer secular community over religious": {"humanism": 2, "atheism": 2}
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 116 | 
             
                    }
         | 
| 117 | 
             
                }
         | 
| 118 | 
             
            ]
         | 
|  | |
| 132 | 
             
                "new_age": {"name": "New Age Spirituality", "description": "Eclectic approach emphasizing personal growth.", "practices": "Meditation, energy work, crystals, yoga", "core_beliefs": "Personal transformation, universal consciousness"},
         | 
| 133 | 
             
                "spiritual_not_religious": {"name": "Spiritual But Not Religious", "description": "Personal spirituality without organized religion.", "practices": "Personal practices, meditation, self-reflection", "core_beliefs": "Individual journey, authenticity, diverse wisdom"},
         | 
| 134 | 
             
                "sikhism": {"name": "Sikhism", "description": "One God emphasizing service, equality, and meditation.", "practices": "Prayer, meditation, community service, 5 Ks", "core_beliefs": "One God, equality, honest living, sharing"},
         | 
| 135 | 
            +
                "indigenous": {"name": "Indigenous Spirituality", "description": "Traditional practices honoring ancestors and land.", "practices": "Ceremonies, storytelling, seasonal rituals", "core_beliefs": "Land connection, ancestor veneration, reciprocity"}
         | 
|  | |
|  | |
|  | |
|  | |
| 136 | 
             
            }
         | 
| 137 |  | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 138 | 
             
            def load_users():
         | 
| 139 | 
            +
                """Load users from JSON file"""
         | 
| 140 | 
             
                try:
         | 
| 141 | 
             
                    if os.path.exists(USERS_FILE):
         | 
| 142 | 
             
                        with open(USERS_FILE, 'r') as f:
         | 
|  | |
| 163 | 
             
                if not users:  # Only create if no users exist
         | 
| 164 | 
             
                    users['test'] = {
         | 
| 165 | 
             
                        'password': generate_password_hash('test'),
         | 
|  | |
|  | |
| 166 | 
             
                        'answers': [],
         | 
| 167 | 
             
                        'results': []
         | 
| 168 | 
             
                    }
         | 
|  | |
| 170 | 
             
                    print("✅ Default test user created (username: test, password: test)")
         | 
| 171 |  | 
| 172 | 
             
            def calculate_results(answers):
         | 
| 173 | 
            +
                """Calculate which spiritual paths align with user's answers"""
         | 
|  | |
|  | |
|  | |
| 174 | 
             
                scores = {}
         | 
|  | |
| 175 |  | 
|  | |
| 176 | 
             
                for answer in answers:
         | 
| 177 | 
             
                    question = next((q for q in QUESTIONS if q["id"] == answer["question_id"]), None)
         | 
| 178 | 
             
                    if question and answer["answer"] in question["options"]:
         | 
| 179 | 
            +
                        points = question["options"][answer["answer"]]
         | 
| 180 | 
            +
                        for religion, score in points.items():
         | 
| 181 | 
            +
                            scores[religion] = scores.get(religion, 0) + score
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 182 |  | 
| 183 | 
            +
                # Sort by score
         | 
| 184 | 
            +
                sorted_scores = sorted(scores.items(), key=lambda x: x[1], reverse=True)
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
| 185 |  | 
| 186 | 
            +
                # Get top 3 recommendations
         | 
| 187 | 
             
                recommendations = []
         | 
| 188 | 
            +
                for religion_key, score in sorted_scores[:3]:
         | 
| 189 | 
            +
                    if religion_key in RELIGIONS:
         | 
| 190 | 
            +
                        religion_info = RELIGIONS[religion_key].copy()
         | 
| 191 | 
            +
                        religion_info["score"] = score
         | 
| 192 | 
            +
                        religion_info["percentage"] = round((score / (len(answers) * 3)) * 100)
         | 
| 193 | 
            +
                        recommendations.append(religion_info)
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 194 |  | 
| 195 | 
             
                return recommendations
         | 
| 196 |  | 
| 197 | 
             
            @app.route("/")
         | 
| 198 | 
            +
            def home():
         | 
| 199 | 
            +
                if 'username' not in session:
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 200 | 
             
                    return redirect(url_for('login'))
         | 
| 201 |  | 
| 202 | 
            +
                users = load_users()
         | 
| 203 | 
            +
                user_data = users.get(session['username'], {})
         | 
| 204 | 
            +
                has_results = 'results' in user_data and user_data['results']
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 205 |  | 
| 206 | 
             
                return render_template(
         | 
| 207 | 
             
                    "index.html", 
         | 
| 208 | 
             
                    title="Spiritual Path Finder", 
         | 
| 209 | 
            +
                    message=f"Welcome, {session['username']}! 🌟",
         | 
| 210 | 
            +
                    username=session['username'],
         | 
| 211 | 
             
                    logged_in=True,
         | 
| 212 | 
             
                    questions=QUESTIONS,
         | 
| 213 | 
             
                    has_results=has_results,
         | 
| 214 | 
            +
                    results=user_data.get('results', []) if has_results else []
         | 
|  | |
| 215 | 
             
                )
         | 
| 216 |  | 
| 217 | 
             
            @app.route("/login", methods=["GET", "POST"])
         | 
|  | |
| 221 | 
             
                        data = request.get_json()
         | 
| 222 | 
             
                        if not data:
         | 
| 223 | 
             
                            return jsonify({"success": False, "message": "Invalid request"}), 400
         | 
| 224 | 
            +
                            
         | 
| 225 | 
            +
                        username = data.get('username', '').strip()
         | 
| 226 | 
            +
                        password = data.get('password', '')
         | 
| 227 |  | 
| 228 | 
            +
                        if not username or not password:
         | 
| 229 | 
            +
                            return jsonify({"success": False, "message": "Username and password required"}), 400
         | 
| 230 |  | 
| 231 | 
            +
                        users = load_users()
         | 
| 232 | 
            +
                        if username in users:
         | 
| 233 | 
            +
                            stored = users[username]['password']
         | 
| 234 | 
            +
                        
         | 
| 235 | 
            +
                            # 1) Try hash-based verification (works for any Werkzeug scheme)
         | 
| 236 | 
            +
                            try:
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 237 | 
             
                                if check_password_hash(stored, password):
         | 
| 238 | 
             
                                    session['username'] = username
         | 
|  | |
| 239 | 
             
                                    return jsonify({"success": True})
         | 
| 240 | 
            +
                            except Exception:
         | 
| 241 | 
            +
                                pass  # if stored isn't a hash string, we'll try plaintext next
         | 
| 242 | 
            +
                        
         | 
| 243 | 
            +
                            # 2) Legacy plaintext fallback → upgrade to a hash
         | 
| 244 | 
            +
                            if stored == password:
         | 
| 245 | 
             
                                users[username]['password'] = generate_password_hash(password)
         | 
| 246 | 
             
                                if not save_users(users):
         | 
| 247 | 
             
                                    return jsonify({"success": False, "message": "Error saving data"}), 500
         | 
| 248 | 
             
                                session['username'] = username
         | 
|  | |
| 249 | 
             
                                return jsonify({"success": True})
         | 
| 250 | 
            +
                        
         | 
| 251 | 
            +
                        return jsonify({"success": False, "message": "Invalid credentials"})
         | 
| 252 | 
             
                    except Exception as e:
         | 
| 253 | 
             
                        print(f"Login error: {e}")
         | 
| 254 | 
             
                        return jsonify({"success": False, "message": "Server error"}), 500
         | 
| 255 |  | 
| 256 | 
            +
                return render_template("index.html", logged_in=False, is_signup=False)
         | 
|  | |
| 257 |  | 
| 258 | 
             
            @app.route("/signup", methods=["GET", "POST"])
         | 
| 259 | 
             
            def signup():
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 260 | 
             
                if request.method == "POST":
         | 
| 261 | 
             
                    try:
         | 
| 262 | 
             
                        data = request.get_json()
         | 
| 263 | 
             
                        if not data:
         | 
| 264 | 
             
                            return jsonify({"success": False, "message": "Invalid request"}), 400
         | 
| 265 |  | 
| 266 | 
            +
                        username = data.get('username', '').strip()
         | 
| 267 | 
            +
                        password = data.get('password', '')
         | 
| 268 |  | 
| 269 | 
            +
                        if not username or not password:
         | 
| 270 | 
            +
                            return jsonify({"success": False, "message": "Username and password required"}), 400
         | 
|  | |
|  | |
|  | |
| 271 |  | 
| 272 | 
             
                        users = load_users()
         | 
| 273 |  | 
| 274 | 
            +
                        if username in users:
         | 
| 275 | 
            +
                            return jsonify({"success": False, "message": "Username already exists"})
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 276 |  | 
| 277 | 
            +
                        # Create new user with hashed password
         | 
| 278 | 
            +
                        users[username] = {
         | 
| 279 | 
            +
                            'password': generate_password_hash(password),
         | 
| 280 | 
            +
                            'answers': [],
         | 
| 281 | 
            +
                            'results': []
         | 
|  | |
|  | |
| 282 | 
             
                        }
         | 
| 283 |  | 
| 284 | 
            +
                        if not save_users(users):
         | 
| 285 | 
            +
                            return jsonify({"success": False, "message": "Error saving user data"}), 500
         | 
| 286 | 
            +
                            
         | 
| 287 | 
            +
                        session['username'] = username
         | 
| 288 | 
            +
                        return jsonify({"success": True})
         | 
|  | |
|  | |
| 289 | 
             
                    except Exception as e:
         | 
| 290 | 
            +
                        print(f"Signup error: {e}")
         | 
| 291 | 
             
                        return jsonify({"success": False, "message": "Server error"}), 500
         | 
| 292 |  | 
| 293 | 
            +
                return render_template("index.html", logged_in=False, is_signup=True)
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 294 |  | 
| 295 | 
             
            @app.route("/logout")
         | 
| 296 | 
             
            def logout():
         | 
|  | |
|  | |
|  | |
| 297 | 
             
                session.pop('username', None)
         | 
| 298 | 
            +
                return redirect(url_for('login'))
         | 
| 299 |  | 
| 300 | 
             
            @app.route("/submit_assessment", methods=["POST"])
         | 
| 301 | 
             
            def submit_assessment():
         | 
| 302 | 
            +
                if 'username' not in session:
         | 
|  | |
|  | |
|  | |
| 303 | 
             
                    return jsonify({"success": False, "message": "Not logged in"})
         | 
| 304 |  | 
| 305 | 
             
                data = request.json
         | 
|  | |
| 311 | 
             
                # Calculate results
         | 
| 312 | 
             
                results = calculate_results(answers)
         | 
| 313 |  | 
| 314 | 
            +
                # Save to user data
         | 
| 315 | 
            +
                users = load_users()
         | 
| 316 | 
            +
                if session['username'] in users:
         | 
| 317 | 
            +
                    users[session['username']]['answers'] = answers
         | 
| 318 | 
            +
                    users[session['username']]['results'] = results
         | 
| 319 | 
            +
                    save_users(users)
         | 
| 320 | 
            +
                    
         | 
|  | |
|  | |
| 321 | 
             
                    return jsonify({"success": True, "results": results})
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 322 |  | 
| 323 | 
             
                return jsonify({"success": False, "message": "User not found"})
         | 
| 324 |  | 
| 325 | 
             
            @app.route("/reset_assessment", methods=["POST"])
         | 
| 326 | 
             
            def reset_assessment():
         | 
| 327 | 
            +
                if 'username' not in session:
         | 
|  | |
|  | |
|  | |
| 328 | 
             
                    return jsonify({"success": False, "message": "Not logged in"})
         | 
| 329 |  | 
| 330 | 
            +
                users = load_users()
         | 
| 331 | 
            +
                if session['username'] in users:
         | 
| 332 | 
            +
                    users[session['username']]['answers'] = []
         | 
| 333 | 
            +
                    users[session['username']]['results'] = []
         | 
| 334 | 
            +
                    save_users(users)
         | 
|  | |
|  | |
|  | |
|  | |
| 335 | 
             
                    return jsonify({"success": True})
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 336 |  | 
| 337 | 
             
                return jsonify({"success": False, "message": "User not found"})
         | 
| 338 |  | 
| 339 | 
             
            @app.route("/chat", methods=["POST"])
         | 
| 340 | 
             
            def chat():
         | 
| 341 | 
            +
                if 'username' not in session:
         | 
|  | |
|  | |
|  | |
|  | |
| 342 | 
             
                    return jsonify({"success": False, "message": "Not logged in"})
         | 
| 343 |  | 
| 344 | 
             
                if not client:
         | 
|  | |
| 352 | 
             
                if not user_message or not religion_name:
         | 
| 353 | 
             
                    return jsonify({"success": False, "message": "Message and religion required"})
         | 
| 354 |  | 
| 355 | 
            +
                # Find religion details
         | 
| 356 | 
             
                religion_data = None
         | 
|  | |
|  | |
| 357 | 
             
                for key, value in RELIGIONS.items():
         | 
| 358 | 
             
                    if value['name'] == religion_name:
         | 
| 359 | 
            +
                        religion_data = value
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
| 360 | 
             
                        break
         | 
| 361 |  | 
| 362 | 
             
                if not religion_data:
         | 
| 363 | 
             
                    return jsonify({"success": False, "message": "Religion not found"})
         | 
| 364 |  | 
| 365 | 
            +
                # Create context-aware system prompt
         | 
| 366 | 
            +
                system_prompt = f"""You're a spiritual guide for {religion_data['name']}.
         | 
| 367 | 
            +
            Info: {religion_data['description']} | Practices: {religion_data['practices']} | Beliefs: {religion_data['core_beliefs']}
         | 
| 368 | 
            +
            Rules: Keep 30-50 words, be respectful, use * for bullet points (format: "Text: * item * item"), answer directly."""
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 369 |  | 
| 370 | 
            +
                # Build conversation history
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 371 | 
             
                messages = [{"role": "system", "content": system_prompt}]
         | 
| 372 |  | 
| 373 | 
            +
                # Add chat history (last 5 messages for context)
         | 
| 374 | 
            +
                for msg in chat_history[-5:]:
         | 
| 375 | 
             
                    messages.append({"role": msg["role"], "content": msg["content"]})
         | 
| 376 |  | 
| 377 | 
            +
                # Add current user message
         | 
| 378 | 
             
                messages.append({"role": "user", "content": user_message})
         | 
| 379 |  | 
| 380 | 
             
                try:
         | 
| 381 | 
            +
                    # Call Together API with limited tokens for concise responses
         | 
| 382 | 
             
                    response = client.chat.completions.create(
         | 
| 383 | 
             
                        model="meta-llama/Meta-Llama-3-8B-Instruct-Lite",
         | 
| 384 | 
             
                        messages=messages,
         | 
| 385 | 
            +
                        max_tokens=80,  # Roughly 50-60 words maximum
         | 
| 386 | 
             
                        temperature=0.7,
         | 
| 387 | 
             
                    )
         | 
| 388 |  | 
|  | |
| 399 | 
             
                        "message": f"Chat error: {str(e)}"
         | 
| 400 | 
             
                    })
         | 
| 401 |  | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 402 | 
             
            # Initialize default test user on startup
         | 
| 403 | 
             
            initialize_default_user()
         | 
| 404 |  | 
| 405 | 
             
            if __name__ == "__main__":
         | 
| 406 | 
            +
                app.run(debug=True, port=5001)
         | 
    	
        rag_utils.py
    DELETED
    
    | @@ -1,31 +0,0 @@ | |
| 1 | 
            -
            """Simple RAG utilities for loading religion data"""
         | 
| 2 | 
            -
            import csv
         | 
| 3 | 
            -
             | 
| 4 | 
            -
            def load_religions_from_csv(csv_path):
         | 
| 5 | 
            -
                """Load religion data from CSV file"""
         | 
| 6 | 
            -
                try:
         | 
| 7 | 
            -
                    religions = {}
         | 
| 8 | 
            -
                    with open(csv_path, 'r', encoding='utf-8') as f:
         | 
| 9 | 
            -
                        reader = csv.DictReader(f)
         | 
| 10 | 
            -
                        for row in reader:
         | 
| 11 | 
            -
                            religions[row['key']] = row
         | 
| 12 | 
            -
                    print(f"✅ Loaded {len(religions)} religions from CSV")
         | 
| 13 | 
            -
                    return religions
         | 
| 14 | 
            -
                except Exception as e:
         | 
| 15 | 
            -
                    print(f"⚠️ Error loading religions CSV: {e}")
         | 
| 16 | 
            -
                    return {}
         | 
| 17 | 
            -
             | 
| 18 | 
            -
            def prepare_religion_rag_context(religion_data):
         | 
| 19 | 
            -
                """Prepare context string from religion data"""
         | 
| 20 | 
            -
                parts = []
         | 
| 21 | 
            -
                
         | 
| 22 | 
            -
                if 'description' in religion_data:
         | 
| 23 | 
            -
                    parts.append(f"Description: {religion_data['description']}")
         | 
| 24 | 
            -
                if 'practices' in religion_data:
         | 
| 25 | 
            -
                    parts.append(f"Practices: {religion_data['practices']}")
         | 
| 26 | 
            -
                if 'core_beliefs' in religion_data:
         | 
| 27 | 
            -
                    parts.append(f"Core Beliefs: {religion_data['core_beliefs']}")
         | 
| 28 | 
            -
                if 'common_curiosities' in religion_data:
         | 
| 29 | 
            -
                    parts.append(f"Common Questions: {religion_data['common_curiosities']}")
         | 
| 30 | 
            -
                
         | 
| 31 | 
            -
                return ['\n\n'.join(parts)]
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
    	
        religions.csv
    DELETED
    
    | @@ -1,109 +0,0 @@ | |
| 1 | 
            -
            id,religion,category,topic,content,keywords,question_relevance
         | 
| 2 | 
            -
            1,christianity,core_belief,nature_of_divine,"Christianity is a monotheistic religion centered on belief in one God who exists as three persons: Father, Son (Jesus Christ), and Holy Spirit. Christians believe God is loving, just, and personal, actively involved in human affairs.","monotheism,trinity,personal god,jesus christ",q1_q4
         | 
| 3 | 
            -
            2,christianity,practice,spiritual_connection,"Christians connect with God through personal prayer, communal worship, reading the Bible, and participating in sacraments like communion and baptism. Church community is central to faith practice.","prayer,worship,bible,communion,church",q2_q5
         | 
| 4 | 
            -
            3,christianity,belief,afterlife,Christianity teaches that faith in Jesus Christ leads to eternal life in Heaven with God. Those who reject Christ face separation from God (Hell). Salvation is through grace and faith.,"heaven,hell,salvation,eternal life,grace",q3
         | 
| 5 | 
            -
            4,christianity,ethics,moral_guidance,"Christian ethics are based on Biblical teachings, especially Jesus' commands to love God and love others. The Ten Commandments and Jesus' Sermon on the Mount provide moral framework.","bible,ten commandments,love,scripture,jesus teaching",q4
         | 
| 6 | 
            -
            5,christianity,practice,nature_relationship,"Christians view humans as stewards of God's creation, called to care for the Earth responsibly. Nature reveals God's glory but is distinct from God.","stewardship,creation care,dominion",q6
         | 
| 7 | 
            -
            6,christianity,belief,suffering,"Suffering is often seen as a test of faith, opportunity for spiritual growth, or part of God's mysterious plan. Jesus' suffering on the cross gives meaning to human suffering.","test of faith,cross,redemptive suffering,gods plan",q7
         | 
| 8 | 
            -
            7,islam,core_belief,nature_of_divine,"Islam is strictly monotheistic, believing in one God (Allah) who is merciful, compassionate, and transcendent. Allah is the creator and sustainer of all existence, revealed through Prophet Muhammad.","monotheism,allah,tawhid,prophet muhammad",q1_q4
         | 
| 9 | 
            -
            8,islam,practice,spiritual_connection,"Muslims connect with Allah through five daily prayers (salat), reciting Quran, and following the Five Pillars. Prayer involves physical prostration showing submission to Allah.","five pillars,salat,prayer,quran,submission",q2_q5
         | 
| 10 | 
            -
            9,islam,belief,afterlife,Muslims believe in Day of Judgment where all are resurrected and judged by Allah. Paradise (Jannah) awaits the righteous; Hell (Jahannam) for those who reject faith and do evil.,"judgment day,jannah,paradise,hell,resurrection",q3
         | 
| 11 | 
            -
            10,islam,ethics,moral_guidance,"Islamic ethics come from Quran and Hadith (Prophet's teachings). Core values include justice, compassion, honesty, modesty, and following Shariah (Islamic law).","quran,hadith,shariah,justice,compassion",q4
         | 
| 12 | 
            -
            11,islam,practice,nature_relationship,"Muslims see humans as Allah's khalifah (stewards) on Earth, responsible for protecting and using resources justly. Nature is a sign of Allah's power and mercy.","khalifah,stewardship,creation,signs of allah",q6
         | 
| 13 | 
            -
            12,islam,belief,suffering,Suffering is a test from Allah to strengthen faith and purify the soul. Patience (sabr) during hardship is highly valued and rewarded by Allah.,"test,sabr,patience,purification,trial",q7
         | 
| 14 | 
            -
            13,buddhism,core_belief,nature_of_divine,"Buddhism generally doesn't focus on a creator god. Instead, it teaches about the nature of reality, suffering, and the path to enlightenment (Nirvana). Some schools venerate Buddha and bodhisattvas.","non-theistic,enlightenment,nirvana,buddha,no creator",q1
         | 
| 15 | 
            -
            14,buddhism,practice,spiritual_connection,"Buddhists practice meditation (especially mindfulness and concentration), follow the Eightfold Path, and cultivate wisdom and compassion. Personal practice is emphasized over communal worship.","meditation,mindfulness,eightfold path,personal practice",q2_q5
         | 
| 16 | 
            -
            15,buddhism,belief,afterlife,Buddhism teaches rebirth (samsara) driven by karma. The goal is to achieve Nirvana - liberation from the cycle of rebirth and suffering. Rebirth isn't eternal soul but continuation of consciousness.,"rebirth,samsara,karma,nirvana,liberation",q3
         | 
| 17 | 
            -
            16,buddhism,ethics,moral_guidance,"Buddhist ethics center on the Four Noble Truths and Eightfold Path. Core principles include non-harm (ahimsa), compassion (karuna), and mindful awareness. Actions create karma.","four noble truths,ahimsa,compassion,karma,mindfulness",q4
         | 
| 18 | 
            -
            17,buddhism,belief,interconnection,Buddhism teaches dependent origination - all phenomena are interconnected. Harming nature harms oneself. All sentient beings deserve compassion and should be treated with respect.,"interconnection,dependent origination,sentient beings,compassion",q6
         | 
| 19 | 
            -
            18,buddhism,belief,suffering,"Suffering (dukkha) is caused by attachment, craving, and ignorance of reality's true nature. The path to end suffering is through understanding, letting go of attachment, and following the Eightfold Path.","dukkha,attachment,craving,four noble truths,cessation",q7
         | 
| 20 | 
            -
            19,hinduism,core_belief,nature_of_divine,"Hinduism embraces diverse views: one supreme reality (Brahman) manifesting as many deities, or devotion to personal gods like Vishnu, Shiva, or Devi. Ultimate reality is beyond form.","brahman,polytheism,monotheism,vishnu,shiva,multiple paths",q1
         | 
| 21 | 
            -
            20,hinduism,practice,spiritual_connection,"Hindus practice yoga, meditation, puja (worship), temple visits, and festivals. Multiple paths exist: devotion (bhakti), knowledge (jnana), action (karma yoga), meditation (raja yoga).","yoga,meditation,puja,bhakti,multiple paths",q2_q5
         | 
| 22 | 
            -
            21,hinduism,belief,afterlife,"Hindus believe in reincarnation (samsara) based on karma. The soul (atman) is reborn until achieving moksha (liberation) - union with Brahman, ending the cycle of rebirth.","reincarnation,karma,moksha,atman,samsara,liberation",q3
         | 
| 23 | 
            -
            22,hinduism,ethics,moral_guidance,"Hindu ethics center on dharma (righteous duty), which varies by role, age, and circumstance. Universal principles include non-violence (ahimsa), truthfulness, and compassion.","dharma,ahimsa,karma,righteous duty",q4
         | 
| 24 | 
            -
            23,hinduism,belief,interconnection,"Hinduism teaches all life contains the divine essence (atman/Brahman). Ahimsa (non-violence) extends to all creatures. Many Hindus are vegetarian, viewing cows and other animals as sacred.","atman,brahman,sacred,ahimsa,interconnected",q6
         | 
| 25 | 
            -
            24,hinduism,belief,suffering,Suffering results from karma - consequences of past actions in this or previous lives. It's an opportunity to work through karmic debt and progress spiritually toward moksha.,"karma,past lives,spiritual progress,moksha",q7
         | 
| 26 | 
            -
            25,judaism,core_belief,nature_of_divine,"Judaism is strictly monotheistic, believing in one God (YHWH/Adonai) who is eternal, creator, and enters into covenant with the Jewish people. God is both transcendent and involved in history.","monotheism,yhwh,covenant,ethical monotheism",q1_q4
         | 
| 27 | 
            -
            26,judaism,practice,spiritual_connection,"Jews connect with God through prayer (especially Shabbat and holidays), Torah study, following mitzvot (commandments), and community participation in synagogue.","prayer,torah,mitzvot,shabbat,synagogue",q2_q5
         | 
| 28 | 
            -
            27,judaism,belief,afterlife,"Jewish views on afterlife vary. Traditional belief includes resurrection of the dead in messianic age. Some emphasize this-world focus, others believe in Olam Ha-Ba (World to Come).","resurrection,messianic age,olam haba,varied views",q3
         | 
| 29 | 
            -
            28,judaism,ethics,moral_guidance,"Jewish ethics come from Torah and Talmud, emphasizing justice (tzedakah), ethical behavior, study, and repair of the world (tikkun olam). The 613 mitzvot guide daily life.","torah,talmud,tzedakah,tikkun olam,justice",q4
         | 
| 30 | 
            -
            29,judaism,practice,nature_relationship,Jews are stewards (bal tashchit - don't destroy) of God's creation. Environmental care is a religious duty. Laws like kosher and sabbatical years reflect respect for creation.,"stewardship,bal tashchit,creation care",q6
         | 
| 31 | 
            -
            30,judaism,belief,suffering,"Suffering raises theological questions addressed differently across Jewish thought. Some see it as test, punishment, mystery, or call to action for justice. Holocaust deeply shaped modern Jewish theology.","test,mystery,justice,theological question",q7
         | 
| 32 | 
            -
            31,taoism,core_belief,nature_of_divine,"Taoism centers on the Tao - the ineffable, eternal source and pattern of all existence. It's not a personal god but the natural way of the universe, beyond words or concepts.","tao,natural way,non-theistic,universal force",q1
         | 
| 33 | 
            -
            32,taoism,practice,spiritual_connection,"Taoists practice meditation, tai chi, qigong, and wu wei (effortless action). The focus is aligning with natural rhythms and simplicity rather than forceful striving.","meditation,tai chi,wu wei,simplicity,natural flow",q2_q5
         | 
| 34 | 
            -
            33,taoism,belief,afterlife,Traditional Taoism includes beliefs in immortality through spiritual cultivation and alchemy. Philosophical Taoism focuses more on living well in harmony with Tao than afterlife concerns.,"immortality,spiritual cultivation,harmony,this-life focus",q3
         | 
| 35 | 
            -
            34,taoism,ethics,moral_guidance,"Taoist ethics emphasize naturalness, spontaneity, simplicity, and compassion. Rather than rigid rules, guidance comes from understanding natural balance (yin-yang) and wu wei.","naturalness,wu wei,yin-yang,balance,spontaneity",q4
         | 
| 36 | 
            -
            35,taoism,belief,interconnection,"Taoism sees humans as integral part of nature, not separate or superior. Living in harmony with natural cycles and respecting all life reflects the Tao. Nature is the primary teacher.","harmony with nature,natural cycles,interconnection,nature teacher",q6
         | 
| 37 | 
            -
            36,taoism,belief,suffering,"Suffering arises from resistance to natural flow and clinging to desires. By accepting change, practicing wu wei, and aligning with Tao, one reduces suffering and finds peace.","resistance,acceptance,wu wei,natural flow",q7
         | 
| 38 | 
            -
            37,paganism,core_belief,nature_of_divine,Modern Paganism typically honors multiple deities (polytheism) or sees divinity in nature itself (pantheism). Gods/goddesses often represent natural forces and archetypal energies.,"polytheism,pantheism,nature deities,goddess,god",q1
         | 
| 39 | 
            -
            38,paganism,practice,spiritual_connection,"Pagans celebrate seasonal festivals (solstices, equinoxes), perform rituals, work with natural elements, and often practice magic. Connection with nature is central to practice.","sabbats,rituals,nature connection,magic,seasonal celebrations",q2_q5
         | 
| 40 | 
            -
            39,paganism,belief,afterlife,"Pagan views vary widely: some believe in reincarnation, others in ancestral realms or otherworlds, some in merging with nature. Many focus on honoring this life fully.","reincarnation,otherworld,ancestral realm,varied views",q3
         | 
| 41 | 
            -
            40,paganism,ethics,moral_guidance,"Pagan ethics often center on personal responsibility and the Wiccan Rede ('harm none'). Values include balance, reciprocity with nature, and authentic personal experience.","harm none,reciprocity,personal responsibility,balance",q4
         | 
| 42 | 
            -
            41,paganism,belief,interconnection,"Pagans view nature as sacred and divine. All life is interconnected. Humans are part of nature's web, not separate or superior. Environmental stewardship is spiritual duty.","nature sacred,divine nature,interconnected,sacred earth",q6
         | 
| 43 | 
            -
            42,paganism,belief,suffering,Suffering is part of natural cycles of death and rebirth. It can be transformative and teach important lessons. Balance between light and dark is natural and necessary.,"cycles,transformation,balance,death and rebirth",q7
         | 
| 44 | 
            -
            43,humanism,core_belief,nature_of_divine,"Humanism is non-religious, rejecting supernatural beliefs. Focus is on human potential, reason, ethics, and science without gods or divine intervention.","atheistic,secular,non-religious,reason,human potential",q1
         | 
| 45 | 
            -
            44,humanism,practice,spiritual_connection,"Humanists connect through reason, critical thinking, community service, art, philosophy, and building meaningful relationships. Fulfillment comes from human connection and contribution.","reason,community,philosophy,critical thinking,service",q2_q5
         | 
| 46 | 
            -
            45,humanism,belief,afterlife,"Humanists generally don't believe in afterlife. This life is all there is, making it precious. Legacy lives through impact on others and contributions to human progress.","no afterlife,this life only,legacy,naturalistic",q3
         | 
| 47 | 
            -
            46,humanism,ethics,moral_guidance,"Humanist ethics are based on reason, empathy, human rights, and wellbeing. Morality comes from human needs and social context, not divine command. Science informs ethical decisions.","reason,empathy,human rights,secular ethics,evidence-based",q4
         | 
| 48 | 
            -
            47,humanism,belief,interconnection,"Humanists view humans as part of natural world, subject to natural laws. Environmental protection is important for human wellbeing and future generations, based on scientific understanding.","naturalism,science,environmentalism,evolution",q6
         | 
| 49 | 
            -
            48,humanism,belief,suffering,"Suffering has natural causes, not divine purpose. Humans can reduce suffering through science, medicine, social progress, and compassionate action. Focus on solving problems, not accepting fate.","natural causes,problem-solving,progress,compassion",q7
         | 
| 50 | 
            -
            49,atheism,core_belief,nature_of_divine,"Atheism is lack of belief in gods or deities. Atheists rely on naturalistic explanations, viewing universe as product of natural processes without supernatural intervention.","no god,naturalistic,non-theistic,skepticism",q1
         | 
| 51 | 
            -
            50,atheism,practice,spiritual_connection,"Atheists typically don't seek spiritual connection in traditional sense. Meaning comes from relationships, experiences, learning, creativity, and contributing to society. Some find awe in nature/science.","secular,community,science,meaning-making,non-spiritual",q2_q5
         | 
| 52 | 
            -
            51,atheism,belief,afterlife,Atheists don't believe in afterlife. Consciousness ends at death. This makes life precious and motivates living fully and ethically now.,"no afterlife,materialism,this life only,consciousness ends",q3
         | 
| 53 | 
            -
            52,atheism,ethics,moral_guidance,"Atheist morality is based on empathy, reason, wellbeing, and social cooperation. Ethics evolved to help humans live together successfully, not from divine command.","secular ethics,empathy,reason,evolution,wellbeing",q4
         | 
| 54 | 
            -
            53,atheism,belief,interconnection,"Atheists understand humans as evolved animals, part of natural world. Environmental concern comes from understanding ecology and protecting our only home, based on scientific evidence.","naturalism,evolution,science,ecology,evidence-based",q6
         | 
| 55 | 
            -
            54,atheism,belief,suffering,"Suffering has natural causes - disease, accidents, natural disasters, human actions. No divine purpose or test. We reduce suffering through medicine, technology, social justice, and compassion.","natural causes,randomness,problem-solving,no divine plan",q7
         | 
| 56 | 
            -
            55,agnosticism,core_belief,nature_of_divine,Agnostics hold that existence/nature of divine is unknown or unknowable. Some lack belief but remain open; others actively believe we cannot know. Focus on uncertainty rather than conviction.,"unknowable,uncertainty,open-minded,skeptical inquiry",q1
         | 
| 57 | 
            -
            56,agnosticism,practice,spiritual_connection,"Agnostics may explore various practices or none at all. Often value philosophical inquiry, ethical living, and intellectual honesty over religious ritual. Open to diverse perspectives.","inquiry,philosophical,eclectic,ethical living,exploration",q2_q5
         | 
| 58 | 
            -
            57,agnosticism,belief,afterlife,"Agnostics are uncertain about afterlife. Some lean toward no afterlife, others remain completely open. Emphasis on living well now given the uncertainty about what follows.","uncertain,unknown,open possibilities,this-life focus",q3
         | 
| 59 | 
            -
            58,agnosticism,ethics,moral_guidance,"Agnostic ethics often based on reason, empathy, and human wellbeing without certainty about divine command. Questions and inquiry are valued over absolute answers.","reason,empathy,inquiry,questioning,open ethics",q4
         | 
| 60 | 
            -
            59,agnosticism,belief,interconnection,Agnostics may appreciate scientific understanding of interconnection or remain open to spiritual interpretations. Often value environmental care based on practical concerns.,"scientific understanding,open interpretation,practical ethics",q6
         | 
| 61 | 
            -
            60,agnosticism,belief,suffering,Agnostics are uncertain whether suffering has purpose or is random. May see it as natural phenomenon while remaining open to other interpretations. Focus on responding compassionately.,"uncertainty,natural and/or meaningful,compassionate response",q7
         | 
| 62 | 
            -
            61,new_age,core_belief,nature_of_divine,"New Age spirituality sees divine as universal consciousness or energy pervading all existence. Often blends ideas from Eastern religions, Western esotericism, and modern psychology.","universal consciousness,divine energy,holistic,eclectic",q1
         | 
| 63 | 
            -
            62,new_age,practice,spiritual_connection,"New Age practitioners use meditation, energy healing, crystals, yoga, tarot, astrology, and visualization. Emphasis on personal experience and whatever resonates individually.","meditation,crystals,energy work,personal practice,eclectic",q2_q5
         | 
| 64 | 
            -
            63,new_age,belief,afterlife,"New Age views often include reincarnation, spiritual evolution across lifetimes, and eventual unity with higher consciousness. Some believe in creating own reality even after death.","reincarnation,spiritual evolution,higher consciousness,varied beliefs",q3
         | 
| 65 | 
            -
            64,new_age,ethics,moral_guidance,"New Age ethics emphasize personal growth, positive thinking, manifesting desires, and universal love. 'What you put out returns to you' (Law of Attraction). Follow inner guidance.","law of attraction,personal growth,inner guidance,positive energy",q4
         | 
| 66 | 
            -
            65,new_age,belief,interconnection,"New Age teaches all is one - humans, nature, cosmos connected through universal energy. Harming environment harms collective consciousness. Earth (Gaia) may be seen as living being.","oneness,universal energy,gaia,interconnected consciousness",q6
         | 
| 67 | 
            -
            66,new_age,belief,suffering,Suffering provides growth opportunities and spiritual lessons. Often seen as self-created for soul evolution. Positive thinking and raising vibration can transform suffering.,"growth opportunity,spiritual lesson,soul evolution,transformation",q7
         | 
| 68 | 
            -
            67,spiritual_not_religious,core_belief,nature_of_divine,"SBNR individuals have personal spiritual beliefs outside organized religion. Views vary widely - some believe in higher power, universal energy, or remain undefined. Value personal experience over doctrine.","personal spirituality,no organized religion,individual path,authentic",q1
         | 
| 69 | 
            -
            68,spiritual_not_religious,practice,spiritual_connection,"SBNR people create personal practices - may include meditation, nature connection, journaling, yoga, or borrowing from various traditions. Emphasis on what feels authentic and meaningful.","personal practice,eclectic,authentic,self-directed,meaningful",q2_q5
         | 
| 70 | 
            -
            69,spiritual_not_religious,belief,afterlife,"SBNR views on afterlife vary widely. Some believe in reincarnation, others in energy continuation, some remain open and uncertain. Focus on present spiritual experience over afterlife doctrine.","varied beliefs,open-minded,present-focused,personal interpretation",q3
         | 
| 71 | 
            -
            70,spiritual_not_religious,ethics,moral_guidance,"SBNR ethics based on personal intuition, inner wisdom, and values like compassion and authenticity. Draw from various sources - philosophy, psychology, wisdom traditions - without dogma.","intuition,inner wisdom,authenticity,compassion,non-dogmatic",q4
         | 
| 72 | 
            -
            71,spiritual_not_religious,belief,interconnection,SBNR individuals often feel deep connection to nature and all life. May see nature as sacred teacher without formal religious framework. Environmental care is spiritual practice.,"nature connection,sacred nature,interconnection,personal meaning",q6
         | 
| 73 | 
            -
            72,spiritual_not_religious,belief,suffering,SBNR views on suffering are personal and varied. Many see it as growth opportunity or natural part of life's journey. Focus on finding personal meaning rather than accepting religious explanation.,"personal meaning,growth,varied interpretation,authentic response",q7
         | 
| 74 | 
            -
            73,sikhism,core_belief,nature_of_divine,"Sikhism is monotheistic, believing in one formless God (Waheguru) who is creator, sustainer, and destroyer. God is timeless, without gender, and accessible to all through devotion and service.","monotheism,waheguru,one god,formless,universal access",q1_q4
         | 
| 75 | 
            -
            74,sikhism,practice,spiritual_connection,"Sikhs connect with God through meditation on God's name (Naam Japna), selfless service (Seva), honest living (Kirat Karni), and sharing (Vand Chakna). Community worship at Gurdwara is important.","naam japna,seva,kirat karni,gurdwara,community",q2_q5_q8
         | 
| 76 | 
            -
            75,sikhism,belief,afterlife,Sikhs believe in reincarnation based on karma until union with God is achieved. The goal is to escape reincarnation cycle and merge with divine light through righteous living.,"reincarnation,karma,union with god,liberation,mukti",q3
         | 
| 77 | 
            -
            76,sikhism,ethics,moral_guidance,"Sikh ethics emphasize equality, justice, service, honest work, and devotion. The five virtues are truth, contentment, compassion, humility, and love. Fight against injustice is duty.","equality,justice,five virtues,honest living,service",q4
         | 
| 78 | 
            -
            77,sikhism,belief,interconnection,"Sikhs see all creation as manifestation of one God. All humans are equal regardless of caste, gender, or religion. Environmental care is duty as God's creation must be respected.","equality,gods creation,stewardship,respect for all",q6
         | 
| 79 | 
            -
            78,sikhism,belief,suffering,"Suffering is result of separation from God and ego (Haumai). It's also karma from past lives. Through devotion, service, and God's grace, one can transcend suffering.","karma,separation from god,ego,grace,transcendence",q7
         | 
| 80 | 
            -
            79,indigenous,core_belief,nature_of_divine,"Indigenous spiritualities vary greatly but often include Great Spirit, creator beings, and/or spirits in all things (animism). Divine is immanent in nature, ancestors, and the land itself.","great spirit,animism,spirits,ancestors,varied traditions",q1
         | 
| 81 | 
            -
            80,indigenous,practice,spiritual_connection,"Indigenous practices include ceremonies, storytelling, seasonal rituals, vision quests, and maintaining relationship with land and ancestors. Community and tradition are central.","ceremonies,storytelling,seasonal rituals,land connection,ancestral",q2_q5
         | 
| 82 | 
            -
            81,indigenous,belief,afterlife,"Indigenous beliefs often include journey to spirit world or ancestral realm after death. Ancestors remain present and active. Death is transformation, not end. Varies by tradition.","spirit world,ancestors,transformation,varied beliefs,continuity",q3
         | 
| 83 | 
            -
            82,indigenous,ethics,moral_guidance,"Indigenous ethics center on reciprocity with nature and community, respect for elders and ancestors, seven generations thinking, and living in balance. Wisdom comes from tradition and land.","reciprocity,respect,balance,traditional wisdom,seven generations",q4
         | 
| 84 | 
            -
            83,indigenous,belief,interconnection,"Indigenous worldviews see all beings as relatives - plants, animals, rocks, rivers all have spirit. Humans are part of nature's web with responsibilities. Land is sacred, not property.","all my relations,sacred land,interconnection,reciprocity,kinship",q6
         | 
| 85 | 
            -
            84,indigenous,belief,suffering,"Suffering may be seen as imbalance, result of not honoring relationships, or spiritual lesson. Healing comes through ceremony, community support, and restoring harmony.","imbalance,ceremony,healing,restoration,community",q7
         | 
| 86 | 
            -
            85,jainism,core_belief,nature_of_divine,"Jainism is non-theistic, focusing on individual spiritual liberation rather than god-worship. The universe is eternal, uncreated. Tirthankaras (enlightened teachers) show the path but aren't gods.","non-theistic,tirthankaras,eternal universe,self-liberation",q1
         | 
| 87 | 
            -
            86,jainism,practice,spiritual_connection,"Jains practice strict non-violence (ahimsa), meditation, fasting, self-discipline, and study. Monks/nuns follow intense ascetic practices. Lay people support monastics and follow modified vows.","ahimsa,meditation,fasting,asceticism,non-violence",q2_q5
         | 
| 88 | 
            -
            87,jainism,belief,afterlife,"Jains believe in reincarnation based on karma. Liberation (moksha) comes through eliminating all karma through right conduct, non-violence, and asceticism, freeing soul from rebirth cycle.","reincarnation,karma,moksha,liberation,soul purification",q3
         | 
| 89 | 
            -
            88,jainism,ethics,moral_guidance,"Jain ethics center on ahimsa (non-violence) to all living beings. Five main vows: non-violence, truth, non-stealing, celibacy/chastity, non-attachment. Compassion extends to smallest creatures.","ahimsa,non-violence,five vows,compassion,universal",q4
         | 
| 90 | 
            -
            89,jainism,belief,interconnection,"Jainism teaches all beings have souls (jiva) and deserve absolute respect. Even plants, water, and air contain souls. Strict vegetarianism and extreme care not to harm any life.","jiva,all beings sacred,extreme non-violence,vegetarianism,reverence for life",q6
         | 
| 91 | 
            -
            90,jainism,belief,suffering,"Suffering results from karma accumulated through violence and attachment. Liberation comes through eliminating karma via strict non-violence, asceticism, and detachment from worldly concerns.","karma,non-violence,asceticism,detachment,purification",q7
         | 
| 92 | 
            -
            91,shintoism,core_belief,nature_of_divine,"Shinto honors kami - spirits in nature, ancestors, and sacred places. Kami are not all-powerful gods but spiritual essences deserving respect. No single creator deity or canonical texts.","kami,nature spirits,ancestors,polytheistic,japanese tradition",q1
         | 
| 93 | 
            -
            92,shintoism,practice,spiritual_connection,"Shinto practices include shrine visits, purification rituals (misogi), festivals (matsuri), offerings to kami, and maintaining harmony with nature. Ritual purity is important.","shrines,purification,matsuri,offerings,rituals",q2_q5
         | 
| 94 | 
            -
            93,shintoism,belief,afterlife,"Shinto has no clear afterlife doctrine. Ancestors become kami and are venerated. Focus is on this life, purity, and harmony rather than afterlife rewards/punishments.","ancestors become kami,this-life focus,veneration,unclear afterlife",q3
         | 
| 95 | 
            -
            94,shintoism,ethics,moral_guidance,"Shinto ethics emphasize purity, harmony with nature and community, gratitude, and living naturally. Morality comes from innate goodness and maintaining balance, not divine commandments.","purity,harmony,gratitude,natural living,balance",q4
         | 
| 96 | 
            -
            95,shintoism,belief,interconnection,"Shinto sees nature as sacred - mountains, rivers, trees, rocks can all house kami. Humans are part of nature, not separate. Living in harmony with natural world is spiritual imperative.","nature sacred,kami in nature,harmony,sacred places,reverence",q6
         | 
| 97 | 
            -
            96,shintoism,belief,suffering,Shinto doesn't have elaborate suffering theology. Misfortune may come from spiritual impurity or disharmony. Purification rituals and harmonious living restore balance and wellbeing.,"purification,impurity,balance,harmony,restoration",q7
         | 
| 98 | 
            -
            97,stoicism,core_belief,nature_of_divine,"Stoicism is philosophical tradition, not religion. Some ancient Stoics believed in divine reason (logos) pervading cosmos; modern Stoics may be theistic, atheistic, or agnostic. Focus is on virtue.","philosophy,logos,reason,virtue,varied divine views",q1
         | 
| 99 | 
            -
            98,stoicism,practice,spiritual_connection,"Stoics practice contemplation, journaling, virtue cultivation, and accepting what can't be controlled. Philosophical study and rational reflection replace religious ritual.","contemplation,journaling,virtue practice,rational reflection,philosophy",q2_q5
         | 
| 100 | 
            -
            99,stoicism,belief,afterlife,Ancient Stoics had varied views; many modern Stoics don't focus on afterlife. Emphasis is on living virtuously now. Some believed in soul's continuation; others focused solely on this life.,"varied views,this-life focus,virtue,unclear afterlife",q3
         | 
| 101 | 
            -
            100,stoicism,ethics,moral_guidance,"Stoic ethics center on four cardinal virtues: wisdom, justice, courage, temperance. Live according to reason and nature. Focus on what you can control; accept what you cannot.","four virtues,reason,acceptance,control,wisdom",q4
         | 
| 102 | 
            -
            101,stoicism,belief,interconnection,"Stoics see humans as part of rational, ordered cosmos. We're social beings with duties to others. Living according to nature means recognizing our place in larger whole.","cosmic order,social duty,rational nature,interconnection",q6
         | 
| 103 | 
            -
            102,stoicism,belief,suffering,"Suffering comes from mistaken judgments and desire for control over externals. By accepting fate (amor fati), focusing on virtue, and distinguishing what we control, we achieve tranquility.","acceptance,amor fati,control,judgment,tranquility",q7
         | 
| 104 | 
            -
            103,confucianism,core_belief,nature_of_divine,"Confucianism is philosophical/ethical system more than religion. Focus is on human relationships and moral cultivation, not supernatural. Some reverence for Heaven (Tian) as moral force.","philosophy,ethics,tian,human relationships,moral cultivation",q1
         | 
| 105 | 
            -
            104,confucianism,practice,spiritual_connection,"Confucian practice emphasizes ritual propriety (li), ancestor veneration, study of classics, self-cultivation, and fulfilling social roles properly. Education and moral development are central.","ritual propriety,ancestor veneration,study,self-cultivation,li",q2_q5
         | 
| 106 | 
            -
            105,confucianism,belief,afterlife,"Confucianism focuses on this life and proper conduct, not afterlife speculation. Ancestors are honored and remembered, continuing influence through descendants.","this-life focus,ancestor honor,unclear afterlife,legacy",q3
         | 
| 107 | 
            -
            106,confucianism,ethics,moral_guidance,"Confucian ethics emphasize five relationships, filial piety, benevolence (ren), righteousness (yi), and proper ritual conduct. Moral cultivation through education and self-reflection.","five relationships,filial piety,ren,yi,moral cultivation",q4
         | 
| 108 | 
            -
            107,confucianism,belief,interconnection,Confucianism sees humans as inherently social beings in web of relationships. Harmony in family and society reflects cosmic order. Proper human conduct maintains balance.,"social harmony,relationships,cosmic order,balance,interconnection",q6
         | 
| 109 | 
            -
            108,confucianism,belief,suffering,"Suffering often results from social disorder, improper relationships, or lack of virtue. Remedy through moral cultivation, proper conduct, education, and restoring harmonious relationships.","moral cultivation,harmony,proper conduct,social order",q7
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
    	
        requirements.txt
    CHANGED
    
    | @@ -1,7 +1,4 @@ | |
| 1 | 
            -
            # Flask + HTML Integration with Chatbot
         | 
| 2 | 
             
            Flask>=2.0.0
         | 
| 3 | 
             
            python-dotenv>=0.19.0
         | 
| 4 | 
            -
            together>=0.2.0
         | 
| 5 | 
            -
            gunicorn>=21.0.0
         | 
| 6 | 
            -
            openai>=1.0.0
         | 
| 7 | 
            -
            firebase-admin>=6.0.0
         | 
|  | |
| 1 | 
            +
            # Task 10 - Flask + HTML Integration with Chatbot
         | 
| 2 | 
             
            Flask>=2.0.0
         | 
| 3 | 
             
            python-dotenv>=0.19.0
         | 
| 4 | 
            +
            together>=0.2.0
         | 
|  | |
|  | |
|  | 
    	
        static/design-tokens.css
    DELETED
    
    | @@ -1,79 +0,0 @@ | |
| 1 | 
            -
            :root {
         | 
| 2 | 
            -
                /* 🎨 Primary Colors */
         | 
| 3 | 
            -
                --primary-dark: #3D3D3D;
         | 
| 4 | 
            -
                --primary-black: #1A1A1A;
         | 
| 5 | 
            -
                --primary-light: #6B7280;
         | 
| 6 | 
            -
                
         | 
| 7 | 
            -
                /* Neutral Colors */
         | 
| 8 | 
            -
                --bg-gray: #F5F5F5;
         | 
| 9 | 
            -
                --bg-white: #FFFFFF;
         | 
| 10 | 
            -
                --bg-surface-alt: #FAFAFA;
         | 
| 11 | 
            -
                --border-divider: #E9ECEF;
         | 
| 12 | 
            -
                
         | 
| 13 | 
            -
                /* Semantic Colors */
         | 
| 14 | 
            -
                --background-color-1:rgb(84, 96, 235);
         | 
| 15 | 
            -
                --background-color-2:rgb(151, 119, 249);
         | 
| 16 | 
            -
                --success: #10B981;
         | 
| 17 | 
            -
                --warning: #F59E0B;
         | 
| 18 | 
            -
                --error: #EF4444;
         | 
| 19 | 
            -
                --info: #6366F1;
         | 
| 20 | 
            -
                
         | 
| 21 | 
            -
                /* Result Ranking Colors */
         | 
| 22 | 
            -
                --rank-1: #FEF3C7;
         | 
| 23 | 
            -
                --rank-2: #DBEAFE;
         | 
| 24 | 
            -
                --rank-3: #D1FAE5;
         | 
| 25 | 
            -
             | 
| 26 | 
            -
                
         | 
| 27 | 
            -
                /* Text Colors */
         | 
| 28 | 
            -
                --text-primary: #3D3D3D;
         | 
| 29 | 
            -
                --text-secondary: #6B7280;
         | 
| 30 | 
            -
                --text-tertiary: #9CA3AF;
         | 
| 31 | 
            -
                --text-inverse: #FFFFFF;
         | 
| 32 | 
            -
                
         | 
| 33 | 
            -
                /* 📏 Typography */
         | 
| 34 | 
            -
                --font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
         | 
| 35 | 
            -
                
         | 
| 36 | 
            -
                --font-size-sm: 0.875rem;      /* 14px */
         | 
| 37 | 
            -
                --font-size-base: 1rem;        /* 16px */
         | 
| 38 | 
            -
                --font-size-lg: 1.125rem;      /* 18px */
         | 
| 39 | 
            -
                --font-size-xl: 1.25rem;       /* 20px */
         | 
| 40 | 
            -
                --font-size-2xl: 1.375rem;     /* 22px */
         | 
| 41 | 
            -
                --font-size-3xl: 2rem;       /* 24px */
         | 
| 42 | 
            -
                --font-size-4xl: 3rem;      /* 28px */
         | 
| 43 | 
            -
                
         | 
| 44 | 
            -
                --font-weight-regular: 400;
         | 
| 45 | 
            -
                --font-weight-medium: 600;
         | 
| 46 | 
            -
                --font-weight-bold: 700;
         | 
| 47 | 
            -
                --font-weight-extrabold: 800;
         | 
| 48 | 
            -
                
         | 
| 49 | 
            -
                /* 📐 Spacing System (4px base unit) */
         | 
| 50 | 
            -
                --space-xs: 0.5rem;      /* 8px */
         | 
| 51 | 
            -
                --space-sm: 0.75rem;     /* 12px */
         | 
| 52 | 
            -
                --space-md: 1rem;        /* 16px */
         | 
| 53 | 
            -
                --space-lg: 1.25rem;     /* 20px */
         | 
| 54 | 
            -
                --space-xl: 1.5rem;      /* 24px */
         | 
| 55 | 
            -
                --space-2xl: 2rem;       /* 32px */
         | 
| 56 | 
            -
                --space-3xl: 2.5rem;     /* 40px */
         | 
| 57 | 
            -
                --space-4xl: 3rem;       /* 48px */
         | 
| 58 | 
            -
                
         | 
| 59 | 
            -
                /* 🔲 Border Radius */
         | 
| 60 | 
            -
                --radius-sm: 8px;
         | 
| 61 | 
            -
                --radius-md: 10px;
         | 
| 62 | 
            -
                --radius-lg: 12px;
         | 
| 63 | 
            -
                --radius-xl: 16px;
         | 
| 64 | 
            -
                --radius-full: 50%;
         | 
| 65 | 
            -
                
         | 
| 66 | 
            -
                /* 🎭 Shadows */
         | 
| 67 | 
            -
                --shadow-sm: 0 2px 6px rgba(0, 0, 0, 0.04);
         | 
| 68 | 
            -
                --shadow-md: 0 2px 8px rgba(0, 0, 0, 0.06);
         | 
| 69 | 
            -
                --shadow-lg: 0 4px 12px rgba(0, 0, 0, 0.08);
         | 
| 70 | 
            -
                --shadow-xl: 0 4px 20px rgba(0, 0, 0, 0.08);
         | 
| 71 | 
            -
                
         | 
| 72 | 
            -
                /* 🔄 Transitions */
         | 
| 73 | 
            -
                --transition-fast: 0.2s;
         | 
| 74 | 
            -
                --transition-base: 0.3s;
         | 
| 75 | 
            -
                --transition-slow: 0.4s;
         | 
| 76 | 
            -
                
         | 
| 77 | 
            -
                /* 📱 Breakpoints */
         | 
| 78 | 
            -
                --breakpoint-mobile: 768px;
         | 
| 79 | 
            -
            }
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
    	
        static/images/Abstract Color Gradient.png
    DELETED
    
    | Git LFS Details
 | 
    	
        static/images/icon1.png
    DELETED
    
    | Git LFS Details
 | 
    	
        static/images/icon2.png
    DELETED
    
    | Git LFS Details
 | 
    	
        static/images/icon3.png
    DELETED
    
    | Git LFS Details
 | 
    	
        static/landing.css
    DELETED
    
    | @@ -1,524 +0,0 @@ | |
| 1 | 
            -
            @import url('design-tokens.css');
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            /* ==========================================================================
         | 
| 4 | 
            -
               RESET & BASE STYLES
         | 
| 5 | 
            -
               ========================================================================== */
         | 
| 6 | 
            -
             | 
| 7 | 
            -
            * {
         | 
| 8 | 
            -
                margin: 0;
         | 
| 9 | 
            -
                padding: 0;
         | 
| 10 | 
            -
                box-sizing: border-box;
         | 
| 11 | 
            -
            }
         | 
| 12 | 
            -
             | 
| 13 | 
            -
            body {
         | 
| 14 | 
            -
                font-family: var(--font-family);
         | 
| 15 | 
            -
                line-height: 1.6;
         | 
| 16 | 
            -
                color: var(--text-primary);
         | 
| 17 | 
            -
                background: #ffffff;
         | 
| 18 | 
            -
                overflow-x: hidden;
         | 
| 19 | 
            -
            }
         | 
| 20 | 
            -
             | 
| 21 | 
            -
            /* ==========================================================================
         | 
| 22 | 
            -
               ANIMATIONS
         | 
| 23 | 
            -
               ========================================================================== */
         | 
| 24 | 
            -
             | 
| 25 | 
            -
            @keyframes gradientShift {
         | 
| 26 | 
            -
                0%, 100% { transform: scale(1) rotate(0deg); }
         | 
| 27 | 
            -
                50% { transform: scale(1.1) rotate(5deg); }
         | 
| 28 | 
            -
            }
         | 
| 29 | 
            -
             | 
| 30 | 
            -
            @keyframes fadeInUp {
         | 
| 31 | 
            -
                from {
         | 
| 32 | 
            -
                    opacity: 0;
         | 
| 33 | 
            -
                    transform: translateY(30px);
         | 
| 34 | 
            -
                }
         | 
| 35 | 
            -
                to {
         | 
| 36 | 
            -
                    opacity: 1;
         | 
| 37 | 
            -
                    transform: translateY(0);
         | 
| 38 | 
            -
                }
         | 
| 39 | 
            -
            }
         | 
| 40 | 
            -
             | 
| 41 | 
            -
            /* ==========================================================================
         | 
| 42 | 
            -
               NAVIGATION
         | 
| 43 | 
            -
               ========================================================================== */
         | 
| 44 | 
            -
             | 
| 45 | 
            -
            .navbar {
         | 
| 46 | 
            -
                position: fixed;
         | 
| 47 | 
            -
                top: 0;
         | 
| 48 | 
            -
                left: 0;
         | 
| 49 | 
            -
                right: 0;
         | 
| 50 | 
            -
                background: rgba(255, 255, 255, 0);
         | 
| 51 | 
            -
                backdrop-filter: blur(10px);
         | 
| 52 | 
            -
                border-bottom: 1px solid var(--border-divider);
         | 
| 53 | 
            -
                z-index: 1000;
         | 
| 54 | 
            -
                padding: var(--space-md) 0;
         | 
| 55 | 
            -
            }
         | 
| 56 | 
            -
             | 
| 57 | 
            -
            .nav-container {
         | 
| 58 | 
            -
                max-width: 1200px;
         | 
| 59 | 
            -
                margin: 0 auto;
         | 
| 60 | 
            -
                padding: 0 var(--space-xl);
         | 
| 61 | 
            -
                display: flex;
         | 
| 62 | 
            -
                justify-content: space-between;
         | 
| 63 | 
            -
                align-items: center;
         | 
| 64 | 
            -
            }
         | 
| 65 | 
            -
             | 
| 66 | 
            -
            .logo {
         | 
| 67 | 
            -
                font-size: var(--font-size-xl);
         | 
| 68 | 
            -
                font-weight: var(--font-weight-bold);
         | 
| 69 | 
            -
                color: var(--text-primary);
         | 
| 70 | 
            -
            }
         | 
| 71 | 
            -
             | 
| 72 | 
            -
            .nav-cta {
         | 
| 73 | 
            -
                padding: var(--space-sm) var(--space-xl);
         | 
| 74 | 
            -
                background: var(--primary-dark);
         | 
| 75 | 
            -
                color: var(--text-inverse);
         | 
| 76 | 
            -
                text-decoration: none;
         | 
| 77 | 
            -
                border-radius: var(--radius-sm);
         | 
| 78 | 
            -
                font-weight: var(--font-weight-medium);
         | 
| 79 | 
            -
                font-size: var(--font-size-sm);
         | 
| 80 | 
            -
                transition: all var(--transition-base);
         | 
| 81 | 
            -
            }
         | 
| 82 | 
            -
             | 
| 83 | 
            -
            .nav-cta:hover {
         | 
| 84 | 
            -
                background: var(--primary-dark);
         | 
| 85 | 
            -
                transform: translateY(-2px);
         | 
| 86 | 
            -
                box-shadow: var(--shadow-lg);
         | 
| 87 | 
            -
            }
         | 
| 88 | 
            -
             | 
| 89 | 
            -
            /* ==========================================================================
         | 
| 90 | 
            -
               HERO SECTION
         | 
| 91 | 
            -
               ========================================================================== */
         | 
| 92 | 
            -
             | 
| 93 | 
            -
            .hero-section {
         | 
| 94 | 
            -
                padding: 120px var(--space-2xl) var(--space-3xl);
         | 
| 95 | 
            -
                text-align: center;
         | 
| 96 | 
            -
                position: relative;
         | 
| 97 | 
            -
                min-height: 100vh;
         | 
| 98 | 
            -
                display: flex;
         | 
| 99 | 
            -
                align-items: center;
         | 
| 100 | 
            -
                overflow: hidden;
         | 
| 101 | 
            -
                background: transparent;
         | 
| 102 | 
            -
            }
         | 
| 103 | 
            -
             | 
| 104 | 
            -
            .hero-container {
         | 
| 105 | 
            -
                max-width: 1000px;
         | 
| 106 | 
            -
                margin: 0 auto;
         | 
| 107 | 
            -
                position: relative;
         | 
| 108 | 
            -
                z-index: 1;
         | 
| 109 | 
            -
            }
         | 
| 110 | 
            -
             | 
| 111 | 
            -
            .hero-video {
         | 
| 112 | 
            -
                position: fixed;
         | 
| 113 | 
            -
                top: 0;
         | 
| 114 | 
            -
                left: 0;
         | 
| 115 | 
            -
                width: 100vw;
         | 
| 116 | 
            -
                height: 100vh;
         | 
| 117 | 
            -
                object-fit: cover;
         | 
| 118 | 
            -
                z-index: -1;
         | 
| 119 | 
            -
                background: #fff;
         | 
| 120 | 
            -
                opacity: .4;
         | 
| 121 | 
            -
                visibility: visible;
         | 
| 122 | 
            -
            }
         | 
| 123 | 
            -
             | 
| 124 | 
            -
            .badge {
         | 
| 125 | 
            -
                display: inline-block;
         | 
| 126 | 
            -
                padding: var(--space-xs) var(--space-md);
         | 
| 127 | 
            -
                font-size: var(--font-size-sm);
         | 
| 128 | 
            -
                font-weight: var(--font-weight-medium);
         | 
| 129 | 
            -
                color: var(--info);
         | 
| 130 | 
            -
                margin-bottom: var(--space-md);
         | 
| 131 | 
            -
                animation: fadeInUp 0.6s ease;
         | 
| 132 | 
            -
            }
         | 
| 133 | 
            -
             | 
| 134 | 
            -
            .hero-title {
         | 
| 135 | 
            -
                font-size: 4.5rem;
         | 
| 136 | 
            -
                font-weight: var(--font-weight-bold);
         | 
| 137 | 
            -
                line-height: 1.1;
         | 
| 138 | 
            -
                margin-bottom: var(--space-xl);
         | 
| 139 | 
            -
                color: var(--text-primary);
         | 
| 140 | 
            -
                animation: fadeInUp 0.6s ease 0.1s both;
         | 
| 141 | 
            -
            }
         | 
| 142 | 
            -
             | 
| 143 | 
            -
            .hero-subtitle {
         | 
| 144 | 
            -
                font-size: var(--font-size-xl);
         | 
| 145 | 
            -
                color: var(--text-primary);
         | 
| 146 | 
            -
                max-width: 600px;
         | 
| 147 | 
            -
                margin: 0 auto 6rem;
         | 
| 148 | 
            -
                line-height: 1.8;
         | 
| 149 | 
            -
                animation: fadeInUp 0.6s ease 0.2s both;
         | 
| 150 | 
            -
            }
         | 
| 151 | 
            -
             | 
| 152 | 
            -
            .cta-buttons {
         | 
| 153 | 
            -
                animation: fadeInUp 0.6s ease 0.3s both;
         | 
| 154 | 
            -
            }
         | 
| 155 | 
            -
             | 
| 156 | 
            -
            .assessment-meta {
         | 
| 157 | 
            -
                display: flex;
         | 
| 158 | 
            -
                justify-content: center;
         | 
| 159 | 
            -
                gap: var(--space-2xl);
         | 
| 160 | 
            -
                margin-top: var(--space-2xl);
         | 
| 161 | 
            -
                font-size: var(--font-size-sm);
         | 
| 162 | 
            -
                color: var(--text-secondary);
         | 
| 163 | 
            -
            }
         | 
| 164 | 
            -
             | 
| 165 | 
            -
            /* ==========================================================================
         | 
| 166 | 
            -
               BUTTONS
         | 
| 167 | 
            -
               ========================================================================== */
         | 
| 168 | 
            -
             | 
| 169 | 
            -
            .btn-primary {
         | 
| 170 | 
            -
                display: inline-flex;
         | 
| 171 | 
            -
                align-items: center;
         | 
| 172 | 
            -
                gap: var(--space-sm);
         | 
| 173 | 
            -
                padding: var(--space-md) var(--space-2xl);
         | 
| 174 | 
            -
                font-size: var(--font-size-lg);
         | 
| 175 | 
            -
                font-weight: var(--font-weight-medium);
         | 
| 176 | 
            -
                text-decoration: none;
         | 
| 177 | 
            -
                border-radius: var(--radius-md);
         | 
| 178 | 
            -
                transition: all var(--transition-base);
         | 
| 179 | 
            -
                cursor: pointer;
         | 
| 180 | 
            -
                background: var(--primary-dark);
         | 
| 181 | 
            -
                color: var(--text-inverse);
         | 
| 182 | 
            -
                box-shadow: var(--shadow-xl);
         | 
| 183 | 
            -
            }
         | 
| 184 | 
            -
             | 
| 185 | 
            -
            .btn-primary:hover {
         | 
| 186 | 
            -
                background: linear-gradient(135deg, var(--background-color-2), var(--background-color-1));
         | 
| 187 | 
            -
                box-shadow: var(--shadow-xl);
         | 
| 188 | 
            -
            }
         | 
| 189 | 
            -
             | 
| 190 | 
            -
            .btn-primary .arrow {
         | 
| 191 | 
            -
                transition: transform var(--transition-base);
         | 
| 192 | 
            -
            }
         | 
| 193 | 
            -
             | 
| 194 | 
            -
            .btn-primary:hover .arrow {
         | 
| 195 | 
            -
                transform: translateX(5px);
         | 
| 196 | 
            -
            }
         | 
| 197 | 
            -
             | 
| 198 | 
            -
            /* ==========================================================================
         | 
| 199 | 
            -
               FEATURES SECTION
         | 
| 200 | 
            -
               ========================================================================== */
         | 
| 201 | 
            -
             | 
| 202 | 
            -
            /* .features-section {
         | 
| 203 | 
            -
                width: 100vw;
         | 
| 204 | 
            -
                min-height: 100vh;
         | 
| 205 | 
            -
                background: url("images/Abstract%20Color%20Gradient.png") center/cover no-repeat;
         | 
| 206 | 
            -
                display: flex;
         | 
| 207 | 
            -
                align-items: center;
         | 
| 208 | 
            -
                justify-content: center;
         | 
| 209 | 
            -
                z-index: 2;
         | 
| 210 | 
            -
            } */
         | 
| 211 | 
            -
             | 
| 212 | 
            -
            /* landing.css */
         | 
| 213 | 
            -
            .features-section {
         | 
| 214 | 
            -
                width: 100vw;
         | 
| 215 | 
            -
                min-height: 100vh;
         | 
| 216 | 
            -
                display: flex;
         | 
| 217 | 
            -
                align-items: center;
         | 
| 218 | 
            -
                justify-content: center;
         | 
| 219 | 
            -
                position: relative;
         | 
| 220 | 
            -
                overflow: hidden;
         | 
| 221 | 
            -
                z-index: 2;
         | 
| 222 | 
            -
             | 
| 223 | 
            -
                background:  radial-gradient(
         | 
| 224 | 
            -
                        160% 130% at 50% -20%,
         | 
| 225 | 
            -
                        rgba(219, 239, 253, 1) 0%,
         | 
| 226 | 
            -
                        rgba(219, 239, 253, 0.65) 45%,
         | 
| 227 | 
            -
                        rgba(255, 255, 255, 0.75) 65%,
         | 
| 228 | 
            -
                        rgba(255, 255, 255, 1) 82%,
         | 
| 229 | 
            -
                        rgba(255, 255, 255, 1) 100%
         | 
| 230 | 
            -
                    ),
         | 
| 231 | 
            -
                    radial-gradient(
         | 
| 232 | 
            -
                        170% 170% at 50% 140%,
         | 
| 233 | 
            -
                        rgba(246, 228, 255, 0.95) 0%,
         | 
| 234 | 
            -
                        rgba(246, 228, 255, 0.55) 55%,
         | 
| 235 | 
            -
                        rgba(246, 228, 255, 0.15) 78%,
         | 
| 236 | 
            -
                        rgba(255, 255, 255, 1) 100%
         | 
| 237 | 
            -
                    );
         | 
| 238 | 
            -
            }
         | 
| 239 | 
            -
             | 
| 240 | 
            -
            .section-container {
         | 
| 241 | 
            -
                max-width: 1200px;
         | 
| 242 | 
            -
                margin: 0 auto;
         | 
| 243 | 
            -
                padding: 0 var(--space-xl);
         | 
| 244 | 
            -
            }
         | 
| 245 | 
            -
             | 
| 246 | 
            -
            .section-header {
         | 
| 247 | 
            -
                text-align: center;
         | 
| 248 | 
            -
                margin-bottom: var(--space-2xl);
         | 
| 249 | 
            -
            }
         | 
| 250 | 
            -
             | 
| 251 | 
            -
            .section-header h2 {
         | 
| 252 | 
            -
                font-size: var(--font-size-4xl);
         | 
| 253 | 
            -
                font-weight: var(--font-weight-extrabold);
         | 
| 254 | 
            -
                color: var(--text-primary);
         | 
| 255 | 
            -
                margin-bottom: var(--space-md);
         | 
| 256 | 
            -
            }
         | 
| 257 | 
            -
             | 
| 258 | 
            -
            .section-subtitle {
         | 
| 259 | 
            -
                font-size: var(--font-size-xl);      /* same as hero-subtitle */
         | 
| 260 | 
            -
                color: var(--text-primary);          /* hero uses primary */
         | 
| 261 | 
            -
                max-width: 600px;                    /* hero-subtitle width */
         | 
| 262 | 
            -
                margin: 0 auto var(--space-4xl);     /* centered, comfortable bottom space */
         | 
| 263 | 
            -
                line-height: 1.8;                     /* easier reading like hero */
         | 
| 264 | 
            -
                animation: fadeInUp 0.6s ease 0.2s both; /* subtle entrance like hero */
         | 
| 265 | 
            -
            }
         | 
| 266 | 
            -
             | 
| 267 | 
            -
            .section-header p {
         | 
| 268 | 
            -
                font-size: var(--font-size-xl);
         | 
| 269 | 
            -
                color: var(--text-secondary);
         | 
| 270 | 
            -
            }
         | 
| 271 | 
            -
             | 
| 272 | 
            -
            .features-grid {
         | 
| 273 | 
            -
                display: grid;
         | 
| 274 | 
            -
                grid-template-columns: repeat(3, 1fr);
         | 
| 275 | 
            -
                gap: var(--space-xl);
         | 
| 276 | 
            -
                justify-items: center;
         | 
| 277 | 
            -
            }
         | 
| 278 | 
            -
             | 
| 279 | 
            -
            .feature-card {
         | 
| 280 | 
            -
                background: var(--bg-white);
         | 
| 281 | 
            -
                padding: var(--space-3xl);
         | 
| 282 | 
            -
                border-radius: var(--radius-lg);
         | 
| 283 | 
            -
                box-shadow: var(--shadow-md);
         | 
| 284 | 
            -
                transition: all var(--transition-base);
         | 
| 285 | 
            -
            }
         | 
| 286 | 
            -
             | 
| 287 | 
            -
            .feature-card:hover {
         | 
| 288 | 
            -
                transform: translateY(-8px);
         | 
| 289 | 
            -
                box-shadow: var(--shadow-xl);
         | 
| 290 | 
            -
            }
         | 
| 291 | 
            -
             | 
| 292 | 
            -
            .feature-icon-img {
         | 
| 293 | 
            -
                width: 68px;
         | 
| 294 | 
            -
                height: 68px;
         | 
| 295 | 
            -
                object-fit: contain;
         | 
| 296 | 
            -
            }
         | 
| 297 | 
            -
             | 
| 298 | 
            -
            .feature-card h3 {
         | 
| 299 | 
            -
                font-size: var(--font-size-2xl);
         | 
| 300 | 
            -
                font-weight: var(--font-weight-bold);
         | 
| 301 | 
            -
                color: var(--text-primary);
         | 
| 302 | 
            -
                margin-bottom: var(--space-md);
         | 
| 303 | 
            -
            }
         | 
| 304 | 
            -
             | 
| 305 | 
            -
            .feature-card p {
         | 
| 306 | 
            -
                color: var(--text-secondary);
         | 
| 307 | 
            -
                line-height: 1.8;
         | 
| 308 | 
            -
            }
         | 
| 309 | 
            -
             | 
| 310 | 
            -
            /* ==========================================================================
         | 
| 311 | 
            -
               CTA SECTION
         | 
| 312 | 
            -
               ========================================================================== */
         | 
| 313 | 
            -
             | 
| 314 | 
            -
            .cta-section {
         | 
| 315 | 
            -
                height: 100vh;
         | 
| 316 | 
            -
                display: flex;
         | 
| 317 | 
            -
                align-items: center;
         | 
| 318 | 
            -
                justify-content: center;
         | 
| 319 | 
            -
                text-align: center;
         | 
| 320 | 
            -
                color: var(--text-inverse);
         | 
| 321 | 
            -
            }
         | 
| 322 | 
            -
             | 
| 323 | 
            -
            .cta-container h2 {
         | 
| 324 | 
            -
                font-size: var(--font-size-4xl);
         | 
| 325 | 
            -
                font-weight: var(--font-weight-bold);
         | 
| 326 | 
            -
                margin-bottom: var(--space-md);
         | 
| 327 | 
            -
                color: var(--text-primary);
         | 
| 328 | 
            -
            }
         | 
| 329 | 
            -
             | 
| 330 | 
            -
            .cta-container p {
         | 
| 331 | 
            -
                font-size: var(--font-size-xl);
         | 
| 332 | 
            -
                margin-bottom: var(--space-3xl);
         | 
| 333 | 
            -
                color: var(--text-primary);
         | 
| 334 | 
            -
            }
         | 
| 335 | 
            -
             | 
| 336 | 
            -
            /* ==========================================================================
         | 
| 337 | 
            -
               FOOTER
         | 
| 338 | 
            -
               ========================================================================== */
         | 
| 339 | 
            -
             | 
| 340 | 
            -
            .footer {
         | 
| 341 | 
            -
                background: var(--primary-dark);
         | 
| 342 | 
            -
                color: var(--text-inverse);
         | 
| 343 | 
            -
                padding: var(--space-md) var(--space-md);
         | 
| 344 | 
            -
                text-align: center;
         | 
| 345 | 
            -
            }
         | 
| 346 | 
            -
             | 
| 347 | 
            -
            .footer-container {
         | 
| 348 | 
            -
                max-width: 1200px;
         | 
| 349 | 
            -
                margin: 0 auto;
         | 
| 350 | 
            -
            }
         | 
| 351 | 
            -
             | 
| 352 | 
            -
            .footer p {
         | 
| 353 | 
            -
                opacity: 0.7;
         | 
| 354 | 
            -
            }
         | 
| 355 | 
            -
             | 
| 356 | 
            -
            /* ==========================================================================
         | 
| 357 | 
            -
               RESPONSIVE DESIGN
         | 
| 358 | 
            -
               ========================================================================== */
         | 
| 359 | 
            -
             | 
| 360 | 
            -
            /* Tablet and smaller desktop */
         | 
| 361 | 
            -
            @media (max-width: 1024px) {
         | 
| 362 | 
            -
                .hero-title {
         | 
| 363 | 
            -
                    font-size: 3.5rem;
         | 
| 364 | 
            -
                }
         | 
| 365 | 
            -
                
         | 
| 366 | 
            -
                .features-grid {
         | 
| 367 | 
            -
                    grid-template-columns: repeat(2, 1fr);
         | 
| 368 | 
            -
                    gap: var(--space-lg);
         | 
| 369 | 
            -
                }
         | 
| 370 | 
            -
                
         | 
| 371 | 
            -
                .feature-card {
         | 
| 372 | 
            -
                    padding: var(--space-xl);
         | 
| 373 | 
            -
                }
         | 
| 374 | 
            -
            }
         | 
| 375 | 
            -
             | 
| 376 | 
            -
            /* Mobile landscape and smaller tablets */
         | 
| 377 | 
            -
            @media (max-width: 768px) {
         | 
| 378 | 
            -
                .nav-container {
         | 
| 379 | 
            -
                    padding: 0 var(--space-md);
         | 
| 380 | 
            -
                }
         | 
| 381 | 
            -
             | 
| 382 | 
            -
                .hero-section {
         | 
| 383 | 
            -
                    padding: 100px var(--space-md) var(--space-3xl);
         | 
| 384 | 
            -
                    min-height: 100vh;
         | 
| 385 | 
            -
                }
         | 
| 386 | 
            -
                
         | 
| 387 | 
            -
                .hero-title {
         | 
| 388 | 
            -
                    font-size: 2.5rem;
         | 
| 389 | 
            -
                    line-height: 1.2;
         | 
| 390 | 
            -
                }
         | 
| 391 | 
            -
                
         | 
| 392 | 
            -
                .hero-subtitle {
         | 
| 393 | 
            -
                    font-size: var(--font-size-lg);
         | 
| 394 | 
            -
                    margin: 0 auto var(--space-2xl);
         | 
| 395 | 
            -
                }
         | 
| 396 | 
            -
                
         | 
| 397 | 
            -
                .assessment-meta {
         | 
| 398 | 
            -
                    flex-direction: column;
         | 
| 399 | 
            -
                    gap: var(--space-sm);
         | 
| 400 | 
            -
                    margin-top: var(--space-xl);
         | 
| 401 | 
            -
                }
         | 
| 402 | 
            -
                
         | 
| 403 | 
            -
                .btn-primary {
         | 
| 404 | 
            -
                    padding: var(--space-md) var(--space-xl);
         | 
| 405 | 
            -
                    font-size: var(--font-size-base);
         | 
| 406 | 
            -
                    width: 100%;
         | 
| 407 | 
            -
                    max-width: 300px;
         | 
| 408 | 
            -
                    justify-content: center;
         | 
| 409 | 
            -
                }
         | 
| 410 | 
            -
                
         | 
| 411 | 
            -
                .features-section {
         | 
| 412 | 
            -
                    height: auto;
         | 
| 413 | 
            -
                    min-height: 100vh;
         | 
| 414 | 
            -
                    padding: var(--space-3xl) 0;
         | 
| 415 | 
            -
                }
         | 
| 416 | 
            -
                
         | 
| 417 | 
            -
                .section-container {
         | 
| 418 | 
            -
                    padding: 0 var(--space-md);
         | 
| 419 | 
            -
                }
         | 
| 420 | 
            -
                
         | 
| 421 | 
            -
                .section-header h2 {
         | 
| 422 | 
            -
                    font-size: var(--font-size-2xl);
         | 
| 423 | 
            -
                }
         | 
| 424 | 
            -
                
         | 
| 425 | 
            -
                .section-header p {
         | 
| 426 | 
            -
                    font-size: var(--font-size-lg);
         | 
| 427 | 
            -
                }
         | 
| 428 | 
            -
                
         | 
| 429 | 
            -
                .features-grid {
         | 
| 430 | 
            -
                    grid-template-columns: 1fr;
         | 
| 431 | 
            -
                    gap: var(--space-lg);
         | 
| 432 | 
            -
                }
         | 
| 433 | 
            -
                
         | 
| 434 | 
            -
                .feature-card {
         | 
| 435 | 
            -
                    padding: var(--space-xl);
         | 
| 436 | 
            -
                    margin: 0 var(--space-sm);
         | 
| 437 | 
            -
                }
         | 
| 438 | 
            -
                
         | 
| 439 | 
            -
                .cta-section {
         | 
| 440 | 
            -
                    height: auto;
         | 
| 441 | 
            -
                    min-height: 100vh;
         | 
| 442 | 
            -
                    padding: var(--space-3xl) var(--space-md);
         | 
| 443 | 
            -
                }
         | 
| 444 | 
            -
                
         | 
| 445 | 
            -
                .cta-container h2 {
         | 
| 446 | 
            -
                    font-size: var(--font-size-2xl);
         | 
| 447 | 
            -
                    margin-bottom: var(--space-lg);
         | 
| 448 | 
            -
                }
         | 
| 449 | 
            -
                
         | 
| 450 | 
            -
                .cta-container p {
         | 
| 451 | 
            -
                    font-size: var(--font-size-lg);
         | 
| 452 | 
            -
                    margin-bottom: var(--space-2xl);
         | 
| 453 | 
            -
                }
         | 
| 454 | 
            -
                
         | 
| 455 | 
            -
                .nav-cta {
         | 
| 456 | 
            -
                    padding: var(--space-sm) var(--space-lg);
         | 
| 457 | 
            -
                    font-size: var(--font-size-sm);
         | 
| 458 | 
            -
                }
         | 
| 459 | 
            -
            }
         | 
| 460 | 
            -
             | 
| 461 | 
            -
            /* Small mobile devices */
         | 
| 462 | 
            -
            @media (max-width: 480px) {
         | 
| 463 | 
            -
                .hero-section {
         | 
| 464 | 
            -
                    padding: 80px var(--space-sm) var(--space-2xl);
         | 
| 465 | 
            -
                }
         | 
| 466 | 
            -
                
         | 
| 467 | 
            -
                .hero-title {
         | 
| 468 | 
            -
                    font-size: 2rem;
         | 
| 469 | 
            -
                }
         | 
| 470 | 
            -
                
         | 
| 471 | 
            -
                .hero-subtitle {
         | 
| 472 | 
            -
                    font-size: var(--font-size-base);
         | 
| 473 | 
            -
                }
         | 
| 474 | 
            -
                
         | 
| 475 | 
            -
                .section-container {
         | 
| 476 | 
            -
                    padding: 0 var(--space-sm);
         | 
| 477 | 
            -
                }
         | 
| 478 | 
            -
                
         | 
| 479 | 
            -
                .feature-card {
         | 
| 480 | 
            -
                    padding: var(--space-lg);
         | 
| 481 | 
            -
                    margin: 0;
         | 
| 482 | 
            -
                }
         | 
| 483 | 
            -
                
         | 
| 484 | 
            -
                .cta-section {
         | 
| 485 | 
            -
                    padding: var(--space-2xl) var(--space-sm);
         | 
| 486 | 
            -
                }
         | 
| 487 | 
            -
                
         | 
| 488 | 
            -
                .cta-container h2 {
         | 
| 489 | 
            -
                    font-size: var(--font-size-xl);
         | 
| 490 | 
            -
                }
         | 
| 491 | 
            -
                
         | 
| 492 | 
            -
                .cta-container p {
         | 
| 493 | 
            -
                    font-size: var(--font-size-base);
         | 
| 494 | 
            -
                }
         | 
| 495 | 
            -
                
         | 
| 496 | 
            -
                .btn-primary {
         | 
| 497 | 
            -
                    padding: var(--space-sm) var(--space-lg);
         | 
| 498 | 
            -
                    font-size: var(--font-size-sm);
         | 
| 499 | 
            -
                }
         | 
| 500 | 
            -
                
         | 
| 501 | 
            -
                .nav-cta {
         | 
| 502 | 
            -
                    padding: var(--space-xs) var(--space-md);
         | 
| 503 | 
            -
                    font-size: var(--font-size-xs);
         | 
| 504 | 
            -
                }
         | 
| 505 | 
            -
            }
         | 
| 506 | 
            -
             | 
| 507 | 
            -
            /* Very small mobile devices */
         | 
| 508 | 
            -
            @media (max-width: 320px) {
         | 
| 509 | 
            -
                .hero-title {
         | 
| 510 | 
            -
                    font-size: 1.8rem;
         | 
| 511 | 
            -
                }
         | 
| 512 | 
            -
                
         | 
| 513 | 
            -
                .hero-subtitle {
         | 
| 514 | 
            -
                    font-size: var(--font-size-sm);
         | 
| 515 | 
            -
                }
         | 
| 516 | 
            -
                
         | 
| 517 | 
            -
                .feature-card {
         | 
| 518 | 
            -
                    padding: var(--space-md);
         | 
| 519 | 
            -
                }
         | 
| 520 | 
            -
                
         | 
| 521 | 
            -
                .cta-container h2 {
         | 
| 522 | 
            -
                    font-size: var(--font-size-lg);
         | 
| 523 | 
            -
                }
         | 
| 524 | 
            -
            }
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
    	
        static/script.js
    CHANGED
    
    | @@ -3,214 +3,33 @@ function sanitizeReligionName(name) { | |
| 3 | 
             
                return name.replace(/\s+/g, '-');
         | 
| 4 | 
             
            }
         | 
| 5 |  | 
| 6 | 
            -
            // ==================== FIREBASE AUTHENTICATION ====================
         | 
| 7 | 
            -
             | 
| 8 | 
            -
            // Google Sign-In with Firebase
         | 
| 9 | 
            -
            async function signInWithGoogle() {
         | 
| 10 | 
            -
                if (!window.firebaseEnabled || !window.firebaseAuth) {
         | 
| 11 | 
            -
                    document.getElementById('result').innerHTML = 
         | 
| 12 | 
            -
                        '<p class="error-msg">⚠️ Firebase not configured</p>';
         | 
| 13 | 
            -
                    return;
         | 
| 14 | 
            -
                }
         | 
| 15 | 
            -
                
         | 
| 16 | 
            -
                const provider = new firebase.auth.GoogleAuthProvider();
         | 
| 17 | 
            -
                
         | 
| 18 | 
            -
                // Configure provider for better popup behavior
         | 
| 19 | 
            -
                provider.setCustomParameters({
         | 
| 20 | 
            -
                    prompt: 'select_account'  // Always show account selection
         | 
| 21 | 
            -
                });
         | 
| 22 | 
            -
                
         | 
| 23 | 
            -
                try {
         | 
| 24 | 
            -
                    // Show loading state
         | 
| 25 | 
            -
                    const resultDiv = document.getElementById('result');
         | 
| 26 | 
            -
                    if (resultDiv) {
         | 
| 27 | 
            -
                        resultDiv.innerHTML = '<p style="color: #666;">Opening sign-in window...</p>';
         | 
| 28 | 
            -
                    }
         | 
| 29 | 
            -
                    
         | 
| 30 | 
            -
                    const result = await window.firebaseAuth.signInWithPopup(provider);
         | 
| 31 | 
            -
                    const user = result.user;
         | 
| 32 | 
            -
                    
         | 
| 33 | 
            -
                    if (resultDiv) {
         | 
| 34 | 
            -
                        resultDiv.innerHTML = '<p style="color: #666;">Signing in...</p>';
         | 
| 35 | 
            -
                    }
         | 
| 36 | 
            -
                    
         | 
| 37 | 
            -
                    // Get ID token to send to backend
         | 
| 38 | 
            -
                    const idToken = await user.getIdToken();
         | 
| 39 | 
            -
                    
         | 
| 40 | 
            -
                    // Send to backend for session creation
         | 
| 41 | 
            -
                    const endpoint = window.location.pathname === '/signup' ? '/signup' : '/login';
         | 
| 42 | 
            -
                    const response = await fetch(endpoint, {
         | 
| 43 | 
            -
                        method: 'POST',
         | 
| 44 | 
            -
                        headers: {'Content-Type': 'application/json'},
         | 
| 45 | 
            -
                        body: JSON.stringify({idToken}),
         | 
| 46 | 
            -
                        credentials: 'same-origin'
         | 
| 47 | 
            -
                    });
         | 
| 48 | 
            -
                    
         | 
| 49 | 
            -
                    const data = await response.json();
         | 
| 50 | 
            -
                    
         | 
| 51 | 
            -
                    if (data.success) {
         | 
| 52 | 
            -
                        window.location.href = '/assessment';
         | 
| 53 | 
            -
                    } else {
         | 
| 54 | 
            -
                        document.getElementById('result').innerHTML = 
         | 
| 55 | 
            -
                            `<p class="error-msg">${data.message || 'Authentication failed'}</p>`;
         | 
| 56 | 
            -
                    }
         | 
| 57 | 
            -
                } catch (error) {
         | 
| 58 | 
            -
                    console.error('Google Sign-In Error:', error);
         | 
| 59 | 
            -
                    console.error('Error code:', error.code);
         | 
| 60 | 
            -
                    console.error('Error details:', error);
         | 
| 61 | 
            -
                    
         | 
| 62 | 
            -
                    const resultDiv = document.getElementById('result');
         | 
| 63 | 
            -
                    let errorMsg = '';
         | 
| 64 | 
            -
                    
         | 
| 65 | 
            -
                    // Handle specific error cases
         | 
| 66 | 
            -
                    if (error.code === 'auth/popup-closed-by-user') {
         | 
| 67 | 
            -
                        errorMsg = '❌ Sign-in window was closed. Please try again and complete the sign-in process.';
         | 
| 68 | 
            -
                    } else if (error.code === 'auth/popup-blocked') {
         | 
| 69 | 
            -
                        errorMsg = '❌ Pop-up was blocked by your browser. Please allow pop-ups for this site and try again.';
         | 
| 70 | 
            -
                    } else if (error.code === 'auth/cancelled-popup-request') {
         | 
| 71 | 
            -
                        errorMsg = '❌ Another sign-in is in progress. Please wait a moment and try again.';
         | 
| 72 | 
            -
                    } else if (error.code === 'auth/unauthorized-domain') {
         | 
| 73 | 
            -
                        errorMsg = '❌ This domain is not authorized for Google Sign-In. Please contact the administrator.';
         | 
| 74 | 
            -
                    } else if (error.code === 'auth/operation-not-allowed') {
         | 
| 75 | 
            -
                        errorMsg = '❌ Google Sign-In is not enabled. Please contact the administrator.';
         | 
| 76 | 
            -
                    } else if (error.code === 'auth/network-request-failed') {
         | 
| 77 | 
            -
                        errorMsg = '❌ Network error. Please check your internet connection and try again.';
         | 
| 78 | 
            -
                    } else {
         | 
| 79 | 
            -
                        errorMsg = `❌ ${error.message || 'Google Sign-In failed. Please try again.'}`;
         | 
| 80 | 
            -
                    }
         | 
| 81 | 
            -
                    
         | 
| 82 | 
            -
                    if (resultDiv) {
         | 
| 83 | 
            -
                        resultDiv.innerHTML = `<p class="error-msg">${errorMsg}</p>`;
         | 
| 84 | 
            -
                    }
         | 
| 85 | 
            -
                }
         | 
| 86 | 
            -
            }
         | 
| 87 | 
            -
             | 
| 88 | 
            -
            // Firebase Email/Password Authentication
         | 
| 89 | 
            -
            async function authenticateWithFirebase(email, password, isSignup) {
         | 
| 90 | 
            -
                if (!window.firebaseEnabled || !window.firebaseAuth) {
         | 
| 91 | 
            -
                    return null; // Fall back to legacy auth
         | 
| 92 | 
            -
                }
         | 
| 93 | 
            -
                
         | 
| 94 | 
            -
                try {
         | 
| 95 | 
            -
                    let userCredential;
         | 
| 96 | 
            -
                    
         | 
| 97 | 
            -
                    if (isSignup) {
         | 
| 98 | 
            -
                        // Create new user with Firebase
         | 
| 99 | 
            -
                        userCredential = await window.firebaseAuth.createUserWithEmailAndPassword(email, password);
         | 
| 100 | 
            -
                        
         | 
| 101 | 
            -
                        // Send email verification
         | 
| 102 | 
            -
                        await userCredential.user.sendEmailVerification();
         | 
| 103 | 
            -
                    } else {
         | 
| 104 | 
            -
                        // Sign in existing user
         | 
| 105 | 
            -
                        userCredential = await window.firebaseAuth.signInWithEmailAndPassword(email, password);
         | 
| 106 | 
            -
                        
         | 
| 107 | 
            -
                        // Check if email is verified
         | 
| 108 | 
            -
                        if (!userCredential.user.emailVerified) {
         | 
| 109 | 
            -
                            document.getElementById('result').innerHTML = 
         | 
| 110 | 
            -
                                '<p class="error-msg">⚠️ Please verify your email first. Check your inbox.</p>';
         | 
| 111 | 
            -
                            await window.firebaseAuth.signOut();
         | 
| 112 | 
            -
                            return null;
         | 
| 113 | 
            -
                        }
         | 
| 114 | 
            -
                    }
         | 
| 115 | 
            -
                    
         | 
| 116 | 
            -
                    // Get ID token
         | 
| 117 | 
            -
                    const idToken = await userCredential.user.getIdToken();
         | 
| 118 | 
            -
                    return idToken;
         | 
| 119 | 
            -
                    
         | 
| 120 | 
            -
                } catch (error) {
         | 
| 121 | 
            -
                    console.error('Firebase Auth Error:', error);
         | 
| 122 | 
            -
                    throw error;
         | 
| 123 | 
            -
                }
         | 
| 124 | 
            -
            }
         | 
| 125 | 
            -
             | 
| 126 | 
             
            // ==================== AUTHENTICATION ====================
         | 
| 127 |  | 
| 128 | 
            -
             | 
| 129 | 
            -
                const  | 
| 130 | 
            -
                const username = document.getElementById('authUsername') ? document.getElementById('authUsername').value.trim() : '';
         | 
| 131 | 
             
                const password = document.getElementById('authPassword').value;
         | 
| 132 |  | 
| 133 | 
            -
                if (! | 
| 134 | 
             
                    document.getElementById('result').innerHTML = 
         | 
| 135 | 
             
                        '<p class="error-msg">⚠️ Please fill in all fields</p>';
         | 
| 136 | 
             
                    return;
         | 
| 137 | 
             
                }
         | 
| 138 |  | 
| 139 | 
            -
                const  | 
| 140 | 
            -
                const endpoint = isSignup ? '/signup' : '/login';
         | 
| 141 | 
            -
                
         | 
| 142 | 
            -
                // Try Firebase authentication first if available
         | 
| 143 | 
            -
                if (window.firebaseEnabled) {
         | 
| 144 | 
            -
                    try {
         | 
| 145 | 
            -
                        const idToken = await authenticateWithFirebase(email, password, isSignup);
         | 
| 146 | 
            -
                        
         | 
| 147 | 
            -
                        if (!idToken) {
         | 
| 148 | 
            -
                            return; // Error already displayed
         | 
| 149 | 
            -
                        }
         | 
| 150 | 
            -
                        
         | 
| 151 | 
            -
                        // Send token to backend
         | 
| 152 | 
            -
                        const response = await fetch(endpoint, {
         | 
| 153 | 
            -
                            method: 'POST',
         | 
| 154 | 
            -
                            headers: {'Content-Type': 'application/json'},
         | 
| 155 | 
            -
                            body: JSON.stringify({idToken}),
         | 
| 156 | 
            -
                            credentials: 'same-origin'
         | 
| 157 | 
            -
                        });
         | 
| 158 | 
            -
                        
         | 
| 159 | 
            -
                        const data = await response.json();
         | 
| 160 | 
            -
                        
         | 
| 161 | 
            -
                        if (data.success) {
         | 
| 162 | 
            -
                            if (isSignup) {
         | 
| 163 | 
            -
                                document.getElementById('result').innerHTML = 
         | 
| 164 | 
            -
                                    '<p class="success-msg">✅ Account created! Please check your email to verify.</p>';
         | 
| 165 | 
            -
                            } else {
         | 
| 166 | 
            -
                                window.location.href = '/assessment';
         | 
| 167 | 
            -
                            }
         | 
| 168 | 
            -
                        } else {
         | 
| 169 | 
            -
                            document.getElementById('result').innerHTML = 
         | 
| 170 | 
            -
                                `<p class="error-msg">${data.message || 'Authentication failed'}</p>`;
         | 
| 171 | 
            -
                        }
         | 
| 172 | 
            -
                        return;
         | 
| 173 | 
            -
                    } catch (error) {
         | 
| 174 | 
            -
                        console.error('Firebase auth error:', error);
         | 
| 175 | 
            -
                        document.getElementById('result').innerHTML = 
         | 
| 176 | 
            -
                            `<p class="error-msg">${error.message || 'Authentication failed'}</p>`;
         | 
| 177 | 
            -
                        return;
         | 
| 178 | 
            -
                    }
         | 
| 179 | 
            -
                }
         | 
| 180 | 
            -
                
         | 
| 181 | 
            -
                // Legacy authentication fallback (if Firebase is disabled)
         | 
| 182 | 
            -
                const body = isSignup 
         | 
| 183 | 
            -
                    ? {username, password, email} 
         | 
| 184 | 
            -
                    : {username, password};
         | 
| 185 |  | 
| 186 | 
             
                fetch(endpoint, {
         | 
| 187 | 
             
                    method: 'POST',
         | 
| 188 | 
             
                    headers: {'Content-Type': 'application/json'},
         | 
| 189 | 
            -
                    body: JSON.stringify( | 
| 190 | 
            -
                    credentials: 'same-origin'
         | 
| 191 | 
            -
                })
         | 
| 192 | 
            -
                .then(response => {
         | 
| 193 | 
            -
                    if (!response.ok) {
         | 
| 194 | 
            -
                        return response.json().then(err => Promise.reject(err));
         | 
| 195 | 
            -
                    }
         | 
| 196 | 
            -
                    return response.json();
         | 
| 197 | 
             
                })
         | 
|  | |
| 198 | 
             
                .then(data => {
         | 
| 199 | 
             
                    if (data.success) {
         | 
| 200 | 
            -
                         | 
| 201 | 
            -
                            document.getElementById('result').innerHTML = 
         | 
| 202 | 
            -
                                '<p class="success-msg">✅ ' + (data.message || 'Account created! Please check your email to verify.') + '</p>';
         | 
| 203 | 
            -
                        } else {
         | 
| 204 | 
            -
                            window.location.href = '/assessment';
         | 
| 205 | 
            -
                        }
         | 
| 206 | 
             
                    } else {
         | 
| 207 | 
             
                        document.getElementById('result').innerHTML = 
         | 
| 208 | 
            -
                            `<p class="error-msg">${data.message | 
| 209 | 
             
                    }
         | 
| 210 | 
            -
                })
         | 
| 211 | 
            -
                .catch(error => {
         | 
| 212 | 
            -
                    document.getElementById('result').innerHTML = 
         | 
| 213 | 
            -
                        `<p class="error-msg">${error.message || 'Network error. Please try again.'}</p>`;
         | 
| 214 | 
             
                });
         | 
| 215 | 
             
            }
         | 
| 216 |  | 
| @@ -219,80 +38,6 @@ function switchAuth() { | |
| 219 | 
             
                window.location.href = newPath;
         | 
| 220 | 
             
            }
         | 
| 221 |  | 
| 222 | 
            -
            function resetPassword() {
         | 
| 223 | 
            -
                const email = document.getElementById('resetEmail').value.trim();
         | 
| 224 | 
            -
                
         | 
| 225 | 
            -
                if (!email) {
         | 
| 226 | 
            -
                    document.getElementById('result').innerHTML = 
         | 
| 227 | 
            -
                        '<p class="error-msg">⚠️ Please enter your email</p>';
         | 
| 228 | 
            -
                    return;
         | 
| 229 | 
            -
                }
         | 
| 230 | 
            -
                
         | 
| 231 | 
            -
                fetch('/forgot-password', {
         | 
| 232 | 
            -
                    method: 'POST',
         | 
| 233 | 
            -
                    headers: {'Content-Type': 'application/json'},
         | 
| 234 | 
            -
                    body: JSON.stringify({email}),
         | 
| 235 | 
            -
                    credentials: 'same-origin'
         | 
| 236 | 
            -
                })
         | 
| 237 | 
            -
                .then(response => {
         | 
| 238 | 
            -
                    if (!response.ok) {
         | 
| 239 | 
            -
                        return response.json().then(err => Promise.reject(err));
         | 
| 240 | 
            -
                    }
         | 
| 241 | 
            -
                    return response.json();
         | 
| 242 | 
            -
                })
         | 
| 243 | 
            -
                .then(data => {
         | 
| 244 | 
            -
                    if (data.success) {
         | 
| 245 | 
            -
                        document.getElementById('result').innerHTML = 
         | 
| 246 | 
            -
                            '<p class="success-msg">✅ Password reset link sent! Check your email (or server console in dev mode).</p>';
         | 
| 247 | 
            -
                    } else {
         | 
| 248 | 
            -
                        document.getElementById('result').innerHTML = 
         | 
| 249 | 
            -
                            `<p class="error-msg">${data.message || 'Failed to send reset link'}</p>`;
         | 
| 250 | 
            -
                    }
         | 
| 251 | 
            -
                })
         | 
| 252 | 
            -
                .catch(error => {
         | 
| 253 | 
            -
                    document.getElementById('result').innerHTML = 
         | 
| 254 | 
            -
                        `<p class="error-msg">${error.message || 'Network error. Please try again.'}</p>`;
         | 
| 255 | 
            -
                });
         | 
| 256 | 
            -
            }
         | 
| 257 | 
            -
             | 
| 258 | 
            -
            function submitPasswordReset() {
         | 
| 259 | 
            -
                const token = document.getElementById('resetToken').value;
         | 
| 260 | 
            -
                const password = document.getElementById('resetPassword').value;
         | 
| 261 | 
            -
                
         | 
| 262 | 
            -
                if (!password) {
         | 
| 263 | 
            -
                    document.getElementById('result').innerHTML = 
         | 
| 264 | 
            -
                        '<p class="error-msg">⚠️ Please enter a new password</p>';
         | 
| 265 | 
            -
                    return;
         | 
| 266 | 
            -
                }
         | 
| 267 | 
            -
                
         | 
| 268 | 
            -
                fetch('/reset-password-submit', {
         | 
| 269 | 
            -
                    method: 'POST',
         | 
| 270 | 
            -
                    headers: {'Content-Type': 'application/json'},
         | 
| 271 | 
            -
                    body: JSON.stringify({token, password}),
         | 
| 272 | 
            -
                    credentials: 'same-origin'
         | 
| 273 | 
            -
                })
         | 
| 274 | 
            -
                .then(response => {
         | 
| 275 | 
            -
                    if (!response.ok) {
         | 
| 276 | 
            -
                        return response.json().then(err => Promise.reject(err));
         | 
| 277 | 
            -
                    }
         | 
| 278 | 
            -
                    return response.json();
         | 
| 279 | 
            -
                })
         | 
| 280 | 
            -
                .then(data => {
         | 
| 281 | 
            -
                    if (data.success) {
         | 
| 282 | 
            -
                        document.getElementById('result').innerHTML = 
         | 
| 283 | 
            -
                            '<p class="success-msg">✅ Password reset successfully! Redirecting to login...</p>';
         | 
| 284 | 
            -
                        setTimeout(() => window.location.href = '/login', 1500);
         | 
| 285 | 
            -
                    } else {
         | 
| 286 | 
            -
                        document.getElementById('result').innerHTML = 
         | 
| 287 | 
            -
                            `<p class="error-msg">${data.message || 'Failed to reset password'}</p>`;
         | 
| 288 | 
            -
                    }
         | 
| 289 | 
            -
                })
         | 
| 290 | 
            -
                .catch(error => {
         | 
| 291 | 
            -
                    document.getElementById('result').innerHTML = 
         | 
| 292 | 
            -
                        `<p class="error-msg">${error.message || 'Network error. Please try again.'}</p>`;
         | 
| 293 | 
            -
                });
         | 
| 294 | 
            -
            }
         | 
| 295 | 
            -
             | 
| 296 | 
             
            // ==================== ASSESSMENT ====================
         | 
| 297 |  | 
| 298 | 
             
            var currentQuestion = 1;
         | 
| @@ -324,22 +69,34 @@ function showQuestion(questionIndex) { | |
| 324 | 
             
                    block.classList.remove('active');
         | 
| 325 | 
             
                    var blockIndex = parseInt(block.getAttribute('data-question-index'));
         | 
| 326 | 
             
                    if (blockIndex === questionIndex) block.classList.add('active');
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
| 327 | 
             
                });
         | 
| 328 |  | 
| 329 | 
             
                currentQuestion = questionIndex;
         | 
| 330 | 
             
                document.getElementById('questionCounter').textContent = 'Question ' + questionIndex + ' of ' + totalQuestions;
         | 
| 331 | 
            -
                document.getElementById('progressBar').style.width = ((questionIndex - 1) /  | 
| 332 | 
             
                updateNavigationButtons();
         | 
| 333 | 
             
            }
         | 
| 334 |  | 
| 335 | 
             
            function updateNavigationButtons() {
         | 
| 336 | 
            -
                 | 
| 337 | 
            -
                var currentQuestionId = questionIds[currentQuestion - 1];
         | 
| 338 | 
            -
                var radioName = 'q' + currentQuestionId;
         | 
| 339 | 
            -
                var isAnswered = document.querySelector('input[name="' + radioName + '"]:checked') !== null;
         | 
| 340 |  | 
| 341 | 
            -
                if ( | 
| 342 | 
            -
                     | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 343 | 
             
                }
         | 
| 344 | 
             
            }
         | 
| 345 |  | 
| @@ -351,12 +108,18 @@ function handleAnswer(radioElement) { | |
| 351 | 
             
                    return;
         | 
| 352 | 
             
                }
         | 
| 353 |  | 
|  | |
|  | |
| 354 | 
             
                // Auto-advance to next question after selection
         | 
| 355 | 
             
                setTimeout(function() {
         | 
| 356 | 
             
                    if (questionIndex < totalQuestions) {
         | 
| 357 | 
             
                        showQuestion(questionIndex + 1);
         | 
| 358 | 
             
                    } else {
         | 
| 359 | 
             
                        // Last question - show submit button
         | 
|  | |
|  | |
|  | |
|  | |
| 360 | 
             
                        document.getElementById('submitBtn').style.display = 'block';
         | 
| 361 | 
             
                    }
         | 
| 362 | 
             
                }, 400);
         | 
| @@ -368,12 +131,6 @@ function goToNext() { | |
| 368 | 
             
                }
         | 
| 369 | 
             
            }
         | 
| 370 |  | 
| 371 | 
            -
            function goToPrev() {
         | 
| 372 | 
            -
                if (currentQuestion > 1) {
         | 
| 373 | 
            -
                    showQuestion(currentQuestion - 1);
         | 
| 374 | 
            -
                }
         | 
| 375 | 
            -
            }
         | 
| 376 | 
            -
             | 
| 377 | 
             
            function submitAssessment() {
         | 
| 378 | 
             
                var form = document.getElementById('assessmentForm');
         | 
| 379 | 
             
                var answers = [];
         | 
| @@ -433,30 +190,6 @@ function resetAssessment() { | |
| 433 | 
             
                });
         | 
| 434 | 
             
            }
         | 
| 435 |  | 
| 436 | 
            -
            // ==================== SHARE RESULTS ====================
         | 
| 437 | 
            -
             | 
| 438 | 
            -
            function shareResults() {
         | 
| 439 | 
            -
                const results = getResultsSummary();
         | 
| 440 | 
            -
                const text = `My Spiritual Path Results:\n\n${results}\n\nTake the assessment: ${window.location.origin}`;
         | 
| 441 | 
            -
                
         | 
| 442 | 
            -
                if (navigator.share) {
         | 
| 443 | 
            -
                    navigator.share({ title: 'Spiritual Path Results', text: text });
         | 
| 444 | 
            -
                } else {
         | 
| 445 | 
            -
                    navigator.clipboard.writeText(text);
         | 
| 446 | 
            -
                    alert('Results copied to clipboard!');
         | 
| 447 | 
            -
                }
         | 
| 448 | 
            -
            }
         | 
| 449 | 
            -
             | 
| 450 | 
            -
            function getResultsSummary() {
         | 
| 451 | 
            -
                const cards = document.querySelectorAll('.result-card');
         | 
| 452 | 
            -
                return Array.from(cards).map((card, i) => {
         | 
| 453 | 
            -
                    const title = card.querySelector('h3').textContent;
         | 
| 454 | 
            -
                    const percentage = card.querySelector('.result-percentage').textContent;
         | 
| 455 | 
            -
                    return `${i+1}. ${title} (${percentage})`;
         | 
| 456 | 
            -
                }).join('\n');
         | 
| 457 | 
            -
            }
         | 
| 458 | 
            -
             | 
| 459 | 
            -
             | 
| 460 | 
             
            // ==================== CHAT FUNCTIONALITY ====================
         | 
| 461 |  | 
| 462 | 
             
            var chatHistories = {};
         | 
| @@ -593,118 +326,3 @@ function sendMessage(religionName) { | |
| 593 | 
             
                });
         | 
| 594 | 
             
            }
         | 
| 595 |  | 
| 596 | 
            -
            // ==================== VOICE CHAT ====================
         | 
| 597 | 
            -
             | 
| 598 | 
            -
            var recognition = null;
         | 
| 599 | 
            -
            var currentReligion = null;
         | 
| 600 | 
            -
            var isRecording = false;
         | 
| 601 | 
            -
             | 
| 602 | 
            -
            function initializeSpeechRecognition() {
         | 
| 603 | 
            -
                if ('webkitSpeechRecognition' in window || 'SpeechRecognition' in window) {
         | 
| 604 | 
            -
                    recognition = new (window.SpeechRecognition || window.webkitSpeechRecognition)();
         | 
| 605 | 
            -
                    recognition.continuous = true;
         | 
| 606 | 
            -
                    recognition.interimResults = true;
         | 
| 607 | 
            -
                    recognition.lang = 'en-US';
         | 
| 608 | 
            -
                    
         | 
| 609 | 
            -
                    recognition.onresult = function(event) {
         | 
| 610 | 
            -
                        var interimTranscript = '';
         | 
| 611 | 
            -
                        var finalTranscript = '';
         | 
| 612 | 
            -
                        
         | 
| 613 | 
            -
                        for (var i = event.resultIndex; i < event.results.length; i++) {
         | 
| 614 | 
            -
                            var transcript = event.results[i][0].transcript;
         | 
| 615 | 
            -
                            if (event.results[i].isFinal) {
         | 
| 616 | 
            -
                                finalTranscript += transcript + ' ';
         | 
| 617 | 
            -
                            } else {
         | 
| 618 | 
            -
                                interimTranscript += transcript;
         | 
| 619 | 
            -
                            }
         | 
| 620 | 
            -
                        }
         | 
| 621 | 
            -
                        
         | 
| 622 | 
            -
                        // Update input field with live transcription
         | 
| 623 | 
            -
                        if (currentReligion) {
         | 
| 624 | 
            -
                            var inputId = 'input-' + sanitizeReligionName(currentReligion);
         | 
| 625 | 
            -
                            var inputEl = document.getElementById(inputId);
         | 
| 626 | 
            -
                            if (inputEl) {
         | 
| 627 | 
            -
                                inputEl.value = finalTranscript + interimTranscript;
         | 
| 628 | 
            -
                            }
         | 
| 629 | 
            -
                        }
         | 
| 630 | 
            -
                    };
         | 
| 631 | 
            -
                    
         | 
| 632 | 
            -
                    recognition.onerror = function(event) {
         | 
| 633 | 
            -
                        console.error('Speech recognition error:', event.error);
         | 
| 634 | 
            -
                        if (event.error === 'no-speech') {
         | 
| 635 | 
            -
                            stopVoiceInput();
         | 
| 636 | 
            -
                        }
         | 
| 637 | 
            -
                    };
         | 
| 638 | 
            -
                    
         | 
| 639 | 
            -
                    recognition.onend = function() {
         | 
| 640 | 
            -
                        if (isRecording) {
         | 
| 641 | 
            -
                            // Restart if it stopped unexpectedly
         | 
| 642 | 
            -
                            try {
         | 
| 643 | 
            -
                                recognition.start();
         | 
| 644 | 
            -
                            } catch(e) {
         | 
| 645 | 
            -
                                stopVoiceInput();
         | 
| 646 | 
            -
                            }
         | 
| 647 | 
            -
                        }
         | 
| 648 | 
            -
                    };
         | 
| 649 | 
            -
                }
         | 
| 650 | 
            -
            }
         | 
| 651 | 
            -
             | 
| 652 | 
            -
            function startVoiceInput(religionName) {
         | 
| 653 | 
            -
                if (!recognition) {
         | 
| 654 | 
            -
                    alert('Speech recognition not supported in your browser');
         | 
| 655 | 
            -
                    return;
         | 
| 656 | 
            -
                }
         | 
| 657 | 
            -
                
         | 
| 658 | 
            -
                currentReligion = religionName;
         | 
| 659 | 
            -
                isRecording = true;
         | 
| 660 | 
            -
                
         | 
| 661 | 
            -
                try {
         | 
| 662 | 
            -
                    recognition.start();
         | 
| 663 | 
            -
                    document.getElementById('voice-' + sanitizeReligionName(religionName)).classList.add('recording');
         | 
| 664 | 
            -
                } catch(e) {
         | 
| 665 | 
            -
                    console.log('Already started or error:', e);
         | 
| 666 | 
            -
                }
         | 
| 667 | 
            -
            }
         | 
| 668 | 
            -
             | 
| 669 | 
            -
            function stopVoiceInput(religionName) {
         | 
| 670 | 
            -
                if (recognition && isRecording) {
         | 
| 671 | 
            -
                    isRecording = false;
         | 
| 672 | 
            -
                    recognition.stop();
         | 
| 673 | 
            -
                    document.getElementById('voice-' + sanitizeReligionName(religionName)).classList.remove('recording');
         | 
| 674 | 
            -
                }
         | 
| 675 | 
            -
            }
         | 
| 676 | 
            -
             | 
| 677 | 
            -
            // Initialize on page load
         | 
| 678 | 
            -
            if (document.readyState === 'loading') {
         | 
| 679 | 
            -
                document.addEventListener('DOMContentLoaded', initializeSpeechRecognition);
         | 
| 680 | 
            -
            } else {
         | 
| 681 | 
            -
                initializeSpeechRecognition();
         | 
| 682 | 
            -
            }
         | 
| 683 | 
            -
             | 
| 684 | 
            -
            // Make tooltips appear instantly on hover
         | 
| 685 | 
            -
            document.addEventListener('DOMContentLoaded', function() {
         | 
| 686 | 
            -
                const micButtons = document.querySelectorAll('button[title]');
         | 
| 687 | 
            -
                
         | 
| 688 | 
            -
                micButtons.forEach(button => {
         | 
| 689 | 
            -
                    const tooltipText = button.getAttribute('title');
         | 
| 690 | 
            -
                    button.removeAttribute('title'); // Remove native tooltip
         | 
| 691 | 
            -
                    
         | 
| 692 | 
            -
                    // Create custom tooltip element
         | 
| 693 | 
            -
                    const tooltip = document.createElement('div');
         | 
| 694 | 
            -
                    tooltip.className = 'custom-tooltip';
         | 
| 695 | 
            -
                    tooltip.textContent = tooltipText;
         | 
| 696 | 
            -
                    
         | 
| 697 | 
            -
                    // Add tooltip to button
         | 
| 698 | 
            -
                    button.style.position = 'relative';
         | 
| 699 | 
            -
                    button.appendChild(tooltip);
         | 
| 700 | 
            -
                    
         | 
| 701 | 
            -
                    button.addEventListener('mouseenter', function() {
         | 
| 702 | 
            -
                        tooltip.style.opacity = '1';
         | 
| 703 | 
            -
                    });
         | 
| 704 | 
            -
                    
         | 
| 705 | 
            -
                    button.addEventListener('mouseleave', function() {
         | 
| 706 | 
            -
                        tooltip.style.opacity = '0';
         | 
| 707 | 
            -
                    });
         | 
| 708 | 
            -
                });
         | 
| 709 | 
            -
            });
         | 
| 710 | 
            -
             | 
|  | |
| 3 | 
             
                return name.replace(/\s+/g, '-');
         | 
| 4 | 
             
            }
         | 
| 5 |  | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 6 | 
             
            // ==================== AUTHENTICATION ====================
         | 
| 7 |  | 
| 8 | 
            +
            function authenticate() {
         | 
| 9 | 
            +
                const username = document.getElementById('authUsername').value.trim();
         | 
|  | |
| 10 | 
             
                const password = document.getElementById('authPassword').value;
         | 
| 11 |  | 
| 12 | 
            +
                if (!username || !password) {
         | 
| 13 | 
             
                    document.getElementById('result').innerHTML = 
         | 
| 14 | 
             
                        '<p class="error-msg">⚠️ Please fill in all fields</p>';
         | 
| 15 | 
             
                    return;
         | 
| 16 | 
             
                }
         | 
| 17 |  | 
| 18 | 
            +
                const endpoint = window.location.pathname === '/signup' ? '/signup' : '/login';
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 19 |  | 
| 20 | 
             
                fetch(endpoint, {
         | 
| 21 | 
             
                    method: 'POST',
         | 
| 22 | 
             
                    headers: {'Content-Type': 'application/json'},
         | 
| 23 | 
            +
                    body: JSON.stringify({username, password})
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 24 | 
             
                })
         | 
| 25 | 
            +
                .then(response => response.json())
         | 
| 26 | 
             
                .then(data => {
         | 
| 27 | 
             
                    if (data.success) {
         | 
| 28 | 
            +
                        window.location.href = '/';
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
| 29 | 
             
                    } else {
         | 
| 30 | 
             
                        document.getElementById('result').innerHTML = 
         | 
| 31 | 
            +
                            `<p class="error-msg">${data.message}</p>`;
         | 
| 32 | 
             
                    }
         | 
|  | |
|  | |
|  | |
|  | |
| 33 | 
             
                });
         | 
| 34 | 
             
            }
         | 
| 35 |  | 
|  | |
| 38 | 
             
                window.location.href = newPath;
         | 
| 39 | 
             
            }
         | 
| 40 |  | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 41 | 
             
            // ==================== ASSESSMENT ====================
         | 
| 42 |  | 
| 43 | 
             
            var currentQuestion = 1;
         | 
|  | |
| 69 | 
             
                    block.classList.remove('active');
         | 
| 70 | 
             
                    var blockIndex = parseInt(block.getAttribute('data-question-index'));
         | 
| 71 | 
             
                    if (blockIndex === questionIndex) block.classList.add('active');
         | 
| 72 | 
            +
                    if (blockIndex < questionIndex) {
         | 
| 73 | 
            +
                        block.querySelectorAll('input[type="radio"]').forEach(function(radio) {
         | 
| 74 | 
            +
                            radio.disabled = true;
         | 
| 75 | 
            +
                        });
         | 
| 76 | 
            +
                    }
         | 
| 77 | 
             
                });
         | 
| 78 |  | 
| 79 | 
             
                currentQuestion = questionIndex;
         | 
| 80 | 
             
                document.getElementById('questionCounter').textContent = 'Question ' + questionIndex + ' of ' + totalQuestions;
         | 
| 81 | 
            +
                document.getElementById('progressBar').style.width = ((questionIndex - 1) / totalQuestions) * 100 + '%';
         | 
| 82 | 
             
                updateNavigationButtons();
         | 
| 83 | 
             
            }
         | 
| 84 |  | 
| 85 | 
             
            function updateNavigationButtons() {
         | 
| 86 | 
            +
                var nextBtn = document.getElementById('nextBtn' + currentQuestion);
         | 
|  | |
|  | |
|  | |
| 87 |  | 
| 88 | 
            +
                if (nextBtn) {
         | 
| 89 | 
            +
                    var currentQuestionId = questionIds[currentQuestion - 1];
         | 
| 90 | 
            +
                    var radioName = 'q' + currentQuestionId;
         | 
| 91 | 
            +
                    var isAnswered = document.querySelector('input[name="' + radioName + '"]:checked') !== null;
         | 
| 92 | 
            +
                    
         | 
| 93 | 
            +
                    if (currentQuestion === totalQuestions && isAnswered) {
         | 
| 94 | 
            +
                        nextBtn.style.display = 'none';
         | 
| 95 | 
            +
                        document.getElementById('submitBtn').style.display = 'block';
         | 
| 96 | 
            +
                    } else {
         | 
| 97 | 
            +
                        nextBtn.disabled = !isAnswered;
         | 
| 98 | 
            +
                        nextBtn.style.display = 'inline-block';
         | 
| 99 | 
            +
                    }
         | 
| 100 | 
             
                }
         | 
| 101 | 
             
            }
         | 
| 102 |  | 
|  | |
| 108 | 
             
                    return;
         | 
| 109 | 
             
                }
         | 
| 110 |  | 
| 111 | 
            +
                updateNavigationButtons();
         | 
| 112 | 
            +
                
         | 
| 113 | 
             
                // Auto-advance to next question after selection
         | 
| 114 | 
             
                setTimeout(function() {
         | 
| 115 | 
             
                    if (questionIndex < totalQuestions) {
         | 
| 116 | 
             
                        showQuestion(questionIndex + 1);
         | 
| 117 | 
             
                    } else {
         | 
| 118 | 
             
                        // Last question - show submit button
         | 
| 119 | 
            +
                        var nextBtn = document.getElementById('nextBtn' + questionIndex);
         | 
| 120 | 
            +
                        if (nextBtn) {
         | 
| 121 | 
            +
                            nextBtn.style.display = 'none';
         | 
| 122 | 
            +
                        }
         | 
| 123 | 
             
                        document.getElementById('submitBtn').style.display = 'block';
         | 
| 124 | 
             
                    }
         | 
| 125 | 
             
                }, 400);
         | 
|  | |
| 131 | 
             
                }
         | 
| 132 | 
             
            }
         | 
| 133 |  | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 134 | 
             
            function submitAssessment() {
         | 
| 135 | 
             
                var form = document.getElementById('assessmentForm');
         | 
| 136 | 
             
                var answers = [];
         | 
|  | |
| 190 | 
             
                });
         | 
| 191 | 
             
            }
         | 
| 192 |  | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 193 | 
             
            // ==================== CHAT FUNCTIONALITY ====================
         | 
| 194 |  | 
| 195 | 
             
            var chatHistories = {};
         | 
|  | |
| 326 | 
             
                });
         | 
| 327 | 
             
            }
         | 
| 328 |  | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
    	
        static/style.css
    CHANGED
    
    | @@ -1,6 +1,3 @@ | |
| 1 | 
            -
            @import url('design-tokens.css');
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            /* ===== RESET & BASE ===== */
         | 
| 4 | 
             
            * {
         | 
| 5 | 
             
                margin: 0;
         | 
| 6 | 
             
                padding: 0;
         | 
| @@ -8,34 +5,24 @@ | |
| 8 | 
             
            }
         | 
| 9 |  | 
| 10 | 
             
            body {
         | 
| 11 | 
            -
                font-family:  | 
| 12 | 
            -
                background:  | 
| 13 | 
            -
                rgb(255, 255, 255) 0%, 
         | 
| 14 | 
            -
                rgb(255, 255, 255) 5%, 
         | 
| 15 | 
            -
                rgb(226, 218, 250) 30%, 
         | 
| 16 | 
            -
                rgb(219, 239, 253) 80%, 
         | 
| 17 | 
            -
                rgb(255, 255, 255) 95%, 
         | 
| 18 | 
            -
                rgb(255, 255, 255) 100%);
         | 
| 19 | 
             
                min-height: 100vh;
         | 
| 20 | 
             
                display: flex;
         | 
| 21 | 
             
                justify-content: center;
         | 
| 22 | 
             
                align-items: center;
         | 
| 23 | 
            -
                padding:  | 
| 24 | 
             
            }
         | 
| 25 |  | 
| 26 | 
            -
             | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 30 | 
            -
             | 
| 31 | 
            -
                background: var(--bg-white);
         | 
| 32 | 
            -
                border-radius: var(--radius-xl);
         | 
| 33 | 
            -
                padding: var(--space-lg);
         | 
| 34 | 
            -
                box-shadow: var(--shadow-xl);
         | 
| 35 | 
             
                max-width: 700px;
         | 
| 36 | 
             
                width: 100%;
         | 
| 37 | 
            -
                animation: slideIn  | 
| 38 | 
            -
                max-height:  | 
| 39 | 
             
                overflow-y: auto;
         | 
| 40 | 
             
            }
         | 
| 41 |  | 
| @@ -44,58 +31,43 @@ body { | |
| 44 | 
             
                to { opacity: 1; transform: translateY(0); }
         | 
| 45 | 
             
            }
         | 
| 46 |  | 
| 47 | 
            -
            /* ===== TYPOGRAPHY ===== */
         | 
| 48 | 
             
            h1 {
         | 
| 49 | 
            -
                color:  | 
| 50 | 
            -
                font-size:  | 
| 51 | 
            -
                margin-bottom:  | 
| 52 | 
            -
                text-align: center;
         | 
| 53 | 
            -
                font-weight: var(--font-weight-bold);
         | 
| 54 | 
            -
            }
         | 
| 55 | 
            -
             | 
| 56 | 
            -
            h2 {
         | 
| 57 | 
            -
                font-size: var(--font-size-2xl);  /* or var(--font-size-2xl) for even smaller */
         | 
| 58 | 
             
                text-align: center;
         | 
| 59 | 
            -
                 | 
| 60 | 
             
            }
         | 
| 61 |  | 
| 62 | 
             
            h3 {
         | 
| 63 | 
             
                text-align: center;
         | 
| 64 | 
            -
                color:  | 
| 65 | 
            -
            }
         | 
| 66 | 
            -
             | 
| 67 | 
            -
            /* ===== ICON STYLING ===== */
         | 
| 68 | 
            -
            .fa-heart {
         | 
| 69 | 
            -
                color: var(--error); /* Red color for heart icons */
         | 
| 70 | 
             
            }
         | 
| 71 |  | 
| 72 | 
             
            p {
         | 
| 73 | 
            -
                color:  | 
| 74 | 
             
                text-align: center;
         | 
| 75 | 
            -
                margin-bottom:  | 
| 76 | 
            -
                font-size:  | 
| 77 | 
             
            }
         | 
| 78 |  | 
| 79 | 
             
            .subtitle {
         | 
| 80 | 
            -
                color:  | 
| 81 | 
            -
                font-size:  | 
| 82 | 
             
                text-align: center;
         | 
| 83 | 
            -
                margin-bottom:  | 
| 84 | 
             
                line-height: 1.6;
         | 
| 85 | 
            -
                max-width: 540px;
         | 
| 86 | 
            -
                margin-left: auto;
         | 
| 87 | 
            -
                margin-right: auto;
         | 
| 88 | 
             
            }
         | 
| 89 |  | 
| 90 | 
            -
            /*  | 
| 91 | 
            -
            input[type="text"], input[type="password"] | 
| 92 | 
             
                width: 100%;
         | 
| 93 | 
            -
                padding:  | 
| 94 | 
            -
                font-size:  | 
| 95 | 
             
                border: none;
         | 
| 96 | 
            -
                background:  | 
| 97 | 
            -
                border-radius:  | 
| 98 | 
            -
                transition: all  | 
| 99 | 
             
                outline: none;
         | 
| 100 | 
             
            }
         | 
| 101 |  | 
| @@ -104,25 +76,25 @@ input:focus { | |
| 104 | 
             
                box-shadow: 0 0 0 2px #E5E5E5;
         | 
| 105 | 
             
            }
         | 
| 106 |  | 
| 107 | 
            -
            /*  | 
| 108 | 
             
            button, .btn, .nav-btn, .submit-btn {
         | 
| 109 | 
            -
                padding:  | 
| 110 | 
            -
                font-size:  | 
| 111 | 
            -
                background:  | 
| 112 | 
            -
                color:  | 
| 113 | 
             
                border: none;
         | 
| 114 | 
            -
                border-radius:  | 
| 115 | 
             
                cursor: pointer;
         | 
| 116 | 
            -
                transition: all  | 
| 117 | 
            -
                font-weight:  | 
| 118 | 
             
                text-decoration: none;
         | 
| 119 | 
             
                display: inline-block;
         | 
| 120 | 
             
            }
         | 
| 121 |  | 
| 122 | 
             
            button:hover, .btn:hover, .nav-btn:hover, .submit-btn:hover {
         | 
| 123 | 
            -
                background:  | 
| 124 | 
             
                transform: translateY(-1px);
         | 
| 125 | 
            -
                box-shadow:  | 
| 126 | 
             
            }
         | 
| 127 |  | 
| 128 | 
             
            button:active, .btn:active {
         | 
| @@ -142,133 +114,58 @@ button:disabled { | |
| 142 | 
             
                transform: none;
         | 
| 143 | 
             
            }
         | 
| 144 |  | 
| 145 | 
            -
            /* Secondary Buttons */
         | 
| 146 | 
            -
            .logout-btn, .reset-btn | 
| 147 | 
            -
                background:  | 
| 148 | 
            -
                padding:  | 
| 149 | 
            -
                font-size:  | 
| 150 | 
            -
                 | 
| 151 | 
            -
                margin-top: var(--space-sm);
         | 
| 152 | 
             
            }
         | 
| 153 |  | 
| 154 | 
            -
            .logout-btn:hover, .reset-btn:hover | 
| 155 | 
             
                background: #4B5563;
         | 
| 156 | 
            -
                box-shadow:  | 
| 157 | 
             
            }
         | 
| 158 |  | 
| 159 | 
             
            /* Submit Button */
         | 
| 160 | 
             
            .submit-btn {
         | 
| 161 | 
             
                width: 100%;
         | 
| 162 | 
            -
                padding:  | 
| 163 | 
            -
                font-size:  | 
| 164 | 
            -
                margin-top:  | 
| 165 | 
             
            }
         | 
| 166 |  | 
| 167 | 
             
            /* Auth Form */
         | 
| 168 | 
            -
            /* Auth-specific container - narrower for login/signup/forgot-password */
         | 
| 169 | 
            -
            .auth-container {
         | 
| 170 | 
            -
                background: var(--bg-white);
         | 
| 171 | 
            -
                border-radius: var(--radius-xl);
         | 
| 172 | 
            -
                padding: var(--space-lg);
         | 
| 173 | 
            -
                box-shadow: var(--shadow-xl);
         | 
| 174 | 
            -
                max-width: 400px;  /* Narrower for auth forms */
         | 
| 175 | 
            -
                width: 100%;
         | 
| 176 | 
            -
                animation: slideIn var(--transition-slow) ease;
         | 
| 177 | 
            -
                max-height: 95vh;
         | 
| 178 | 
            -
                overflow-y: auto;
         | 
| 179 | 
            -
                text-align: center;
         | 
| 180 | 
            -
            }
         | 
| 181 | 
            -
             | 
| 182 | 
             
            .auth-form input {
         | 
| 183 | 
             
                width: 100%;
         | 
| 184 | 
            -
                margin-bottom:  | 
| 185 | 
             
            }
         | 
| 186 |  | 
| 187 | 
             
            .auth-form button {
         | 
| 188 | 
             
                width: 100%;
         | 
| 189 | 
             
            }
         | 
| 190 |  | 
| 191 | 
            -
            /* Google Sign-In Button */
         | 
| 192 | 
            -
            .google-signin-btn {
         | 
| 193 | 
            -
                width: 100%;
         | 
| 194 | 
            -
                padding: var(--space-sm) var(--space-lg);
         | 
| 195 | 
            -
                background: white;
         | 
| 196 | 
            -
                color: #444;
         | 
| 197 | 
            -
                border: 1px solid #ddd;
         | 
| 198 | 
            -
                border-radius: var(--radius-md);
         | 
| 199 | 
            -
                font-size: var(--font-size-base);
         | 
| 200 | 
            -
                font-weight: 500;
         | 
| 201 | 
            -
                cursor: pointer;
         | 
| 202 | 
            -
                display: flex;
         | 
| 203 | 
            -
                align-items: center;
         | 
| 204 | 
            -
                justify-content: center;
         | 
| 205 | 
            -
                gap: 12px;
         | 
| 206 | 
            -
                transition: all var(--transition-fast);
         | 
| 207 | 
            -
                margin-bottom: var(--space-md);
         | 
| 208 | 
            -
            }
         | 
| 209 | 
            -
             | 
| 210 | 
            -
            .google-signin-btn:hover {
         | 
| 211 | 
            -
                background: #f8f8f8;
         | 
| 212 | 
            -
                border-color: #ccc;
         | 
| 213 | 
            -
                box-shadow: 0 2px 4px rgba(0,0,0,0.1);
         | 
| 214 | 
            -
            }
         | 
| 215 | 
            -
             | 
| 216 | 
            -
            .google-signin-btn svg {
         | 
| 217 | 
            -
                flex-shrink: 0;
         | 
| 218 | 
            -
            }
         | 
| 219 | 
            -
             | 
| 220 | 
            -
            /* Divider for "or" between Google and email/password */
         | 
| 221 | 
            -
            .divider {
         | 
| 222 | 
            -
                display: flex;
         | 
| 223 | 
            -
                align-items: center;
         | 
| 224 | 
            -
                text-align: center;
         | 
| 225 | 
            -
                margin: var(--space-md) 0;
         | 
| 226 | 
            -
                color: var(--text-secondary);
         | 
| 227 | 
            -
                font-size: var(--font-size-sm);
         | 
| 228 | 
            -
            }
         | 
| 229 | 
            -
             | 
| 230 | 
            -
            .divider::before,
         | 
| 231 | 
            -
            .divider::after {
         | 
| 232 | 
            -
                content: '';
         | 
| 233 | 
            -
                flex: 1;
         | 
| 234 | 
            -
                border-bottom: 1px solid #ddd;
         | 
| 235 | 
            -
            }
         | 
| 236 | 
            -
             | 
| 237 | 
            -
            .divider span {
         | 
| 238 | 
            -
                padding: 0 var(--space-sm);
         | 
| 239 | 
            -
            }
         | 
| 240 | 
            -
             | 
| 241 | 
            -
            #result {
         | 
| 242 | 
            -
                margin-bottom: var(--space-md);  /* 16px bottom margin only */
         | 
| 243 | 
            -
                margin-top: 0;
         | 
| 244 | 
            -
                padding: 0;
         | 
| 245 | 
            -
            }
         | 
| 246 | 
            -
             | 
| 247 | 
             
            .switch-link {
         | 
| 248 | 
            -
                color:  | 
| 249 | 
             
                text-decoration: none;
         | 
| 250 | 
             
                cursor: pointer;
         | 
| 251 | 
            -
                font-weight:  | 
| 252 | 
            -
                 | 
| 253 | 
            -
                display: block;
         | 
| 254 | 
            -
                 | 
| 255 | 
            -
                transition: color var(--transition-fast);
         | 
| 256 | 
            -
                font-size: var(--font-size-sm);
         | 
| 257 | 
             
            }
         | 
| 258 |  | 
| 259 | 
             
            .switch-link:hover {
         | 
| 260 | 
            -
                color:  | 
| 261 | 
             
                text-decoration: underline;
         | 
| 262 | 
             
            }
         | 
| 263 |  | 
| 264 | 
            -
             | 
| 265 | 
            -
             | 
| 266 | 
            -
            /* ===== QUESTION BLOCKS ===== */
         | 
| 267 | 
             
            .question-block {
         | 
| 268 | 
            -
                background:  | 
| 269 | 
            -
                padding:  | 
| 270 | 
            -
                border-radius:  | 
| 271 | 
            -
                margin-bottom:  | 
| 272 | 
             
                border: none;
         | 
| 273 | 
             
                display: none;
         | 
| 274 | 
             
                min-height: 400px;
         | 
| @@ -276,7 +173,7 @@ button:disabled { | |
| 276 |  | 
| 277 | 
             
            .question-block.active {
         | 
| 278 | 
             
                display: block;
         | 
| 279 | 
            -
                animation: fadeIn  | 
| 280 | 
             
            }
         | 
| 281 |  | 
| 282 | 
             
            @keyframes fadeIn {
         | 
| @@ -285,53 +182,52 @@ button:disabled { | |
| 285 | 
             
            }
         | 
| 286 |  | 
| 287 | 
             
            .question-block h4 {
         | 
| 288 | 
            -
                color:  | 
| 289 | 
            -
                margin-bottom:  | 
| 290 | 
            -
                font-weight:  | 
| 291 | 
            -
                font-size:  | 
| 292 | 
             
                line-height: 1.6;
         | 
| 293 | 
             
            }
         | 
| 294 |  | 
| 295 | 
             
            .question-number {
         | 
| 296 | 
             
                display: inline-block;
         | 
| 297 | 
            -
                background:  | 
| 298 | 
            -
                color:  | 
| 299 | 
             
                width: 32px;
         | 
| 300 | 
             
                height: 32px;
         | 
| 301 | 
            -
                border-radius:  | 
| 302 | 
             
                text-align: center;
         | 
| 303 | 
             
                line-height: 32px;
         | 
| 304 | 
            -
                margin-right:  | 
| 305 | 
            -
                font-size:  | 
| 306 | 
             
            }
         | 
| 307 |  | 
| 308 | 
            -
            /*  | 
| 309 | 
             
            .option {
         | 
| 310 | 
            -
                display:  | 
| 311 | 
            -
                 | 
| 312 | 
            -
                 | 
| 313 | 
            -
                 | 
| 314 | 
            -
                background: var(--bg-white);
         | 
| 315 | 
             
                border: none;
         | 
| 316 | 
            -
                border-radius:  | 
| 317 | 
             
                cursor: pointer;
         | 
| 318 | 
            -
                transition: all  | 
| 319 | 
            -
                font-size:  | 
| 320 | 
            -
                color:  | 
| 321 | 
            -
                box-shadow:  | 
| 322 | 
             
            }
         | 
| 323 |  | 
| 324 | 
             
            .option:hover {
         | 
| 325 | 
            -
                background:  | 
| 326 | 
             
                transform: translateX(5px);
         | 
| 327 | 
            -
                box-shadow:  | 
| 328 | 
             
            }
         | 
| 329 |  | 
| 330 | 
             
            .option input[type="radio"] {
         | 
| 331 | 
            -
                margin-right:  | 
| 332 | 
             
                cursor: pointer;
         | 
| 333 | 
            -
                width:  | 
| 334 | 
            -
                height:  | 
| 335 | 
             
            }
         | 
| 336 |  | 
| 337 | 
             
            .option input[type="radio"]:disabled {
         | 
| @@ -345,222 +241,187 @@ button:disabled { | |
| 345 | 
             
            }
         | 
| 346 |  | 
| 347 | 
             
            .option:has(input[type="radio"]:disabled):hover {
         | 
| 348 | 
            -
                background:  | 
| 349 | 
             
                transform: none;
         | 
| 350 | 
             
            }
         | 
| 351 |  | 
| 352 | 
            -
            /*  | 
| 353 | 
             
            .question-counter {
         | 
| 354 | 
             
                text-align: center;
         | 
| 355 | 
             
                color: #999;
         | 
| 356 | 
            -
                font-size:  | 
| 357 | 
            -
                margin-bottom:  | 
| 358 | 
            -
                font-weight:  | 
| 359 | 
             
            }
         | 
| 360 |  | 
| 361 | 
             
            .progress-bar {
         | 
| 362 | 
            -
                background:  | 
| 363 | 
            -
                height:  | 
| 364 | 
             
                border-radius: 4px;
         | 
| 365 | 
             
                overflow: hidden;
         | 
| 366 | 
            -
                margin-bottom:  | 
| 367 | 
             
            }
         | 
| 368 |  | 
| 369 | 
             
            .progress-fill {
         | 
| 370 | 
            -
                background:  | 
| 371 | 
             
                height: 100%;
         | 
| 372 | 
            -
                transition: width  | 
| 373 | 
             
            }
         | 
| 374 |  | 
|  | |
| 375 | 
             
            .nav-buttons {
         | 
| 376 | 
             
                display: flex;
         | 
| 377 | 
            -
                gap:  | 
| 378 | 
            -
                justify-content:  | 
| 379 | 
            -
                margin-top:  | 
| 380 | 
            -
            }
         | 
| 381 | 
            -
             | 
| 382 | 
            -
            .nav-btn.prev {
         | 
| 383 | 
            -
                background: transparent;
         | 
| 384 | 
            -
                color: #999;
         | 
| 385 | 
            -
                border: none;
         | 
| 386 | 
            -
                padding: 0;
         | 
| 387 | 
            -
                font-weight: var(--font-weight-medium);
         | 
| 388 | 
            -
                font-size: var(--font-size-sm);
         | 
| 389 | 
            -
                text-decoration: none;
         | 
| 390 | 
            -
                display: inline-flex;
         | 
| 391 | 
            -
                align-items: center;
         | 
| 392 | 
            -
                gap: 4px;
         | 
| 393 | 
            -
                transition: all var(--transition-base) ease;
         | 
| 394 | 
            -
                box-shadow: none;
         | 
| 395 | 
            -
            }
         | 
| 396 | 
            -
             | 
| 397 | 
            -
            .nav-btn.prev:hover {
         | 
| 398 | 
            -
                background: transparent;
         | 
| 399 | 
            -
                color: #666;
         | 
| 400 | 
            -
                transform: translateX(-3px);
         | 
| 401 | 
            -
                box-shadow: none;
         | 
| 402 | 
             
            }
         | 
| 403 |  | 
| 404 | 
             
            .buttons-row {
         | 
| 405 | 
             
                display: flex;
         | 
| 406 | 
            -
                gap:  | 
| 407 | 
             
                justify-content: center;
         | 
| 408 | 
            -
                margin-top:  | 
| 409 | 
            -
            }
         | 
| 410 | 
            -
             | 
| 411 | 
            -
            /* ===== RESULTS ===== */
         | 
| 412 | 
            -
            .results-explanation {
         | 
| 413 | 
            -
                max-width: 400px; /* Adjust this value as needed */
         | 
| 414 | 
            -
                margin: 0 auto var(--space-sm);
         | 
| 415 | 
            -
                text-align: center;
         | 
| 416 | 
            -
                color: var(--text-secondary);
         | 
| 417 | 
            -
                font-size: var(--font-size-sm);
         | 
| 418 | 
            -
                line-height: 1.5;
         | 
| 419 | 
             
            }
         | 
| 420 |  | 
|  | |
| 421 | 
             
            .result-card {
         | 
| 422 | 
            -
                padding:  | 
| 423 | 
            -
                border-radius:  | 
| 424 | 
            -
                margin-bottom:  | 
| 425 | 
             
                border: none;
         | 
| 426 | 
            -
                box-shadow:  | 
| 427 | 
             
            }
         | 
| 428 |  | 
| 429 | 
             
            .result-card.rank-1 {
         | 
| 430 | 
            -
                background:  | 
| 431 | 
             
            }
         | 
| 432 |  | 
| 433 | 
             
            .result-card.rank-2 {
         | 
| 434 | 
            -
                background:  | 
| 435 | 
             
            }
         | 
| 436 |  | 
| 437 | 
             
            .result-card.rank-3 {
         | 
| 438 | 
            -
                background:  | 
| 439 | 
             
            }
         | 
| 440 |  | 
| 441 | 
             
            .result-header {
         | 
| 442 | 
             
                display: flex;
         | 
| 443 | 
             
                align-items: center;
         | 
| 444 | 
             
                justify-content: space-between;
         | 
| 445 | 
            -
                margin-bottom:  | 
| 446 | 
             
            }
         | 
| 447 |  | 
| 448 | 
             
            .result-rank {
         | 
| 449 | 
            -
                color:  | 
| 450 | 
            -
                width:  | 
| 451 | 
            -
                height:  | 
| 452 | 
            -
                border-radius:  | 
| 453 | 
             
                display: flex;
         | 
| 454 | 
             
                align-items: center;
         | 
| 455 | 
             
                justify-content: center;
         | 
| 456 | 
            -
                font-size:  | 
| 457 | 
            -
                font-weight:  | 
| 458 | 
            -
                background:  | 
| 459 | 
             
            }
         | 
| 460 |  | 
| 461 | 
             
            .result-title {
         | 
| 462 | 
             
                flex: 1;
         | 
| 463 | 
            -
                margin-left:  | 
| 464 | 
             
            }
         | 
| 465 |  | 
| 466 | 
             
            .result-title h3 {
         | 
| 467 | 
            -
                font-size:  | 
| 468 | 
             
                margin-bottom: 5px;
         | 
| 469 | 
            -
                color:  | 
| 470 | 
            -
            }
         | 
| 471 | 
            -
             | 
| 472 | 
            -
            .result-details h5 i {
         | 
| 473 | 
            -
                font-size: var(--font-size-sm);
         | 
| 474 | 
            -
                margin-right: var(--space-xs);
         | 
| 475 | 
             
            }
         | 
| 476 |  | 
| 477 | 
             
            .result-percentage {
         | 
| 478 | 
            -
                font-size:  | 
| 479 | 
            -
                font-weight:  | 
| 480 | 
            -
                color:  | 
| 481 | 
             
            }
         | 
| 482 |  | 
| 483 | 
             
            .result-description {
         | 
| 484 | 
             
                color: #666;
         | 
| 485 | 
             
                line-height: 1.6;
         | 
| 486 | 
            -
                margin-bottom:  | 
| 487 | 
            -
                font-size:  | 
| 488 | 
             
            }
         | 
| 489 |  | 
| 490 | 
             
            .result-details {
         | 
| 491 | 
             
                background: rgba(255, 255, 255, 0.6);
         | 
| 492 | 
             
                border: none;
         | 
| 493 | 
            -
                padding:  | 
| 494 | 
            -
                border-radius:  | 
| 495 | 
            -
                margin-top:  | 
| 496 | 
             
            }
         | 
| 497 |  | 
| 498 | 
             
            .result-details h5 {
         | 
| 499 | 
            -
                color:  | 
| 500 | 
            -
                font-size:  | 
| 501 | 
            -
                margin-bottom:  | 
| 502 | 
            -
                font-weight:  | 
| 503 | 
             
            }
         | 
| 504 |  | 
| 505 | 
             
            .result-details p {
         | 
| 506 | 
             
                color: #666;
         | 
| 507 | 
            -
                font-size:  | 
| 508 | 
            -
                margin-bottom:  | 
| 509 | 
             
                text-align: left;
         | 
| 510 | 
             
            }
         | 
| 511 |  | 
| 512 | 
            -
            /*  | 
| 513 | 
             
            .icon {
         | 
| 514 | 
            -
                font-size:  | 
| 515 | 
            -
                margin-right:  | 
| 516 | 
             
            }
         | 
| 517 |  | 
| 518 | 
             
            .success-msg {
         | 
| 519 | 
            -
                color:  | 
| 520 | 
            -
                font-weight:  | 
| 521 | 
             
            }
         | 
| 522 |  | 
| 523 | 
             
            .error-msg {
         | 
| 524 | 
             
                color: #666;
         | 
| 525 | 
            -
                font-weight:  | 
| 526 | 
             
                text-align: center;
         | 
| 527 | 
            -
                padding:  | 
| 528 | 
             
            }
         | 
| 529 |  | 
| 530 | 
            -
            /*  | 
| 531 | 
             
            .chat-toggle-btn {
         | 
| 532 | 
             
                background: rgba(255, 255, 255, 0.8);
         | 
| 533 | 
            -
                color:  | 
| 534 | 
             
                border: none;
         | 
| 535 | 
            -
                padding:  | 
| 536 | 
            -
                border-radius:  | 
| 537 | 
             
                cursor: pointer;
         | 
| 538 | 
            -
                font-size:  | 
| 539 | 
            -
                font-weight:  | 
| 540 | 
            -
                margin-top:  | 
| 541 | 
             
                width: 100%;
         | 
| 542 | 
            -
                transition: background  | 
| 543 | 
            -
                box-shadow:  | 
| 544 | 
             
            }
         | 
| 545 |  | 
| 546 | 
             
            .chat-toggle-btn:hover {
         | 
| 547 | 
            -
                background:  | 
| 548 | 
            -
                color:  | 
| 549 | 
             
            }
         | 
| 550 |  | 
| 551 | 
             
            .chat-window {
         | 
| 552 | 
             
                display: none;
         | 
| 553 | 
             
                background: rgba(255, 255, 255, 0.9);
         | 
| 554 | 
             
                border: none;
         | 
| 555 | 
            -
                border-radius:  | 
| 556 | 
            -
                margin-top:  | 
| 557 | 
             
                overflow: hidden;
         | 
| 558 | 
            -
                box-shadow:  | 
| 559 | 
             
            }
         | 
| 560 |  | 
| 561 | 
             
            .chat-window.open {
         | 
| 562 | 
             
                display: block;
         | 
| 563 | 
            -
                animation: slideDown  | 
| 564 | 
             
            }
         | 
| 565 |  | 
| 566 | 
             
            @keyframes slideDown {
         | 
| @@ -571,37 +432,37 @@ button:disabled { | |
| 571 | 
             
            .chat-messages {
         | 
| 572 | 
             
                height: 250px;
         | 
| 573 | 
             
                overflow-y: auto;
         | 
| 574 | 
            -
                padding:  | 
| 575 | 
             
                background: transparent;
         | 
| 576 | 
             
            }
         | 
| 577 |  | 
| 578 | 
             
            .chat-message {
         | 
| 579 | 
            -
                margin-bottom:  | 
| 580 | 
            -
                padding:  | 
| 581 | 
            -
                border-radius:  | 
| 582 | 
             
                max-width: 85%;
         | 
| 583 | 
             
                line-height: 1.5;
         | 
| 584 | 
            -
                font-size:  | 
| 585 | 
             
            }
         | 
| 586 |  | 
| 587 | 
             
            .chat-message.user {
         | 
| 588 | 
            -
                background:  | 
| 589 | 
            -
                color:  | 
| 590 | 
             
                margin-left: auto;
         | 
| 591 | 
             
                text-align: right;
         | 
| 592 | 
             
            }
         | 
| 593 |  | 
| 594 | 
             
            .chat-message.bot {
         | 
| 595 | 
            -
                background:  | 
| 596 | 
            -
                color:  | 
| 597 | 
             
                border: none;
         | 
| 598 | 
             
                text-align: left;
         | 
| 599 | 
            -
                box-shadow:  | 
| 600 | 
             
            }
         | 
| 601 |  | 
| 602 | 
             
            .chat-message.bot ul {
         | 
| 603 | 
            -
                margin:  | 
| 604 | 
            -
                padding-left:  | 
| 605 | 
             
            }
         | 
| 606 |  | 
| 607 | 
             
            .chat-message.bot li {
         | 
| @@ -611,180 +472,55 @@ button:disabled { | |
| 611 |  | 
| 612 | 
             
            .chat-input-area {
         | 
| 613 | 
             
                display: flex;
         | 
| 614 | 
            -
                gap:  | 
| 615 | 
            -
                padding:  | 
| 616 | 
             
                background: transparent;
         | 
| 617 | 
             
                border-top: none;
         | 
| 618 | 
             
            }
         | 
| 619 |  | 
| 620 | 
             
            .chat-input {
         | 
| 621 | 
             
                flex: 1;
         | 
| 622 | 
            -
                padding:  | 
| 623 | 
             
                border: none;
         | 
| 624 | 
            -
                background:  | 
| 625 | 
            -
                border-radius:  | 
| 626 | 
            -
                font-size:  | 
| 627 | 
             
                outline: none;
         | 
| 628 | 
            -
                color:  | 
| 629 | 
            -
                box-shadow:  | 
| 630 | 
             
            }
         | 
| 631 |  | 
| 632 | 
             
            .chat-input:focus {
         | 
| 633 | 
            -
                box-shadow:  | 
| 634 | 
             
            }
         | 
| 635 |  | 
| 636 | 
             
            .chat-send-btn {
         | 
| 637 | 
            -
                padding:  | 
| 638 | 
            -
                background:  | 
| 639 | 
            -
                color:  | 
| 640 | 
             
                border: none;
         | 
| 641 | 
            -
                border-radius:  | 
| 642 | 
             
                cursor: pointer;
         | 
| 643 | 
            -
                font-weight:  | 
| 644 | 
            -
                font-size:  | 
| 645 | 
            -
                transition: background  | 
| 646 | 
             
            }
         | 
| 647 |  | 
| 648 | 
             
            .chat-send-btn:hover {
         | 
| 649 | 
            -
                background:  | 
| 650 | 
            -
                color:  | 
| 651 | 
             
            }
         | 
| 652 |  | 
| 653 | 
             
            .chat-send-btn:disabled {
         | 
| 654 | 
            -
                background:  | 
| 655 | 
             
                color: #999;
         | 
| 656 | 
            -
             | 
| 657 | 
            -
             | 
| 658 | 
            -
            .voice-btn {
         | 
| 659 | 
            -
                padding: var(--space-sm) var(--space-sm);
         | 
| 660 | 
            -
                background: var(--primary-dark);
         | 
| 661 | 
            -
                color: var(--text-inverse);
         | 
| 662 | 
            -
                border: none;
         | 
| 663 | 
            -
                border-radius: var(--radius-sm);
         | 
| 664 | 
            -
                cursor: pointer;
         | 
| 665 | 
            -
                font-size: var(--font-size-lg);
         | 
| 666 | 
            -
                transition: all var(--transition-fast);
         | 
| 667 | 
            -
            }
         | 
| 668 | 
            -
             | 
| 669 | 
            -
            .voice-btn:hover {
         | 
| 670 | 
            -
                background: var(--info);
         | 
| 671 | 
            -
            }
         | 
| 672 | 
            -
             | 
| 673 | 
            -
            .voice-btn.recording {
         | 
| 674 | 
            -
                background: var(--error);
         | 
| 675 | 
            -
                animation: pulse 1s infinite;
         | 
| 676 | 
            -
            }
         | 
| 677 | 
            -
             | 
| 678 | 
            -
            @keyframes pulse {
         | 
| 679 | 
            -
                0%, 100% { opacity: 1; }
         | 
| 680 | 
            -
                50% { opacity: 0.7; }
         | 
| 681 | 
             
            }
         | 
| 682 |  | 
| 683 | 
             
            .chat-typing {
         | 
| 684 | 
             
                color: #999;
         | 
| 685 | 
             
                font-style: italic;
         | 
| 686 | 
            -
                font-size:  | 
| 687 | 
            -
                padding:  | 
| 688 | 
            -
            }
         | 
| 689 | 
            -
             | 
| 690 | 
            -
            /* ===== NAVIGATION & UTILITIES ===== */
         | 
| 691 | 
            -
            .nav-header {
         | 
| 692 | 
            -
                padding: 0 0 var(--space-lg) 0;
         | 
| 693 | 
            -
                margin-bottom: var(--space-lg);
         | 
| 694 | 
            -
                border-bottom: 1px solid var(--border-divider);
         | 
| 695 | 
             
            }
         | 
| 696 |  | 
| 697 | 
            -
            .back-link {
         | 
| 698 | 
            -
                color: #667eea;
         | 
| 699 | 
            -
                text-decoration: none;
         | 
| 700 | 
            -
                font-weight: var(--font-weight-medium);
         | 
| 701 | 
            -
                font-size: var(--font-size-sm);
         | 
| 702 | 
            -
                transition: all var(--transition-base) ease;
         | 
| 703 | 
            -
                display: inline-flex;
         | 
| 704 | 
            -
                align-items: center;
         | 
| 705 | 
            -
                gap: 4px;
         | 
| 706 | 
            -
                
         | 
| 707 | 
            -
            }
         | 
| 708 | 
            -
             | 
| 709 | 
            -
            .back-link:hover {
         | 
| 710 | 
            -
                color: #5a6fd8;
         | 
| 711 | 
            -
                transform: translateX(-3px);
         | 
| 712 | 
            -
            }
         | 
| 713 | 
            -
             | 
| 714 | 
            -
            .results-spacing {
         | 
| 715 | 
            -
                margin-top: var(--space-3xl);
         | 
| 716 | 
            -
            }
         | 
| 717 | 
            -
             | 
| 718 | 
            -
            /* ===== MOBILE RESPONSIVE ===== */
         | 
| 719 | 
            -
            @media (max-width: 768px) {
         | 
| 720 | 
            -
                .container {
         | 
| 721 | 
            -
                    padding: var(--space-sm);
         | 
| 722 | 
            -
                    border-radius: var(--radius-lg);
         | 
| 723 | 
            -
                    margin: 5px;
         | 
| 724 | 
            -
                }
         | 
| 725 | 
            -
                
         | 
| 726 | 
            -
                h1 {
         | 
| 727 | 
            -
                    font-size: var(--font-size-3xl);
         | 
| 728 | 
            -
                }
         | 
| 729 | 
            -
                
         | 
| 730 | 
            -
                p {
         | 
| 731 | 
            -
                    font-size: var(--font-size-lg);
         | 
| 732 | 
            -
                }
         | 
| 733 | 
            -
                
         | 
| 734 | 
            -
                .subtitle {
         | 
| 735 | 
            -
                    font-size: var(--font-size-base);
         | 
| 736 | 
            -
                }
         | 
| 737 | 
            -
                
         | 
| 738 | 
            -
                input[type="text"], input[type="password"], input[type="email"] {
         | 
| 739 | 
            -
                    padding: var(--space-md) var(--space-lg);
         | 
| 740 | 
            -
                    font-size: var(--font-size-lg);
         | 
| 741 | 
            -
                }
         | 
| 742 | 
            -
                
         | 
| 743 | 
            -
                button, .btn, .nav-btn, .submit-btn {
         | 
| 744 | 
            -
                    padding: var(--space-md) var(--space-2xl);
         | 
| 745 | 
            -
                    font-size: var(--font-size-lg);
         | 
| 746 | 
            -
                }
         | 
| 747 | 
            -
                
         | 
| 748 | 
            -
                .question-block {
         | 
| 749 | 
            -
                    padding: var(--space-lg);
         | 
| 750 | 
            -
                    min-height: 350px;
         | 
| 751 | 
            -
                }
         | 
| 752 | 
            -
                
         | 
| 753 | 
            -
                .question-block h4 {
         | 
| 754 | 
            -
                    font-size: var(--font-size-2xl);
         | 
| 755 | 
            -
                }
         | 
| 756 | 
            -
                
         | 
| 757 | 
            -
                .option {
         | 
| 758 | 
            -
                    padding: var(--space-lg) var(--space-xl);
         | 
| 759 | 
            -
                    margin-bottom: var(--space-md);
         | 
| 760 | 
            -
                    font-size: var(--font-size-lg);
         | 
| 761 | 
            -
                }
         | 
| 762 | 
            -
                
         | 
| 763 | 
            -
                .option input[type="radio"] {
         | 
| 764 | 
            -
                    width: 22px;
         | 
| 765 | 
            -
                    height: 22px;
         | 
| 766 | 
            -
                    margin-right: var(--space-md);
         | 
| 767 | 
            -
                }
         | 
| 768 | 
            -
                
         | 
| 769 | 
            -
            }
         | 
| 770 | 
            -
             | 
| 771 | 
            -
             | 
| 772 | 
            -
            /* Custom tooltip styles */
         | 
| 773 | 
            -
            .custom-tooltip {
         | 
| 774 | 
            -
                position: absolute;
         | 
| 775 | 
            -
                background: var(--primary-dark);
         | 
| 776 | 
            -
                color: var(--text-inverse);
         | 
| 777 | 
            -
                padding: var(--space-xs) var(--space-sm);
         | 
| 778 | 
            -
                border-radius: var(--radius-sm);
         | 
| 779 | 
            -
                font-family: var(--font-family);
         | 
| 780 | 
            -
                font-size: 13px;
         | 
| 781 | 
            -
                font-weight: var(--font-weight-regular);
         | 
| 782 | 
            -
                white-space: nowrap;
         | 
| 783 | 
            -
                z-index: 10000;
         | 
| 784 | 
            -
                pointer-events: none;
         | 
| 785 | 
            -
                opacity: 0;
         | 
| 786 | 
            -
                transition: opacity var(--transition-fast) ease-in-out;
         | 
| 787 | 
            -
                top: -50px;
         | 
| 788 | 
            -
                left: 50%;
         | 
| 789 | 
            -
                transform: translateX(-50%);
         | 
| 790 | 
            -
            }
         | 
|  | |
|  | |
|  | |
|  | |
| 1 | 
             
            * {
         | 
| 2 | 
             
                margin: 0;
         | 
| 3 | 
             
                padding: 0;
         | 
|  | |
| 5 | 
             
            }
         | 
| 6 |  | 
| 7 | 
             
            body {
         | 
| 8 | 
            +
                font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
         | 
| 9 | 
            +
                background: #F5F5F5;
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 10 | 
             
                min-height: 100vh;
         | 
| 11 | 
             
                display: flex;
         | 
| 12 | 
             
                justify-content: center;
         | 
| 13 | 
             
                align-items: center;
         | 
| 14 | 
            +
                padding: 20px;
         | 
| 15 | 
             
            }
         | 
| 16 |  | 
| 17 | 
            +
            .container {
         | 
| 18 | 
            +
                background: white;
         | 
| 19 | 
            +
                border-radius: 16px;
         | 
| 20 | 
            +
                padding: 40px;
         | 
| 21 | 
            +
                box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
         | 
|  | |
|  | |
|  | |
|  | |
| 22 | 
             
                max-width: 700px;
         | 
| 23 | 
             
                width: 100%;
         | 
| 24 | 
            +
                animation: slideIn 0.4s ease;
         | 
| 25 | 
            +
                max-height: 90vh;
         | 
| 26 | 
             
                overflow-y: auto;
         | 
| 27 | 
             
            }
         | 
| 28 |  | 
|  | |
| 31 | 
             
                to { opacity: 1; transform: translateY(0); }
         | 
| 32 | 
             
            }
         | 
| 33 |  | 
|  | |
| 34 | 
             
            h1 {
         | 
| 35 | 
            +
                color: #3D3D3D;
         | 
| 36 | 
            +
                font-size: 32px;
         | 
| 37 | 
            +
                margin-bottom: 8px;
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 38 | 
             
                text-align: center;
         | 
| 39 | 
            +
                font-weight: 800;
         | 
| 40 | 
             
            }
         | 
| 41 |  | 
| 42 | 
             
            h3 {
         | 
| 43 | 
             
                text-align: center;
         | 
| 44 | 
            +
                color: #3D3D3D;
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
| 45 | 
             
            }
         | 
| 46 |  | 
| 47 | 
             
            p {
         | 
| 48 | 
            +
                color: #6B7280;
         | 
| 49 | 
             
                text-align: center;
         | 
| 50 | 
            +
                margin-bottom: 30px;
         | 
| 51 | 
            +
                font-size: 15px;
         | 
| 52 | 
             
            }
         | 
| 53 |  | 
| 54 | 
             
            .subtitle {
         | 
| 55 | 
            +
                color: #9CA3AF;
         | 
| 56 | 
            +
                font-size: 14px;
         | 
| 57 | 
             
                text-align: center;
         | 
| 58 | 
            +
                margin-bottom: 25px;
         | 
| 59 | 
             
                line-height: 1.6;
         | 
|  | |
|  | |
|  | |
| 60 | 
             
            }
         | 
| 61 |  | 
| 62 | 
            +
            /* Form Inputs */
         | 
| 63 | 
            +
            input[type="text"], input[type="password"] {
         | 
| 64 | 
             
                width: 100%;
         | 
| 65 | 
            +
                padding: 12px 16px;
         | 
| 66 | 
            +
                font-size: 15px;
         | 
| 67 | 
             
                border: none;
         | 
| 68 | 
            +
                background: #F5F5F5;
         | 
| 69 | 
            +
                border-radius: 10px;
         | 
| 70 | 
            +
                transition: all 0.2s;
         | 
| 71 | 
             
                outline: none;
         | 
| 72 | 
             
            }
         | 
| 73 |  | 
|  | |
| 76 | 
             
                box-shadow: 0 0 0 2px #E5E5E5;
         | 
| 77 | 
             
            }
         | 
| 78 |  | 
| 79 | 
            +
            /* Buttons - Consolidated styles */
         | 
| 80 | 
             
            button, .btn, .nav-btn, .submit-btn {
         | 
| 81 | 
            +
                padding: 12px 24px;
         | 
| 82 | 
            +
                font-size: 15px;
         | 
| 83 | 
            +
                background: #3D3D3D;
         | 
| 84 | 
            +
                color: white;
         | 
| 85 | 
             
                border: none;
         | 
| 86 | 
            +
                border-radius: 10px;
         | 
| 87 | 
             
                cursor: pointer;
         | 
| 88 | 
            +
                transition: all 0.2s;
         | 
| 89 | 
            +
                font-weight: 600;
         | 
| 90 | 
             
                text-decoration: none;
         | 
| 91 | 
             
                display: inline-block;
         | 
| 92 | 
             
            }
         | 
| 93 |  | 
| 94 | 
             
            button:hover, .btn:hover, .nav-btn:hover, .submit-btn:hover {
         | 
| 95 | 
            +
                background: #1A1A1A;
         | 
| 96 | 
             
                transform: translateY(-1px);
         | 
| 97 | 
            +
                box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
         | 
| 98 | 
             
            }
         | 
| 99 |  | 
| 100 | 
             
            button:active, .btn:active {
         | 
|  | |
| 114 | 
             
                transform: none;
         | 
| 115 | 
             
            }
         | 
| 116 |  | 
| 117 | 
            +
            /* Secondary Buttons - Consolidated */
         | 
| 118 | 
            +
            .logout-btn, .reset-btn {
         | 
| 119 | 
            +
                background: #6B7280;
         | 
| 120 | 
            +
                padding: 8px 16px;
         | 
| 121 | 
            +
                font-size: 13px;
         | 
| 122 | 
            +
                margin-top: 15px;
         | 
|  | |
| 123 | 
             
            }
         | 
| 124 |  | 
| 125 | 
            +
            .logout-btn:hover, .reset-btn:hover {
         | 
| 126 | 
             
                background: #4B5563;
         | 
| 127 | 
            +
                box-shadow: 0 4px 12px rgba(107, 114, 128, 0.3);
         | 
| 128 | 
             
            }
         | 
| 129 |  | 
| 130 | 
             
            /* Submit Button */
         | 
| 131 | 
             
            .submit-btn {
         | 
| 132 | 
             
                width: 100%;
         | 
| 133 | 
            +
                padding: 16px;
         | 
| 134 | 
            +
                font-size: 16px;
         | 
| 135 | 
            +
                margin-top: 10px;
         | 
| 136 | 
             
            }
         | 
| 137 |  | 
| 138 | 
             
            /* Auth Form */
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 139 | 
             
            .auth-form input {
         | 
| 140 | 
             
                width: 100%;
         | 
| 141 | 
            +
                margin-bottom: 15px;
         | 
| 142 | 
             
            }
         | 
| 143 |  | 
| 144 | 
             
            .auth-form button {
         | 
| 145 | 
             
                width: 100%;
         | 
| 146 | 
             
            }
         | 
| 147 |  | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 148 | 
             
            .switch-link {
         | 
| 149 | 
            +
                color: #3D3D3D;
         | 
| 150 | 
             
                text-decoration: none;
         | 
| 151 | 
             
                cursor: pointer;
         | 
| 152 | 
            +
                font-weight: 600;
         | 
| 153 | 
            +
                margin-top: 15px;
         | 
| 154 | 
            +
                display: inline-block;
         | 
| 155 | 
            +
                transition: color 0.2s;
         | 
|  | |
|  | |
| 156 | 
             
            }
         | 
| 157 |  | 
| 158 | 
             
            .switch-link:hover {
         | 
| 159 | 
            +
                color: #1A1A1A;
         | 
| 160 | 
             
                text-decoration: underline;
         | 
| 161 | 
             
            }
         | 
| 162 |  | 
| 163 | 
            +
            /* Question Blocks */
         | 
|  | |
|  | |
| 164 | 
             
            .question-block {
         | 
| 165 | 
            +
                background: #FAFAFA;
         | 
| 166 | 
            +
                padding: 30px;
         | 
| 167 | 
            +
                border-radius: 12px;
         | 
| 168 | 
            +
                margin-bottom: 20px;
         | 
| 169 | 
             
                border: none;
         | 
| 170 | 
             
                display: none;
         | 
| 171 | 
             
                min-height: 400px;
         | 
|  | |
| 173 |  | 
| 174 | 
             
            .question-block.active {
         | 
| 175 | 
             
                display: block;
         | 
| 176 | 
            +
                animation: fadeIn 0.3s ease;
         | 
| 177 | 
             
            }
         | 
| 178 |  | 
| 179 | 
             
            @keyframes fadeIn {
         | 
|  | |
| 182 | 
             
            }
         | 
| 183 |  | 
| 184 | 
             
            .question-block h4 {
         | 
| 185 | 
            +
                color: #3D3D3D;
         | 
| 186 | 
            +
                margin-bottom: 25px;
         | 
| 187 | 
            +
                font-weight: 700;
         | 
| 188 | 
            +
                font-size: 18px;
         | 
| 189 | 
             
                line-height: 1.6;
         | 
| 190 | 
             
            }
         | 
| 191 |  | 
| 192 | 
             
            .question-number {
         | 
| 193 | 
             
                display: inline-block;
         | 
| 194 | 
            +
                background: #3D3D3D;
         | 
| 195 | 
            +
                color: #fff;
         | 
| 196 | 
             
                width: 32px;
         | 
| 197 | 
             
                height: 32px;
         | 
| 198 | 
            +
                border-radius: 50%;
         | 
| 199 | 
             
                text-align: center;
         | 
| 200 | 
             
                line-height: 32px;
         | 
| 201 | 
            +
                margin-right: 12px;
         | 
| 202 | 
            +
                font-size: 16px;
         | 
| 203 | 
             
            }
         | 
| 204 |  | 
| 205 | 
            +
            /* Options */
         | 
| 206 | 
             
            .option {
         | 
| 207 | 
            +
                display: block;
         | 
| 208 | 
            +
                padding: 16px 20px;
         | 
| 209 | 
            +
                margin-bottom: 12px;
         | 
| 210 | 
            +
                background: white;
         | 
|  | |
| 211 | 
             
                border: none;
         | 
| 212 | 
            +
                border-radius: 10px;
         | 
| 213 | 
             
                cursor: pointer;
         | 
| 214 | 
            +
                transition: all 0.2s;
         | 
| 215 | 
            +
                font-size: 15px;
         | 
| 216 | 
            +
                color: #3D3D3D;
         | 
| 217 | 
            +
                box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
         | 
| 218 | 
             
            }
         | 
| 219 |  | 
| 220 | 
             
            .option:hover {
         | 
| 221 | 
            +
                background: #F5F5F5;
         | 
| 222 | 
             
                transform: translateX(5px);
         | 
| 223 | 
            +
                box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
         | 
| 224 | 
             
            }
         | 
| 225 |  | 
| 226 | 
             
            .option input[type="radio"] {
         | 
| 227 | 
            +
                margin-right: 12px;
         | 
| 228 | 
             
                cursor: pointer;
         | 
| 229 | 
            +
                width: 18px;
         | 
| 230 | 
            +
                height: 18px;
         | 
| 231 | 
             
            }
         | 
| 232 |  | 
| 233 | 
             
            .option input[type="radio"]:disabled {
         | 
|  | |
| 241 | 
             
            }
         | 
| 242 |  | 
| 243 | 
             
            .option:has(input[type="radio"]:disabled):hover {
         | 
| 244 | 
            +
                background: white;
         | 
| 245 | 
             
                transform: none;
         | 
| 246 | 
             
            }
         | 
| 247 |  | 
| 248 | 
            +
            /* Question Counter & Progress */
         | 
| 249 | 
             
            .question-counter {
         | 
| 250 | 
             
                text-align: center;
         | 
| 251 | 
             
                color: #999;
         | 
| 252 | 
            +
                font-size: 14px;
         | 
| 253 | 
            +
                margin-bottom: 15px;
         | 
| 254 | 
            +
                font-weight: 600;
         | 
| 255 | 
             
            }
         | 
| 256 |  | 
| 257 | 
             
            .progress-bar {
         | 
| 258 | 
            +
                background: #F5F5F5;
         | 
| 259 | 
            +
                height: 8px;
         | 
| 260 | 
             
                border-radius: 4px;
         | 
| 261 | 
             
                overflow: hidden;
         | 
| 262 | 
            +
                margin-bottom: 20px;
         | 
| 263 | 
             
            }
         | 
| 264 |  | 
| 265 | 
             
            .progress-fill {
         | 
| 266 | 
            +
                background: #3D3D3D;
         | 
| 267 | 
             
                height: 100%;
         | 
| 268 | 
            +
                transition: width 0.3s;
         | 
| 269 | 
             
            }
         | 
| 270 |  | 
| 271 | 
            +
            /* Navigation */
         | 
| 272 | 
             
            .nav-buttons {
         | 
| 273 | 
             
                display: flex;
         | 
| 274 | 
            +
                gap: 12px;
         | 
| 275 | 
            +
                justify-content: space-between;
         | 
| 276 | 
            +
                margin-top: 20px;
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 277 | 
             
            }
         | 
| 278 |  | 
| 279 | 
             
            .buttons-row {
         | 
| 280 | 
             
                display: flex;
         | 
| 281 | 
            +
                gap: 10px;
         | 
| 282 | 
             
                justify-content: center;
         | 
| 283 | 
            +
                margin-top: 20px;
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 284 | 
             
            }
         | 
| 285 |  | 
| 286 | 
            +
            /* Results */
         | 
| 287 | 
             
            .result-card {
         | 
| 288 | 
            +
                padding: 25px;
         | 
| 289 | 
            +
                border-radius: 12px;
         | 
| 290 | 
            +
                margin-bottom: 20px;
         | 
| 291 | 
             
                border: none;
         | 
| 292 | 
            +
                box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
         | 
| 293 | 
             
            }
         | 
| 294 |  | 
| 295 | 
             
            .result-card.rank-1 {
         | 
| 296 | 
            +
                background: #FFFACD;
         | 
| 297 | 
             
            }
         | 
| 298 |  | 
| 299 | 
             
            .result-card.rank-2 {
         | 
| 300 | 
            +
                background: #B4C7E7;
         | 
| 301 | 
             
            }
         | 
| 302 |  | 
| 303 | 
             
            .result-card.rank-3 {
         | 
| 304 | 
            +
                background: #90EE90;
         | 
| 305 | 
             
            }
         | 
| 306 |  | 
| 307 | 
             
            .result-header {
         | 
| 308 | 
             
                display: flex;
         | 
| 309 | 
             
                align-items: center;
         | 
| 310 | 
             
                justify-content: space-between;
         | 
| 311 | 
            +
                margin-bottom: 15px;
         | 
| 312 | 
             
            }
         | 
| 313 |  | 
| 314 | 
             
            .result-rank {
         | 
| 315 | 
            +
                color: #fff;
         | 
| 316 | 
            +
                width: 40px;
         | 
| 317 | 
            +
                height: 40px;
         | 
| 318 | 
            +
                border-radius: 50%;
         | 
| 319 | 
             
                display: flex;
         | 
| 320 | 
             
                align-items: center;
         | 
| 321 | 
             
                justify-content: center;
         | 
| 322 | 
            +
                font-size: 20px;
         | 
| 323 | 
            +
                font-weight: 800;
         | 
| 324 | 
            +
                background: #3D3D3D;
         | 
| 325 | 
             
            }
         | 
| 326 |  | 
| 327 | 
             
            .result-title {
         | 
| 328 | 
             
                flex: 1;
         | 
| 329 | 
            +
                margin-left: 15px;
         | 
| 330 | 
             
            }
         | 
| 331 |  | 
| 332 | 
             
            .result-title h3 {
         | 
| 333 | 
            +
                font-size: 22px;
         | 
| 334 | 
             
                margin-bottom: 5px;
         | 
| 335 | 
            +
                color: #3D3D3D;
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
| 336 | 
             
            }
         | 
| 337 |  | 
| 338 | 
             
            .result-percentage {
         | 
| 339 | 
            +
                font-size: 24px;
         | 
| 340 | 
            +
                font-weight: 800;
         | 
| 341 | 
            +
                color: #3D3D3D;
         | 
| 342 | 
             
            }
         | 
| 343 |  | 
| 344 | 
             
            .result-description {
         | 
| 345 | 
             
                color: #666;
         | 
| 346 | 
             
                line-height: 1.6;
         | 
| 347 | 
            +
                margin-bottom: 12px;
         | 
| 348 | 
            +
                font-size: 14px;
         | 
| 349 | 
             
            }
         | 
| 350 |  | 
| 351 | 
             
            .result-details {
         | 
| 352 | 
             
                background: rgba(255, 255, 255, 0.6);
         | 
| 353 | 
             
                border: none;
         | 
| 354 | 
            +
                padding: 15px;
         | 
| 355 | 
            +
                border-radius: 8px;
         | 
| 356 | 
            +
                margin-top: 15px;
         | 
| 357 | 
             
            }
         | 
| 358 |  | 
| 359 | 
             
            .result-details h5 {
         | 
| 360 | 
            +
                color: #3D3D3D;
         | 
| 361 | 
            +
                font-size: 13px;
         | 
| 362 | 
            +
                margin-bottom: 8px;
         | 
| 363 | 
            +
                font-weight: 700;
         | 
| 364 | 
             
            }
         | 
| 365 |  | 
| 366 | 
             
            .result-details p {
         | 
| 367 | 
             
                color: #666;
         | 
| 368 | 
            +
                font-size: 13px;
         | 
| 369 | 
            +
                margin-bottom: 10px;
         | 
| 370 | 
             
                text-align: left;
         | 
| 371 | 
             
            }
         | 
| 372 |  | 
| 373 | 
            +
            /* Icons & Messages */
         | 
| 374 | 
             
            .icon {
         | 
| 375 | 
            +
                font-size: 24px;
         | 
| 376 | 
            +
                margin-right: 8px;
         | 
| 377 | 
             
            }
         | 
| 378 |  | 
| 379 | 
             
            .success-msg {
         | 
| 380 | 
            +
                color: #3D3D3D;
         | 
| 381 | 
            +
                font-weight: 600;
         | 
| 382 | 
             
            }
         | 
| 383 |  | 
| 384 | 
             
            .error-msg {
         | 
| 385 | 
             
                color: #666;
         | 
| 386 | 
            +
                font-weight: 600;
         | 
| 387 | 
             
                text-align: center;
         | 
| 388 | 
            +
                padding: 10px;
         | 
| 389 | 
             
            }
         | 
| 390 |  | 
| 391 | 
            +
            /* Chat Interface */
         | 
| 392 | 
             
            .chat-toggle-btn {
         | 
| 393 | 
             
                background: rgba(255, 255, 255, 0.8);
         | 
| 394 | 
            +
                color: #3D3D3D;
         | 
| 395 | 
             
                border: none;
         | 
| 396 | 
            +
                padding: 10px 20px;
         | 
| 397 | 
            +
                border-radius: 8px;
         | 
| 398 | 
             
                cursor: pointer;
         | 
| 399 | 
            +
                font-size: 14px;
         | 
| 400 | 
            +
                font-weight: 600;
         | 
| 401 | 
            +
                margin-top: 15px;
         | 
| 402 | 
             
                width: 100%;
         | 
| 403 | 
            +
                transition: background 0.2s, color 0.2s;
         | 
| 404 | 
            +
                box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
         | 
| 405 | 
             
            }
         | 
| 406 |  | 
| 407 | 
             
            .chat-toggle-btn:hover {
         | 
| 408 | 
            +
                background: #3D3D3D;
         | 
| 409 | 
            +
                color: #fff;
         | 
| 410 | 
             
            }
         | 
| 411 |  | 
| 412 | 
             
            .chat-window {
         | 
| 413 | 
             
                display: none;
         | 
| 414 | 
             
                background: rgba(255, 255, 255, 0.9);
         | 
| 415 | 
             
                border: none;
         | 
| 416 | 
            +
                border-radius: 10px;
         | 
| 417 | 
            +
                margin-top: 15px;
         | 
| 418 | 
             
                overflow: hidden;
         | 
| 419 | 
            +
                box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
         | 
| 420 | 
             
            }
         | 
| 421 |  | 
| 422 | 
             
            .chat-window.open {
         | 
| 423 | 
             
                display: block;
         | 
| 424 | 
            +
                animation: slideDown 0.3s ease;
         | 
| 425 | 
             
            }
         | 
| 426 |  | 
| 427 | 
             
            @keyframes slideDown {
         | 
|  | |
| 432 | 
             
            .chat-messages {
         | 
| 433 | 
             
                height: 250px;
         | 
| 434 | 
             
                overflow-y: auto;
         | 
| 435 | 
            +
                padding: 15px;
         | 
| 436 | 
             
                background: transparent;
         | 
| 437 | 
             
            }
         | 
| 438 |  | 
| 439 | 
             
            .chat-message {
         | 
| 440 | 
            +
                margin-bottom: 12px;
         | 
| 441 | 
            +
                padding: 10px 14px;
         | 
| 442 | 
            +
                border-radius: 8px;
         | 
| 443 | 
             
                max-width: 85%;
         | 
| 444 | 
             
                line-height: 1.5;
         | 
| 445 | 
            +
                font-size: 14px;
         | 
| 446 | 
             
            }
         | 
| 447 |  | 
| 448 | 
             
            .chat-message.user {
         | 
| 449 | 
            +
                background: #3D3D3D;
         | 
| 450 | 
            +
                color: #fff;
         | 
| 451 | 
             
                margin-left: auto;
         | 
| 452 | 
             
                text-align: right;
         | 
| 453 | 
             
            }
         | 
| 454 |  | 
| 455 | 
             
            .chat-message.bot {
         | 
| 456 | 
            +
                background: white;
         | 
| 457 | 
            +
                color: #3D3D3D;
         | 
| 458 | 
             
                border: none;
         | 
| 459 | 
             
                text-align: left;
         | 
| 460 | 
            +
                box-shadow: 0 2px 6px rgba(0, 0, 0, 0.04);
         | 
| 461 | 
             
            }
         | 
| 462 |  | 
| 463 | 
             
            .chat-message.bot ul {
         | 
| 464 | 
            +
                margin: 8px 0 0 0;
         | 
| 465 | 
            +
                padding-left: 20px;
         | 
| 466 | 
             
            }
         | 
| 467 |  | 
| 468 | 
             
            .chat-message.bot li {
         | 
|  | |
| 472 |  | 
| 473 | 
             
            .chat-input-area {
         | 
| 474 | 
             
                display: flex;
         | 
| 475 | 
            +
                gap: 8px;
         | 
| 476 | 
            +
                padding: 12px;
         | 
| 477 | 
             
                background: transparent;
         | 
| 478 | 
             
                border-top: none;
         | 
| 479 | 
             
            }
         | 
| 480 |  | 
| 481 | 
             
            .chat-input {
         | 
| 482 | 
             
                flex: 1;
         | 
| 483 | 
            +
                padding: 10px 14px;
         | 
| 484 | 
             
                border: none;
         | 
| 485 | 
            +
                background: white;
         | 
| 486 | 
            +
                border-radius: 8px;
         | 
| 487 | 
            +
                font-size: 14px;
         | 
| 488 | 
             
                outline: none;
         | 
| 489 | 
            +
                color: #3D3D3D;
         | 
| 490 | 
            +
                box-shadow: 0 2px 6px rgba(0, 0, 0, 0.04);
         | 
| 491 | 
             
            }
         | 
| 492 |  | 
| 493 | 
             
            .chat-input:focus {
         | 
| 494 | 
            +
                box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
         | 
| 495 | 
             
            }
         | 
| 496 |  | 
| 497 | 
             
            .chat-send-btn {
         | 
| 498 | 
            +
                padding: 10px 20px;
         | 
| 499 | 
            +
                background: #3D3D3D;
         | 
| 500 | 
            +
                color: #fff;
         | 
| 501 | 
             
                border: none;
         | 
| 502 | 
            +
                border-radius: 8px;
         | 
| 503 | 
             
                cursor: pointer;
         | 
| 504 | 
            +
                font-weight: 600;
         | 
| 505 | 
            +
                font-size: 14px;
         | 
| 506 | 
            +
                transition: background 0.2s;
         | 
| 507 | 
             
            }
         | 
| 508 |  | 
| 509 | 
             
            .chat-send-btn:hover {
         | 
| 510 | 
            +
                background: #1A1A1A;
         | 
| 511 | 
            +
                color: #fff;
         | 
| 512 | 
             
            }
         | 
| 513 |  | 
| 514 | 
             
            .chat-send-btn:disabled {
         | 
| 515 | 
            +
                background: #F5F5F5;
         | 
| 516 | 
             
                color: #999;
         | 
| 517 | 
            +
                cursor: not-allowed;
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 518 | 
             
            }
         | 
| 519 |  | 
| 520 | 
             
            .chat-typing {
         | 
| 521 | 
             
                color: #999;
         | 
| 522 | 
             
                font-style: italic;
         | 
| 523 | 
            +
                font-size: 13px;
         | 
| 524 | 
            +
                padding: 10px 14px;
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 525 | 
             
            }
         | 
| 526 |  | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
    	
        static/video/Animation (Light theme).mp4
    DELETED
    
    | @@ -1,3 +0,0 @@ | |
| 1 | 
            -
            version https://git-lfs.github.com/spec/v1
         | 
| 2 | 
            -
            oid sha256:c53cd9d87f17d8c3e0500572a448609819d7bb1f44d61e19727c65ed15977ac1
         | 
| 3 | 
            -
            size 6026968
         | 
|  | |
|  | |
|  | |
|  | 
    	
        templates/index.html
    CHANGED
    
    | @@ -1,132 +1,35 @@ | |
| 1 | 
             
            <!DOCTYPE html>
         | 
| 2 | 
             
            <html>
         | 
| 3 | 
             
            <head>
         | 
| 4 | 
            -
                <meta charset="UTF-8">
         | 
| 5 | 
            -
                <meta name="viewport" content="width=device-width, initial-scale=1.0">
         | 
| 6 | 
             
                <title>{{ title if logged_in else 'Spiritual Path Finder - Login' }}</title>
         | 
| 7 | 
             
                <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
         | 
| 8 | 
            -
                <!-- Add Font Awesome here -->
         | 
| 9 | 
            -
                <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
         | 
| 10 | 
            -
                
         | 
| 11 | 
            -
                <!-- Firebase SDK -->
         | 
| 12 | 
            -
                <script src="https://www.gstatic.com/firebasejs/10.7.1/firebase-app-compat.js"></script>
         | 
| 13 | 
            -
                <script src="https://www.gstatic.com/firebasejs/10.7.1/firebase-auth-compat.js"></script>
         | 
| 14 | 
            -
                
         | 
| 15 | 
            -
                {% if firebase_config and firebase_config.apiKey %}
         | 
| 16 | 
            -
                <script>
         | 
| 17 | 
            -
                    // Initialize Firebase
         | 
| 18 | 
            -
                    const firebaseConfig = {
         | 
| 19 | 
            -
                        apiKey: "{{ firebase_config.apiKey }}",
         | 
| 20 | 
            -
                        authDomain: "{{ firebase_config.authDomain }}",
         | 
| 21 | 
            -
                        projectId: "{{ firebase_config.projectId }}",
         | 
| 22 | 
            -
                        storageBucket: "{{ firebase_config.storageBucket }}",
         | 
| 23 | 
            -
                        messagingSenderId: "{{ firebase_config.messagingSenderId }}",
         | 
| 24 | 
            -
                        appId: "{{ firebase_config.appId }}"
         | 
| 25 | 
            -
                    };
         | 
| 26 | 
            -
                    firebase.initializeApp(firebaseConfig);
         | 
| 27 | 
            -
                    window.firebaseAuth = firebase.auth();
         | 
| 28 | 
            -
                    window.firebaseEnabled = true;
         | 
| 29 | 
            -
                </script>
         | 
| 30 | 
            -
                {% else %}
         | 
| 31 | 
            -
                <script>
         | 
| 32 | 
            -
                    window.firebaseEnabled = false;
         | 
| 33 | 
            -
                </script>
         | 
| 34 | 
            -
                {% endif %}
         | 
| 35 | 
             
            </head>
         | 
| 36 | 
             
            <body>
         | 
| 37 | 
            -
                <div class=" | 
| 38 | 
            -
                    <div class="nav-header">
         | 
| 39 | 
            -
                        <a href="/" class="back-link">← Back to Home</a>
         | 
| 40 | 
            -
                    </div>
         | 
| 41 | 
             
                    {% if not logged_in %}
         | 
| 42 | 
             
                        <!-- Login/Signup Form -->
         | 
| 43 | 
            -
                        < | 
| 44 | 
             
                        <p>{{ 'Begin your journey of self-discovery' if is_signup else 'Welcome back, seeker!' }}</p>
         | 
| 45 |  | 
| 46 | 
            -
                        {% if verify_success %}
         | 
| 47 | 
            -
                        <div class="success-msg" style="padding: 15px; margin-bottom: 20px; border-radius: 8px;">
         | 
| 48 | 
            -
                            ✅ Email verified successfully! You can now sign in.
         | 
| 49 | 
            -
                        </div>
         | 
| 50 | 
            -
                        {% endif %}
         | 
| 51 | 
            -
                        
         | 
| 52 | 
            -
                        {% if verify_error %}
         | 
| 53 | 
            -
                        <div class="error-msg" style="padding: 15px; margin-bottom: 20px; border-radius: 8px;">
         | 
| 54 | 
            -
                            ⚠️ {{ verify_error }}
         | 
| 55 | 
            -
                        </div>
         | 
| 56 | 
            -
                        {% endif %}
         | 
| 57 | 
            -
                        
         | 
| 58 | 
            -
                        {% if reset_error %}
         | 
| 59 | 
            -
                        <div class="error-msg" style="padding: 15px; margin-bottom: 20px; border-radius: 8px;">
         | 
| 60 | 
            -
                            ⚠️ {{ reset_error }}
         | 
| 61 | 
            -
                        </div>
         | 
| 62 | 
            -
                        {% endif %}
         | 
| 63 | 
            -
                        
         | 
| 64 | 
             
                        <div class="auth-form">
         | 
| 65 | 
            -
                             | 
| 66 | 
            -
                             | 
| 67 | 
            -
                            {% if firebase_config and firebase_config.apiKey %}
         | 
| 68 | 
            -
                            <button class="google-signin-btn" onclick="signInWithGoogle()">
         | 
| 69 | 
            -
                                <svg width="18" height="18" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
         | 
| 70 | 
            -
                                    <path fill="#EA4335" d="M24 9.5c3.54 0 6.71 1.22 9.21 3.6l6.85-6.85C35.9 2.38 30.47 0 24 0 14.62 0 6.51 5.38 2.56 13.22l7.98 6.19C12.43 13.72 17.74 9.5 24 9.5z"/>
         | 
| 71 | 
            -
                                    <path fill="#4285F4" d="M46.98 24.55c0-1.57-.15-3.09-.38-4.55H24v9.02h12.94c-.58 2.96-2.26 5.48-4.78 7.18l7.73 6c4.51-4.18 7.09-10.36 7.09-17.65z"/>
         | 
| 72 | 
            -
                                    <path fill="#FBBC05" d="M10.53 28.59c-.48-1.45-.76-2.99-.76-4.59s.27-3.14.76-4.59l-7.98-6.19C.92 16.46 0 20.12 0 24c0 3.88.92 7.54 2.56 10.78l7.97-6.19z"/>
         | 
| 73 | 
            -
                                    <path fill="#34A853" d="M24 48c6.48 0 11.93-2.13 15.89-5.81l-7.73-6c-2.15 1.45-4.92 2.3-8.16 2.3-6.26 0-11.57-4.22-13.47-9.91l-7.98 6.19C6.51 42.62 14.62 48 24 48z"/>
         | 
| 74 | 
            -
                                    <path fill="none" d="M0 0h48v48H0z"/>
         | 
| 75 | 
            -
                                </svg>
         | 
| 76 | 
            -
                                Continue with Google
         | 
| 77 | 
            -
                            </button>
         | 
| 78 | 
            -
                            
         | 
| 79 | 
            -
                            <div class="divider">
         | 
| 80 | 
            -
                                <span>or</span>
         | 
| 81 | 
            -
                            </div>
         | 
| 82 | 
            -
                            {% endif %}
         | 
| 83 | 
            -
                            
         | 
| 84 | 
            -
                            <!-- Around line 84-88 -->
         | 
| 85 | 
            -
                            {% if firebase_config and firebase_config.apiKey %}
         | 
| 86 | 
            -
                            <input type="email" id="authEmail" placeholder="Email">
         | 
| 87 | 
            -
                            {% else %}
         | 
| 88 | 
            -
                            <input type="text" id="authUsername" placeholder="User name">
         | 
| 89 | 
            -
                            {% endif %}
         | 
| 90 | 
            -
                            {% if is_signup and firebase_config and firebase_config.apiKey %}
         | 
| 91 | 
            -
                            <input type="text" id="authUsername" placeholder="Display Name (optional)">
         | 
| 92 | 
            -
                            {% elif not firebase_config or not firebase_config.apiKey %}
         | 
| 93 | 
            -
                            {% if is_signup %}
         | 
| 94 | 
            -
                            <input type="email" id="authEmail" placeholder="Email">
         | 
| 95 | 
            -
                            {% endif %}
         | 
| 96 | 
            -
                            {% endif %} 
         | 
| 97 | 
            -
                            
         | 
| 98 | 
             
                            <button onclick="authenticate()">{{ 'Sign Up' if is_signup else 'Sign In' }}</button>
         | 
| 99 | 
             
                            <div id="result"></div>
         | 
| 100 | 
            -
                            {% if not is_signup %}
         | 
| 101 | 
            -
                            <p class="switch-link" onclick="window.location.href='/forgot-password'">
         | 
| 102 | 
            -
                                Forgot Password?
         | 
| 103 | 
            -
                            </p>
         | 
| 104 | 
            -
                            {% endif %}
         | 
| 105 | 
             
                            <p class="switch-link" onclick="switchAuth()">
         | 
| 106 | 
             
                                {{ 'Already have an account? Sign In' if is_signup else 'New here? Sign Up' }}
         | 
| 107 | 
             
                            </p>
         | 
| 108 | 
            -
                            {% else %}
         | 
| 109 | 
            -
                            {% if show_reset_form %}
         | 
| 110 | 
            -
                            <input type="password" id="resetPassword" placeholder="New Password">
         | 
| 111 | 
            -
                            <input type="hidden" id="resetToken" value="{{ reset_token }}">
         | 
| 112 | 
            -
                            <button onclick="submitPasswordReset()">Reset Password</button>
         | 
| 113 | 
            -
                            <div id="result"></div>
         | 
| 114 | 
            -
                            {% else %}
         | 
| 115 | 
            -
                            <input type="email" id="resetEmail" placeholder="Email">
         | 
| 116 | 
            -
                            <button onclick="resetPassword()">Send Reset Link</button>
         | 
| 117 | 
            -
                            <div id="result"></div>
         | 
| 118 | 
            -
                            {% endif %}
         | 
| 119 | 
            -
                            <p class="switch-link" onclick="window.location.href='/login'">
         | 
| 120 | 
            -
                                Back to Sign In
         | 
| 121 | 
            -
                            </p>
         | 
| 122 | 
            -
                            {% endif %}
         | 
| 123 | 
             
                        </div>
         | 
| 124 | 
             
                    {% else %}
         | 
| 125 | 
             
                        <!-- Assessment Interface -->
         | 
| 126 | 
            -
                        < | 
| 127 | 
            -
                        <p>{{ message }} | 
| 128 |  | 
| 129 | 
             
                        {% if not has_results %}
         | 
|  | |
|  | |
|  | |
|  | |
| 130 |  | 
| 131 | 
             
                            <div class="question-counter" id="questionCounter">Question 1 of {{ questions|length }}</div>
         | 
| 132 |  | 
| @@ -158,9 +61,9 @@ | |
| 158 | 
             
                                    </label>
         | 
| 159 | 
             
                                    {% endfor %}
         | 
| 160 |  | 
| 161 | 
            -
                                    <div class="nav-buttons">
         | 
| 162 | 
            -
                                        <button type="button" class="nav-btn  | 
| 163 | 
            -
                                             | 
| 164 | 
             
                                        </button>
         | 
| 165 | 
             
                                    </div>
         | 
| 166 | 
             
                                </div>
         | 
| @@ -177,11 +80,8 @@ | |
| 177 | 
             
                            <p class="subtitle">
         | 
| 178 | 
             
                                Based on your responses, here are the spiritual paths that align most closely with your values and beliefs:
         | 
| 179 | 
             
                            </p>
         | 
| 180 | 
            -
                            <div class="results-explanation">
         | 
| 181 | 
            -
                                * Percentages reflect how strongly your answers align with each path, using weighted scoring where more fundamental beliefs count more.
         | 
| 182 | 
            -
                            </div>
         | 
| 183 |  | 
| 184 | 
            -
                            <div id="resultsContainer" | 
| 185 | 
             
                                {% for result in results %}
         | 
| 186 | 
             
                                <div class="result-card rank-{{ loop.index }}">
         | 
| 187 | 
             
                                    <div class="result-header">
         | 
| @@ -193,21 +93,22 @@ | |
| 193 | 
             
                                    </div>
         | 
| 194 | 
             
                                    <p class="result-description">{{ result.description }}</p>
         | 
| 195 | 
             
                                    <div class="result-details">
         | 
| 196 | 
            -
                                        <h5 | 
| 197 | 
             
                                        <p>{{ result.practices }}</p>
         | 
| 198 | 
            -
                                        <h5 | 
| 199 | 
             
                                        <p>{{ result.core_beliefs }}</p>
         | 
| 200 | 
             
                                    </div>
         | 
| 201 |  | 
| 202 | 
             
                                    <button class="chat-toggle-btn" onclick="toggleChat('{{ result.name }}')">
         | 
| 203 | 
            -
                                         | 
| 204 | 
             
                                    </button>
         | 
| 205 |  | 
| 206 | 
             
                                    <div class="chat-window" id="chat-{{ result.name|replace(' ', '-') }}">
         | 
| 207 | 
             
                                        <div class="chat-messages" id="messages-{{ result.name|replace(' ', '-') }}">
         | 
| 208 | 
             
                                            <div class="chat-message bot">
         | 
| 209 | 
             
                                                Hi! Ask me anything about {{ result.name }}.<br>
         | 
| 210 | 
            -
                                                <span style="color:# | 
|  | |
| 211 | 
             
                                                    Example: "How do I get started with this path?"
         | 
| 212 | 
             
                                                </span>
         | 
| 213 | 
             
                                            </div>
         | 
| @@ -218,15 +119,6 @@ | |
| 218 | 
             
                                                   id="input-{{ result.name|replace(' ', '-') }}"
         | 
| 219 | 
             
                                                   placeholder="Ask about {{ result.name }}..."
         | 
| 220 | 
             
                                                   onkeypress="if(event.key==='Enter') sendMessage('{{ result.name }}')">
         | 
| 221 | 
            -
                                            <button class="voice-btn" 
         | 
| 222 | 
            -
                                                    id="voice-{{ result.name|replace(' ', '-') }}"
         | 
| 223 | 
            -
                                                    onmousedown="startVoiceInput('{{ result.name }}')"
         | 
| 224 | 
            -
                                                    onmouseup="stopVoiceInput('{{ result.name }}')"
         | 
| 225 | 
            -
                                                    ontouchstart="startVoiceInput('{{ result.name }}')"
         | 
| 226 | 
            -
                                                    ontouchend="stopVoiceInput('{{ result.name }}')"
         | 
| 227 | 
            -
                                                    title="Hold to record with live transcription">
         | 
| 228 | 
            -
                                                    <i class="fa-solid fa-microphone"></i>
         | 
| 229 | 
            -
                                            </button>
         | 
| 230 | 
             
                                            <button class="chat-send-btn" 
         | 
| 231 | 
             
                                                    id="send-{{ result.name|replace(' ', '-') }}"
         | 
| 232 | 
             
                                                    onclick="sendMessage('{{ result.name }}')">
         | 
| @@ -239,17 +131,13 @@ | |
| 239 | 
             
                            </div>
         | 
| 240 |  | 
| 241 | 
             
                            <div class="buttons-row">
         | 
| 242 | 
            -
                                <button class="btn reset-btn" onclick="resetAssessment()"> | 
| 243 | 
            -
                                    <i class="fa-solid fa-arrow-rotate-right"></i> Retake Assessment
         | 
| 244 | 
            -
                                </button>
         | 
| 245 | 
            -
                                <button class="btn share-btn" onclick="shareResults()">
         | 
| 246 | 
            -
                                    <i class="fa-solid fa-share-nodes"></i> Share Results
         | 
| 247 | 
            -
                                </button>
         | 
| 248 | 
            -
                                <a href="/logout" class="btn logout-btn">
         | 
| 249 | 
            -
                                    <i class="fa-solid fa-arrow-right-from-bracket"></i> Sign Out
         | 
| 250 | 
            -
                                </a>
         | 
| 251 | 
             
                            </div>
         | 
| 252 | 
             
                        {% endif %}
         | 
|  | |
|  | |
|  | |
|  | |
| 253 | 
             
                    {% endif %}
         | 
| 254 | 
             
                </div>
         | 
| 255 | 
             
                <script src="{{ url_for('static', filename='script.js') }}"></script>
         | 
|  | |
| 1 | 
             
            <!DOCTYPE html>
         | 
| 2 | 
             
            <html>
         | 
| 3 | 
             
            <head>
         | 
|  | |
|  | |
| 4 | 
             
                <title>{{ title if logged_in else 'Spiritual Path Finder - Login' }}</title>
         | 
| 5 | 
             
                <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 6 | 
             
            </head>
         | 
| 7 | 
             
            <body>
         | 
| 8 | 
            +
                <div class="container">
         | 
|  | |
|  | |
|  | |
| 9 | 
             
                    {% if not logged_in %}
         | 
| 10 | 
             
                        <!-- Login/Signup Form -->
         | 
| 11 | 
            +
                        <h1><span class="icon">🌟</span>Spiritual Path Finder</h1>
         | 
| 12 | 
             
                        <p>{{ 'Begin your journey of self-discovery' if is_signup else 'Welcome back, seeker!' }}</p>
         | 
| 13 |  | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 14 | 
             
                        <div class="auth-form">
         | 
| 15 | 
            +
                            <input type="text" id="authUsername" placeholder="Username">
         | 
| 16 | 
            +
                            <input type="password" id="authPassword" placeholder="Password">
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 17 | 
             
                            <button onclick="authenticate()">{{ 'Sign Up' if is_signup else 'Sign In' }}</button>
         | 
| 18 | 
             
                            <div id="result"></div>
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
| 19 | 
             
                            <p class="switch-link" onclick="switchAuth()">
         | 
| 20 | 
             
                                {{ 'Already have an account? Sign In' if is_signup else 'New here? Sign Up' }}
         | 
| 21 | 
             
                            </p>
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 22 | 
             
                        </div>
         | 
| 23 | 
             
                    {% else %}
         | 
| 24 | 
             
                        <!-- Assessment Interface -->
         | 
| 25 | 
            +
                        <h1>{{ title }}</h1>
         | 
| 26 | 
            +
                        <p>{{ message }}</p>
         | 
| 27 |  | 
| 28 | 
             
                        {% if not has_results %}
         | 
| 29 | 
            +
                            <p class="subtitle">
         | 
| 30 | 
            +
                                Discover which spiritual or religious path aligns with your beliefs, values, and lifestyle. 
         | 
| 31 | 
            +
                                Answer 8 thoughtful questions about your worldview.
         | 
| 32 | 
            +
                            </p>
         | 
| 33 |  | 
| 34 | 
             
                            <div class="question-counter" id="questionCounter">Question 1 of {{ questions|length }}</div>
         | 
| 35 |  | 
|  | |
| 61 | 
             
                                    </label>
         | 
| 62 | 
             
                                    {% endfor %}
         | 
| 63 |  | 
| 64 | 
            +
                                    <div class="nav-buttons" style="justify-content: flex-end;">
         | 
| 65 | 
            +
                                        <button type="button" class="nav-btn next" id="nextBtn{{ q_index }}" onclick="goToNext()" disabled>
         | 
| 66 | 
            +
                                            Next →
         | 
| 67 | 
             
                                        </button>
         | 
| 68 | 
             
                                    </div>
         | 
| 69 | 
             
                                </div>
         | 
|  | |
| 80 | 
             
                            <p class="subtitle">
         | 
| 81 | 
             
                                Based on your responses, here are the spiritual paths that align most closely with your values and beliefs:
         | 
| 82 | 
             
                            </p>
         | 
|  | |
|  | |
|  | |
| 83 |  | 
| 84 | 
            +
                            <div id="resultsContainer">
         | 
| 85 | 
             
                                {% for result in results %}
         | 
| 86 | 
             
                                <div class="result-card rank-{{ loop.index }}">
         | 
| 87 | 
             
                                    <div class="result-header">
         | 
|  | |
| 93 | 
             
                                    </div>
         | 
| 94 | 
             
                                    <p class="result-description">{{ result.description }}</p>
         | 
| 95 | 
             
                                    <div class="result-details">
         | 
| 96 | 
            +
                                        <h5>📿 Common Practices:</h5>
         | 
| 97 | 
             
                                        <p>{{ result.practices }}</p>
         | 
| 98 | 
            +
                                        <h5>💭 Core Beliefs:</h5>
         | 
| 99 | 
             
                                        <p>{{ result.core_beliefs }}</p>
         | 
| 100 | 
             
                                    </div>
         | 
| 101 |  | 
| 102 | 
             
                                    <button class="chat-toggle-btn" onclick="toggleChat('{{ result.name }}')">
         | 
| 103 | 
            +
                                        💬 Ask Questions About {{ result.name }}
         | 
| 104 | 
             
                                    </button>
         | 
| 105 |  | 
| 106 | 
             
                                    <div class="chat-window" id="chat-{{ result.name|replace(' ', '-') }}">
         | 
| 107 | 
             
                                        <div class="chat-messages" id="messages-{{ result.name|replace(' ', '-') }}">
         | 
| 108 | 
             
                                            <div class="chat-message bot">
         | 
| 109 | 
             
                                                Hi! Ask me anything about {{ result.name }}.<br>
         | 
| 110 | 
            +
                                                <span style="color:#7C3AED; font-size:13px;">
         | 
| 111 | 
            +
                                                    Example: "What are the daily practices?"<br>
         | 
| 112 | 
             
                                                    Example: "How do I get started with this path?"
         | 
| 113 | 
             
                                                </span>
         | 
| 114 | 
             
                                            </div>
         | 
|  | |
| 119 | 
             
                                                   id="input-{{ result.name|replace(' ', '-') }}"
         | 
| 120 | 
             
                                                   placeholder="Ask about {{ result.name }}..."
         | 
| 121 | 
             
                                                   onkeypress="if(event.key==='Enter') sendMessage('{{ result.name }}')">
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 122 | 
             
                                            <button class="chat-send-btn" 
         | 
| 123 | 
             
                                                    id="send-{{ result.name|replace(' ', '-') }}"
         | 
| 124 | 
             
                                                    onclick="sendMessage('{{ result.name }}')">
         | 
|  | |
| 131 | 
             
                            </div>
         | 
| 132 |  | 
| 133 | 
             
                            <div class="buttons-row">
         | 
| 134 | 
            +
                                <button class="btn reset-btn" onclick="resetAssessment()">🔄 Retake Assessment</button>
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 135 | 
             
                            </div>
         | 
| 136 | 
             
                        {% endif %}
         | 
| 137 | 
            +
                        
         | 
| 138 | 
            +
                        <div style="text-align: center;">
         | 
| 139 | 
            +
                            <a href="/logout" class="btn logout-btn">Logout</a>
         | 
| 140 | 
            +
                        </div>
         | 
| 141 | 
             
                    {% endif %}
         | 
| 142 | 
             
                </div>
         | 
| 143 | 
             
                <script src="{{ url_for('static', filename='script.js') }}"></script>
         | 
    	
        templates/landing.html
    DELETED
    
    | @@ -1,109 +0,0 @@ | |
| 1 | 
            -
            <!DOCTYPE html>
         | 
| 2 | 
            -
            <html lang="en">
         | 
| 3 | 
            -
            <head>
         | 
| 4 | 
            -
                <meta charset="UTF-8">
         | 
| 5 | 
            -
                <meta name="viewport" content="width=device-width, initial-scale=1.0">
         | 
| 6 | 
            -
                <title>Spiritual Path Assessment</title>
         | 
| 7 | 
            -
                <link rel="stylesheet" href="{{ url_for('static', filename='landing.css') }}">
         | 
| 8 | 
            -
                <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap" rel="stylesheet">
         | 
| 9 | 
            -
                <!-- Add Font Awesome here -->
         | 
| 10 | 
            -
                <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
         | 
| 11 | 
            -
            </head>
         | 
| 12 | 
            -
            <body>
         | 
| 13 | 
            -
                <div class="gradient-bg"></div>
         | 
| 14 | 
            -
                
         | 
| 15 | 
            -
                <nav class="navbar">
         | 
| 16 | 
            -
                    <div class="nav-container">
         | 
| 17 | 
            -
                        <div class="logo"> <i class="fa-solid fa-compass"></i> Spiritual Path</div>
         | 
| 18 | 
            -
                        <!-- <a href="/login" class="nav-cta">Start Assessment</a> -->
         | 
| 19 | 
            -
                    </div>
         | 
| 20 | 
            -
                </nav>
         | 
| 21 | 
            -
             | 
| 22 | 
            -
                <main class="main-content">
         | 
| 23 | 
            -
                    <section class="hero-section">
         | 
| 24 | 
            -
                        <!-- Video Background -->
         | 
| 25 | 
            -
                            <video class="hero-video" autoplay muted loop playsinline preload="auto">
         | 
| 26 | 
            -
                                <source src="{{ url_for('static', filename='video/Animation (Light theme).mp4') }}" type="video/mp4">
         | 
| 27 | 
            -
                                Your browser does not support the video tag.
         | 
| 28 | 
            -
                            </video>
         | 
| 29 | 
            -
                        
         | 
| 30 | 
            -
                        <div class="hero-container">
         | 
| 31 | 
            -
                            <div class="badge"> <i class="fa-solid fa-compass"></i> Discover Your Path</div>
         | 
| 32 | 
            -
                            <h1 class="hero-title">
         | 
| 33 | 
            -
                                Find Your Spiritual Journey
         | 
| 34 | 
            -
                            </h1>
         | 
| 35 | 
            -
                            <p class="hero-subtitle">
         | 
| 36 | 
            -
                                Discover the spiritual or religious path that resonates with your unique beliefs, values, and lifestyle.
         | 
| 37 | 
            -
                                Answer 9 thoughtful questions to gain deep insights into your worldview.
         | 
| 38 | 
            -
                            </p>
         | 
| 39 | 
            -
                            
         | 
| 40 | 
            -
                            <div class="cta-buttons">
         | 
| 41 | 
            -
                                <a href="/login" class="btn-primary">
         | 
| 42 | 
            -
                                    Begin Your Assessment
         | 
| 43 | 
            -
                                    <span class="arrow">→</span>
         | 
| 44 | 
            -
                                </a>
         | 
| 45 | 
            -
                                <div class="assessment-meta">
         | 
| 46 | 
            -
                                    <span><i class="fa-solid fa-clock"></i> 5-10 minutes</span>
         | 
| 47 | 
            -
                                    <span><i class="fa-solid fa-heart"></i> Completely free</span>
         | 
| 48 | 
            -
                                    <span><i class="fa-solid fa-file"></i> Personalized insights</span>
         | 
| 49 | 
            -
                                </div>
         | 
| 50 | 
            -
                            </div>
         | 
| 51 | 
            -
                        </div>
         | 
| 52 | 
            -
                    </section>
         | 
| 53 | 
            -
             | 
| 54 | 
            -
                    <section class="features-section">
         | 
| 55 | 
            -
                        <div class="section-container">
         | 
| 56 | 
            -
                            <div class="section-header">
         | 
| 57 | 
            -
                                <h2>What You'll Discover</h2>
         | 
| 58 | 
            -
                                <p class="section-subtitle">
         | 
| 59 | 
            -
                                    After completing the assessment, explore your top 3 spiritual paths and ask questions through our interactive chat feature.
         | 
| 60 | 
            -
                                </p>
         | 
| 61 | 
            -
                            </div>
         | 
| 62 | 
            -
             | 
| 63 | 
            -
                            <div class="features-grid">
         | 
| 64 | 
            -
                                <div class="feature-card">
         | 
| 65 | 
            -
                                    <div class="feature-icon-wrapper">
         | 
| 66 | 
            -
                                        <img src="{{ url_for('static', filename='images/icon3.png') }}" alt="ring icon" class="feature-icon-img">
         | 
| 67 | 
            -
                                    </div>
         | 
| 68 | 
            -
                                    <h3>Your Spiritual Dimensions</h3>
         | 
| 69 | 
            -
                                    <p>Understand your current spiritual development across multiple dimensions and uncover hidden aspects of your journey.</p>
         | 
| 70 | 
            -
                                </div>
         | 
| 71 | 
            -
                                
         | 
| 72 | 
            -
                                <div class="feature-card">
         | 
| 73 | 
            -
                                    <div class="feature-icon-wrapper">
         | 
| 74 | 
            -
                                        <img src="{{ url_for('static', filename='images/icon2.png') }}" alt="round abstract icon" class="feature-icon-img">
         | 
| 75 | 
            -
                                    </div>
         | 
| 76 | 
            -
                                    <h3>Personalized Recommendations</h3>
         | 
| 77 | 
            -
                                    <p>Get specific guidance tailored to your unique spiritual path, beliefs, and goals for meaningful growth.</p>
         | 
| 78 | 
            -
                                </div>
         | 
| 79 | 
            -
                                
         | 
| 80 | 
            -
                                <div class="feature-card">
         | 
| 81 | 
            -
                                    <div class="feature-icon-wrapper">
         | 
| 82 | 
            -
                                        <img src="{{ url_for('static', filename='images/icon1.png') }}" alt="star shaped icon" class="feature-icon-img">
         | 
| 83 | 
            -
                                    </div>
         | 
| 84 | 
            -
                                    <h3>Growth Opportunities</h3>
         | 
| 85 | 
            -
                                    <p>Identify areas for spiritual growth and receive practical steps to deepen your practice and understanding.</p>
         | 
| 86 | 
            -
                                </div>
         | 
| 87 | 
            -
                            </div>
         | 
| 88 | 
            -
                        </div>
         | 
| 89 | 
            -
                    </section>
         | 
| 90 | 
            -
             | 
| 91 | 
            -
                    <section class="cta-section">
         | 
| 92 | 
            -
                        <div class="cta-container">
         | 
| 93 | 
            -
                            <h2>Ready to begin your journey?</h2>
         | 
| 94 | 
            -
                            <p>Start your spiritual path assessment today</p>
         | 
| 95 | 
            -
                            <a href="/login" class="btn-primary">
         | 
| 96 | 
            -
                                Get Started Now
         | 
| 97 | 
            -
                                <span class="arrow">→</span>
         | 
| 98 | 
            -
                            </a>
         | 
| 99 | 
            -
                        </div>
         | 
| 100 | 
            -
                    </section>
         | 
| 101 | 
            -
                </main>
         | 
| 102 | 
            -
             | 
| 103 | 
            -
                <footer class="footer">
         | 
| 104 | 
            -
                    <div class="footer-container">
         | 
| 105 | 
            -
                        <p>© 2025 Spiritual Path Assessment. Empowering your spiritual journey.</p>
         | 
| 106 | 
            -
                    </div>
         | 
| 107 | 
            -
                </footer>
         | 
| 108 | 
            -
            </body>
         | 
| 109 | 
            -
            </html>
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  |