# Project export: Quizzly - AI-Powered Educational Quiz Generator

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: Cal Hacks 12.0
- Tagline: Transform any educational video into personalized quizzes with AI-powered difficulty adjustment, smart recommendations, and comprehensive learning analytics, using Reka Vision and Research API.
- Devpost: https://devpost.com/software/quizzly-ai-powered-educational-quiz-generator
- GitHub: https://github.com/chenyinuo8888/reka-quiz
- Video: https://www.youtube.com/embed/8cYjg9YI3Rg?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 3 GitHub contributor(s) — chenyinuo8888 (8 commits), chalkgt (4 commits), JoshuaSkiBear (4 commits)

## Devpost submission (written by the team)

### Inspiration

Picture this: You're watching an educational video about machine learning, taking notes furiously, but when the video ends, you realize you've absorbed almost nothing. Sound familiar? We've all been there - the endless scroll of educational content that promises to teach us everything, but leaves us with nothing but a sense of information overload and the nagging feeling that we're not actually learning. The problem hit us during our own study sessions. We'd watch hours of educational content, convinced we were learning, only to discover we couldn't recall the key concepts when it mattered most. Traditional video learning is passive, one-size-fits-all, and frankly, it's not working for most people. We wanted to change that. The breakthrough came when we realized that learning isn't just about consuming content - it's about active engagement, personalized feedback, and adaptive challenges that grow with you. What if we could transform any educational video into an intelligent, personalized learning experience that actually helps you retain and understand the material?

### What it does

Quizzly is more than just another quiz app - it's your personal AI learning companion that transforms any educational video into an intelligent, adaptive learning experience. Here's the magic: upload any educational video, and Quizzly uses advanced AI to analyze the content, understand the key concepts, and generate personalized quizzes that adapt to your learning style and pace. But here's where it gets interesting. Quizzly doesn't just throw random questions at you. It watches how you learn, understands your strengths and weaknesses, and automatically adjusts the difficulty to keep you challenged but not overwhelmed. Get a question wrong? Instead of just showing you the answer, Quizzly generates a personalized explanation that helps you understand not just what you got wrong, but why you got it wrong and how to think about it differently. The system learns from your performance patterns, suggesting related topics to explore, identifying skill gaps, and even recommending the perfect next video to watch based on your learning journey. It's like having a personal tutor who knows exactly how you learn and what you need to succeed.

### How we built it

We started with the Reka Vision API to analyze video content and extract meaningful educational concepts. This wasn't just about transcribing speech, we needed the AI to understand context, identify key learning objectives, and recognize the educational value of different segments. The real challenge came with the adaptive difficulty system. We spent hours analyzing learning patterns, studying how people progress through educational content, and building algorithms that could predict the optimal challenge level for each user. The system tracks your recent performance, identifies trends, and automatically adjusts question difficulty - if you're acing everything, it ramps up the challenge; if you're struggling, it provides more foundational questions to build your confidence. The personalized explanations feature was our secret sauce. When you get a question wrong, our AI doesn't just tell you the correct answer - it analyzes your specific mistake, considers the context of the video content, and generates a custom explanation that addresses your particular misunderstanding. It's like having a tutor who can see exactly where your thinking went wrong and guide you back to the right path. The smart recommendations engine was where we really pushed the boundaries. By analyzing your learning patterns, topic preferences, and performance trends, the system can suggest not just what to learn next, but how to learn it. It identifies your learning style, recommends related topics that build on your current knowledge, and even suggests when you might be ready to tackle more advanced concepts.

### Challenges we ran into

The biggest challenge was making the AI truly intelligent, not just smart. Early versions of Quizzly would generate questions, but they felt robotic and disconnected from the actual learning experience. We spent hours refining the prompts and algorithms to make the AI understand not just what was said in the video, but what the learner needed to understand. The personalized explanations feature was technically complex - we needed the AI to not just identify wrong answers, but understand the reasoning behind those wrong answers and provide targeted feedback. This required sophisticated natural language processing and a deep understanding of common learning misconceptions. Performance was another challenge. With all the AI processing, real-time analytics, and adaptive features, we had to carefully optimize every component to ensure a smooth user experience. The system needed to feel instant and responsive while doing incredibly complex work behind the scenes.

