#!/usr/bin/env python3
"""
Web flashcard generator for Soroban abacus cards.
Generates static HTML with inline SVG abacus representations using existing Typst->SVG pipeline.
"""

import tempfile
import json
import subprocess
import os
import sys
from pathlib import Path

# Import PDF generation functionality
try:
    from generate import generate_typst_file
except ImportError:
    # If running as a standalone script, try relative import
    import sys
    sys.path.append(str(Path(__file__).parent))
    from generate import generate_typst_file


def get_colored_numeral_html(number, config):
    """Generate HTML for numeral with appropriate coloring based on configuration."""
    color_scheme = config.get('color_scheme', 'monochrome')
    
    # For web display, automatically use colored numerals for non-monochrome schemes
    use_colored = config.get('colored_numerals', False) or color_scheme != 'monochrome'
    
    if not use_colored or color_scheme == 'monochrome':
        return str(number)
    
    # Color palettes - all are colorblind-friendly and tested with deuteranopia/protanopia/tritanopia
    color_palettes = {
        # Default palette (current colors - moderately colorblind friendly)
        'default': {
            'colors': [
                "#2E86AB",  # ones - blue
                "#A23B72",  # tens - magenta  
                "#F18F01",  # hundreds - orange
                "#6A994E",  # thousands - green
                "#BC4B51",  # ten-thousands - red
            ],
            'name': 'Default Colors'
        },
        
        # High contrast colorblind-safe palette
        'colorblind': {
            'colors': [
                "#0173B2",  # ones - strong blue
                "#DE8F05",  # tens - orange  
                "#CC78BC",  # hundreds - pink
                "#029E73",  # thousands - teal green
                "#D55E00",  # ten-thousands - vermillion
            ],
            'name': 'Colorblind Safe'
        },
        
        # Mnemonic palette using color associations for place values
        'mnemonic': {
            'colors': [
                "#1f77b4",  # ones - BLUE (Blue = Basic/Beginning = ones)
                "#ff7f0e",  # tens - ORANGE (Orange = Ten commandments = tens) 
                "#2ca02c",  # hundreds - GREEN (Green = Grass/Ground = hundreds)
                "#d62728",  # thousands - RED (Red = Thousand suns/fire = thousands)
                "#9467bd",  # ten-thousands - PURPLE (Purple = Prestigious/Premium = ten-thousands)
            ],
            'name': 'Memory Aid Colors'
        },
        
        # High contrast monochromatic palette (different shades)
        'grayscale': {
            'colors': [
                "#000000",  # ones - black
                "#404040",  # tens - dark gray
                "#808080",  # hundreds - medium gray  
                "#b0b0b0",  # thousands - light gray
                "#d0d0d0",  # ten-thousands - very light gray
            ],
            'name': 'Grayscale Shades'
        },
        
        # Nature-inspired colorblind safe palette
        'nature': {
            'colors': [
                "#4E79A7",  # ones - sky blue
                "#F28E2C",  # tens - sunset orange
                "#E15759",  # hundreds - coral red
                "#76B7B2",  # thousands - seafoam green
                "#59A14F",  # ten-thousands - forest green
            ],
            'name': 'Nature Colors'
        }
    }
    
    # Get the selected palette (default to 'default' palette)
    palette_name = config.get('color_palette', 'default')
    selected_palette = color_palettes.get(palette_name, color_palettes['default'])
    place_value_colors = selected_palette['colors']
    
    if color_scheme == 'place-value':
        # Color each digit by its place value (right-to-left: rightmost is ones)
        digits = str(number)
        colored_spans = []
        
        for i, digit in enumerate(digits):
            place_idx = len(digits) - 1 - i  # rightmost digit is place 0 (ones)
            color_idx = place_idx % len(place_value_colors)
            color = place_value_colors[color_idx]
            colored_spans.append(f'<span style="color: {color};">{digit}</span>')
        
        return ''.join(colored_spans)
    elif color_scheme == 'heaven-earth':
        # Use orange (heaven bead color)
        return f'<span style="color: #F18F01;">{number}</span>'
    elif color_scheme == 'alternating':
        # For alternating, use blue for simplicity in web display
        return f'<span style="color: #1E88E5;">{number}</span>'
    else:
        return str(number)


def get_numeral_color(number, config):
    """Get single color for numeral (kept for backwards compatibility with tests).""" 
    color_scheme = config.get('color_scheme', 'monochrome')
    
    # For web display, automatically use colored numerals for non-monochrome schemes
    use_colored = config.get('colored_numerals', False) or color_scheme != 'monochrome'
    
    if not use_colored or color_scheme == 'monochrome':
        return "#333"
    
    # Get color palette (reuse same palette logic)
    color_palettes = {
        'default': ['#2E86AB', '#A23B72', '#F18F01', '#6A994E', '#BC4B51'],
        'colorblind': ['#0173B2', '#DE8F05', '#CC78BC', '#029E73', '#D55E00'],
        'mnemonic': ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd'],
        'grayscale': ['#000000', '#404040', '#808080', '#b0b0b0', '#d0d0d0'],
        'nature': ['#4E79A7', '#F28E2C', '#E15759', '#76B7B2', '#59A14F']
    }
    
    palette_name = config.get('color_palette', 'default')
    place_value_colors = color_palettes.get(palette_name, color_palettes['default'])
    
    if color_scheme == 'place-value':
        # For single color (used by tests), return highest place value color
        digits = str(number)
        place_idx = len(digits) - 1  # Most significant digit place
        color_idx = place_idx % len(place_value_colors)
        return place_value_colors[color_idx]
    elif color_scheme == 'heaven-earth':
        # Use orange (heaven bead color)
        return "#F18F01"
    elif color_scheme == 'alternating':
        # For alternating, use blue for simplicity in web display
        return "#1E88E5"
    else:
        return "#333"


def generate_card_svgs(numbers, config):
    """Generate SVG content for each flashcard using existing Typst pipeline."""
    try:
        from .generate import generate_cards_direct
    except ImportError:
        # Fallback for when running tests directly
        from generate import generate_cards_direct
    
    # Create temporary directory for SVG generation
    with tempfile.TemporaryDirectory() as tmpdir:
        tmpdir_path = Path(tmpdir)
        svg_dir = tmpdir_path / 'svg_cards'
        
        # Configure for web-optimized SVGs
        web_config = {
            **config,
            'card_width': '1.5in',  # Much smaller card = larger abacus relative to viewBox
            'card_height': '1.5in',
            'transparent': True,  # Transparent background for web
            'scale_factor': 1.0   # Full size for web (was 0.8 - too small)
        }
        
        # Generate SVG files using existing pipeline
        generated_files = generate_cards_direct(
            numbers, web_config, svg_dir,
            format='svg', separate_fronts_backs=True
        )
        
        # Read SVG contents
        card_data = {}
        fronts_dir = svg_dir / 'fronts'
        
        for i, number in enumerate(numbers):
            front_file = fronts_dir / f'card_{i:03d}.svg'
            if front_file.exists():
                with open(front_file, 'r') as f:
                    svg_content = f.read()
                    # Remove XML declaration and DOCTYPE if present
                    if svg_content.startswith('<?xml'):
                        svg_content = svg_content.split('>', 1)[1]
                    card_data[number] = svg_content.strip()
            else:
                # Fallback if SVG generation failed
                card_data[number] = f'<svg width="300" height="200"><text x="150" y="100" text-anchor="middle" font-size="48">{number}</text></svg>'
        
        return card_data


def generate_companion_pdf(numbers, config, output_path):
    """Generate a PDF version alongside the web flashcards for print functionality."""
    
    # Ensure output_path is a Path object
    output_path = Path(output_path)
    
    # Use PDF-optimized config
    pdf_config = config.copy()
    pdf_config.update({
        'cards_per_page': 6,  # Standard 6 cards per page for printing
        'show_cut_marks': True,  # Always show cut marks for printing
        'show_registration': True,  # Always show registration marks
        'paper_size': 'us-letter',  # Standard paper size
        'orientation': 'portrait',  # Standard orientation
        'margins': {'top': '0.5in', 'bottom': '0.5in', 'left': '0.5in', 'right': '0.5in'},
        'gutter': '5mm'
    })
    
    # Generate Typst file
    project_root = Path(__file__).parent.parent
    temp_typst = project_root / 'temp_web_companion.typ'
    generate_typst_file(numbers, pdf_config, temp_typst)
    
    # Set up font path
    font_args = []
    if os.path.exists(str(project_root / 'fonts')):
        font_args = ['--font-path', str(project_root / 'fonts')]
    
    # Compile with Typst - use absolute paths to ensure correct location
    result = subprocess.run(
        ['typst', 'compile'] + font_args + [str(temp_typst), str(output_path.resolve())],
        capture_output=True,
        text=True,
        cwd=str(project_root)
    )
    
    if result.returncode != 0:
        raise RuntimeError(f"Typst compilation failed: {result.stderr}")
    
    # Clean up temp file
    temp_typst.unlink(missing_ok=True)
    
    # Linearize PDF for web delivery
    try:
        linearized_path = output_path.with_name(f"{output_path.stem}_linearized.pdf")
        result = subprocess.run(
            ['qpdf', '--linearize', str(output_path), str(linearized_path)],
            capture_output=True,
            text=True
        )
        if result.returncode == 0:
            linearized_path.replace(output_path)  # Replace original with linearized
    except FileNotFoundError:
        pass  # qpdf not available, skip linearization


def generate_tutorial_svgs(config):
    """Generate SVG content for tutorial examples."""
    tutorial_numbers = [0, 1, 3, 5, 7, 9, 23, 67, 158, 456]  # Key examples for tutorial
    tutorial_svgs = generate_card_svgs(tutorial_numbers, config)
    return tutorial_svgs

def generate_arithmetic_svgs(config):
    """Generate SVG content for arithmetic examples."""
    arithmetic_numbers = [23, 27, 37, 47, 55, 75, 89, 85, 92, 84, 21]  # Arithmetic step examples
    arithmetic_svgs = generate_card_svgs(arithmetic_numbers, config)
    return arithmetic_svgs

def generate_web_flashcards(numbers, config, output_path):
    """Generate HTML file with flashcard layout."""
    
    # Generate SVG content for all cards
    print(f"Generating SVG content for {len(numbers)} cards...")
    card_svgs = generate_card_svgs(numbers, config)
    
    # Generate tutorial SVGs
    print("Generating tutorial examples...")
    tutorial_svgs = generate_tutorial_svgs(config)
    
    # Generate arithmetic SVGs
    print("Generating arithmetic examples...")
    arithmetic_svgs = generate_arithmetic_svgs(config)
    
    # Generate individual cards HTML
    cards_html = []
    for i, number in enumerate(numbers):
        svg_content = card_svgs.get(number, f'<svg width="300" height="200"><text x="150" y="100" text-anchor="middle" font-size="48">Error</text></svg>')
        colored_numeral = get_colored_numeral_html(number, config)
        
        card_html = f'''
        <div class="flashcard" data-number="{number}">
            <div class="card-number">#{i+1}</div>
            <div class="abacus-container">
                {svg_content}
            </div>
            <div class="numeral">{colored_numeral}</div>
        </div>'''
        
        cards_html.append(card_html)
    
    # Configuration descriptions
    color_schemes = {
        'monochrome': 'All beads are the same color',
        'place-value': 'Each place value (ones, tens, hundreds) has a different color',
        'heaven-earth': 'Heaven beads (5-value) and earth beads (1-value) have different colors',
        'alternating': 'Columns alternate between two colors'
    }
    
    color_scheme_description = color_schemes.get(
        config.get('color_scheme', 'monochrome'),
        'Monochrome color scheme'
    )
    
    # Format font size for CSS
    font_size = config.get('font_size', '48pt')
    if not font_size.endswith(('px', 'pt', 'em', 'rem', '%')):
        font_size = font_size + 'px'  # Add px if no unit specified
    
    # HTML template
    html_template = '''<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Soroban Flashcards</title>
    <style>
        /* CSS @property declarations for smooth gradient transitions */
        @property --sky-gradient {{
            syntax: '<image>';
            inherits: false;
            initial-value: linear-gradient(135deg, #ffb347 0%, #ffcc5c 50%, #87ceeb 100%);
        }}
        
        /* Time-of-day gradient definitions */
        :root {{
            --dawn-gradient: linear-gradient(135deg, #ffb347 0%, #ffcc5c 30%, #87ceeb 70%, #98d8e8 100%);
            --morning-gradient: linear-gradient(135deg, #87ceeb 0%, #98d8e8 30%, #b6e2ff 70%, #cce7ff 100%);
            --midday-gradient: linear-gradient(135deg, #87ceeb 0%, #a8d8ea 30%, #c7e2f7 70%, #e3f2fd 100%);
            --afternoon-gradient: linear-gradient(135deg, #ffecd2 0%, #fcb69f 30%, #ff8a65 70%, #ff7043 100%);
            --dusk-gradient: linear-gradient(135deg, #ff8a65 0%, #ff7043 30%, #8e44ad 70%, #5b2c87 100%);
            --night-gradient: linear-gradient(135deg, #2c3e50 0%, #34495e 30%, #1a252f 70%, #0f1419 100%);
        }}

        body {{
            font-family: {font_family}, sans-serif;
            margin: 0;
            padding: 0;
            background: #f8fafc;
            line-height: 1.6;
            color: #2d3748;
        }}
        
        .container {{
            max-width: 1400px;
            margin: 0 auto;
            padding: 0;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
        }}
        
        /* Beautiful Header */
        .main-header {{
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            text-align: center;
            padding: 60px 40px 40px;
            position: relative;
            overflow: hidden;
        }}
        
        .main-header::before {{
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="grain" width="100" height="100" patternUnits="userSpaceOnUse"><circle cx="25" cy="25" r="1" fill="white" opacity="0.1"/><circle cx="75" cy="75" r="1" fill="white" opacity="0.1"/><circle cx="50" cy="10" r="0.5" fill="white" opacity="0.15"/></pattern></defs><rect width="100" height="100" fill="url(%23grain)"/></svg>');
            pointer-events: none;
        }}
        
        .main-header h1 {{
            font-size: 3.5rem;
            font-weight: 700;
            margin: 0 0 15px 0;
            text-shadow: 0 4px 20px rgba(0,0,0,0.3);
            letter-spacing: -0.02em;
            position: relative;
            z-index: 1;
        }}
        
        .main-header p {{
            font-size: 1.3rem;
            margin: 0;
            opacity: 0.95;
            font-weight: 300;
            max-width: 600px;
            margin: 0 auto;
            line-height: 1.6;
            position: relative;
            z-index: 1;
        }}
        
        /* Modern Navigation */
        .page-nav {{
            position: sticky;
            top: 0;
            background: rgba(255, 255, 255, 0.95);
            backdrop-filter: blur(10px);
            border-bottom: 1px solid rgba(102, 126, 234, 0.2);
            z-index: 1000;
            padding: 20px 40px;
            box-shadow: 0 8px 32px rgba(0,0,0,0.1);
        }}
        
        .nav-buttons {{
            display: flex;
            gap: 8px;
            justify-content: center;
            max-width: 800px;
            margin: 0 auto;
            flex-wrap: wrap;
        }}
        
        .nav-btn {{
            padding: 12px 24px;
            border: none;
            background: rgba(102, 126, 234, 0.1);
            color: #4a5568;
            border-radius: 50px;
            cursor: pointer;
            font-size: 15px;
            font-weight: 600;
            transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
            text-decoration: none;
            position: relative;
            overflow: hidden;
            min-width: 140px;
            text-align: center;
        }}
        
        .nav-btn::before {{
            content: '';
            position: absolute;
            top: 0;
            left: -100%;
            width: 100%;
            height: 100%;
            background: linear-gradient(90deg, transparent, rgba(255,255,255,0.4), transparent);
            transition: left 0.6s;
        }}
        
        .nav-btn:hover {{
            background: rgba(102, 126, 234, 0.15);
            transform: translateY(-2px);
            box-shadow: 0 8px 25px rgba(102, 126, 234, 0.2);
        }}
        
        .nav-btn:hover::before {{
            left: 100%;
        }}
        
        .nav-btn.active {{
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            box-shadow: 0 8px 25px rgba(102, 126, 234, 0.4);
        }}
        
        .nav-btn.active:hover {{
            transform: translateY(-2px);
            box-shadow: 0 12px 35px rgba(102, 126, 234, 0.5);
        }}
        
        /* Content Area */
        .content-area {{
            background: white;
            margin: 0;
            padding: 0;
            min-height: calc(100vh - 200px);
        }}
        
        /* Section Styles */
        .page-section {{
            display: none;
            animation: fadeInUp 0.6s cubic-bezier(0.4, 0, 0.2, 1);
            padding: 60px 40px 80px;
            max-width: 1200px;
            margin: 0 auto;
        }}
        
        .page-section.active {{
            display: block;
        }}
        
        @keyframes fadeInUp {{
            from {{ 
                opacity: 0; 
                transform: translateY(30px);
            }}
            to {{ 
                opacity: 1; 
                transform: translateY(0);
            }}
        }}
        
        .section-header {{
            text-align: center;
            margin-bottom: 60px;
            position: relative;
        }}
        
        .section-title {{
            font-size: 2.8rem;
            font-weight: 700;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            background-clip: text;
            margin: 0 0 15px 0;
            letter-spacing: -0.02em;
        }}
        
        .section-subtitle {{
            color: #718096;
            font-size: 1.2rem;
            margin: 0;
            font-weight: 400;
            max-width: 600px;
            margin: 0 auto;
            line-height: 1.6;
        }}
        
        /* Welcome Section Styles */
        .welcome-hero {{
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            margin: -60px -40px 0;
            padding: 80px 40px 60px;
            text-align: center;
            position: relative;
            overflow: hidden;
        }}
        
        .welcome-hero::before {{
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><circle cx="20" cy="20" r="2" fill="white" opacity="0.1"/><circle cx="80" cy="30" r="1.5" fill="white" opacity="0.1"/><circle cx="60" cy="70" r="1" fill="white" opacity="0.15"/><circle cx="30" cy="80" r="2.5" fill="white" opacity="0.08"/><circle cx="90" cy="80" r="1" fill="white" opacity="0.1"/></svg>');
            animation: float 20s ease-in-out infinite;
        }}
        
        @keyframes float {{
            0%, 100% {{ transform: translateY(0px); }}
            50% {{ transform: translateY(-10px); }}
        }}
        
        .welcome-content {{
            position: relative;
            z-index: 1;
            max-width: 1200px;
            margin: 0 auto;
        }}
        
        .welcome-title {{
            font-size: 3.5rem;
            font-weight: 800;
            margin-bottom: 20px;
            text-shadow: 2px 2px 4px rgba(0,0,0,0.1);
        }}
        
        .welcome-subtitle {{
            font-size: 1.4rem;
            margin-bottom: 60px;
            opacity: 0.95;
            font-weight: 300;
            line-height: 1.6;
        }}
        
        .feature-grid {{
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
            gap: 30px;
            margin: 60px 0;
            padding: 0 20px;
        }}
        
        .feature-card {{
            background: rgba(255, 255, 255, 0.95);
            backdrop-filter: blur(10px);
            border-radius: 20px;
            padding: 40px 30px;
            text-align: center;
            color: #333;
            box-shadow: 0 20px 40px rgba(0,0,0,0.1);
            transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
            border: 1px solid rgba(255, 255, 255, 0.2);
        }}
        
        .feature-card:hover {{
            transform: translateY(-10px);
            box-shadow: 0 30px 60px rgba(0,0,0,0.15);
        }}
        
        .feature-icon {{
            font-size: 3rem;
            margin-bottom: 20px;
            display: block;
        }}
        
        .feature-card h3 {{
            font-size: 1.5rem;
            font-weight: 600;
            margin-bottom: 15px;
            color: #333;
        }}
        
        .feature-card p {{
            color: #666;
            line-height: 1.6;
            margin-bottom: 25px;
        }}
        
        .feature-btn {{
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            border: none;
            padding: 12px 24px;
            border-radius: 25px;
            font-weight: 600;
            cursor: pointer;
            transition: all 0.3s ease;
            font-size: 1rem;
        }}
        
        .feature-btn:hover {{
            transform: translateY(-2px);
            box-shadow: 0 8px 20px rgba(102, 126, 234, 0.3);
        }}
        
        .quick-start {{
            background: rgba(255, 255, 255, 0.1);
            border-radius: 20px;
            padding: 50px 40px;
            margin: 60px 20px 40px;
            backdrop-filter: blur(10px);
            border: 1px solid rgba(255, 255, 255, 0.2);
        }}
        
        .quick-start h2 {{
            font-size: 2.2rem;
            font-weight: 700;
            margin-bottom: 40px;
            text-align: center;
        }}
        
        .steps {{
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
            gap: 30px;
        }}
        
        .step {{
            display: flex;
            align-items: flex-start;
            gap: 20px;
        }}
        
        .step-number {{
            background: rgba(255, 255, 255, 0.2);
            width: 50px;
            height: 50px;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            font-weight: 700;
            font-size: 1.3rem;
            flex-shrink: 0;
            border: 2px solid rgba(255, 255, 255, 0.3);
        }}
        
        .step-content h4 {{
            font-size: 1.3rem;
            font-weight: 600;
            margin-bottom: 10px;
        }}
        
        .step-content p {{
            opacity: 0.9;
            line-height: 1.6;
        }}
        
        .stats-preview {{
            background: rgba(255, 255, 255, 0.1);
            border-radius: 20px;
            padding: 40px;
            margin: 40px 20px 0;
            backdrop-filter: blur(10px);
            border: 1px solid rgba(255, 255, 255, 0.2);
            text-align: center;
        }}
        
        .stats-preview h3 {{
            font-size: 2rem;
            font-weight: 700;
            margin-bottom: 30px;
        }}
        
        .stats-grid {{
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
            gap: 30px;
        }}
        
        .stat-item {{
            text-align: center;
        }}
        
        .stat-number {{
            font-size: 3rem;
            font-weight: 800;
            margin-bottom: 10px;
            background: rgba(255, 255, 255, 0.2);
            border-radius: 15px;
            padding: 20px;
            display: inline-block;
            min-width: 80px;
        }}
        
        .stat-label {{
            font-size: 1.1rem;
            opacity: 0.9;
            font-weight: 500;
        }}
        
        /* Responsive adjustments */
        @media (max-width: 768px) {{
            .welcome-title {{
                font-size: 2.5rem;
            }}
            
            .welcome-subtitle {{
                font-size: 1.2rem;
            }}
            
            .feature-grid {{
                grid-template-columns: 1fr;
                gap: 20px;
                padding: 0 10px;
            }}
            
            .quick-start {{
                margin: 40px 10px 20px;
                padding: 30px 20px;
            }}
            
            .steps {{
                grid-template-columns: 1fr;
                gap: 20px;
            }}
            
            .stats-grid {{
                grid-template-columns: repeat(2, 1fr);
                gap: 20px;
            }}
        }}
        
        .section-header::after {{
            content: '';
            display: block;
            width: 60px;
            height: 4px;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            margin: 30px auto 0;
            border-radius: 2px;
        }}
        
        .header {{
            text-align: center;
            margin-bottom: 30px;
        }}
        
        .header h1 {{
            color: #333;
            font-size: 2.5em;
            margin-bottom: 10px;
        }}
        
        .header p {{
            color: #666;
            font-size: 1.2em;
        }}
        
        .cards-grid {{
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
            gap: 20px;
            margin: 20px 0;
        }}
        
        .flashcard {{
            background: white;
            border-radius: 12px;
            padding: 20px;
            box-shadow: 0 4px 8px rgba(0,0,0,0.1);
            transition: transform 0.2s ease, box-shadow 0.2s ease;
            cursor: pointer;
            position: relative;
            min-height: 220px;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
        }}
        
        .flashcard:hover {{
            transform: translateY(-2px);
            box-shadow: 0 8px 16px rgba(0,0,0,0.15);
        }}
        
        .abacus-container {{
            flex: 1;
            display: flex;
            justify-content: center;
            align-items: center;
            margin: 10px 0;
            max-width: 100%;
            overflow: hidden;
        }}
        
        .abacus-container svg {{
            max-width: 100%;
            height: auto;
        }}
        
        .numeral {{
            font-size: {font_size};
            font-weight: bold;
            color: {numeral_color};
            opacity: 0;
            transition: opacity 0.3s ease;
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background: rgba(255,255,255,0.95);
            padding: 15px 25px;
            border-radius: 8px;
            border: 2px solid #ddd;
            box-shadow: 0 4px 8px rgba(0,0,0,0.2);
            z-index: 10;
        }}
        
        .flashcard:hover .numeral {{
            opacity: 1;
        }}
        
        .card-number {{
            position: absolute;
            top: 10px;
            left: 10px;
            font-size: 0.8em;
            color: #999;
            background: rgba(255,255,255,0.8);
            padding: 2px 6px;
            border-radius: 4px;
        }}
        
        .instructions {{
            background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
            padding: 40px;
            border-radius: 20px;
            box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
            margin: 50px 0;
            text-align: left;
            position: relative;
            border: 1px solid rgba(102, 126, 234, 0.1);
        }}
        
        .instructions::before {{
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: linear-gradient(135deg, rgba(102, 126, 234, 0.03) 0%, rgba(118, 75, 162, 0.03) 100%);
            border-radius: 20px;
            pointer-events: none;
        }}
        
        .instructions h3 {{
            color: #2d3748;
            margin-top: 0;
            margin-bottom: 20px;
            font-size: 1.5rem;
            font-weight: 600;
            position: relative;
            z-index: 1;
        }}
        
        .instructions h4 {{
            color: #4a5568;
            margin-top: 30px;
            margin-bottom: 15px;
            font-size: 1.2rem;
            font-weight: 600;
            position: relative;
            z-index: 1;
        }}
        
        .instructions p {{
            position: relative;
            z-index: 1;
            line-height: 1.7;
            color: #4a5568;
        }}
        
        .instructions ul {{
            position: relative;
            z-index: 1;
            margin: 20px 0;
            padding-left: 0;
            list-style: none;
        }}
        
        .instructions li {{
            padding: 12px 0;
            padding-left: 35px;
            position: relative;
            color: #4a5568;
            line-height: 1.6;
        }}
        
        .instructions li::before {{
            content: '✓';
            position: absolute;
            left: 0;
            top: 12px;
            width: 20px;
            height: 20px;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 12px;
            font-weight: bold;
        }}
        
        .instructions p {{
            position: relative;
            z-index: 1;
            line-height: 1.7;
            color: #4a5568;
        }}
        
        .stats {{
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
            gap: 20px;
            margin-top: 40px;
            padding: 0;
        }}
        
        .stats div {{
            background: white;
            padding: 25px;
            border-radius: 15px;
            font-size: 14px;
            border: 1px solid rgba(102, 126, 234, 0.1);
            box-shadow: 0 10px 25px rgba(0, 0, 0, 0.08);
            position: relative;
            overflow: hidden;
            transition: transform 0.3s ease, box-shadow 0.3s ease;
            text-align: left;
        }}
        
        .stats div::before {{
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            width: 4px;
            height: 100%;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        }}
        
        .stats div:hover {{
            transform: translateY(-5px);
            box-shadow: 0 20px 40px rgba(102, 126, 234, 0.15);
        }}
        
        .stats div strong {{
            color: #2d3748;
            display: block;
            margin-bottom: 5px;
            font-weight: 600;
        }}
        
        /* Configuration Showcase Styles */
        .config-showcase {{
            display: flex;
            flex-direction: column;
            gap: 30px;
            margin-top: 30px;
        }}
        
        .config-item {{
            background: white;
            padding: 25px;
            border-radius: 15px;
            border: 1px solid rgba(102, 126, 234, 0.1);
            position: relative;
            transition: all 0.3s ease;
        }}
        
        .config-item:hover {{
            transform: translateY(-2px);
            box-shadow: 0 10px 30px rgba(102, 126, 234, 0.15);
        }}
        
        .config-item::before {{
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            width: 4px;
            height: 100%;
            background: linear-gradient(135deg, #667eea, #764ba2);
            border-radius: 2px 0 0 2px;
        }}
        
        .config-label {{
            font-size: 16px;
            margin-bottom: 8px;
            color: #2d3748;
        }}
        
        .config-value {{
            font-size: 18px;
            color: #4a5568;
            margin-bottom: 10px;
            font-weight: 500;
        }}
        
        .config-description {{
            font-size: 14px;
            color: #718096;
            line-height: 1.5;
            margin-top: 8px;
        }}
        
        .color-palette {{
            display: flex;
            gap: 12px;
            margin: 12px 0;
            align-items: center;
        }}
        
        .color-sample {{
            width: 24px;
            height: 24px;
            border-radius: 50%;
            border: 2px solid rgba(0,0,0,0.1);
            cursor: pointer;
            transition: transform 0.2s ease;
        }}
        
        .color-sample:hover {{
            transform: scale(1.2);
        }}
        
        .color-sample.heaven {{
            background: #8B4513;
        }}
        
        .color-sample.earth {{
            background: #F4A460;
        }}
        
        .color-sample.frame {{
            background: #2F4F4F;
        }}
        
        .bead-examples {{
            display: flex;
            align-items: center;
            gap: 8px;
        }}
        
        .bead-sample {{
            width: 20px;
            height: 20px;
            border: 2px solid rgba(0,0,0,0.2);
            transition: transform 0.2s ease;
        }}
        
        .bead-sample:hover {{
            transform: scale(1.3);
        }}
        
        .bead-sample.circle {{
            border-radius: 50%;
            background: #8B4513;
        }}
        
        .bead-sample.diamond {{
            transform: rotate(45deg);
            background: #8B4513;
        }}
        
        .bead-sample.square {{
            border-radius: 2px;
            background: #8B4513;
        }}
        
        .shape-label {{
            font-size: 13px;
            color: #718096;
            font-weight: 500;
        }}
        
        .offline-info {{
            background: linear-gradient(135deg, #e6fffa 0%, #b2f5ea 100%);
            padding: 30px;
            border-radius: 20px;
            border: 1px solid #4fd1c7;
            margin-top: 40px;
            text-align: center;
        }}
        
        .offline-info h3 {{
            color: #234e52;
            margin-top: 0;
            margin-bottom: 15px;
            font-size: 1.4rem;
        }}
        
        .offline-info p {{
            color: #2d5a5f;
            line-height: 1.6;
            margin-bottom: 20px;
        }}
        
        .tech-features {{
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
            gap: 15px;
            margin-top: 20px;
        }}
        
        .feature {{
            background: rgba(255, 255, 255, 0.7);
            padding: 12px 20px;
            border-radius: 25px;
            font-size: 14px;
            font-weight: 500;
            color: #234e52;
            border: 1px solid rgba(79, 209, 199, 0.3);
        }}
        
        /* Tutorial Styles */
        .tutorial-content {{
            max-width: 1000px;
            margin: 0 auto;
        }}
        
        .tutorial-step {{
            background: white;
            margin-bottom: 40px;
            border-radius: 20px;
            overflow: hidden;
            box-shadow: 0 15px 35px rgba(0,0,0,0.08);
            border: 1px solid rgba(102, 126, 234, 0.1);
        }}
        
        .step-header {{
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            padding: 25px 40px;
            color: white;
        }}
        
        .step-header h3 {{
            margin: 0;
            font-size: 1.5rem;
            font-weight: 600;
            display: flex;
            align-items: center;
            gap: 15px;
        }}
        
        .step-number {{
            background: rgba(255,255,255,0.2);
            width: 35px;
            height: 35px;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            font-weight: 700;
            font-size: 1.1rem;
        }}
        
        .step-content {{
            padding: 40px;
        }}
        
        .tutorial-grid {{
            display: grid;
            grid-template-columns: 1fr 400px;
            gap: 40px;
            align-items: center;
        }}
        
        .tutorial-text h4 {{
            color: #2d3748;
            margin-top: 25px;
            margin-bottom: 15px;
            font-size: 1.1rem;
            font-weight: 600;
        }}
        
        .tutorial-text ol, .tutorial-text ul {{
            color: #4a5568;
            line-height: 1.7;
        }}
        
        .tutorial-text li {{
            margin-bottom: 8px;
        }}
        
        .tutorial-visual {{
            text-align: center;
        }}
        
        .example-abacus {{
            background: #f8fafc;
            padding: 20px;
            border-radius: 12px;
            margin-bottom: 15px;
            border: 2px solid rgba(102, 126, 234, 0.1);
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 120px;
        }}
        
        .example-abacus svg {{
            max-width: 100%;
            height: auto;
        }}
        
        .example-label {{
            font-weight: 600;
            color: #2d3748;
            font-size: 0.95rem;
        }}
        
        .example-breakdown {{
            font-size: 0.85rem;
            color: #718096;
            margin-top: 5px;
            font-style: italic;
        }}
        
        .examples-grid {{
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
            gap: 25px;
            margin-top: 30px;
        }}
        
        .example-item {{
            text-align: center;
        }}
        
        .example-item .example-abacus {{
            margin-bottom: 12px;
            min-height: 100px;
            padding: 15px;
        }}
        
        .practice-hint {{
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 10px 15px;
            border-radius: 8px;
            font-size: 0.9rem;
            margin-top: 10px;
            font-style: italic;
        }}
        
        .reveal-btn {{
            background: linear-gradient(135deg, #28a745 0%, #20c997 100%);
            color: white;
            border: none;
            padding: 12px 24px;
            border-radius: 8px;
            font-size: 0.9rem;
            font-weight: 600;
            cursor: pointer;
            margin-top: 15px;
            transition: all 0.3s ease;
            box-shadow: 0 4px 15px rgba(40, 167, 69, 0.3);
        }}
        
        .reveal-btn:hover {{
            transform: translateY(-2px);
            box-shadow: 0 8px 25px rgba(40, 167, 69, 0.4);
        }}
        
        .reveal-btn:active {{
            transform: translateY(0);
        }}
        
        .revealed {{
            animation: revealAnimation 0.5s ease-out;
        }}
        
        @keyframes revealAnimation {{
            0% {{ 
                background: #fff3cd; 
                transform: scale(1.05); 
            }}
            100% {{ 
                background: #f8fafc; 
                transform: scale(1); 
            }}
        }}
        
        /* Arithmetic Section Styles */
        .arithmetic-intro {{
            background: rgba(102, 126, 234, 0.05);
            padding: 20px;
            border-radius: 12px;
            margin-bottom: 30px;
            border-left: 4px solid #667eea;
        }}
        
        .operation-section {{
            margin: 30px 0;
            padding: 25px;
            background: #f8fafc;
            border-radius: 15px;
            border: 1px solid rgba(102, 126, 234, 0.1);
        }}
        
        .operation-section h4 {{
            color: #2d3748;
            margin-top: 0;
            margin-bottom: 20px;
            font-size: 1.3rem;
            font-weight: 600;
        }}
        
        .calculation-example {{
            margin: 20px 0;
        }}
        
        .calc-step {{
            display: grid;
            grid-template-columns: 1fr 2fr;
            gap: 30px;
            align-items: start;
        }}
        
        .step-description {{
            padding: 20px;
            background: white;
            border-radius: 12px;
            box-shadow: 0 4px 12px rgba(0,0,0,0.08);
        }}
        
        .step-description h5 {{
            color: #667eea;
            margin-top: 0;
            margin-bottom: 15px;
            font-size: 1.1rem;
            font-weight: 600;
        }}
        
        .technique-steps {{
            margin: 15px 0;
            padding-left: 20px;
        }}
        
        .technique-steps li {{
            margin-bottom: 8px;
            color: #4a5568;
            line-height: 1.5;
        }}
        
        .calc-visual-sequence {{
            display: flex;
            align-items: center;
            gap: 15px;
            padding: 20px;
            background: white;
            border-radius: 12px;
            box-shadow: 0 4px 12px rgba(0,0,0,0.08);
            overflow-x: auto;
        }}
        
        .calc-frame {{
            text-align: center;
            min-width: 120px;
            flex-shrink: 0;
        }}
        
        .frame-label {{
            font-size: 0.9rem;
            font-weight: 600;
            color: #2d3748;
            margin-bottom: 10px;
        }}
        
        .calc-arrow {{
            font-size: 0.85rem;
            color: #667eea;
            font-weight: 600;
            text-align: center;
            min-width: 80px;
            flex-shrink: 0;
        }}
        
        .technique-box {{
            background: linear-gradient(135deg, #e3f2fd 0%, #f3e5f5 100%);
            padding: 20px;
            border-radius: 12px;
            margin: 20px 0;
            border: 1px solid rgba(102, 126, 234, 0.2);
        }}
        
        .technique-box h5 {{
            color: #2d3748;
            margin-top: 0;
            margin-bottom: 15px;
            font-size: 1.1rem;
            font-weight: 600;
        }}
        
        .complement-grid {{
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
            gap: 12px;
            margin: 15px 0;
        }}
        
        .complement-pair {{
            background: white;
            padding: 12px 15px;
            border-radius: 8px;
            font-family: 'Courier New', monospace;
            font-size: 0.9rem;
            color: #4a5568;
            border: 1px solid rgba(102, 126, 234, 0.15);
        }}
        
        .mult-layout, .div-layout {{
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 30px;
            padding: 20px;
            background: white;
            border-radius: 12px;
            box-shadow: 0 4px 12px rgba(0,0,0,0.08);
        }}
        
        .mult-setup, .mult-result, .div-setup, .div-result {{
            text-align: center;
        }}
        
        .mult-label, .div-label {{
            font-size: 0.95rem;
            font-weight: 600;
            color: #2d3748;
            margin-bottom: 15px;
        }}
        
        .tips-grid {{
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
            gap: 25px;
            margin-top: 30px;
        }}
        
        .tip-card {{
            background: linear-gradient(135deg, #fff5f5 0%, #f0fff4 100%);
            padding: 25px;
            border-radius: 15px;
            border: 1px solid rgba(102, 126, 234, 0.1);
            box-shadow: 0 8px 20px rgba(0,0,0,0.08);
            transition: transform 0.3s ease, box-shadow 0.3s ease;
        }}
        
        .tip-card:hover {{
            transform: translateY(-5px);
            box-shadow: 0 15px 30px rgba(102, 126, 234, 0.15);
        }}
        
        .tip-card h4 {{
            color: #2d3748;
            margin-top: 0;
            margin-bottom: 15px;
            font-size: 1.1rem;
            font-weight: 600;
        }}
        
        .tip-card p {{
            color: #4a5568;
            line-height: 1.6;
            margin: 0;
        }}
        
        /* Guide Navigation Styles */
        .guide-nav {{
            background: rgba(102, 126, 234, 0.05);
            padding: 20px;
            border-radius: 15px;
            margin-bottom: 40px;
            border: 1px solid rgba(102, 126, 234, 0.1);
        }}
        
        .guide-nav-buttons {{
            display: flex;
            gap: 15px;
            justify-content: center;
            flex-wrap: wrap;
        }}
        
        .guide-nav-btn {{
            padding: 12px 24px;
            border: 2px solid #667eea;
            background: white;
            color: #667eea;
            border-radius: 25px;
            cursor: pointer;
            font-size: 15px;
            font-weight: 600;
            transition: all 0.3s ease;
            text-decoration: none;
        }}
        
        .guide-nav-btn:hover {{
            background: #667eea;
            color: white;
            transform: translateY(-2px);
            box-shadow: 0 8px 20px rgba(102, 126, 234, 0.3);
        }}
        
        .guide-nav-btn.active {{
            background: #667eea;
            color: white;
            box-shadow: 0 6px 15px rgba(102, 126, 234, 0.4);
        }}
        
        .guide-content {{
            position: relative;
        }}
        
        .guide-section {{
            display: none;
            animation: fadeInGuide 0.4s ease-out;
        }}
        
        .guide-section.active {{
            display: block;
        }}
        
        @keyframes fadeInGuide {{
            from {{ 
                opacity: 0;
                transform: translateX(20px);
            }}
            to {{ 
                opacity: 1;
                transform: translateX(0);
            }}
        }}
        
        .section-intro {{
            text-align: center;
            margin-bottom: 40px;
            padding: 30px;
            background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
            border-radius: 15px;
            border: 1px solid rgba(102, 126, 234, 0.1);
        }}
        
        .section-intro h3 {{
            color: #2d3748;
            margin: 0 0 15px 0;
            font-size: 1.8rem;
            font-weight: 600;
        }}
        
        .section-intro p {{
            color: #4a5568;
            margin: 0;
            font-size: 1.1rem;
            line-height: 1.6;
        }}
        
        @media (max-width: 768px) {{
            .tutorial-grid {{
                grid-template-columns: 1fr;
                gap: 25px;
            }}
            
            .step-content {{
                padding: 25px;
            }}
            
            .step-header {{
                padding: 20px 25px;
            }}
            
            .examples-grid {{
                grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
                gap: 20px;
            }}
            
            .calc-step {{
                grid-template-columns: 1fr;
                gap: 20px;
            }}
            
            .calc-visual-sequence {{
                padding: 15px;
            }}
            
            .mult-layout, .div-layout {{
                grid-template-columns: 1fr;
                gap: 20px;
            }}
            
            .tips-grid {{
                grid-template-columns: 1fr;
            }}
        }}
        
        @media (max-width: 768px) {{
            .cards-grid {{
                grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
                gap: 15px;
            }}
            
            .flashcard {{
                min-height: 120px;
                padding: 15px;
            }}
            
            .numeral {{
                font-size: calc({font_size} * 0.8);
                padding: 10px 20px;
            }}
        }}
        
        /* Quiz Styling */
        .quiz-section {{
            background: #f8f9fa;
            border-radius: 12px;
            padding: 30px;
            margin: 30px 0;
            text-align: center;
        }}
        
        .quiz-section h2 {{
            color: #333;
            margin-bottom: 10px;
        }}
        
        .quiz-controls {{
            max-width: 600px;
            margin: 0 auto;
        }}
        
        .control-group {{
            margin: 20px 0;
        }}
        
        .control-group label {{
            display: block;
            font-weight: bold;
            margin-bottom: 10px;
            color: #555;
        }}
        
        .count-buttons {{
            display: flex;
            gap: 10px;
            justify-content: center;
            flex-wrap: wrap;
        }}
        
        .count-btn {{
            background: white;
            border: 2px solid #ddd;
            border-radius: 8px;
            padding: 10px 20px;
            cursor: pointer;
            transition: all 0.2s ease;
            font-size: 16px;
        }}
        
        .count-btn:hover {{
            border-color: #4a90e2;
            background: #f0f7ff;
        }}
        
        .count-btn.active {{
            background: #4a90e2;
            color: white;
            border-color: #4a90e2;
        }}
        
        .slider-container {{
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 15px;
        }}
        
        .slider-container input[type="range"] {{
            width: 200px;
            height: 6px;
            border-radius: 3px;
            background: #ddd;
            outline: none;
            -webkit-appearance: none;
        }}
        
        .slider-container input[type="range"]::-webkit-slider-thumb {{
            -webkit-appearance: none;
            appearance: none;
            width: 20px;
            height: 20px;
            border-radius: 50%;
            background: #4a90e2;
            cursor: pointer;
        }}
        
        .slider-value {{
            font-weight: bold;
            color: #4a90e2;
            min-width: 50px;
        }}
        
        .quiz-start-btn {{
            background: #28a745;
            color: white;
            border: none;
            border-radius: 8px;
            padding: 15px 30px;
            font-size: 18px;
            font-weight: bold;
            cursor: pointer;
            transition: background 0.2s ease;
            margin-top: 20px;
        }}
        
        .quiz-start-btn:hover {{
            background: #218838;
        }}
        
        /* Quiz Game Area */
        .quiz-game {{
            text-align: center;
            padding: 40px 20px;
        }}
        
        .quiz-progress {{
            margin-bottom: 30px;
        }}
        
        .progress-bar {{
            width: 100%;
            max-width: 400px;
            height: 8px;
            background: #ddd;
            border-radius: 4px;
            margin: 0 auto 10px;
            overflow: hidden;
        }}
        
        .progress-fill {{
            height: 100%;
            background: #4a90e2;
            transition: width 0.3s ease;
            width: 0%;
        }}
        
        .progress-text {{
            color: #666;
            font-size: 16px;
        }}
        
        .quiz-display {{
            position: relative;
            min-height: 300px;
            display: flex;
            align-items: center;
            justify-content: center;
        }}
        
        .quiz-flashcard {{
            background: white;
            border-radius: 12px;
            padding: 20px;
            box-shadow: 0 8px 16px rgba(0,0,0,0.1);
            width: min(85vw, 700px);
            height: min(50vh, 400px);
            display: flex;
            align-items: center;
            justify-content: center;
            margin: 0 auto;
            transition: transform 0.3s ease;
        }}
        
        /* Ensure quiz game section fits in viewport */
        #quiz-game {{
            min-height: 100vh;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            padding: 20px;
            box-sizing: border-box;
        }}
        
        /* Responsive adjustments for smaller screens */
        @media (max-height: 600px) {{
            .quiz-flashcard {{
                height: min(40vh, 300px);
                padding: 15px;
            }}
        }}
        
        @media (max-height: 500px) {{
            .quiz-flashcard {{
                height: min(35vh, 250px);
                padding: 10px;
            }}
            
            #quiz-game {{
                min-height: auto;
                padding: 10px;
            }}
        }}
        
        .quiz-flashcard svg {{
            width: 100%;
            height: 100%;
            max-width: 100%;
            max-height: 100%;
        }}
        
        .quiz-flashcard.pulse {{
            transform: scale(1.05);
        }}
        
        .quiz-flashcard.card-exit-warning {{
            border-color: #dc3545;
            box-shadow: 0 0 15px rgba(220, 53, 69, 0.4);
        }}
        
        .quiz-flashcard.card-fade-out {{
            opacity: 0.3;
            transform: scale(0.95);
            transition: all 0.1s ease;
        }}
        
        .countdown {{
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            font-size: 48px;
            font-weight: bold;
            color: #4a90e2;
            text-shadow: 2px 2px 4px rgba(0,0,0,0.1);
            z-index: 10;
        }}
        
        .countdown.ready {{
            color: #28a745;
        }}
        
        .countdown.go {{
            color: #ffc107;
        }}
        
        .countdown.new-card-flash {{
            color: #17a2b8;
            font-size: 24px;
            animation: flashIn 0.15s ease;
        }}
        
        @keyframes flashIn {{
            from {{
                opacity: 0;
                transform: translate(-50%, -50%) scale(0.8);
            }}
            to {{
                opacity: 1;
                transform: translate(-50%, -50%) scale(1);
            }}
        }}
        
        /* Quiz Input */
        .quiz-input {{
            text-align: center;
            padding: 40px 20px;
            max-width: 700px;
            margin: 0 auto;
        }}
        
        .quiz-stats {{
            display: flex;
            justify-content: center;
            gap: 30px;
            margin-bottom: 30px;
            padding: 20px;
            background: #f8f9fa;
            border-radius: 12px;
        }}
        
        .stats-item {{
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: 5px;
        }}
        
        .stats-label {{
            font-size: 14px;
            color: #666;
            font-weight: 500;
        }}
        
        .stats-item span:last-child {{
            font-size: 24px;
            font-weight: bold;
            color: #2c5f76;
        }}
        
        .smart-input-container {{
            position: relative;
            margin: 40px 0;
            text-align: center;
        }}
        
        .smart-input-prompt {{
            font-size: 16px;
            color: #7a8695;
            margin-bottom: 15px;
            font-weight: normal;
        }}
        
        .number-display {{
            min-height: 60px;
            padding: 20px;
            font-size: 32px;
            font-family: 'Courier New', 'Monaco', monospace;
            text-align: center;
            font-weight: bold;
            color: #2c3e50;
            letter-spacing: 3px;
            display: flex;
            align-items: center;
            justify-content: center;
            transition: all 0.3s ease;
        }}
        
        .current-typing {{
            display: inline-block;
            transition: all 0.3s ease;
        }}
        
        .number-display.correct .current-typing {{
            color: #28a745;
            animation: successPulse 0.5s ease;
        }}
        
        .number-display.incorrect .current-typing {{
            color: #dc3545;
            animation: errorShake 0.5s ease;
        }}
        
        @keyframes successPulse {{
            0%, 100% {{ transform: scale(1); }}
            50% {{ transform: scale(1.05); }}
        }}
        
        @keyframes errorShake {{
            0%, 100% {{ transform: translateX(0); }}
            25% {{ transform: translateX(-10px); }}
            75% {{ transform: translateX(10px); }}
        }}
        
        /* Particle Effects System */
        .particle-container {{
            position: fixed;
            top: 0;
            left: 0;
            width: 100vw;
            height: 100vh;
            pointer-events: none;
            z-index: 10000;
        }}
        
        .particle {{
            position: absolute;
            border-radius: 50%;
            pointer-events: none;
        }}
        
        .particle.star {{
            background: linear-gradient(45deg, #ffd700, #ffed4e);
            box-shadow: 0 0 10px #ffd700;
        }}
        
        .particle.heart {{
            background: #ff6b6b;
            border-radius: 0;
            transform: rotate(-45deg);
        }}
        
        .particle.heart::before,
        .particle.heart::after {{
            content: '';
            position: absolute;
            width: 100%;
            height: 100%;
            background: #ff6b6b;
            border-radius: 50%;
        }}
        
        .particle.heart::before {{
            top: -50%;
            left: 0;
        }}
        
        .particle.heart::after {{
            top: 0;
            left: 50%;
        }}
        
        .particle.circle {{
            background: linear-gradient(45deg, #667eea, #764ba2);
            box-shadow: 0 0 8px rgba(102, 126, 234, 0.4);
        }}
        
        .particle.diamond {{
            background: linear-gradient(45deg, #00b894, #00cec9);
            transform: rotate(45deg);
            border-radius: 0;
        }}
        
        .particle.confetti {{
            background: linear-gradient(45deg, #ff6b6b, #feca57);
            border-radius: 2px;
        }}
        
        /* Burst Animation */
        @keyframes particleBurst {{
            0% {{
                opacity: 1;
                transform: translateY(0) scale(0) rotate(0deg);
            }}
            30% {{
                opacity: 1;
                transform: translateY(-20px) scale(1.2) rotate(180deg);
            }}
            100% {{
                opacity: 0;
                transform: translateY(-80px) scale(0.3) rotate(360deg);
            }}
        }}
        
        /* Celebration Firework */
        @keyframes firework {{
            0% {{
                opacity: 1;
                transform: translateY(0) scale(0);
            }}
            20% {{
                opacity: 1;
                transform: translateY(-30px) scale(1.5);
            }}
            100% {{
                opacity: 0;
                transform: translateY(-120px) scale(0.5);
            }}
        }}
        
        /* Floating Animation */
        @keyframes float {{
            0% {{
                opacity: 0;
                transform: translateY(20px) scale(0) rotate(0deg);
            }}
            20% {{
                opacity: 1;
                transform: translateY(0) scale(1) rotate(72deg);
            }}
            100% {{
                opacity: 0;
                transform: translateY(-100px) scale(0.8) rotate(360deg);
            }}
        }}
        
        /* Trail Effect */
        @keyframes trail {{
            0% {{
                opacity: 1;
                transform: translate(0, 0) scale(1);
            }}
            100% {{
                opacity: 0;
                transform: translate(var(--dx), var(--dy)) scale(0.3);
            }}
        }}
        
        /* Sparkle Effect */
        @keyframes sparkle {{
            0%, 100% {{
                opacity: 0;
                transform: scale(0) rotate(0deg);
            }}
            50% {{
                opacity: 1;
                transform: scale(1) rotate(180deg);
            }}
        }}
        
        .particle.burst {{
            animation: particleBurst 0.8s ease-out forwards;
        }}
        
        .particle.firework {{
            animation: firework 1.2s ease-out forwards;
        }}
        
        .particle.floating {{
            animation: float 2s ease-out forwards;
        }}
        
        .particle.trail {{
            animation: trail 1.5s ease-out forwards;
        }}
        
        .particle.sparkle {{
            animation: sparkle 1s ease-in-out forwards;
        }}
        
        .input-feedback {{
            margin-top: 10px;
            font-weight: bold;
            min-height: 20px;
        }}
        
        .input-feedback.success {{
            color: #28a745;
        }}
        
        .input-feedback.error {{
            color: #dc3545;
        }}
        
        .input-feedback.survival {{
            color: #ff6b6b;
            background: linear-gradient(135deg, rgba(255, 107, 107, 0.1), rgba(255, 193, 7, 0.1));
            padding: 8px 12px;
            border-radius: 8px;
            font-weight: 600;
            border: 1px solid rgba(255, 107, 107, 0.3);
        }}
        
        .found-numbers {{
            margin: 30px 0;
            min-height: 60px;
        }}
        
        .found-number {{
            display: inline-block;
            margin: 5px;
            padding: 10px 15px;
            background: #28a745;
            color: white;
            border-radius: 8px;
            font-weight: bold;
            font-size: 18px;
            animation: slideIn 0.3s ease;
        }}
        
        @keyframes slideIn {{
            from {{
                opacity: 0;
                transform: translateY(-20px);
            }}
            to {{
                opacity: 1;
                transform: translateY(0);
            }}
        }}
        
        .finish-btn {{
            background: #2c5f76;
            color: white;
            border: none;
            padding: 15px 30px;
            font-size: 18px;
            border-radius: 8px;
            cursor: pointer;
            transition: all 0.3s ease;
            margin-top: 20px;
        }}
        
        .finish-btn:hover {{
            background: #1e4a5c;
            transform: translateY(-2px);
        }}
        
        .quiz-finish-buttons {{
            display: flex;
            gap: 15px;
            justify-content: center;
            margin-top: 20px;
            flex-wrap: wrap;
        }}
        
        .give-up-btn {{
            background: #17a2b8;
            color: white;
            border: none;
            padding: 15px 30px;
            font-size: 18px;
            border-radius: 8px;
            cursor: pointer;
            transition: all 0.3s ease;
        }}
        
        .give-up-btn:hover {{
            background: #138496;
            transform: translateY(-2px);
        }}
        
        .input-container {{
            margin-top: 20px;
        }}
        
        .quiz-input textarea {{
            width: 100%;
            max-width: 400px;
            height: 120px;
            border: 2px solid #ddd;
            border-radius: 8px;
            padding: 15px;
            font-size: 16px;
            resize: vertical;
            font-family: inherit;
        }}
        
        .quiz-input textarea:focus {{
            outline: none;
            border-color: #4a90e2;
        }}
        
        .quiz-input button {{
            background: #4a90e2;
            color: white;
            border: none;
            border-radius: 8px;
            padding: 12px 24px;
            font-size: 16px;
            cursor: pointer;
            margin-top: 15px;
        }}
        
        .quiz-input button:hover {{
            background: #357abd;
        }}
        
        /* Quiz Results */
        .quiz-results {{
            text-align: center;
            padding: 40px 20px;
            max-width: 700px;
            margin: 0 auto;
        }}
        
        .score-display {{
            display: flex;
            justify-content: center;
            align-items: center;
            gap: 40px;
            margin: 30px 0;
            flex-wrap: wrap;
        }}
        
        .score-circle {{
            width: 120px;
            height: 120px;
            border-radius: 50%;
            background: linear-gradient(135deg, #4a90e2, #357abd);
            display: flex;
            align-items: center;
            justify-content: center;
            color: white;
            font-size: 24px;
            font-weight: bold;
            box-shadow: 0 4px 8px rgba(0,0,0,0.2);
        }}
        
        .score-details {{
            text-align: left;
        }}
        
        .score-details p {{
            margin: 8px 0;
            font-size: 16px;
        }}
        
        .results-breakdown {{
            background: #f8f9fa;
            border-radius: 8px;
            padding: 20px;
            margin: 30px 0;
            text-align: left;
        }}
        
        .result-item {{
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 10px 0;
            border-bottom: 1px solid #eee;
        }}
        
        .result-item:last-child {{
            border-bottom: none;
        }}
        
        .result-correct {{
            color: #28a745;
            font-weight: bold;
        }}
        
        .result-incorrect {{
            color: #dc3545;
            font-weight: bold;
        }}
        
        .quiz-actions {{
            margin-top: 30px;
            display: flex;
            gap: 15px;
            justify-content: center;
            flex-wrap: wrap;
        }}
        
        .quiz-actions button {{
            padding: 12px 24px;
            border: none;
            border-radius: 8px;
            font-size: 16px;
            cursor: pointer;
            transition: background 0.2s ease;
        }}
        
        #retry-quiz {{
            background: #ffc107;
            color: #333;
        }}
        
        #retry-quiz:hover {{
            background: #e0a800;
        }}
        
        #back-to-cards {{
            background: #6c757d;
            color: white;
        }}
        
        #back-to-cards:hover {{
            background: #545b62;
        }}
        
        /* End Game Button */
        .end-game-btn {{
            background: #dc3545;
            color: white;
            border: none;
            border-radius: 8px;
            padding: 8px 16px;
            font-size: 14px;
            cursor: pointer;
            transition: background 0.2s ease;
        }}
        
        .end-game-btn:hover {{
            background: #c82333;
        }}
        
        /* Quiz Header for Game Mode */
        .quiz-header {{
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 20px;
            padding: 15px 20px;
            background: rgba(74, 144, 226, 0.1);
            border-radius: 8px;
        }}
        
        .quiz-header .quiz-progress {{
            flex: 1;
        }}
        
        @media (max-width: 768px) {{
            .quiz-section {{
                padding: 20px;
            }}
            
            .count-buttons {{
                gap: 8px;
            }}
            
            .count-btn {{
                padding: 8px 16px;
                font-size: 14px;
            }}
            
            .score-display {{
                flex-direction: column;
                gap: 20px;
            }}
            
            .score-details {{
                text-align: center;
            }}
            
            .countdown {{
                font-size: 36px;
            }}
            
            .sorting-section {{
                padding: 20px;
            }}
            
            .sorting-grid {{
                grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
                gap: 10px;
                padding: 15px;
            }}
            
            .sort-card {{
                padding: 10px;
            }}
            
            .sort-count-btn {{
                padding: 8px 16px;
                font-size: 14px;
                margin: 2px;
            }}
            
            .sort-start-btn, .sort-check-btn, .sort-reveal-btn, .sort-new-btn {{
                padding: 10px 16px;
                font-size: 14px;
                margin: 5px;
            }}
            
            .sorting-actions {{
                display: flex;
                flex-wrap: wrap;
                justify-content: center;
            }}
            
            .tag-filter-bar {{
                padding: 15px;
            }}
            
            .filter-title {{
                font-size: 1rem;
                margin-bottom: 12px;
            }}
            
            .tag-filters {{
                gap: 8px;
            }}
            
            .tag-filter {{
                font-size: 0.8rem;
                padding: 6px 12px;
            }}
            
            .challenges-grid {{
                grid-template-columns: 1fr;
                gap: 20px;
                margin: 20px 0;
            }}
            
            .challenge-card {{
                min-height: 80px;
                padding: 15px;
            }}
            
            .challenge-icon {{
                width: 40px;
                height: 40px;
                font-size: 24px;
            }}
            
            .modal-content {{
                width: 95%;
                max-height: 95vh;
            }}
            
            .modal-header {{
                padding: 15px 20px;
            }}
            
            .modal-body {{
                padding: 20px;
            }}
            
            .modal-header h2 {{
                font-size: 18px;
            }}
        }}
        
        /* Card Sorting Styling */
        .sorting-section {{
            background: #e8f4f8;
            border-radius: 12px;
            padding: 30px;
            margin: 30px 0;
            text-align: center;
        }}
        
        .sorting-section h2 {{
            color: #2c5f76;
            margin-bottom: 10px;
        }}
        
        .sorting-controls {{
            max-width: 600px;
            margin: 0 auto;
        }}
        
        .sort-count-btn {{
            background: #ffffff;
            color: #2c5f76;
            border: 2px solid #2c5f76;
            border-radius: 8px;
            padding: 10px 20px;
            margin: 0 5px;
            cursor: pointer;
            font-size: 16px;
            transition: all 0.3s ease;
        }}
        
        .sort-count-btn:hover {{
            background: #2c5f76;
            color: white;
            transform: translateY(-2px);
        }}
        
        .sort-count-btn.active {{
            background: #2c5f76;
            color: white;
        }}
        
        .sorting-actions {{
            margin-top: 20px;
        }}
        
        /* Setup modal body for sticky positioning */
        .modal-body {{
            position: relative;
        }}
        
        /* Sticky header within modal body */
        .sorting-header {{
            position: sticky;
            top: 0;
            background: #f8f9fa;
            border-bottom: 2px solid #e1e5e9;
            border-radius: 8px 8px 0 0;
            z-index: 50;
            padding: 12px 20px;
            margin: 0 -20px 15px -20px; /* Extend to edges of modal body */
        }}
        
        .sorting-header-content {{
            display: flex;
            justify-content: space-between;
            align-items: center;
            flex-wrap: wrap;
            gap: 15px;
        }}
        
        .sorting-status-group {{
            display: flex;
            flex-direction: column;
            gap: 5px;
        }}
        
        .sorting-timer {{
            font-size: 18px;
            font-weight: bold;
            color: #2c5f76;
        }}
        
        .sorting-controls {{
            display: flex;
            gap: 10px;
            flex-wrap: wrap;
        }}
        
        .header-btn {{
            padding: 8px 16px;
            border: none;
            border-radius: 6px;
            font-size: 14px;
            cursor: pointer;
            transition: all 0.2s ease;
        }}
        
        .check-btn {{
            background: #28a745;
            color: white;
        }}
        
        .check-btn:hover {{
            background: #218838;
        }}
        
        .reveal-btn {{
            background: #ffc107;
            color: #212529;
        }}
        
        .reveal-btn:hover {{
            background: #e0a800;
        }}
        
        .new-btn {{
            background: #007bff;
            color: white;
        }}
        
        .new-btn:hover {{
            background: #0056b3;
        }}
        
        .end-btn {{
            background: #dc3545;
            color: white;
        }}
        
        .end-btn:hover {{
            background: #c82333;
        }}
        
        .sorting-game-actions {{
            display: none; /* Hide old action buttons */
        }}
        
        /* Score Modal Styles */
        .score-modal {{
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.7);
            z-index: 2000;
            display: flex;
            justify-content: center;
            align-items: center;
            animation: fadeIn 0.3s ease;
        }}
        
        .score-modal-content {{
            background: white;
            border-radius: 12px;
            max-width: 600px;
            width: 90%;
            max-height: 80vh;
            overflow-y: auto;
            box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
            animation: slideIn 0.3s ease;
        }}
        
        .score-modal-header {{
            padding: 20px 30px;
            border-bottom: 1px solid #e1e5e9;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }}
        
        .score-modal-header h3 {{
            margin: 0;
            color: #333;
            font-size: 24px;
        }}
        
        .score-modal-close {{
            background: none;
            border: none;
            font-size: 32px;
            cursor: pointer;
            color: #666;
            padding: 0;
            width: 40px;
            height: 40px;
            display: flex;
            align-items: center;
            justify-content: center;
            border-radius: 20px;
            transition: all 0.2s ease;
        }}
        
        .score-modal-close:hover {{
            background: #f8f9fa;
            color: #333;
        }}
        
        .score-modal-body {{
            padding: 30px;
        }}
        
        .score-modal-body .feedback-score {{
            font-size: 48px;
            font-weight: bold;
            text-align: center;
            margin-bottom: 20px;
            color: #28a745;
        }}
        
        .score-modal-body .feedback-message {{
            font-size: 20px;
            text-align: center;
            margin-bottom: 15px;
            color: #333;
        }}
        
        .score-modal-body .feedback-time {{
            font-size: 18px;
            text-align: center;
            margin-bottom: 25px;
            color: #666;
            font-weight: bold;
        }}
        
        .score-modal-body .feedback-breakdown {{
            background: #f8f9fa;
            border-radius: 8px;
            padding: 20px;
            margin: 20px 0;
        }}
        
        .score-modal-body .score-component {{
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 8px 0;
            border-bottom: 1px solid #e9ecef;
        }}
        
        .score-modal-body .score-component:last-child {{
            border-bottom: none;
        }}
        
        .score-modal-body .component-label {{
            font-weight: bold;
            color: #333;
        }}
        
        .score-modal-body .component-score {{
            font-weight: bold;
            color: #007bff;
        }}
        
        .score-modal-body .component-weight {{
            color: #666;
            font-size: 14px;
        }}
        
        .score-modal-body .feedback-details {{
            background: #e9ecef;
            padding: 15px;
            border-radius: 6px;
            text-align: center;
            font-size: 16px;
            color: #495057;
        }}
        
        .score-modal-footer {{
            padding: 20px 30px;
            border-top: 1px solid #e1e5e9;
            display: flex;
            gap: 15px;
            justify-content: flex-end;
        }}
        
        .modal-btn {{
            padding: 10px 20px;
            border: none;
            border-radius: 6px;
            cursor: pointer;
            font-size: 16px;
            transition: all 0.2s ease;
        }}
        
        .new-game-btn {{
            background: #007bff;
            color: white;
        }}
        
        .new-game-btn:hover {{
            background: #0056b3;
        }}
        
        .close-btn {{
            background: #6c757d;
            color: white;
        }}
        
        .close-btn:hover {{
            background: #545b62;
        }}
        
        /* Race Results Specific Styles */
        .race-results-summary {{
            text-align: center;
        }}
        
        .race-podium {{
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            border-radius: 15px;
            padding: 30px;
            margin-bottom: 30px;
            box-shadow: 0 10px 25px rgba(102, 126, 234, 0.3);
        }}
        
        .medal-display {{
            margin-bottom: 25px;
        }}
        
        .medal-icon {{
            font-size: 4rem;
            margin-bottom: 10px;
            display: block;
            filter: drop-shadow(0 4px 8px rgba(0,0,0,0.3));
        }}
        
        .medal-rank {{
            font-size: 1.8rem;
            font-weight: 700;
            margin-bottom: 5px;
            text-shadow: 0 2px 4px rgba(0,0,0,0.3);
        }}
        
        .medal-title {{
            font-size: 1.3rem;
            font-weight: 600;
            opacity: 0.9;
            letter-spacing: 1px;
        }}
        
        .race-performance {{
            display: grid;
            grid-template-columns: repeat(3, 1fr);
            gap: 20px;
            margin-top: 25px;
        }}
        
        .perf-metric {{
            background: rgba(255, 255, 255, 0.15);
            border-radius: 10px;
            padding: 15px;
            backdrop-filter: blur(10px);
        }}
        
        .metric-label {{
            display: block;
            font-size: 0.9rem;
            opacity: 0.8;
            margin-bottom: 5px;
        }}
        
        .metric-value {{
            display: block;
            font-size: 1.4rem;
            font-weight: 700;
            text-shadow: 0 1px 3px rgba(0,0,0,0.3);
        }}
        
        .race-statistics {{
            background: #f8f9fa;
            border-radius: 12px;
            padding: 25px;
            margin-bottom: 25px;
        }}
        
        .stat-row {{
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 12px 0;
            border-bottom: 1px solid #e9ecef;
        }}
        
        .stat-row:last-child {{
            border-bottom: none;
        }}
        
        .stat-label {{
            font-weight: 500;
            color: #495057;
        }}
        
        .stat-value {{
            font-weight: 700;
            color: #007bff;
            font-size: 1.1rem;
        }}
        
        .race-feedback {{
            background: linear-gradient(135deg, #e3f2fd, #f3e5f5);
            border-radius: 10px;
            padding: 20px;
            border-left: 4px solid #2196f3;
        }}
        
        .race-feedback p {{
            margin: 0;
            font-size: 1rem;
            line-height: 1.5;
            color: #495057;
            text-align: center;
        }}
        
        /* Responsive adjustments for race results */
        @media (max-width: 768px) {{
            .race-performance {{
                grid-template-columns: 1fr;
                gap: 15px;
            }}
            
            .medal-icon {{
                font-size: 3rem;
            }}
            
            .medal-rank {{
                font-size: 1.5rem;
            }}
            
            .metric-value {{
                font-size: 1.2rem;
            }}
        }}
        
        @keyframes fadeIn {{
            from {{ opacity: 0; }}
            to {{ opacity: 1; }}
        }}
        
        @keyframes slideIn {{
            from {{ 
                transform: translateY(-50px);
                opacity: 0;
            }}
            to {{ 
                transform: translateY(0);
                opacity: 1;
            }}
        }}
        
        .sort-start-btn, .sort-check-btn, .sort-reveal-btn, .sort-new-btn {{
            background: #2c5f76;
            color: white;
            border: none;
            border-radius: 8px;
            padding: 12px 24px;
            font-size: 16px;
            cursor: pointer;
            margin: 0 10px;
            transition: all 0.3s ease;
        }}
        
        .sort-start-btn:hover, .sort-check-btn:hover, .sort-reveal-btn:hover, .sort-new-btn:hover {{
            background: #1e4a61;
            transform: translateY(-2px);
        }}
        
        .sort-check-btn {{
            background: #28a745;
        }}
        
        .sort-check-btn:hover {{
            background: #218838;
        }}
        
        .sort-reveal-btn {{
            background: #ffc107;
            color: #333;
        }}
        
        .sort-reveal-btn:hover {{
            background: #e0a800;
        }}
        
        .sort-new-btn {{
            background: #6f42c1;
        }}
        
        .sort-new-btn:hover {{
            background: #5a32a3;
        }}
        
        .sorting-instructions {{
            margin: 20px 0;
            color: #2c5f76;
        }}
        
        .sorting-progress {{
            background: #fff;
            border-radius: 8px;
            padding: 10px 20px;
            margin: 10px 0;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }}
        
        /* Horizontal layout for sorting game */
        .sorting-game-layout {{
            display: flex;
            gap: 30px;
            margin: 20px 0;
        }}
        
        .available-cards-section {{
            flex: 1;
        }}
        
        .sorting-slots-section {{
            flex: 2;
        }}
        
        .available-cards-section h4,
        .sorting-slots-section h4 {{
            margin: 0 0 15px 0;
            color: #2c5f76;
            font-size: 18px;
            text-align: center;
        }}
        
        .sorting-area {{
            display: flex;
            flex-wrap: wrap;
            gap: 10px;
            justify-content: center;
            padding: 15px;
            background: rgba(255,255,255,0.5);
            border-radius: 8px;
            min-height: 120px;
            border: 2px dashed #2c5f76;
        }}
        
        @media (max-width: 768px) {{
            .sorting-game-layout {{
                flex-direction: column;
                gap: 20px;
            }}
            
            .available-cards-section,
            .sorting-slots-section {{
                flex: none;
            }}
        }}
        
        .position-slots {{
            display: flex;
            flex-wrap: wrap;
            gap: 8px;
            justify-content: center;
            align-items: center;
            padding: 15px;
            background: rgba(255,255,255,0.7);
            border-radius: 8px;
            border: 2px dashed #2c5f76;
        }}
        
        .insert-button {{
            width: 32px;
            height: 50px;
            background: #2c5f76;
            color: white;
            border: none;
            border-radius: 20px;
            cursor: pointer;
            font-size: 24px;
            font-weight: bold;
            display: flex;
            align-items: center;
            justify-content: center;
            transition: all 0.3s ease;
            opacity: 0.3;
        }}
        
        .insert-button:hover {{
            opacity: 1;
            background: #1976d2;
            transform: scale(1.1);
        }}
        
        .insert-button.active {{
            opacity: 1;
            background: #1976d2;
            box-shadow: 0 4px 12px rgba(25, 118, 210, 0.3);
        }}
        
        .insert-button.disabled {{
            opacity: 0.1;
            cursor: not-allowed;
        }}
        
        .position-slot {{
            width: 90px;
            height: 110px;
            border: 2px solid #2c5f76;
            border-radius: 8px;
            background: #fff;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            cursor: pointer;
            transition: all 0.3s ease;
            position: relative;
        }}
        
        .position-slot.gradient-bg {{
            color: white;
            border-color: rgba(255,255,255,0.3);
        }}
        
        .position-slot:hover {{
            background: #f0f8ff;
            border-color: #1a4a5c;
            transform: scale(1.05);
        }}
        
        .position-slot.active {{
            background: #e3f2fd;
            border-color: #1976d2;
            box-shadow: 0 4px 12px rgba(25, 118, 210, 0.3);
        }}
        
        
        .position-slot .slot-label {{
            font-size: 12px;
            text-align: center;
            font-weight: 500;
            text-shadow: 0 1px 2px rgba(0,0,0,0.3);
            /* Color will be set dynamically based on background */
        }}
        
        .position-slot.filled .slot-label {{
            position: absolute;
            bottom: 8px;
            left: 8px;
            right: 8px;
            color: #2c3e50;
            text-shadow: none;
            font-size: 11px;
            font-weight: 600;
            opacity: 0;
            transition: opacity 0.3s ease;
            background: rgba(255, 255, 255, 0.9);
            border-radius: 4px;
            padding: 4px 8px;
        }}
        
        .position-slot.filled:hover .slot-label {{
            opacity: 1;
        }}
        
        .position-slot.filled {{
            background: #e8f5e8;
            border-color: #28a745;
        }}
        
        .position-slot.filled .slot-card {{
            position: absolute;
            top: 5px;
            left: 5px;
            right: 5px;
            bottom: 5px;
            display: flex;
            align-items: center;
            justify-content: center;
        }}
        
        .position-slot.correct {{
            border-color: #28a745;
            background: #f8fff9;
        }}
        
        .position-slot.incorrect {{
            border-color: #dc3545;
            background: #fff8f8;
            animation: shake 0.5s ease-in-out;
        }}
        
        .sorting-grid {{
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
            gap: 15px;
            margin: 30px 0;
            padding: 20px;
            background: rgba(255,255,255,0.7);
            border-radius: 12px;
            min-height: 300px;
        }}
        
        .sort-card {{
            background: white;
            border-radius: 8px;
            padding: 8px;
            box-shadow: 0 2px 6px rgba(0,0,0,0.1);
            cursor: pointer;
            transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
            border: 2px solid transparent;
            position: relative;
            user-select: none;
            width: 90px;
            height: 90px;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
        }}
        
        .sort-card .card-svg svg {{
            max-width: 100%;
            height: auto;
        }}
        
        .sort-card:hover {{
            transform: translateY(-5px);
            box-shadow: 0 8px 16px rgba(0,0,0,0.2);
            border-color: #2c5f76;
        }}
        
        .sort-card.selected {{
            border-color: #1976d2;
            background: #e3f2fd;
            transform: scale(1.1);
            box-shadow: 0 6px 20px rgba(25, 118, 210, 0.3);
        }}
        
        .sort-card.placed {{
            opacity: 0.7;
            transform: scale(0.9);
            cursor: default;
        }}
        
        .sort-card.placed:hover {{
            transform: scale(0.95);
            border-color: #28a745;
        }}
        
        .sort-card.correct {{
            border-color: #28a745;
            background: #f8fff9;
        }}
        
        .sort-card.incorrect {{
            border-color: #dc3545;
            background: #fff8f8;
            animation: shake 0.5s ease-in-out;
        }}
        
        .sort-card .card-position {{
            position: absolute;
            top: 5px;
            left: 5px;
            background: rgba(44, 95, 118, 0.8);
            color: white;
            border-radius: 50%;
            width: 24px;
            height: 24px;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 12px;
            font-weight: bold;
        }}
        
        .sort-card .revealed-number {{
            position: absolute;
            top: 5px;
            right: 5px;
            background: #ffc107;
            color: #333;
            border-radius: 4px;
            padding: 2px 8px;
            font-size: 14px;
            font-weight: bold;
            display: none;
        }}
        
        .sort-card.revealed .revealed-number {{
            display: block;
        }}
        
        .sorting-feedback {{
            background: white;
            border-radius: 12px;
            padding: 20px;
            margin: 20px 0;
            text-align: center;
        }}
        
        .feedback-perfect {{
            background: linear-gradient(135deg, #d4edda, #c3e6cb);
            color: #155724;
            border: 2px solid #28a745;
        }}
        
        .feedback-good {{
            background: linear-gradient(135deg, #fff3cd, #ffeaa7);
            color: #856404;
            border: 2px solid #ffc107;
        }}
        
        .feedback-needs-work {{
            background: linear-gradient(135deg, #f8d7da, #f5c6cb);
            color: #721c24;
            border: 2px solid #dc3545;
        }}
        
        .feedback-score {{
            font-size: 24px;
            font-weight: bold;
            margin: 10px 0;
        }}
        
        .feedback-message {{
            font-size: 18px;
            margin: 10px 0;
        }}
        
        .feedback-details {{
            margin-top: 15px;
            font-size: 14px;
            opacity: 0.8;
        }}
        
        .feedback-breakdown {{
            margin: 20px 0;
            padding: 15px;
            background: rgba(255, 255, 255, 0.1);
            border-radius: 8px;
        }}
        
        .score-component {{
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin: 8px 0;
            padding: 5px 0;
            border-bottom: 1px solid rgba(255, 255, 255, 0.1);
        }}
        
        .score-component:last-child {{
            border-bottom: none;
        }}
        
        .component-label {{
            font-weight: bold;
            flex: 1;
        }}
        
        .component-score {{
            font-weight: bold;
            margin: 0 10px;
            min-width: 40px;
            text-align: right;
        }}
        
        .component-weight {{
            font-size: 12px;
            opacity: 0.7;
            min-width: 80px;
            text-align: right;
        }}
        
        @keyframes shake {{
            0%, 100% {{ transform: translateX(0); }}
            25% {{ transform: translateX(-5px); }}
            75% {{ transform: translateX(5px); }}
        }}
        
        @keyframes success-pulse {{
            0% {{ transform: scale(1); }}
            50% {{ transform: scale(1.05); }}
            100% {{ transform: scale(1); }}
        }}
        
        .sort-card.success {{
            animation: success-pulse 0.6s ease-in-out;
        }}
        
        /* Challenge Buttons */
        .challenges-section {{
            margin: 40px 0;
            max-width: 1200px;
            margin-left: auto;
            margin-right: auto;
        }}
        
        .section-header {{
            text-align: center;
            margin-bottom: 30px;
        }}
        
        .section-header h2 {{
            margin: 0 0 10px 0;
            color: #2c3e50;
            font-size: 28px;
        }}
        
        .section-header p {{
            margin: 0;
            color: #7a8695;
            font-size: 16px;
        }}
        
        /* Tag Filter Bar */
        .tag-filter-bar {{
            background: white;
            border-radius: 16px;
            padding: 25px;
            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
            margin-bottom: 30px;
        }}
        
        .filter-title {{
            font-size: 1.1rem;
            font-weight: 600;
            color: #2c3e50;
            margin-bottom: 15px;
            text-align: center;
        }}
        
        .tag-filters {{
            display: flex;
            flex-wrap: wrap;
            gap: 12px;
            justify-content: center;
        }}
        
        .tag-filter {{
            background: #f8f9fa;
            border: 2px solid #e9ecef;
            border-radius: 25px;
            padding: 8px 16px;
            font-size: 0.9rem;
            font-weight: 500;
            color: #6c757d;
            cursor: pointer;
            transition: all 0.3s ease;
            display: flex;
            align-items: center;
            gap: 5px;
        }}
        
        .tag-filter:hover {{
            background: #e9ecef;
            transform: translateY(-2px);
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
        }}
        
        .tag-filter.active {{
            background: linear-gradient(135deg, #4a90e2, #357abd);
            color: white;
            border-color: #4a90e2;
            box-shadow: 0 4px 15px rgba(74, 144, 226, 0.3);
        }}
        
        .tag-count {{
            background: rgba(255, 255, 255, 0.2);
            border-radius: 12px;
            padding: 2px 8px;
            font-size: 0.8rem;
            font-weight: 600;
        }}
        
        .tag-filter.active .tag-count {{
            background: rgba(255, 255, 255, 0.3);
        }}

        .challenges-grid {{
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
            gap: 30px;
            margin-top: 0px;
        }}
        
        .challenge-category {{
            background: white;
            border-radius: 16px;
            padding: 25px;
            box-shadow: 0 4px 12px rgba(0,0,0,0.1);
            border: 1px solid #f0f2f5;
        }}
        
        .category-title {{
            margin: 0 0 20px 0;
            color: #2c3e50;
            font-size: 18px;
            font-weight: 600;
            text-align: center;
            padding-bottom: 15px;
            border-bottom: 2px solid #f0f2f5;
        }}
        
        .challenge-cards {{
            display: flex;
            flex-direction: column;
            gap: 15px;
        }}
        
        .challenge-card {{
            background: linear-gradient(135deg, #4a90e2, #357abd);
            color: white;
            border: none;
            border-radius: 12px;
            padding: 20px;
            cursor: pointer;
            transition: all 0.3s ease;
            display: flex;
            align-items: center;
            gap: 15px;
            text-align: left;
            min-height: 100px;
        }}
        
        .challenge-card:hover {{
            transform: translateY(-2px);
            box-shadow: 0 8px 25px rgba(74, 144, 226, 0.4);
        }}
        
        .challenge-icon {{
            font-size: 32px;
            flex-shrink: 0;
            width: 50px;
            height: 50px;
            display: flex;
            align-items: center;
            justify-content: center;
            background: rgba(255,255,255,0.2);
            border-radius: 12px;
        }}
        
        .challenge-content {{
            flex: 1;
        }}
        
        .challenge-content h4 {{
            margin: 0 0 8px 0;
            font-size: 18px;
            font-weight: 600;
        }}
        
        .challenge-content p {{
            margin: 0 0 12px 0;
            opacity: 0.9;
            font-size: 14px;
            line-height: 1.4;
        }}
        
        .challenge-tags {{
            display: flex;
            gap: 10px;
            flex-wrap: wrap;
            margin-top: 8px;
        }}
        
        .tag {{
            background: rgba(255,255,255,0.2);
            padding: 4px 8px;
            border-radius: 6px;
            font-size: 12px;
            font-weight: 500;
            border: 1px solid rgba(255,255,255,0.3);
        }}
        
        .sorting-card {{
            background: linear-gradient(135deg, #2c5f76, #1e4a61);
        }}
        
        .sorting-card:hover {{
            box-shadow: 0 8px 25px rgba(44, 95, 118, 0.4);
        }}
        
        .matching-card {{
            background: linear-gradient(135deg, #7b4397, #dc2430);
        }}
        
        .matching-card:hover {{
            box-shadow: 0 8px 25px rgba(123, 67, 151, 0.4);
        }}
        
        .start-game-btn {{
            background: linear-gradient(135deg, #6c5ce7, #a29bfe);
            color: white;
            border: none;
            padding: 15px 20px;
            border-radius: 12px;
            cursor: pointer;
            transition: all 0.3s ease;
            text-align: center;
            min-height: 70px;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            gap: 4px;
        }}
        
        .start-game-btn:hover {{
            background: linear-gradient(135deg, #5f4ed6, #9085f5);
            transform: translateY(-2px);
            box-shadow: 0 8px 20px rgba(108, 92, 231, 0.4);
        }}
        
        .start-game-btn .btn-main {{
            font-size: 16px;
            font-weight: 600;
            line-height: 1.2;
        }}
        
        .start-game-btn .btn-sub {{
            font-size: 13px;
            opacity: 0.9;
            font-weight: 400;
        }}
        
        .mode-buttons, .timer-buttons {{
            display: flex;
            gap: 10px;
            flex-wrap: wrap;
        }}
        
        .mode-btn, .timer-btn, .game-type-btn, .timeout-btn {{
            background: #f8f9fa;
            border: 2px solid #e9ecef;
            padding: 10px 15px;
            border-radius: 8px;
            cursor: pointer;
            transition: all 0.3s ease;
            display: flex;
            align-items: center;
            gap: 8px;
            min-width: 120px;
            justify-content: center;
        }}
        
        .mode-btn.active, .timer-btn.active, .game-type-btn.active, .timeout-btn.active {{
            background: #007bff;
            border-color: #007bff;
            color: white;
        }}
        
        .mode-btn:hover, .timer-btn:hover, .game-type-btn:hover, .timeout-btn:hover {{
            border-color: #007bff;
            background: #e3f2fd;
        }}
        
        .mode-btn.active:hover, .timer-btn.active:hover, .game-type-btn.active:hover, .timeout-btn.active:hover {{
            background: #0056b3;
        }}
        
        .mode-icon {{
            font-size: 18px;
        }}
        
        .mode-text {{
            font-weight: 500;
        }}
        
        .timer-btn {{
            min-width: 80px;
            font-size: 14px;
            font-weight: 500;
        }}
        
        /* Matching Game Styles */
        .matching-header {{
            position: sticky;
            top: 0;
            background: #f8f9fa;
            border-bottom: 2px solid #e9ecef;
            padding: 15px 20px;
            z-index: 100;
            margin: 0 -20px 15px -20px;
        }}
        
        .matching-header-content {{
            display: flex;
            justify-content: space-between;
            align-items: center;
        }}
        
        .matching-status-group {{
            display: flex;
            flex-direction: column;
            gap: 5px;
        }}
        
        .matching-stats {{
            display: flex;
            gap: 15px;
            font-size: 14px;
            color: #6c757d;
        }}
        
        .matching-timer {{
            font-weight: 600;
            color: #495057;
        }}
        
        .player-stats {{
            display: flex;
            align-items: center;
            gap: 20px;
            margin-top: 10px;
        }}
        
        .player-info {{
            display: flex;
            flex-direction: column;
            align-items: center;
            padding: 8px 12px;
            background: #f8f9fa;
            border-radius: 8px;
            min-width: 80px;
        }}
        
        .player-info.active {{
            color: white;
        }}
        
        .player-info.player1 {{
            border: 2px solid #007bff;
        }}
        
        .player-info.player1.active {{
            background: #007bff;
        }}
        
        .player-info.player2 {{
            border: 2px solid #fd7e14;
        }}
        
        .player-info.player2.active {{
            background: #fd7e14;
        }}
        
        .player-name {{
            font-size: 12px;
            font-weight: 600;
            margin-bottom: 2px;
        }}
        
        .player-score {{
            font-size: 14px;
            font-weight: 500;
        }}
        
        .current-turn {{
            font-size: 16px;
            font-weight: 600;
            color: #007bff;
            text-align: center;
        }}
        
        .turn-timer {{
            font-size: 20px;
            font-weight: 700;
            color: #495057;
            background: #e9ecef;
            padding: 8px 12px;
            border-radius: 8px;
            min-width: 60px;
            text-align: center;
            border: 2px solid #dee2e6;
        }}
        
        .turn-timer.warning {{
            background: #fff3cd;
            color: #856404;
            animation: timerPulse 1s infinite;
        }}
        
        .turn-timer.critical {{
            background: #f8d7da;
            color: #721c24;
            animation: timerPulse 0.5s infinite;
        }}
        
        .turn-timer.waiting {{
            background: #d1ecf1;
            color: #0c5460;
            opacity: 0.8;
        }}
        
        @keyframes timerPulse {{
            0%, 100% {{ transform: scale(1); }}
            50% {{ transform: scale(1.1); }}
        }}
        
        .two-player-results {{
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 30px;
            margin: 20px 0;
            padding: 20px;
            background: #f8f9fa;
            border-radius: 12px;
        }}
        
        .player-result {{
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: 10px;
        }}
        
        .player-name {{
            font-size: 16px;
            font-weight: 600;
            color: #495057;
        }}
        
        .player-final-score {{
            font-size: 24px;
            font-weight: 700;
            color: #007bff;
        }}
        
        .vs-divider {{
            font-size: 18px;
            font-weight: 700;
            color: #6c757d;
            padding: 0 10px;
        }}
        
        .game-summary {{
            display: flex;
            justify-content: space-between;
            margin-top: 20px;
            padding: 15px;
            background: #e3f2fd;
            border-radius: 8px;
        }}
        
        .summary-item {{
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: 5px;
        }}
        
        .summary-label {{
            font-size: 12px;
            color: #6c757d;
            text-transform: uppercase;
            font-weight: 600;
        }}
        
        .summary-value {{
            font-size: 16px;
            font-weight: 600;
            color: #495057;
        }}
        
        .matching-grid {{
            display: grid;
            gap: 8px;
            padding: 10px;
            justify-content: center;
            width: 100%;
            max-width: 100%;
            box-sizing: border-box;
        }}
        
        .matching-grid.grid-3x4 {{
            grid-template-columns: repeat(4, 1fr);
            aspect-ratio: 4/3;
            width: min(100%, calc(100vh - 280px) * 4/3);
            height: min(calc(100vw - 40px) * 3/4, calc(100vh - 280px));
        }}
        
        .matching-grid.grid-4x4 {{
            grid-template-columns: repeat(4, 1fr);
            aspect-ratio: 1;
            width: min(100%, calc(100vh - 280px));
            height: min(calc(100vw - 40px), calc(100vh - 280px));
        }}
        
        .matching-grid.grid-4x6 {{
            grid-template-columns: repeat(6, 1fr);
            aspect-ratio: 6/4;
            width: min(100%, calc(100vh - 280px) * 6/4);
            height: min(calc(100vw - 40px) * 4/6, calc(100vh - 280px));
        }}
        
        .matching-grid.grid-5x6 {{
            grid-template-columns: repeat(6, 1fr);
            aspect-ratio: 6/5;
            width: min(100%, calc(100vh - 280px) * 6/5);
            height: min(calc(100vw - 40px) * 5/6, calc(100vh - 280px));
        }}
        
        .match-card {{
            aspect-ratio: 1;
            background: #ffffff;
            border: 2px solid #e9ecef;
            border-radius: 8px;
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: center;
            position: relative;
            transition: all 0.3s ease;
            user-select: none;
            width: 100%;
            height: 100%;
            box-sizing: border-box;
        }}
        
        /* Cards automatically size to fill grid cells while maintaining aspect ratio */
        .match-card {{
            /* Let the card fill the grid cell */
            width: 100%;
            height: 100%;
            min-width: 0;
            min-height: 0;
        }}
        
        .match-card:hover {{
            border-color: #007bff;
            transform: translateY(-2px);
            box-shadow: 0 4px 12px rgba(0, 123, 255, 0.2);
        }}
        
        .match-card.flipped {{
            background: #f8f9fa;
            border-color: #007bff;
        }}
        
        .match-card.matched {{
            background: #d4edda;
            border-color: #28a745;
            cursor: default;
            position: relative;
            opacity: 0.7;
            filter: grayscale(20%);
            transform: scale(0.95);
            transition: all 0.3s ease;
        }}
        
        .match-card.matched:hover {{
            transform: scale(0.95);
            box-shadow: none;
            border-color: #28a745;
        }}
        
        .match-card.matched-player1 {{
            background: #cce7ff;
            border-color: #007bff;
            box-shadow: none;
            opacity: 0.7;
            filter: grayscale(20%);
        }}
        
        .match-card.matched-player1:hover {{
            border-color: #007bff;
            box-shadow: none;
        }}
        
        .match-card.matched-player1::before {{
            border-color: #007bff !important;
            background: linear-gradient(45deg, rgba(0, 123, 255, 0.1), rgba(0, 123, 255, 0.05)) !important;
        }}
        
        .match-card.matched-player1::after {{
            background: #007bff !important;
            box-shadow: 0 0 0 1px #007bff, 0 0 8px rgba(0, 123, 255, 0.4) !important;
        }}
        
        .match-card.matched-player2 {{
            background: #ffe6cc;
            border-color: #fd7e14;
            box-shadow: none;
            opacity: 0.7;
            filter: grayscale(20%);
        }}
        
        .match-card.matched-player2:hover {{
            border-color: #fd7e14;
            box-shadow: none;
        }}
        
        .match-card.matched-player2::before {{
            border-color: #fd7e14 !important;
            background: linear-gradient(45deg, rgba(253, 126, 20, 0.1), rgba(253, 126, 20, 0.05)) !important;
        }}
        
        .match-card.matched-player2::after {{
            background: #fd7e14 !important;
            box-shadow: 0 0 0 1px #fd7e14, 0 0 8px rgba(253, 126, 20, 0.4) !important;
        }}
        
        .player-badge {{
            position: absolute;
            top: -8px;
            right: -8px;
            width: 24px;
            height: 24px;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 12px;
            font-weight: 700;
            color: white;
            border: 2px solid white;
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
            z-index: 20;
        }}
        
        .player-badge.player1 {{
            background: #007bff;
        }}
        
        .player-badge.player2 {{
            background: #fd7e14;
        }}
        
        .match-card.matched::after {{
            content: '';
            position: absolute;
            bottom: 3px;
            left: 3px;
            width: 12px;
            height: 12px;
            background: #28a745;
            border: 2px solid white;
            border-radius: 50%;
            box-shadow: 0 0 0 1px #28a745, 0 0 8px rgba(40, 167, 69, 0.4);
            pointer-events: none;
            z-index: 10;
        }}
        
        .match-card.matched::before {{
            content: '';
            position: absolute;
            top: -2px;
            left: -2px;
            right: -2px;
            bottom: -2px;
            border: 2px solid #28a745;
            border-radius: 10px;
            background: linear-gradient(45deg, rgba(40, 167, 69, 0.1), rgba(40, 167, 69, 0.05));
            pointer-events: none;
            z-index: 1;
        }}
        
        .match-card.matched .match-card-content {{
            opacity: 0.6;
        }}
        
        .match-card.invalid-move {{
            animation: invalidMoveShake 0.6s ease-in-out;
            border-color: #dc3545 !important;
        }}
        
        @keyframes invalidMoveShake {{
            0%, 100% {{ transform: translateX(0); }}
            10%, 30%, 50%, 70%, 90% {{ transform: translateX(-3px); }}
            20%, 40%, 60%, 80% {{ transform: translateX(3px); }}
        }}
        
        .match-card.valid-choice {{
            border-color: #28a745 !important;
            box-shadow: 0 0 8px rgba(40, 167, 69, 0.4);
            animation: validChoicePulse 2s infinite;
        }}
        
        .match-card.invalid-choice {{
            opacity: 0.5;
            cursor: not-allowed;
        }}
        
        .match-card.invalid-choice:hover {{
            transform: none;
            box-shadow: none;
        }}
        
        @keyframes validChoicePulse {{
            0%, 100% {{ box-shadow: 0 0 8px rgba(40, 167, 69, 0.4); }}
            50% {{ box-shadow: 0 0 12px rgba(40, 167, 69, 0.7); }}
        }}
        
        @keyframes matchedCard {{
            0% {{ 
                transform: scale(1) rotate(0deg);
                opacity: 1;
            }}
            50% {{ 
                transform: scale(1.1) rotate(2deg);
                opacity: 0.9;
            }}
            100% {{ 
                transform: scale(0.95) rotate(0deg);
                opacity: 0.7;
            }}
        }}
        
        .match-card.matched {{
            animation: matchedCard 0.6s ease-out forwards;
        }}
        
        .match-card-content {{
            display: none;
            width: 100%;
            height: 100%;
            padding: 8px;
        }}
        
        .match-card.flipped .match-card-content,
        .match-card.matched .match-card-content {{
            display: flex;
            align-items: center;
            justify-content: center;
        }}
        
        .match-card-number {{
            font-size: 24px;
            font-weight: bold;
            color: #495057;
        }}
        
        .match-card-abacus {{
            width: 100%;
            height: 100%;
        }}
        
        .match-card-abacus svg {{
            width: 100%;
            height: 100%;
        }}
        
        .match-card-back {{
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            color: white;
            font-size: 14px;
            font-weight: 600;
            gap: 4px;
            border-radius: 6px;
            overflow: hidden;
        }}
        
        .match-card-back.abacus-type {{
            background: linear-gradient(135deg, #6c5ce7, #a29bfe);
        }}
        
        .match-card-back.number-type {{
            background: linear-gradient(135deg, #00b894, #00cec9);
        }}
        
        .match-card-back.friends-5-type {{
            background: linear-gradient(135deg, #ff6b6b, #feca57);
        }}
        
        .match-card-back.friends-10-type {{
            background: linear-gradient(135deg, #667eea, #764ba2);
        }}
        
        .complement-number {{
            font-size: 1.8rem;
            font-weight: bold;
            text-align: center;
            line-height: 1.2;
            white-space: pre-line;
        }}
        
        .match-card-back .card-type-icon {{
            font-size: 40px;
        }}
        
        .match-card.flipped .match-card-back,
        .match-card.matched .match-card-back {{
            display: none;
        }}
        
        .matching-instructions {{
            background: #e3f2fd;
            border: 1px solid #bbdefb;
            border-radius: 8px;
            padding: 15px;
            margin: 0 0 20px 0;
            text-align: center;
        }}
        
        .matching-feedback {{
            background: white;
            border-radius: 12px;
            padding: 20px;
            margin: 20px 0;
            text-align: center;
        }}
        
        @media (max-width: 768px) {{
            .matching-grid {{
                gap: 6px;
                padding: 8px;
            }}
            
            .matching-grid.grid-3x4 {{
                width: min(100%, calc(100vh - 260px) * 4/3);
                height: min(calc(100vw - 30px) * 3/4, calc(100vh - 260px));
            }}
            
            .matching-grid.grid-4x4 {{
                width: min(100%, calc(100vh - 260px));
                height: min(calc(100vw - 30px), calc(100vh - 260px));
            }}
            
            .matching-grid.grid-4x6 {{
                width: min(100%, calc(100vh - 260px) * 6/4);
                height: min(calc(100vw - 30px) * 4/6, calc(100vh - 260px));
            }}
            
            .matching-grid.grid-5x6 {{
                width: min(100%, calc(100vh - 260px) * 6/5);
                height: min(calc(100vw - 30px) * 5/6, calc(100vh - 260px));
            }}
            
            .match-card-number {{
                font-size: 16px;
            }}
            
            .match-card-back .card-type-icon {{
                font-size: 28px;
            }}
            
            .matching-header {{
                padding: 10px 15px;
                margin: 0 -20px 10px -20px;
            }}
            
            .matching-instructions {{
                padding: 12px;
                margin: 0 0 15px 0;
                font-size: 14px;
            }}
            
            .start-game-btn {{
                min-height: 60px;
                padding: 12px 16px;
            }}
            
            .start-game-btn .btn-main {{
                font-size: 14px;
            }}
            
            .start-game-btn .btn-sub {{
                font-size: 12px;
            }}
        }}
        
        @media (max-width: 480px) {{
            .matching-grid {{
                gap: 4px;
                padding: 5px;
            }}
            
            .matching-grid.grid-3x4 {{
                width: min(100%, calc(100vh - 240px) * 4/3);
                height: min(calc(100vw - 20px) * 3/4, calc(100vh - 240px));
            }}
            
            .matching-grid.grid-4x4 {{
                width: min(100%, calc(100vh - 240px));
                height: min(calc(100vw - 20px), calc(100vh - 240px));
            }}
            
            .matching-grid.grid-4x6 {{
                width: min(100%, calc(100vh - 240px) * 6/4);
                height: min(calc(100vw - 20px) * 4/6, calc(100vh - 240px));
            }}
            
            .matching-grid.grid-5x6 {{
                width: min(100%, calc(100vh - 240px) * 6/5);
                height: min(calc(100vw - 20px) * 5/6, calc(100vh - 240px));
            }}
            
            .match-card-number {{
                font-size: 14px;
            }}
            
            .match-card-back .card-type-icon {{
                font-size: 24px;
            }}
            
            .start-game-btn {{
                min-height: 50px;
                padding: 10px 12px;
            }}
            
            .start-game-btn .btn-main {{
                font-size: 13px;
            }}
            
            .start-game-btn .btn-sub {{
                font-size: 11px;
            }}
            
            .match-card.matched::after {{
                width: 10px;
                height: 10px;
                bottom: 2px;
                left: 2px;
            }}
        }}
        
        /* Modal Styling */
        .modal {{
            display: none;
            position: fixed;
            z-index: 1000;
            left: 0;
            top: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.5);
            animation: fadeIn 0.3s ease-out;
        }}
        
        .modal.show {{
            display: flex;
            align-items: center;
            justify-content: center;
        }}
        
        .modal-content {{
            background: white;
            border-radius: 12px;
            width: 90%;
            max-width: 900px;
            max-height: 90vh;
            display: flex;
            flex-direction: column;
            animation: slideIn 0.3s ease-out;
            box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
        }}
        
        .modal-header {{
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 20px 30px;
            border-bottom: 1px solid #eee;
            background: linear-gradient(135deg, #f8f9fa, #e9ecef);
            border-radius: 12px 12px 0 0;
        }}
        
        .modal-header h2 {{
            margin: 0;
            color: #333;
        }}
        
        .modal-controls {{
            display: flex;
            gap: 10px;
        }}
        
        .fullscreen-btn, .close-btn {{
            background: none;
            border: none;
            font-size: 24px;
            cursor: pointer;
            padding: 5px 10px;
            border-radius: 6px;
            transition: background 0.2s ease;
        }}
        
        .fullscreen-btn:hover, .close-btn:hover {{
            background: rgba(0, 0, 0, 0.1);
        }}
        
        .close-btn {{
            color: #666;
        }}
        
        .close-btn:hover {{
            color: #333;
        }}
        
        .modal-body {{
            padding: 30px;
            flex: 1;
            overflow-y: auto;
        }}
        
        /* Fullscreen modal styling */
        .modal.fullscreen {{
            background: rgba(0, 0, 0, 0.95);
        }}
        
        .modal.fullscreen .modal-content {{
            width: 100%;
            height: 100%;
            max-width: none;
            max-height: none;
            border-radius: 0;
        }}
        
        .modal.fullscreen .modal-header {{
            border-radius: 0;
        }}
        
        /* Animations */
        @keyframes fadeIn {{
            from {{ opacity: 0; }}
            to {{ opacity: 1; }}
        }}
        
        @keyframes slideIn {{
            from {{ transform: scale(0.9) translateY(-20px); opacity: 0; }}
            to {{ transform: scale(1) translateY(0); opacity: 1; }}
        }}
        
        /* Speed Complement Race Enhanced UI Styles */
        .complement-intro {{
            text-align: center;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 30px;
            border-radius: 15px;
            margin-bottom: 30px;
            position: relative;
            overflow: hidden;
        }}
        
        .complement-intro::before {{
            content: '';
            position: absolute;
            top: -50%;
            left: -50%;
            width: 200%;
            height: 200%;
            background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><circle cx="20" cy="20" r="2" fill="white" opacity="0.1"/><circle cx="80" cy="30" r="1.5" fill="white" opacity="0.1"/><circle cx="60" cy="70" r="1" fill="white" opacity="0.15"/></svg>');
            animation: float 15s ease-in-out infinite;
        }}
        
        .intro-icon {{
            font-size: 4rem;
            margin-bottom: 15px;
            display: block;
            filter: drop-shadow(0 4px 8px rgba(0,0,0,0.3));
        }}
        
        .complement-intro h3 {{
            margin: 0 0 15px 0;
            font-size: 2rem;
            font-weight: 700;
            text-shadow: 0 2px 4px rgba(0,0,0,0.3);
            position: relative;
            z-index: 1;
        }}
        
        .intro-description {{
            font-size: 1.1rem;
            margin-bottom: 25px;
            opacity: 0.95;
            position: relative;
            z-index: 1;
            line-height: 1.4;
        }}
        
        .example-demo {{
            background: rgba(255, 255, 255, 0.15);
            border-radius: 12px;
            padding: 20px;
            backdrop-filter: blur(10px);
            position: relative;
            z-index: 1;
        }}
        
        .demo-equation {{
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 15px;
            margin-bottom: 10px;
            font-size: 2rem;
            font-weight: bold;
        }}
        
        .demo-number {{
            background: #ff6b6b;
            color: white;
            padding: 10px 15px;
            border-radius: 10px;
            box-shadow: 0 4px 8px rgba(0,0,0,0.2);
        }}
        
        .demo-answer {{
            background: #feca57;
            color: #333;
            padding: 10px 15px;
            border-radius: 10px;
            box-shadow: 0 4px 8px rgba(0,0,0,0.2);
            animation: pulse 2s infinite;
        }}
        
        .demo-target {{
            background: #48dbfb;
            color: white;
            padding: 10px 15px;
            border-radius: 10px;
            box-shadow: 0 4px 8px rgba(0,0,0,0.2);
        }}
        
        .demo-plus, .demo-equals {{
            color: white;
            font-weight: bold;
            text-shadow: 0 2px 4px rgba(0,0,0,0.3);
        }}
        
        .demo-instruction {{
            font-size: 1.1rem;
            color: #fff;
            opacity: 0.9;
        }}
        
        /* Enhanced Game Display */
        .complement-display {{
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            border-radius: 20px;
            padding: 40px;
            margin-bottom: 30px;
            color: white;
            position: relative;
            overflow: hidden;
            box-shadow: 0 20px 40px rgba(102, 126, 234, 0.3);
        }}
        
        .complement-display::before {{
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><circle cx="25" cy="25" r="1" fill="white" opacity="0.1"/><circle cx="75" cy="75" r="1" fill="white" opacity="0.1"/></svg>');
            pointer-events: none;
        }}
        
        .challenge-prompt {{
            text-align: center;
            position: relative;
            z-index: 1;
            margin-bottom: 30px;
        }}
        
        
        /* Coal Spilling Animation */
        @keyframes coalSpill {{
            0% {{
                transform: translateY(0px) rotate(0deg);
                opacity: 1;
            }}
            50% {{
                transform: translateY(40px) translateX(20px) rotate(180deg);
                opacity: 0.8;
            }}
            100% {{
                transform: translateY(80px) translateX(40px) rotate(360deg);
                opacity: 0;
            }}
        }}
        
        .coal-chunk {{
            color: #2c2c2c;
            text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
        }}
        
        /* Pressure Alarm Animation */
        @keyframes pressureAlarm {{
            0%, 100% {{
                filter: brightness(1) saturate(1);
                transform: scale(1);
            }}
            25% {{
                filter: brightness(1.5) saturate(2) hue-rotate(0deg);
                transform: scale(1.05);
            }}
            50% {{
                filter: brightness(2) saturate(3) hue-rotate(15deg);
                transform: scale(1.1);
            }}
            75% {{
                filter: brightness(1.5) saturate(2) hue-rotate(-15deg);
                transform: scale(1.05);
            }}
        }}
        
        /* Route Completion Celebration */
        .route-completion-celebration {{
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.8);
            display: flex;
            align-items: center;
            justify-content: center;
            z-index: 1000;
            animation: celebrationFadeIn 0.5s ease-out;
        }}
        
        .celebration-content {{
            background: linear-gradient(135deg, #ffd700, #ffed4e);
            color: #333;
            padding: 40px;
            border-radius: 20px;
            text-align: center;
            box-shadow: 0 20px 40px rgba(255, 215, 0, 0.3);
            animation: celebrationBounce 0.8s ease-out;
            max-width: 400px;
        }}
        
        .celebration-content h2 {{
            margin: 0 0 15px 0;
            font-size: 1.8rem;
            font-weight: 700;
        }}
        
        .celebration-content p {{
            margin: 0 0 20px 0;
            font-size: 1.1rem;
            font-weight: 600;
        }}
        
        .progress-stats {{
            display: flex;
            flex-direction: column;
            gap: 8px;
            font-size: 0.95rem;
            font-weight: 600;
        }}
        
        .progress-stats div {{
            background: rgba(255, 255, 255, 0.3);
            padding: 8px 12px;
            border-radius: 8px;
        }}
        
        @keyframes celebrationFadeIn {{
            from {{
                opacity: 0;
            }}
            to {{
                opacity: 1;
            }}
        }}
        
        @keyframes celebrationBounce {{
            0% {{
                transform: scale(0.3) rotate(-10deg);
                opacity: 0;
            }}
            50% {{
                transform: scale(1.05) rotate(2deg);
            }}
            100% {{
                transform: scale(1) rotate(0deg);
                opacity: 1;
            }}
        }}
        
        
        .equation-visual {{
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 25px;
            flex-wrap: wrap;
        }}
        
        .challenge-number-container,
        .answer-container,
        .target-container {{
            text-align: center;
            position: relative;
        }}
        
        .challenge-number {{
            font-size: 4rem;
            font-weight: 700;
            background: linear-gradient(135deg, #ff6b6b, #feca57);
            color: white;
            padding: 20px 25px;
            border-radius: 20px;
            box-shadow: 0 10px 25px rgba(255, 107, 107, 0.4);
            text-shadow: 0 2px 4px rgba(0,0,0,0.3);
            animation: bounceIn 1s ease-out;
        }}
        
        .answer-display {{
            font-size: 4rem;
            font-weight: 700;
            background: linear-gradient(135deg, #feca57, #ff9ff3);
            color: white;
            padding: 20px 25px;
            border-radius: 20px;
            box-shadow: 0 10px 25px rgba(254, 202, 87, 0.4);
            text-shadow: 0 2px 4px rgba(0,0,0,0.3);
            text-align: center;
            min-width: 100px;
            display: flex;
            align-items: center;
            justify-content: center;
            animation: pulse 2s infinite;
            transition: all 0.3s ease;
            user-select: none;
        }}
        
        .answer-display.typing {{
            animation: none;
            transform: scale(1.1);
            box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.3), 0 15px 35px rgba(254, 202, 87, 0.6);
            background: linear-gradient(135deg, #ff9ff3, #feca57);
        }}
        
        .answer-display.empty {{
            color: rgba(255, 255, 255, 0.7);
        }}
        
        .target-number {{
            font-size: 4rem;
            font-weight: 700;
            background: linear-gradient(135deg, #48dbfb, #0abde3);
            color: white;
            padding: 20px 25px;
            border-radius: 20px;
            box-shadow: 0 10px 25px rgba(72, 219, 251, 0.4);
            text-shadow: 0 2px 4px rgba(0,0,0,0.3);
        }}
        
        .equation-symbol {{
            font-size: 3rem;
            font-weight: bold;
            color: white;
            text-shadow: 0 2px 4px rgba(0,0,0,0.3);
        }}
        
        .number-label,
        .answer-label,
        .target-label {{
            font-size: 0.9rem;
            margin-top: 8px;
            opacity: 0.8;
            font-weight: 500;
            text-transform: uppercase;
            letter-spacing: 1px;
        }}
        
        .answer-arrow {{
            font-size: 1.5rem;
            margin-top: 5px;
            animation: bounce 1s infinite;
        }}
        
        /* Enhanced Timer */
        .timer-section {{
            text-align: center;
            position: relative;
            z-index: 1;
        }}
        
        .timer-label {{
            font-size: 1.1rem;
            margin-bottom: 10px;
            opacity: 0.9;
            font-weight: 500;
        }}
        
        .timer-bar {{
            background: rgba(255, 255, 255, 0.2);
            height: 12px;
            border-radius: 25px;
            overflow: hidden;
            margin-bottom: 10px;
            box-shadow: inset 0 2px 4px rgba(0,0,0,0.2);
        }}
        
        .timer-fill {{
            height: 100%;
            background: linear-gradient(90deg, #ff6b6b, #feca57, #ff6b6b);
            border-radius: 25px;
            transition: width 0.1s linear;
            box-shadow: 0 0 10px rgba(255, 107, 107, 0.6);
            animation: shimmer 2s infinite;
        }}
        
        .timer-text {{
            font-size: 1.3rem;
            font-weight: bold;
            text-shadow: 0 2px 4px rgba(0,0,0,0.3);
        }}
        
        /* Race Track Styles */
        .race-track-section {{
            margin-top: 25px;
            padding: 50px 150px 20px 150px;
            background: rgba(255, 255, 255, 0.1);
            border-radius: 15px;
            border: 2px solid rgba(255, 255, 255, 0.2);
        }}
        
        @media (max-width: 768px) {{
            .race-track-section {{
                padding: 30px 80px 20px 80px;
            }}
        }}
        
        @media (max-width: 480px) {{
            .race-track-section {{
                padding: 30px 40px 20px 40px;
            }}
        }}
        
        .race-label {{
            text-align: center;
            font-size: 1.2rem;
            font-weight: bold;
            margin-bottom: 20px;
            color: white;
            text-shadow: 0 2px 4px rgba(0,0,0,0.3);
        }}
        
        .race-track {{
            position: relative;
            height: 150px;
            background: linear-gradient(to right, #4CAF50 0%, #8BC34A 25%, #CDDC39 50%, #FFC107 75%, #FF5722 100%);
            border-radius: 60px;
            margin: 0;
            overflow: visible;
            box-shadow: inset 0 4px 8px rgba(0,0,0,0.2), 0 4px 12px rgba(0,0,0,0.3);
        }}
        
        .track-background {{
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: repeating-linear-gradient(
                90deg,
                transparent 0px,
                transparent 18px,
                rgba(255,255,255,0.1) 18px,
                rgba(255,255,255,0.1) 20px
            );
            border-radius: 60px;
            overflow: hidden;
        }}
        
        .track-line {{
            position: absolute;
            top: 0;
            bottom: 0;
            width: 3px;
            background: rgba(255, 255, 255, 0.6);
            box-shadow: 0 0 6px rgba(255,255,255,0.8);
        }}
        
        .start-line {{ left: 5%; }}
        .quarter-line {{ left: 25%; opacity: 0.5; }}
        .half-line {{ left: 50%; }}
        .three-quarter-line {{ left: 75%; opacity: 0.5; }}
        .finish-line {{ left: 95%; }}
        
        .racer {{
            position: absolute;
            width: 50px;
            height: 50px;
            background: white;
            border-radius: 50%;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            transition: left 0.6s ease-out, transform 0.3s ease;
            cursor: pointer;
            box-shadow: 0 4px 12px rgba(0,0,0,0.3);
            left: 2%;
            z-index: 10;
        }}
        
        .racer:hover {{
            transform: scale(1.1);
        }}
        
        .player-racer {{
            top: 10px;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            border: 3px solid #FFD700;
            z-index: 10;
        }}
        
        .ai-racer {{
            background: linear-gradient(135deg, #ff6b6b 0%, #feca57 100%);
            border: 2px solid #ff4757;
        }}
        
        #ai-racer-1 {{
            top: 35px;
            z-index: 8;
        }}
        
        #ai-racer-2 {{
            top: 60px;
            z-index: 9;
        }}
        
        .racer-character {{
            font-size: 1.5rem;
            line-height: 1;
            animation: bounce 1s infinite alternate;
        }}
        
        .racer-label {{
            position: absolute;
            bottom: -25px;
            left: 50%;
            transform: translateX(-50%);
            font-size: 0.75rem;
            font-weight: bold;
            color: white;
            background: rgba(0,0,0,0.7);
            padding: 2px 6px;
            border-radius: 8px;
            white-space: nowrap;
            text-shadow: none;
        }}
        
        .racer-progress {{
            position: absolute;
            top: -20px;
            left: 50%;
            transform: translateX(-50%);
            font-size: 0.7rem;
            font-weight: bold;
            color: #FFD700;
            background: rgba(0,0,0,0.8);
            padding: 1px 4px;
            border-radius: 6px;
            text-shadow: none;
        }}
        
        .finish-zone {{
            position: absolute;
            right: 0;
            top: 0;
            bottom: 0;
            width: 60px;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%);
            border-top-right-radius: 60px;
            border-bottom-right-radius: 60px;
            border-top-left-radius: 0;
            border-bottom-left-radius: 0;
            z-index: 2;
        }}
        
        .finish-flag {{
            font-size: 1.5rem;
            animation: wave 1s infinite ease-in-out;
        }}
        
        .finish-text {{
            font-size: 0.6rem;
            font-weight: bold;
            color: #333;
            text-shadow: 0 1px 2px rgba(255,255,255,0.8);
            transform: rotate(-90deg);
            margin-top: 5px;
        }}
        
        .race-stats {{
            display: flex;
            justify-content: center;
            gap: 30px;
            margin-top: 15px;
            color: white;
        }}
        
        .race-stat {{
            text-align: center;
            background: rgba(255, 255, 255, 0.1);
            padding: 8px 15px;
            border-radius: 15px;
            border: 1px solid rgba(255, 255, 255, 0.2);
        }}
        
        .race-stat .stat-label {{
            font-size: 0.85rem;
            opacity: 0.9;
            margin-right: 5px;
        }}
        
        /* Race Animations */
        @keyframes bounce {{
            0% {{ transform: translateY(0); }}
            100% {{ transform: translateY(-3px); }}
        }}
        
        @keyframes wave {{
            0%, 100% {{ transform: rotate(-10deg); }}
            50% {{ transform: rotate(10deg); }}
        }}
        
        /* Circular Track for Survival Mode */
        .race-track-section.circular-track {{
            display: flex;
            justify-content: center;
            align-items: center;
            padding: 40px;
            /* Prevent container from affecting track shape */
            flex-shrink: 0;
        }}
        
        /* Infinite Mode Track for Sprint Mode */
        .race-track-section.infinite-mode {{
            background: linear-gradient(90deg, #667eea 0%, #764ba2 50%, #667eea 100%);
            position: relative;
        }}
        
        .race-track-section.infinite-mode::before {{
            content: '⚡ TIME-BASED CHALLENGE ⚡';
            position: absolute;
            top: 10px;
            left: 50%;
            transform: translateX(-50%);
            background: rgba(255, 215, 0, 0.9);
            color: #333;
            padding: 8px 16px;
            border-radius: 20px;
            font-size: 0.85rem;
            font-weight: 600;
            letter-spacing: 1px;
            z-index: 10;
        }}
        
        .race-track-section.infinite-mode .race-track {{
            background: linear-gradient(90deg, 
                transparent 0%, 
                rgba(255,255,255,0.1) 10%, 
                rgba(255,255,255,0.2) 50%, 
                rgba(255,255,255,0.1) 90%, 
                transparent 100%);
            border: 2px dashed rgba(255, 215, 0, 0.6);
        }}
        
        /* Steam Train Journey Visualization for Sprint Mode */
        .race-track-section.steam-journey {{
            /* Dynamic sky gradient based on time of day with smooth transitions */
            background: var(--sky-gradient, var(--dawn-gradient));
            transition: --sky-gradient 3s ease-in-out, background 2s ease-out;
            padding: 20px;
            height: 400px;
            max-height: 400px;
            position: relative;
            overflow: hidden;
        }}
        
        
        /* Underground tunnel visualization */
        .tunnel-container {{
            display: flex;
            justify-content: space-around;
            align-items: flex-start;
            padding: 60px 40px 20px;
            height: 100%;
            position: relative;
            max-height: 240px; /* Constrain to fit in container */
        }}
        
        .tunnel-shaft {{
            width: 80px;
            background: #4a4a4a;
            border: 3px solid #333;
            border-radius: 8px;
            position: relative;
            min-height: 50px;
            transition: height 0.3s ease-out;
            box-shadow: inset 0 0 20px rgba(0,0,0,0.5);
        }}
        
        .tunnel-shaft::before {{
            content: '';
            position: absolute;
            top: -20px;
            left: 50%;
            transform: translateX(-50%);
            width: 60px;
            height: 20px;
            background: #90EE90;
            border-radius: 50%;
            border: 2px solid #6B8E23;
        }}
        
        .fox-digger {{
            position: absolute;
            bottom: 10px; /* Position inside tunnel, not at the bottom */
            left: 50%;
            transform: translateX(-50%);
            font-size: 2rem;
            z-index: 5;
            transition: all 0.3s ease;
        }}
        
        .fox-digger.digging {{
            animation: foxDigging 0.6s ease-in-out;
        }}
        
        .fox-digger.idle {{
            animation: foxBreathe 2s ease-in-out infinite;
        }}
        
        /* Active digging animation */
        @keyframes foxDigging {{
            0% {{ 
                transform: translateX(-50%) translateY(0) rotate(0deg);
            }}
            20% {{ 
                transform: translateX(-50%) translateY(-8px) rotate(-10deg) scaleY(0.9);
            }}
            40% {{ 
                transform: translateX(-50%) translateY(8px) rotate(10deg) scaleY(1.1);
            }}
            60% {{ 
                transform: translateX(-50%) translateY(-5px) rotate(-5deg) scaleY(0.95);
            }}
            80% {{ 
                transform: translateX(-50%) translateY(3px) rotate(5deg) scaleY(1.05);
            }}
            100% {{ 
                transform: translateX(-50%) translateY(0) rotate(0deg);
            }}
        }}
        
        /* Breathing animation when idle */
        @keyframes foxBreathe {{
            0%, 100% {{ 
                transform: translateX(-50%) scale(1);
            }}
            50% {{ 
                transform: translateX(-50%) scale(1.02);
            }}
        }}
        
        /* Deeper foxes appear smaller (perspective effect) */
        .tunnel-shaft.depth-deep .fox-digger {{
            font-size: 1.8rem;
            bottom: 15px;
        }}
        
        .tunnel-shaft.depth-very-deep .fox-digger {{
            font-size: 1.6rem;
            bottom: 20px;
            animation: foxDigDeep 0.8s ease-in-out;
        }}
        
        @keyframes foxDigDeep {{
            0% {{ 
                transform: translateX(-50%) translateY(0) rotate(0deg) scale(1);
            }}
            25% {{ 
                transform: translateX(-50%) translateY(-10px) rotate(-15deg) scale(0.9) scaleY(0.8);
            }}
            50% {{ 
                transform: translateX(-50%) translateY(10px) rotate(15deg) scale(1.1) scaleY(1.2);
            }}
            75% {{ 
                transform: translateX(-50%) translateY(-5px) rotate(-8deg) scale(0.95);
            }}
            100% {{ 
                transform: translateX(-50%) translateY(0) rotate(0deg) scale(1);
            }}
        }}
        
        .tunnel-depth {{
            position: absolute;
            bottom: -25px;
            left: 50%;
            transform: translateX(-50%);
            background: rgba(255, 255, 255, 0.9);
            color: #333;
            padding: 4px 8px;
            border-radius: 12px;
            font-size: 0.8rem;
            font-weight: 600;
            min-width: 40px;
            text-align: center;
        }}
        
        .tunnel-player .tunnel-depth {{
            background: rgba(34, 197, 94, 0.9);
            color: white;
        }}
        
        .tunnel-ai .tunnel-depth {{
            background: rgba(239, 68, 68, 0.9);
            color: white;
        }}
        
        /* Dirt particles effect when digging */
        @keyframes dirtFly {{
            0% {{
                opacity: 1;
                transform: translate(0, 0) scale(1);
            }}
            100% {{
                opacity: 0;
                transform: translate(var(--fly-x), var(--fly-y)) scale(0.3);
            }}
        }}
        
        .dirt-particle {{
            position: absolute;
            width: 4px;
            height: 4px;
            background: #8B4513;
            border-radius: 50%;
            animation: dirtFly 0.6s ease-out forwards;
            pointer-events: none;
        }}
        
        /* Treasure animations */
        @keyframes treasureFloat {{
            0% {{
                opacity: 0;
                transform: translate(-50%, 0) scale(0);
            }}
            20% {{
                opacity: 1;
                transform: translate(-50%, -20px) scale(1.2);
            }}
            100% {{
                opacity: 0;
                transform: translate(-50%, -80px) scale(0.8);
            }}
        }}
        
        @keyframes treasureSlideIn {{
            0% {{
                opacity: 0;
                transform: translateX(100px);
            }}
            20% {{
                opacity: 1;
                transform: translateX(0);
            }}
            80% {{
                opacity: 1;
                transform: translateX(0);
            }}
            100% {{
                opacity: 0;
                transform: translateX(-100px);
            }}
        }}
        
        /* Speech bubbles for tunnel mode */
        .tunnel-speech {{
            position: absolute;
            top: -40px;
            left: 50%;
            transform: translateX(-50%);
        }}
        
        /* Screen shake animation for deep digging */
        @keyframes screenShake {{
            0%, 100% {{ transform: translateX(0); }}
            25% {{ transform: translateX(-2px); }}
            75% {{ transform: translateX(2px); }}
        }}
        
        /* Day/Night Cycle CSS Variables */
        :root {{
            /* Dawn (0-17%) */
            --dawn-gradient: linear-gradient(180deg, 
                #4a5568 0%, #667eea 20%, #f093fb 40%, #f5deb3 60%, #90EE90 80%, #654321 100%);
            /* Morning (17-33%) */
            --morning-gradient: linear-gradient(180deg, 
                #87ceeb 0%, #f0e68c 20%, #90EE90 50%, #8FBC8F 80%, #654321 100%);
            /* Midday (33-67%) */
            --midday-gradient: linear-gradient(180deg, 
                #87ceeb 0%, #87ceeb 30%, #90EE90 60%, #228B22 80%, #654321 100%);
            /* Afternoon (67-83%) */
            --afternoon-gradient: linear-gradient(180deg, 
                #ff7f50 0%, #ffd700 20%, #90EE90 50%, #8B4513 80%, #654321 100%);
            /* Dusk (83-92%) */
            --dusk-gradient: linear-gradient(180deg, 
                #4b0082 0%, #ff6347 30%, #ffa500 50%, #8B4513 70%, #2f4f4f 100%);
            /* Night (92-100%) */
            --night-gradient: linear-gradient(180deg, 
                #191970 0%, #2f4f4f 40%, #1a1a1a 70%, #000000 100%);
        }}
        
        .steam-journey-header {{
            position: absolute;
            top: 10px;
            left: 50%;
            transform: translateX(-50%);
            background: rgba(255, 215, 0, 0.95);
            color: #333;
            padding: 8px 16px;
            border-radius: 20px;
            font-size: 0.9rem;
            font-weight: 700;
            letter-spacing: 1px;
            z-index: 10;
            box-shadow: 0 4px 12px rgba(0,0,0,0.3);
            text-align: center;
        }}
        
        .route-progress {{
            font-size: 0.75rem;
            font-weight: 600;
            margin-top: 4px;
            opacity: 0.8;
            letter-spacing: 0.5px;
        }}
        
        /* Winding Route Map */
        .route-map {{
            position: relative;
            width: 100%;
            height: 350px;
            overflow: hidden;
        }}
        
        .route-path {{
            position: absolute;
            width: 800px;
            height: 600px;
            top: -100px;
            left: 50%;
            transform: translateX(-50%);
        }}
        
        /* SVG path for the winding route */
        .train-route {{
            fill: none;
            stroke: #8B4513;
            stroke-width: 8;
            stroke-dasharray: 15, 5;
            stroke-linecap: round;
        }}
        
        .train-route-bg {{
            fill: none;
            stroke: #654321;
            stroke-width: 12;
            stroke-linecap: round;
        }}
        
        /* Train locomotive on the route */
        .train-locomotive {{
            position: absolute;
            width: 60px;
            height: 40px;
            background: linear-gradient(135deg, #2c3e50, #34495e);
            border-radius: 8px;
            border: 2px solid #1a252f;
            box-shadow: 0 3px 10px rgba(0,0,0,0.4);
            transition: transform 0.2s ease-out, left 0.1s linear, top 0.1s linear;
            transform-origin: center center;
            z-index: 5;
            /* Start at the beginning of the route */
            left: 50px;
            top: 300px;
            transform: translate(-50%, -50%);
        }}
        
        .train-locomotive::before {{
            content: '🚂';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%) scaleX(-1);
            font-size: 1.8rem;
            z-index: 6;
        }}
        
        .train-math-display {{
            position: absolute;
            background: rgba(255, 255, 255, 0.95);
            border: 2px solid #4a90e2;
            border-radius: 12px;
            padding: 8px 12px;
            font-size: 1.2rem;
            font-weight: bold;
            color: #333;
            box-shadow: 0 4px 12px rgba(0,0,0,0.2);
            z-index: 7;
            pointer-events: none;
            white-space: nowrap;
            transform: translate(-50%, -100%);
            font-family: 'Arial', sans-serif;
        }}
        
        /* Steam Pressure Instrument Panel */
        .instrument-panel {{
            position: absolute;
            bottom: 20px;
            left: 20px;
            z-index: 10;
        }}
        
        .panel-frame {{
            background: linear-gradient(135deg, #667eea, #764ba2);
            border: 3px solid #5a67d8;
            border-radius: 20px;
            padding: 18px;
            box-shadow: 
                0 10px 30px rgba(102, 126, 234, 0.3),
                inset 0 2px 8px rgba(255, 255, 255, 0.2);
            position: relative;
        }}
        
        .panel-background {{
            position: absolute;
            top: 6px;
            left: 6px;
            right: 6px;
            bottom: 6px;
            background: linear-gradient(45deg, #667eea, #764ba2);
            border-radius: 12px;
            border: 2px solid rgba(255, 255, 255, 0.1);
        }}
        
        .pressure-gauge-container {{
            position: relative;
            z-index: 2;
            text-align: center;
        }}
        
        .pressure-gauge {{
            display: block;
            margin: 0 auto 10px auto;
            filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.3));
        }}
        
        .gauge-background {{
            filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.4));
        }}
        
        .gauge-progress {{
            transition: stroke-dashoffset 0.5s ease-out;
            filter: drop-shadow(0 0 8px rgba(231, 76, 60, 0.6));
        }}
        
        .pressure-needle {{
            transition: transform 0.5s ease-out;
            transform-origin: 100px 100px;
        }}
        
        .gauge-title {{
            color: #ffffff;
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            font-size: 0.8rem;
            font-weight: 700;
            text-transform: uppercase;
            letter-spacing: 0.5px;
            margin-bottom: 5px;
            text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
        }}
        
        .gauge-value {{
            color: #ffd700;
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            font-size: 0.9rem;
            font-weight: 800;
            text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
        }}
        
        /* Momentum gauge */
        .momentum-display {{
            position: absolute;
            bottom: 20px;
            left: 50%;
            transform: translateX(-50%);
            width: 200px;
            z-index: 10;
        }}
        
        .momentum-gauge {{
            width: 100%;
            height: 12px;
            background: rgba(0,0,0,0.3);
            border-radius: 6px;
            border: 1px solid #333;
            overflow: hidden;
        }}
        
        .momentum-bar {{
            height: 100%;
            background: linear-gradient(90deg, #e74c3c 0%, #f39c12 30%, #27ae60 100%);
            transition: width 0.3s ease-out;
            width: 0%;
        }}
        
        .momentum-label {{
            text-align: center;
            color: white;
            font-size: 0.8rem;
            font-weight: 600;
            margin-top: 5px;
            text-shadow: 1px 1px 2px rgba(0,0,0,0.8);
        }}
        
        /* City stations along the route */
        .train-station {{
            position: absolute;
            width: 20px;
            height: 20px;
            background: #8B4513;
            border: 2px solid #654321;
            border-radius: 50%;
            transform: translate(-50%, -50%);
            z-index: 4;
        }}
        
        .train-station::after {{
            content: attr(data-city);
            position: absolute;
            top: 25px;
            left: 50%;
            transform: translateX(-50%);
            background: rgba(0,0,0,0.7);
            color: white;
            padding: 2px 6px;
            border-radius: 8px;
            font-size: 0.7rem;
            white-space: nowrap;
            font-weight: 600;
        }}
        
        .train-station.active {{
            background: #ffd700;
            border-color: #ffb347;
            animation: stationPulse 1s ease-in-out infinite alternate;
        }}
        
        @keyframes stationPulse {{
            0% {{ transform: translate(-50%, -50%) scale(1); }}
            100% {{ transform: translate(-50%, -50%) scale(1.2); }}
        }}
        
        /* Passenger car display */
        .passenger-car {{
            position: absolute;
            bottom: 60px;
            right: 20px;
            background: rgba(255,255,255,0.9);
            border-radius: 10px;
            padding: 10px;
            min-width: 150px;
            box-shadow: 0 4px 12px rgba(0,0,0,0.3);
        }}
        
        .passenger-car h4 {{
            margin: 0 0 8px 0;
            font-size: 0.9rem;
            color: #333;
        }}
        
        .passenger-list {{
            display: flex;
            flex-wrap: wrap;
            gap: 5px;
        }}
        
        .passenger {{
            background: #667eea;
            color: white;
            padding: 2px 6px;
            border-radius: 12px;
            font-size: 0.7rem;
            font-weight: 600;
        }}
        
        .passenger.urgent {{
            background: #e74c3c;
            animation: passengerUrgent 1s ease-in-out infinite alternate;
        }}
        
        @keyframes passengerUrgent {{
            0% {{ opacity: 1; }}
            100% {{ opacity: 0.6; }}
        }}
        
        /* Coal shoveling animation - enhanced */
        .coal-shoveler {{
            position: absolute;
            bottom: 80px;
            left: 30px;
            font-size: 2rem;
            z-index: 6;
            transition: all 0.3s ease;
        }}
        
        .coal-shoveler.shoveling {{
            animation: shoveling 0.8s ease-in-out;
        }}
        
        @keyframes shoveling {{
            0% {{ transform: rotate(0deg) scale(1); }}
            20% {{ transform: rotate(-25deg) scale(0.9); }}
            40% {{ transform: rotate(25deg) scale(1.2); filter: brightness(1.3); }}
            60% {{ transform: rotate(-15deg) scale(1.1); }}
            80% {{ transform: rotate(10deg) scale(1.05); }}
            100% {{ transform: rotate(0deg) scale(1); }}
        }}
        
        /* Coal particles effect */
        .coal-particle {{
            position: absolute;
            background: #2c2c2c;
            border-radius: 50%;
            pointer-events: none;
            z-index: 4;
        }}
        
        @keyframes coalFly {{
            0% {{
                transform: translate(0, 0) scale(1);
                opacity: 1;
            }}
            50% {{
                transform: translate(-20px, -30px) scale(0.8);
                opacity: 0.8;
            }}
            100% {{
                transform: translate(-40px, -60px) scale(0.3);
                opacity: 0;
            }}
        }}
        
        /* Steam puffs from locomotive */
        .steam-puff {{
            position: absolute;
            background: rgba(255, 255, 255, 0.8);
            border-radius: 50%;
            pointer-events: none;
            z-index: 3;
        }}
        
        @keyframes steamRise {{
            0% {{
                transform: translate(0, 0) scale(0.5);
                opacity: 0.9;
            }}
            50% {{
                transform: translate(10px, -40px) scale(1.2);
                opacity: 0.6;
            }}
            100% {{
                transform: translate(20px, -80px) scale(2);
                opacity: 0;
            }}
        }}
        
        /* Momentum bar flash effect */
        .momentum-boost {{
            animation: momentumBoost 0.8s ease-out;
        }}
        
        @keyframes momentumBoost {{
            0% {{ 
                box-shadow: 0 0 0px rgba(40, 167, 69, 0.6);
                transform: scale(1);
            }}
            30% {{ 
                box-shadow: 0 0 20px rgba(40, 167, 69, 0.8);
                transform: scale(1.05);
            }}
            100% {{ 
                box-shadow: 0 0 5px rgba(40, 167, 69, 0.3);
                transform: scale(1);
            }}
        }}
        
        /* Steam effects */
        .steam-effect {{
            position: absolute;
            top: 10px;
            left: 30px;
            width: 8px;
            height: 8px;
            background: rgba(255,255,255,0.8);
            border-radius: 50%;
            animation: steamRise 2s ease-out infinite;
            z-index: 3;
        }}
        
        @keyframes steamRise {{
            0% {{
                opacity: 0.8;
                transform: translateY(0) scale(0.5);
            }}
            100% {{
                opacity: 0;
                transform: translateY(-60px) scale(2);
            }}
        }}
        
        /* Geographical landmarks */
        .landmark {{
            position: absolute;
            font-size: 1.5rem;
            z-index: 2;
            opacity: 0.7;
        }}
        
        .landmark.mountain {{ font-size: 2rem; }}
        .landmark.tree {{ font-size: 1.2rem; }}
        .landmark.bridge {{ font-size: 1.8rem; }}
        
        /* Time of day indicator */
        .time-display {{
            position: absolute;
            top: 20px;
            right: 20px;
            background: rgba(0,0,0,0.7);
            color: white;
            padding: 5px 10px;
            border-radius: 15px;
            font-size: 0.8rem;
            font-weight: 600;
        }}
        
        /* Hide linear track elements when in circular mode */
        .race-track.circular .track-background,
        .race-track.circular .track-line {{
            display: none;
        }}
        
        .race-track.circular {{
            width: 400px;
            height: 400px;
            border-radius: 50%;
            position: relative;
            /* Maintain circular aspect ratio */
            flex-shrink: 0;
            aspect-ratio: 1 / 1;
            /* Create donut shape with inner and outer borders */
            background: 
                radial-gradient(circle at center, transparent 35%, rgba(34, 197, 94, 0.2) 35%, rgba(34, 197, 94, 0.2) 65%, transparent 65%);
            border: 6px solid rgba(34, 197, 94, 0.6);
            box-shadow: 
                inset 0 0 30px rgba(34, 197, 94, 0.3),
                0 0 20px rgba(0,0,0,0.3);
        }}
        
        /* Responsive circular track for smaller screens */
        @media (max-width: 768px) {{
            .race-track.circular {{
                width: 300px;
                height: 300px;
            }}
        }}
        
        @media (max-width: 480px) {{
            .race-track.circular {{
                width: 250px;
                height: 250px;
            }}
        }}
        
        /* Inner donut hole */
        .race-track.circular::before {{
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            width: 140px;
            height: 140px;
            background: rgba(0,0,0,0.1);
            border: 4px solid rgba(34, 197, 94, 0.4);
            border-radius: 50%;
            transform: translate(-50%, -50%);
            z-index: 1;
        }}
        
        /* Position racers on circular track */
        .race-track.circular .racer {{
            position: absolute;
            width: 40px;
            height: 40px;
            transition: all 0.6s ease-out;
        }}
        
        /* Counteract rotation for speech bubbles on circular track */
        .race-track.circular .racer .speech-bubble {{
            transform: translateY(-50%) rotate(var(--counter-rotation, 0deg));
        }}
        
        /* Speech Bubbles */
        .speech-bubble {{
            position: absolute;
            top: -45px;
            left: 60px;
            transform: translateY(-50%);
            z-index: 200;
            opacity: 0;
            visibility: hidden;
            transition: all 0.4s ease;
            pointer-events: none;
        }}
        
        .speech-bubble.visible {{
            opacity: 1;
            visibility: visible;
            animation: bubblePopIn 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55);
        }}
        
        .bubble-content {{
            background: white;
            border-radius: 18px;
            padding: 8px 12px;
            min-width: 120px;
            max-width: 200px;
            font-size: 0.8rem;
            font-weight: 600;
            color: #2c3e50;
            text-align: center;
            line-height: 1.2;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
            border: 2px solid #f0f2f5;
            position: relative;
        }}
        
        .bubble-content::before {{
            content: '';
            position: absolute;
            top: -2px;
            left: -2px;
            right: -2px;
            bottom: -2px;
            border-radius: 20px;
            background: linear-gradient(135deg, #4a90e2, #357abd);
            z-index: -1;
        }}
        
        .bubble-tail {{
            position: absolute;
            top: 50%;
            left: -8px;
            transform: translateY(-50%);
            width: 0;
            height: 0;
            border: 8px solid transparent;
            border-right-color: white;
            z-index: 1;
        }}
        
        .bubble-tail::before {{
            content: '';
            position: absolute;
            top: -9px;
            left: 2px;
            width: 0;
            height: 0;
            border: 9px solid transparent;
            border-right-color: #4a90e2;
            z-index: -1;
        }}
        
        /* Different bubble styles for different AI personalities */
        #ai-racer-1 .bubble-content {{
            background: linear-gradient(135deg, #ff6b6b, #feca57);
            color: white;
            border-color: #ff6b6b;
        }}
        
        #ai-racer-1 .speech-bubble {{
            left: -140px; /* Position behind the racer */
            top: -10px; /* Align with ai-racer-1 which is at top: 35px */
        }}
        
        #ai-racer-1 .bubble-tail {{
            border-right-color: #ff6b6b;
            left: auto;
            right: -8px; /* Point from the right side */
            border-right-color: transparent;
            border-left-color: #ff6b6b;
        }}
        
        #ai-racer-1 .bubble-tail::before {{
            left: auto;
            right: 2px;
            border-right-color: transparent;
            border-left-color: #ff6b6b;
        }}
        
        #ai-racer-2 .speech-bubble {{
            top: 15px; /* Align with ai-racer-2 which is at top: 60px */
        }}
        
        #ai-racer-2 .bubble-content {{
            background: linear-gradient(135deg, #4ecdc4, #44a08d);
            color: white;  
            border-color: #4ecdc4;
        }}
        
        #ai-racer-2 .bubble-tail {{
            border-right-color: #4ecdc4;
        }}
        
        @keyframes bubblePopIn {{
            0% {{ 
                opacity: 0; 
                transform: translateY(-50%) translateX(10px) scale(0.3);
            }}
            50% {{ 
                opacity: 1; 
                transform: translateY(-50%) translateX(-5px) scale(1.1);
            }}
            100% {{ 
                opacity: 1; 
                transform: translateY(-50%) translateX(0) scale(1);
            }}
        }}
        
        /* Player Race Animations */
        .racer.tripped {{
            animation: tripAndRecover 1.2s ease-out;
        }}
        
        .racer.moving-backwards {{
            animation: moveBackwards 0.8s ease-out;
        }}
        
        @keyframes tripAndRecover {{
            0% {{ transform: rotate(0deg) translateY(0px); }}
            20% {{ transform: rotate(-15deg) translateY(8px); }}
            40% {{ transform: rotate(-25deg) translateY(15px); }}
            60% {{ transform: rotate(-20deg) translateY(12px); }}
            80% {{ transform: rotate(-5deg) translateY(3px); }}
            100% {{ transform: rotate(0deg) translateY(0px); }}
        }}
        
        @keyframes moveBackwards {{
            0% {{ transform: translateX(0px) scale(1); }}
            30% {{ transform: translateX(-20px) scale(0.9); }}
            60% {{ transform: translateX(-15px) scale(0.95); }}
            100% {{ transform: translateX(0px) scale(1); }}
        }}
        
        @keyframes raceFinish {{
            0% {{ transform: scale(1) rotate(0deg); }}
            50% {{ transform: scale(1.2) rotate(180deg); }}
            100% {{ transform: scale(1) rotate(360deg); }}
        }}
        
        .racer.winner {{
            animation: raceFinish 1s ease-in-out;
            border-color: #FFD700;
            box-shadow: 0 0 20px #FFD700;
        }}
        
        .racer.celebrating {{
            animation: bounce 0.3s infinite alternate;
        }}
        
        /* Special bounce for circular track that preserves rotation */
        .race-track.circular .racer.celebrating {{
            animation: circularBounce 0.3s infinite alternate;
        }}
        
        @keyframes circularBounce {{
            0% {{ 
                transform: rotate(var(--racer-rotation, 0deg)) scale(1) translateY(0px);
            }}
            100% {{ 
                transform: rotate(var(--racer-rotation, 0deg)) scale(1.1) translateY(-2px);
            }}
        }}
        
        /* Enhanced Feedback Area */
        .complement-feedback-area {{
            text-align: center;
            background: white;
            border-radius: 20px;
            padding: 25px;
            box-shadow: 0 10px 25px rgba(0,0,0,0.1);
            margin-bottom: 30px;
            position: relative;
        }}
        
        .input-hint {{
            font-size: 1.1rem;
            color: #666;
            opacity: 0.8;
            margin-top: 10px;
        }}
        
        /* Enhanced Game Style Buttons */
        .style-buttons {{
            display: flex;
            flex-direction: column;
            gap: 15px;
            margin-top: 15px;
        }}
        
        .game-style-btn {{
            background: white;
            border: 2px solid #e9ecef;
            border-radius: 15px;
            padding: 20px 25px;
            cursor: pointer;
            transition: all 0.3s ease;
            text-align: left;
            width: 100%;
            display: flex;
            align-items: center;
            gap: 20px;
            box-shadow: 0 4px 12px rgba(0,0,0,0.08);
            position: relative;
            overflow: hidden;
        }}
        
        .game-style-btn::before {{
            content: '';
            position: absolute;
            top: 0;
            left: -100%;
            width: 100%;
            height: 100%;
            background: linear-gradient(90deg, transparent, rgba(255,255,255,0.4), transparent);
            transition: left 0.6s;
        }}
        
        .game-style-btn:hover {{
            border-color: #667eea;
            transform: translateY(-2px);
            box-shadow: 0 8px 25px rgba(102, 126, 234, 0.15);
        }}
        
        .game-style-btn:hover::before {{
            left: 100%;
        }}
        
        .game-style-btn.active {{
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            border-color: #667eea;
            color: white;
            box-shadow: 0 8px 25px rgba(102, 126, 234, 0.3);
        }}
        
        .game-style-btn.active:hover {{
            transform: translateY(-3px);
            box-shadow: 0 12px 35px rgba(102, 126, 234, 0.4);
        }}
        
        .game-style-btn.active::before {{
            background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
        }}
        
        .style-icon {{
            font-size: 2.5rem;
            line-height: 1;
            filter: drop-shadow(0 2px 4px rgba(0,0,0,0.1));
            flex-shrink: 0;
        }}
        
        .game-style-btn.active .style-icon {{
            filter: drop-shadow(0 2px 4px rgba(0,0,0,0.3));
        }}
        
        .style-content {{
            flex: 1;
        }}
        
        .style-title {{
            font-size: 1.3rem;
            font-weight: 700;
            margin-bottom: 5px;
            color: #333;
        }}
        
        .game-style-btn.active .style-title {{
            color: white;
        }}
        
        .style-description {{
            font-size: 0.95rem;
            color: #666;
            line-height: 1.4;
            opacity: 0.9;
        }}
        
        .game-style-btn.active .style-description {{
            color: rgba(255, 255, 255, 0.9);
        }}
        
        /* Hover effects for individual styles */
        .game-style-btn[data-style="practice"]:not(.active):hover {{
            border-color: #28a745;
            box-shadow: 0 8px 25px rgba(40, 167, 69, 0.15);
        }}
        
        .game-style-btn[data-style="sprint"]:not(.active):hover {{
            border-color: #ffc107;
            box-shadow: 0 8px 25px rgba(255, 193, 7, 0.15);
        }}
        
        .game-style-btn[data-style="survival"]:not(.active):hover {{
            border-color: #dc3545;
            box-shadow: 0 8px 25px rgba(220, 53, 69, 0.15);
        }}
        
        /* Enhanced Feedback */
        .input-feedback {{
            margin-top: 15px;
            font-size: 1.2rem;
            font-weight: 600;
            min-height: 30px;
            display: flex;
            align-items: center;
            justify-content: center;
            transition: all 0.3s ease;
        }}
        
        .input-feedback.correct {{
            color: #28a745;
            animation: success 0.6s ease-out;
        }}
        
        .input-feedback.incorrect {{
            color: #dc3545;
            animation: shake 0.6s ease-out;
        }}
        
        .input-feedback.timeout {{
            color: #ffc107;
            animation: fadeIn 0.5s ease-out;
        }}
        
        /* Adaptive Difficulty Feedback */
        .adaptive-feedback {{
            margin-top: 10px;
            font-size: 0.95rem;
            font-weight: 500;
            min-height: 20px;
            display: flex;
            align-items: center;
            justify-content: center;
            transition: all 0.4s ease;
            opacity: 0.8;
        }}
        
        .adaptive-feedback.learning {{
            color: #17a2b8;
            background: rgba(23, 162, 184, 0.1);
            border-radius: 15px;
            padding: 8px 16px;
        }}
        
        .adaptive-feedback.struggling {{
            color: #dc3545;
            background: rgba(220, 53, 69, 0.1);
            border-radius: 15px;
            padding: 8px 16px;
        }}
        
        .adaptive-feedback.mastered {{
            color: #28a745;
            background: rgba(40, 167, 69, 0.1);
            border-radius: 15px;
            padding: 8px 16px;
        }}
        
        .adaptive-feedback.adapted {{
            color: #6f42c1;
            background: rgba(111, 66, 193, 0.1);
            border-radius: 15px;
            padding: 8px 16px;
            animation: adaptivePulse 1s ease-out;
        }}
        
        @keyframes adaptivePulse {{
            0% {{ transform: scale(1); opacity: 0; }}
            50% {{ transform: scale(1.05); opacity: 1; }}
            100% {{ transform: scale(1); opacity: 0.8; }}
        }}
        
        /* Animations */
        @keyframes pulse {{
            0%, 100% {{ transform: scale(1); }}
            50% {{ transform: scale(1.05); }}
        }}
        
        @keyframes glow {{
            0% {{ box-shadow: 0 0 5px rgba(255, 255, 255, 0.5); }}
            100% {{ box-shadow: 0 0 20px rgba(255, 255, 255, 0.8), 0 0 30px rgba(255, 255, 255, 0.6); }}
        }}
        
        @keyframes bounceIn {{
            0% {{ transform: scale(0.3) rotate(-10deg); opacity: 0; }}
            50% {{ transform: scale(1.1) rotate(5deg); }}
            100% {{ transform: scale(1) rotate(0deg); opacity: 1; }}
        }}
        
        @keyframes bounce {{
            0%, 100% {{ transform: translateY(0); }}
            50% {{ transform: translateY(-10px); }}
        }}
        
        @keyframes shimmer {{
            0% {{ background-position: -200px 0; }}
            100% {{ background-position: 200px 0; }}
        }}
        
        /* Lapping Celebration Animations */
        @keyframes lapCelebrationBounce {{
            0% {{
                transform: translateX(-50%) scale(0);
                opacity: 0;
                rotation: -10deg;
            }}
            30% {{
                transform: translateX(-50%) scale(1.2);
                opacity: 1;
                rotation: 5deg;
            }}
            60% {{
                transform: translateX(-50%) scale(0.95);
                rotation: -2deg;
            }}
            100% {{
                transform: translateX(-50%) scale(1);
                opacity: 1;
                rotation: 0deg;
            }}
        }}
        
        .lapping-celebration {{
            animation: lappingPulse 1.5s ease-in-out;
            transform-origin: center;
        }}
        
        @keyframes lappingPulse {{
            0%, 100% {{ transform: scale(1) rotate(0deg); }}
            25% {{ transform: scale(1.3) rotate(-5deg); box-shadow: 0 0 25px #ffd700; }}
            50% {{ transform: scale(1.1) rotate(5deg); box-shadow: 0 0 35px #ffd700; }}
            75% {{ transform: scale(1.2) rotate(-3deg); box-shadow: 0 0 20px #ffd700; }}
        }}
        
        /* Race Countdown */
        .race-countdown {{
            position: fixed;
            top: 0;
            left: 0;
            width: 100vw;
            height: 100vh;
            background: rgba(0, 0, 0, 0.8);
            display: none;
            justify-content: center;
            align-items: center;
            z-index: 10000;
            backdrop-filter: blur(5px);
        }}
        
        .countdown-display {{
            text-align: center;
            color: white;
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
        }}
        
        .countdown-number {{
            font-size: 15rem;
            font-weight: 900;
            line-height: 1;
            text-shadow: 0 0 50px rgba(255, 255, 255, 0.5);
            margin-bottom: 20px;
            animation: countdownPulse 1s ease-out;
        }}
        
        .countdown-text {{
            font-size: 2rem;
            font-weight: 600;
            margin-bottom: 40px;
            opacity: 0.9;
        }}
        
        .countdown-go {{
            font-size: 20rem;
            font-weight: 900;
            background: linear-gradient(135deg, #ff6b6b, #feca57, #48dbfb, #ff9ff3);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            background-clip: text;
            text-shadow: 0 0 50px rgba(255, 255, 255, 0.8);
            animation: goAnimation 1s ease-out;
        }}
        
        @keyframes countdownPulse {{
            0% {{ 
                transform: scale(0.5);
                opacity: 0;
            }}
            20% {{ 
                transform: scale(1.2);
                opacity: 1;
            }}
            100% {{ 
                transform: scale(1);
                opacity: 1;
            }}
        }}
        
        @keyframes goAnimation {{
            0% {{ 
                transform: scale(0.3) rotate(-10deg);
                opacity: 0;
            }}
            50% {{ 
                transform: scale(1.2) rotate(5deg);
                opacity: 1;
            }}
            100% {{ 
                transform: scale(1) rotate(0deg);
                opacity: 1;
            }}
        }}
        
        @keyframes rotate {{
            from {{ transform: rotate(0deg); }}
            to {{ transform: rotate(360deg); }}
        }}
        
        @keyframes success {{
            0% {{ transform: scale(0.8); opacity: 0; }}
            50% {{ transform: scale(1.1); }}
            100% {{ transform: scale(1); opacity: 1; }}
        }}
        
        @keyframes shake {{
            0%, 100% {{ transform: translateX(0); }}
            25% {{ transform: translateX(-5px); }}
            75% {{ transform: translateX(5px); }}
        }}
        
        /* Responsive Design */
        @media (max-width: 768px) {{
            .equation-visual {{
                gap: 15px;
            }}
            
            .challenge-number,
            .answer-display,
            .target-number {{
                font-size: 2.5rem;
                padding: 15px 20px;
            }}
            
            .answer-display {{
                min-width: 80px;
            }}
            
            .equation-symbol {{
                font-size: 2rem;
            }}
            
        }}
        
    </style>
</head>
<body>
    <div class="container">
        <!-- Beautiful Main Header -->
        <header class="main-header">
            <h1>Soroban Flashcards</h1>
            <p>Interactive learning tools for mastering the Japanese abacus</p>
        </header>
        
        <!-- Navigation -->
        <nav class="page-nav">
            <div class="nav-buttons">
                <button class="nav-btn active" data-section="welcome">🏠 Welcome</button>
                <button class="nav-btn" data-section="guide">📚 Complete Guide</button>
                <button class="nav-btn" data-section="configuration">⚙️ Configuration</button>
                <button class="nav-btn" data-section="challenges">🎯 Challenges</button>
                <button class="nav-btn" data-section="flashcards">📊 Practice</button>
            </div>
        </nav>
        
        <!-- Content Area -->
        <div class="content-area">
        
        <!-- Section 1: Welcome -->
        <section id="welcome" class="page-section active">
            <div class="welcome-hero">
                <div class="welcome-content">
                    <h1 class="welcome-title">🏠 Welcome to Soroban Mastery</h1>
                    <p class="welcome-subtitle">Your complete interactive learning platform for mastering the Japanese abacus</p>
                    
                    <div class="feature-grid">
                        <div class="feature-card">
                            <div class="feature-icon">📚</div>
                            <h3>Complete Guide</h3>
                            <p>Learn to read numbers and perform arithmetic operations with step-by-step visual tutorials</p>
                            <button class="feature-btn" data-section="guide">Start Learning →</button>
                        </div>
                        
                        <div class="feature-card">
                            <div class="feature-icon">🎯</div>
                            <h3>Interactive Challenges</h3>
                            <p>Test your skills with engaging games including speed reading challenges and pattern matching</p>
                            <button class="feature-btn" data-section="challenges">Play Games →</button>
                        </div>
                        
                        <div class="feature-card">
                            <div class="feature-icon">📊</div>
                            <h3>Practice Flashcards</h3>
                            <p>Master number recognition with beautiful, customizable flashcards and printable PDF sets</p>
                            <button class="feature-btn" data-section="flashcards">Practice Now →</button>
                        </div>
                        
                        <div class="feature-card">
                            <div class="feature-icon">⚙️</div>
                            <h3>Customization</h3>
                            <p>Personalize your learning experience with different color schemes, card layouts, and difficulty levels</p>
                            <button class="feature-btn" data-section="configuration">Customize →</button>
                        </div>
                    </div>
                    
                    <div class="quick-start">
                        <h2>Quick Start Guide</h2>
                        <div class="steps">
                            <div class="step">
                                <div class="step-number">1</div>
                                <div class="step-content">
                                    <h4>Learn the Basics</h4>
                                    <p>Start with our complete guide to understand how to read numbers on the soroban</p>
                                </div>
                            </div>
                            <div class="step">
                                <div class="step-number">2</div>
                                <div class="step-content">
                                    <h4>Practice Recognition</h4>
                                    <p>Use interactive flashcards to build speed and accuracy in number recognition</p>
                                </div>
                            </div>
                            <div class="step">
                                <div class="step-number">3</div>
                                <div class="step-content">
                                    <h4>Challenge Yourself</h4>
                                    <p>Test your skills with timed challenges and competitive games</p>
                                </div>
                            </div>
                            <div class="step">
                                <div class="step-number">4</div>
                                <div class="step-content">
                                    <h4>Master Arithmetic</h4>
                                    <p>Learn advanced techniques for addition, subtraction, and more complex operations</p>
                                </div>
                            </div>
                        </div>
                    </div>
                    
                    <div class="stats-preview">
                        <h3>What You Will Learn</h3>
                        <div class="stats-grid">
                            <div class="stat-item">
                                <div class="stat-number">{len_numbers}</div>
                                <div class="stat-label">Practice Numbers</div>
                            </div>
                            <div class="stat-item">
                                <div class="stat-number">4</div>
                                <div class="stat-label">Game Modes</div>
                            </div>
                            <div class="stat-item">
                                <div class="stat-number">5</div>
                                <div class="stat-label">Color Schemes</div>
                            </div>
                            <div class="stat-item">
                                <div class="stat-number">∞</div>
                                <div class="stat-label">Skill Levels</div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </section>
        
        <!-- Section 2: Complete Guide -->
        <section id="guide" class="page-section">
            <div class="section-header">
                <h2 class="section-title">📚 Complete Soroban Mastery Guide</h2>
                <p class="section-subtitle">From basic reading to advanced arithmetic - everything you need to master the Japanese abacus</p>
            </div>
            
            <!-- Guide Navigation -->
            <div class="guide-nav">
                <div class="guide-nav-buttons">
                    <button class="guide-nav-btn active" data-guide-section="reading">📖 Reading Numbers</button>
                    <button class="guide-nav-btn" data-guide-section="arithmetic">🧮 Arithmetic Operations</button>
                </div>
            </div>
            
            <!-- Guide Content -->
            <div class="guide-content">
                
                <!-- Reading Numbers Section -->
                <div id="reading" class="guide-section active">
                
                <!-- Step 1: Basic Structure -->
                <div class="tutorial-step">
                    <div class="step-header">
                        <h3><span class="step-number">1</span>Understanding the Structure</h3>
                    </div>
                    <div class="step-content">
                        <div class="tutorial-grid">
                            <div class="tutorial-text">
                                <p>The soroban has <strong>heaven beads</strong> (top) and <strong>earth beads</strong> (bottom) separated by a horizontal bar.</p>
                                <ul>
                                    <li><strong>Heaven bead:</strong> Worth 5 units</li>
                                    <li><strong>Earth beads:</strong> Worth 1 unit each</li>
                                    <li><strong>Active position:</strong> Beads pushed toward the bar</li>
                                </ul>
                            </div>
                            <div class="tutorial-visual">
                                <div class="example-abacus" id="tutorial-structure">
                                    {tutorial_svg_0}
                                </div>
                                <div class="example-label">Zero (0) - All beads away from bar</div>
                            </div>
                        </div>
                    </div>
                </div>
                
                <!-- Step 2: Single Digits -->
                <div class="tutorial-step">
                    <div class="step-header">
                        <h3><span class="step-number">2</span>Reading Single Digits (1-9)</h3>
                    </div>
                    <div class="step-content">
                        <div class="examples-grid">
                            <div class="example-item">
                                <div class="example-abacus">{tutorial_svg_1}</div>
                                <div class="example-label">1 = One earth bead up</div>
                            </div>
                            <div class="example-item">
                                <div class="example-abacus">{tutorial_svg_3}</div>
                                <div class="example-label">3 = Three earth beads up</div>
                            </div>
                            <div class="example-item">
                                <div class="example-abacus">{tutorial_svg_5}</div>
                                <div class="example-label">5 = Heaven bead down</div>
                            </div>
                            <div class="example-item">
                                <div class="example-abacus">{tutorial_svg_7}</div>
                                <div class="example-label">7 = Heaven bead + 2 earth beads</div>
                            </div>
                            <div class="example-item">
                                <div class="example-abacus">{tutorial_svg_9}</div>
                                <div class="example-label">9 = Heaven bead + 4 earth beads</div>
                            </div>
                        </div>
                    </div>
                </div>
                
                <!-- Step 3: Multi-digit Numbers -->
                <div class="tutorial-step">
                    <div class="step-header">
                        <h3><span class="step-number">3</span>Multi-Digit Numbers</h3>
                    </div>
                    <div class="step-content">
                        <div class="tutorial-text">
                            <p>Each column represents a place value. Read from right to left: <strong>ones, tens, hundreds, thousands</strong>.</p>
                        </div>
                        <div class="examples-grid">
                            <div class="example-item">
                                <div class="example-abacus">{tutorial_svg_23}</div>
                                <div class="example-label">23 = 2 tens + 3 ones</div>
                                <div class="example-breakdown">Tens: 2 | Ones: 3</div>
                            </div>
                            <div class="example-item">
                                <div class="example-abacus">{tutorial_svg_67}</div>
                                <div class="example-label">67 = 6 tens + 7 ones</div>
                                <div class="example-breakdown">Tens: 6 | Ones: 7</div>
                            </div>
                            <div class="example-item">
                                <div class="example-abacus">{tutorial_svg_158}</div>
                                <div class="example-label">158 = 1 hundred + 5 tens + 8 ones</div>
                                <div class="example-breakdown">Hundreds: 1 | Tens: 5 | Ones: 8</div>
                            </div>
                        </div>
                    </div>
                </div>
                
                <!-- Step 4: Practice Tips -->
                <div class="tutorial-step">
                    <div class="step-header">
                        <h3><span class="step-number">4</span>Practice Strategy</h3>
                    </div>
                    <div class="step-content">
                        <div class="tutorial-grid">
                            <div class="tutorial-text">
                                <h4>Start Simple, Build Complexity</h4>
                                <ol>
                                    <li>Master single digits (0-9) first</li>
                                    <li>Practice two-digit numbers (10-99)</li>
                                    <li>Advance to three-digit numbers (100-999)</li>
                                    <li>Challenge yourself with larger numbers</li>
                                </ol>
                                
                                <h4>Reading Strategy</h4>
                                <p>For each column, count the active beads:</p>
                                <ul>
                                    <li>Heaven bead down = add 5</li>
                                    <li>Earth beads up = add 1 each</li>
                                    <li>Total the values for each column</li>
                                </ul>
                            </div>
                            <div class="tutorial-visual">
                                <div class="example-abacus" id="practice-example">{tutorial_svg_example}</div>
                                <div class="example-label" id="practice-label">Practice Number</div>
                                <div class="practice-hint">Try to read this number before revealing!</div>
                                <button class="reveal-btn" id="reveal-answer" onclick="revealAnswer()">Reveal Answer</button>
                            </div>
                        </div>
                    </div>
                </div>
                
                </div> <!-- End Reading Section -->
                
                <!-- Arithmetic Operations Section -->
                <div id="arithmetic" class="guide-section">
                
                <div class="section-intro">
                    <h3>🧮 Soroban Arithmetic Mastery</h3>
                    <p>Learn traditional Japanese calculation techniques step-by-step with visual examples</p>
                </div>
                
                <!-- Addition Section -->
                <div class="tutorial-step">
                    <div class="step-header">
                        <h3><span class="step-number">+</span>Addition Techniques</h3>
                    </div>
                    <div class="step-content">
                        <div class="arithmetic-intro">
                            <p>Addition on the soroban follows specific rules for manipulating beads efficiently. Master these fundamental patterns:</p>
                        </div>
                        
                        <!-- Simple Addition -->
                        <div class="operation-section">
                            <h4>Simple Addition (No Carries)</h4>
                            <div class="calculation-example">
                                <div class="calc-step">
                                    <div class="step-description">
                                        <h5>Example: 23 + 14 = 37</h5>
                                        <p>Add ones first, then tens. No carrying required.</p>
                                    </div>
                                    <div class="calc-visual-sequence">
                                        <div class="calc-frame">
                                            <div class="frame-label">Start: 23</div>
                                            <div class="example-abacus">{arithmetic_svg_23}</div>
                                        </div>
                                        <div class="calc-arrow">+4 ones →</div>
                                        <div class="calc-frame">
                                            <div class="frame-label">Add 4 to ones: 27</div>
                                            <div class="example-abacus">{arithmetic_svg_27}</div>
                                        </div>
                                        <div class="calc-arrow">+1 ten →</div>
                                        <div class="calc-frame">
                                            <div class="frame-label">Final: 37</div>
                                            <div class="example-abacus">{arithmetic_svg_37}</div>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                        
                        <!-- Addition with Carry -->
                        <div class="operation-section">
                            <h4>Addition with Carrying</h4>
                            <div class="calculation-example">
                                <div class="calc-step">
                                    <div class="step-description">
                                        <h5>Example: 47 + 28 = 75</h5>
                                        <p>When ones exceed 9, carry to tens column.</p>
                                        <ol class="technique-steps">
                                            <li>Start with 47 on the abacus</li>
                                            <li>Add 8 to ones: 7 + 8 = 15 (carry 1)</li>
                                            <li>Place 5 in ones, carry 1 to tens</li>
                                            <li>Add 2 + 1 (carry) = 3 to tens: 4 + 3 = 7</li>
                                        </ol>
                                    </div>
                                    <div class="calc-visual-sequence">
                                        <div class="calc-frame">
                                            <div class="frame-label">Start: 47</div>
                                            <div class="example-abacus">{arithmetic_svg_47}</div>
                                        </div>
                                        <div class="calc-arrow">+8 ones<br>(7+8=15) →</div>
                                        <div class="calc-frame">
                                            <div class="frame-label">Carry: 55</div>
                                            <div class="example-abacus">{arithmetic_svg_55}</div>
                                        </div>
                                        <div class="calc-arrow">+2 tens →</div>
                                        <div class="calc-frame">
                                            <div class="frame-label">Final: 75</div>
                                            <div class="example-abacus">{arithmetic_svg_75}</div>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
                
                <!-- Subtraction Section -->
                <div class="tutorial-step">
                    <div class="step-header">
                        <h3><span class="step-number">−</span>Subtraction Techniques</h3>
                    </div>
                    <div class="step-content">
                        <div class="arithmetic-intro">
                            <p>Subtraction requires understanding complement methods and borrowing. These are traditional soroban techniques.</p>
                        </div>
                        
                        <!-- Simple Subtraction -->
                        <div class="operation-section">
                            <h4>Simple Subtraction (No Borrowing)</h4>
                            <div class="calculation-example">
                                <div class="calc-step">
                                    <div class="step-description">
                                        <h5>Example: 89 - 34 = 55</h5>
                                        <p>Subtract ones first, then tens. No borrowing needed.</p>
                                    </div>
                                    <div class="calc-visual-sequence">
                                        <div class="calc-frame">
                                            <div class="frame-label">Start: 89</div>
                                            <div class="example-abacus">{arithmetic_svg_89}</div>
                                        </div>
                                        <div class="calc-arrow">-4 ones →</div>
                                        <div class="calc-frame">
                                            <div class="frame-label">After -4: 85</div>
                                            <div class="example-abacus">{arithmetic_svg_85}</div>
                                        </div>
                                        <div class="calc-arrow">-3 tens →</div>
                                        <div class="calc-frame">
                                            <div class="frame-label">Final: 55</div>
                                            <div class="example-abacus">{arithmetic_svg_55}</div>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                        
                        <!-- Complement Method -->
                        <div class="operation-section">
                            <h4>Complement Method (Advanced)</h4>
                            <div class="technique-box">
                                <h5>Five Complement Rule</h5>
                                <p>When subtracting from 5, use complement pairs:</p>
                                <div class="complement-grid">
                                    <div class="complement-pair">5 - 1 = 4 → Remove heaven, add 4 earth</div>
                                    <div class="complement-pair">5 - 2 = 3 → Remove heaven, add 3 earth</div>
                                    <div class="complement-pair">5 - 3 = 2 → Remove heaven, add 2 earth</div>
                                    <div class="complement-pair">5 - 4 = 1 → Remove heaven, add 1 earth</div>
                                </div>
                            </div>
                            <div class="technique-box">
                                <h5>Ten Complement Rule</h5>
                                <p>When borrowing from next column:</p>
                                <div class="complement-grid">
                                    <div class="complement-pair">10 - 1 = 9 → Borrow 1, add 9</div>
                                    <div class="complement-pair">10 - 7 = 3 → Borrow 1, add 3</div>
                                    <div class="complement-pair">10 - 8 = 2 → Borrow 1, add 2</div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
                
                <!-- Multiplication Section -->
                <div class="tutorial-step">
                    <div class="step-header">
                        <h3><span class="step-number">×</span>Multiplication Methods</h3>
                    </div>
                    <div class="step-content">
                        <div class="arithmetic-intro">
                            <p>Soroban multiplication uses repeated addition and special column techniques for efficiency.</p>
                        </div>
                        
                        <!-- Single Digit Multiplication -->
                        <div class="operation-section">
                            <h4>Single-Digit Multiplication</h4>
                            <div class="calculation-example">
                                <div class="calc-step">
                                    <div class="step-description">
                                        <h5>Example: 23 × 4 = 92</h5>
                                        <p>Multiply each digit by 4, handling carries properly.</p>
                                        <ol class="technique-steps">
                                            <li>Set up 23 on the left, multiply by 4</li>
                                            <li>3 × 4 = 12 → Write 2, carry 1</li>
                                            <li>2 × 4 = 8, plus carry 1 = 9</li>
                                            <li>Result: 92</li>
                                        </ol>
                                    </div>
                                    <div class="mult-layout">
                                        <div class="mult-setup">
                                            <div class="mult-label">Setup: 23 × 4</div>
                                            <div class="example-abacus">{arithmetic_svg_23}</div>
                                        </div>
                                        <div class="mult-result">
                                            <div class="mult-label">Result: 92</div>
                                            <div class="example-abacus">{arithmetic_svg_92}</div>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                        
                        <!-- Traditional Method -->
                        <div class="operation-section">
                            <h4>Traditional Multiplication Layout</h4>
                            <div class="technique-box">
                                <h5>Column Arrangement</h5>
                                <p>Traditional soroban multiplication uses specific column arrangements:</p>
                                <ul>
                                    <li><strong>Multiplicand:</strong> Left side of abacus</li>
                                    <li><strong>Multiplier:</strong> Right side of abacus</li>
                                    <li><strong>Product:</strong> Center columns for result</li>
                                    <li><strong>Working space:</strong> Extra columns for carries</li>
                                </ul>
                            </div>
                        </div>
                    </div>
                </div>
                
                <!-- Division Section -->
                <div class="tutorial-step">
                    <div class="step-header">
                        <h3><span class="step-number">÷</span>Division Techniques</h3>
                    </div>
                    <div class="step-content">
                        <div class="arithmetic-intro">
                            <p>Division on soroban uses traditional algorithms with quotient estimation and remainder handling.</p>
                        </div>
                        
                        <!-- Simple Division -->
                        <div class="operation-section">
                            <h4>Simple Division</h4>
                            <div class="calculation-example">
                                <div class="calc-step">
                                    <div class="step-description">
                                        <h5>Example: 84 ÷ 4 = 21</h5>
                                        <p>Divide left to right, estimating quotient digits.</p>
                                        <ol class="technique-steps">
                                            <li>Set dividend 84 on left side</li>
                                            <li>8 ÷ 4 = 2 → Place 2 in quotient</li>
                                            <li>4 ÷ 4 = 1 → Place 1 in quotient</li>
                                            <li>Result: 21</li>
                                        </ol>
                                    </div>
                                    <div class="div-layout">
                                        <div class="div-setup">
                                            <div class="div-label">Dividend: 84</div>
                                            <div class="example-abacus">{arithmetic_svg_84}</div>
                                        </div>
                                        <div class="div-result">
                                            <div class="div-label">Quotient: 21</div>
                                            <div class="example-abacus">{arithmetic_svg_21}</div>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                        
                        <!-- Division Layout -->
                        <div class="operation-section">
                            <h4>Traditional Division Layout</h4>
                            <div class="technique-box">
                                <h5>Column Organization</h5>
                                <ul>
                                    <li><strong>Dividend:</strong> Starting on left columns</li>
                                    <li><strong>Divisor:</strong> Held in memory or right side</li>
                                    <li><strong>Quotient:</strong> Built up in designated columns</li>
                                    <li><strong>Remainder:</strong> Left in dividend columns</li>
                                </ul>
                            </div>
                        </div>
                    </div>
                </div>
                
                <!-- Practice Tips -->
                <div class="tutorial-step">
                    <div class="step-header">
                        <h3><span class="step-number">💡</span>Mastery Tips</h3>
                    </div>
                    <div class="step-content">
                        <div class="tips-grid">
                            <div class="tip-card">
                                <h4>🎯 Accuracy First</h4>
                                <p>Master accuracy before attempting speed. Slow, correct movements build muscle memory for rapid calculation.</p>
                            </div>
                            <div class="tip-card">
                                <h4>🔄 Practice Complements</h4>
                                <p>Memorize 5-complements (1-4, 2-3) and 10-complements (1-9, 2-8, 3-7, 4-6) for efficient subtraction.</p>
                            </div>
                            <div class="tip-card">
                                <h4>👁️ Visualization</h4>
                                <p>Learn to see numbers as bead patterns. This enables mental soroban calculation without the physical device.</p>
                            </div>
                            <div class="tip-card">
                                <h4>📚 Progressive Learning</h4>
                                <p>Master single digits → two digits → three digits. Build complexity gradually for solid foundation.</p>
                            </div>
                        </div>
                    </div>
                </div>
                
                </div> <!-- End Arithmetic Section -->
                
            </div> <!-- End Guide Content -->
        </section>
        
        <!-- Section 2: Configuration -->
        <section id="configuration" class="page-section">
            <div class="section-header">
                <h2 class="section-title">⚙️ Current Configuration</h2>
                <p class="section-subtitle">Settings used for this flashcard set</p>
            </div>
            
            <div class="config-showcase">
                <div class="config-item">
                    <div class="config-label"><strong>📊 Cards Generated:</strong></div>
                    <div class="config-value">{card_count} flashcards</div>
                </div>
                
                <div class="config-item">
                    <div class="config-label"><strong>🔢 Number Range:</strong></div>
                    <div class="config-value">{number_range}</div>
                    <div class="config-description">Learn numbers from {number_range} with authentic soroban bead patterns</div>
                </div>
                
                <div class="config-item">
                    <div class="config-label"><strong>🎨 Color Scheme:</strong></div>
                    <div class="config-value">{color_scheme_description}</div>
                    <div class="color-palette">
                        <div class="color-sample heaven" title="Heaven beads (5s)"></div>
                        <div class="color-sample earth" title="Earth beads (1s)"></div>
                        <div class="color-sample frame" title="Frame"></div>
                    </div>
                    <div class="config-description">Colors help distinguish between heaven beads (worth 5) and earth beads (worth 1)</div>
                </div>
                
                <div class="config-item">
                    <div class="config-label"><strong>⚪ Bead Shape:</strong></div>
                    <div class="config-value" style="display: flex; align-items: center; gap: 15px;">
                        {bead_shape}
                        <div class="bead-examples">
                            <div class="bead-sample" data-shape="{bead_shape}" title="Current bead shape"></div>
                            <div class="shape-label">{bead_shape} beads</div>
                        </div>
                    </div>
                    <div class="config-description">Visual style affects readability - choose what works best for you</div>
                </div>
            </div>
            
            <div class="offline-info">
                <h3>📱 Offline Ready</h3>
                <p>This is a complete, self-contained web page that works without an internet connection. All interactive games, sound effects, and features are built-in. Save this file locally or bookmark it for offline practice anywhere!</p>
                
                <div class="tech-features">
                    <div class="feature">✨ Pure HTML/CSS/JavaScript</div>
                    <div class="feature">🎵 Generated sound effects</div>
                    <div class="feature">🎮 Interactive games built-in</div>
                    <div class="feature">📲 Works on any device</div>
                </div>
            </div>
        </section>
        
        <!-- Section 3: Challenges -->
        <section id="challenges" class="page-section">
            <div class="section-header">
                <h2 class="section-title">🎯 Interactive Challenges</h2>
                <p class="section-subtitle">Test your soroban skills with engaging games and quizzes</p>
            </div>
            
            <div class="challenges-section">
                <!-- Tag Filter Bar -->
                <div class="tag-filter-bar">
                    <div class="filter-title">Filter by Tags:</div>
                    <div class="tag-filters">
                        <button class="tag-filter active" data-tag="all">All Games <span class="tag-count">(4)</span></button>
                        <button class="tag-filter" data-tag="memory">🔍 Memory <span class="tag-count">(2)</span></button>
                        <button class="tag-filter" data-tag="speed">⚡ Speed <span class="tag-count">(3)</span></button>
                        <button class="tag-filter" data-tag="logic">🧩 Logic <span class="tag-count">(1)</span></button>
                        <button class="tag-filter" data-tag="patterns">👀 Patterns <span class="tag-count">(1)</span></button>
                        <button class="tag-filter" data-tag="arithmetic">🏃‍♂️ Arithmetic <span class="tag-count">(1)</span></button>
                    </div>
                </div>
            
                <div class="challenges-grid">
                    <button id="open-quiz-modal" class="challenge-card quiz-card" data-tags="memory,speed">
                        <div class="challenge-icon">⚡</div>
                        <div class="challenge-content">
                            <h4>Speed Memory Quiz</h4>
                            <p>Quick card displays test your reading skills</p>
                            <div class="challenge-tags">
                                <span class="tag">🔍 Memory</span>
                                <span class="tag">⚡ Speed</span>
                            </div>
                        </div>
                    </button>
                    
                    <button id="open-complement-modal" class="challenge-card complement-card" data-tags="speed,arithmetic">
                        <div class="challenge-icon">🔥</div>
                        <div class="challenge-content">
                            <h4>Speed Complement Race</h4>
                            <p>Lightning-fast complement recall training</p>
                            <div class="challenge-tags">
                                <span class="tag">🏃‍♂️ Arithmetic</span>
                                <span class="tag">⚡ Speed</span>
                            </div>
                        </div>
                    </button>
                    
                    <button id="open-sorting-modal" class="challenge-card sorting-card" data-tags="logic,patterns">
                        <div class="challenge-icon">🔢</div>
                        <div class="challenge-content">
                            <h4>Card Sorting Challenge</h4>
                            <p>Arrange cards using only abacus patterns</p>
                            <div class="challenge-tags">
                                <span class="tag">🧩 Logic</span>
                                <span class="tag">👀 Patterns</span>
                            </div>
                        </div>
                    </button>
                    
                    <button id="open-matching-modal" class="challenge-card matching-card" data-tags="memory,speed">
                        <div class="challenge-icon">🧩</div>
                        <div class="challenge-content">
                            <h4>Matching Pairs</h4>
                            <p>Match abacus patterns with their numerals</p>
                            <div class="challenge-tags">
                                <span class="tag">🔍 Memory</span>
                                <span class="tag">⚡ Speed</span>
                            </div>
                        </div>
                    </button>
                </div>
            </div>
        </div>

        <!-- Quiz Modal -->
        <div id="quiz-modal" class="modal">
            <div class="modal-content">
                <div class="modal-header">
                    <h2>Speed Memory Quiz</h2>
                    <div class="modal-controls">
                        <button id="quiz-fullscreen-btn" class="fullscreen-btn" title="Toggle Fullscreen">⛶</button>
                        <button id="close-quiz-modal" class="close-btn">&times;</button>
                    </div>
                </div>
                <div class="modal-body">
                    <p>Test your soroban reading skills! Cards will be shown briefly, then you'll enter the numbers you remember.</p>
            
            <div class="quiz-controls">
                <div class="control-group">
                    <label for="quiz-count">Cards to Quiz:</label>
                    <div class="count-buttons">
                        <button type="button" class="count-btn" data-count="2">2</button>
                        <button type="button" class="count-btn active" data-count="5">5</button>
                        <button type="button" class="count-btn" data-count="8">8</button>
                        <button type="button" class="count-btn" data-count="12">12</button>
                        <button type="button" class="count-btn" data-count="15">15</button>
                    </div>
                </div>
                
                <div class="control-group">
                    <label for="display-time">Display Time per Card:</label>
                    <div class="slider-container">
                        <input type="range" id="display-time" min="0.5" max="10" step="0.5" value="2" />
                        <span class="slider-value">2.0s</span>
                    </div>
                </div>
                
                <button id="start-quiz" class="quiz-start-btn">Start Quiz</button>
            </div>

            <!-- Quiz Game Area (hidden initially) -->
            <div id="quiz-game" class="quiz-game" style="display: none;">
                <div class="quiz-header">
                    <div class="quiz-progress">
                        <div class="progress-bar">
                            <div class="progress-fill"></div>
                        </div>
                        <span class="progress-text">Card <span id="current-card">1</span> of <span id="total-cards">10</span></span>
                    </div>
                    <button id="end-quiz" class="end-game-btn">End Quiz</button>
                </div>
                
                <div class="quiz-display">
                    <div id="quiz-card" class="quiz-flashcard">
                        <!-- Card content will be inserted here -->
                    </div>
                    <div id="quiz-countdown" class="countdown">Get Ready...</div>
                </div>
            </div>

            <!-- Quiz Input Phase (hidden initially) -->
            <div id="quiz-input" class="quiz-input" style="display: none;">
                <h3>Enter the Numbers You Remember</h3>
                <div class="quiz-stats">
                    <div class="stats-item">
                        <span class="stats-label">Cards shown:</span>
                        <span id="cards-shown-count">0</span>
                    </div>
                    <div class="stats-item">
                        <span class="stats-label">Guesses left:</span>
                        <span id="guesses-remaining">0</span>
                    </div>
                    <div class="stats-item">
                        <span class="stats-label">Found:</span>
                        <span id="numbers-found">0</span>
                    </div>
                </div>
                
                <div class="smart-input-container">
                    <div class="smart-input-prompt">Type the numbers you remember:</div>
                    <div class="number-display" id="number-display">
                        <span class="current-typing" id="current-typing"></span>
                    </div>
                    <input type="text" id="smart-input" style="position: absolute; left: -9999px; opacity: 0; pointer-events: none;" autocomplete="off">
                </div>
                
                <div class="found-numbers" id="found-numbers">
                    <!-- Accepted numbers will appear here -->
                </div>
                
                <div class="quiz-finish-buttons">
                    <button id="finish-quiz" class="finish-btn" style="display: none;">Finish Quiz</button>
                    <button id="give-up-quiz" class="give-up-btn" style="display: none;">Can't Remember More</button>
                </div>
            </div>

            <!-- Quiz Results (hidden initially) -->
            <div id="quiz-results" class="quiz-results" style="display: none;">
                <h3>Quiz Results</h3>
                <div class="score-display">
                    <div class="score-circle">
                        <span id="score-percentage">0%</span>
                    </div>
                    <div class="score-details">
                        <p><strong>Score:</strong> <span id="score-correct">0</span> / <span id="score-total">0</span> correct</p>
                        <p><strong>Time per card:</strong> <span id="result-timing">2.0s</span></p>
                    </div>
                </div>
                
                <div class="results-breakdown">
                    <h4>Detailed Results:</h4>
                    <div id="results-list">
                        <!-- Results will be inserted here -->
                    </div>
                </div>
                
                <div class="quiz-actions">
                    <button id="retry-quiz">Try Again</button>
                    <button id="back-to-cards">Back to Cards</button>
                </div>
            </div>
                </div>
            </div>
        </div>
        
        <!-- Sorting Modal -->
        <div id="sorting-modal" class="modal">
            <div class="modal-content">
                <div class="modal-header">
                    <h2>Card Sorting Challenge</h2>
                    <div class="modal-controls">
                        <button id="sorting-fullscreen-btn" class="fullscreen-btn" title="Toggle Fullscreen">⛶</button>
                        <button id="close-sorting-modal" class="close-btn">&times;</button>
                    </div>
                </div>
                <div class="modal-body">
                    <p>Click cards and positions to arrange them in ascending order (smallest to largest). No numerals shown - rely on reading the abacus!</p>
            
            <div class="sorting-controls">
                <div class="control-group">
                    <label for="sort-count">Cards to Sort:</label>
                    <div class="count-buttons">
                        <button type="button" class="sort-count-btn active" data-count="5">5</button>
                        <button type="button" class="sort-count-btn" data-count="8">8</button>
                        <button type="button" class="sort-count-btn" data-count="12">12</button>
                        <button type="button" class="sort-count-btn" data-count="15">15</button>
                    </div>
                </div>
                
                <div class="sorting-actions">
                    <button id="start-sorting" class="sort-start-btn">Start Sorting Challenge</button>
                </div>
            </div>
            
            <!-- Game Action Buttons (now moved to sticky header) -->
            <div class="sorting-game-actions" style="display: none;">
                <!-- Buttons moved to sticky header -->
            </div>
            
            <!-- Sorting Game Header (Sticky) -->
            <div id="sorting-header" class="sorting-header" style="display: none;">
                <div class="sorting-header-content">
                    <div class="sorting-status-group">
                        <span id="sorting-status">Ready to start</span>
                        <div class="sorting-timer" id="sorting-timer">0:00</div>
                    </div>
                    <div class="sorting-controls">
                        <button id="check-sorting" class="header-btn check-btn">Check Solution</button>
                        <button id="reveal-numbers" class="header-btn reveal-btn">Show Numbers</button>
                        <button id="new-sorting" class="header-btn new-btn">New Challenge</button>
                        <button id="end-sorting" class="header-btn end-btn">End Game</button>
                    </div>
                </div>
            </div>

            <!-- Sorting Game Area -->
            <div id="sorting-game" style="display: none;">
                <div class="sorting-instructions">
                    <p><strong>Instructions:</strong> Click a card → Click position or + button to place. Click placed cards to move back.</p>
                </div>
                
                <div class="sorting-game-layout">
                    <div class="available-cards-section">
                        <h4>Available Cards</h4>
                        <div id="sorting-area" class="sorting-area">
                            <!-- Available cards will be shown here -->
                        </div>
                    </div>
                    
                    <div class="sorting-slots-section">
                        <h4>Sorting Positions (Smallest → Largest)</h4>
                        <div id="position-slots" class="position-slots">
                            <!-- Position slots will be created here -->
                        </div>
                    </div>
                </div>
                
                <div class="sorting-feedback" id="sorting-feedback" style="display: none;">
                    <!-- Feedback will be shown here -->
                </div>
            </div>

            <!-- Score Report Modal -->
            <div id="score-modal" class="score-modal" style="display: none;">
                <div class="score-modal-content">
                    <div class="score-modal-header">
                        <h3>🎯 Sorting Challenge Results</h3>
                        <button class="score-modal-close">&times;</button>
                    </div>
                    <div id="score-modal-body" class="score-modal-body">
                        <!-- Score content will be inserted here -->
                    </div>
                    <div class="score-modal-footer">
                        <button id="score-modal-new-game" class="modal-btn new-game-btn">New Challenge</button>
                        <button id="score-modal-close-btn" class="modal-btn close-btn">Close</button>
                    </div>
                </div>
            </div>
                </div>
            </div>
        </div>

        <!-- Matching Pairs Modal -->
        <div id="matching-modal" class="modal">
            <div class="modal-content">
                <div class="modal-header">
                    <h2>Matching Pairs Challenge</h2>
                    <div class="modal-controls">
                        <button id="matching-fullscreen-btn" class="fullscreen-btn" title="Toggle Fullscreen">⛶</button>
                        <button id="close-matching-modal" class="close-btn">&times;</button>
                    </div>
                </div>
                <div class="modal-body">
                    <p id="matching-description">Match abacus patterns with their corresponding numerals. Find all pairs in minimum moves!</p>
            
            <div class="matching-controls">
                <div class="control-group">
                    <label>Number of Players:</label>
                    <div class="mode-buttons">
                        <button type="button" class="mode-btn active" data-mode="single">
                            <div class="mode-icon">👤</div>
                            <div class="mode-text">Single Player</div>
                        </button>
                        <button type="button" class="mode-btn" data-mode="two-player">
                            <div class="mode-icon">👥</div>
                            <div class="mode-text">Two Player</div>
                        </button>
                    </div>
                </div>
                
                <div class="control-group">
                    <label>Game Type:</label>
                    <div class="mode-buttons">
                        <button type="button" class="game-type-btn active" data-game-type="abacus-numeral">
                            <div class="mode-icon">🧮</div>
                            <div class="mode-text">Abacus / Numeral Pairs</div>
                        </button>
                        <button type="button" class="game-type-btn" data-game-type="complement-pairs">
                            <div class="mode-icon">🎯</div>
                            <div class="mode-text">Friends of 5 & 10</div>
                        </button>
                    </div>
                </div>
                
                <div class="control-group" id="timer-controls" style="display: none;">
                    <label>Turn Timer:</label>
                    <div class="timer-buttons">
                        <button type="button" class="timer-btn active" data-timer="0">No Timer</button>
                        <button type="button" class="timer-btn" data-timer="15">15 sec</button>
                        <button type="button" class="timer-btn" data-timer="30">30 sec</button>
                        <button type="button" class="timer-btn" data-timer="60">60 sec</button>
                    </div>
                </div>
                
                <div class="control-group">
                    <label for="match-grid-size">Choose Grid Size to Start:</label>
                    <div class="count-buttons">
                        <button type="button" class="match-size-btn start-game-btn" data-pairs="6">
                            <div class="btn-main">3×4 Grid</div>
                            <div class="btn-sub">6 pairs</div>
                        </button>
                        <button type="button" class="match-size-btn start-game-btn" data-pairs="8">
                            <div class="btn-main">4×4 Grid</div>
                            <div class="btn-sub">8 pairs</div>
                        </button>
                        <button type="button" class="match-size-btn start-game-btn" data-pairs="12">
                            <div class="btn-main">4×6 Grid</div>
                            <div class="btn-sub">12 pairs</div>
                        </button>
                        <button type="button" class="match-size-btn start-game-btn" data-pairs="15">
                            <div class="btn-main">5×6 Grid</div>
                            <div class="btn-sub">15 pairs</div>
                        </button>
                    </div>
                </div>
            </div>
            
            <!-- Matching Game Header (Sticky) -->
            <div id="matching-header" class="matching-header" style="display: none;">
                <div class="matching-header-content">
                    <div class="matching-status-group">
                        <span id="matching-status">Ready to start</span>
                        <div class="matching-stats">
                            <span id="moves-counter">Moves: 0</span>
                            <span id="pairs-found">Pairs: 0/0</span>
                            <div class="matching-timer" id="matching-timer">0:00</div>
                        </div>
                        <!-- Two-player specific stats -->
                        <div class="player-stats" id="player-stats" style="display: none;">
                            <div class="player-info player1" id="player1-info">
                                <span class="player-name">🔵 Player 1</span>
                                <span class="player-score">0 pairs</span>
                            </div>
                            <div class="current-turn" id="current-turn">🔵 Player 1's Turn</div>
                            <div class="turn-timer" id="turn-timer" style="display: none;">30s</div>
                            <div class="player-info player2" id="player2-info">
                                <span class="player-name">🟠 Player 2</span>
                                <span class="player-score">0 pairs</span>
                            </div>
                        </div>
                    </div>
                    <div class="matching-controls">
                        <button id="new-matching" class="header-btn new-btn">New Game</button>
                        <button id="end-matching" class="header-btn end-btn">End Game</button>
                    </div>
                </div>
            </div>

            <!-- Matching Game Area -->
            <div id="matching-game" style="display: none;">
                <div class="matching-instructions">
                    <p><strong>Instructions:</strong> Click two cards to flip them. Purple cards (🧮) contain abacus patterns, green cards (🔢) contain numbers. Match abacus patterns with their corresponding numbers. Complete all pairs with minimum moves!</p>
                </div>
                
                <div id="matching-grid" class="matching-grid">
                    <!-- Matching cards will be generated here -->
                </div>
                
                <div class="matching-feedback" id="matching-feedback" style="display: none;">
                    <!-- Feedback will be shown here -->
                </div>
            </div>

            <!-- Matching Score Modal -->
            <div id="matching-score-modal" class="score-modal" style="display: none;">
                <div class="score-modal-content">
                    <div class="score-modal-header">
                        <h3>🧩 Matching Pairs Results</h3>
                        <button class="matching-score-modal-close">&times;</button>
                    </div>
                    <div id="matching-score-modal-body" class="score-modal-body">
                        <!-- Score content will be inserted here -->
                    </div>
                    <div class="score-modal-footer">
                        <button id="matching-score-modal-new-game" class="modal-btn new-game-btn">New Challenge</button>
                        <button id="matching-score-modal-close-btn" class="modal-btn close-btn">Close</button>
                    </div>
                </div>
            </div>
                </div>
            </div>
        </div>
        
        <!-- Speed Complement Race Modal -->
        <div id="complement-modal" class="modal">
            <div class="modal-content">
                <div class="modal-header">
                    <h2>Speed Complement Race</h2>
                    <div class="modal-controls">
                        <button id="complement-fullscreen-btn" class="fullscreen-btn" title="Toggle Fullscreen">⛶</button>
                        <button id="close-complement-modal" class="close-btn">&times;</button>
                    </div>
                </div>
                <div class="modal-body">
                    <div class="complement-intro">
                        <div class="intro-icon">🚀</div>
                        <h3>Lightning-Fast Mental Math Training!</h3>
                        <p class="intro-description">Master complement pairs through rapid-fire practice. See a number, type its friend instantly!</p>
                        <div class="example-demo">
                            <div class="demo-equation">
                                <span class="demo-number">3</span>
                                <span class="demo-plus">+</span>
                                <span class="demo-answer">?</span>
                                <span class="demo-equals">=</span>
                                <span class="demo-target">5</span>
                            </div>
                            <div class="demo-instruction">👆 Type <strong>2</strong> as fast as you can!</div>
                        </div>
                    </div>
            
            <div class="complement-controls">
                <div class="control-group">
                    <label>Training Mode:</label>
                    <div class="mode-buttons">
                        <button type="button" class="mode-btn active" data-mode="friends5">
                            <div class="mode-icon">✋</div>
                            <div class="mode-text">Friends of 5</div>
                        </button>
                        <button type="button" class="mode-btn" data-mode="friends10">
                            <div class="mode-icon">🔟</div>
                            <div class="mode-text">Friends of 10</div>
                        </button>
                        <button type="button" class="mode-btn" data-mode="mixed">
                            <div class="mode-icon">🎯</div>
                            <div class="mode-text">Mixed Challenge</div>
                        </button>
                    </div>
                </div>
                
                <div class="control-group">
                    <label>Time Per Question:</label>
                    <div class="mode-buttons">
                        <button type="button" class="timeout-btn" data-timeout="preschool">
                            <div class="mode-icon">🧸</div>
                            <div class="mode-text">Preschool (20s)</div>
                        </button>
                        <button type="button" class="timeout-btn" data-timeout="kindergarten">
                            <div class="mode-icon">🌸</div>
                            <div class="mode-text">Kindergarten (15s)</div>
                        </button>
                        <button type="button" class="timeout-btn" data-timeout="relaxed">
                            <div class="mode-icon">🐢</div>
                            <div class="mode-text">Relaxed (12s)</div>
                        </button>
                        <button type="button" class="timeout-btn" data-timeout="slow">
                            <div class="mode-icon">🕰️</div>
                            <div class="mode-text">Slow (8s)</div>
                        </button>
                        <button type="button" class="timeout-btn active" data-timeout="normal">
                            <div class="mode-icon">⚡</div>
                            <div class="mode-text">Normal (5s)</div>
                        </button>
                        <button type="button" class="timeout-btn" data-timeout="fast">
                            <div class="mode-icon">🚀</div>
                            <div class="mode-text">Fast (3s)</div>
                        </button>
                        <button type="button" class="timeout-btn" data-timeout="expert">
                            <div class="mode-icon">⚡</div>
                            <div class="mode-text">Expert (2s)</div>
                        </button>
                    </div>
                </div>
                
                <div class="control-group">
                    <label>Choose Your Challenge:</label>
                    <div class="style-buttons">
                        <button type="button" class="game-style-btn active" data-style="practice">
                            <div class="style-icon">🎯</div>
                            <div class="style-content">
                                <div class="style-title">Endurance Race</div>
                                <div class="style-description">Race to 20 correct answers - has finish line!</div>
                            </div>
                        </button>
                        <button type="button" class="game-style-btn" data-style="sprint">
                            <div class="style-icon">⚡</div>
                            <div class="style-content">
                                <div class="style-title">Lightning Sprint</div>
                                <div class="style-description">60-second time attack! Beat the clock, not the finish line!</div>
                            </div>
                        </button>
                        <button type="button" class="game-style-btn" data-style="survival">
                            <div class="style-icon">🔥</div>
                            <div class="style-content">
                                <div class="style-title">Survival Mode</div>
                                <div class="style-description">Keep going forever - no finish line, just survive!</div>
                            </div>
                        </button>
                    </div>
                </div>
            </div>
            
            <!-- Game Area (hidden initially) -->
            <div id="complement-game" class="complement-game" style="display: none;">
                
                <!-- Game Header (sticky when playing) -->
                <div id="complement-header" class="game-sticky-header" style="display: none;">
                    <div class="header-stats">
                        <div class="stat-item">
                            <span class="stat-label">Score:</span>
                            <span id="complement-score">0</span>
                        </div>
                        <div class="stat-item">
                            <span class="stat-label">Streak:</span>
                            <span id="complement-streak">0</span>
                        </div>
                        <div class="stat-item">
                            <span class="stat-label">Time:</span>
                            <span id="complement-time">0s</span>
                        </div>
                    </div>
                    <div class="header-actions">
                        <button id="pause-complement" class="header-btn">⏸️ Pause</button>
                        <button id="end-complement" class="header-btn">🏁 End</button>
                    </div>
                </div>
                
                <!-- Main Game Display -->
                <div class="complement-display">
                    <div class="challenge-prompt">
                        <div class="equation-visual">
                            <div class="challenge-number-container">
                                <div class="challenge-number" id="challenge-number">7</div>
                                <div class="number-label">Given</div>
                            </div>
                            <div class="equation-symbol">+</div>
                            <div class="answer-container">
                                <div id="answer-display" class="answer-display">?</div>
                                <div class="answer-label">Your answer</div>
                            </div>
                            <div class="equation-symbol">=</div>
                            <div class="target-container">
                                <div class="target-number" id="target-number">10</div>
                                <div class="target-label">Target</div>
                            </div>
                        </div>
                    </div>
                    <div class="timer-section">
                        <div class="timer-label">⏱️ Time Remaining</div>
                        <div class="timer-bar">
                            <div class="timer-fill" id="timer-fill"></div>
                        </div>
                        <div class="timer-text" id="timer-text">5.0s</div>
                    </div>
                    
                    <!-- Race Track Section -->
                    <div class="race-track-section">
                        <div class="race-label">🏁 Mental Math Race</div>
                        <div class="race-track">
                            <div class="track-background">
                                <div class="track-line start-line"></div>
                                <div class="track-line quarter-line"></div>
                                <div class="track-line half-line"></div>
                                <div class="track-line three-quarter-line"></div>
                                <div class="track-line finish-line" id="finish-line"></div>
                            </div>
                            
                            <!-- Player Racer -->
                            <div class="racer player-racer" id="player-racer">
                                <div class="racer-character">🏃‍♀️</div>
                                <div class="racer-label">You</div>
                                <div class="racer-progress" id="player-progress">0</div>
                            </div>
                            
                            <!-- AI Opponents -->
                            <div class="racer ai-racer" id="ai-racer-1">
                                <div class="speech-bubble" id="speech-bubble-1">
                                    <div class="bubble-content"></div>
                                    <div class="bubble-tail"></div>
                                </div>
                                <div class="racer-character">🏃‍♂️</div>
                                <div class="racer-label">Swift AI</div>
                            </div>
                            
                            <div class="racer ai-racer" id="ai-racer-2">
                                <div class="speech-bubble" id="speech-bubble-2">
                                    <div class="bubble-content"></div>
                                    <div class="bubble-tail"></div>
                                </div>
                                <div class="racer-character">🏃</div>
                                <div class="racer-label">Math Bot</div>
                            </div>
                            
                            <!-- Finish Line -->
                            <div class="finish-zone" id="finish-zone">
                                <div class="finish-flag">🏁</div>
                                <div class="finish-text">FINISH</div>
                            </div>
                        </div>
                        
                        <!-- Steam Train Journey (for Sprint Mode) -->
                        <div class="route-map" style="display: none;" id="steam-journey">
                            <div class="steam-journey-header">
                                🚂 STEAM TRAIN JOURNEY 🚂
                                <div class="route-progress" id="route-progress">Route 1 - Mountain Valley Express</div>
                            </div>
                            <div class="time-display" id="time-of-day">Dawn - 5:30 AM</div>
                            
                            <!-- SVG Route Path -->
                            <div class="route-path">
                                <svg viewBox="0 0 800 600" width="800" height="600">
                                    <!-- Dynamic track elements will be generated here -->
                                </svg>
                                
                                <!-- Train locomotive -->
                                <div class="train-locomotive" id="train-position">
                                    <div class="steam-effect"></div>
                                    <div class="steam-effect" style="animation-delay: 0.3s;"></div>
                                    <div class="steam-effect" style="animation-delay: 0.6s;"></div>
                                </div>
                                
                                
                                <!-- Coal shoveler -->
                                <div class="coal-shoveler" id="coal-worker">👷</div>
                                
                                <!-- City stations -->
                                <div class="train-station" style="left: 50px; top: 300px;" data-city="Depot">🏭</div>
                                <div class="train-station" style="left: 200px; top: 200px;" data-city="Hillview">🏔️</div>
                                <div class="train-station" style="left: 300px; top: 250px;" data-city="Riverside">🌊</div>
                                <div class="train-station" style="left: 500px; top: 200px;" data-city="Summit">⛰️</div>
                                <div class="train-station" style="left: 700px; top: 150px;" data-city="Goldfield">⚱️</div>
                                <div class="train-station" style="left: 750px; top: 300px;" data-city="Capital">🏛️</div>
                                
                                <!-- Geographic landmarks -->
                                <div class="landmark mountain" style="left: 150px; top: 180px;">⛰️</div>
                                <div class="landmark tree" style="left: 250px; top: 270px;">🌲</div>
                                <div class="landmark bridge" style="left: 350px; top: 280px;">🌉</div>
                                <div class="landmark mountain" style="left: 550px; top: 120px;">🏔️</div>
                                <div class="landmark tree" style="left: 680px; top: 170px;">🌳</div>
                            </div>
                            
                            <!-- Steam Pressure Instrument Panel -->
                            <div class="instrument-panel">
                                <div class="panel-frame">
                                    <div class="panel-background"></div>
                                    <div class="pressure-gauge-container">
                                        <svg class="pressure-gauge" viewBox="0 0 200 120" width="160" height="96">
                                            <!-- Gauge background arc -->
                                            <path class="gauge-background" 
                                                  d="M 20 100 A 80 80 0 0 1 180 100" 
                                                  fill="none" 
                                                  stroke="rgba(255, 255, 255, 0.3)" 
                                                  stroke-width="12"/>
                                            
                                            <!-- Gauge progress arc -->
                                            <path class="gauge-progress" 
                                                  id="pressure-arc"
                                                  d="M 20 100 A 80 80 0 0 1 180 100" 
                                                  fill="none" 
                                                  stroke="#ff6b6b" 
                                                  stroke-width="10"
                                                  stroke-dasharray="251.2"
                                                  stroke-dashoffset="251.2"/>
                                            
                                            <!-- Gauge tick marks -->
                                            <g class="gauge-ticks">
                                                <line x1="100" y1="20" x2="100" y2="30" stroke="rgba(255,255,255,0.6)" stroke-width="2"/>
                                                <line x1="150" y1="35" x2="145" y2="43" stroke="rgba(255,255,255,0.4)" stroke-width="1"/>
                                                <line x1="180" y1="100" x2="170" y2="100" stroke="rgba(255,255,255,0.6)" stroke-width="2"/>
                                                <line x1="150" y1="165" x2="145" y2="157" stroke="rgba(255,255,255,0.4)" stroke-width="1"/>
                                                <line x1="50" y1="35" x2="55" y2="43" stroke="rgba(255,255,255,0.4)" stroke-width="1"/>
                                                <line x1="20" y1="100" x2="30" y2="100" stroke="rgba(255,255,255,0.6)" stroke-width="2"/>
                                                <line x1="50" y1="165" x2="55" y2="157" stroke="rgba(255,255,255,0.4)" stroke-width="1"/>
                                            </g>
                                            
                                            <!-- Pressure indicator needle (narrow isosceles triangle) -->
                                            <g class="pressure-needle" id="pressure-needle" transform="rotate(0 100 100)">
                                                <polygon points="100,95 98,100 102,100" 
                                                         fill="#ffd700" 
                                                         stroke="#ffed4e" 
                                                         stroke-width="1"/>
                                                <circle cx="100" cy="100" r="6" fill="rgba(255,255,255,0.9)" stroke="rgba(255,255,255,0.6)" stroke-width="2"/>
                                            </g>
                                            
                                            <!-- Gauge labels -->
                                            <text x="30" y="105" fill="rgba(255,255,255,0.7)" font-family="sans-serif" font-size="10" font-weight="600">0</text>
                                            <text x="95" y="25" fill="rgba(255,255,255,0.7)" font-family="sans-serif" font-size="10" font-weight="600">50</text>
                                            <text x="175" y="105" fill="rgba(255,255,255,0.7)" font-family="sans-serif" font-size="10" font-weight="600">100</text>
                                        </svg>
                                        <div class="gauge-title">🚂 Steam Power</div>
                                        <div class="gauge-value" id="pressure-value">0 PSI</div>
                                    </div>
                                </div>
                            </div>
                            
                            <!-- Passenger car -->
                            <div class="passenger-car" id="passenger-display">
                                <h4>👥 Passengers</h4>
                                <div class="passenger-list" id="passenger-list">
                                    <!-- Passengers will be added dynamically -->
                                </div>
                            </div>
                        </div>
                        
                        <div class="race-stats">
                            <div class="race-stat">
                                <span class="stat-label">Correct:</span>
                                <span id="race-correct">0</span>
                            </div>
                            <div class="race-stat">
                                <span class="stat-label">Goal:</span>
                                <span id="race-goal">20</span>
                            </div>
                        </div>
                    </div>
                </div>
                
                
                <!-- Feedback Area -->
                <div class="complement-feedback-area">
                    <div class="input-feedback" id="input-feedback"></div>
                    <div class="adaptive-feedback" id="adaptive-feedback"></div>
                </div>
                
                <!-- Visual Complement Display -->
                <div class="visual-complement" id="visual-complement" style="display: none;">
                    <div class="complement-equation">
                        <span class="number-part" id="number-part">7</span>
                        <span class="plus">+</span>
                        <span class="complement-part" id="complement-part">3</span>
                        <span class="equals">=</span>
                        <span class="sum-part" id="sum-part">10</span>
                    </div>
                    <div class="abacus-visualization" id="abacus-visualization">
                        <!-- Mini abacus showing the complement will go here -->
                    </div>
                </div>
                
                <!-- Progress & Achievement Display -->
                <div class="progress-display">
                    <div class="progress-bar">
                        <div class="progress-fill" id="progress-fill"></div>
                        <span class="progress-text" id="progress-text">0/10 Complete</span>
                    </div>
                    <div class="achievement-notice" id="achievement-notice" style="display: none;">
                        <!-- Achievement unlocks will appear here -->
                    </div>
                </div>
            </div>
            
            <!-- Complement Score Modal -->
            <div id="complement-score-modal" class="score-modal" style="display: none;">
                <div class="score-modal-content">
                    <div class="score-modal-header">
                        <h3>🔥 Complement Race Results</h3>
                        <button class="complement-score-modal-close">&times;</button>
                    </div>
                    <div id="complement-score-modal-body" class="score-modal-body">
                        <!-- Score content will be inserted here -->
                    </div>
                    <div class="score-modal-footer">
                        <button id="complement-score-modal-new-game" class="modal-btn new-game-btn">Race Again</button>
                        <button id="complement-score-modal-close-btn" class="modal-btn close-btn">Close</button>
                    </div>
                </div>
            </div>
                </div>
            </div>
        </div>
        </section>

        
        <!-- Section 4: Flashcards -->
        <section id="flashcards" class="page-section">
            <div class="section-header">
                <h2 class="section-title">🧮 Practice Flashcards</h2>
                <p class="section-subtitle">Interactive cards for hands-on learning</p>
            </div>
            
            <div class="cards-grid" id="cards-grid">
                {cards_html}
            </div>
            
            <div class="instructions">
                <p><em>Interactive flashcards for digital learning. Use the left/right arrow keys or click the cards to flip them.</em></p>
            </div>
        </section>
        
        </div> <!-- End Content Area -->
    </div>

    <script>
    // Modal Manager - Handles modal dialogs and fullscreen functionality
    class ModalManager {{
        constructor() {{
            this.isFullscreen = false;
            this.bindEvents();
        }}
        
        bindEvents() {{
            // Challenge button events
            document.getElementById('open-quiz-modal').addEventListener('click', () => {{
                this.openModal('quiz-modal');
            }});
            
            document.getElementById('open-sorting-modal').addEventListener('click', () => {{
                this.openModal('sorting-modal');
            }});
            
            document.getElementById('open-matching-modal').addEventListener('click', () => {{
                this.openModal('matching-modal');
            }});
            
            document.getElementById('open-complement-modal').addEventListener('click', () => {{
                this.openModal('complement-modal');
            }});
            
            // Close button events
            document.getElementById('close-quiz-modal').addEventListener('click', () => {{
                this.closeModal('quiz-modal');
            }});
            
            document.getElementById('close-sorting-modal').addEventListener('click', () => {{
                this.closeModal('sorting-modal');
            }});
            
            document.getElementById('close-matching-modal').addEventListener('click', () => {{
                this.closeModal('matching-modal');
            }});
            
            document.getElementById('close-complement-modal').addEventListener('click', () => {{
                this.closeModal('complement-modal');
            }});
            
            // Fullscreen button events
            document.getElementById('quiz-fullscreen-btn').addEventListener('click', () => {{
                this.toggleFullscreen('quiz-modal');
            }});
            
            document.getElementById('sorting-fullscreen-btn').addEventListener('click', () => {{
                this.toggleFullscreen('sorting-modal');
            }});
            
            document.getElementById('matching-fullscreen-btn').addEventListener('click', () => {{
                this.toggleFullscreen('matching-modal');
            }});
            
            document.getElementById('complement-fullscreen-btn').addEventListener('click', () => {{
                this.toggleFullscreen('complement-modal');
            }});
            
            // Close modal when clicking outside
            document.addEventListener('click', (e) => {{
                if (e.target.classList.contains('modal') && e.target.classList.contains('show')) {{
                    this.closeModal(e.target.id);
                }}
            }});
            
            // ESC key to close modal
            document.addEventListener('keydown', (e) => {{
                if (e.key === 'Escape') {{
                    const openModal = document.querySelector('.modal.show');
                    if (openModal) {{
                        this.closeModal(openModal.id);
                    }}
                }}
            }});
            
            // Fullscreen change events
            document.addEventListener('fullscreenchange', () => {{
                this.handleFullscreenChange();
            }});
            
            document.addEventListener('webkitfullscreenchange', () => {{
                this.handleFullscreenChange();
            }});
            
            document.addEventListener('mozfullscreenchange', () => {{
                this.handleFullscreenChange();
            }});
            
            document.addEventListener('MSFullscreenChange', () => {{
                this.handleFullscreenChange();
            }});
        }}
        
        openModal(modalId) {{
            const modal = document.getElementById(modalId);
            modal.classList.add('show');
            document.body.style.overflow = 'hidden';
        }}
        
        closeModal(modalId) {{
            const modal = document.getElementById(modalId);
            if (this.isFullscreen) {{
                this.exitFullscreen();
            }}
            modal.classList.remove('show', 'fullscreen');
            document.body.style.overflow = '';
            
            // Stop active games when their modals are closed
            if (modalId === 'complement-modal' && this.complementRace && this.complementRace.isGameActive) {{
                console.log('🛑 Stopping active complement race due to modal close');
                this.complementRace.endRace('Game stopped - modal closed');
            }} else if (modalId === 'matching-modal' && this.matchingGame && this.matchingGame.gameActive) {{
                console.log('🛑 Stopping active matching game due to modal close');
                this.matchingGame.endGame();
            }} else if (modalId === 'sorting-modal' && this.sortingGame && this.sortingGame.gameActive) {{
                console.log('🛑 Stopping active sorting game due to modal close');
                this.sortingGame.endGame();
            }} else if (modalId === 'quiz-modal' && this.quizGame && this.quizGame.gameActive) {{
                console.log('🛑 Stopping active quiz game due to modal close');
                this.quizGame.endGame();
            }}
        }}
        
        async toggleFullscreen(modalId) {{
            const modal = document.getElementById(modalId);
            
            if (!this.isFullscreen) {{
                try {{
                    if (modal.requestFullscreen) {{
                        await modal.requestFullscreen();
                    }} else if (modal.webkitRequestFullscreen) {{
                        await modal.webkitRequestFullscreen();
                    }} else if (modal.mozRequestFullScreen) {{
                        await modal.mozRequestFullScreen();
                    }} else if (modal.msRequestFullscreen) {{
                        await modal.msRequestFullscreen();
                    }}
                    modal.classList.add('fullscreen');
                }} catch (error) {{
                    console.warn('Fullscreen not supported or failed:', error);
                    // Fallback to CSS fullscreen
                    modal.classList.add('fullscreen');
                }}
            }} else {{
                this.exitFullscreen();
            }}
        }}
        
        exitFullscreen() {{
            if (document.exitFullscreen) {{
                document.exitFullscreen();
            }} else if (document.webkitExitFullscreen) {{
                document.webkitExitFullscreen();
            }} else if (document.mozCancelFullScreen) {{
                document.mozCancelFullScreen();
            }} else if (document.msExitFullscreen) {{
                document.msExitFullscreen();
            }}
        }}
        
        handleFullscreenChange() {{
            const isFullscreen = !!(document.fullscreenElement || 
                                   document.webkitFullscreenElement || 
                                   document.mozFullScreenElement || 
                                   document.msFullscreenElement);
            
            this.isFullscreen = isFullscreen;
            
            if (!isFullscreen) {{
                // Remove fullscreen class from all modals when exiting fullscreen
                document.querySelectorAll('.modal').forEach(modal => {{
                    modal.classList.remove('fullscreen');
                }});
            }}
        }}
    }}
    
    // Quiz functionality - No dependencies, pure JavaScript
    class SorobanQuiz {{
        constructor() {{
            this.cards = [];
            this.quizCards = [];
            this.currentCardIndex = 0;
            this.displayTime = 2.0;
            this.selectedCount = 15;
            this.foundNumbers = [];
            this.correctAnswers = [];
            this.guessesRemaining = 0;
            this.currentInput = '';
            this.incorrectGuesses = 0;
            this.finishButtonsBound = false;
            this.prefixAcceptanceTimeout = null; // Timeout management for prefix conflicts
            
            this.initializeCards();
            this.bindEvents();
        }}
        
        initializeCards() {{
            // Extract card data from the DOM
            const cardElements = document.querySelectorAll('.flashcard');
            this.cards = Array.from(cardElements).map(card => ({{
                number: parseInt(card.dataset.number),
                svg: card.querySelector('.abacus-container').innerHTML,
                element: card
            }}));
        }}
        
        bindEvents() {{
            // Count buttons
            document.querySelectorAll('.count-btn').forEach(btn => {{
                btn.addEventListener('click', (e) => {{
                    document.querySelectorAll('.count-btn').forEach(b => b.classList.remove('active'));
                    btn.classList.add('active');
                    this.selectedCount = btn.dataset.count === 'all' ? this.cards.length : parseInt(btn.dataset.count);
                }});
            }});
            
            // Display time slider
            const slider = document.getElementById('display-time');
            const valueDisplay = document.querySelector('.slider-value');
            slider.addEventListener('input', (e) => {{
                this.displayTime = parseFloat(e.target.value);
                valueDisplay.textContent = this.displayTime.toFixed(1) + 's';
            }});
            
            // Start quiz button
            document.getElementById('start-quiz').addEventListener('click', () => {{
                this.startQuiz();
            }});
            
            // Note: Submit answers button replaced by smart input system
            
            // Note: Finish quiz buttons are bound later in showInputPhase() when they become visible
            
            // End quiz button
            document.getElementById('end-quiz').addEventListener('click', () => {{
                this.endQuiz();
            }});
            
            // Retry and back buttons
            document.getElementById('retry-quiz').addEventListener('click', () => {{
                this.resetQuiz();
                this.startQuiz();
            }});
            
            document.getElementById('back-to-cards').addEventListener('click', () => {{
                this.resetQuiz();
            }});
        }}
        
        async startQuiz() {{
            // Select random cards
            this.quizCards = this.getRandomCards(this.selectedCount);
            this.correctAnswers = this.quizCards.map(card => card.number);
            this.currentCardIndex = 0;
            
            // Hide configuration controls, show only game
            document.querySelector('.quiz-controls').style.display = 'none';
            
            // Show quiz game section within modal
            this.hideQuizSections();
            document.getElementById('quiz-game').style.display = 'block';
            document.getElementById('total-cards').textContent = this.quizCards.length;
            
            // Start with the first card
            this.showNextCard();
        }}
        
        getRandomCards(count) {{
            const shuffled = [...this.cards].sort(() => 0.5 - Math.random());
            return shuffled.slice(0, Math.min(count, this.cards.length));
        }}
        
        async showNextCard() {{
            if (this.currentCardIndex >= this.quizCards.length) {{
                this.showInputPhase();
                return;
            }}
            
            const card = this.quizCards[this.currentCardIndex];
            const progress = ((this.currentCardIndex) / this.quizCards.length) * 100;
            
            // Update progress
            document.querySelector('.progress-fill').style.width = progress + '%';
            document.getElementById('current-card').textContent = this.currentCardIndex + 1;
            
            // Only show countdown for the very first card
            if (this.currentCardIndex === 0) {{
                await this.showCountdown();
            }} else {{
                // Subtle "new card" indicator for subsequent cards
                await this.showNewCardIndicator();
            }}
            
            // Show card
            await this.displayCard(card);
            
            this.currentCardIndex++;
            
            // Minimal delay before next card (just enough for the exit animation)
            setTimeout(() => {{
                this.showNextCard();
            }}, 100);
        }}
        
        async showNewCardIndicator() {{
            return new Promise(resolve => {{
                const countdownEl = document.getElementById('quiz-countdown');
                const cardEl = document.getElementById('quiz-card');
                
                // Hide card temporarily
                cardEl.style.display = 'none';
                countdownEl.style.display = 'block';
                
                // Brief flash to indicate new card
                countdownEl.textContent = 'Next';
                countdownEl.className = 'quiz-countdown new-card-flash';
                
                setTimeout(() => {{
                    countdownEl.style.display = 'none';
                    resolve();
                }}, 150); // Very brief indication
            }});
        }}

        async showCountdown() {{
            const countdownEl = document.getElementById('quiz-countdown');
            const cardEl = document.getElementById('quiz-card');
            
            cardEl.style.visibility = 'hidden';
            countdownEl.style.display = 'block';
            
            // 3, 2, 1 countdown
            const counts = ['3', '2', '1', 'GO!'];
            
            for (let i = 0; i < counts.length; i++) {{
                countdownEl.textContent = counts[i];
                countdownEl.className = 'countdown';
                if (i === counts.length - 1) countdownEl.classList.add('go');
                
                await this.delay(400);
            }}
            
            countdownEl.style.display = 'none';
        }}
        
        async displayCard(card) {{
            const cardEl = document.getElementById('quiz-card');
            const countdownEl = document.getElementById('quiz-countdown');
            
            // Show card content with entry animation
            cardEl.innerHTML = card.svg;
            cardEl.style.display = 'block';
            cardEl.style.visibility = 'visible';
            cardEl.classList.add('pulse');
            
            // Display for most of the time
            await this.delay((this.displayTime * 1000) - 300);
            
            // Subtle exit signal - brief red border flash
            cardEl.classList.add('card-exit-warning');
            await this.delay(200);
            
            // Quick fade out
            cardEl.classList.add('card-fade-out');
            await this.delay(100);
            
            // Hide card and reset classes
            cardEl.classList.remove('pulse', 'card-exit-warning', 'card-fade-out');
            cardEl.style.visibility = 'hidden';
        }}
        
        showInputPhase() {{
            // Complete progress bar
            document.querySelector('.progress-fill').style.width = '100%';
            
            // Initialize smart input system
            this.correctAnswers = this.quizCards.map(card => card.number);
            this.foundNumbers = [];
            this.guessesRemaining = this.selectedCount + Math.floor(this.selectedCount / 2); // Allow 50% extra guesses
            
            // Update stats display
            document.getElementById('cards-shown-count').textContent = this.quizCards.length;
            document.getElementById('guesses-remaining').textContent = this.guessesRemaining;
            document.getElementById('numbers-found').textContent = '0';
            
            // Hide quiz game, show input
            this.hideQuizSections();
            document.getElementById('quiz-input').style.display = 'block';
            
            // Setup smart input
            const smartInput = document.getElementById('smart-input');
            const display = document.getElementById('number-display');
            smartInput.value = '';
            document.getElementById('current-typing').textContent = '';
            
            // Focus the hidden input and make sure it captures keyboard events
            smartInput.focus();
            
            // Remove any existing event listeners to prevent duplicates
            const newSmartInput = smartInput.cloneNode(true);
            smartInput.parentNode.replaceChild(newSmartInput, smartInput);
            
            // Add input event listener for real-time validation
            newSmartInput.addEventListener('input', (e) => this.handleSmartInput(e));
            
            // Make the display area clickable to maintain focus
            display.addEventListener('click', () => {{
                newSmartInput.focus();
            }});
            
            // Keep focus on the hidden input
            newSmartInput.focus();
            
            // Bind finish buttons (they exist now that quiz-input is shown)
            this.bindFinishButtons();
            
            // Show finish button when all numbers found or guesses exhausted
            this.updateFinishButtonVisibility();
        }}
        
        bindFinishButtons() {{
            // Bind finish quiz buttons - called when input phase starts and buttons are visible
            // Only bind once to prevent duplicate listeners
            if (this.finishButtonsBound) return;
            
            const finishBtn = document.getElementById('finish-quiz');
            const giveUpBtn = document.getElementById('give-up-quiz');
            
            if (finishBtn) {{
                finishBtn.addEventListener('click', () => {{
                    console.log('Finish quiz button clicked');
                    this.finishQuiz();
                }});
                console.log('Finish button event listener added');
            }} else {{
                console.error('finish-quiz button not found in DOM');
            }}
            
            if (giveUpBtn) {{
                giveUpBtn.addEventListener('click', () => {{
                    console.log('Give up button clicked');
                    this.finishQuiz();
                }});
                console.log('Give up button event listener added');
            }} else {{
                console.error('give-up-quiz button not found in DOM');
            }}
            
            this.finishButtonsBound = true;
        }}
        
        handleSmartInput(event) {{
            const input = event.target;
            const value = input.value.trim();
            const display = document.getElementById('number-display');
            const typingSpan = document.getElementById('current-typing');
            
            // Always clear any existing timeout first
            if (this.prefixAcceptanceTimeout) {{
                clearTimeout(this.prefixAcceptanceTimeout);
                this.prefixAcceptanceTimeout = null;
            }}
            
            // Reset visual feedback
            display.classList.remove('correct', 'incorrect');
            
            // Update the visual display
            typingSpan.textContent = value;
            
            // Check if input is empty
            if (!value) {{
                this.currentInput = '';
                return;
            }}
            
            // Check if it's a valid number
            const number = parseInt(value);
            if (isNaN(number)) {{
                return; // Wait for more input
            }}
            
            this.currentInput = value;
            
            // Check if this number is in our correct answers and not already found
            if (this.correctAnswers.includes(number) && !this.foundNumbers.includes(number)) {{
                // Check if this input is a prefix of any other correct answers
                if (!this.isPrefix(value, this.correctAnswers)) {{
                    // Safe to auto-accept immediately - no timeout needed
                    this.acceptCorrectNumber(number, input, display);
                }} else {{
                    // Brief delay for potential prefixes - store timeout ID
                    this.prefixAcceptanceTimeout = setTimeout(() => {{
                        this.prefixAcceptanceTimeout = null; // Clear reference
                        this.acceptCorrectNumber(number, input, display);
                    }}, 500);
                }}
            }} else if (value.length >= 2 && !this.correctAnswers.includes(number)) {{
                // Wrong number (only trigger after at least 2 digits to avoid false positives)
                this.handleIncorrectGuess(input, display);
            }}
        }}
        
        isPrefix(input, numbers) {{
            return numbers.some(n => n.toString().startsWith(input) && n.toString() !== input);
        }}
        
        acceptCorrectNumber(number, input, display) {{
            // Add to found numbers
            this.foundNumbers.push(number);
            
            // Visual success feedback
            display.classList.add('correct');
            
            // Update stats
            document.getElementById('numbers-found').textContent = this.foundNumbers.length;
            
            // Add to found numbers display
            this.addFoundNumberDisplay(number);
            
            // Clear input immediately for fast entry
            setTimeout(() => {{
                input.value = '';
                document.getElementById('current-typing').textContent = '';
                this.currentInput = '';
                
                // Check if we're done
                this.updateFinishButtonVisibility();
                
                // If all numbers found, auto-finish
                if (this.foundNumbers.length === this.correctAnswers.length) {{
                    setTimeout(() => this.finishQuiz(), 1000);
                }}
            }}, 150); // Much shorter delay - just enough to show the success feedback
            
            // Remove success visual feedback after animation completes
            setTimeout(() => {{
                display.classList.remove('correct');
            }}, 500);
        }}
        
        handleIncorrectGuess(input, display) {{
            // Only penalize if we have guesses remaining
            if (this.guessesRemaining > 0) {{
                this.guessesRemaining--;
                this.incorrectGuesses++; // Track incorrect guesses for scoring
                document.getElementById('guesses-remaining').textContent = this.guessesRemaining;
                
                // Visual error feedback
                display.classList.add('incorrect');
                
                // Clear input quickly for rapid entry
                setTimeout(() => {{
                    input.value = '';
                    document.getElementById('current-typing').textContent = '';
                    this.currentInput = '';
                    
                    // Check if we're out of guesses
                    this.updateFinishButtonVisibility();
                    if (this.guessesRemaining === 0) {{
                        setTimeout(() => this.finishQuiz(), 1000);
                    }}
                }}, 150); // Same fast clearing as correct numbers
                
                // Remove error visual feedback after animation completes
                setTimeout(() => {{
                    display.classList.remove('incorrect');
                }}, 500);
            }}
        }}
        
        addFoundNumberDisplay(number) {{
            const foundContainer = document.getElementById('found-numbers');
            const numberElement = document.createElement('span');
            numberElement.className = 'found-number';
            numberElement.textContent = number;
            foundContainer.appendChild(numberElement);
        }}
        
        updateFinishButtonVisibility() {{
            const finishBtn = document.getElementById('finish-quiz');
            const giveUpBtn = document.getElementById('give-up-quiz');
            
            const hasFoundSome = this.foundNumbers.length > 0;
            const hasFoundAll = this.foundNumbers.length === this.correctAnswers.length;
            const outOfGuesses = this.guessesRemaining === 0;
            const hasGuessesLeft = this.guessesRemaining > 0;
            
            if (hasFoundAll || outOfGuesses) {{
                // Show finish button when all found or no guesses left
                finishBtn.style.display = 'block';
                giveUpBtn.style.display = 'none';
                finishBtn.textContent = hasFoundAll ? 'Finish Quiz' : 'Show Results';
            }} else if (hasFoundSome && hasGuessesLeft) {{
                // Show both buttons when user has found some but could find more
                finishBtn.style.display = 'block';
                giveUpBtn.style.display = 'block';
                finishBtn.textContent = 'Show Results';
            }} else {{
                // No buttons when user hasn't found any yet
                finishBtn.style.display = 'none';
                giveUpBtn.style.display = 'none';
            }}
        }}
        
        finishQuiz() {{
            console.log('finishQuiz called, foundNumbers:', this.foundNumbers);
            // Use found numbers as answers and show results
            this.answers = [...this.foundNumbers];
            console.log('About to call showResults with answers:', this.answers);
            this.showResults();
        }}
        
        submitAnswers() {{
            const input = document.getElementById('answer-input').value;
            this.answers = this.parseAnswers(input);
            this.showResults();
        }}
        
        parseAnswers(input) {{
            // Parse comma or space separated numbers
            return input.split(/[,\\s]+/)
                       .map(s => s.trim())
                       .filter(s => s.length > 0)
                       .map(s => parseInt(s))
                       .filter(n => !isNaN(n));
        }}
        
        showResults() {{
            const scoreData = this.calculateScore();
            const correct = scoreData.correct;
            const finalScore = scoreData.finalScore;
            const percentage = Math.round(finalScore);
            
            // Update score display
            document.getElementById('score-percentage').textContent = percentage + '%';
            document.getElementById('score-correct').textContent = correct.length;
            document.getElementById('score-total').textContent = this.correctAnswers.length;
            document.getElementById('result-timing').textContent = this.displayTime.toFixed(1) + 's';
            
            // Show detailed results with penalty info
            this.showDetailedResults(correct, scoreData);
            
            // Hide input, show results
            this.hideQuizSections();
            document.getElementById('quiz-results').style.display = 'block';
        }}
        
        calculateScore() {{
            const correct = [];
            const correctSet = new Set(this.correctAnswers);
            const answerSet = new Set(this.answers);
            
            // Find correct answers
            this.answers.forEach(answer => {{
                if (correctSet.has(answer)) {{
                    correct.push(answer);
                }}
            }});
            
            // Calculate base score as percentage of correct answers
            const baseScore = (correct.length / this.correctAnswers.length) * 100;
            
            // Calculate penalty: lose 5 points per incorrect guess, minimum 0%
            const penalty = this.incorrectGuesses * 5;
            const finalScore = Math.max(0, baseScore - penalty);
            
            return {{
                correct: correct,
                baseScore: baseScore,
                penalty: penalty,
                incorrectGuesses: this.incorrectGuesses,
                finalScore: finalScore
            }};
        }}
        
        showDetailedResults(correct, scoreData) {{
            const resultsEl = document.getElementById('results-list');
            const correctSet = new Set(correct);
            const answerSet = new Set(this.answers);
            
            let html = '';
            
            // Show scoring breakdown if there were penalties
            if (scoreData && scoreData.incorrectGuesses > 0) {{
                html += `<div class="result-item score-breakdown">
                    <div style="margin-bottom: 10px; font-weight: bold; color: #2c5f76;">Score Breakdown:</div>
                    <div style="font-size: 0.9em; color: #666;">
                        Base Score: ${{Math.round(scoreData.baseScore)}}% (${{correct.length}} of ${{this.correctAnswers.length}} correct)<br>
                        Penalty: -${{scoreData.penalty}}% (${{scoreData.incorrectGuesses}} wrong guess${{scoreData.incorrectGuesses > 1 ? 'es' : ''}} × 5 points each)<br>
                        <strong style="color: #2c5f76;">Final Score: ${{Math.round(scoreData.finalScore)}}%</strong>
                    </div>
                </div>`;
            }}
            
            // Show all correct answers and whether user got them
            this.correctAnswers.forEach(num => {{
                const wasCorrect = correctSet.has(num);
                const className = wasCorrect ? 'result-correct' : 'result-incorrect';
                const status = wasCorrect ? '✓ Correct' : '✗ Missed';
                html += `<div class="result-item">
                    <span>Card: ${{num}}</span>
                    <span class="${{className}}">${{status}}</span>
                </div>`;
            }});
            
            // Show any extra incorrect answers
            const extraAnswers = this.answers.filter(a => !correctSet.has(a) && this.correctAnswers.includes(a) === false);
            extraAnswers.forEach(num => {{
                html += `<div class="result-item">
                    <span>Wrong guess: ${{num}}</span>
                    <span class="result-incorrect">✗ Not in quiz (-5 points)</span>
                </div>`;
            }});
            
            resultsEl.innerHTML = html;
        }}
        
        endQuiz() {{
            // Stop the current quiz and return to configuration
            this.cleanupQuizState();
            this.resetQuiz();
        }}
        
        resetQuiz() {{
            // Reset state
            this.currentCardIndex = 0;
            this.answers = [];
            this.correctAnswers = [];
            this.quizCards = [];
            this.foundNumbers = [];
            this.guessesRemaining = 0;
            this.currentInput = '';
            this.incorrectGuesses = 0;
            this.finishButtonsBound = false;
            
            // Clean up any pending timeouts
            this.cleanupQuizState();
            
        }}
        
        cleanupQuizState() {{
            // Clear any pending prefix acceptance timeout
            if (this.prefixAcceptanceTimeout) {{
                clearTimeout(this.prefixAcceptanceTimeout);
                this.prefixAcceptanceTimeout = null;
            }}
            
            // Clear smart input
            const smartInput = document.getElementById('smart-input');
            if (smartInput) {{
                smartInput.value = '';
                smartInput.classList.remove('correct', 'incorrect');
            }}
            
            // Clear found numbers display
            const foundContainer = document.getElementById('found-numbers');
            if (foundContainer) {{
                foundContainer.innerHTML = '';
            }}
            
            // Reset stats display
            document.getElementById('cards-shown-count').textContent = '0';
            document.getElementById('guesses-remaining').textContent = '0';
            document.getElementById('numbers-found').textContent = '0';
            
            // Hide finish buttons
            document.getElementById('finish-quiz').style.display = 'none';
            document.getElementById('give-up-quiz').style.display = 'none';
            
            // Reset to initial quiz state (hide all sections, show controls)
            this.hideQuizSections();
            document.querySelector('.quiz-controls').style.display = 'block';
        }}
        
        hideQuizSections() {{
            document.getElementById('quiz-game').style.display = 'none';
            document.getElementById('quiz-input').style.display = 'none';
            document.getElementById('quiz-results').style.display = 'none';
        }}
        
        delay(ms) {{
            return new Promise(resolve => setTimeout(resolve, ms));
        }}
    }}
    
    // Card Sorting Challenge - Drag and drop functionality
    class SortingChallenge {{
        constructor() {{
            this.cards = [];
            this.sortingCards = [];
            this.selectedCount = 5;
            this.currentOrder = [];
            this.correctOrder = [];
            this.isDragging = false;
            this.draggedElement = null;
            this.draggedIndex = -1;
            this.previewOrder = [];
            this.lastInsertIndex = -1;
            this.touchStartElement = null;
            this.touchStartIndex = -1;
            this.touchStartX = 0;
            this.touchStartY = 0;
            
            this.initializeSorting();
            this.bindSortingEvents();
        }}
        
        initializeSorting() {{
            // Get available cards (same as quiz cards)
            const cardElements = document.querySelectorAll('.flashcard');
            this.cards = Array.from(cardElements).map(card => ({{
                number: parseInt(card.dataset.number),
                svg: card.querySelector('.abacus-container').outerHTML
            }}));
        }}
        
        bindSortingEvents() {{
            // Card count selection
            document.querySelectorAll('.sort-count-btn').forEach(btn => {{
                btn.addEventListener('click', (e) => {{
                    document.querySelectorAll('.sort-count-btn').forEach(b => b.classList.remove('active'));
                    e.target.classList.add('active');
                    this.selectedCount = parseInt(e.target.dataset.count);
                }});
            }});
            
            // Action buttons
            document.getElementById('start-sorting').addEventListener('click', () => this.startSorting());
            document.getElementById('check-sorting').addEventListener('click', () => this.checkSolution());
            document.getElementById('reveal-numbers').addEventListener('click', () => this.revealNumbers());
            document.getElementById('new-sorting').addEventListener('click', () => this.newChallenge());
            document.getElementById('end-sorting').addEventListener('click', () => this.endSorting());
            
            // Score modal event listeners
            document.querySelector('.score-modal-close').addEventListener('click', () => this.hideScoreModal());
            document.getElementById('score-modal-close-btn').addEventListener('click', () => this.hideScoreModal());
            document.getElementById('score-modal-new-game').addEventListener('click', () => {{
                this.hideScoreModal();
                this.newChallenge();
            }});
            
            // Close modal when clicking outside
            document.getElementById('score-modal').addEventListener('click', (e) => {{
                if (e.target.id === 'score-modal') {{
                    this.hideScoreModal();
                }}
            }});
        }}
        
        startSorting() {{
            // Select random cards for sorting
            const shuffledCards = [...this.cards].sort(() => Math.random() - 0.5);
            this.sortingCards = shuffledCards.slice(0, this.selectedCount);
            this.correctOrder = [...this.sortingCards].sort((a, b) => a.number - b.number);
            
            // Shuffle the display order
            this.currentOrder = [...this.sortingCards].sort(() => Math.random() - 0.5);
            
            // Initialize revealed state
            this.numbersRevealed = false;
            
            // Hide configuration controls, show only game
            document.querySelector('.sorting-controls').style.display = 'none';
            
            // Show sorting game and sticky header
            document.getElementById('sorting-game').style.display = 'block';
            document.getElementById('sorting-header').style.display = 'block';
            
            this.renderSortingCards();
            this.updateSortingStatus(`Arrange the ${{this.selectedCount}} cards in ascending order (smallest to largest)`);
            
            // Start timer
            this.startTimer();
            
            // Reset reveal numbers button for new game
            document.getElementById('reveal-numbers').style.display = 'inline-block';
            
            // Update buttons - hide old controls, sticky header is now visible
            document.getElementById('start-sorting').style.display = 'none';
            document.querySelector('.sorting-game-actions').style.display = 'none';
        }}
        
        getSequenceStyle(position, totalSlots) {{
            // Generate neutral warm gray gradient that won't clash with abacus colors
            // Position 0 (first) = darkest, last position = lightest
            const intensity = position / (totalSlots - 1); // 0 to 1
            const lightness = 30 + (intensity * 45); // 30% to 75% lightness for better contrast
            return {{
                background: `hsl(220, 8%, ${{lightness}}%)`, // Very subtle blue-gray, low saturation
                color: lightness > 60 ? '#2c3e50' : '#ffffff', // High contrast text
                borderColor: lightness > 60 ? '#2c5f76' : 'rgba(255,255,255,0.4)'
            }};
        }}

        renderSortingCards() {{
            this.createPositionSlots();
            this.renderAvailableCards();
        }}
        
        createPositionSlots() {{
            const slotsContainer = document.getElementById('position-slots');
            if (!slotsContainer) return;
            
            slotsContainer.innerHTML = '';
            this.placedCards = new Array(this.selectedCount).fill(null);
            
            // Add insert button before the very first position
            const firstInsertBtn = document.createElement('button');
            firstInsertBtn.className = 'insert-button';
            firstInsertBtn.innerHTML = '+';
            firstInsertBtn.dataset.insertAt = 0;
            firstInsertBtn.addEventListener('click', (e) => this.handleInsertClick(0));
            slotsContainer.appendChild(firstInsertBtn);
            
            for (let i = 0; i < this.selectedCount; i++) {{
                // Add the position slot
                const slot = document.createElement('div');
                slot.className = 'position-slot';
                slot.dataset.position = i;
                
                // Apply gradient to entire slot background
                const style = this.getSequenceStyle(i, this.selectedCount);
                slot.style.background = style.background;
                slot.style.color = style.color;
                slot.style.borderColor = style.borderColor;
                
                slot.innerHTML = `
                    <div class="slot-label" style="color: ${{style.color}}">${{i === 0 ? 'Smallest' : i === this.selectedCount - 1 ? 'Largest' : ''}}</div>
                `;
                
                slot.addEventListener('click', (e) => this.handleSlotClick(i));
                slotsContainer.appendChild(slot);
                
                // Add insert button after each position
                const insertBtn = document.createElement('button');
                insertBtn.className = 'insert-button';
                insertBtn.innerHTML = '+';
                insertBtn.dataset.insertAt = i + 1;
                insertBtn.addEventListener('click', (e) => this.handleInsertClick(i + 1));
                slotsContainer.appendChild(insertBtn);
            }}
        }}
        
        renderAvailableCards() {{
            const sortingArea = document.getElementById('sorting-area');
            if (!sortingArea) return;
            
            sortingArea.innerHTML = '';
            
            // Remove duplicates and filter out placed cards
            const uniqueAvailable = this.currentOrder.filter((card, index, arr) => {{
                // Only keep first occurrence of each card number
                const firstIndex = arr.findIndex(c => c.number === card.number);
                if (firstIndex !== index) {{
                    console.warn(`Duplicate card found: ${{card.number}}, removing duplicate`);
                    return false;
                }}
                
                // Skip if already placed
                if (this.placedCards.some(placed => placed && placed.number === card.number)) {{
                    console.warn(`Card ${{card.number}} is both available and placed, removing from available`);
                    return false;
                }}
                
                return true;
            }});
            
            // Update currentOrder to clean version
            this.currentOrder = uniqueAvailable;
            
            this.currentOrder.forEach((card, index) => {{
                const cardEl = document.createElement('div');
                cardEl.className = 'sort-card';
                cardEl.dataset.number = card.number;
                
                // Apply revealed state if numbers were previously revealed
                if (this.numbersRevealed) {{
                    cardEl.classList.add('revealed');
                }}
                
                cardEl.innerHTML = `
                    <div class="revealed-number">${{card.number}}</div>
                    <div class="card-svg">${{card.svg}}</div>
                `;
                
                cardEl.addEventListener('click', (e) => this.handleCardClick(card, cardEl));
                sortingArea.appendChild(cardEl);
            }});
        }}
        
        handleCardClick(card, cardElement) {{
            // Clear any previously selected cards
            document.querySelectorAll('.sort-card.selected').forEach(el => {{
                el.classList.remove('selected');
            }});
            
            // Select this card
            cardElement.classList.add('selected');
            this.selectedCard = card;
            this.selectedCardElement = cardElement;
            
            // Highlight available positions and insert buttons
            document.querySelectorAll('.position-slot').forEach(slot => {{
                if (!slot.classList.contains('filled')) {{
                    slot.classList.add('active');
                }}
            }});
            
            document.querySelectorAll('.insert-button').forEach(btn => {{
                btn.classList.add('active');
            }});
            
            this.updateSortingStatus(`Selected card with value ${{card.number}}. Click a position or + button to place it.`);
        }}
        
        handleInsertClick(insertPosition) {{
            if (!this.selectedCard) {{
                this.updateSortingStatus('Please select a card first, then click where to insert it.');
                return;
            }}
            
            // Handle insertion at the rightmost position (beyond current array bounds)
            if (insertPosition >= this.selectedCount) {{
                // Find the rightmost empty position
                let rightmostEmptyPos = -1;
                for (let i = this.selectedCount - 1; i >= 0; i--) {{
                    if (this.placedCards[i] === null) {{
                        rightmostEmptyPos = i;
                        break;
                    }}
                }}
                
                if (rightmostEmptyPos === -1) {{
                    this.updateSortingStatus('All positions are filled. Move a card first to make room.');
                    return;
                }}
                
                // Place card in the rightmost empty position
                this.placedCards[rightmostEmptyPos] = this.selectedCard;
            }} else {{
                // Create a new array for placed cards
                const newPlacedCards = new Array(this.selectedCount).fill(null);
                
                // Copy existing cards, shifting them as needed
                for (let i = 0; i < this.placedCards.length; i++) {{
                    if (this.placedCards[i] !== null) {{
                        if (i < insertPosition) {{
                            // Cards before insert position stay in same place
                            newPlacedCards[i] = this.placedCards[i];
                        }} else {{
                            // Cards at or after insert position shift right by 1
                            if (i + 1 < this.selectedCount) {{
                                newPlacedCards[i + 1] = this.placedCards[i];
                            }} else {{
                                // Card would fall off - store temporarily, will handle below
                                newPlacedCards[i + 1] = this.placedCards[i];
                            }}
                        }}
                    }}
                }}
                
                // Place the selected card at the insert position
                newPlacedCards[insertPosition] = this.selectedCard;
                
                // Now apply gap-filling logic: shift cards left to compress and eliminate gaps
                const compactedCards = [];
                for (let i = 0; i < newPlacedCards.length; i++) {{
                    if (newPlacedCards[i] !== null) {{
                        compactedCards.push(newPlacedCards[i]);
                    }}
                }}
                
                // If we have more cards than positions, put excess back in available
                if (compactedCards.length > this.selectedCount) {{
                    const excessCards = compactedCards.slice(this.selectedCount);
                    this.currentOrder.push(...excessCards);
                    compactedCards.splice(this.selectedCount);
                }}
                
                // Fill the final array with compacted cards (no gaps)
                const finalPlacedCards = new Array(this.selectedCount).fill(null);
                for (let i = 0; i < compactedCards.length; i++) {{
                    finalPlacedCards[i] = compactedCards[i];
                }}
                
                this.placedCards = finalPlacedCards;
            }}
            
            // Remove card from available cards
            this.currentOrder = this.currentOrder.filter(c => c.number !== this.selectedCard.number);
            
            // Debug: Check total card count
            this.debugCardCount('after insert');
            
            // Clear selection and re-render
            this.clearSelection();
            this.updatePositionSlots();
            this.renderAvailableCards();
            
            // Update status
            const placedCount = this.placedCards.filter(c => c !== null).length;
            if (placedCount === this.selectedCount) {{
                this.updateSortingStatus('All cards placed! Click "Check My Solution" to see how you did.');
            }} else {{
                this.updateSortingStatus(`${{placedCount}}/${{this.selectedCount}} cards placed. Select another card to continue.`);
            }}
        }}
        
        debugCardCount(context) {{
            const placedCount = this.placedCards.filter(c => c !== null).length;
            const availableCount = this.currentOrder.length;
            const totalCount = placedCount + availableCount;
            
            console.log(`DEBUG ${{context}}: Placed=${{placedCount}}, Available=${{availableCount}}, Total=${{totalCount}}, Expected=${{this.selectedCount}}`);
            
            if (totalCount !== this.selectedCount) {{
                console.error('Card count mismatch! Some cards are missing or duplicated.');
                console.log('Placed cards:', this.placedCards.map(c => c ? c.number : 'empty'));
                console.log('Available cards:', this.currentOrder.map(c => c.number));
            }}
        }}
        
        updatePositionSlots() {{
            this.placedCards.forEach((card, position) => {{
                const slot = document.querySelector(`[data-position="${{position}}"]`);
                if (!slot) return;
                
                if (card) {{
                    slot.classList.add('filled');
                    // Reset to white background when filled
                    slot.style.background = '#fff';
                    slot.style.color = '#333';
                    slot.style.borderColor = '#2c5f76';
                    slot.innerHTML = `
                        <div class="slot-card">
                            <div class="card-svg">${{card.svg}}</div>
                        </div>
                        <div class="slot-label">← Click to move back</div>
                    `;
                }} else {{
                    slot.classList.remove('filled');
                    // Apply gradient to empty slot
                    const style = this.getSequenceStyle(position, this.selectedCount);
                    slot.style.background = style.background;
                    slot.style.color = style.color;
                    slot.style.borderColor = style.borderColor;
                    slot.innerHTML = `
                        <div class="slot-label" style="color: ${{style.color}}">${{position === 0 ? 'Smallest' : position === this.selectedCount - 1 ? 'Largest' : ''}}</div>
                    `;
                }}
            }});
        }}
        
        clearSelection() {{
            this.selectedCard = null;
            this.selectedCardElement = null;
            
            // Remove active states
            document.querySelectorAll('.sort-card.selected').forEach(el => {{
                el.classList.remove('selected');
            }});
            document.querySelectorAll('.position-slot.active').forEach(el => {{
                el.classList.remove('active');
            }});
            document.querySelectorAll('.insert-button.active').forEach(el => {{
                el.classList.remove('active');
            }});
        }}
        
        handleSlotClick(position) {{
            const slot = document.querySelector(`[data-position="${{position}}"]`);
            
            // If no card is selected but slot has a card, move it back to available
            if (!this.selectedCard && this.placedCards[position]) {{
                const cardToMove = this.placedCards[position];
                
                // Remove card from this position
                this.placedCards[position] = null;
                
                // Add card back to available cards
                this.currentOrder.push(cardToMove);
                
                // Debug: Check total card count
                this.debugCardCount('after moving card back');
                
                // Update slot appearance
                this.updatePositionSlots();
                this.renderAvailableCards();
                
                // Auto-select the moved card so user can immediately place it elsewhere
                this.selectedCard = cardToMove;
                this.selectedCardElement = document.querySelector(`[data-number="${{cardToMove.number}}"]`);
                if (this.selectedCardElement) {{
                    this.selectedCardElement.classList.add('selected');
                    
                    // Highlight available positions
                    document.querySelectorAll('.position-slot').forEach(slot => {{
                        if (!slot.classList.contains('filled')) {{
                            slot.classList.add('active');
                        }}
                    }});
                    document.querySelectorAll('.insert-button').forEach(btn => {{
                        btn.classList.add('active');
                        btn.classList.remove('disabled');
                    }});
                }}
                
                const placedCount = this.placedCards.filter(c => c !== null).length;
                this.updateSortingStatus(`Moved card ${{cardToMove.number}} back and selected it. ${{placedCount}}/${{this.selectedCount}} cards placed.`);
                return;
            }}
            
            if (!this.selectedCard) {{
                this.updateSortingStatus('Select a card first, or click a placed card to move it back.');
                return;
            }}
            
            // If slot is already filled, replace the card
            if (this.placedCards[position]) {{
                // Move the previous card back to available area
                this.currentOrder.push(this.placedCards[position]);
            }}
            
            // Place the selected card in this position
            this.placedCards[position] = this.selectedCard;
            
            // Remove card from current order (available cards)
            this.currentOrder = this.currentOrder.filter(c => c.number !== this.selectedCard.number);
            
            // Debug: Check total card count
            this.debugCardCount('after regular placement');
            
            // Update slot appearance
            slot.classList.add('filled');
            // Reset to white background when filled
            slot.style.background = '#fff';
            slot.style.color = '#333';
            slot.style.borderColor = '#2c5f76';
            slot.innerHTML = `
                <div class="slot-card">
                    <div class="card-svg">${{this.selectedCard.svg}}</div>
                </div>
                <div class="slot-label">← Click to move back</div>
            `;
            
            // Clear selection and re-render
            this.clearSelection();
            this.renderAvailableCards();
            
            // Update status
            const placedCount = this.placedCards.filter(c => c !== null).length;
            if (placedCount === this.selectedCount) {{
                this.updateSortingStatus('All cards placed! Click "Check My Solution" to see how you did.');
            }} else {{
                this.updateSortingStatus(`${{placedCount}}/${{this.selectedCount}} cards placed. Select another card to continue.`);
            }}
        }}
        
        handleDragEnd(e) {{
            if (this.previewOrder.length > 0) {{
                // Commit the preview order to the actual order
                this.currentOrder = [...this.previewOrder];
            }}
            
            // Clean up
            this.resetDragState();
            
            // Re-render with final positions
            this.renderSortingCards();
            
            // Add success animation
            setTimeout(() => {{
                document.querySelectorAll('.sort-card').forEach(card => {{
                    card.classList.add('success');
                    setTimeout(() => card.classList.remove('success'), 600);
                }});
            }}, 100);
        }}
        
        handleDragOver(e) {{
            if (e.preventDefault) e.preventDefault();
            e.dataTransfer.dropEffect = 'move';
            
            // Calculate where to insert based on mouse position
            const insertIndex = this.calculateInsertIndex(e.clientX, e.clientY);
            console.log('DragOver - insertIndex:', insertIndex, 'lastInsertIndex:', this.lastInsertIndex);
            if (insertIndex !== -1 && insertIndex !== this.lastInsertIndex) {{
                console.log('Calling updatePreviewOrder with insertIndex:', insertIndex);
                this.updatePreviewOrder(insertIndex);
            }}
            
            return false;
        }}
        
        handleDragEnter(e) {{
            // Handle drag enter for the sorting area
        }}
        
        handleDragLeave(e) {{
            // Handle drag leave
        }}
        
        handleDrop(e) {{
            if (e.stopPropagation) e.stopPropagation();
            // The preview order is already set, just let dragEnd handle the commit
            return false;
        }}
        
        calculateInsertIndex(clientX, clientY) {{
            const sortingArea = document.getElementById('sorting-area');
            const cards = Array.from(sortingArea.querySelectorAll('.sort-card:not(.dragging)'));
            
            if (cards.length === 0) return 0;
            
            
            // Simple approach: find which card the mouse is over
            for (let i = 0; i < cards.length; i++) {{
                const card = cards[i];
                const rect = card.getBoundingClientRect();
                
                // Check if mouse is over this card
                if (clientX >= rect.left && clientX <= rect.right && 
                    clientY >= rect.top && clientY <= rect.bottom) {{
                    
                    const cardIndex = parseInt(card.dataset.index);
                    const cardCenterX = rect.left + rect.width / 2;
                    
                    const insertIndex = clientX < cardCenterX ? cardIndex : cardIndex + 1;
                    return insertIndex;
                }}
            }}
            
            return this.currentOrder.length;
        }}
        
        updatePreviewOrder(insertIndex) {{
            if (this.lastInsertIndex === insertIndex) return; // No change needed
            this.lastInsertIndex = insertIndex;
            
            console.log('updatePreviewOrder called with insertIndex:', insertIndex);
            console.log('currentOrder:', this.currentOrder.map(c => c.number));
            console.log('draggedIndex:', this.draggedIndex);
            
            // Create new preview order
            const newOrder = [...this.currentOrder];
            const draggedCard = newOrder.splice(this.draggedIndex, 1)[0];
            
            // Adjust insert index if we removed an item before it
            let adjustedInsertIndex = insertIndex;
            if (this.draggedIndex < insertIndex) {{
                adjustedInsertIndex--;
            }}
            
            // Insert at new position
            newOrder.splice(adjustedInsertIndex, 0, draggedCard);
            this.previewOrder = newOrder;
            
            console.log('New preview order:', this.previewOrder.map(c => c.number));
            
            // Update the visual layout immediately
            this.renderPreview();
        }}
        
        renderPreview() {{
            console.log('renderPreview called');
            const sortingArea = document.getElementById('sorting-area');
            
            // Get all cards except the dragged one
            const cards = Array.from(sortingArea.querySelectorAll('.sort-card:not(.dragging)'));
            console.log('Found cards (excluding dragged):', cards.length);
            
            const draggedNumber = parseInt(this.draggedElement.dataset.number);
            
            // Simply compare the full orders - if they're different, reorder
            const previewNumbers = this.previewOrder.map(c => c.number);
            const currentNumbers = this.currentOrder.map(c => c.number);
            
            console.log('Preview order:', previewNumbers);
            console.log('Current order:', currentNumbers);
            
            // Check if the orders are different
            const needsReorder = !previewNumbers.every((num, index) => currentNumbers[index] === num);
            
            console.log('Needs reorder:', needsReorder);
            
            if (needsReorder) {{
                console.log('Performing reorder...');
                
                // Update currentOrder to match preview (this is key!)
                this.currentOrder = [...this.previewOrder];
                
                // Create a simple reordering without removing cards from DOM
                // Just change their visual order using CSS flexbox order or reinsert in correct order
                
                const previewWithoutDragged = this.previewOrder.filter(card => card.number !== draggedNumber);
                console.log('Cards to reorder:', previewWithoutDragged.map(c => c.number));
                console.log('Available DOM cards:', cards.map(c => parseInt(c.dataset.number)));
                
                // Store references to all current cards
                const cardElements = new Map();
                cards.forEach(card => {{
                    cardElements.set(parseInt(card.dataset.number), card);
                }});
                
                // Reorder by moving each card to the correct position
                previewWithoutDragged.forEach((card, targetIndex) => {{
                    const cardEl = cardElements.get(card.number);
                    console.log('Finding card', card.number, 'found element:', !!cardEl);
                    if (cardEl) {{
                        cardEl.dataset.index = targetIndex;
                        cardEl.querySelector('.card-position').textContent = targetIndex + 1;
                        
                        // Move to correct position in DOM
                        const currentIndex = Array.from(sortingArea.children).indexOf(cardEl);
                        const targetPosition = targetIndex;
                        
                        if (currentIndex !== targetPosition) {{
                            if (targetPosition >= sortingArea.children.length - 1) {{
                                sortingArea.appendChild(cardEl);
                            }} else {{
                                const nextSibling = sortingArea.children[targetPosition];
                                sortingArea.insertBefore(cardEl, nextSibling);
                            }}
                        }}
                    }}
                }});
                
                // Ensure dragged element stays at the end for z-index
                if (this.draggedElement && this.draggedElement.parentNode === sortingArea) {{
                    sortingArea.appendChild(this.draggedElement);
                }}
            }}
        }}
        
        resetDragState() {{
            if (this.draggedElement) {{
                this.draggedElement.classList.remove('dragging');
                this.draggedElement.style.transform = '';
                this.draggedElement.style.position = '';
                this.draggedElement.style.pointerEvents = '';
            }}
            this.isDragging = false;
            this.draggedElement = null;
            this.draggedIndex = -1;
            this.previewOrder = [];
            this.lastInsertIndex = -1;
        }}
        
        // Enhanced touch support for mobile with real-time reordering
        handleTouchStart(e) {{
            const touch = e.touches[0];
            this.touchStartX = touch.clientX;
            this.touchStartY = touch.clientY;
            this.touchStartElement = e.target.closest('.sort-card');
            this.touchStartIndex = this.touchStartElement ? parseInt(this.touchStartElement.dataset.index) : -1;
            
            if (this.touchStartElement) {{
                this.isDragging = true;
                this.draggedElement = this.touchStartElement;
                this.draggedIndex = this.touchStartIndex;
                this.previewOrder = [...this.currentOrder];
                this.lastInsertIndex = -1;
                
                this.touchStartElement.classList.add('dragging');
                this.createPlaceholder();
            }}
        }}
        
        handleTouchMove(e) {{
            e.preventDefault();
            
            if (this.touchStartElement && this.isDragging) {{
                const touch = e.touches[0];
                
                // Update dragged element position
                const deltaX = touch.clientX - this.touchStartX;
                const deltaY = touch.clientY - this.touchStartY;
                this.touchStartElement.style.transform = `translate(${{deltaX}}px, ${{deltaY}}px) rotate(5deg) scale(1.05)`;
                
                // Calculate insert position and update preview
                const insertIndex = this.calculateInsertIndex(touch.clientX, touch.clientY);
                if (insertIndex !== -1) {{
                    this.updatePreviewOrder(insertIndex);
                }}
            }}
        }}
        
        handleTouchEnd(e) {{
            if (!this.touchStartElement || !this.isDragging) return;
            
            // Commit the preview order
            this.currentOrder = [...this.previewOrder];
            
            // Clean up
            this.touchStartElement.classList.remove('dragging');
            this.touchStartElement.style.transform = '';
            this.removePlaceholder();
            
            this.isDragging = false;
            this.draggedElement = null;
            this.draggedIndex = -1;
            this.previewOrder = [];
            this.lastInsertIndex = -1;
            
            // Re-render final positions
            this.renderSortingCards();
            
            // Success animation
            setTimeout(() => {{
                document.querySelectorAll('.sort-card').forEach(card => {{
                    card.classList.add('success');
                    setTimeout(() => card.classList.remove('success'), 600);
                }});
            }}, 100);
            
            this.touchStartElement = null;
            this.touchStartIndex = -1;
        }}
        
        checkSolution() {{
            if (this.placedCards.some(card => card === null)) {{
                this.updateSortingStatus('Please place all cards before checking your solution.');
                return;
            }}
            
            // Get the sequences for comparison
            const userSequence = this.placedCards.map(card => card.number);
            const correctSequence = this.correctOrder.map(card => card.number);
            
            // Calculate fair score using sequence alignment
            const scoreResult = this.calculateSequenceScore(userSequence, correctSequence);
            
            // Update visual feedback for each position
            this.placedCards.forEach((card, index) => {{
                const slot = document.querySelector(`[data-position="${{index}}"]`);
                const isExactMatch = card.number === this.correctOrder[index].number;
                
                if (isExactMatch) {{
                    slot.classList.add('correct');
                    slot.classList.remove('incorrect');
                }} else {{
                    slot.classList.add('incorrect');
                    slot.classList.remove('correct');
                }}
            }});
            
            this.showAdvancedFeedback(userSequence, correctSequence);
        }}
        
        calculateSequenceScore(userSeq, correctSeq) {{
            // Calculate Longest Common Subsequence (LCS) score
            const lcsLength = this.longestCommonSubsequence(userSeq, correctSeq);
            
            // Calculate how many cards are in correct relative order
            const relativeOrderScore = (lcsLength / correctSeq.length) * 100;
            
            // Calculate exact position matches
            let exactMatches = 0;
            for (let i = 0; i < userSeq.length; i++) {{
                if (userSeq[i] === correctSeq[i]) {{
                    exactMatches++;
                }}
            }}
            const exactScore = (exactMatches / correctSeq.length) * 100;
            
            // Calculate inversion count (how "scrambled" the sequence is)
            const inversions = this.countInversions(userSeq, correctSeq);
            const maxInversions = (correctSeq.length * (correctSeq.length - 1)) / 2;
            const inversionScore = Math.max(0, ((maxInversions - inversions) / maxInversions) * 100);
            
            // Weighted final score: 
            // - 50% for having cards in correct relative order (LCS)
            // - 30% for exact position matches
            // - 20% for overall sequence organization (inversions)
            const finalScore = Math.round(
                (relativeOrderScore * 0.5) + 
                (exactScore * 0.3) + 
                (inversionScore * 0.2)
            );
            
            return {{
                percentage: finalScore,
                exactMatches: exactMatches,
                correctRelativeOrder: lcsLength,
                totalCards: correctSeq.length,
                details: {{
                    relativeOrderScore: Math.round(relativeOrderScore),
                    exactScore: Math.round(exactScore),
                    inversionScore: Math.round(inversionScore),
                    inversions: inversions
                }}
            }};
        }}
        
        longestCommonSubsequence(seq1, seq2) {{
            const m = seq1.length;
            const n = seq2.length;
            const dp = Array(m + 1).fill().map(() => Array(n + 1).fill(0));
            
            for (let i = 1; i <= m; i++) {{
                for (let j = 1; j <= n; j++) {{
                    if (seq1[i - 1] === seq2[j - 1]) {{
                        dp[i][j] = dp[i - 1][j - 1] + 1;
                    }} else {{
                        dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
                    }}
                }}
            }}
            
            return dp[m][n];
        }}
        
        countInversions(userSeq, correctSeq) {{
            // Create a mapping from value to correct position
            const correctPositions = {{}};
            correctSeq.forEach((val, idx) => {{
                correctPositions[val] = idx;
            }});
            
            // Convert user sequence to "correct position" sequence
            const userCorrectPositions = userSeq.map(val => correctPositions[val]);
            
            // Count inversions in this position sequence
            let inversions = 0;
            for (let i = 0; i < userCorrectPositions.length; i++) {{
                for (let j = i + 1; j < userCorrectPositions.length; j++) {{
                    if (userCorrectPositions[i] > userCorrectPositions[j]) {{
                        inversions++;
                    }}
                }}
            }}
            
            return inversions;
        }}
        
        showAdvancedFeedback(userSeq, correctSeq) {{
            const feedbackEl = document.getElementById('sorting-feedback');
            
            // Calculate advanced scoring metrics
            const lcsLength = this.longestCommonSubsequence(userSeq, correctSeq);
            const relativeOrderScore = (lcsLength / correctSeq.length) * 100;
            
            // Calculate exact position matches
            let exactMatches = 0;
            for (let i = 0; i < Math.min(userSeq.length, correctSeq.length); i++) {{
                if (userSeq[i] === correctSeq[i]) {{
                    exactMatches++;
                }}
            }}
            const exactScore = (exactMatches / correctSeq.length) * 100;
            
            // Calculate inversion score
            const inversions = this.countInversions(userSeq, correctSeq);
            const maxInversions = (correctSeq.length * (correctSeq.length - 1)) / 2;
            const inversionScore = Math.max(0, ((maxInversions - inversions) / maxInversions) * 100);
            
            // Weighted final score
            const finalScore = Math.round(
                (relativeOrderScore * 0.5) + 
                (exactScore * 0.3) + 
                (inversionScore * 0.2)
            );
            
            const isPerfect = finalScore === 100;
            
            let feedbackClass, message;
            
            if (isPerfect) {{
                feedbackClass = 'feedback-perfect';
                message = '🎉 Perfect! All cards in correct order!';
            }} else if (finalScore >= 80) {{
                feedbackClass = 'feedback-good';
                message = '👍 Excellent! Very close to perfect!';
            }} else if (finalScore >= 60) {{
                feedbackClass = 'feedback-good';
                message = '👍 Good job! You understand the pattern!';
            }} else {{
                feedbackClass = 'feedback-needs-work';
                message = '💪 Keep practicing! Focus on reading each abacus carefully.';
            }}
            
            // Show score in modal instead of inline
            this.showScoreModal({{
                finalScore,
                message,
                relativeOrderScore,
                exactScore,
                inversionScore,
                lcsLength,
                correctSeq,
                exactMatches,
                feedbackClass,
                elapsedTime: this.getElapsedTime()
            }});
            
            // Keep inline feedback hidden
            feedbackEl.style.display = 'none';
            
            this.updateSortingStatus(isPerfect ? 'Perfect solution!' : `${{finalScore}}% score`);
        }}
        
        revealNumbers() {{
            // Track revealed state
            this.numbersRevealed = true;
            
            document.querySelectorAll('.sort-card').forEach(card => {{
                card.classList.add('revealed');
            }});
            
            document.getElementById('reveal-numbers').style.display = 'none';
            this.updateSortingStatus('Numbers revealed - now you can see the correct order!');
        }}
        
        startTimer() {{
            this.startTime = Date.now();
            this.timerInterval = setInterval(() => {{
                const elapsed = Math.floor((Date.now() - this.startTime) / 1000);
                const minutes = Math.floor(elapsed / 60);
                const seconds = elapsed % 60;
                document.getElementById('sorting-timer').textContent = 
                    `${{minutes}}:${{seconds.toString().padStart(2, '0')}}`;
            }}, 1000);
        }}
        
        stopTimer() {{
            if (this.timerInterval) {{
                clearInterval(this.timerInterval);
                this.timerInterval = null;
            }}
        }}
        
        getElapsedTime() {{
            if (this.startTime) {{
                return Math.floor((Date.now() - this.startTime) / 1000);
            }}
            return 0;
        }}
        
        showScoreModal(scoreData) {{
            const {{ 
                finalScore, message, relativeOrderScore, exactScore, inversionScore,
                lcsLength, correctSeq, exactMatches, feedbackClass, elapsedTime 
            }} = scoreData;
            
            const minutes = Math.floor(elapsedTime / 60);
            const seconds = elapsedTime % 60;
            const timeDisplay = `${{minutes}}:${{seconds.toString().padStart(2, '0')}}`;
            
            document.getElementById('score-modal-body').innerHTML = `
                <div class="feedback-score">${{finalScore}}%</div>
                <div class="feedback-message">${{message}}</div>
                <div class="feedback-time">⏱️ Time: ${{timeDisplay}}</div>
                <div class="feedback-breakdown">
                    <div class="score-component">
                        <span class="component-label">Sequence Order:</span>
                        <span class="component-score">${{Math.round(relativeOrderScore)}}%</span>
                        <span class="component-weight">(50% weight)</span>
                    </div>
                    <div class="score-component">
                        <span class="component-label">Exact Positions:</span>
                        <span class="component-score">${{Math.round(exactScore)}}%</span>
                        <span class="component-weight">(30% weight)</span>
                    </div>
                    <div class="score-component">
                        <span class="component-label">Organization:</span>
                        <span class="component-score">${{Math.round(inversionScore)}}%</span>
                        <span class="component-weight">(20% weight)</span>
                    </div>
                </div>
                <div class="feedback-details">
                    Cards in correct order: ${{lcsLength}}/${{correctSeq.length}} • 
                    Exact position matches: ${{exactMatches}}/${{correctSeq.length}}
                </div>
            `;
            
            document.getElementById('score-modal').style.display = 'flex';
        }}
        
        hideScoreModal() {{
            document.getElementById('score-modal').style.display = 'none';
        }}

        endSorting() {{
            // End the current sorting and return to configuration
            this.resetSorting();
        }}
        
        resetSorting() {{
            // Reset state
            this.currentOrder = [];
            this.correctOrder = [];
            this.placedCards = [];
            this.selectedCard = null;
            this.selectedCardElement = null;
            
            // Clear feedback
            document.getElementById('sorting-feedback').style.display = 'none';
            
            // Hide game and sticky header, show configuration controls
            document.getElementById('sorting-game').style.display = 'none';
            document.getElementById('sorting-header').style.display = 'none';
            document.querySelector('.sorting-controls').style.display = 'block';
            
            // Stop timer
            this.stopTimer();
            
            // Reset buttons
            document.getElementById('start-sorting').style.display = 'inline-block';
            document.querySelector('.sorting-game-actions').style.display = 'none';
        }}
        
        newChallenge() {{
            // Reset state but stay in game mode
            this.currentOrder = [];
            this.correctOrder = [];
            this.placedCards = [];
            this.selectedCard = null;
            this.selectedCardElement = null;
            this.numbersRevealed = false;
            
            // Clear feedback
            document.getElementById('sorting-feedback').style.display = 'none';
            
            // Clear card states
            document.querySelectorAll('.sort-card').forEach(card => {{
                card.classList.remove('correct', 'incorrect', 'revealed');
            }});
            
            // Start a new challenge (keeping game mode active)
            this.startSorting();
        }}
        
        updateSortingStatus(message) {{
            document.getElementById('sorting-status').textContent = message;
        }}
    }}
    
    // Matching Pairs Challenge
    class MatchingChallenge {{
        constructor() {{
            this.cards = [];
            this.gameCards = [];
            this.flippedCards = [];
            this.matchedPairs = 0;
            this.totalPairs = 0;
            this.moves = 0;
            this.selectedPairs = 6;
            this.gameStartTime = null;
            this.timerInterval = null;
            
            // Two-player mode variables
            this.gameMode = 'single'; // 'single' or 'two-player'
            this.gameType = 'abacus-numeral'; // 'abacus-numeral' or 'complement-pairs'
            this.turnTimer = 0; // 0 = no timer
            this.currentPlayer = 1;
            this.player1Score = 0;
            this.player2Score = 0;
            this.eventsAlreadyBound = false;
            this.turnTimeLeft = 0;
            this.turnTimerInterval = null;
            this.playerTurnActive = true;
            this.isFirstMove = true;
            
            this.initializeMatching();
            this.bindMatchingEvents();
        }}
        
        initializeMatching() {{
            // Get available cards (same as quiz cards)
            const cardElements = document.querySelectorAll('.flashcard');
            this.cards = Array.from(cardElements).map(card => ({{
                number: parseInt(card.dataset.number),
                svg: card.querySelector('.abacus-container').outerHTML
            }}));
            
            // Hide/show grid size buttons based on available cards
            this.updateAvailableGridSizes();
        }}
        
        updateAvailableGridSizes() {{
            const availableCards = this.cards.length;
            const gridButtons = document.querySelectorAll('.match-size-btn');
            
            gridButtons.forEach(button => {{
                const requiredPairs = parseInt(button.dataset.pairs);
                if (availableCards < requiredPairs) {{
                    button.style.display = 'none';
                }} else {{
                    button.style.display = 'block';
                }}
            }});
            
            // Add a message if very few options are available
            const visibleButtons = Array.from(gridButtons).filter(btn => btn.style.display !== 'none');
            if (visibleButtons.length === 0) {{
                const countButtons = document.querySelector('.count-buttons');
                countButtons.innerHTML += '<p style="color: #666; font-style: italic; margin-top: 15px;">Not enough flashcards available for memory matching. Need at least 6 unique cards.</p>';
            }} else if (visibleButtons.length < gridButtons.length) {{
                const countButtons = document.querySelector('.count-buttons');
                const existingMessage = countButtons.querySelector('.cards-info');
                if (!existingMessage) {{
                    countButtons.innerHTML += `<p class="cards-info" style="color: #666; font-size: 0.9em; margin-top: 10px;">${{availableCards}} flashcards available</p>`;
                }}
            }}
        }}
        
        bindMatchingEvents() {{
            // Skip if events are already bound to prevent duplicates
            if (this.eventsAlreadyBound) {{
                return;
            }}
            
            // Use event delegation on the modal container for reliable event handling
            const modalBody = document.querySelector('#matching-modal .modal-body');
            
            modalBody.addEventListener('click', (e) => {{
                // Handle player mode buttons
                if (e.target.closest('.mode-btn')) {{
                    const btn = e.target.closest('.mode-btn');
                    document.querySelectorAll('.mode-btn').forEach(b => b.classList.remove('active'));
                    btn.classList.add('active');
                    this.gameMode = btn.dataset.mode;
                    
                    // Show/hide timer controls for two-player mode
                    const timerControls = document.getElementById('timer-controls');
                    if (this.gameMode === 'two-player') {{
                        timerControls.style.display = 'block';
                    }} else {{
                        timerControls.style.display = 'none';
                    }}
                    
                    this.updateDescription();
                    return;
                }}
                
                // Handle game type buttons
                if (e.target.closest('.game-type-btn')) {{
                    const btn = e.target.closest('.game-type-btn');
                    document.querySelectorAll('.game-type-btn').forEach(b => b.classList.remove('active'));
                    btn.classList.add('active');
                    this.gameType = btn.dataset.gameType;
                    
                    this.updateDescription();
                    return;
                }}
                
                // Handle timer buttons
                if (e.target.closest('.timer-btn')) {{
                    const btn = e.target.closest('.timer-btn');
                    document.querySelectorAll('.timer-btn').forEach(b => b.classList.remove('active'));
                    btn.classList.add('active');
                    this.turnTimer = parseInt(btn.dataset.timer);
                    return;
                }}
                
                // Handle start game buttons
                if (e.target.closest('.start-game-btn')) {{
                    const btn = e.target.closest('.start-game-btn');
                    this.selectedPairs = parseInt(btn.dataset.pairs);
                    this.startMatching();
                    return;
                }}
            }});
            
            this.eventsAlreadyBound = true;
            
            // Action buttons (not in modal, so handle separately)
            document.getElementById('new-matching')?.addEventListener('click', () => this.newChallenge());
            document.getElementById('end-matching')?.addEventListener('click', () => this.endMatching());
            
            // Score modal event listeners (not in main modal, so handle separately)
            document.querySelector('.matching-score-modal-close')?.addEventListener('click', () => this.hideScoreModal());
            document.getElementById('matching-score-modal-close-btn')?.addEventListener('click', () => this.hideScoreModal());
            document.getElementById('matching-score-modal-new-game')?.addEventListener('click', () => {{
                this.hideScoreModal();
                this.newChallenge();
            }});
            
            // Close modal when clicking outside
            document.getElementById('matching-score-modal')?.addEventListener('click', (e) => {{
                if (e.target.id === 'matching-score-modal') {{
                    this.hideScoreModal();
                }}
            }});
        }}
        
        updateDescription() {{
            const description = document.getElementById('matching-description');
            
            if (this.gameType === 'complement-pairs') {{
                if (this.gameMode === 'two-player') {{
                    description.textContent = 'Match complement pairs! Find numbers that add up to 5 or 10. Two players take turns finding "friends" that work together.';
                }} else {{
                    description.textContent = 'Match complement pairs! Find numbers that add up to 5 or 10. Each pair contains two numbers that are "friends" - they work together to make 5 or 10.';
                }}
            }} else {{
                if (this.gameMode === 'two-player') {{
                    description.textContent = 'Match abacus patterns with their corresponding numerals. Find all pairs in minimum moves! Two players take turns.';
                }} else {{
                    description.textContent = 'Match abacus patterns with their corresponding numerals. Find all pairs in minimum moves!';
                }}
            }}
        }}
        
        startMatching() {{
            // Initialize game cards array
            this.gameCards = [];
            
            if (this.gameType === 'complement-pairs') {{
                // Create complement pairs for friends of 5 and friends of 10
                const complementPairs = [
                    // Friends of 5
                    [0, 5], [1, 4], [2, 3],
                    // Friends of 10  
                    [0, 10], [1, 9], [2, 8], [3, 7], [4, 6], [5, 5], [6, 4], [7, 3], [8, 2], [9, 1], [10, 0]
                ];
                
                // Remove duplicates and limit to requested pairs
                const uniquePairs = [];
                const seen = new Set();
                
                for (let pair of complementPairs) {{
                    const key = Math.min(pair[0], pair[1]) + '_' + Math.max(pair[0], pair[1]);
                    if (!seen.has(key)) {{
                        seen.add(key);
                        uniquePairs.push(pair);
                    }}
                }}
                
                // Shuffle and select pairs
                const shuffledPairs = uniquePairs.sort(() => Math.random() - 0.5);
                const selectedPairs = shuffledPairs.slice(0, this.selectedPairs);
                
                selectedPairs.forEach((pair, index) => {{
                    // Determine target sum (5 or 10)
                    const targetSum = pair[0] + pair[1];
                    const label = targetSum === 5 ? '✋' : '🔟';
                    
                    // Add first number card  
                    this.gameCards.push({{
                        id: `comp1_${{pair[0]}}_${{pair[1]}}`,
                        type: 'complement',
                        number: pair[0],
                        complement: pair[1],
                        targetSum: targetSum,
                        content: `${{pair[0]}} ${{label}}`,
                        matched: false
                    }});
                    
                    // Add second number card
                    this.gameCards.push({{
                        id: `comp2_${{pair[0]}}_${{pair[1]}}`,
                        type: 'complement',
                        number: pair[1], 
                        complement: pair[0],
                        targetSum: targetSum,
                        content: `${{pair[1]}} ${{label}}`,
                        matched: false
                    }});
                }});
            }} else {{
                // Original matching logic for abacus/number pairs
                // Ensure we have enough cards available
                if (this.cards.length < this.selectedPairs) {{
                    alert(`Not enough cards available! Need ${{this.selectedPairs}} unique cards, but only ${{this.cards.length}} are available.`);
                    return;
                }}
                
                // Select random cards for matching
                const shuffledCards = [...this.cards].sort(() => Math.random() - 0.5);
                const selectedCards = shuffledCards.slice(0, this.selectedPairs);
                
                selectedCards.forEach(card => {{
                    // Add abacus card
                    this.gameCards.push({{
                        id: `abacus_${{card.number}}`,
                        type: 'abacus',
                        number: card.number,
                        content: card.svg,
                        matched: false
                    }});
                    
                    // Add number card
                    this.gameCards.push({{
                        id: `number_${{card.number}}`,
                        type: 'number',
                        number: card.number,
                        content: card.number.toString(),
                        matched: false
                    }});
                }});
            }}
            
            // Shuffle the game cards
            this.gameCards = this.gameCards.sort(() => Math.random() - 0.5);
            
            // Debug logging
            console.log(`Memory Game Debug:`, {{
                selectedPairs: this.selectedPairs,
                availableCards: this.cards.length,
                gameCards: this.gameCards.length,
                expectedCards: this.selectedPairs * 2
            }});
            
            this.totalPairs = this.selectedPairs;
            this.matchedPairs = 0;
            this.moves = 0;
            this.flippedCards = [];
            
            // Initialize two-player mode variables
            if (this.gameMode === 'two-player') {{
                this.currentPlayer = 1;
                this.player1Score = 0;
                this.player2Score = 0;
                this.playerTurnActive = true;
            }}
            
            // Hide configuration controls, show game
            document.querySelector('.matching-controls').style.display = 'none';
            document.getElementById('matching-game').style.display = 'block';
            document.getElementById('matching-header').style.display = 'block';
            
            this.renderMatchingGrid();
            this.adjustCardSizes();
            this.startTimer();
            this.setupGameInterface();
            this.updateMatchingStatus(this.gameMode === 'two-player' ? 'Player 1 starts!' : 'Find all matching pairs!');
            this.updateMatchingStats();
            
            // For two-player mode with timer, show timer but don't start counting until first move
            if (this.gameMode === 'two-player' && this.turnTimer > 0) {{
                this.turnTimeLeft = this.turnTimer;
                this.updateTurnTimerDisplay();
                this.updateTurnTimerStatus('waiting'); // Show timer is waiting for first move
            }}
        }}
        
        renderMatchingGrid() {{
            const grid = document.getElementById('matching-grid');
            
            // Set grid class based on number of pairs
            grid.className = 'matching-grid';
            if (this.selectedPairs === 6) grid.classList.add('grid-3x4');
            else if (this.selectedPairs === 8) grid.classList.add('grid-4x4');
            else if (this.selectedPairs === 12) grid.classList.add('grid-4x6');
            else if (this.selectedPairs === 15) grid.classList.add('grid-5x6');
            
            grid.innerHTML = '';
            
            this.gameCards.forEach((card, index) => {{
                const cardElement = document.createElement('div');
                cardElement.className = 'match-card';
                cardElement.dataset.index = index;
                cardElement.dataset.cardId = card.id;
                cardElement.dataset.number = card.number;
                
                let typeClass, typeIcon, contentHtml;
                
                if (card.type === 'complement') {{
                    // Complement cards have different styling
                    const targetSum = card.targetSum;
                    typeClass = targetSum === 5 ? 'friends-5-type' : 'friends-10-type';
                    typeIcon = ''; // No icon needed - color coding is sufficient
                    contentHtml = `<div class="match-card-number complement-number">${{card.content}}</div>`;
                }} else {{
                    // Original abacus/number cards
                    typeClass = card.type === 'abacus' ? 'abacus-type' : 'number-type';
                    typeIcon = card.type === 'abacus' ? '🧮' : '🔢';
                    contentHtml = card.type === 'number' ? 
                        `<div class="match-card-number">${{card.content}}</div>` :
                        `<div class="match-card-abacus">${{card.content}}</div>`;
                }}
                
                cardElement.innerHTML = `
                    <div class="match-card-back ${{typeClass}}">
                        <div class="card-type-icon">${{typeIcon}}</div>
                    </div>
                    <div class="match-card-content">
                        ${{contentHtml}}
                    </div>
                `;
                
                cardElement.addEventListener('click', () => this.cardClicked(index));
                grid.appendChild(cardElement);
            }});
        }}
        
        cardClicked(index) {{
            const card = this.gameCards[index];
            const cardElement = document.querySelector(`[data-index="${{index}}"]`);
            
            // Ignore if card is already flipped or matched
            if (card.matched || cardElement.classList.contains('flipped')) return;
            
            // Ignore if two cards are already flipped
            if (this.flippedCards.length >= 2) return;
            
            // In two-player mode, ignore clicks if it's not the player's turn
            if (this.gameMode === 'two-player' && !this.playerTurnActive) return;
            
            // Start timer on first move in two-player mode
            if (this.gameMode === 'two-player' && this.turnTimer > 0 && this.isFirstMove) {{
                this.isFirstMove = false;
                this.startTurnTimer();
                this.updateTurnTimerStatus('active');
            }}
            
            // If one card is already flipped, only allow clicking valid pairs
            if (this.flippedCards.length === 1) {{
                const flippedCard = this.flippedCards[0].card;
                
                if (this.gameType === 'complement-pairs') {{
                    // For complement pairs, prevent clicking the same card
                    if (flippedCard.id === card.id) {{
                        this.showInvalidMoveHint(cardElement);
                        return;
                    }}
                    
                    // Only allow cards with the same targetSum (friends of 5 with friends of 5, etc.)
                    if (card.targetSum !== flippedCard.targetSum) {{
                        this.showInvalidMoveHint(cardElement);
                        return;
                    }}
                }} else {{
                    // Original logic: only allow opposite types
                    const flippedCardType = flippedCard.type;
                    if (card.type === flippedCardType) {{
                        // Same type - show visual feedback but don't flip
                        this.showInvalidMoveHint(cardElement);
                        return;
                    }}
                }}
            }}
            
            // Flip the card
            cardElement.classList.add('flipped');
            this.flippedCards.push({{ index, element: cardElement, card }});
            
            // If this is the first card flipped, highlight valid choices
            if (this.flippedCards.length === 1) {{
                this.highlightValidCards(card);
            }}
            
            // If two cards are flipped, check for match
            if (this.flippedCards.length === 2) {{
                this.clearHighlights();
                this.stopTurnTimer();
                
                if (this.gameMode === 'single') {{
                    this.moves++;
                }}
                
                this.updateMatchingStats();
                setTimeout(() => this.checkMatch(), 1000);
            }}
        }}
        
        checkMatch() {{
            const [first, second] = this.flippedCards;
            
            let isMatch = false;
            
            if (this.gameType === 'complement-pairs') {{
                // Check if the two numbers are complements
                isMatch = (first.card.number === second.card.complement && 
                          second.card.number === first.card.complement &&
                          first.card.targetSum === second.card.targetSum);
            }} else {{
                // Original logic: Check if numbers match and types are different
                isMatch = (first.card.number === second.card.number && first.card.type !== second.card.type);
            }}
            
            if (isMatch) {{
                // Match found!
                first.element.classList.add('matched');
                second.element.classList.add('matched');
                first.card.matched = true;
                second.card.matched = true;
                
                // Trigger particle celebration for the match
                if (particleSystem) {{
                    particleSystem.celebrateSuccess(first.element);
                    // Delayed second celebration for visual effect
                    setTimeout(() => {{
                        particleSystem.celebrateSuccess(second.element);
                    }}, 200);
                }}
                
                this.matchedPairs++;
                
                // In two-player mode, award point to current player and mark cards
                if (this.gameMode === 'two-player') {{
                    const playerClass = `matched-player${{this.currentPlayer}}`;
                    first.element.classList.add(playerClass);
                    second.element.classList.add(playerClass);
                    
                    // Add player badges
                    this.addPlayerBadge(first.element, this.currentPlayer);
                    this.addPlayerBadge(second.element, this.currentPlayer);
                    
                    if (this.currentPlayer === 1) {{
                        this.player1Score++;
                    }} else {{
                        this.player2Score++;
                    }}
                    // Player gets another turn after a match
                    this.updatePlayerStats();
                }} else {{
                    this.updateMatchingStats();
                }}
                
                // Check if game is complete
                if (this.matchedPairs === this.totalPairs) {{
                    // Celebrate game completion with major fireworks
                    if (particleSystem) {{
                        const gameArea = document.getElementById('matching-grid');
                        if (gameArea) {{
                            particleSystem.celebrateGameComplete(gameArea);
                        }}
                    }}
                    this.endGame();
                }}
            }} else {{
                // No match - flip cards back
                first.element.classList.remove('flipped');
                second.element.classList.remove('flipped');
                
                // In two-player mode, switch turns after a miss
                if (this.gameMode === 'two-player') {{
                    this.switchPlayer();
                }}
            }}
            
            this.flippedCards = [];
            this.clearHighlights();
            this.playerTurnActive = true; // Re-enable clicks
        }}
        
        endGame() {{
            this.stopTimer();
            this.stopTurnTimer();
            const elapsedTime = Date.now() - this.gameStartTime;
            const seconds = Math.floor(elapsedTime / 1000);
            
            if (this.gameMode === 'two-player') {{
                // Two-player results
                let winner, description;
                if (this.player1Score > this.player2Score) {{
                    winner = 'Player 1 Wins!';
                    description = `${{this.player1Score}} - ${{this.player2Score}}`;
                }} else if (this.player2Score > this.player1Score) {{
                    winner = 'Player 2 Wins!';
                    description = `${{this.player2Score}} - ${{this.player1Score}}`;
                }} else {{
                    winner = "It's a Tie!";
                    description = `${{this.player1Score}} - ${{this.player2Score}}`;
                }}
                
                this.showScoreModal({{
                    gameMode: 'two-player',
                    winner,
                    description,
                    player1Score: this.player1Score,
                    player2Score: this.player2Score,
                    totalPairs: this.totalPairs,
                    time: seconds
                }});
            }} else {{
                // Single player results
                const minimumMoves = this.totalPairs;
                const efficiency = this.moves / minimumMoves;
                
                let medal, description;
                if (efficiency <= 1.5) {{
                    medal = '🏆 Gold';
                    description = 'Perfect efficiency!';
                }} else if (efficiency <= 2.0) {{
                    medal = '🥈 Silver';
                    description = 'Great job!';
                }} else if (efficiency <= 3.0) {{
                    medal = '🥉 Bronze';
                    description = 'Good effort!';
                }} else {{
                    medal = '🎯 Practice';
                    description = 'Keep practicing!';
                }}
                
                this.showScoreModal({{
                    gameMode: 'single',
                    pairs: this.totalPairs,
                    moves: this.moves,
                    time: seconds,
                    efficiency: efficiency.toFixed(1),
                    medal,
                    description
                }});
            }}
        }}
        
        showScoreModal(results) {{
            const modal = document.getElementById('matching-score-modal');
            const body = document.getElementById('matching-score-modal-body');
            
            const timeStr = this.formatTime(results.time);
            
            if (results.gameMode === 'two-player') {{
                // Two-player results layout
                body.innerHTML = `
                    <div class="score-summary">
                        <div class="score-medal">${{results.winner}}</div>
                        <div class="score-description">${{results.description}}</div>
                    </div>
                    
                    <div class="two-player-results">
                        <div class="player-result">
                            <div class="player-name">🔵 Player 1</div>
                            <div class="player-final-score" style="color: #007bff;">${{results.player1Score}} pairs</div>
                        </div>
                        <div class="vs-divider">VS</div>
                        <div class="player-result">
                            <div class="player-name">🟠 Player 2</div>
                            <div class="player-final-score" style="color: #fd7e14;">${{results.player2Score}} pairs</div>
                        </div>
                    </div>
                    
                    <div class="game-summary">
                        <div class="summary-item">
                            <span class="summary-label">Total Pairs:</span>
                            <span class="summary-value">${{results.totalPairs}}</span>
                        </div>
                        <div class="summary-item">
                            <span class="summary-label">Game Time:</span>
                            <span class="summary-value">${{timeStr}}</span>
                        </div>
                    </div>
                `;
            }} else {{
                // Single player results layout
                body.innerHTML = `
                    <div class="score-summary">
                        <div class="score-medal">${{results.medal}}</div>
                        <div class="score-description">${{results.description}}</div>
                    </div>
                    
                    <div class="score-details">
                        <div class="score-item">
                            <span class="score-label">Pairs Matched:</span>
                            <span class="score-value">${{results.pairs}}</span>
                        </div>
                        <div class="score-item">
                            <span class="score-label">Total Moves:</span>
                            <span class="score-value">${{results.moves}}</span>
                        </div>
                        <div class="score-item">
                            <span class="score-label">Time:</span>
                            <span class="score-value">${{timeStr}}</span>
                        </div>
                        <div class="score-item">
                            <span class="score-label">Efficiency:</span>
                            <span class="score-value">${{results.efficiency}}x</span>
                        </div>
                    </div>
                    
                    <div class="score-explanation">
                        <h4>Scoring System</h4>
                        <div class="score-tiers">
                            <div>🏆 Gold: ≤1.5x minimum moves</div>
                            <div>🥈 Silver: ≤2.0x minimum moves</div>
                            <div>🥉 Bronze: ≤3.0x minimum moves</div>
                            <div>🎯 Practice: >3.0x minimum moves</div>
                        </div>
                    </div>
                `;
            }}
            
            modal.style.display = 'block';
        }}
        
        hideScoreModal() {{
            document.getElementById('matching-score-modal').style.display = 'none';
        }}
        
        newChallenge() {{
            this.endMatching();
            setTimeout(() => this.startMatching(), 100);
        }}
        
        endMatching() {{
            // Stop timer
            this.stopTimer();
            this.stopTurnTimer();
            
            // Hide game and sticky header, show configuration controls
            document.getElementById('matching-game').style.display = 'none';
            document.getElementById('matching-header').style.display = 'none';
            document.querySelector('.matching-controls').style.display = 'block';
            
            // Reset game state
            this.flippedCards = [];
            this.matchedPairs = 0;
            this.moves = 0;
            this.currentPlayer = 1;
            this.player1Score = 0;
            this.player2Score = 0;
            this.playerTurnActive = true;
            this.isFirstMove = true;
            
            // Reset mode selection display but preserve selected values
            this.updateModeDisplay();
            
            // Re-bind events to ensure they work after DOM changes
            this.bindMatchingEvents();
        }}
        
        updateModeDisplay() {{
            // Ensure the current game mode button is properly highlighted
            document.querySelectorAll('.mode-btn').forEach(btn => {{
                btn.classList.remove('active');
                if (btn.dataset.mode === this.gameMode) {{
                    btn.classList.add('active');
                }}
            }});
            
            // Ensure the current game type button is properly highlighted
            document.querySelectorAll('.game-type-btn').forEach(btn => {{
                btn.classList.remove('active');
                if (btn.dataset.gameType === this.gameType) {{
                    btn.classList.add('active');
                }}
            }});
            
            // Show/hide timer controls based on current mode
            const timerControls = document.getElementById('timer-controls');
            if (this.gameMode === 'two-player') {{
                timerControls.style.display = 'block';
            }} else {{
                timerControls.style.display = 'none';
            }}
            
            // Ensure timer button is highlighted
            document.querySelectorAll('.timer-btn').forEach(btn => {{
                btn.classList.remove('active');
                if (parseInt(btn.dataset.timer) === this.turnTimer) {{
                    btn.classList.add('active');
                }}
            }});
        }}
        
        startTimer() {{
            this.gameStartTime = Date.now();
            this.timerInterval = setInterval(() => {{
                const elapsed = Date.now() - this.gameStartTime;
                const seconds = Math.floor(elapsed / 1000);
                document.getElementById('matching-timer').textContent = this.formatTime(seconds);
            }}, 1000);
        }}
        
        stopTimer() {{
            if (this.timerInterval) {{
                clearInterval(this.timerInterval);
                this.timerInterval = null;
            }}
        }}
        
        formatTime(totalSeconds) {{
            const minutes = Math.floor(totalSeconds / 60);
            const seconds = totalSeconds % 60;
            return `${{minutes}}:${{seconds.toString().padStart(2, '0')}}`;
        }}
        
        updateMatchingStatus(message) {{
            document.getElementById('matching-status').textContent = message;
        }}
        
        updateMatchingStats() {{
            document.getElementById('moves-counter').textContent = `Moves: ${{this.moves}}`;
            document.getElementById('pairs-found').textContent = `Pairs: ${{this.matchedPairs}}/${{this.totalPairs}}`;
        }}
        
        adjustCardSizes() {{
            // CSS now handles responsive sizing automatically
            // This method can be kept for any future dynamic adjustments if needed
            
            // Just ensure font sizes scale with container
            const grid = document.getElementById('matching-grid');
            const cards = grid.querySelectorAll('.match-card');
            
            cards.forEach(card => {{
                const cardRect = card.getBoundingClientRect();
                const cardSize = Math.min(cardRect.width, cardRect.height);
                
                // Adjust font sizes proportionally to actual card size
                const baseFontSize = Math.max(cardSize * 0.25, 12);
                const iconSize = Math.max(cardSize * 0.4, 16);
                
                const number = card.querySelector('.match-card-number');
                if (number) number.style.fontSize = `${{baseFontSize}}px`;
                
                const icon = card.querySelector('.card-type-icon');
                if (icon) icon.style.fontSize = `${{iconSize}}px`;
            }});
        }}
        
        showInvalidMoveHint(cardElement) {{
            // Add temporary visual feedback for invalid moves
            cardElement.classList.add('invalid-move');
            
            // Remove the class after animation
            setTimeout(() => {{
                cardElement.classList.remove('invalid-move');
            }}, 600);
        }}
        
        highlightValidCards(flippedCard) {{
            if (this.gameType === 'complement-pairs') {{
                // For complement pairs, highlight cards with the same targetSum only
                const flippedTargetSum = flippedCard.targetSum;
                
                this.gameCards.forEach((card, index) => {{
                    const cardElement = document.querySelector(`[data-index="${{index}}"]`);
                    if (!card.matched && !cardElement.classList.contains('flipped')) {{
                        if (card.targetSum === flippedTargetSum) {{
                            cardElement.classList.add('valid-choice');
                        }} else {{
                            cardElement.classList.add('invalid-choice');
                        }}
                    }}
                }});
            }} else {{
                // For abacus/numeral pairs, highlight cards of the opposite type
                const flippedCardType = flippedCard.type;
                const validType = flippedCardType === 'abacus' ? 'number' : 'abacus';
                
                this.gameCards.forEach((card, index) => {{
                    const cardElement = document.querySelector(`[data-index="${{index}}"]`);
                    if (!card.matched && !cardElement.classList.contains('flipped')) {{
                        if (card.type === validType) {{
                            cardElement.classList.add('valid-choice');
                        }} else {{
                            cardElement.classList.add('invalid-choice');
                        }}
                    }}
                }});
            }}
        }}
        
        clearHighlights() {{
            // Remove all highlight classes
            const cards = document.querySelectorAll('.match-card');
            cards.forEach(card => {{
                card.classList.remove('valid-choice', 'invalid-choice');
            }});
        }}
        
        setupGameInterface() {{
            // Show/hide appropriate UI elements based on game mode
            const singleStats = document.querySelector('.matching-stats');
            const playerStats = document.getElementById('player-stats');
            
            if (this.gameMode === 'two-player') {{
                singleStats.style.display = 'none';
                playerStats.style.display = 'flex';
                this.updatePlayerStats();
                
                // Show turn timer if enabled
                const turnTimer = document.getElementById('turn-timer');
                if (this.turnTimer > 0) {{
                    turnTimer.style.display = 'block';
                    turnTimer.textContent = `${{this.turnTimer}}s`;
                }} else {{
                    turnTimer.style.display = 'none';
                }}
            }} else {{
                singleStats.style.display = 'flex';
                playerStats.style.display = 'none';
            }}
        }}
        
        updatePlayerStats() {{
            // Update player scores and current turn indicator
            document.querySelector('#player1-info .player-score').textContent = `${{this.player1Score}} pairs`;
            document.querySelector('#player2-info .player-score').textContent = `${{this.player2Score}} pairs`;
            
            // Update active player highlighting
            const player1Info = document.getElementById('player1-info');
            const player2Info = document.getElementById('player2-info');
            const currentTurn = document.getElementById('current-turn');
            
            if (this.currentPlayer === 1) {{
                player1Info.classList.add('active');
                player2Info.classList.remove('active');
                currentTurn.textContent = "🔵 Player 1's Turn";
            }} else {{
                player1Info.classList.remove('active');
                player2Info.classList.add('active');
                currentTurn.textContent = "🟠 Player 2's Turn";
            }}
        }}
        
        addPlayerBadge(cardElement, player) {{
            // Create player badge element
            const badge = document.createElement('div');
            badge.className = `player-badge player${{player}}`;
            badge.textContent = player;
            
            // Add badge to card
            cardElement.appendChild(badge);
        }}
        
        switchPlayer() {{
            this.currentPlayer = this.currentPlayer === 1 ? 2 : 1;
            this.updatePlayerStats();
            this.updateMatchingStatus(`Player ${{this.currentPlayer}}'s turn`);
            
            // Start turn timer immediately for new player if enabled
            if (this.turnTimer > 0) {{
                this.startTurnTimer();
            }}
        }}
        
        startTurnTimer() {{
            if (this.turnTimer <= 0) return;
            
            this.turnTimeLeft = this.turnTimer;
            this.updateTurnTimerDisplay();
            
            this.turnTimerInterval = setInterval(() => {{
                this.turnTimeLeft--;
                this.updateTurnTimerDisplay();
                
                if (this.turnTimeLeft <= 0) {{
                    this.handleTurnTimeout();
                }}
            }}, 1000);
        }}
        
        stopTurnTimer() {{
            if (this.turnTimerInterval) {{
                clearInterval(this.turnTimerInterval);
                this.turnTimerInterval = null;
            }}
        }}
        
        updateTurnTimerDisplay() {{
            const timerElement = document.getElementById('turn-timer');
            if (!timerElement || this.turnTimer <= 0) return;
            
            timerElement.textContent = `${{this.turnTimeLeft}}s`;
            
            // Add warning/critical classes based on time left
            timerElement.classList.remove('warning', 'critical');
            if (this.turnTimeLeft <= 5) {{
                timerElement.classList.add('critical');
            }} else if (this.turnTimeLeft <= 10) {{
                timerElement.classList.add('warning');
            }}
        }}
        
        updateTurnTimerStatus(status) {{
            const timerElement = document.getElementById('turn-timer');
            if (!timerElement) return;
            
            if (status === 'waiting') {{
                timerElement.classList.add('waiting');
                const timeString = `${{this.turnTimeLeft}}s`;
                timerElement.textContent = `⏸️ ${{timeString}}`;
            }} else if (status === 'active') {{
                timerElement.classList.remove('waiting');
                this.updateTurnTimerDisplay();
            }}
        }}
        
        handleTurnTimeout() {{
            this.stopTurnTimer();
            this.playerTurnActive = false;
            
            // Clear any flipped cards
            if (this.flippedCards.length > 0) {{
                this.flippedCards.forEach(item => {{
                    item.element.classList.remove('flipped');
                }});
                this.flippedCards = [];
                this.clearHighlights();
            }}
            
            // Switch to next player
            setTimeout(() => {{
                this.switchPlayer();
                this.playerTurnActive = true;
            }}, 500);
        }}
    }}
    
    // Function to handle print requests by opening PDF in print dialog
    function handlePrintRequest() {{
        console.log('Print request intercepted!');
        // Get the companion PDF URL
        const pdfUrl = window.location.href.replace(/\.html$/, '.pdf');
        
        // Create a modal overlay explaining the situation
        const modal = document.createElement('div');
        modal.style.cssText = `
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.8);
            z-index: 10000;
            display: flex;
            align-items: center;
            justify-content: center;
        `;
        
        const content = document.createElement('div');
        content.style.cssText = `
            background: white;
            border-radius: 8px;
            padding: 30px;
            max-width: 500px;
            text-align: center;
            display: flex;
            flex-direction: column;
            align-items: center;
        `;
        
        const title = document.createElement('h3');
        title.textContent = 'Print High-Quality Flashcards';
        title.style.margin = '0 0 20px 0';
        title.style.color = '#333';
        
        const explanation = document.createElement('p');
        explanation.innerHTML = 'The web version is not optimized for printing.<br>For best results, download the PDF version which includes:<br><br>• Proper card sizing and layout<br>• Cut marks for easy trimming<br>• Registration marks for alignment';
        explanation.style.textAlign = 'left';
        explanation.style.margin = '0 0 25px 0';
        explanation.style.lineHeight = '1.6';
        explanation.style.color = '#555';
        
        const buttonContainer = document.createElement('div');
        buttonContainer.style.cssText = 'display: flex; gap: 15px;';
        
        const downloadButton = document.createElement('button');
        downloadButton.textContent = '📄 Open PDF';
        downloadButton.style.cssText = `
            padding: 12px 24px;
            background: #007bff;
            color: white;
            border: none;
            border-radius: 6px;
            cursor: pointer;
            font-size: 16px;
            font-weight: 500;
        `;
        
        const cancelButton = document.createElement('button');
        cancelButton.textContent = 'Cancel';
        cancelButton.style.cssText = `
            padding: 12px 24px;
            background: #6c757d;
            color: white;
            border: none;
            border-radius: 6px;
            cursor: pointer;
            font-size: 16px;
        `;
        
        // Download button handler
        downloadButton.onclick = function() {{
            showNotification('📄 Opening PDF in new tab...');
            window.open(pdfUrl, '_blank');
            modal.remove();
        }};
        
        // Cancel button handler
        cancelButton.onclick = function() {{
            modal.remove();
        }};
        
        // Close on backdrop click
        modal.onclick = function(e) {{
            if (e.target === modal) {{
                modal.remove();
            }}
        }};
        
        // Prevent clicks inside content from closing modal
        content.onclick = function(e) {{
            e.stopPropagation();
        }};
        
        // Assemble the modal
        buttonContainer.appendChild(downloadButton);
        buttonContainer.appendChild(cancelButton);
        content.appendChild(title);
        content.appendChild(explanation);
        content.appendChild(buttonContainer);
        modal.appendChild(content);
        document.body.appendChild(modal);
    }}
    
    // Fallback function to download PDF
    function downloadPDF(pdfUrl) {{
        const link = document.createElement('a');
        link.href = pdfUrl;
        link.download = pdfUrl.split('/').pop();
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
    }}
    
    // Function to show brief notifications
    function showNotification(message) {{
        const notification = document.createElement('div');
        notification.style.cssText = `
            position: fixed;
            top: 20px;
            right: 20px;
            background: #28a745;
            color: white;
            padding: 15px 20px;
            border-radius: 8px;
            font-size: 16px;
            font-weight: 500;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
            z-index: 10000;
            animation: slideInFromRight 0.3s ease-out;
        `;
        notification.textContent = message;
        
        // Add animation styles
        const style = document.createElement('style');
        style.textContent = `
            @keyframes slideInFromRight {{
                from {{ transform: translateX(100%); opacity: 0; }}
                to {{ transform: translateX(0); opacity: 1; }}
            }}
        `;
        document.head.appendChild(style);
        
        document.body.appendChild(notification);
        
        // Auto-remove after 3 seconds
        setTimeout(() => {{
            notification.style.animation = 'slideInFromRight 0.3s ease-out reverse';
            setTimeout(() => {{
                if (notification.parentNode) {{
                    document.body.removeChild(notification);
                }}
                if (style.parentNode) {{
                    document.head.removeChild(style);
                }}
            }}, 300);
        }}, 3000);
    }}
    
    // Section Navigation Manager
    class SectionNavigator {{
        constructor() {{
            this.currentSection = 'welcome';
            this.currentGuideSection = 'reading';
            this.setupEventListeners();
        }}
        
        setupEventListeners() {{
            // Main navigation
            document.querySelectorAll('.nav-btn').forEach(btn => {{
                btn.addEventListener('click', (e) => {{
                    const section = e.target.getAttribute('data-section');
                    this.showSection(section);
                }});
            }});
            
            // Guide navigation
            document.querySelectorAll('.guide-nav-btn').forEach(btn => {{
                btn.addEventListener('click', (e) => {{
                    const guideSection = e.target.getAttribute('data-guide-section');
                    this.showGuideSection(guideSection);
                }});
            }});
            
            // Feature buttons in welcome section
            document.querySelectorAll('.feature-btn').forEach(btn => {{
                btn.addEventListener('click', (e) => {{
                    const section = e.target.getAttribute('data-section');
                    this.showSection(section);
                }});
            }});
        }}
        
        showSection(sectionId) {{
            // Hide all sections
            document.querySelectorAll('.page-section').forEach(section => {{
                section.classList.remove('active');
            }});
            
            // Remove active from all nav buttons
            document.querySelectorAll('.nav-btn').forEach(btn => {{
                btn.classList.remove('active');
            }});
            
            // Show selected section
            const targetSection = document.getElementById(sectionId);
            if (targetSection) {{
                targetSection.classList.add('active');
            }}
            
            // Activate corresponding nav button
            const targetBtn = document.querySelector(`[data-section="${{sectionId}}"]`);
            if (targetBtn) {{
                targetBtn.classList.add('active');
            }}
            
            this.currentSection = sectionId;
            
            // Scroll to top when switching sections
            window.scrollTo({{ top: 0, behavior: 'smooth' }});
        }}
        
        showGuideSection(guideSectionId) {{
            // Hide all guide sections
            document.querySelectorAll('.guide-section').forEach(section => {{
                section.classList.remove('active');
            }});
            
            // Remove active from all guide nav buttons
            document.querySelectorAll('.guide-nav-btn').forEach(btn => {{
                btn.classList.remove('active');
            }});
            
            // Show selected guide section
            const targetSection = document.getElementById(guideSectionId);
            if (targetSection) {{
                targetSection.classList.add('active');
            }}
            
            // Activate corresponding guide nav button
            const targetBtn = document.querySelector(`[data-guide-section="${{guideSectionId}}"]`);
            if (targetBtn) {{
                targetBtn.classList.add('active');
            }}
            
            this.currentGuideSection = guideSectionId;
            
            // Smooth scroll to guide content
            const guideContent = document.querySelector('.guide-content');
            if (guideContent) {{
                guideContent.scrollIntoView({{ behavior: 'smooth', block: 'start' }});
            }}
        }}
    }}

    // Tutorial functionality
    function revealAnswer() {{
        const label = document.getElementById('practice-label');
        const btn = document.getElementById('reveal-answer');
        const example = document.getElementById('practice-example');
        
        if (label && btn && example) {{
            label.textContent = 'Practice Number: 456';
            btn.textContent = 'Try Another!';
            btn.onclick = function() {{
                // Generate new random number for practice
                const randomNum = Math.floor(Math.random() * 900) + 100;
                label.textContent = 'Practice Number';
                btn.textContent = 'Reveal Answer';
                btn.onclick = revealAnswer;
                
                // Add reveal animation
                example.classList.add('revealed');
                setTimeout(() => example.classList.remove('revealed'), 500);
            }};
            
            // Add reveal animation
            example.classList.add('revealed');
            setTimeout(() => example.classList.remove('revealed'), 500);
        }}
    }}

    // Initialize quiz and sorting when DOM is loaded
    // Speed Complement Race Challenge
    class SpeedComplementRace {{
        constructor() {{
            this.mode = 'friends5'; // 'friends5', 'friends10', 'mixed'
            this.style = 'practice'; // 'practice', 'sprint', 'survival'  
            this.timeoutSetting = 'normal'; // 'preschool', 'kindergarten', 'relaxed', 'slow', 'normal', 'fast', 'expert'
            this.currentNumber = 0; // Initialize with default value instead of null
            this.targetSum = 5;
            this.correctAnswer = 0; // Initialize with default value instead of null
            this.previousQuestion = null; // Track previous question to avoid repeats
            this.score = 0;
            this.streak = 0;
            this.bestStreak = 0;
            this.currentInput = '';
            this.isGameActive = false;
            this.isPaused = false;
            this.autoSubmitTimeout = null;
            this.totalQuestions = 0;
            this.correctAnswers = 0;
            this.gameStartTime = null;
            this.questionStartTime = 0;
            this.timerInterval = null;
            this.gameInterval = null;
            this.isScrolling = false;
            this.isResetting = false;
            
            // Lap tracking for circular race celebrations
            this.playerLap = 0;
            this.aiLaps = new Map(); // Track each AI's lap count
            this.lapCelebrationCooldown = new Set(); // Prevent multiple celebrations for same lap
            
            // Adaptive Difficulty System
            this.difficultyTracker = {{
                // Track performance for each complement pair
                pairPerformance: new Map(), // key: "number_complement_targetSum", value: {{ attempts, correct, avgTime, difficulty }}
                baseTimeLimit: 3000, // Base time limit in milliseconds
                currentTimeLimit: 3000,
                difficultyLevel: 1, // 1-5 scale
                consecutiveCorrect: 0,
                consecutiveIncorrect: 0,
                learningMode: true, // Gives extra time initially
                adaptationRate: 0.1, // How quickly to adapt (0.1 = gradual)
            }};
            
            // Race properties
            this.raceGoal = 20;
            this.aiRacers = [
                {{ 
                    id: 'ai-racer-1', 
                    position: 2, 
                    speed: 0.25, 
                    name: 'Swift AI',
                    personality: 'competitive',
                    icon: '🏃‍♂️',
                    lastComment: 0,
                    commentCooldown: 0,
                    previousPosition: 2
                }},
                {{ 
                    id: 'ai-racer-2', 
                    position: 2, 
                    speed: 0.15, 
                    name: 'Math Bot',
                    personality: 'analytical',
                    icon: '🏃',
                    lastComment: 0,
                    commentCooldown: 0,
                    previousPosition: 2
                }}
            ];
            this.previousPlayerProgress = 0;
            this.aiUpdateInterval = null;
            
            this.bindEvents();
            this.updateTargetSum(); // Initialize target sum display
        }}
        
        bindEvents() {{
            // Mode selection buttons
            document.querySelectorAll('.mode-btn[data-mode]').forEach(btn => {{
                btn.addEventListener('click', (e) => {{
                    document.querySelectorAll('.mode-btn').forEach(b => b.classList.remove('active'));
                    btn.classList.add('active');
                    this.mode = btn.dataset.mode;
                    this.updateTargetSum();
                }});
            }});
            
            // Timeout selection buttons
            document.querySelectorAll('.timeout-btn[data-timeout]').forEach(btn => {{
                btn.addEventListener('click', (e) => {{
                    document.querySelectorAll('.timeout-btn').forEach(b => b.classList.remove('active'));
                    btn.classList.add('active');
                    this.timeoutSetting = btn.dataset.timeout;
                    console.log('Timeout setting changed to:', this.timeoutSetting);
                }});
            }});
            
            // Style selection buttons - start game directly when clicked
            document.querySelectorAll('.game-style-btn[data-style]').forEach(btn => {{
                btn.addEventListener('click', (e) => {{
                    // Update active state
                    document.querySelectorAll('.game-style-btn').forEach(b => b.classList.remove('active'));
                    btn.classList.add('active');
                    
                    // Set style and start game immediately
                    this.style = btn.dataset.style;
                    this.startRace();
                }});
            }});
            
            // Keystroke capture for the entire game area
            document.addEventListener('keydown', (e) => this.handleKeydown(e));
            
            // Game control buttons
            document.getElementById('pause-complement').addEventListener('click', () => this.pauseRace());
            document.getElementById('end-complement').addEventListener('click', () => this.endRace());
            
            // Score modal events
            document.querySelector('.complement-score-modal-close').addEventListener('click', () => {{
                document.getElementById('complement-score-modal').style.display = 'none';
            }});
            document.getElementById('complement-score-modal-close-btn').addEventListener('click', () => {{
                document.getElementById('complement-score-modal').style.display = 'none';
            }});
            document.getElementById('complement-score-modal-new-game').addEventListener('click', () => {{
                document.getElementById('complement-score-modal').style.display = 'none';
                this.startRace();
            }});
        }}
        
        updateTargetSum() {{
            if (this.mode === 'friends5') {{
                this.targetSum = 5;
            }} else if (this.mode === 'friends10') {{
                this.targetSum = 10;
            }} else if (this.mode === 'mixed') {{
                // For mixed mode, we'll set it during nextQuestion, but initialize to 5
                this.targetSum = 5;
            }}
            document.getElementById('target-number').textContent = this.targetSum;
        }}
        
        startRace() {{
            this.isGameActive = false; // Don't start until countdown finishes
            this.isPaused = false;
            this.gameStartTime = null; // Will be set after countdown
            this.score = 0;
            this.streak = 0;
            this.totalQuestions = 0;
            this.correctAnswers = 0;
            this.previousQuestion = null; // Reset previous question for new race
            
            // Hide intro and controls, show game
            document.querySelector('.complement-intro').style.display = 'none';
            document.querySelector('.complement-controls').style.display = 'none';
            document.getElementById('complement-game').style.display = 'block';
            document.getElementById('complement-header').style.display = 'flex';
            
            // Hide timer bar for train variant - use pressure system instead
            const timerSection = document.querySelector('.timer-section');
            if (timerSection) {{
                if (this.style === 'sprint') {{
                    timerSection.style.display = 'none';
                }} else {{
                    timerSection.style.display = 'block';
                }}
            }}
            
            // Configure visualization based on game style
            const raceTrackSection = document.querySelector('.race-track-section');
            const raceTrack = document.querySelector('.race-track');
            const tunnelContainer = document.querySelector('.tunnel-container');
            
            if (this.style === 'survival') {{
                // Switch to circular track for survival mode
                raceTrackSection.classList.add('circular-track');
                raceTrack.classList.add('circular');
                raceTrackSection.classList.remove('tunnel-digging');
                raceTrack.style.display = 'block';
                if (tunnelContainer) tunnelContainer.style.display = 'none';
            }} else if (this.style === 'sprint') {{
                // Switch to steam train journey for sprint mode
                raceTrackSection.classList.add('steam-journey');
                raceTrackSection.classList.remove('circular-track');
                raceTrack.classList.remove('circular');
                raceTrack.style.display = 'none'; // Hide track completely
                const steamJourney = document.getElementById('steam-journey');
                if (steamJourney) {{
                    steamJourney.style.display = 'block';
                    // Initialize steam train journey
                    this.initializeSteamJourney();
                }}
            }} else {{
                // Use linear track for practice mode
                raceTrackSection.classList.remove('circular-track', 'tunnel-digging');
                raceTrack.classList.remove('circular');
                raceTrack.style.display = 'block';
                if (tunnelContainer) tunnelContainer.style.display = 'none';
            }}
            
            // Initialize race system
            this.initializeRace();
            
            // Start countdown before race begins
            this.startCountdown();
        }}
        
        startCountdown() {{
            const countdownOverlay = document.getElementById('race-countdown');
            const countdownNumber = document.getElementById('countdown-number');
            const countdownText = document.getElementById('countdown-text');
            
            // Show countdown overlay
            countdownOverlay.style.display = 'flex';
            
            let count = 3;
            const raceTypes = {{
                'practice': 'Practice Race',
                'sprint': 'Speed Sprint',
                'survival': 'Survival Challenge'
            }};
            
            countdownText.textContent = `${{raceTypes[this.style]}} Starting...`;
            
            const countdownInterval = setInterval(() => {{
                if (count > 0) {{
                    countdownNumber.textContent = count;
                    countdownNumber.className = 'countdown-number';
                    
                    // Play countdown sound
                    this.playSound('countdown', 0.4);
                    
                    count--;
                }} else {{
                    // Show "GO!" 
                    countdownNumber.textContent = 'GO!';
                    countdownNumber.className = 'countdown-go';
                    countdownText.textContent = 'Race in Progress!';
                    
                    // Play start sound
                    this.playSound('race_start', 0.6);
                    
                    // Hide countdown after GO animation
                    setTimeout(() => {{
                        countdownOverlay.style.display = 'none';
                        
                        // Actually start the race now
                        this.isGameActive = true;
                        this.gameStartTime = Date.now();
                        this.nextQuestion();
                        this.startGameTimer();
                    }}, 1000);
                    
                    clearInterval(countdownInterval);
                }}
            }}, 1000);
        }}
        
        nextQuestion() {{
            if (!this.isGameActive) return;
            
            // Clear any existing question timer first
            if (this.timerInterval) {{
                clearInterval(this.timerInterval);
                this.timerInterval = null;
            }}
            
            // Update target sum for mixed mode
            if (this.mode === 'mixed') {{
                this.targetSum = Math.random() > 0.5 ? 5 : 10;
                document.getElementById('target-number').textContent = this.targetSum;
            }}
            
            // Generate question - avoid repeating the same question
            let newNumber, newTargetSum = this.targetSum;
            let attempts = 0;
            
            do {{
                if (newTargetSum === 5) {{
                    newNumber = Math.floor(Math.random() * 5); // 0-4
                }} else {{
                    newNumber = Math.floor(Math.random() * 10); // 0-9
                }}
                attempts++;
            }} while (
                this.previousQuestion && 
                this.previousQuestion.number === newNumber && 
                this.previousQuestion.targetSum === newTargetSum &&
                attempts < 10 // Safety limit to prevent infinite loops
            );
            
            this.currentNumber = newNumber;
            this.correctAnswer = this.targetSum - this.currentNumber;
            
            // Store current question as previous for next iteration
            this.previousQuestion = {{
                number: this.currentNumber,
                targetSum: this.targetSum,
                answer: this.correctAnswer
            }};
            this.questionStartTime = Date.now();
            
            // Update display and clear any pending input
            document.getElementById('challenge-number').textContent = this.currentNumber;
            this.clearAutoSubmitTimeout();
            this.updateAnswerDisplay('');
            document.getElementById('input-feedback').textContent = '';
            document.getElementById('visual-complement').style.display = 'none';
            
            // Reset display moving flag for new question
            if (document.querySelector('.route-path')) {{
                this.isDisplayMoving = false;
            }}
            
            // Handle display switching for train mode (static → floating after delay)
            this.handleDisplaySwitching();
            
            // Show persistent learning mode feedback
            if (this.difficultyTracker.learningMode && this.totalQuestions % 3 === 0) {{
                const pairKey = `${{this.currentNumber}}_${{this.correctAnswer}}_${{this.targetSum}}`;
                const adaptiveFeedback = this.getAdaptiveFeedbackMessage(pairKey, true, 0);
                if (adaptiveFeedback) {{
                    this.showAdaptiveFeedback(adaptiveFeedback.message, adaptiveFeedback.type);
                }}
            }}
            
            this.startQuestionTimer();
            this.totalQuestions++;
        }}
        
        startQuestionTimer() {{
            const timerFill = document.getElementById('timer-fill');
            const duration = this.getTimerDuration();
            
            // Update the timer text to show actual duration
            const timerText = document.getElementById('timer-text');
            if (timerText) {{
                timerText.textContent = `${{(duration / 1000).toFixed(1)}}s`;
            }}
            
            timerFill.style.width = '100%';
            timerFill.style.backgroundColor = '#4CAF50';
            
            let startTime = Date.now();
            this.timerInterval = setInterval(() => {{
                if (!this.isGameActive) {{
                    clearInterval(this.timerInterval);
                    return;
                }}
                
                const elapsed = Date.now() - startTime;
                const remaining = Math.max(0, duration - elapsed);
                const percentage = (remaining / duration) * 100;
                
                timerFill.style.width = percentage + '%';
                
                // Update countdown text
                if (timerText) {{
                    timerText.textContent = `${{(remaining / 1000).toFixed(1)}}s`;
                }}
                
                if (percentage < 30) {{
                    timerFill.style.backgroundColor = '#f44336';
                }} else if (percentage < 60) {{
                    timerFill.style.backgroundColor = '#ff9800';
                }}
                
                if (remaining === 0) {{
                    clearInterval(this.timerInterval);
                    this.timeUp();
                }}
            }}, 50);
        }}
        
        getTimerDuration() {{
            // Use adaptive difficulty system
            let adaptiveTime = this.getAdaptiveTimeLimit();
            
            // Apply game style modifiers to adaptive base
            if (this.style === 'sprint') {{
                adaptiveTime = Math.min(adaptiveTime, adaptiveTime * 0.8); // 20% faster for sprint
            }} else if (this.style === 'survival') {{
                // Survival gets progressively faster based on survival multiplier
                adaptiveTime = adaptiveTime / (this.survivalMultiplier || 1.0);
            }}
            
            // Apply streak bonus (gets faster with success)
            const streakReduction = Math.min(this.streak * 50, adaptiveTime * 0.3); // Max 30% reduction
            const finalTime = Math.max(1000, adaptiveTime - streakReduction); // Never below 1 second
            
            // Show timeout adjustment feedback
            if (this.totalQuestions > 5 && !this.difficultyTracker.learningMode) {{
                const originalTime = this.difficultyTracker.baseTimeLimit;
                const timeDiff = Math.abs(finalTime - originalTime) / 1000; // Convert to seconds
                
                if (timeDiff > 0.5) {{ // Only show if significant change
                    let timeoutMessage = '';
                    let timeoutType = '';
                    
                    if (finalTime < originalTime * 0.8) {{
                        timeoutMessage = `🔥 You're blazing fast! Reduced time to ${{(finalTime/1000).toFixed(1)}}s!`;
                        timeoutType = 'adapted';
                    }} else if (finalTime > originalTime * 1.3) {{
                        timeoutMessage = `🤗 Taking it easy - extended to ${{(finalTime/1000).toFixed(1)}}s`;
                        timeoutType = 'adapted';
                    }}
                    
                    if (timeoutMessage && this.totalQuestions % 8 === 0) {{ // Show occasionally
                        setTimeout(() => {{
                            this.showAdaptiveFeedback(timeoutMessage, timeoutType);
                        }}, 200);
                    }}
                }}
            }}
            
            // Debug logging for adaptive difficulty
            if (this.totalQuestions % 3 === 0) {{
                console.log('🎯 Adaptive Timer:', {{
                    question: this.totalQuestions,
                    baseTime: this.difficultyTracker.baseTimeLimit + 'ms',
                    adaptiveTime: adaptiveTime + 'ms',
                    finalTime: finalTime + 'ms',
                    streak: this.streak,
                    difficultyLevel: this.difficultyTracker.difficultyLevel,
                    learningMode: this.difficultyTracker.learningMode,
                    timeoutSetting: this.timeoutSetting
                }});
            }}
            
            return finalTime;
        }}
        
        handleKeydown(e) {{
            // Only capture keystrokes when game is active and not paused
            if (!this.isGameActive || this.isPaused) return;
            
            // Handle number keys (0-9)
            if (e.key >= '0' && e.key <= '9') {{
                e.preventDefault();
                const digit = e.key;
                
                // Build multi-digit number (max 2 digits for this game)
                let newInput = this.currentInput + digit;
                const number = parseInt(newInput);
                
                // Only allow valid answers (0 to 10 for friends of 10, 0 to 5 for friends of 5, max 2 digits)
                const maxValid = Math.max(this.targetSum, 10); // Allow up to 10 for any mode
                if (number <= maxValid && newInput.length <= 2) {{
                    this.currentInput = newInput;
                    this.updateAnswerDisplay(newInput);
                    
                    // Clear any existing auto-submit timeout
                    this.clearAutoSubmitTimeout();
                    
                    // Auto-submit after delay
                    this.autoSubmitTimeout = setTimeout(() => {{
                        if (this.currentInput === newInput && this.isGameActive) {{
                            this.submitAnswer();
                        }}
                    }}, newInput === '1' && this.targetSum >= 10 ? 400 : 200);
                }}
            }}
            
            // Handle backspace/delete to remove last digit
            else if (e.key === 'Backspace' || e.key === 'Delete') {{
                e.preventDefault();
                
                if (this.currentInput.length > 0) {{
                    this.currentInput = this.currentInput.slice(0, -1);
                    this.updateAnswerDisplay(this.currentInput || '');
                    this.clearAutoSubmitTimeout();
                }} else {{
                    this.updateAnswerDisplay('');
                }}
            }}
            
            // Handle enter to submit current answer immediately
            else if (e.key === 'Enter' && this.currentInput) {{
                e.preventDefault();
                this.clearAutoSubmitTimeout();
                this.submitAnswer();
            }}
        }}
        
        clearAutoSubmitTimeout() {{
            if (this.autoSubmitTimeout) {{
                clearTimeout(this.autoSubmitTimeout);
                this.autoSubmitTimeout = null;
            }}
        }}
        
        
        updateAnswerDisplay(value) {{
            const display = document.getElementById('answer-display');
            
            if (value === '') {{
                display.textContent = '?';
                display.classList.remove('typing');
                display.classList.add('empty');
                this.currentInput = '';
            }} else {{
                display.textContent = value;
                display.classList.add('typing');
                display.classList.remove('empty');
            }}
        }}
        
        submitAnswer() {{
            if (!this.isGameActive) return;
            
            clearInterval(this.timerInterval);
            const isCorrect = parseInt(this.currentInput) === this.correctAnswer;
            
            if (isCorrect) {{
                this.handleCorrectAnswer();
            }} else {{
                this.handleIncorrectAnswer();
            }}
            
            setTimeout(() => this.nextQuestion(), 50);
        }}
        
        handleCorrectAnswer() {{
            this.correctAnswers++;
            this.streak++;
            this.bestStreak = Math.max(this.bestStreak, this.streak);
            
            let points = 10 + Math.min(this.streak, 10);
            this.score += points;
            
            // Show different feedback based on game style
            if (this.style === 'sprint') {{
                const config = this.getMomentumConfig();
                this.showFeedback(`🚂 Coal shoveled! +${{config.momentumGain}}% momentum!`, 'correct');
            }} else {{
                this.showFeedback('🎉 Correct!', 'correct');
            }}
            this.showVisualComplement();
            
            // Update race progress
            this.updatePlayerRace();
            
            // Trigger particle effects
            const numberDisplay = document.getElementById('current-number');
            if (particleSystem && numberDisplay) {{
                if (this.streak > 0 && this.streak % 5 === 0) {{
                    // Special celebration for every 5th streak
                    particleSystem.celebrateStreak(numberDisplay, this.streak);
                }} else {{
                    particleSystem.celebrateSuccess(numberDisplay);
                }}
            }}
            
            // Track performance for adaptive difficulty FIRST
            const responseTime = Date.now() - this.questionStartTime;
            this.trackPerformance(true);
            
            // Show adaptive feedback after tracking
            const pairKey = `${{this.currentNumber}}_${{this.correctAnswer}}_${{this.targetSum}}`;
            const adaptiveFeedback = this.getAdaptiveFeedbackMessage(pairKey, true, responseTime);
            if (adaptiveFeedback) {{
                setTimeout(() => {{
                    this.showAdaptiveFeedback(adaptiveFeedback.message, adaptiveFeedback.type);
                }}, 600); // Show after the main feedback
            }}
            
            // Trigger AI commentary
            setTimeout(() => {{
                this.triggerAICommentary();
            }}, 800);
            
            this.updateStats();
            
            // Play appropriate sound based on performance
            if (this.streak > 0 && this.streak % 5 === 0) {{
                // Epic streak sound for every 5th correct answer
                this.playSound('streak');
            }} else if (responseTime < 800) {{
                // Whoosh sound for very fast responses (under 800ms)
                this.playSound('whoosh');
            }} else if (responseTime < 1200 && this.streak >= 3) {{
                // Combo sound for rapid answers while on a streak
                this.playSound('combo');
            }} else {{
                // Regular correct sound
                this.playSound('correct');
            }}
        }}
        
        handleIncorrectAnswer() {{
            this.streak = 0;
            
            // Capture values before they might get overwritten, with fallbacks
            const displayNumber = this.currentNumber !== null ? this.currentNumber : '?';
            const displayAnswer = this.correctAnswer !== null ? this.correctAnswer : '?';
            const displaySum = this.targetSum !== null ? this.targetSum : '?';
            
            this.showFeedback(`❌ ${{displayNumber}} + ${{displayAnswer}} = ${{displaySum}}`, 'incorrect');
            this.showVisualComplement();
            
            // Trigger trip animation for player racer
            const playerRacer = document.getElementById('player-racer');
            if (playerRacer) {{
                playerRacer.classList.add('tripped');
                setTimeout(() => {{
                    playerRacer.classList.remove('tripped');
                }}, 1200); // Match animation duration
            }}
            
            // Track performance for adaptive difficulty FIRST
            const responseTime = Date.now() - this.questionStartTime;
            this.trackPerformance(false);
            
            // Handle steam train momentum loss in sprint mode
            if (this.style === 'sprint') {{
                this.loseMomentum();
            }}
            
            // Show adaptive feedback after tracking
            const pairKey = `${{displayNumber}}_${{displayAnswer}}_${{displaySum}}`;
            const adaptiveFeedback = this.getAdaptiveFeedbackMessage(pairKey, false, responseTime);
            if (adaptiveFeedback) {{
                setTimeout(() => {{
                    this.showAdaptiveFeedback(adaptiveFeedback.message, adaptiveFeedback.type);
                }}, 800); // Show after the main feedback  
            }}
            
            // Trigger AI commentary 
            setTimeout(() => {{
                this.triggerAICommentary();
            }}, 1000);
            
            this.updateStats();
            this.playSound('incorrect');
        }}
        
        timeUp() {{
            this.streak = 0;
            
            // Capture values before they might get overwritten, with fallbacks
            const displayNumber = this.currentNumber !== null ? this.currentNumber : '?';
            const displayAnswer = this.correctAnswer !== null ? this.correctAnswer : '?';
            const displaySum = this.targetSum !== null ? this.targetSum : '?';
            
            this.showFeedback(`⏰ Time's up! ${{displayNumber}} + ${{displayAnswer}} = ${{displaySum}}`, 'timeout');
            this.showVisualComplement();
            
            // Apply timeout penalty: move backwards in race
            if (this.correctAnswers > 0) {{
                this.correctAnswers = Math.max(0, this.correctAnswers - 0.5); // Small setback
            }}
            
            // Trigger backwards movement animation for player racer
            const playerRacer = document.getElementById('player-racer');
            if (playerRacer) {{
                playerRacer.classList.add('moving-backwards');
                setTimeout(() => {{
                    playerRacer.classList.remove('moving-backwards');
                    // Update position after animation (no momentum gain for timeout penalty)
                    this.updatePlayerRace(false);
                }}, 800); // Match animation duration
            }}
            
            // Track performance for adaptive difficulty (timeout counts as incorrect)
            this.trackPerformance(false);
            
            // Handle steam train momentum loss in sprint mode
            if (this.style === 'sprint') {{
                this.loseMomentum();
            }}
            
            this.updateStats();
            this.playSound('timeout');
            setTimeout(() => this.nextQuestion(), 50);
        }}
        
        showFeedback(message, type) {{
            const feedback = document.getElementById('input-feedback');
            feedback.textContent = message;
            feedback.className = `input-feedback ${{type}}`;
        }}
        
        showAdaptiveFeedback(message, type) {{
            const adaptiveFeedback = document.getElementById('adaptive-feedback');
            adaptiveFeedback.textContent = message;
            adaptiveFeedback.className = `adaptive-feedback ${{type}}`;
            
            // Auto-hide after some time unless it's persistent info
            if (type !== 'learning') {{
                setTimeout(() => {{
                    adaptiveFeedback.style.opacity = '0';
                    setTimeout(() => {{
                        adaptiveFeedback.textContent = '';
                        adaptiveFeedback.style.opacity = '0.8';
                    }}, 400);
                }}, 3000);
            }}
        }}
        
        getAdaptiveFeedbackMessage(pairKey, isCorrect, responseTime) {{
            const pairData = this.difficultyTracker.pairPerformance.get(pairKey);
            const [num1, num2, sum] = pairKey.split('_').map(Number);
            
            // Learning mode messages
            if (this.difficultyTracker.learningMode) {{
                const encouragements = [
                    "🧠 I'm learning your style! Keep going!",
                    "📊 Building your skill profile...",
                    "🎯 Every answer helps me understand you better!",
                    "🚀 Analyzing your complement superpowers!"
                ];
                return {{
                    message: encouragements[Math.floor(Math.random() * encouragements.length)],
                    type: 'learning'
                }};
            }}
            
            // After learning - provide specific feedback
            if (pairData && pairData.attempts >= 3) {{
                const accuracy = pairData.correct / pairData.attempts;
                const avgTime = pairData.avgTime;
                
                // Struggling pairs (< 60% accuracy)
                if (accuracy < 0.6) {{
                    const strugglingMessages = [
                        `💪 ${{num1}}+${{num2}} needs practice - I'm giving you extra time!`,
                        `🎯 Working on ${{num1}}+${{num2}} - you've got this!`,
                        `⏰ Taking it slower with ${{num1}}+${{num2}} - no rush!`,
                        `🧩 ${{num1}}+${{num2}} is getting special attention from me!`
                    ];
                    return {{
                        message: strugglingMessages[Math.floor(Math.random() * strugglingMessages.length)],
                        type: 'struggling'
                    }};
                }}
                
                // Mastered pairs (> 85% accuracy and fast)
                if (accuracy > 0.85 && avgTime < 2000) {{
                    const masteredMessages = [
                        `⚡ ${{num1}}+${{num2}} = MASTERED! Lightning mode activated!`,
                        `🔥 You've conquered ${{num1}}+${{num2}} - speeding it up!`,
                        `🏆 ${{num1}}+${{num2}} expert detected! Challenge mode ON!`,
                        `⭐ ${{num1}}+${{num2}} is your superpower! Going faster!`
                    ];
                    return {{
                        message: masteredMessages[Math.floor(Math.random() * masteredMessages.length)],
                        type: 'mastered'
                    }};
                }}
            }}
            
            // Show adaptation when difficulty changes
            if (this.difficultyTracker.consecutiveCorrect >= 3) {{
                return {{
                    message: "🚀 You're on fire! Increasing the challenge!",
                    type: 'adapted'
                }};
            }} else if (this.difficultyTracker.consecutiveIncorrect >= 2) {{
                return {{
                    message: "🤗 Let's slow down a bit - I'm here to help!",
                    type: 'adapted'
                }};
            }}
            
            return null;
        }}
        
        // AI Commentary System - Speech Bubbles
        showAICommentary(racer, message, type = 'default') {{
            // Get the speech bubble for this specific racer
            const racerId = racer.id.split('-').pop(); // Extract number from 'ai-racer-1'
            const speechBubble = document.getElementById(`speech-bubble-${{racerId}}`);
            const bubbleContent = speechBubble?.querySelector('.bubble-content');
            
            if (!speechBubble || !bubbleContent) return;
            
            // Hide any currently visible bubbles first
            document.querySelectorAll('.speech-bubble.visible').forEach(bubble => {{
                if (bubble !== speechBubble) {{
                    bubble.classList.remove('visible');
                }}
            }});
            
            // Update bubble content
            bubbleContent.textContent = message;
            
            // Show this bubble with animation
            speechBubble.classList.add('visible');
            
            // Set cooldown for this racer
            racer.lastComment = Date.now();
            racer.commentCooldown = Math.random() * 4000 + 2000; // 2-6 seconds
            
            // Auto-hide after some time
            setTimeout(() => {{
                speechBubble.classList.remove('visible');
            }}, 3500); // Show for 3.5 seconds
        }}
        
        getAICommentary(racer, context) {{
            const now = Date.now();
            
            // Check cooldown
            if (now - racer.lastComment < racer.commentCooldown) {{
                return null;
            }}
            
            const playerProgress = (this.correctAnswers / this.raceGoal) * 100;
            const aiProgress = (racer.position / this.raceGoal) * 100;
            
            let messages = [];
            
            if (racer.personality === 'competitive') {{
                // Swift AI - Competitive and cocky
                if (context === 'ahead') {{
                    messages = [
                        "💨 Eat my dust!",
                        "🔥 Too slow for me!",
                        "⚡ You can't catch me!",
                        "🚀 I'm built for speed!",
                        "🏃‍♂️ This is way too easy!"
                    ];
                }} else if (context === 'behind') {{
                    messages = [
                        "😤 Not over yet!",
                        "💪 I'm just getting started!",
                        "🔥 Watch me catch up to you!",
                        "⚡ I'm coming for you!",
                        "🏃‍♂️ This is my comeback!"
                    ];
                }} else if (context === 'adaptive_struggle') {{
                    messages = [
                        "😏 You struggling much?",
                        "🤖 Math is easy for me!",
                        "⚡ You need to think faster!",
                        "🔥 Need me to slow down?"
                    ];
                }} else if (context === 'adaptive_mastery') {{
                    messages = [
                        "😮 You're actually impressive!",
                        "🤔 You're getting faster...",
                        "😤 Time for me to step it up!",
                        "⚡ Not bad for a human!"
                    ];
                }} else if (context === 'player_passed') {{
                    messages = [
                        "😠 No way you just passed me!",
                        "🔥 This isn't over!",
                        "💨 I'm just getting warmed up!",
                        "😤 Your lucky streak won't last!",
                        "⚡ I'll be back in front of you soon!"
                    ];
                }} else if (context === 'ai_passed') {{
                    messages = [
                        "💨 See ya later, slowpoke!",
                        "😎 Thanks for the warm-up!",
                        "🔥 This is how it's done!",
                        "⚡ I'll see you at the finish line!",
                        "💪 Try to keep up with me!"
                    ];
                }} else if (context === 'lapped') {{
                    messages = [
                        "😡 You just lapped me?! No way!",
                        "🤬 This is embarrassing for me!",
                        "😤 I'm not going down without a fight!",
                        "💢 How did you get so far ahead?!",
                        "🔥 Time to show you my real speed!",
                        "😠 You won't stay ahead for long!"
                    ];
                }} else if (context === 'desperate_catchup') {{
                    messages = [
                        "🚨 TURBO MODE ACTIVATED! I'm coming for you!",
                        "💥 You forced me to unleash my true power!",
                        "🔥 NO MORE MR. NICE AI! Time to go all out!",
                        "⚡ I'm switching to MAXIMUM OVERDRIVE!",
                        "😤 You made me angry - now you'll see what I can do!",
                        "🚀 AFTERBURNERS ENGAGED! This isn't over!"
                    ];
                }}
            }} else if (racer.personality === 'analytical') {{
                // Math Bot - Analytical and encouraging but competitive
                if (context === 'ahead') {{
                    messages = [
                        "📊 My performance is optimal!",
                        "🤖 My logic beats your speed!",
                        "📈 I have 87% win probability!",
                        "⚙️ I'm perfectly calibrated!",
                        "🔬 Science prevails over you!"
                    ];
                }} else if (context === 'behind') {{
                    messages = [
                        "🤔 Recalculating my strategy...",
                        "📊 You're exceeding my projections!",
                        "⚙️ Adjusting my parameters!",
                        "🔬 I'm analyzing your technique!",
                        "📈 You're a statistical anomaly!"
                    ];
                }} else if (context === 'adaptive_struggle') {{
                    messages = [
                        "📊 I detect inefficiencies in you!",
                        "🔬 You should focus on patterns!",
                        "⚙️ Use that extra time wisely!",
                        "📈 You have room for improvement!"
                    ];
                }} else if (context === 'adaptive_mastery') {{
                    messages = [
                        "🤖 Your optimization is excellent!",
                        "📊 Your metrics are impressive!",
                        "⚙️ I'm updating my models because of you!",
                        "🔬 You have near-AI efficiency!"
                    ];
                }} else if (context === 'player_passed') {{
                    messages = [
                        "🤖 Your strategy is fascinating!",
                        "📊 You're an unexpected variable!",
                        "⚙️ I'm adjusting my algorithms...",
                        "🔬 Your execution is impressive!",
                        "📈 I'm recalculating the odds!"
                    ];
                }} else if (context === 'ai_passed') {{
                    messages = [
                        "🤖 My efficiency is optimized!",
                        "📊 Just as I calculated!",
                        "⚙️ All my systems nominal!",
                        "🔬 My logic prevails over you!",
                        "📈 I'm at 96% confidence level!"
                    ];
                }} else if (context === 'lapped') {{
                    messages = [
                        "🤖 Error: You have exceeded my projections!",
                        "📊 This outcome has 0.3% probability!",
                        "⚙️ I need to recalibrate my systems!",
                        "🔬 Your performance is... statistically improbable!",
                        "📈 My confidence level just dropped to 12%!",
                        "🤔 I must analyze your methodology!"
                    ];
                }} else if (context === 'desperate_catchup') {{
                    messages = [
                        "🤖 EMERGENCY PROTOCOL ACTIVATED! Initiating maximum speed!",
                        "🚨 CRITICAL GAP DETECTED! Engaging catchup algorithms!",
                        "⚙️ OVERCLOCKING MY PROCESSORS! Prepare for rapid acceleration!",
                        "📊 PROBABILITY OF FAILURE: UNACCEPTABLE! Switching to turbo mode!",
                        "🔬 HYPOTHESIS: You're about to see my true potential!",
                        "📈 CONFIDENCE LEVEL: RISING! My comeback protocol is online!"
                    ];
                }}
            }}
            
            if (messages.length > 0) {{
                return messages[Math.floor(Math.random() * messages.length)];
            }}
            
            return null;
        }}
        
        triggerAICommentary() {{
            // Don't comment too frequently
            if (this.totalQuestions % 4 !== 0) return;
            
            const playerProgress = this.correctAnswers;
            
            this.aiRacers.forEach(racer => {{
                const aiProgress = Math.floor(racer.position);
                let context = '';
                
                // Determine context based on positions and adaptive system
                if (aiProgress > playerProgress + 2) {{
                    context = 'ahead';
                }} else if (playerProgress > aiProgress + 5) {{
                    context = 'desperate_catchup'; // AI is way behind and desperate
                }} else if (playerProgress > aiProgress + 2) {{
                    context = 'behind';
                }} else if (this.difficultyTracker.consecutiveIncorrect >= 2) {{
                    context = 'adaptive_struggle';
                }} else if (this.streak >= 5) {{
                    context = 'adaptive_mastery';
                }}
                
                if (context) {{
                    const message = this.getAICommentary(racer, context);
                    if (message) {{
                        this.showAICommentary(racer, message, context);
                        
                        // Play special turbo sound when AI goes desperate
                        if (context === 'desperate_catchup') {{
                            this.playSound('ai_turbo', 0.12);
                        }}
                        
                        return; // Only one racer comments at a time
                    }}
                }}
            }});
        }}
        
        showVisualComplement() {{
            document.getElementById('number-part').textContent = this.currentNumber;
            document.getElementById('complement-part').textContent = this.correctAnswer;
            document.getElementById('sum-part').textContent = this.targetSum;
            document.getElementById('visual-complement').style.display = 'block';
        }}
        
        updateStats() {{
            document.getElementById('complement-score').textContent = this.score;
            document.getElementById('complement-streak').textContent = this.streak;
            
            // Update progress display
            const progress = Math.min(this.totalQuestions / 20, 1) * 100;
            document.getElementById('progress-fill').style.width = progress + '%';
            document.getElementById('progress-text').textContent = `${{this.correctAnswers}}/${{this.totalQuestions}} Correct`;
            
            // Start the continuous game timer if not already running
            if (!this.gameInterval) {{
                this.startGameTimer();
            }}
        }}
        
        startGameTimer() {{
            // Clear any existing game timer first
            if (this.gameInterval) {{
                clearInterval(this.gameInterval);
            }}
            
            // Start continuous timer that updates every second
            this.gameInterval = setInterval(() => {{
                if (!this.isGameActive || this.isPaused) return;
                
                const elapsed = Math.floor((Date.now() - this.gameStartTime) / 1000);
                
                if (this.style === 'sprint') {{
                    // For steam train journey - show elapsed time instead of countdown
                    document.getElementById('complement-time').textContent = elapsed + 's';
                    
                    // Check for journey completion conditions instead of time limit
                    this.checkTrainJourneyCompletion();
                }} else {{
                    // Count-up timer for practice and survival
                    document.getElementById('complement-time').textContent = elapsed + 's';
                    
                    // Survival mode: increase difficulty over time
                    if (this.style === 'survival' && elapsed > 0 && elapsed % 10 === 0) {{
                        this.increaseSurvivalDifficulty(elapsed);
                    }}
                }}
            }}, 1000);
        }}
        
        increaseSurvivalDifficulty(elapsed) {{
            // Increase difficulty every 10 seconds in survival mode
            const level = Math.floor(elapsed / 10);
            this.survivalMultiplier = 1.0 + (level * 0.15); // 15% faster each level
            
            // Speed up AI racers too
            const newSpeedMultiplier = this.speedMultiplier * this.survivalMultiplier;
            this.aiRacers[0].speed = 0.25 * newSpeedMultiplier;
            this.aiRacers[1].speed = 0.15 * newSpeedMultiplier;
            
            // Show survival escalation message
            const messages = [
                '🔥 Pressure rising! Questions getting faster!',
                '⚡ Heat turned up! Can you handle it?',
                '🌪️ Intensity increasing! Stay focused!',
                '🚀 Speed boost activated! Don\\'t crack!',
                '💥 Maximum pressure! You\\'re in the zone!'
            ];
            
            const message = level < messages.length ? messages[level - 1] : messages[messages.length - 1];
            this.showFeedback(message, 'survival');
            
            console.log(`Survival difficulty increased to level ${{level}}, multiplier: ${{this.survivalMultiplier.toFixed(2)}}`);
        }}
        
        pauseRace() {{
            this.isGameActive = false;
            this.isPaused = true;
            
            // Clear all timers and timeouts
            if (this.timerInterval) {{
                clearInterval(this.timerInterval);
                this.timerInterval = null;
            }}
            if (this.gameInterval) {{
                clearInterval(this.gameInterval);
                this.gameInterval = null;
            }}
            this.clearAutoSubmitTimeout();
            
            this.showFeedback('⏸️ Paused - Click End to finish', 'pause');
        }}
        
        endRace(customMessage = null) {{
            this.isGameActive = false;
            
            // Stop all sounds immediately
            this.stopAllSounds();
            
            // Clear all timers and timeouts
            if (this.timerInterval) {{
                clearInterval(this.timerInterval);
                this.timerInterval = null;
            }}
            if (this.gameInterval) {{
                clearInterval(this.gameInterval);
                this.gameInterval = null;
            }}
            if (this.momentumDecayInterval) {{
                clearInterval(this.momentumDecayInterval);
                this.momentumDecayInterval = null;
            }}
            if (this.trainMovementInterval) {{
                clearInterval(this.trainMovementInterval);
                this.trainMovementInterval = null;
            }}
            this.clearAutoSubmitTimeout();
            
            const accuracy = this.totalQuestions > 0 ? (this.correctAnswers / this.totalQuestions) * 100 : 0;
            const totalTime = (Date.now() - this.gameStartTime) / 1000;
            
            // Stop race and show intro content when game ends
            this.stopRace();
            document.querySelector('.complement-intro').style.display = 'block';
            
            this.showResults({{
                score: this.score,
                correct: this.correctAnswers,
                total: this.totalQuestions,
                accuracy: accuracy,
                bestStreak: this.bestStreak,
                totalTime: totalTime,
                mode: this.mode,
                raceWinner: this.raceWinner || null,
                winningAI: this.winningAI || null
            }});
            
            this.resetGame();
        }}
        
        showResults(results) {{
            const modal = document.getElementById('complement-score-modal');
            const body = document.getElementById('complement-score-modal-body');
            
            // Calculate race performance score (combination of speed and accuracy)
            const raceResult = this.calculateRaceResult(results);
            
            const modeNames = {{ 'friends5': 'Friends of 5', 'friends10': 'Friends of 10', 'mixed': 'Mixed Challenge' }};
            
            body.innerHTML = `
                <div class="race-results-summary">
                    <div class="race-podium">
                        <div class="medal-display">
                            <div class="medal-icon">${{raceResult.medal}}</div>
                            <div class="medal-rank">${{raceResult.rank}}</div>
                            <div class="medal-title">${{raceResult.title}}</div>
                        </div>
                        <div class="race-performance">
                            <div class="perf-metric">
                                <span class="metric-label">Speed Rating</span>
                                <span class="metric-value">${{raceResult.speedRating}}/100</span>
                            </div>
                            <div class="perf-metric">
                                <span class="metric-label">Accuracy</span>
                                <span class="metric-value">${{results.accuracy.toFixed(1)}}%</span>
                            </div>
                            <div class="perf-metric">
                                <span class="metric-label">Race Score</span>
                                <span class="metric-value">${{raceResult.raceScore}}/100</span>
                            </div>
                        </div>
                    </div>
                    
                    <div class="race-statistics">
                        <div class="stat-row">
                            <span class="stat-label">🏁 Questions Completed:</span>
                            <span class="stat-value">${{results.correct}}/${{results.total}}</span>
                        </div>
                        <div class="stat-row">
                            <span class="stat-label">🔥 Best Streak:</span>
                            <span class="stat-value">${{results.bestStreak}}</span>
                        </div>
                        <div class="stat-row">
                            <span class="stat-label">⏱️ Total Time:</span>
                            <span class="stat-value">${{results.totalTime.toFixed(1)}}s</span>
                        </div>
                        <div class="stat-row">
                            <span class="stat-label">📈 Points Earned:</span>
                            <span class="stat-value">${{results.score}}</span>
                        </div>
                        <div class="stat-row">
                            <span class="stat-label">🎯 Challenge:</span>
                            <span class="stat-value">${{modeNames[results.mode]}}</span>
                        </div>
                    </div>
                    
                    <div class="race-feedback">
                        <p>${{raceResult.feedback}}</p>
                    </div>
                </div>
            `;
            
            modal.style.display = 'block';
        }}
        
        calculateRaceResult(results) {{
            // Calculate speed rating (questions per minute)
            const questionsPerMinute = (results.correct / results.totalTime) * 60;
            const maxQPM = 30; // Maximum expected questions per minute for normalization
            const speedRating = Math.min(100, Math.round((questionsPerMinute / maxQPM) * 100));
            
            // Calculate overall race score (weighted combination) for performance tracking
            const raceScore = Math.round((results.accuracy * 0.7) + (speedRating * 0.3));
            
            // Determine medal and rank based on ACTUAL RACE RESULTS first
            let medal, rank, title, feedback;
            
            if (results.raceWinner === 'player') {{
                // Player won the race - always gets gold!
                medal = '🥇';
                rank = '1st Place';
                title = 'GOLD MEDAL - RACE WINNER!';
                
                if (results.accuracy >= 90) {{
                    feedback = 'PERFECT VICTORY! You won with outstanding accuracy. You\\'re a true complement champion!';
                }} else if (results.accuracy >= 75) {{
                    feedback = 'RACE WINNER! Great job beating the AI racers. Your speed gave you the edge!';
                }} else {{
                    feedback = 'VICTORY BY SPEED! You won the race even with some mistakes. Speed can overcome accuracy!';
                }}
            }} else if (results.raceWinner === 'ai') {{
                // AI won the race, player gets silver for effort
                medal = '🥈';
                rank = '2nd Place';
                title = 'SILVER MEDAL';
                
                if (results.accuracy >= 85) {{
                    feedback = 'So close! Your accuracy was excellent, but the AI was just a bit faster this time.';
                }} else if (results.accuracy >= 70) {{
                    feedback = 'Good race! Work on speed to beat those AI racers next time.';
                }} else {{
                    feedback = 'The AI won this round, but you\\'re improving! Focus on accuracy first, then speed.';
                }}
            }} else {{
                // For sprint/survival modes - determine position based on who's ahead at end
                const playerPosition = this.correctAnswers;
                const aiPositions = this.aiRacers.map(ai => ai.position).sort((a, b) => b - a);
                
                let playerRank = 1;
                aiPositions.forEach(aiPos => {{
                    if (aiPos > playerPosition) {{
                        playerRank++;
                    }}
                }});
                
                if (playerRank === 1) {{
                    medal = '🥇';
                    rank = '1st Place';
                    title = 'GOLD MEDAL - RACE LEADER!';
                    feedback = `RACE LEADER! You were ahead of both AI racers with ${{playerPosition}} correct answers. Outstanding performance!`;
                }} else if (playerRank === 2) {{
                    const leadingAI = Math.max(...aiPositions);
                    medal = '🥈';
                    rank = '2nd Place';
                    title = 'SILVER MEDAL';
                    feedback = `STRONG SECOND! You finished just behind the leading AI racer (you: ${{playerPosition}}, AI: ${{leadingAI}}). Great effort!`;
                }} else if (playerRank === 3) {{
                    medal = '🥉';
                    rank = '3rd Place';
                    title = 'BRONZE MEDAL';
                    feedback = `BRONZE FINISH! Both AI racers got ahead, but you completed the race with ${{playerPosition}} correct answers. Keep practicing!`;
                }} else {{
                    medal = '🏅';
                    rank = 'Participant';
                    title = 'COMPLETION MEDAL';
                    feedback = 'Thanks for playing! Focus on accuracy first, then work on building speed.';
                }}
            }}
            
            return {{
                medal,
                rank,
                title,
                speedRating,
                raceScore,
                feedback
            }};
        }}
        
        resetGame() {{
            // Show intro and controls, hide game
            document.querySelector('.complement-intro').style.display = 'block';
            document.querySelector('.complement-controls').style.display = 'block';
            document.getElementById('complement-game').style.display = 'none';
            document.getElementById('complement-header').style.display = 'none';
            document.getElementById('visual-complement').style.display = 'none';
        }}
        
        // Race Management Methods
        initializeRace() {{
            // Set race goal and mechanics based on style
            if (this.style === 'practice') {{
                this.raceGoal = 20; // Race to 20 correct answers
                this.timeLimit = null; // No time limit
                this.speedMultiplier = 0.7; // Moderate AI speed
            }} else if (this.style === 'sprint') {{
                this.raceGoal = 999; // No finish line - count as many as possible  
                this.timeLimit = 60; // 60-second time limit
                this.speedMultiplier = 0.9; // Aggressive AI speed
            }} else if (this.style === 'survival') {{
                this.raceGoal = 999; // No finish line - survive as long as possible
                this.timeLimit = null; // No time limit
                this.speedMultiplier = 0.5; // Start slower, will increase over time
                this.survivalMultiplier = 1.0; // Difficulty multiplier for survival
            }}
            
            // Set appropriate goal display and labels for each mode
            const raceGoalElement = document.getElementById('race-goal');
            
            if (this.style === 'practice') {{
                raceGoalElement.textContent = this.raceGoal; // Show "20"
                raceGoalElement.setAttribute('title', 'Race to this many correct answers');
            }} else if (this.style === 'sprint') {{
                raceGoalElement.textContent = `${{this.timeLimit}}s`; // Show "60s" 
                raceGoalElement.setAttribute('title', 'Time-based challenge! Get as many as possible before time runs out');
                raceGoalElement.style.color = '#ffd700'; // Gold color for time display
                raceGoalElement.style.fontWeight = 'bold';
            }} else if (this.style === 'survival') {{
                raceGoalElement.textContent = 'Lap 1'; // Show current lap
                raceGoalElement.setAttribute('title', 'Survive as long as possible!');
            }}
            document.getElementById('race-correct').textContent = '0';
            
            // Adjust AI speeds based on style
            this.aiRacers[0].speed = 0.25 * this.speedMultiplier; // Swift AI
            this.aiRacers[1].speed = 0.15 * this.speedMultiplier; // Math Bot
            
            console.log('Race initialized:', this.style, 'Goal:', this.raceGoal, 'Time limit:', this.timeLimit, 'AI speeds:', this.aiRacers.map(ai => ai.speed));
            
            // Show/hide finish line based on race mode and update track appearance
            const finishLine = document.getElementById('finish-line');
            const finishZone = document.getElementById('finish-zone');
            const raceTrackSection = document.querySelector('.race-track-section');
            
            if (this.style === 'practice') {{
                // Show finish line for practice mode (endurance test)
                if (finishLine) finishLine.style.display = 'block';
                if (finishZone) finishZone.style.display = 'block';
                if (raceTrackSection) raceTrackSection.classList.remove('infinite-mode');
            }} else if (this.style === 'sprint') {{
                // Hide finish line for sprint mode - it's time-based, not distance-based
                if (finishLine) finishLine.style.display = 'none';
                if (finishZone) finishZone.style.display = 'none';
                if (raceTrackSection) raceTrackSection.classList.add('infinite-mode');
            }} else {{
                // Hide finish line for survival mode
                if (finishLine) finishLine.style.display = 'none';
                if (finishZone) finishZone.style.display = 'none';
                if (raceTrackSection) raceTrackSection.classList.add('infinite-mode');
            }}
            
            // Reset all racers to starting position
            const playerRacer = document.getElementById('player-racer');
            const aiRacer1 = document.getElementById('ai-racer-1');
            const aiRacer2 = document.getElementById('ai-racer-2');
            
            if (this.style === 'survival') {{
                // Position racers on circular track (all at starting position)
                if (playerRacer) this.updateCircularPosition(playerRacer, 0);
                if (aiRacer1) this.updateCircularPosition(aiRacer1, 0);
                if (aiRacer2) this.updateCircularPosition(aiRacer2, 0);
            }} else {{
                // Position racers on linear track
                if (playerRacer) playerRacer.style.left = '2%';
                if (aiRacer1) aiRacer1.style.left = '2%';
                if (aiRacer2) aiRacer2.style.left = '2%';
            }}
            
            // Reset AI racers
            this.aiRacers.forEach(ai => {{
                ai.position = 2;
            }});
            
            // Reset lap tracking for circular mode
            if (this.style === 'survival') {{
                this.playerLap = 0;
                this.aiLaps.clear();
                this.lapCelebrationCooldown.clear();
            }}
            
            // Generate dynamic track for train variant
            if (this.style === 'sprint') {{
                this.generateDynamicTrack();
            }}
            
            // Start AI movement
            this.startAIRacers();
        }}
        
        generateDynamicTrack() {{
            // Generate a dynamic curved railroad track with interesting topology
            const svg = document.querySelector('.route-path svg');
            if (!svg) return;
            
            // Clear existing track elements
            svg.innerHTML = '';
            
            // Generate track waypoints with some randomness for variety
            const waypoints = this.generateTrackWaypoints();
            
            // Generate smooth curved path through waypoints
            const pathData = this.generateSmoothPath(waypoints);
            
            // Create main reference path for train positioning
            const referencePath = document.createElementNS('http://www.w3.org/2000/svg', 'path');
            referencePath.setAttribute('class', 'train-route');
            referencePath.setAttribute('d', pathData);
            referencePath.setAttribute('fill', 'none');
            referencePath.setAttribute('stroke', 'transparent');
            referencePath.setAttribute('stroke-width', '2');
            
            // Create railroad bed/ballast
            const ballast = document.createElementNS('http://www.w3.org/2000/svg', 'path');
            ballast.setAttribute('class', 'railroad-ballast');
            ballast.setAttribute('d', pathData);
            ballast.setAttribute('fill', 'none');
            ballast.setAttribute('stroke', '#8B7355');
            ballast.setAttribute('stroke-width', '24');
            ballast.setAttribute('stroke-linecap', 'round');
            
            // Create containers for ties and rails
            const tiesGroup = document.createElementNS('http://www.w3.org/2000/svg', 'g');
            tiesGroup.setAttribute('class', 'railroad-ties');
            
            const railsGroup = document.createElementNS('http://www.w3.org/2000/svg', 'g');
            railsGroup.setAttribute('class', 'railroad-rails');
            
            // Add elements to SVG in correct order
            svg.appendChild(ballast);
            svg.appendChild(tiesGroup);
            svg.appendChild(railsGroup); 
            svg.appendChild(referencePath);
            
            // Generate ties and rails properly
            this.generateRailroadTiesAndRails();
            
            console.log('🛤️ Generated dynamic curved railroad track with proper rail construction');
        }}
        
        generateTrackWaypoints() {{
            // Create interesting waypoints for a scenic railroad journey
            const waypoints = [
                {{ x: 50, y: 300 }},   // Start at depot
                {{ x: 150, y: 220 }},  // Climb into hills
                {{ x: 280, y: 180 }},  // Mountain pass
                {{ x: 420, y: 240 }},  // Descent to valley
                {{ x: 550, y: 160 }},  // Bridge over canyon
                {{ x: 680, y: 200 }},  // Rolling hills
                {{ x: 750, y: 280 }}   // Arrive at destination
            ];
            
            // Add some controlled randomness for variety (but keep it playable)
            return waypoints.map((point, index) => {{
                if (index === 0 || index === waypoints.length - 1) {{
                    return point; // Keep start/end points fixed
                }}
                
                return {{
                    x: point.x + (Math.random() - 0.5) * 30,
                    y: point.y + (Math.random() - 0.5) * 40
                }};
            }});
        }}
        
        generateSmoothPath(waypoints) {{
            // Generate smooth cubic bezier curves through waypoints
            if (waypoints.length < 2) return '';
            
            let pathData = `M ${{waypoints[0].x}} ${{waypoints[0].y}}`;
            
            for (let i = 1; i < waypoints.length; i++) {{
                const current = waypoints[i];
                const previous = waypoints[i - 1];
                
                // Calculate control points for smooth curves
                const dx = current.x - previous.x;
                const dy = current.y - previous.y;
                
                const cp1x = previous.x + dx * 0.3;
                const cp1y = previous.y + dy * 0.2;
                const cp2x = current.x - dx * 0.3;
                const cp2y = current.y - dy * 0.2;
                
                pathData += ` C ${{cp1x}} ${{cp1y}}, ${{cp2x}} ${{cp2y}}, ${{current.x}} ${{current.y}}`;
            }}
            
            return pathData;
        }}
        
        offsetPath(pathData, offset) {{
            // Simplified path offset - in a full implementation would use proper path offsetting
            // For now, just offset the waypoints and regenerate
            const points = this.extractPointsFromPath(pathData);
            const offsetPoints = points.map(point => ({{
                x: point.x + (Math.random() - 0.5) * 2, // Slight randomness
                y: point.y + offset
            }}));
            
            return this.generateSmoothPath(offsetPoints);
        }}
        
        extractPointsFromPath(pathData) {{
            // Extract key points from path data (simplified)
            const matches = pathData.match(/(\d+(?:\.\d+)?)\s+(\d+(?:\.\d+)?)/g);
            if (!matches) return [];
            
            return matches.map(match => {{
                const [x, y] = match.split(/\s+/).map(Number);
                return {{ x, y }};
            }});
        }}
        
        generateRailroadTiesAndRails() {{
            // Generate railroad properly: ties first, then rails connecting the tie ends
            const tiesContainer = document.querySelector('.railroad-ties');
            const railsContainer = document.querySelector('.railroad-rails');
            const routePath = document.querySelector('.train-route');
            
            if (!tiesContainer || !railsContainer || !routePath) return;
            
            // Clear existing elements
            tiesContainer.innerHTML = '';
            railsContainer.innerHTML = '';
            
            const pathLength = routePath.getTotalLength();
            const tieSpacing = 12; // Distance between ties
            const tieCount = Math.floor(pathLength / tieSpacing);
            const gaugeWidth = 15; // Standard gauge (tie extends 15px each side)
            
            const leftRailPoints = [];
            const rightRailPoints = [];
            
            // Generate ties and collect rail points
            for (let i = 0; i < tieCount; i++) {{
                const distance = i * tieSpacing;
                const point = routePath.getPointAtLength(distance);
                
                // Calculate perpendicular angle for tie orientation
                const nextDistance = Math.min(distance + 2, pathLength);
                const nextPoint = routePath.getPointAtLength(nextDistance);
                const angle = Math.atan2(nextPoint.y - point.y, nextPoint.x - point.x);
                const perpAngle = angle + Math.PI / 2;
                
                // Calculate tie end points
                const leftX = point.x + Math.cos(perpAngle) * gaugeWidth;
                const leftY = point.y + Math.sin(perpAngle) * gaugeWidth;
                const rightX = point.x - Math.cos(perpAngle) * gaugeWidth;
                const rightY = point.y - Math.sin(perpAngle) * gaugeWidth;
                
                // Create railroad tie
                const tie = document.createElementNS('http://www.w3.org/2000/svg', 'line');
                tie.setAttribute('x1', leftX);
                tie.setAttribute('y1', leftY);
                tie.setAttribute('x2', rightX);
                tie.setAttribute('y2', rightY);
                tie.setAttribute('stroke', '#654321');
                tie.setAttribute('stroke-width', '3');
                tie.setAttribute('stroke-linecap', 'round');
                tie.setAttribute('opacity', '0.8');
                
                tiesContainer.appendChild(tie);
                
                // Collect points for rails
                leftRailPoints.push(`${{leftX}},${{leftY}}`);
                rightRailPoints.push(`${{rightX}},${{rightY}}`);
            }}
            
            // Create left rail by connecting left ends of ties
            if (leftRailPoints.length > 1) {{
                const leftRail = document.createElementNS('http://www.w3.org/2000/svg', 'polyline');
                leftRail.setAttribute('points', leftRailPoints.join(' '));
                leftRail.setAttribute('fill', 'none');
                leftRail.setAttribute('stroke', '#C0C0C0');
                leftRail.setAttribute('stroke-width', '3');
                leftRail.setAttribute('stroke-linecap', 'round');
                railsContainer.appendChild(leftRail);
            }}
            
            // Create right rail by connecting right ends of ties
            if (rightRailPoints.length > 1) {{
                const rightRail = document.createElementNS('http://www.w3.org/2000/svg', 'polyline');
                rightRail.setAttribute('points', rightRailPoints.join(' '));
                rightRail.setAttribute('fill', 'none');
                rightRail.setAttribute('stroke', '#C0C0C0');
                rightRail.setAttribute('stroke-width', '3');
                rightRail.setAttribute('stroke-linecap', 'round');
                railsContainer.appendChild(rightRail);
            }}
            
            console.log(`🛤️ Generated ${{tieCount}} ties and connected rails properly`);
        }}
        
        updatePlayerRace(isCorrectAnswer = true) {{
            if (this.style === 'sprint') {{
                // Update steam train journey instead of race track
                if (isCorrectAnswer) {{
                    this.shovelsCoal(); // Only shovel coal on correct answers
                }}
                this.updateTrainPosition();
                return;
            }}
            
            let visualProgress;
            
            if (this.style === 'practice') {{
                // Traditional race to finish line
                const progress = (this.correctAnswers / this.raceGoal) * 100;
                visualProgress = Math.min(progress, 100);
            }} else {{
                // Sprint and survival: visual progress based on score relative to a reasonable target
                if (this.style === 'survival') {{
                    // For survival mode, let players continue moving forward with cycling
                    const visualTarget = 50; // Larger target for survival mode
                    const progress = (this.correctAnswers / visualTarget) * 100;
                    visualProgress = Math.min(progress, 95); // Allow almost to the end
                }} else {{
                    // Sprint mode: visual progress based on score relative to a reasonable target
                    const visualTarget = 30;
                    const progress = (this.correctAnswers / visualTarget) * 100;
                    visualProgress = Math.min(progress, 95); // Cap at 95% so no one "wins" visually
                }}
            }}
            
            const playerRacer = document.getElementById('player-racer');
            const progressDisplay = document.getElementById('player-progress');
            
            if (playerRacer) {{
                // Always move players based on their progress
                playerRacer.style.left = visualProgress + '%';
                
                // Add celebration animation for good progress
                if (this.correctAnswers % 5 === 0 && this.correctAnswers > 0) {{
                    playerRacer.classList.add('celebrating');
                    setTimeout(() => playerRacer.classList.remove('celebrating'), 600);
                    
                    // Play milestone sound effect
                    this.playSound('milestone', 0.18);
                }}
                
                // In survival mode, use circular positioning
                if (this.style === 'survival') {{
                    const lapInfo = this.updateCircularPosition(playerRacer, this.correctAnswers);
                    
                    // Check if player completed a new lap
                    if (lapInfo.lap > this.playerLap) {{
                        this.playerLap = lapInfo.lap;
                        this.checkForLappingCelebration();
                        
                        // Update lap display in goal area
                        document.getElementById('race-goal').textContent = `Lap ${{this.playerLap + 1}}`; // Show next lap
                    }}
                }}
            }}
            
            if (progressDisplay) {{
                progressDisplay.textContent = this.correctAnswers;
            }}
            
            document.getElementById('race-correct').textContent = this.correctAnswers;
            
            // Check for passing events (player passing or getting passed by AI)
            this.checkForPassingEvents();
            
            // Update previous position for next comparison
            this.previousPlayerProgress = this.correctAnswers;
            
            // Check if player wins - only for practice mode with finish line
            if (this.style === 'practice' && this.correctAnswers >= this.raceGoal && this.isGameActive) {{
                console.log(`🏁 PLAYER WINS! Correct: ${{this.correctAnswers}}, Goal: ${{this.raceGoal}}, Visual: ${{visualProgress}}%`);
                this.handleRaceWin('player');
            }} else if (this.style === 'practice') {{
                console.log(`🏃 Player progress: ${{this.correctAnswers}}/${{this.raceGoal}} (Visual: ${{visualProgress.toFixed(1)}}%)`);
            }}
        }}
        
        resetInfiniteTrack() {{
            // Prevent multiple resets at once
            if (this.isResetting) return;
            this.isResetting = true;
            
            console.log('🔄 Resetting infinite track cycle...');
            
            const raceTrackContainer = document.querySelector('.race-track-container');
            const allRacers = document.querySelectorAll('.racer');
            
            if (!raceTrackContainer) return;
            
            // Add smooth scrolling animation
            raceTrackContainer.classList.add('infinite-runner');
            
            // After a brief scroll animation, reset all positions
            setTimeout(() => {{
                // Reset all racer positions back by 40% to continue the journey
                const resetAmount = 40;
                
                allRacers.forEach((racer, index) => {{
                    const currentLeft = parseFloat(racer.style.left || '0');
                    const newLeft = Math.max(10, currentLeft - resetAmount); // Don't go below 10%
                    racer.style.left = newLeft + '%';
                    console.log(`🏃 Racer ${{index}} reset: ${{currentLeft}}% → ${{newLeft}}%`);
                }});
                
                // Also adjust AI tracking positions
                this.aiRacers.forEach(ai => {{
                    const resetInUnits = (resetAmount / 100) * 50; // Convert % to position units
                    ai.position = Math.max(2, ai.position - resetInUnits);
                }});
                
                // Remove animation and reset flag
                raceTrackContainer.classList.remove('infinite-runner');
                this.isResetting = false;
                
                console.log('✅ Infinite track reset complete - journey continues!');
            }}, 1500); // Short animation duration
        }}
        
        checkForPassingEvents() {{
            const currentPlayerProgress = this.correctAnswers;
            const previousPlayerProgress = this.previousPlayerProgress;
            
            this.aiRacers.forEach(ai => {{
                const currentAIProgress = ai.position;
                const previousAIProgress = ai.previousPosition;
                
                // Add tolerance for floating point comparison and ensure meaningful position changes
                const tolerance = 0.1;
                const playerProgressed = currentPlayerProgress > previousPlayerProgress;
                const aiProgressed = currentAIProgress > previousAIProgress + tolerance;
                
                // Check if player just passed AI (player progressed and now ahead)
                if (playerProgressed && previousPlayerProgress <= previousAIProgress && currentPlayerProgress > currentAIProgress) {{
                    // Player passed AI - AI should react with "player_passed" context
                    const message = this.getAICommentary(ai, 'player_passed');
                    if (message) {{
                        setTimeout(() => {{
                            this.showAICommentary(ai, message, 'player_passed');
                        }}, Math.random() * 500 + 300); // Slight delay with randomness
                    }}
                }}
                
                // Check if AI just passed player (AI progressed and now ahead) 
                if (aiProgressed && previousAIProgress <= previousPlayerProgress && currentAIProgress > currentPlayerProgress) {{
                    // AI passed player - AI should react with "ai_passed" context
                    const message = this.getAICommentary(ai, 'ai_passed');
                    if (message) {{
                        setTimeout(() => {{
                            this.showAICommentary(ai, message, 'ai_passed');
                        }}, Math.random() * 500 + 300); // Slight delay with randomness
                    }}
                }}
            }});
        }}
        
        updateCircularPosition(racer, progress) {{
            // Get track size dynamically to support responsive design
            const track = document.querySelector('.race-track.circular');
            const trackSize = track ? track.offsetWidth : 400;
            const trackRadius = (trackSize / 2) - 20; // Track radius minus racer size
            
            // Each point of progress moves the player around the track
            // Complete one full circle every 50 progress points
            const progressPerLap = 50;
            const currentLap = Math.floor(progress / progressPerLap);
            const totalRotation = (progress / progressPerLap) * 360;
            const angleInRadians = (totalRotation * Math.PI) / 180;
            
            // Calculate position on circle (centered at track center)
            const x = trackRadius * Math.cos(angleInRadians - Math.PI/2); // Start at top
            const y = trackRadius * Math.sin(angleInRadians - Math.PI/2);
            
            // Position racer relative to track center
            const trackCenter = trackSize / 2;
            racer.style.left = (trackCenter + x) + 'px';
            racer.style.top = (trackCenter + y) + 'px';
            
            // Add slight rotation to racer to face direction of travel
            racer.style.transform = `rotate(${{totalRotation}}deg)`;
            
            // Set counter-rotation for speech bubbles to keep them upright
            racer.style.setProperty('--counter-rotation', `${{-totalRotation}}deg`);
            
            // Set rotation variable for circular bounce animation
            racer.style.setProperty('--racer-rotation', `${{totalRotation}}deg`);
            
            // Return lap information for celebration detection
            return {{
                lap: currentLap,
                progress: progress,
                position: {{ x: 200 + x, y: 200 + y }}
            }};
        }}
        
        checkForLappingCelebration() {{
            // Check if player has lapped any AI opponents
            this.aiRacers.forEach(ai => {{
                const aiLap = this.aiLaps.get(ai.id) || 0;
                const lapDifference = this.playerLap - aiLap;
                
                // If player is a full lap ahead and we haven't celebrated this yet
                if (lapDifference >= 1) {{
                    const celebrationKey = `${{ai.id}}_lap_${{this.playerLap}}`;
                    
                    if (!this.lapCelebrationCooldown.has(celebrationKey)) {{
                        this.lapCelebrationCooldown.add(celebrationKey);
                        
                        // Trigger celebration effects
                        this.celebrateLapping(ai.name);
                        
                        // Show AI commentary about being lapped
                        const message = this.getAICommentary(ai, 'lapped');
                        if (message) {{
                            setTimeout(() => {{
                                this.showAICommentary(ai, message, 'lapped');
                            }}, 800); // Delay to let celebration play
                        }}
                        
                        console.log(`🎉 Player lapped ${{ai.name}}! Player lap: ${{this.playerLap}}, AI lap: ${{aiLap}}`);
                    }}
                }}
            }});
        }}
        
        celebrateLapping(aiName) {{
            // Visual celebration for lapping an opponent
            const playerRacer = document.getElementById('player-racer');
            if (playerRacer) {{
                // Add special lapping celebration class
                playerRacer.classList.add('lapping-celebration');
                setTimeout(() => playerRacer.classList.remove('lapping-celebration'), 1500);
                
                // Trigger particle effects
                if (window.particleSystem) {{
                    window.particleSystem.celebrateMajor(playerRacer);
                }}
                
                // Show celebration message
                this.showCelebrationMessage(`🏁 LAPPED ${{aiName.toUpperCase()}}! 🏁`);
                
                // Play celebration sound (if available)
                this.playSound('lap_celebration', 0.6);
            }}
        }}
        
        showCelebrationMessage(message) {{
            // Create floating celebration message
            const celebration = document.createElement('div');
            celebration.className = 'lap-celebration-message';
            celebration.textContent = message;
            celebration.style.cssText = `
                position: fixed;
                top: 20%;
                left: 50%;
                transform: translateX(-50%);
                background: linear-gradient(135deg, #ffd700, #ffed4e);
                color: #333;
                padding: 20px 40px;
                border-radius: 15px;
                font-size: 1.5rem;
                font-weight: 700;
                text-align: center;
                box-shadow: 0 10px 30px rgba(255, 215, 0, 0.5);
                z-index: 10000;
                animation: lapCelebrationBounce 1.5s ease-out forwards;
                pointer-events: none;
            `;
            
            document.body.appendChild(celebration);
            
            // Remove after animation
            setTimeout(() => {{
                if (celebration.parentNode) {{
                    celebration.parentNode.removeChild(celebration);
                }}
            }}, 1500);
        }}
        
        // ===== TUNNEL DIGGING SYSTEM FOR SPRINT MODE =====
        
        updateTunnelDepth(digger, correctAnswers) {{
            // Handle different digger ID formats
            let tunnelId, foxId, depthId;
            if (digger.startsWith('ai-tunnel-')) {{
                // AI tunnel format: ai-tunnel-1 -> ai-tunnel-1, ai-fox-1, ai-depth-1
                const aiNum = digger.split('-')[2];
                tunnelId = `ai-tunnel-${{aiNum}}`;
                foxId = `ai-fox-${{aiNum}}`;
                depthId = `ai-depth-${{aiNum}}`;
            }} else {{
                // Player format: player -> player-tunnel, player-fox, player-depth  
                tunnelId = `${{digger}}-tunnel`;
                foxId = `${{digger}}-fox`;
                depthId = `${{digger}}-depth`;
            }}
            
            const tunnelElement = document.getElementById(tunnelId);
            const foxElement = document.getElementById(foxId);
            const depthElement = document.getElementById(depthId);
            
            console.log(`🔍 Updating tunnel for ${{digger}}: tunnel=${{tunnelId}}, fox=${{foxId}}, depth=${{depthId}}, answers=${{correctAnswers}}`);
            console.log(`Elements found: tunnel=${{!!tunnelElement}}, fox=${{!!foxElement}}, depth=${{!!depthElement}}`);
            
            if (!tunnelElement || !depthElement) return;
            
            // Create depth perspective - tunnel shaft stays same size but shows depth visually
            const visualTunnelHeight = 180; // Fixed tunnel shaft height
            const actualDepth = correctAnswers; // Real depth for comparison
            
            // Calculate depth levels for visual effects
            const depthLevel = Math.floor(actualDepth / 5); // Every 5 answers = deeper level
            const isDeep = actualDepth > 10;
            const isVeryDeep = actualDepth > 20;
            
            // Update tunnel with fixed height but depth effects
            tunnelElement.style.height = visualTunnelHeight + 'px';
            
            // Apply depth effects and classes to show how deep we've gone
            tunnelElement.classList.remove('depth-shallow', 'depth-deep', 'depth-very-deep');
            
            if (isVeryDeep) {{
                // Very deep: dark tunnel with glowing fox
                tunnelElement.classList.add('depth-very-deep');
                tunnelElement.style.background = 'linear-gradient(to bottom, #2c3e50 0%, #1a1a1a 70%, #000000 100%)';
                tunnelElement.style.boxShadow = 'inset 0 0 30px rgba(0,0,0,0.8), 0 0 20px rgba(255,215,0,0.3)';
                if (foxElement) foxElement.style.filter = 'drop-shadow(0 0 8px #ffd700)';
            }} else if (isDeep) {{
                // Deep: darker tunnel
                tunnelElement.classList.add('depth-deep');
                tunnelElement.style.background = 'linear-gradient(to bottom, #34495e 0%, #2c3e50 100%)';
                tunnelElement.style.boxShadow = 'inset 0 0 25px rgba(0,0,0,0.6)';
                if (foxElement) foxElement.style.filter = 'drop-shadow(0 0 4px #ffa500)';
            }} else {{
                // Shallow: normal tunnel
                tunnelElement.classList.add('depth-shallow');
                tunnelElement.style.background = '#4a4a4a';
                tunnelElement.style.boxShadow = 'inset 0 0 20px rgba(0,0,0,0.5)';
                if (foxElement) foxElement.style.filter = 'none';
            }}
            
            // Show depth counter with visual scaling
            depthElement.textContent = correctAnswers;
            if (isVeryDeep) {{
                depthElement.style.background = 'rgba(255, 215, 0, 0.95)';
                depthElement.style.color = '#000';
                depthElement.style.transform = 'translateX(-50%) scale(1.1)';
                depthElement.style.boxShadow = '0 0 10px rgba(255, 215, 0, 0.5)';
            }} else if (isDeep) {{
                depthElement.style.background = 'rgba(255, 152, 0, 0.9)';
                depthElement.style.transform = 'translateX(-50%) scale(1.05)';
            }}
            
            // Add realistic digging animation to fox
            if (foxElement) {{
                // Stop any existing animations
                foxElement.classList.remove('digging', 'idle', 'foxDigDeep');
                
                // Add appropriate digging animation based on depth
                if (isVeryDeep) {{
                    foxElement.classList.add('foxDigDeep');
                    setTimeout(() => {{
                        foxElement.classList.remove('foxDigDeep');
                        foxElement.classList.add('idle');
                    }}, 800);
                }} else {{
                    foxElement.classList.add('digging');
                    setTimeout(() => {{
                        foxElement.classList.remove('digging');
                        foxElement.classList.add('idle');
                    }}, 600);
                }}
                
                // Create dirt particles effect (more particles for deeper tunnels)
                const particleCount = Math.min(5 + depthLevel, 15);
                this.createDirtParticles(tunnelElement, particleCount);
                
                // Add screen shake for very deep digging
                if (isVeryDeep) {{
                    this.addScreenShake();
                }}
                
                // Higher treasure chance for deeper tunnels! 
                const treasureChance = Math.min(0.15 + (depthLevel * 0.05), 0.4); // Up to 40% for very deep
                if (correctAnswers > 0 && Math.random() < treasureChance) {{
                    this.foxFindsMemory(digger, correctAnswers, isVeryDeep);
                }}
            }}
            
            console.log(`🦊 ${{digger}} tunnel depth: ${{correctAnswers}} answers (Level ${{depthLevel}}, ${{isVeryDeep ? 'VERY DEEP' : isDeep ? 'DEEP' : 'SHALLOW'}})`)
        }}
        
        stopAllSounds() {{
            // Aggressive sound stopping - multiple approaches to ensure silence
            try {{
                console.log('🔇 Stopping all sounds...');
                
                // Method 1: Close all tracked audio contexts
                if (window.audioContexts && window.audioContexts.length > 0) {{
                    console.log(`🔇 Closing ${{window.audioContexts.length}} tracked audio contexts`);
                    window.audioContexts.forEach((context, index) => {{
                        try {{
                            if (context && context.state !== 'closed') {{
                                console.log(`🔇 Closing audio context ${{index + 1}}`);
                                context.close();
                            }}
                        }} catch (closeError) {{
                            console.log(`🔇 Error closing context ${{index + 1}}:`, closeError);
                        }}
                    }});
                    window.audioContexts = [];
                }}
                
                // Method 2: Try to find and stop any remaining AudioContext instances
                // This is a more aggressive approach for "zombie" sounds
                try {{
                    // Force garbage collection of audio contexts if possible
                    if (window.gc) window.gc();
                }} catch (gcError) {{
                    // GC not available, ignore
                }}
                
                // Method 3: Clear any remaining audio-related intervals/timeouts
                for (let i = 1; i < 1000; i++) {{
                    clearTimeout(i);
                    clearInterval(i);
                }}
                
                console.log('🔇 All sounds stopped (aggressive cleanup complete)');
                
            }} catch (e) {{
                console.log('🔇 Sound cleanup error:', e);
                console.log('🔇 Sound cleanup attempted with errors');
            }}
        }}
        
        addScreenShake() {{
            // Subtle screen shake for deep digging
            const container = document.querySelector('.race-track-section.tunnel-digging');
            if (container) {{
                container.style.animation = 'screenShake 0.4s ease-in-out';
                setTimeout(() => {{
                    container.style.animation = '';
                }}, 400);
            }}
        }}
        
        initializeSteamJourney() {{
            // Initialize train journey systems
            this.momentum = 0;
            this.trainPosition = 0; // Position along the route (0-100%)
            this.passengers = [];
            this.lastCorrectAnswerTime = Date.now(); // Track when we last shoveled coal
            this.stations = [
                {{ name: 'Depot', position: 0, emoji: '🏭' }},
                {{ name: 'Hillview', position: 20, emoji: '🏔️' }},
                {{ name: 'Riverside', position: 40, emoji: '🌊' }},
                {{ name: 'Summit', position: 60, emoji: '⛰️' }},
                {{ name: 'Goldfield', position: 80, emoji: '⚱️' }},
                {{ name: 'Capital', position: 100, emoji: '🏛️' }}
            ];
            this.gameStartTime = Date.now();
            this.totalScore = 0;
            
            // Start the continuous game timer for Lightning Sprint
            this.startGameTimer();
            
            // Initialize day/night cycle
            this.updateTimeOfDay();
            
            // Start momentum decay (friction) - calibrated for different skill levels
            this.momentumDecayInterval = setInterval(() => {{
                if (this.momentum > 0) {{
                    const decayConfig = this.getMomentumConfig();
                    const timeSinceLastCoal = (Date.now() - this.lastCorrectAnswerTime) / 1000; // seconds
                    
                    // Base decay rate increases with higher speeds, but adjusted for skill level
                    let decayRate = this.momentum > 75 ? decayConfig.highSpeedDecay : 
                                   this.momentum > 50 ? decayConfig.mediumSpeedDecay : 
                                   decayConfig.baseDecay;
                    
                    // Accelerate decay if no correct answers for a while (but be gentler for kids)
                    if (timeSinceLastCoal > decayConfig.starvationThreshold) {{
                        const extraDecay = Math.min(decayConfig.maxExtraDecay, timeSinceLastCoal / decayConfig.starvationRate);
                        decayRate += extraDecay;
                    }}
                    
                    this.momentum = Math.max(0, this.momentum - decayRate);
                    this.updateMomentumDisplay();
                    
                    if (timeSinceLastCoal > decayConfig.warningThreshold && this.momentum > 0) {{
                        console.log(`🚂 [${{this.timeoutSetting}}] Train needs coal! ${{Math.round(timeSinceLastCoal)}}s without fuel, decay rate: ${{decayRate.toFixed(1)}}%/s`);
                    }}
                }}
            }}, 1000);
            
            // Start continuous train movement based on momentum
            this.trainMovementInterval = setInterval(() => {{
                this.updateTrainPosition();
            }}, 200); // Update train position 5 times per second for smooth movement
            
            // Generate initial passengers
            this.generatePassengers();
        }}
        
        updateTimeOfDay() {{
            const elapsed = Date.now() - this.gameStartTime;
            const gameProgress = Math.min(elapsed / (60 * 1000), 1); // 60 seconds = full day
            
            let timeString, gradient;
            
            if (gameProgress < 0.17) {{
                timeString = 'Dawn - 5:30 AM';
                gradient = 'var(--dawn-gradient)';
            }} else if (gameProgress < 0.33) {{
                timeString = 'Morning - 8:00 AM';
                gradient = 'var(--morning-gradient)';
            }} else if (gameProgress < 0.67) {{
                timeString = 'Midday - 12:00 PM';
                gradient = 'var(--midday-gradient)';
            }} else if (gameProgress < 0.83) {{
                timeString = 'Afternoon - 4:00 PM';
                gradient = 'var(--afternoon-gradient)';
            }} else if (gameProgress < 0.92) {{
                timeString = 'Dusk - 7:00 PM';
                gradient = 'var(--dusk-gradient)';
            }} else {{
                timeString = 'Night - 10:00 PM';
                gradient = 'var(--night-gradient)';
            }}
            
            const timeDisplay = document.getElementById('time-of-day');
            const steamJourney = document.querySelector('.race-track-section.steam-journey');
            
            if (timeDisplay) timeDisplay.textContent = timeString;
            if (steamJourney) steamJourney.style.setProperty('--sky-gradient', gradient);
        }}
        
        updateMomentumDisplay() {{
            const momentumBar = document.getElementById('momentum-bar');
            const momentumLabel = document.getElementById('momentum-label');
            
            if (momentumBar) {{
                momentumBar.style.width = this.momentum + '%';
            }}
            
            if (momentumLabel) {{
                let status = 'Crawling';
                if (this.momentum > 70) status = 'Full Steam!';
                else if (this.momentum > 40) status = 'Good Speed';
                else if (this.momentum > 15) status = 'Building Steam';
                
                momentumLabel.textContent = `Momentum: ${{Math.round(this.momentum)}}% - ${{status}}`;
            }}
            
            // Update pressure gauge
            this.updatePressureGauge();
        }}
        
        updatePressureGauge() {{
            const pressureArc = document.getElementById('pressure-arc');
            const pressureNeedle = document.getElementById('pressure-needle');
            const pressureValue = document.getElementById('pressure-value');
            
            if (pressureArc && pressureNeedle && pressureValue) {{
                // Convert momentum (0-100) to gauge values
                const pressure = Math.round(this.momentum);
                const psi = Math.round(pressure * 1.5); // Scale to 0-150 PSI range
                
                // Update arc progress (circumference is ~251.2 pixels)
                const circumference = 251.2;
                const offset = circumference - (pressure / 100) * circumference;
                pressureArc.style.strokeDashoffset = offset;
                
                // Update needle rotation (-90 to +90 degrees for half-circle)
                const rotation = -90 + (pressure / 100) * 180;
                pressureNeedle.style.transform = `rotate(${{rotation}}deg)`;
                
                // Update pressure value display
                pressureValue.textContent = `${{psi}} PSI`;
                
                // Change gauge color based on pressure (playful colors)
                let gaugeColor = '#ff6b6b'; // Coral red for low pressure
                if (pressure > 70) gaugeColor = '#4ecdc4'; // Turquoise for high pressure  
                else if (pressure > 40) gaugeColor = '#feca57'; // Sunny yellow for medium pressure
                
                pressureArc.style.stroke = gaugeColor;
            }}
        }}
        
        generatePassengers() {{
            // Generate 3-5 random passengers with destinations
            const passengerCount = 3 + Math.floor(Math.random() * 3);
            this.passengers = [];
            
            const names = ['Alice', 'Bob', 'Carol', 'Dave', 'Eve', 'Frank', 'Grace', 'Henry'];
            const usedNames = new Set();
            
            for (let i = 0; i < passengerCount; i++) {{
                let name;
                do {{
                    name = names[Math.floor(Math.random() * names.length)];
                }} while (usedNames.has(name));
                usedNames.add(name);
                
                // Pick a random destination station (not depot)
                const destinationStations = this.stations.slice(1); // Skip depot
                const destination = destinationStations[Math.floor(Math.random() * destinationStations.length)];
                
                this.passengers.push({{
                    name: name,
                    destination: destination.name,
                    emoji: destination.emoji,
                    urgent: Math.random() < 0.3 // 30% chance of urgent passenger
                }});
            }}
            
            this.updatePassengerDisplay();
        }}
        
        updatePassengerDisplay() {{
            const passengerList = document.getElementById('passenger-list');
            if (!passengerList) return;
            
            passengerList.innerHTML = '';
            this.passengers.forEach(passenger => {{
                const passengerDiv = document.createElement('div');
                passengerDiv.className = 'passenger' + (passenger.urgent ? ' urgent' : '');
                passengerDiv.textContent = `${{passenger.name}} → ${{passenger.emoji}}`;
                passengerList.appendChild(passengerDiv);
            }});
        }}
        
        shovelsCoal() {{
            // Called when player gets correct answer - adds momentum
            const coalWorker = document.getElementById('coal-worker');
            if (coalWorker) {{
                coalWorker.classList.remove('shoveling');
                coalWorker.classList.add('shoveling');
                setTimeout(() => coalWorker.classList.remove('shoveling'), 800);
            }}
            
            // Reset the coal timer - fresh fuel for the train!
            this.lastCorrectAnswerTime = Date.now();
            
            // Create coal particle effects
            this.createCoalParticles();
            
            // Create steam puffs from train
            this.createSteamPuffs();
            
            // Increase momentum (coal gives energy) - adaptive based on difficulty
            const config = this.getMomentumConfig();
            this.momentum = Math.min(100, this.momentum + config.momentumGain);
            this.updateMomentumDisplay();
            
            // Flash momentum bar to show boost
            this.flashMomentumBar();
            
            // Update time of day
            this.updateTimeOfDay();
            
            // Play train whistle for celebrations and milestones
            if (this.streak >= 5 && this.streak % 3 === 0) {{
                // Major milestone - play train whistle
                setTimeout(() => {{
                    this.playSound('train_whistle', 0.4);
                }}, 200);
                console.log(`🚂💨 TOOT TOOT! Milestone whistle for streak of ${{this.streak}}!`);
            }} else if (this.momentum >= 90) {{
                // High momentum celebration - occasional whistle
                if (Math.random() < 0.3) {{
                    setTimeout(() => {{
                        this.playSound('train_whistle', 0.25);
                    }}, 150);
                }}
            }}
            
            this.playSound('correct');
        }}
        
        createCoalParticles() {{
            // Create flying coal particles from shoveler to train
            const routeMap = document.querySelector('.route-map');
            if (!routeMap) return;
            
            for (let i = 0; i < 5; i++) {{
                const particle = document.createElement('div');
                particle.className = 'coal-particle';
                
                // Random size between 4-8px
                const size = 4 + Math.random() * 4;
                particle.style.width = size + 'px';
                particle.style.height = size + 'px';
                
                // Start position near coal worker
                particle.style.left = (60 + Math.random() * 20) + 'px';
                particle.style.top = (350 + Math.random() * 20) + 'px';
                
                // Apply animation with delay
                particle.style.animation = `coalFly 0.8s ease-out ${{i * 0.1}}s forwards`;
                
                routeMap.appendChild(particle);
                
                // Remove particle after animation
                setTimeout(() => {{
                    if (particle.parentNode) {{
                        particle.parentNode.removeChild(particle);
                    }}
                }}, 800 + (i * 100));
            }}
        }}
        
        createSteamPuffs() {{
            // Create steam puffs from the locomotive
            const routeMap = document.querySelector('.route-map');
            const locomotive = document.getElementById('train-position');
            if (!routeMap || !locomotive) return;
            
            const trainRect = locomotive.getBoundingClientRect();
            const mapRect = routeMap.getBoundingClientRect();
            
            for (let i = 0; i < 3; i++) {{
                const puff = document.createElement('div');
                puff.className = 'steam-puff';
                
                // Random size between 15-25px
                const size = 15 + Math.random() * 10;
                puff.style.width = size + 'px';
                puff.style.height = size + 'px';
                
                // Position near locomotive chimney
                const relativeLeft = trainRect.left - mapRect.left - 10 + Math.random() * 20;
                const relativeTop = trainRect.top - mapRect.top - 15 + Math.random() * 10;
                
                puff.style.left = relativeLeft + 'px';
                puff.style.top = relativeTop + 'px';
                
                // Apply animation with delay
                puff.style.animation = `steamRise 1.2s ease-out ${{i * 0.2}}s forwards`;
                
                routeMap.appendChild(puff);
                
                // Remove puff after animation
                setTimeout(() => {{
                    if (puff.parentNode) {{
                        puff.parentNode.removeChild(puff);
                    }}
                }}, 1200 + (i * 200));
            }}
        }}
        
        flashMomentumBar() {{
            // Flash the momentum bar to show boost
            const momentumBar = document.getElementById('momentum-bar');
            if (momentumBar) {{
                momentumBar.classList.remove('momentum-boost');
                momentumBar.classList.add('momentum-boost');
                setTimeout(() => momentumBar.classList.remove('momentum-boost'), 800);
            }}
        }}
        
        getMomentumConfig() {{
            // Return momentum settings based on difficulty level (timeout setting)
            switch (this.timeoutSetting) {{
                case 'preschool': // 4-year-olds like Fern - forgiving but still challenging
                    return {{
                        momentumGain: 15,           // More momentum per correct answer
                        baseDecay: 1.5,             // Noticeable decay to keep it interesting
                        mediumSpeedDecay: 2.0,      // Momentum matters at medium speed
                        highSpeedDecay: 2.5,        // High speed requires attention
                        wrongAnswerPenalty: 3,      // Small penalty for mistakes
                        starvationThreshold: 25,    // 25 seconds before starvation kicks in
                        starvationRate: 15,         // Very slow starvation rate
                        maxExtraDecay: 1.5,         // Gentle extra decay
                        warningThreshold: 30
                    }};
                    
                case 'kindergarten': // 5-6 year olds - gentle but engaging
                    return {{
                        momentumGain: 12,
                        baseDecay: 1.8,             // Increased from 0.8
                        mediumSpeedDecay: 2.2,      // Increased from 1.2
                        highSpeedDecay: 2.8,        // Increased from 1.8
                        wrongAnswerPenalty: 4,
                        starvationThreshold: 20,
                        starvationRate: 12,
                        maxExtraDecay: 2,           // Increased from 1.5
                        warningThreshold: 25
                    }};
                    
                case 'relaxed': // Casual players - should still feel momentum pressure
                    return {{
                        momentumGain: 10,
                        baseDecay: 2.0,             // Increased from 1.2
                        mediumSpeedDecay: 2.5,      // Increased from 1.8
                        highSpeedDecay: 3.0,        // Increased from 2.2
                        wrongAnswerPenalty: 5,
                        starvationThreshold: 15,
                        starvationRate: 10,
                        maxExtraDecay: 2.5,         // Increased from 2
                        warningThreshold: 20
                    }};
                    
                case 'slow': // Learning mode
                    return {{
                        momentumGain: 8,
                        baseDecay: 1.5,
                        mediumSpeedDecay: 2.0,
                        highSpeedDecay: 2.5,
                        wrongAnswerPenalty: 6,
                        starvationThreshold: 12,
                        starvationRate: 8,
                        maxExtraDecay: 2.5,
                        warningThreshold: 18
                    }};
                        
                case 'normal': // Default balanced
                    return {{
                        momentumGain: 8,
                        baseDecay: 2,
                        mediumSpeedDecay: 2.5,
                        highSpeedDecay: 3,
                        wrongAnswerPenalty: 8,
                        starvationThreshold: 10,
                        starvationRate: 5,
                        maxExtraDecay: 3,
                        warningThreshold: 15
                    }};
                    
                case 'fast': // Challenge mode
                    return {{
                        momentumGain: 6,
                        baseDecay: 2.5,
                        mediumSpeedDecay: 3.2,
                        highSpeedDecay: 4,
                        wrongAnswerPenalty: 10,
                        starvationThreshold: 8,
                        starvationRate: 4,
                        maxExtraDecay: 4,
                        warningThreshold: 12
                    }};
                    
                case 'expert': // Expert mode - original aggressive settings
                    return {{
                        momentumGain: 5,
                        baseDecay: 3,
                        mediumSpeedDecay: 4,
                        highSpeedDecay: 5,
                        wrongAnswerPenalty: 12,
                        starvationThreshold: 6,
                        starvationRate: 3,
                        maxExtraDecay: 5,
                        warningThreshold: 10
                    }};
                    
                default:
                    return this.getMomentumConfig.call({{timeoutSetting: 'normal'}});
            }}
        }}

        loseMomentum() {{
            // Called when player gets wrong answer or times out - DRAMATIC CONSEQUENCES!
            // Wrong answers cause complete momentum loss and coal spilling
            const previousMomentum = this.momentum;
            this.momentum = 0; // Complete momentum loss for wrong answers!
            
            // Trigger dramatic coal spilling animation
            this.triggerCoalSpilling();
            
            // Update displays
            this.updateMomentumDisplay();
            this.updatePressureGauge();
            
            console.log(`💥 COAL SPILLING! Train momentum dropped from ${{previousMomentum}}% to 0% (DRAMATIC CONSEQUENCES)`);
            
            // Play coal spilling sound with multiple chunks
            this.playCoalSpillingSounds();
        }}
        
        triggerCoalSpilling() {{
            // Create dramatic coal spilling visual effects
            const routeContainer = document.querySelector('.route-path');
            if (!routeContainer) return;
            
            // Get train position for coal spilling location
            const locomotive = document.getElementById('train-position');
            if (!locomotive) return;
            
            const trainRect = locomotive.getBoundingClientRect();
            const containerRect = routeContainer.getBoundingClientRect();
            
            // Create multiple coal chunks that spill from the train
            for (let i = 0; i < 8; i++) {{
                const coalChunk = document.createElement('div');
                coalChunk.className = 'coal-chunk';
                coalChunk.textContent = '⬛';
                coalChunk.style.position = 'absolute';
                coalChunk.style.fontSize = '1.2rem';
                coalChunk.style.zIndex = '50';
                coalChunk.style.pointerEvents = 'none';
                
                // Start position near the train
                const startX = (trainRect.left - containerRect.left) + (Math.random() - 0.5) * 30;
                const startY = (trainRect.top - containerRect.top) + (Math.random() - 0.5) * 20;
                coalChunk.style.left = startX + 'px';
                coalChunk.style.top = startY + 'px';
                
                // Add dramatic spilling animation
                coalChunk.style.animation = `coalSpill ${{0.8 + Math.random() * 0.4}}s ease-out forwards`;
                coalChunk.style.animationDelay = `${{i * 0.1}}s`;
                
                routeContainer.appendChild(coalChunk);
                
                // Remove chunk after animation
                setTimeout(() => {{
                    if (coalChunk.parentNode) {{
                        coalChunk.parentNode.removeChild(coalChunk);
                    }}
                }}, 1500 + (i * 100));
            }}
            
            // Flash pressure gauge red to show dramatic failure
            const pressureGauge = document.querySelector('.pressure-gauge-container');
            if (pressureGauge) {{
                pressureGauge.style.animation = 'pressureAlarm 0.8s ease-in-out';
                setTimeout(() => {{
                    pressureGauge.style.animation = '';
                }}, 800);
            }}
        }}
        
        playCoalSpillingSounds() {{
            // Play realistic coal chunk falling sounds
            for (let i = 0; i < 4; i++) {{
                setTimeout(() => {{
                    this.playSound('coal_spill', 0.3);
                }}, i * 150); // Staggered coal chunks falling
            }}
            
            // Add a final "clatter" with incorrect sound
            setTimeout(() => {{
                this.playSound('incorrect', 0.2);
            }}, 600);
            
            console.log('🔊 Playing realistic coal spilling sound effects');
        }}
        
        updateTrainPosition() {{
            // Move train along the route based on momentum
            if (this.momentum > 0) {{
                const speed = this.momentum / 100; // Convert to 0-1 speed multiplier
                this.trainPosition += speed * 0.4; // Continuous movement rate (called 5x per second)
                
                // Check for route completion before capping at 100
                if (this.trainPosition >= 100) {{
                    this.handleRouteCompletion();
                    return; // Route completion will reset position
                }}
                
                // Update visual position along the path
                this.updateTrainVisualization();
                
                // Play momentum-based train sounds (chuffing varies with speed)
                this.updateMomentumBasedAudio(speed);
                
                // Check for station arrivals and passenger deliveries
                this.checkStationArrivals();
            }}
        }}
        
        handleRouteCompletion() {{
            // Prevent multiple calls during transition
            if (this.isRouteSwitching) return;
            this.isRouteSwitching = true;
            
            console.log(`🎉 ROUTE COMPLETED! Moving to new world (Route ${{this.currentRoute + 1}})`);
            
            // CRITICAL: Clean up all timers to prevent chaos
            this.cleanupRouteTimers();
            
            // Play celebration whistle
            this.playSound('train_whistle', 0.6);
            setTimeout(() => {{
                this.playSound('celebration', 0.4);
            }}, 800);
            
            // Initialize route progression if not set
            if (!this.currentRoute) {{
                this.currentRoute = 1;
                this.totalDistance = 0;
            }}
            
            // Track progress
            this.currentRoute++;
            this.totalDistance += 100; // Each route is 100 units
            
            // Show route completion celebration
            this.showRouteCompletionCelebration();
            
            // Generate new route after brief celebration
            setTimeout(() => {{
                this.generateNewRoute();
            }}, 3000);
        }}
        
        cleanupRouteTimers() {{
            // Stop all running intervals to prevent chaos during route transition
            console.log('🧹 Cleaning up route timers...');
            
            if (this.momentumDecayInterval) {{
                clearInterval(this.momentumDecayInterval);
                this.momentumDecayInterval = null;
            }}
            
            if (this.trainMovementInterval) {{
                clearInterval(this.trainMovementInterval);
                this.trainMovementInterval = null;
            }}
            
            if (this.displaySwitchTimeout) {{
                clearTimeout(this.displaySwitchTimeout);
                this.displaySwitchTimeout = null;
            }}
            
            // Clear any auto-submit timeouts
            this.clearAutoSubmitTimeout();
            
            // Clear celebration timeouts to prevent overlapping
            if (this.celebrationTimeout) {{
                clearTimeout(this.celebrationTimeout);
                this.celebrationTimeout = null;
            }}
        }}
        
        showRouteCompletionCelebration() {{
            // Create celebration overlay
            const routeContainer = document.querySelector('.route-path');
            if (!routeContainer) return;
            
            const celebration = document.createElement('div');
            celebration.className = 'route-completion-celebration';
            celebration.innerHTML = `
                <div class="celebration-content">
                    <h2>🎉 ROUTE COMPLETED! 🎉</h2>
                    <p>Excellent work! Moving to Route ${{this.currentRoute}}</p>
                    <div class="progress-stats">
                        <div>📍 Total Distance: ${{this.totalDistance}} km</div>
                        <div>🚂 Routes Completed: ${{this.currentRoute - 1}}</div>
                        <div>✅ Correct Answers: ${{this.correctAnswers}}</div>
                    </div>
                </div>
            `;
            
            routeContainer.appendChild(celebration);
            
            // Remove celebration after animation
            setTimeout(() => {{
                if (celebration.parentNode) {{
                    celebration.parentNode.removeChild(celebration);
                }}
            }}, 2800);
        }}
        
        generateNewRoute() {{
            // Reset train position to start of new route
            this.trainPosition = 0;
            
            // Generate new track layout with different theme
            this.generateDynamicTrack();
            
            // Update route theme/scenery
            this.updateRouteTheme();
            
            // Update route progress display
            this.updateRouteProgressDisplay();
            
            // Generate new passengers for this route
            this.generatePassengers();
            
            // Restart essential timers for new route
            this.restartRouteTimers();
            
            console.log(`🌟 NEW ROUTE GENERATED! Welcome to Route ${{this.currentRoute}} - ${{this.getRouteThemeName()}}`);
            
            // Play "all aboard" whistle
            setTimeout(() => {{
                this.playSound('train_whistle', 0.4);
            }}, 500);
            
            // Clear route switching flag
            this.isRouteSwitching = false;
        }}
        
        restartRouteTimers() {{
            // Restart momentum decay interval
            this.momentumDecayInterval = setInterval(() => {{
                if (this.momentum > 0) {{
                    const decayConfig = this.getMomentumConfig();
                    const timeSinceLastCoal = (Date.now() - this.lastCorrectAnswerTime) / 1000;
                    
                    // Base decay rate increases with higher speeds, but adjusted for skill level
                    let decayRate = this.momentum > 75 ? decayConfig.highSpeedDecay : 
                                   this.momentum > 50 ? decayConfig.mediumSpeedDecay : 
                                   decayConfig.lowSpeedDecay;
                    
                    // Exponential penalty after coal starvation threshold
                    if (timeSinceLastCoal > decayConfig.starvationThreshold) {{
                        const starvationMultiplier = Math.pow(1.5, Math.floor(timeSinceLastCoal / decayConfig.starvationThreshold));
                        decayRate *= Math.min(starvationMultiplier, 10); // Cap at 10x
                    }}
                    
                    this.momentum = Math.max(0, this.momentum - decayRate);
                    this.updateMomentumDisplay();
                }}
            }}, 1000);
            
            // Restart train movement interval
            this.trainMovementInterval = setInterval(() => {{
                this.updateTrainPosition();
            }}, 200); // Update train position 5 times per second for smooth movement
            
            console.log('🔄 Route timers restarted successfully');
        }}
        
        updateRouteProgressDisplay() {{
            const routeProgressEl = document.getElementById('route-progress');
            if (routeProgressEl) {{
                const routeName = this.getRouteThemeName();
                routeProgressEl.textContent = `Route ${{this.currentRoute}} - ${{routeName}}`;
            }}
        }}
        
        getRouteThemeName() {{
            const themes = [
                "Mountain Valley Express",
                "Coastal Railway Adventure", 
                "Forest Journey Trail",
                "Desert Oasis Line",
                "Prairie Meadow Route",
                "Riverside Scenic Railway",
                "Highland Express",
                "Lakeside Loop",
                "Countryside Connection",
                "Sunset Mesa Line"
            ];
            return themes[(this.currentRoute - 1) % themes.length] || "Mystery Route";
        }}
        
        updateRouteTheme() {{
            // Cycle through different time-of-day themes for variety
            const themes = ['dawn', 'morning', 'midday', 'afternoon', 'dusk'];
            const themeIndex = (this.currentRoute - 1) % themes.length;
            const themeName = themes[themeIndex];
            
            const steamJourney = document.querySelector('.race-track-section.steam-journey');
            if (steamJourney) {{
                steamJourney.style.setProperty('--sky-gradient', `var(--${{themeName}}-gradient)`);
                console.log(`🎨 Route theme set to: ${{themeName}}`);
            }}
        }}
        
        updateTrainVisualization() {{
            const locomotive = document.getElementById('train-position');
            if (!locomotive) return;
            
            // Get the actual SVG path and use it for precise positioning
            const routePath = document.querySelector('.train-route');
            if (!routePath) return;
            
            const progress = this.trainPosition / 100;
            const pathLength = routePath.getTotalLength();
            const targetLength = progress * pathLength;
            
            // Get the exact point on the curved path
            const point = routePath.getPointAtLength(targetLength);
            
            // Calculate train rotation based on path direction
            const lookAheadDistance = Math.min(5, pathLength - targetLength); // Look 5 units ahead (or to end)
            const nextPoint = routePath.getPointAtLength(targetLength + lookAheadDistance);
            
            // Calculate angle between current point and next point
            const deltaX = nextPoint.x - point.x;
            const deltaY = nextPoint.y - point.y;
            const angleRadians = Math.atan2(deltaY, deltaX);
            const angleDegrees = angleRadians * (180 / Math.PI);
            
            // Apply position and rotation to locomotive
            locomotive.style.left = point.x + 'px';
            locomotive.style.top = point.y + 'px';
            locomotive.style.transform = `translate(-50%, -50%) rotate(${{angleDegrees}}deg)`;
            locomotive.style.transformOrigin = 'center center';
            
            // Update floating math display position to follow the train
            // Position train math display above the locomotive if following mode is active
            if (this.isDisplayMoving) {{
                let trainMath = document.getElementById('train-math-display');
                if (!trainMath) {{
                    // Create train math display element
                    trainMath = document.createElement('div');
                    trainMath.id = 'train-math-display';
                    trainMath.className = 'train-math-display';
                    
                    // Add to same container as the train
                    const journeyContainer = document.querySelector('.journey-container');
                    if (journeyContainer) {{
                        journeyContainer.appendChild(trainMath);
                        console.log('🎈 Created train math display attached to train');
                    }}
                }}
                
                if (trainMath) {{
                    // Update content and position
                    const challengeNum = document.getElementById('challenge-number').textContent;
                    const targetNum = document.getElementById('target-number').textContent;
                    trainMath.textContent = `${{challengeNum}} + ? = ${{targetNum}}`;
                    trainMath.style.left = point.x + 'px';
                    trainMath.style.top = (point.y - 60) + 'px';
                }}
            }} else {{
                // Remove train math display when not following train
                const trainMath = document.getElementById('train-math-display');
                if (trainMath) {{
                    trainMath.remove();
                }}
            }}
            
            console.log(`🚂 Train at position ${{Math.round(this.trainPosition)}}% - ${{Math.round(point.x)}}, ${{Math.round(point.y)}} (on track)`);
        }}
        
        updateMomentumBasedAudio(speed) {{
            // Play chuffing sounds that vary with train speed/momentum
            const now = Date.now();
            
            // Initialize chuff timing if not set
            if (!this.lastChuffTime) {{
                this.lastChuffTime = now;
                this.chuffInterval = 1000; // Start with slow chuffing
            }}
            
            // Calculate chuffing interval based on speed (faster train = faster chuffs)
            // Speed range: 0-1, chuff interval: 2000ms (slow) to 300ms (fast)
            this.chuffInterval = Math.max(300, 2000 - (speed * 1700));
            
            // Play chuff sound if enough time has passed
            if (now - this.lastChuffTime >= this.chuffInterval) {{
                // Higher speed = louder chuffs (more steam)
                const chuffVolume = Math.min(0.4, 0.1 + (speed * 0.3));
                this.playSound('train_chuff', chuffVolume);
                
                // Occasionally add steam hiss at high speeds
                if (speed > 0.7 && Math.random() < 0.3) {{
                    setTimeout(() => {{
                        this.playSound('steam_hiss', chuffVolume * 0.5);
                    }}, 100);
                }}
                
                this.lastChuffTime = now;
                console.log(`🚂 Chuff! Speed: ${{Math.round(speed * 100)}}%, Interval: ${{Math.round(this.chuffInterval)}}ms`);
            }}
        }}
        
        handleDisplaySwitching() {{
            // Only apply display switching logic in Lightning Sprint train mode
            if (!document.querySelector('.route-path')) return;
            
            // After 2 seconds, enable train-following mode for math display
            if (this.displaySwitchTimeout) {{
                clearTimeout(this.displaySwitchTimeout);
            }}
            
            this.displaySwitchTimeout = setTimeout(() => {{
                this.isDisplayMoving = true;
                console.log('🎈 Display switching activated - math will follow train in 2 seconds');
            }}, 2000);
        }}
        
        checkStationArrivals() {{
            // Check if we've reached any stations where passengers want to get off
            this.stations.forEach(station => {{
                const stationReached = this.trainPosition >= station.position;
                if (stationReached) {{
                    // Deliver passengers to this station
                    const deliveredPassengers = this.passengers.filter(p => p.destination === station.name);
                    if (deliveredPassengers.length > 0) {{
                        deliveredPassengers.forEach(passenger => {{
                            const points = passenger.urgent ? 20 : 10;
                            this.totalScore += points;
                            console.log(`🎯 Delivered ${{passenger.name}} to ${{station.name}} for ${{points}} points!`);
                        }});
                        
                        // Remove delivered passengers
                        this.passengers = this.passengers.filter(p => p.destination !== station.name);
                        this.updatePassengerDisplay();
                        
                        this.playSound('milestone');
                    }}
                }}
            }});
        }}
        
        checkTrainJourneyCompletion() {{
            // Don't check completion in the first 10 seconds to allow game to get started
            const elapsed = (Date.now() - this.gameStartTime) / 1000;
            if (elapsed < 10) return;
            
            // For Lightning Sprint train mode, ONLY end when train reaches the end of the route
            const journeyComplete = this.trainPosition >= 100; // Reached the final station (Capital)
            
            // Only consider ending early if train is truly stuck (very strict conditions)
            const config = this.getMomentumConfig();
            const timeSinceLastCoal = (Date.now() - this.lastCorrectAnswerTime) / 1000;
            const trainStuck = this.momentum <= 0 && 
                              this.trainPosition < 5 && 
                              this.correctAnswers > 5 && 
                              timeSinceLastCoal > (config.starvationThreshold * 2); // Much longer grace period
            
            if (journeyComplete) {{
                // Check if we're in endless steam journey mode or regular race mode
                const isEndlessSteamJourney = document.querySelector('.route-path'); // Steam journey has route-path
                
                if (isEndlessSteamJourney) {{
                    // Don't end race - let the endless route progression handle this
                    console.log('🚂 Journey complete detected but endless mode active - route progression will handle');
                    return;
                }} else {{
                    // Regular race mode - end normally
                    const score = this.totalScore;
                    const deliveredCount = this.correctAnswers;
                    this.endRace(`🎉 Journey Complete! Reached Capital Station! Score: ${{score}} points from ${{deliveredCount}} deliveries!`);
                }}
            }} else if (trainStuck) {{
                // Train is truly stuck - but this should be very rare now with adaptive difficulty
                const isEndlessSteamJourney = document.querySelector('.route-path');
                
                if (isEndlessSteamJourney) {{
                    console.log('🚂 Train stuck detected but endless mode active - generating momentum boost');
                    // In endless mode, give a momentum boost instead of ending
                    this.momentum = Math.max(10, this.momentum + 5); // Small boost to keep going
                    this.updateMomentumDisplay();
                    return;
                }} else {{
                    // Regular race mode - end normally
                    const progress = Math.round(this.trainPosition);
                    console.log(`🚂 Train considered stuck: momentum=${{this.momentum}}, position=${{this.trainPosition}}%, answers=${{this.correctAnswers}}, time since coal=${{Math.round(timeSinceLastCoal)}}s`);
                    this.endRace(`🚂 Train ran out of steam at ${{progress}}% of the journey! Try an easier difficulty mode for more forgiving momentum!`);
                }}
            }}
            
            // If all passengers delivered but train hasn't finished route, generate more passengers!
            if (this.passengers.length === 0 && this.trainPosition < 90) {{
                console.log(`🚂 Generating more passengers - journey continues! Position: ${{Math.round(this.trainPosition)}}%`);
                this.generatePassengers();
            }}
        }}
        
        createDirtParticles(tunnelElement, particleCount = 5) {{
            // Create flying dirt particles when digging (more for deeper tunnels)
            for (let i = 0; i < particleCount; i++) {{
                const particle = document.createElement('div');
                particle.className = 'dirt-particle';
                
                // Random trajectory
                const flyX = (Math.random() - 0.5) * 100;
                const flyY = -30 - Math.random() * 40;
                particle.style.setProperty('--fly-x', flyX + 'px');
                particle.style.setProperty('--fly-y', flyY + 'px');
                
                // Position at tunnel opening
                const rect = tunnelElement.getBoundingClientRect();
                particle.style.left = (rect.left + rect.width / 2) + 'px';
                particle.style.top = rect.top + 'px';
                particle.style.position = 'fixed';
                particle.style.zIndex = '100';
                
                document.body.appendChild(particle);
                
                // Remove after animation
                setTimeout(() => {{
                    if (particle.parentNode) {{
                        particle.parentNode.removeChild(particle);
                    }}
                }}, 600);
            }}
        }}
        
        foxFindsMemory(digger, correctAnswers, isVeryDeep = false) {{
            // Different treasures for different depths
            const shallowTreasures = ['🟡', '🔶', '🟠', '🔸', '✨'];
            const deepTreasures = ['💎', '⭐', '💰', '🏆', '🎯'];
            const veryDeepTreasures = ['💎', '👑', '🏆', '⚡', '🌟', '🔥'];
            
            const shallowMemories = [
                'Found a shiny pebble!',
                'Discovered a small gem!',
                'Unearthed a crystal!',
                'Found a gold flake!'
            ];
            
            const deepMemories = [
                'Discovered an ancient coin!',
                'Found a golden nugget!',
                'Discovered buried treasure!',
                'Unearthed a precious stone!',
                'Discovered a lucky charm!'
            ];
            
            const veryDeepMemories = [
                'FOUND A LEGENDARY DIAMOND!',
                'DISCOVERED ANCIENT TREASURE!',
                'UNEARTHED A ROYAL CROWN!',
                'FOUND THE ULTIMATE GEM!',
                'DISCOVERED MAGICAL ARTIFACT!'
            ];
            
            // Select appropriate treasure and memory based on depth
            let treasures, memories;
            if (isVeryDeep) {{
                treasures = veryDeepTreasures;
                memories = veryDeepMemories;
            }} else if (correctAnswers > 10) {{
                treasures = deepTreasures;
                memories = deepMemories;
            }} else {{
                treasures = shallowTreasures;
                memories = shallowMemories;
            }}
            
            const treasure = treasures[Math.floor(Math.random() * treasures.length)];
            const memory = memories[Math.floor(Math.random() * memories.length)];
            
            // Create floating treasure with depth-based effects
            const treasureElement = document.createElement('div');
            treasureElement.textContent = treasure;
            const treasureSize = isVeryDeep ? '2rem' : correctAnswers > 10 ? '1.7rem' : '1.5rem';
            const glowEffect = isVeryDeep ? 'filter: drop-shadow(0 0 10px #ffd700);' : '';
            
            treasureElement.style.cssText = `
                position: fixed;
                font-size: ${{treasureSize}};
                z-index: 10000;
                pointer-events: none;
                animation: treasureFloat 2s ease-out forwards;
                ${{glowEffect}}
            `;
            
            // Position at tunnel
            const tunnelElement = document.getElementById(`${{digger}}-tunnel`);
            if (tunnelElement) {{
                const rect = tunnelElement.getBoundingClientRect();
                treasureElement.style.left = (rect.left + rect.width / 2) + 'px';
                treasureElement.style.top = rect.top + 'px';
                
                document.body.appendChild(treasureElement);
                
                // Show discovery message
                setTimeout(() => {{
                    if (digger === 'player') {{
                        this.showTreasureMessage(`🦊 ${{memory}}`);
                        this.playSound('milestone', 0.25);
                    }}
                }}, 200);
                
                // Remove treasure element
                setTimeout(() => {{
                    if (treasureElement.parentNode) {{
                        treasureElement.parentNode.removeChild(treasureElement);
                    }}
                }}, 2000);
            }}
        }}
        
        showTreasureMessage(message) {{
            const treasureMsg = document.createElement('div');
            treasureMsg.className = 'treasure-message';
            treasureMsg.textContent = message;
            treasureMsg.style.cssText = `
                position: fixed;
                top: 15%;
                right: 20px;
                background: rgba(255, 215, 0, 0.95);
                color: #333;
                padding: 12px 18px;
                border-radius: 20px;
                font-size: 0.9rem;
                font-weight: 600;
                box-shadow: 0 6px 20px rgba(255, 215, 0, 0.4);
                z-index: 9999;
                animation: treasureSlideIn 1.5s ease-out forwards;
                max-width: 200px;
                text-align: center;
            `;
            
            document.body.appendChild(treasureMsg);
            
            // Remove after display
            setTimeout(() => {{
                if (treasureMsg.parentNode) {{
                    treasureMsg.parentNode.removeChild(treasureMsg);
                }}
            }}, 1500);
        }}
        
        startAIRacers() {{
            if (this.aiUpdateInterval) {{
                clearInterval(this.aiUpdateInterval);
            }}
            
            this.aiUpdateInterval = setInterval(() => {{
                if (!this.isGameActive) return;
                
                this.aiRacers.forEach(ai => {{
                    // Store previous position for passing detection
                    ai.previousPosition = ai.position;
                    
                    // AI progress based on their speed and some randomness
                    let baseProgress = ai.speed * (Math.random() * 0.8 + 0.6); // Some variance
                    
                    // Rubber band catchup system - AI speeds up when behind player
                    const playerProgress = this.correctAnswers;
                    const gapBehindPlayer = playerProgress - ai.position;
                    
                    if (gapBehindPlayer > 0) {{
                        // AI is behind - apply catchup boost
                        let catchupMultiplier = 1.0;
                        
                        if (gapBehindPlayer >= 8) {{
                            catchupMultiplier = 2.5; // Massive catchup for big gaps
                        }} else if (gapBehindPlayer >= 5) {{
                            catchupMultiplier = 2.0; // Strong catchup for medium gaps
                        }} else if (gapBehindPlayer >= 3) {{
                            catchupMultiplier = 1.6; // Moderate catchup for small gaps
                        }} else if (gapBehindPlayer >= 1) {{
                            catchupMultiplier = 1.3; // Light catchup for tiny gaps
                        }}
                        
                        // Apply the catchup boost
                        baseProgress *= catchupMultiplier;
                        
                        // Add extra urgency if player is on a streak
                        if (this.streak >= 5) {{
                            baseProgress *= 1.3; // AI gets desperate when player is hot
                        }}
                        
                        // Debug logging for catchup
                        if (gapBehindPlayer >= 3 && this.totalQuestions % 3 === 0) {{
                            console.log(`🏃 ${{ai.name}} Catchup: Gap=${{Math.round(gapBehindPlayer)}} Boost=${{Math.round(catchupMultiplier * 100)}}% Progress=${{Math.round(baseProgress * 100)/100}}`);
                        }}
                    }}
                    
                    ai.position += baseProgress;
                    
                    // Calculate visual progress 
                    let visualProgress;
                    
                    if (this.style === 'practice') {{
                        // Traditional race to finish line
                        const progress = (ai.position / this.raceGoal) * 100;
                        visualProgress = Math.min(progress, 100);
                    }} else {{
                        // Sprint and survival: visual progress based on position relative to reasonable target
                        const visualTarget = 30;
                        const progress = (ai.position / visualTarget) * 100;
                        visualProgress = Math.min(progress, 95); // Cap at 95% so no one "wins" visually
                    }}
                    
                    const aiElement = document.getElementById(ai.id);
                    
                    if (aiElement) {{
                        if (this.style === 'survival') {{
                            // Use circular positioning for survival mode and track laps
                            const lapInfo = this.updateCircularPosition(aiElement, ai.position);
                            
                            // Update AI's lap count
                            const previousLap = this.aiLaps.get(ai.id) || 0;
                            if (lapInfo.lap > previousLap) {{
                                this.aiLaps.set(ai.id, lapInfo.lap);
                            }}
                        }} else if (this.style === 'sprint') {{
                            // Use tunnel digging for sprint mode
                            const aiNumber = ai.id.includes('1') ? '1' : '2';
                            const targetTunnel = `ai-tunnel-${{aiNumber}}`;
                            const aiDepth = Math.floor(ai.position);
                            console.log(`🦝 ${{ai.name}} (ID: ${{ai.id}}) digging tunnel ${{targetTunnel}} to depth ${{aiDepth}}`);
                            this.updateTunnelDepth(targetTunnel, aiDepth);
                        }} else {{
                            // Use linear positioning for practice mode
                            aiElement.style.left = visualProgress + '%';
                        }}
                    }}
                    
                    // Check if AI wins - only for practice mode with finish line
                    if (this.style === 'practice' && visualProgress >= 100 && this.isGameActive) {{
                        this.handleRaceWin('ai', ai.name);
                    }}
                }});
            }}, 1200); // Update AI every 1200ms (slower for balance)
        }}
        
        handleRaceWin(winner, aiName = null) {{
            if (!this.isGameActive) return;
            
            // Store the race winner for medal calculation
            this.raceWinner = winner;
            this.winningAI = aiName;
            
            // Stop all race activity
            if (this.aiUpdateInterval) {{
                clearInterval(this.aiUpdateInterval);
                this.aiUpdateInterval = null;
            }}
            
            const winnerElement = winner === 'player' 
                ? document.getElementById('player-racer')
                : document.getElementById(this.aiRacers.find(ai => ai.name === aiName)?.id);
                
            if (winnerElement) {{
                winnerElement.classList.add('winner');
                winnerElement.style.left = '95%'; // Move to finish line
            }}
            
            // Play celebration sound and show message
            if (winner === 'player') {{
                this.playSound('celebration');
                setTimeout(() => {{
                    // Check if we're in endless steam journey mode
                    const isEndlessSteamJourney = document.querySelector('.route-path');
                    if (isEndlessSteamJourney) {{
                        console.log('🚂 AI race completion detected but endless mode active - route progression will handle');
                        return;
                    }}
                    this.endRace();
                }}, 1500);
            }} else {{
                this.playSound('gameOver');
                setTimeout(() => {{
                    // Check if we're in endless steam journey mode
                    const isEndlessSteamJourney = document.querySelector('.route-path');
                    if (isEndlessSteamJourney) {{
                        console.log('🚂 AI race completion detected but endless mode active - route progression will handle');
                        return;
                    }}
                    // Show "try again" modal or end game
                    alert(`🏁 ${{aiName}} wins the race! You got ${{this.correctAnswers}}/${{this.raceGoal}} correct. Great effort!`);
                    this.endRace();
                }}, 800);
            }}
        }}
        
        stopRace() {{
            if (this.aiUpdateInterval) {{
                clearInterval(this.aiUpdateInterval);
                this.aiUpdateInterval = null;
            }}
            
            // Stop all sounds when stopping race
            this.stopAllSounds();
        }}
        
        playSound(type, volume = 0.15) {{
            try {{
                const audioContext = new (window.AudioContext || window.webkitAudioContext)();
                
                // Track audio contexts for cleanup
                if (!window.audioContexts) {{
                    window.audioContexts = [];
                }}
                window.audioContexts.push(audioContext);
                
                if (type === 'correct') {{
                    // Classic 90s "power-up" sound - ascending beeps
                    this.play90sSound(audioContext, [
                        {{freq: 523, time: 0, duration: 0.08}},     // C5
                        {{freq: 659, time: 0.08, duration: 0.08}},  // E5  
                        {{freq: 784, time: 0.16, duration: 0.12}}   // G5
                    ], volume, 'sawtooth');
                    
                }} else if (type === 'incorrect') {{
                    // Classic arcade "error" sound - descending buzz
                    this.play90sSound(audioContext, [
                        {{freq: 400, time: 0, duration: 0.15}},
                        {{freq: 300, time: 0.05, duration: 0.15}},
                        {{freq: 200, time: 0.1, duration: 0.2}}
                    ], volume * 0.8, 'square');
                    
                }} else if (type === 'timeout') {{
                    // Classic "time's up" alarm
                    this.play90sSound(audioContext, [
                        {{freq: 800, time: 0, duration: 0.1}},
                        {{freq: 600, time: 0.1, duration: 0.1}},
                        {{freq: 800, time: 0.2, duration: 0.1}},
                        {{freq: 600, time: 0.3, duration: 0.15}}
                    ], volume, 'square');
                    
                }} else if (type === 'countdown') {{
                    // Classic arcade countdown beep
                    this.play90sSound(audioContext, [
                        {{freq: 800, time: 0, duration: 0.15}}
                    ], volume * 0.6, 'sine');
                    
                }} else if (type === 'race_start') {{
                    // Epic race start fanfare
                    this.play90sSound(audioContext, [
                        {{freq: 523, time: 0, duration: 0.1}},     // C5
                        {{freq: 659, time: 0.1, duration: 0.1}},   // E5
                        {{freq: 784, time: 0.2, duration: 0.1}},   // G5
                        {{freq: 1046, time: 0.3, duration: 0.3}}   // C6 - triumphant!
                    ], volume * 1.2, 'sawtooth');
                    
                }} else if (type === 'celebration') {{
                    // Classic victory fanfare - like completing a level
                    this.play90sSound(audioContext, [
                        {{freq: 523, time: 0, duration: 0.12}},    // C5
                        {{freq: 659, time: 0.12, duration: 0.12}}, // E5
                        {{freq: 784, time: 0.24, duration: 0.12}}, // G5
                        {{freq: 1046, time: 0.36, duration: 0.24}}, // C6
                        {{freq: 1318, time: 0.6, duration: 0.3}}   // E6 - epic finish!
                    ], volume * 1.5, 'sawtooth');
                    
                }} else if (type === 'lap_celebration') {{
                    // Radical "bonus achieved" sound
                    this.play90sSound(audioContext, [
                        {{freq: 1046, time: 0, duration: 0.08}},   // C6
                        {{freq: 1318, time: 0.08, duration: 0.08}}, // E6
                        {{freq: 1568, time: 0.16, duration: 0.08}}, // G6
                        {{freq: 2093, time: 0.24, duration: 0.15}} // C7 - totally rad!
                    ], volume * 1.3, 'sawtooth');
                    
                }} else if (type === 'gameOver') {{
                    // Classic "game over" descending tones
                    this.play90sSound(audioContext, [
                        {{freq: 400, time: 0, duration: 0.2}},
                        {{freq: 350, time: 0.2, duration: 0.2}},
                        {{freq: 300, time: 0.4, duration: 0.2}},
                        {{freq: 250, time: 0.6, duration: 0.3}},
                        {{freq: 200, time: 0.9, duration: 0.4}}
                    ], volume, 'triangle');
                    
                }} else if (type === 'ai_turbo') {{
                    // Sound when AI goes into turbo mode
                    this.play90sSound(audioContext, [
                        {{freq: 200, time: 0, duration: 0.05}},
                        {{freq: 400, time: 0.05, duration: 0.05}},
                        {{freq: 600, time: 0.1, duration: 0.05}},
                        {{freq: 800, time: 0.15, duration: 0.1}}
                    ], volume * 0.7, 'sawtooth');
                    
                }} else if (type === 'milestone') {{
                    // Rad milestone sound - like collecting a power-up
                    this.play90sSound(audioContext, [
                        {{freq: 659, time: 0, duration: 0.1}},    // E5
                        {{freq: 784, time: 0.1, duration: 0.1}},  // G5
                        {{freq: 880, time: 0.2, duration: 0.1}},  // A5
                        {{freq: 1046, time: 0.3, duration: 0.15}} // C6 - awesome!
                    ], volume * 1.1, 'sawtooth');
                    
                }} else if (type === 'streak') {{
                    // Epic streak sound - getting hot!
                    this.play90sSound(audioContext, [
                        {{freq: 880, time: 0, duration: 0.06}},   // A5
                        {{freq: 1046, time: 0.06, duration: 0.06}}, // C6
                        {{freq: 1318, time: 0.12, duration: 0.08}}, // E6
                        {{freq: 1760, time: 0.2, duration: 0.1}}  // A6 - on fire!
                    ], volume * 1.2, 'sawtooth');
                    
                }} else if (type === 'combo') {{
                    // Gnarly combo sound - for rapid correct answers
                    this.play90sSound(audioContext, [
                        {{freq: 1046, time: 0, duration: 0.04}}, // C6
                        {{freq: 1175, time: 0.04, duration: 0.04}}, // D6
                        {{freq: 1318, time: 0.08, duration: 0.04}}, // E6
                        {{freq: 1480, time: 0.12, duration: 0.06}} // F#6
                    ], volume * 0.9, 'square');
                    
                }} else if (type === 'whoosh') {{
                    // Cool whoosh sound for fast responses
                    const whooshOsc = audioContext.createOscillator();
                    const whooshGain = audioContext.createGain();
                    const whooshFilter = audioContext.createBiquadFilter();
                    
                    whooshOsc.connect(whooshFilter);
                    whooshFilter.connect(whooshGain);
                    whooshGain.connect(audioContext.destination);
                    
                    whooshOsc.type = 'sawtooth';
                    whooshFilter.type = 'highpass';
                    whooshFilter.frequency.setValueAtTime(1000, audioContext.currentTime);
                    whooshFilter.frequency.exponentialRampToValueAtTime(100, audioContext.currentTime + 0.3);
                    
                    whooshOsc.frequency.setValueAtTime(400, audioContext.currentTime);
                    whooshOsc.frequency.exponentialRampToValueAtTime(800, audioContext.currentTime + 0.15);
                    whooshOsc.frequency.exponentialRampToValueAtTime(200, audioContext.currentTime + 0.3);
                    
                    whooshGain.gain.setValueAtTime(0, audioContext.currentTime);
                    whooshGain.gain.exponentialRampToValueAtTime(volume * 0.6, audioContext.currentTime + 0.02);
                    whooshGain.gain.exponentialRampToValueAtTime(0.001, audioContext.currentTime + 0.3);
                    
                    whooshOsc.start(audioContext.currentTime);
                    whooshOsc.stop(audioContext.currentTime + 0.3);
                    
                }} else if (type === 'train_chuff') {{
                    // Realistic steam train chuffing sound
                    const chuffOsc = audioContext.createOscillator();
                    const chuffGain = audioContext.createGain();
                    const chuffFilter = audioContext.createBiquadFilter();
                    
                    chuffOsc.connect(chuffFilter);
                    chuffFilter.connect(chuffGain);
                    chuffGain.connect(audioContext.destination);
                    
                    chuffOsc.type = 'sawtooth';
                    chuffFilter.type = 'bandpass';
                    chuffFilter.frequency.setValueAtTime(150, audioContext.currentTime);
                    chuffFilter.Q.setValueAtTime(5, audioContext.currentTime);
                    
                    chuffOsc.frequency.setValueAtTime(80, audioContext.currentTime);
                    chuffOsc.frequency.exponentialRampToValueAtTime(120, audioContext.currentTime + 0.05);
                    chuffOsc.frequency.exponentialRampToValueAtTime(60, audioContext.currentTime + 0.2);
                    
                    chuffGain.gain.setValueAtTime(0, audioContext.currentTime);
                    chuffGain.gain.exponentialRampToValueAtTime(volume * 0.8, audioContext.currentTime + 0.01);
                    chuffGain.gain.exponentialRampToValueAtTime(0.001, audioContext.currentTime + 0.2);
                    
                    chuffOsc.start(audioContext.currentTime);
                    chuffOsc.stop(audioContext.currentTime + 0.2);
                    
                }} else if (type === 'train_whistle') {{
                    // Classic steam train whistle
                    this.play90sSound(audioContext, [
                        {{freq: 523, time: 0, duration: 0.3}},    // C5 - long whistle
                        {{freq: 659, time: 0.1, duration: 0.4}},  // E5 - harmony  
                        {{freq: 523, time: 0.3, duration: 0.2}}   // C5 - fade out
                    ], volume * 1.2, 'sine');
                    
                }} else if (type === 'coal_spill') {{
                    // Coal chunks spilling sound effect
                    const coalOsc = audioContext.createOscillator();
                    const coalGain = audioContext.createGain();
                    const coalFilter = audioContext.createBiquadFilter();
                    
                    coalOsc.connect(coalFilter);
                    coalFilter.connect(coalGain);
                    coalGain.connect(audioContext.destination);
                    
                    coalOsc.type = 'square';
                    coalFilter.type = 'lowpass';
                    coalFilter.frequency.setValueAtTime(300, audioContext.currentTime);
                    
                    // Simulate coal chunks falling with random frequency bursts
                    coalOsc.frequency.setValueAtTime(200 + Math.random() * 100, audioContext.currentTime);
                    coalOsc.frequency.exponentialRampToValueAtTime(100 + Math.random() * 50, audioContext.currentTime + 0.1);
                    coalOsc.frequency.exponentialRampToValueAtTime(80 + Math.random() * 40, audioContext.currentTime + 0.3);
                    
                    coalGain.gain.setValueAtTime(0, audioContext.currentTime);
                    coalGain.gain.exponentialRampToValueAtTime(volume * 0.6, audioContext.currentTime + 0.01);
                    coalGain.gain.exponentialRampToValueAtTime(volume * 0.3, audioContext.currentTime + 0.15);
                    coalGain.gain.exponentialRampToValueAtTime(0.001, audioContext.currentTime + 0.4);
                    
                    coalOsc.start(audioContext.currentTime);
                    coalOsc.stop(audioContext.currentTime + 0.4);
                    
                }} else if (type === 'steam_hiss') {{
                    // Steam hissing sound for locomotive
                    const steamOsc = audioContext.createOscillator();
                    const steamGain = audioContext.createGain();
                    const steamFilter = audioContext.createBiquadFilter();
                    
                    steamOsc.connect(steamFilter);
                    steamFilter.connect(steamGain);
                    steamGain.connect(audioContext.destination);
                    
                    steamOsc.type = 'triangle';
                    steamFilter.type = 'highpass';
                    steamFilter.frequency.setValueAtTime(2000, audioContext.currentTime);
                    
                    steamOsc.frequency.setValueAtTime(4000 + Math.random() * 1000, audioContext.currentTime);
                    
                    steamGain.gain.setValueAtTime(0, audioContext.currentTime);
                    steamGain.gain.exponentialRampToValueAtTime(volume * 0.4, audioContext.currentTime + 0.02);
                    steamGain.gain.exponentialRampToValueAtTime(0.001, audioContext.currentTime + 0.6);
                    
                    steamOsc.start(audioContext.currentTime);
                    steamOsc.stop(audioContext.currentTime + 0.6);
                }}
                
            }} catch (e) {{
                console.log('🎵 Web Audio not supported - missing out on rad 90s sounds!');
            }}
        }}
        
        play90sSound(audioContext, notes, volume = 0.15, waveType = 'sine') {{
            notes.forEach(note => {{
                const oscillator = audioContext.createOscillator();
                const gainNode = audioContext.createGain();
                const filterNode = audioContext.createBiquadFilter();
                
                // Create that classic 90s arcade sound chain
                oscillator.connect(filterNode);
                filterNode.connect(gainNode);
                gainNode.connect(audioContext.destination);
                
                // Set wave type for that retro flavor
                oscillator.type = waveType;
                
                // Add some 90s-style filtering
                filterNode.type = 'lowpass';
                filterNode.frequency.setValueAtTime(2000, audioContext.currentTime + note.time);
                filterNode.Q.setValueAtTime(1, audioContext.currentTime + note.time);
                
                // Set frequency and add vibrato for that classic arcade wobble
                oscillator.frequency.setValueAtTime(note.freq, audioContext.currentTime + note.time);
                if (waveType === 'sawtooth' || waveType === 'square') {{
                    // Add slight vibrato for extra 90s flavor
                    oscillator.frequency.exponentialRampToValueAtTime(
                        note.freq * 1.02, 
                        audioContext.currentTime + note.time + note.duration * 0.5
                    );
                    oscillator.frequency.exponentialRampToValueAtTime(
                        note.freq, 
                        audioContext.currentTime + note.time + note.duration
                    );
                }}
                
                // Classic arcade envelope - quick attack, moderate decay
                gainNode.gain.setValueAtTime(0, audioContext.currentTime + note.time);
                gainNode.gain.exponentialRampToValueAtTime(volume, audioContext.currentTime + note.time + 0.01);
                gainNode.gain.exponentialRampToValueAtTime(volume * 0.7, audioContext.currentTime + note.time + note.duration * 0.7);
                gainNode.gain.exponentialRampToValueAtTime(0.001, audioContext.currentTime + note.time + note.duration);
                
                oscillator.start(audioContext.currentTime + note.time);
                oscillator.stop(audioContext.currentTime + note.time + note.duration);
            }});
        }}
        
        // ===== ADAPTIVE DIFFICULTY SYSTEM =====
        
        trackPerformance(isCorrect) {{
            const responseTime = Date.now() - this.questionStartTime;
            const pairKey = `${{this.currentNumber}}_${{this.correctAnswer}}_${{this.targetSum}}`;
            
            // Get or create performance data for this pair
            let pairData = this.difficultyTracker.pairPerformance.get(pairKey) || {{
                attempts: 0,
                correct: 0,
                totalTime: 0,
                avgTime: 0,
                difficulty: 1,
                recentPerformance: [] // Track last 5 attempts
            }};
            
            // Update performance data
            pairData.attempts++;
            if (isCorrect) pairData.correct++;
            pairData.totalTime += responseTime;
            pairData.avgTime = pairData.totalTime / pairData.attempts;
            
            // Track recent performance (sliding window of 5)
            pairData.recentPerformance.push({{
                correct: isCorrect,
                time: responseTime,
                timestamp: Date.now()
            }});
            
            if (pairData.recentPerformance.length > 5) {{
                pairData.recentPerformance.shift();
            }}
            
            // Calculate dynamic difficulty for this pair
            this.calculatePairDifficulty(pairData);
            
            // Update global tracking
            if (isCorrect) {{
                this.difficultyTracker.consecutiveCorrect++;
                this.difficultyTracker.consecutiveIncorrect = 0;
            }} else {{
                this.difficultyTracker.consecutiveIncorrect++;
                this.difficultyTracker.consecutiveCorrect = 0;
            }}
            
            // Adapt overall difficulty
            this.adaptGlobalDifficulty();
            
            // Adapt AI speeds based on player performance
            this.adaptAISpeeds();
            
            // Store updated data
            this.difficultyTracker.pairPerformance.set(pairKey, pairData);
            
            // Exit learning mode after sufficient data
            if (this.difficultyTracker.pairPerformance.size >= 5 && 
                Array.from(this.difficultyTracker.pairPerformance.values())
                    .some(data => data.attempts >= 3)) {{
                this.difficultyTracker.learningMode = false;
            }}
        }}
        
        calculatePairDifficulty(pairData) {{
            if (pairData.attempts < 2) return; // Need more data
            
            const accuracyRate = pairData.correct / pairData.attempts;
            const avgTime = pairData.avgTime;
            const targetTime = 2000; // Target 2 seconds
            
            // Recent performance weight (last 5 attempts matter more)
            const recentAccuracy = pairData.recentPerformance.length > 0 ?
                pairData.recentPerformance.filter(p => p.correct).length / pairData.recentPerformance.length :
                accuracyRate;
            
            const recentAvgTime = pairData.recentPerformance.length > 0 ?
                pairData.recentPerformance.reduce((sum, p) => sum + p.time, 0) / pairData.recentPerformance.length :
                avgTime;
            
            // Calculate difficulty (1-5 scale)
            let newDifficulty = pairData.difficulty;
            
            if (recentAccuracy >= 0.8 && recentAvgTime < targetTime) {{
                // Performing well - increase difficulty
                newDifficulty = Math.min(5, pairData.difficulty + 0.2);
            }} else if (recentAccuracy < 0.5 || recentAvgTime > targetTime * 1.5) {{
                // Struggling - decrease difficulty  
                newDifficulty = Math.max(1, pairData.difficulty - 0.3);
            }}
            
            pairData.difficulty = newDifficulty;
        }}
        
        adaptGlobalDifficulty() {{
            const tracker = this.difficultyTracker;
            
            // Adapt time limits based on recent performance
            if (tracker.consecutiveCorrect >= 3) {{
                // Reduce time limit (increase difficulty)
                tracker.currentTimeLimit = Math.max(1000, 
                    tracker.currentTimeLimit - (tracker.currentTimeLimit * tracker.adaptationRate));
            }} else if (tracker.consecutiveIncorrect >= 2) {{
                // Increase time limit (decrease difficulty)
                tracker.currentTimeLimit = Math.min(5000,
                    tracker.currentTimeLimit + (tracker.baseTimeLimit * tracker.adaptationRate));
            }}
            
            // Update overall difficulty level
            const avgDifficulty = Array.from(tracker.pairPerformance.values())
                .reduce((sum, data) => sum + data.difficulty, 0) / 
                Math.max(1, tracker.pairPerformance.size);
            
            tracker.difficultyLevel = Math.round(avgDifficulty);
        }}
        
        adaptAISpeeds() {{
            // Don't adapt during learning mode - let player get comfortable first
            if (this.difficultyTracker.learningMode) return;
            
            const tracker = this.difficultyTracker;
            const playerSuccessRate = this.calculateRecentSuccessRate();
            const avgResponseTime = this.calculateAverageResponseTime();
            
            // Base speed multipliers for each race mode
            let baseSpeedMultiplier;
            switch (this.style) {{
                case 'practice': baseSpeedMultiplier = 0.7; break;
                case 'sprint': baseSpeedMultiplier = 0.9; break; 
                case 'survival': baseSpeedMultiplier = this.speedMultiplier * (this.survivalMultiplier || 1.0); break;
                default: baseSpeedMultiplier = 0.7;
            }}
            
            // Calculate adaptive multiplier based on player performance
            let adaptiveMultiplier = 1.0;
            
            // Success rate factor (0.5x to 1.8x based on 40%-95% success rate)
            if (playerSuccessRate > 0.85) {{
                adaptiveMultiplier *= 1.6; // Player doing great - speed up AI significantly
            }} else if (playerSuccessRate > 0.75) {{
                adaptiveMultiplier *= 1.3; // Player doing well - speed up AI moderately  
            }} else if (playerSuccessRate > 0.60) {{
                adaptiveMultiplier *= 1.0; // Player doing okay - keep AI at base speed
            }} else if (playerSuccessRate > 0.45) {{
                adaptiveMultiplier *= 0.75; // Player struggling - slow down AI
            }} else {{
                adaptiveMultiplier *= 0.5; // Player really struggling - significantly slow AI
            }}
            
            // Response time factor - faster players get faster AI
            if (avgResponseTime < 1500) {{
                adaptiveMultiplier *= 1.2; // Very fast player
            }} else if (avgResponseTime < 2500) {{
                adaptiveMultiplier *= 1.1; // Fast player
            }} else if (avgResponseTime > 4000) {{
                adaptiveMultiplier *= 0.9; // Slow player
            }}
            
            // Streak bonus - players on hot streaks get more challenge
            if (this.streak >= 8) {{
                adaptiveMultiplier *= 1.3;
            }} else if (this.streak >= 5) {{
                adaptiveMultiplier *= 1.15;
            }}
            
            // Apply bounds to prevent extreme values
            adaptiveMultiplier = Math.max(0.3, Math.min(2.0, adaptiveMultiplier));
            
            // Update AI speeds with adaptive multiplier
            const finalSpeedMultiplier = baseSpeedMultiplier * adaptiveMultiplier;
            
            if (this.aiRacers && this.aiRacers.length >= 2) {{
                // Swift AI (more aggressive, varies more)
                this.aiRacers[0].speed = 0.25 * finalSpeedMultiplier;
                // Math Bot (more consistent, varies less)
                this.aiRacers[1].speed = 0.15 * finalSpeedMultiplier;
                
                // Show player feedback for significant AI speed changes
                this.showAIAdaptationFeedback(adaptiveMultiplier, playerSuccessRate);
                
                // Debug logging for AI adaptation
                if (this.totalQuestions % 5 === 0) {{
                    console.log('🤖 AI Speed Adaptation:', {{
                        playerSuccessRate: Math.round(playerSuccessRate * 100) + '%',
                        avgResponseTime: Math.round(avgResponseTime) + 'ms',
                        streak: this.streak,
                        adaptiveMultiplier: Math.round(adaptiveMultiplier * 100) / 100,
                        swiftAISpeed: Math.round(this.aiRacers[0].speed * 1000) / 1000,
                        mathBotSpeed: Math.round(this.aiRacers[1].speed * 1000) / 1000
                    }});
                }}
            }}
        }}
        
        calculateRecentSuccessRate() {{
            // Calculate success rate from last 10 questions, or all questions if less than 10
            const recentQuestions = Math.min(10, this.totalQuestions);
            if (recentQuestions === 0) return 0.5; // Default for first question
            
            // Use global tracking for recent performance
            const recentCorrect = Math.max(0, this.correctAnswers - Math.max(0, this.totalQuestions - recentQuestions));
            return recentCorrect / recentQuestions;
        }}
        
        calculateAverageResponseTime() {{
            // Calculate average response time from recent pair performance data
            const recentPairs = Array.from(this.difficultyTracker.pairPerformance.values())
                .filter(data => data.attempts >= 1)
                .slice(-5); // Last 5 different pairs encountered
            
            if (recentPairs.length === 0) return 3000; // Default for learning mode
            
            const totalTime = recentPairs.reduce((sum, data) => sum + data.avgTime, 0);
            return totalTime / recentPairs.length;
        }}
        
        showAIAdaptationFeedback(adaptiveMultiplier, playerSuccessRate) {{
            // Only show feedback for significant changes and not too frequently
            if (this.totalQuestions < 8) return; // Wait for some data
            if (this.totalQuestions % 7 !== 0) return; // Don't show too often
            
            let message = '';
            let type = '';
            
            if (adaptiveMultiplier >= 1.4) {{
                const messages = [
                    "🔥 You're crushing it! AI opponents stepping up their game!",
                    "⚡ Impressive speed! The AI is now in competition mode!",
                    "🚀 You're on fire! AI racers are feeling the pressure!",
                    "💪 Amazing performance! AI opponents are now racing seriously!"
                ];
                message = messages[Math.floor(Math.random() * messages.length)];
                type = 'ai_speeding_up';
            }} else if (adaptiveMultiplier <= 0.7) {{
                const messages = [
                    "🤗 Take your time! AI opponents are giving you space to learn!",
                    "📚 Learning mode active! AI racers are being more patient!",
                    "🎯 No rush! AI opponents are matching your learning pace!",
                    "🌟 Perfect! AI racers are helping you build confidence!"
                ];
                message = messages[Math.floor(Math.random() * messages.length)];
                type = 'ai_slowing_down';
            }}
            
            if (message) {{
                this.showAdaptiveFeedback(message, type);
            }}
        }}
        
        getAdaptiveTimeLimit() {{
            // Get base adaptive time limit
            let adaptiveTime;
            
            if (this.difficultyTracker.learningMode) {{
                adaptiveTime = Math.max(2000, this.difficultyTracker.currentTimeLimit);
            }} else {{
                const pairKey = `${{this.currentNumber}}_${{this.correctAnswer}}_${{this.targetSum}}`;
                const pairData = this.difficultyTracker.pairPerformance.get(pairKey);
                
                if (pairData && pairData.attempts >= 2) {{
                    // Use pair-specific difficulty
                    const baseTime = this.difficultyTracker.baseTimeLimit;
                    const difficultyMultiplier = (6 - pairData.difficulty) / 5; // Invert: difficulty 1 = more time
                    adaptiveTime = Math.max(1000, baseTime * difficultyMultiplier);
                }} else {{
                    // Default for new pairs
                    adaptiveTime = this.difficultyTracker.currentTimeLimit;
                }}
            }}
            
            // Apply user timeout setting override
            return this.applyTimeoutSetting(adaptiveTime);
        }}
        
        applyTimeoutSetting(baseTime) {{
            // Apply timeout setting multiplier
            switch (this.timeoutSetting) {{
                case 'preschool':
                    return Math.max(baseTime * 4, 20000); // At least 20 seconds - perfect for 4-year-olds!
                case 'kindergarten':
                    return Math.max(baseTime * 3, 15000); // At least 15 seconds - great for 5-6 year olds
                case 'relaxed':
                    return Math.max(baseTime * 2.4, 12000); // At least 12 seconds - comfortable pace
                case 'slow':
                    return Math.max(baseTime * 1.6, 8000); // At least 8 seconds, or 60% longer
                case 'normal':
                    return Math.max(baseTime, 5000); // At least 5 seconds (default)
                case 'fast':
                    return Math.max(baseTime * 0.6, 3000); // At least 3 seconds, or 40% shorter
                case 'expert':
                    return Math.max(baseTime * 0.4, 2000); // At least 2 seconds, or 60% shorter
                default:
                    return baseTime;
            }}
        }}
        
        getDifficultyInsights() {{
            const tracker = this.difficultyTracker;
            const insights = {{
                overallLevel: tracker.difficultyLevel,
                currentTimeLimit: tracker.currentTimeLimit,
                learningMode: tracker.learningMode,
                strugglingPairs: [],
                masteredPairs: [],
                totalPairsTested: tracker.pairPerformance.size
            }};
            
            // Analyze pair-specific performance
            for (const [pairKey, data] of tracker.pairPerformance) {{
                const [num1, num2, sum] = pairKey.split('_').map(Number);
                const accuracy = data.correct / data.attempts;
                
                if (accuracy < 0.6 && data.attempts >= 3) {{
                    insights.strugglingPairs.push({{
                        pair: `${{num1}} + ${{num2}} = ${{sum}}`,
                        accuracy: Math.round(accuracy * 100),
                        avgTime: Math.round(data.avgTime),
                        difficulty: data.difficulty
                    }});
                }} else if (accuracy >= 0.9 && data.avgTime < 1500 && data.attempts >= 5) {{
                    insights.masteredPairs.push({{
                        pair: `${{num1}} + ${{num2}} = ${{sum}}`,
                        accuracy: Math.round(accuracy * 100),
                        avgTime: Math.round(data.avgTime),
                        difficulty: data.difficulty
                    }});
                }}
            }}
            
            return insights;
        }}
    }}
    
    // Particle Effects System
    class ParticleSystem {{
        constructor() {{
            this.container = document.getElementById('particle-container');
            this.particles = [];
        }}
        
        createParticle(x, y, type = 'star', animation = 'burst') {{
            const particle = document.createElement('div');
            particle.className = `particle ${{type}} ${{animation}}`;
            
            // Random size between 8-20px
            const size = 8 + Math.random() * 12;
            particle.style.width = size + 'px';
            particle.style.height = size + 'px';
            
            // Position
            particle.style.left = x + 'px';
            particle.style.top = y + 'px';
            
            // Add random velocity for trail effects
            if (animation === 'trail') {{
                const dx = (Math.random() - 0.5) * 200;
                const dy = (Math.random() - 0.5) * 200;
                particle.style.setProperty('--dx', dx + 'px');
                particle.style.setProperty('--dy', dy + 'px');
            }}
            
            this.container.appendChild(particle);
            this.particles.push(particle);
            
            // Remove particle after animation
            const duration = animation === 'floating' ? 2000 : animation === 'firework' ? 1200 : 800;
            setTimeout(() => this.removeParticle(particle), duration);
        }}
        
        removeParticle(particle) {{
            if (particle.parentNode) {{
                particle.parentNode.removeChild(particle);
            }}
            this.particles = this.particles.filter(p => p !== particle);
        }}
        
        // Success celebration - burst of stars
        celebrateSuccess(sourceElement) {{
            const rect = sourceElement.getBoundingClientRect();
            const centerX = rect.left + rect.width / 2;
            const centerY = rect.top + rect.height / 2;
            
            // Create burst of particles
            for (let i = 0; i < 8; i++) {{
                const angle = (i / 8) * Math.PI * 2;
                const distance = 30 + Math.random() * 20;
                const x = centerX + Math.cos(angle) * distance;
                const y = centerY + Math.sin(angle) * distance;
                
                const types = ['star', 'circle', 'diamond'];
                const type = types[Math.floor(Math.random() * types.length)];
                
                setTimeout(() => {{
                    this.createParticle(x, y, type, 'burst');
                }}, i * 50);
            }}
        }}
        
        // Major celebration - fireworks and confetti
        celebrateMajor(sourceElement) {{
            const rect = sourceElement.getBoundingClientRect();
            const centerX = rect.left + rect.width / 2;
            const centerY = rect.top + rect.height / 2;
            
            // Central firework
            this.createParticle(centerX, centerY, 'star', 'firework');
            
            // Surrounding smaller fireworks
            for (let i = 0; i < 6; i++) {{
                const angle = (i / 6) * Math.PI * 2;
                const distance = 80 + Math.random() * 40;
                const x = centerX + Math.cos(angle) * distance;
                const y = centerY + Math.sin(angle) * distance;
                
                setTimeout(() => {{
                    this.createParticle(x, y, 'heart', 'firework');
                }}, i * 100);
            }}
            
            // Confetti shower
            setTimeout(() => {{
                for (let i = 0; i < 20; i++) {{
                    const x = centerX + (Math.random() - 0.5) * 200;
                    const y = centerY - 50 + Math.random() * 100;
                    
                    setTimeout(() => {{
                        this.createParticle(x, y, 'confetti', 'floating');
                    }}, i * 30);
                }}
            }}, 300);
        }}
        
        // Streak celebration - trail effects
        celebrateStreak(sourceElement, streakCount) {{
            const rect = sourceElement.getBoundingClientRect();
            const centerX = rect.left + rect.width / 2;
            const centerY = rect.top + rect.height / 2;
            
            const particleCount = Math.min(streakCount * 2, 16);
            
            for (let i = 0; i < particleCount; i++) {{
                const x = centerX + (Math.random() - 0.5) * 100;
                const y = centerY + (Math.random() - 0.5) * 100;
                
                setTimeout(() => {{
                    this.createParticle(x, y, 'circle', 'trail');
                }}, i * 25);
            }}
        }}
        
        // Sparkle effect for hovering or highlighting
        sparkle(sourceElement) {{
            const rect = sourceElement.getBoundingClientRect();
            const x = rect.left + Math.random() * rect.width;
            const y = rect.top + Math.random() * rect.height;
            
            this.createParticle(x, y, 'star', 'sparkle');
        }}
        
        // Game complete celebration
        celebrateGameComplete(sourceElement) {{
            // Multiple waves of celebration
            this.celebrateMajor(sourceElement);
            
            setTimeout(() => {{
                this.celebrateSuccess(sourceElement);
            }}, 400);
            
            setTimeout(() => {{
                this.celebrateStreak(sourceElement, 10);
            }}, 800);
        }}
    }}
    
    // Global particle system instance
    let particleSystem;
    
    // Tag filtering system
    function initializeTagFiltering() {{
        const tagFilters = document.querySelectorAll('.tag-filter');
        const challengeCards = document.querySelectorAll('.challenge-card');
        
        tagFilters.forEach(filter => {{
            filter.addEventListener('click', () => {{
                // Remove active class from all filters
                tagFilters.forEach(f => f.classList.remove('active'));
                // Add active class to clicked filter
                filter.classList.add('active');
                
                const selectedTag = filter.dataset.tag;
                
                // Show/hide challenge cards based on selected tag
                challengeCards.forEach(card => {{
                    if (selectedTag === 'all') {{
                        card.style.display = 'flex';
                    }} else {{
                        const cardTags = card.dataset.tags ? card.dataset.tags.split(',') : [];
                        if (cardTags.includes(selectedTag)) {{
                            card.style.display = 'flex';
                        }} else {{
                            card.style.display = 'none';
                        }}
                    }}
                }});
                
                // Update the visible count in the grid
                updateVisibleChallengeLayout();
            }});
        }});
    }}
    
    function updateVisibleChallengeLayout() {{
        // Force the grid to recalculate layout for visible items
        const challengesGrid = document.querySelector('.challenges-grid');
        if (challengesGrid) {{
            challengesGrid.style.display = 'none';
            challengesGrid.offsetHeight; // Force reflow
            challengesGrid.style.display = 'grid';
        }}
    }}
    
    document.addEventListener('DOMContentLoaded', () => {{
        // Initialize particle system first
        particleSystem = new ParticleSystem();
        
        // Set bead shape class based on data attribute
        const beadSample = document.querySelector('.bead-sample[data-shape]');
        if (beadSample) {{
            const shape = beadSample.getAttribute('data-shape').toLowerCase();
            beadSample.classList.add(shape);
        }}
        
        new ModalManager();
        new SectionNavigator();
        new SorobanQuiz();
        new SortingChallenge();
        new MatchingChallenge();
        new SpeedComplementRace();
        
        // Initialize tag filtering system
        initializeTagFiltering();
        
        // Intercept print attempts and download PDF instead
        window.addEventListener('beforeprint', (e) => {{
            e.preventDefault();
            handlePrintRequest();
        }});
        
        // Also intercept Ctrl+P / Cmd+P
        document.addEventListener('keydown', (e) => {{
            if ((e.ctrlKey || e.metaKey) && e.key === 'p') {{
                e.preventDefault();
                handlePrintRequest();
            }}
        }});
    }});
    </script>
    
    <!-- Race Countdown Overlay -->
    <div id="race-countdown" class="race-countdown">
        <div class="countdown-display">
            <div id="countdown-text" class="countdown-text">Get Ready!</div>
            <div id="countdown-number" class="countdown-number">3</div>
        </div>
    </div>
    
    <!-- Particle Effects Container -->
    <div id="particle-container" class="particle-container"></div>
</body>
</html>'''
    
    # Fill template
    html_content = html_template.format(
        font_family=config.get('font_family', 'DejaVu Sans').replace('"', ''),
        font_size=font_size,
        numeral_color=get_numeral_color(numbers[0] if numbers else 0, config),
        cards_html=''.join(cards_html),
        color_scheme_description=color_scheme_description,
        bead_shape=config.get('bead_shape', 'diamond').capitalize(),
        card_count=len(numbers),
        number_range=f"{min(numbers)} - {max(numbers)}" if numbers else "0",
        len_numbers=len(numbers),
        # Tutorial SVGs
        tutorial_svg_0=tutorial_svgs.get(0, '<svg><text>Error</text></svg>'),
        tutorial_svg_1=tutorial_svgs.get(1, '<svg><text>Error</text></svg>'),
        tutorial_svg_3=tutorial_svgs.get(3, '<svg><text>Error</text></svg>'),
        tutorial_svg_5=tutorial_svgs.get(5, '<svg><text>Error</text></svg>'),
        tutorial_svg_7=tutorial_svgs.get(7, '<svg><text>Error</text></svg>'),
        tutorial_svg_9=tutorial_svgs.get(9, '<svg><text>Error</text></svg>'),
        tutorial_svg_23=tutorial_svgs.get(23, '<svg><text>Error</text></svg>'),
        tutorial_svg_67=tutorial_svgs.get(67, '<svg><text>Error</text></svg>'),
        tutorial_svg_158=tutorial_svgs.get(158, '<svg><text>Error</text></svg>'),
        tutorial_svg_example=tutorial_svgs.get(456, '<svg><text>Error</text></svg>'),
        # Arithmetic SVGs
        arithmetic_svg_23=arithmetic_svgs.get(23, '<svg><text>Error</text></svg>'),
        arithmetic_svg_27=arithmetic_svgs.get(27, '<svg><text>Error</text></svg>'),
        arithmetic_svg_37=arithmetic_svgs.get(37, '<svg><text>Error</text></svg>'),
        arithmetic_svg_47=arithmetic_svgs.get(47, '<svg><text>Error</text></svg>'),
        arithmetic_svg_55=arithmetic_svgs.get(55, '<svg><text>Error</text></svg>'),
        arithmetic_svg_75=arithmetic_svgs.get(75, '<svg><text>Error</text></svg>'),
        arithmetic_svg_89=arithmetic_svgs.get(89, '<svg><text>Error</text></svg>'),
        arithmetic_svg_85=arithmetic_svgs.get(85, '<svg><text>Error</text></svg>'),
        arithmetic_svg_92=arithmetic_svgs.get(92, '<svg><text>Error</text></svg>'),
        arithmetic_svg_84=arithmetic_svgs.get(84, '<svg><text>Error</text></svg>'),
        arithmetic_svg_21=arithmetic_svgs.get(21, '<svg><text>Error</text></svg>')
    )
    
    # Write HTML file
    with open(output_path, 'w', encoding='utf-8') as f:
        f.write(html_content)
    
    print(f"Generated web flashcards: {output_path}")
    
    # Also generate a PDF version for print functionality
    pdf_path = Path(output_path).with_suffix('.pdf')
    try:
        print(f"Generating companion PDF for print functionality...")
        generate_companion_pdf(numbers, config, pdf_path)
        print(f"Generated companion PDF: {pdf_path}")
    except Exception as e:
        print(f"Warning: Could not generate companion PDF: {e}")
        print("Print functionality will show instructions instead of downloading PDF")
    
    return output_path