### Accomplishments we're proud of

We're incredibly proud of creating a system that truly understands how people learn. The adaptive difficulty feature works so well that users often don't even notice it's happening. They just feel like the content is perfectly matched to their level. The personalized explanations have received amazing feedback, with users saying they finally understand concepts they've been struggling with for years. The analytics dashboard is something we're particularly proud of. It doesn't just show numbers, it tells a story about the user's learning journey, highlighting progress, identifying patterns, and providing actionable insights that actually help people learn better. But what we're most proud of is the impact we're seeing. Users are reporting that they're retaining information better, learning faster, and actually enjoying the process of education again. We've created something that doesn't just test knowledge. It builds it.

### What we learned

Building Quizzly taught us that the future of education isn't about replacing human teachers. It's about augmenting human learning with intelligent technology that adapts to individual needs. We learned that effective learning isn't just about content delivery, but about creating the right conditions for understanding to emerge. We discovered that personalization in education isn't just about different difficulty levels - it's about understanding how each person thinks, learns, and processes information. The AI needed to be empathetic, not just intelligent. The technical challenges taught us the importance of user experience in AI applications. The most sophisticated AI in the world is useless if it doesn't feel natural and helpful to the user. We learned to prioritize the human experience over technical complexity.

### What's next

The learning revolution is just beginning. We're working on expanding Quizzly to support multiple languages, making it accessible to learners worldwide. We're developing mobile apps that bring the power of adaptive learning to your phone, so you can learn anywhere, anytime. We're exploring partnerships with educational institutions to integrate Quizzly into formal learning environments, creating a bridge between traditional education and AI-powered personalized learning. The goal is to make this technology available to every student, regardless of their background or resources. The future is collaborative. We're building features that allow learners to study together, share insights, and learn from each other's perspectives. Imagine a study group where the AI can facilitate discussions, suggest topics, and help everyone learn more effectively. We're making learning measurable. Advanced analytics will help learners understand not just what they know, but how they learn best. We're developing predictive models that can identify when someone is about to struggle with a concept and provide proactive support. The vision is clear: a world where every learner has access to personalized, adaptive, intelligent education that helps them reach their full potential. Quizzly is just the beginning of that journey.

## README (from the GitHub repository)

# Reka Quiz - Hackathon Project

A hackathon project based on the Reka AI "Roast My Life" template, adapted for quiz functionality using Reka's Vision API.

## 🎯 Project Overview

This project demonstrates how to use the **Reka Vision API** to create an interactive quiz application that can analyze videos and generate questions or commentary. Built on the foundation of the original "Roast My Life" template, this version is adapted for educational and quiz purposes.

## ✨ Features

- 🔍 Dynamic video list fetched from Reka Vision backend 
- 🤖 Reka Vision chat endpoint integration for quiz generation
- 🧪 Clean, documented Python code (type hints + docstrings)
- 🐳 Docker support for fast containerized runs
- 📱 Responsive UI with a lightweight custom palette
- 🎓 Quiz-focused functionality (adapted from roasting template)

## 🏗️ Project Structure

```
.
├── src/                  # Application source code
│   ├── app.py           # Main Flask application
│   ├── templates/       # HTML templates
│   │   ├── index.html  # Home page
│   │   └── form.html   # Video selection form page
│   └── static/         # Static files
│       ├── css/
│       │   └── style.css    # Stylesheets
│       └── images/     # Image assets
├── workshop/           # Workshop version with additional features
├── requirements.txt     # Python dependencies
├── Dockerfile          # Docker configuration
└── .env-sample         # Environment variables template
```

## 🚀 Quick Start

### Prerequisites

- Python 3.12 or higher
- pip (Python package manager)
- Reka AI API key ([Get free API key](https://link.reka.ai/free))

### Installation & Setup

1. **Clone this repository**
   ```bash
   git clone <your-repo-url>
   cd reka-quiz
   ```

2. **Create a virtual environment (recommended)**
   ```bash
   python3 -m venv venv
   source venv/bin/activate  # On Windows: venv\Scripts\activate
   ```

3. **Install dependencies**
   ```bash
   pip install -r requirements.txt
   ```

4. **Set up environment variables**
   ```bash
   cp .env-sample .env
   # Edit .env with your API key
   ```

5. **Run the application**
   ```bash
   python src/app.py
   ```

6. **Open your browser**
   Navigate to: `http://localhost:8111`

### Docker Setup

1. **Build the Docker image**
   ```bash
   docker build -t reka-quiz .
   ```

2. **Run with environment variables**
   ```bash
   docker run --env-file .env -p 8111:8111 reka-quiz
   ```

## 🔧 Environment Variables

Create a `.env` file using the `.env-sample` template:

```env
# Primary API key (get free key at https://link.reka.ai/free)
API_KEY=your_api_key_here

# Reka Vision API endpoint
BASE_URL=https://vision-agent.api.reka.ai
```

## 🎮 Usage

1. Open the app and navigate to the Quiz page
2. Select a video from the available list
3. Click "Generate Quiz" to create questions based on the video content
4. Enjoy your AI-generated quiz experience!

## 🛠️ Development

This project is based on the [Reka AI roast_my_life template](https://github.com/reka-ai/api-examples-python/tree/main/roast_my_life) and has been adapted for quiz functionality.

### Key Adaptations

- Modified prompts to generate quiz questions instead of roasts
- Updated UI to reflect quiz functionality
- Enhanced error handling for educational content
- Added quiz-specific features

## 📚 Resources

- [Reka Vision API Documentation](https://docs.reka.ai/vision)
- [Get Free API Key](https://link.reka.ai/free)
- [Original Template Repository](https://github.com/reka-ai/api-examples-python)

## 🤝 Contributing

This is a hackathon project. Feel free to fork, modify, and extend for your own quiz applications!

## 📄 License

Educational / sample use. Adapt freely.

---

**Built with ❤️ for the hackathon using Reka AI's powerful Vision API**


## Detected evidence (automated analysis)

Indexed codebase: 9 recognized source files, 263 KB.
- CSS (language) — detected in the code
- Flask (technology) — detected in the code
- HTML (language) — detected in the code
- Python (language) — detected in the code
- JavaScript (language) — claimed on Devpost, not found in the code

## Codebase structure (from repository index)

### Files (18 of 18)

```
.dockerignore
.env-sample
.gitignore
api/index.py
Dockerfile
README.md
render.yaml
requirements.txt
src/.env-sample
src/.gitignore
src/app.py
src/README.md
src/requirements.txt
src/static/css/style.css
src/templates/analytics.html
src/templates/form.html
src/templates/index.html
vercel.json
```

### Dependencies

- requirements.txt: Flask@==3.0.0, markdown@>=3.4.0, python-dotenv@==1.1.1, requests@==2.31.0, Werkzeug@==3.0.1
- src/requirements.txt: Flask@==3.0.0, markdown@>=3.4.0, python-dotenv@==1.1.1, requests@==2.31.0, Werkzeug@==3.0.1

### Recent commits (newest first)

- Fix vercel.json: Remove routes conflict, use only rewrites
- Add Vercel deployment configuration
- Prepare application for deployment: Add Render.com configuration
- Update: Link commits to chalkgt GitHub account
- style
- Fix quiz UI issues: consistent question choice placement and auto-generate new quiz
- Fix analytics dashboard data loading
- Remove redundant personalized feedback for presentation
- Complete Phase 6: Advanced AI Features 🤖
- Complete Phase 5: Analytics & Progress Tracking
- 🚀 Major UI/UX improvements and Quizzly rebranding
- UI improvements
- Delete button and quiz feature fixed
- Fix quiz generation: Focus on multiple choice questions and improve error handling
- fixed analysis
- Add .gitignore to ignore local environment files
- folder rename
- Phase 4: Advanced Features & Polish
- Phase 3: Implement Interactive Quiz Taking Experience
- Clean up UI and rebrand to Reka Quiz

## Key source files (fetched from GitHub, selected and truncated for size)

### requirements.txt

```
Flask==3.0.0
Werkzeug==3.0.1
python-dotenv==1.1.1
requests==2.31.0
markdown>=3.4.0
```

### Dockerfile

```
# Use Python 3.12 slim image as base
FROM python:3.12-slim

# Set working directory in the container
WORKDIR /app

# Recommended Python runtime flags
ENV PYTHONDONTWRITEBYTECODE=1 \
	PYTHONUNBUFFERED=1

# Copy requirements file
COPY requirements.txt .

# Install Python dependencies
RUN pip install --no-cache-dir -r requirements.txt

# Copy application files
COPY src/ src/

# Expose port 5000
EXPOSE 5000

# Optional build-time injection of environment variables (not recommended for secrets)
# Usage: docker build --build-arg API_KEY=... --build-arg BASE_URL=... -t roast-my-life .
ARG API_KEY
ARG BASE_URL

# Make them available at runtime (can be overridden by docker run -e / --env-file)
ENV API_KEY=${API_KEY} \
	BASE_URL=${BASE_URL}

# Set environment variables
ENV FLASK_APP=src/app.py
ENV FLASK_ENV=production

# Run the application
CMD ["python", "src/app.py"]

```

### src/requirements.txt

```
Flask==3.0.0
Werkzeug==3.0.1
python-dotenv==1.1.1
requests==2.31.0
markdown>=3.4.0
```

### api/index.py

```python
"""
Vercel serverless function entry point for Flask application.
This file wraps the Flask app to work with Vercel's serverless function format.
"""
import sys
import os

# Add the src directory to the Python path so we can import app
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'src'))

# Import the Flask app
from app import app

# Vercel's @vercel/python builder automatically detects Flask apps
# Just export the app and Vercel will handle the WSGI wrapping
__all__ = ['app']


```

### src/app.py

```python
import os
import time
from typing import Any, Dict, List

from dotenv import load_dotenv
from flask import Flask, render_template, request, jsonify
import requests

app = Flask(__name__)

load_dotenv()
api_key = os.environ.get('API_KEY')
base_url = os.environ.get('BASE_URL')

# Endpoint for the external chat/vision agent API. If needed this can be
# overridden via env; otherwise we default to using base_url + /qa/chat
REKA_VIDEO_QA_ENDPOINT = os.environ.get(
    'REKA_VIDEO_QA_ENDPOINT', 
    f"{base_url.rstrip('/')}/qa/chat"
)

# Simple in-memory cache for videos to avoid hitting the API on every request.
_VIDEO_CACHE: Dict[str, Any] = {
    "timestamp": 0.0,
    "ttl": 60.0,
    "results": []
}

# Track deleted video IDs to filter them out
_DELETED_VIDEOS: set[str] = {
    'b5f1c874-f168-40df-8d34-8f5d215fec90',  # Derivatives Organic Chemistry Tutor
    '3247ed0f-ffef-4815-91bc-ec2051d834b1',  # Definition of the Derivative
    '45f4099b-6ad5-4be7-a8ea-4c7ab3939d0b',  # Rick Astley video
}


def fetch_videos() -> List[Dict[str, Any]]:
    """
    Fetch the list of videos from Reka Vision API, with basic caching.

    The API is expected to respond with a JSON structure containing a
    "results" key that holds a list of video objects. Each video includes
    metadata with fields like "title" and "thumbnail".

    Returns:
        List[Dict[str, Any]]: List of video dictionaries from the API.
    """
    now = time.time()
    is_stale = (now - _VIDEO_CACHE["timestamp"]) > _VIDEO_CACHE["ttl"]

    if not base_url:
        # Without BASE_URL we can't call the API; return empty.
        return []

    url = f"{base_url.rstrip('/')}/videos/get"
    headers = {}
    if api_key:
        headers["X-Api-Key"] = api_key

    try:
        response = requests.post(url, headers=headers, timeout=10)
        response.raise_for_status()
        data = response.json()
        results = data.get("results", [])
        
        # Filter out deleted videos
        results = [video for video in results if video.get("video_id") not in _DELETED_VIDEOS]
        
        _VIDEO_CACHE.update({
            "timestamp": now,
            "results": results
        })
        return results
    except Exception as e:
        # On failure, keep old cache if available; otherwise empty list.
        if _VIDEO_CACHE["results"]:
            return _VIDEO_CACHE["results"]
        return []


def call_reka_vision_qa(video_id: str) -> Dict[str, Any]:
    """Call the Reka Video QA API for a given video.

    The request format follows the user's provided specification. We issue a
    POST request with the video_id and a static user prompt asking to gently
    roast the person in the video.

    Environment Variables:
        REKA_VIDEO_QA_ENDPOINT: Optional override for the API endpoint.
            If not set, defaults to {base_url}/qa/chat
        api_key or API_KEY: API key placed in the X-Api-Key header.

    Parameters:
        video_id (str): The UUID of the video to query.

    Returns:
        Dict[str, Any]: Parsed JSON response (may include keys like
        chat_response, system_message, error, status, etc.). On total failure
        returns a dict with an 'error' key.
    """
    headers = {}
    if api_key:
        headers['X-Api-Key'] = api_key

    payload = {
        "video_id": video_id,
        "messages": [
            {
                "role": "user",
                "content": "Write a funny and gently roast about the person, or the voice in this video. Reply in a markdown format."
            }
        ]
    }

    try:
        resp = requests.post(
            REKA_VIDEO_QA_ENDPOINT,
            headers=headers,
            json=payload,
            timeout=30
        )
        # Even on non-2xx we attempt to parse JSON for richer error context.
        data: Dict[str, Any]
        try:
            data = resp.json()
        except Exception:
            data = {"error": f"Non-JSON response (status {resp.status_code})"}

        if not resp.ok and 'error' not in data:
            data['error'] = f"HTTP {resp.status_code} calling chat endpoint"
        return data
    except requests.Timeout:
        return {"error": "Request to chat API timed out"}
    except Exception as e:  # broad catch to avoid propagating unexpected errors
        return {"error": f"Chat API call failed: {e}"}


def simple_markdown_to_html(md: str) -> str:
    """
    Convert Markdown text to HTML using the Python-Markdown library.

    This function uses the 'markdown' package for robust Markdown parsing and HTML output.
    Any HTML in the source is safely handled by the library to mitigate injection risks.

    Parameters:
        md (str): Markdown input string.

    Returns:
        str: HTML output.
    """
    if not md:
        return ""
    import markdown
    # Use 'extra' and 'sane_lists' extensions for better Markdown support
    return markdown.markdown(md, extensions=['extra', 'sane_lists'])


def analyze_video_content(video_id: str) -> Dict[str, Any]:
    """
    Analyze video for educational content, topics, and key concepts.
    
    This function uses Reka Vision API to analyze educational videos and extract:
    - Main subject/topic
    - Key concepts and strategies
    - Difficulty level
    - Learning objectives
    - Important timestamps
    
    Parameters:
        video_id (str): The UUID of the video to analyze
        
    Returns:
        Dict[str, Any]: Structured analysis data with educational insights
    """
    headers = {}
    if api_key:
        headers['X-Api-Key'] = api_key

    analysis_prompt = """
    Analyze this educational video and provide a comprehensive educational analysis. 
    
    Please identify and return the following information in JSON format:
    
    1. **Subject Area**: What is the main academic subject? (e.g., Mathematics, Science, History, Language Arts, etc.)
    2. **Topic**: What specific topic is being taught? (e.g., "Quadratic Equations", "Photosynthesis", "World Wa
[truncated — 38999 more characters]
```

### render.yaml

```yaml
services:
  - type: web
    name: reka-quiz
    env: python
    buildCommand: cd src && pip install -r requirements.txt
    startCommand: cd src && python app.py
    envVars:
      - key: API_KEY
        sync: false
      - key: BASE_URL
        sync: false
      - key: REKA_VIDEO_QA_ENDPOINT
        sync: false
      - key: FLASK_DEBUG
        value: "False"
      - key: PORT
        fromService:
          type: web
          name: reka-quiz
          property: port


```

### src/templates/index.html

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Quizzly - AI-Powered Educational Quiz Generator</title>
    <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head>
<body>
    <header class="fancy-header">
        <div class="interactive-bg" id="interactiveBg"></div>
        <div class="header-content">
            <h1 class="fancy-title">🧠 Quizzly</h1>
            <p class="fancy-subtitle">Your AI-Powered Quiz Generator for Educational Videos</p>
            <div class="floating-elements">
                <div class="floating-icon">📚</div>
                <div class="floating-icon">🎯</div>
                <div class="floating-icon">💡</div>
                <div class="floating-icon">📊</div>
            </div>
        </div>
    </header>

    <nav>
        <ul>
            <li><a href="/" class="active">Home</a></li>
            <li><a href="/form">Create Quiz</a></li>
            <li><a href="/analytics">Analytics</a></li>
        </ul>
    </nav>

    <div class="container">
        <div class="welcome-section">
            <h2>Welcome to Quizzly 🎓</h2>
            <p>
                Transform any educational video into an interactive quiz using the power of <strong>Reka Vision API</strong>. 
                Our AI analyzes video content to extract key concepts, topics, and learning objectives, then generates 
                comprehensive quiz questions tailored to the educational content.
            </p>
            <p>
                Perfect for educators, students, and anyone looking to create engaging educational assessments from video content.
            </p>
            
            <h3 style="color: #203F72; margin-top: 2rem; margin-bottom: 1rem;">Features</h3>
            <ul class="feature-list">
                <li>📚 <strong>Video Analysis</strong> - Extract educational topics and key concepts</li>
                <li>🎯 <strong>Smart Quiz Generation</strong> - Create multiple choice, short answer, and problem-solving questions</li>
                <li>📊 <strong>Difficulty Assessment</strong> - Automatically determine content difficulty level</li>
                <li>⏰ <strong>Key Moments</strong> - Identify important timestamps and learning objectives</li>
                <li>💡 <strong>Detailed Explanations</strong> - Every question includes comprehensive explanations</li>
                <li>🎨 <strong>Modern Interface</strong> - Clean, responsive design for optimal user experience</li>
            </ul>

            <h3 style="color: #203F72; margin-top: 2rem; margin-bottom: 1rem;">How It Works</h3>
            <div class="workflow-steps">
                <div class="step">
                    <div class="step-number">1</div>
                    <div class="step-content">
                        <h4>Upload Video</h4>
                        <p>Upload or provide a URL to an educational video</p>
                    </div>
                </div>
                <div class="step">
                    <div class="step-number">2</div>
                    <div class="step-content">
                        <h4>AI Analysis</h4>
                        <p>Our AI analyzes the video to extract topics, concepts, and learning objectives</p>
                    </div>
                </div>
                <div class="step">
                    <div class="step-number">3</div>
                    <div class="step-content">
                        <h4>Generate Quiz</h4>
                        <p>Create comprehensive quiz questions based on the video content</p>
                    </div>
                </div>
            </div>

            <h3 style="color: #203F72; margin-top: 2rem; margin-bottom: 1rem;">Get Started</h3>
            <p>
                Ready to create your first AI-generated quiz? Head over to <strong>Create Quiz</strong>, 
                upload an educational video, and watch the magic happen!
            </p>
            <div class="cta-section">
                <a href="/form" class="cta-button">🚀 Start Creating Quizzes</a>
            </div>
        </div>
    </div>

    <style>
        /* Fancy Header Styles */
        .fancy-header {
            position: relative;
            background: linear-gradient(135deg, #0F1D34 0%, #203F72 50%, #2276FF 100%);
            color: #F1EEE7;
            padding: 4rem 0;
            overflow: hidden;
            min-height: 300px;
            display: flex;
            align-items: center;
            justify-content: center;
        }

        .interactive-bg {
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: radial-gradient(circle at 50% 50%, rgba(255, 255, 255, 0.1) 0%, transparent 50%);
            transition: all 0.3s ease;
            pointer-events: none;
        }

        .fancy-title {
            font-size: 3.5rem;
            font-weight: 700;
            margin-bottom: 1rem;
            text-align: center;
            background: linear-gradient(45deg, #ffffff, #E9F2F6, #ffffff);
            background-size: 200% 200%;
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            background-clip: text;
            animation: gradientShift 3s ease-in-out infinite;
            text-shadow: 0 0 30px rgba(255, 255, 255, 0.3);
        }

        .fancy-subtitle {
            font-size: 1.3rem;
            text-align: center;
            margin-bottom: 2rem;
            opacity: 0.9;
            font-weight: 300;
        }

        .floating-elements {
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            pointer-events: none;
        }

        .floating-icon {
            position: absolute;
            font-size: 2rem;
            opacity: 0.3;
           
[truncated — 5423 more characters]
```

### src/static/css/style.css

```css
/* 
 * Color Palette:
 * #F1EEE7 - Light cream
 * #D5D0C1 - Beige
 * #2276FF - Bright blue
 * #2E2F2F - Dark gray
 * #FF93ED - Pink
 * #E9F2F6 - Light blue
 * #D6E9F1 - Sky blue
 * #B6D6E3 - Medium blue
 * #203F72 - Navy blue
 * #0F1D34 - Dark navy
 * #403E34 - Brown gray
 */

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    background: linear-gradient(135deg, #F1EEE7 0%, #E9F2F6 100%);
    color: #2E2F2F;
    line-height: 1.6;
    transition: all 0.3s ease;
}

/* Header Styles */
header {
    background: linear-gradient(135deg, #0F1D34 0%, #203F72 50%, #2276FF 100%);
    color: #F1EEE7;
    padding: 3rem 0;
    box-shadow: 0 8px 16px rgba(0, 0, 0, 0.15);
}

.header-content {
    max-width: 1200px;
    margin: 0 auto;
    padding: 0 2rem;
}

header h1 {
    font-size: 2.5rem;
    margin-bottom: 0.5rem;
}

/* Navigation Styles */
nav {
    background-color: #203F72;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

nav ul {
    list-style: none;
    display: flex;
    max-width: 1200px;
    margin: 0 auto;
    padding: 0 2rem;
}

nav ul li {
    margin: 0;
}

nav ul li a {
    display: block;
    color: #F1EEE7;
    text-decoration: none;
    padding: 1rem 1.5rem;
    transition: background-color 0.3s ease;
}

nav ul li a:hover {
    background-color: #2276FF;
}

nav ul li a.active {
    background-color: #2276FF;
    font-weight: bold;
}

/* Container Styles */
.container {
    max-width: 1200px;
    margin: 2rem auto;
    padding: 0 2rem;
}

/* Welcome Section */
.welcome-section {
    background-color: #E9F2F6;
    border-radius: 12px;
    padding: 3rem;
    margin: 2rem 0;
    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}

.welcome-section h2 {
    color: #203F72;
    font-size: 2rem;
    margin-bottom: 1rem;
}

.welcome-section p {
    font-size: 1.1rem;
    margin-bottom: 1rem;
    color: #403E34;
}

.feature-list {
    list-style: none;
    margin-top: 2rem;
}

.feature-list li {
    padding: 0.8rem 0;
    padding-left: 2rem;
    position: relative;
}

.feature-list li:before {
    content: "✓";
    position: absolute;
    left: 0;
    color: #2276FF;
    font-weight: bold;
    font-size: 1.2rem;
}

/* Form Section */
.form-section {
    background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
    border-radius: 16px;
    padding: 2.5rem;
    margin: 2rem 0;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);
    border: 1px solid rgba(34, 118, 255, 0.1);
}

.form-section h2 {
    color: #203F72;
    font-size: 1.8rem;
    margin-bottom: 1.5rem;
}

/* Image Grid */
.image-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
    gap: 1.5rem;
    margin-bottom: 2rem;
}

.image-card {
    background: linear-gradient(135deg, #ffffff 0%, #E9F2F6 100%);
    border-radius: 12px;
    padding: 1rem;
    cursor: pointer;
    transition: all 0.4s ease;
    border: 3px solid transparent;
    position: relative;
    overflow: hidden;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}

.image-card::before {
    content: '';
    position: absolute;
    top: 0;
    left: -100%;
    width: 100%;
    height: 100%;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.5), transparent);
    transition: left 0.5s;
}

.image-card:hover::before {
    left: 100%;
}

.image-card:hover {
    transform: translateY(-8px) scale(1.02);
    box-shadow: 0 12px 24px rgba(34, 118, 255, 0.2);
    border-color: #2276FF;
}

.image-card.selected {
    border-color: #2276FF;
    background-color: #D6E9F1;
}

.image-card img {
    width: 100%;
    height: 180px;
    object-fit: cover;
    border-radius: 6px;
    background-color: #D5D0C1;
}

.image-card h3 {
    margin-top: 0.8rem;
    color: #203F72;
    font-size: 1.1rem;
    text-align: center;
}

/* Button Styles */
.button-container {
    text-align: center;
    margin: 2rem 0;
}

.btn {
    background: linear-gradient(135deg, #2276FF 0%, #203F72 100%);
    color: #F1EEE7;
    padding: 1rem 3rem;
    border: none;
    border-radius: 12px;
    font-size: 1.1rem;
    cursor: pointer;
    transition: all 0.3s ease;
    box-shadow: 0 4px 12px rgba(34, 118, 255, 0.3);
    position: relative;
    overflow: hidden;
}

.btn::before {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    width: 0;
    height: 0;
    background: rgba(255, 255, 255, 0.2);
    border-radius: 50%;
    transform: translate(-50%, -50%);
    transition: width 0.6s, height 0.6s;
}

.btn:hover::before {
    width: 300px;
    height: 300px;
}

.btn:hover {
    transform: translateY(-3px);
    box-shadow: 0 8px 20px rgba(34, 118, 255, 0.4);
}

.btn:disabled {
    background: #D5D0C1;
    cursor: not-allowed;
    transform: none;
}

/* Result Section */
.result-section {
    background-color: #D6E9F1;
    border-radius: 8px;
    padding: 2rem;
    margin-top: 2rem;
    display: none;
}

.result-section.show {
    display: block;
}

.result-section h3 {
    color: #203F72;
    margin-bottom: 1rem;
}

.result-content {
    background-color: #fff;
    padding: 1.5rem;
    border-radius: 6px;
    color: #2E2F2F;
    max-height: 500px;
    overflow-y: auto;
    line-height: 1.8;
    word-wrap: break-word;
    overflow-wrap: break-word;
}

.result-content p {
    margin-bottom: 1rem;
}

.result-content p:last-child {
    margin-bottom: 0;
}

.result-content ul, .result-content ol {
    margin-left: 1.5rem;
    margin-bottom: 1rem;
}

.result-content li {
    margin-bottom: 0.5rem;
}

.result-content h1, .result-content h2, .result-content h3 {
    margin-top: 1.5rem;
    margin-bottom: 0.75rem;
    color: #203F72;
}

.result-content h1:first-child,
.result-content h2:first-child,
.result-content h3:first-child {
    margin-top: 0;
}

.result-content code {
    background-color: #F1EEE7;
    padding: 0.2rem 0.4rem;
    border-radius: 3px;
    font-family: 'Courier New', monospace;
}

.result-content pre {
    background-color: #F1EEE7;
    paddin
[truncated — 1556 more characters]
```