T.ME/BIBIL_0DAY
CasperSecurity


Server : Apache/2
System : Linux server-15-235-50-60 5.15.0-164-generic #174-Ubuntu SMP Fri Nov 14 20:25:16 UTC 2025 x86_64
User : gositeme ( 1004)
PHP Version : 8.2.29
Disable Function : exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname
Directory :  /home/gositeme/domains/soundstudiopro.com/private_html/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/gositeme/domains/soundstudiopro.com/private_html/community_fixed.php
<?php
session_start();

// Include translation system
require_once 'includes/translations.php';

require_once 'config/database.php';

// Include audio token system for signed URLs
require_once 'utils/audio_token.php';

// Prevent caching of this page to ensure deleted tracks don't show
header('Cache-Control: no-cache, no-store, must-revalidate, max-age=0');
header('Pragma: no-cache');
header('Expires: 0');

// Set page variables
$current_page = 'community_fixed';
$page_title = t('community.page_title');
$page_description = t('community.page_description');

// Include header
include 'includes/header.php';

$pdo = getDBConnection();

// Ensure wishlist table exists for queries on this page
try {
    $pdo->exec("
        CREATE TABLE IF NOT EXISTS user_wishlist (
            id INT AUTO_INCREMENT PRIMARY KEY,
            user_id INT NOT NULL,
            track_id INT NOT NULL,
            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
            UNIQUE KEY unique_wishlist (user_id, track_id),
            FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
            FOREIGN KEY (track_id) REFERENCES music_tracks(id) ON DELETE CASCADE
        )
    ");
} catch (Exception $e) {
    error_log('Wishlist ensure failed: ' . $e->getMessage());
}

// Get current user info
$user_id = $_SESSION['user_id'] ?? null;
$user_name = 'Guest';

if ($user_id) {
    $stmt = $pdo->prepare("SELECT name FROM users WHERE id = ?");
    $stmt->execute([$user_id]);
    $user = $stmt->fetch();
    $user_name = $user['name'] ?? 'User';
}

// Get filter parameters
$sort = $_GET['sort'] ?? 'latest'; // latest, trending, popular, random
$genre = $_GET['genre'] ?? 'all';
// Decode and clean genre parameter (remove quotes if present, decode URL encoding)
if ($genre !== 'all') {
    $genre = urldecode($genre);
    $genre = trim($genre, '"\'');
    $genre = trim($genre);
    
    // Validate genre - reject JSON objects or invalid formats
    // Check if it looks like JSON (starts with { or [)
    if (preg_match('/^[\s]*[{\[]/', $genre)) {
        // This is JSON, not a valid genre - reset to 'all'
        error_log("Invalid genre parameter detected (JSON): " . substr($genre, 0, 100));
        $genre = 'all';
    }
    
    // Check if it contains JSON-like structures (callBackUrl, etc.)
    if (stripos($genre, 'callBackUrl') !== false || stripos($genre, 'callback') !== false) {
        // This contains callback URL data, not a valid genre - reset to 'all'
        error_log("Invalid genre parameter detected (contains callback): " . substr($genre, 0, 100));
        $genre = 'all';
    }
    
    // Additional validation: genre should be a simple string, not contain JSON characters
    if (preg_match('/[{}[\]]/', $genre)) {
        // Contains JSON brackets - invalid genre
        error_log("Invalid genre parameter detected (contains JSON brackets): " . substr($genre, 0, 100));
        $genre = 'all';
    }
}
$time_filter = $_GET['time'] ?? 'all'; // all, today, week, month
$search = $_GET['search'] ?? ''; // search keyword
// Decode and clean search parameter (remove quotes if present, decode URL encoding)
if (!empty($search)) {
    $search = urldecode($search);
    $search = trim($search, '"\'');
    $search = trim($search);
}
$page = max(1, intval($_GET['page'] ?? 1));
$per_page = 24; // Efficient grid layout
$offset = ($page - 1) * $per_page;

// Build time filter
$time_condition = '';
switch ($time_filter) {
    case 'today':
        $time_condition = 'AND mt.created_at >= CURDATE()';
        break;
    case 'week':
        $time_condition = 'AND mt.created_at >= DATE_SUB(NOW(), INTERVAL 1 WEEK)';
        break;
    case 'month':
        $time_condition = 'AND mt.created_at >= DATE_SUB(NOW(), INTERVAL 1 MONTH)';
        break;
}

// Build sort order
$order_by = 'mt.created_at DESC';
switch ($sort) {
    case 'trending':
        $order_by = '(mt.likes_count * 2 + mt.plays_count + mt.comments_count) DESC, mt.created_at DESC';
        break;
    case 'popular':
        $order_by = 'mt.likes_count DESC, mt.plays_count DESC';
        break;
    case 'random':
        $order_by = 'RAND()';
        break;
    default:
        $order_by = 'mt.created_at DESC';
}

// Build genre filter - check genre column, tags, and metadata JSON
// Use case-insensitive LIKE for all conditions to match partial words (e.g., "deep" in "Deep House")
$genre_condition = '';
if ($genre !== 'all' && !empty($genre)) {
    // Normalize genre parameter to lowercase for consistent matching
    $genre_lower = strtolower(trim($genre));
    $genre_like = '%' . $genre_lower . '%';
    
    // Check genre column, tags, and metadata JSON fields (genre and style)
    // All use case-insensitive LIKE to match partial words in compound genres
    $genre_condition = "AND (
        LOWER(mt.genre) LIKE ?
        OR LOWER(mt.tags) LIKE ?
        OR LOWER(JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.genre'))) LIKE ?
        OR LOWER(JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.style'))) LIKE ?
        OR LOWER(CAST(JSON_EXTRACT(mt.metadata, '$.genre') AS CHAR)) LIKE ?
        OR LOWER(CAST(JSON_EXTRACT(mt.metadata, '$.style') AS CHAR)) LIKE ?
    )";
}

// Build comprehensive search filter - industry-leading search across ALL fields
// Searches: title, artist, genre (all locations), tags (all locations), mood, style, instruments, prompt, lyrics
// This ensures "deep" finds "Deep House", "rap" finds all rap tracks, etc.
$search_condition = '';
if (!empty($search)) {
    // Use EXACT same pattern as genre filter for genre fields, then add other fields
    $search_condition = "AND (
        LOWER(mt.title) LIKE ? 
        OR LOWER(u.name) LIKE ?
        OR LOWER(COALESCE(mt.prompt, '')) LIKE ?
        OR LOWER(COALESCE(mt.lyrics, '')) LIKE ?
        OR LOWER(mt.genre) LIKE ?
        OR LOWER(mt.tags) LIKE ?
        OR LOWER(JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.genre'))) LIKE ?
        OR LOWER(JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.style'))) LIKE ?
        OR LOWER(CAST(JSON_EXTRACT(mt.metadata, '$.genre') AS CHAR)) LIKE ?
        OR LOWER(CAST(JSON_EXTRACT(mt.metadata, '$.style') AS CHAR)) LIKE ?
        OR LOWER(mt.style) LIKE ?
        OR LOWER(CAST(JSON_EXTRACT(mt.metadata, '$.proGenre') AS CHAR)) LIKE ?
        OR LOWER(JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.proGenre'))) LIKE ?
        OR LOWER(CAST(JSON_EXTRACT(mt.metadata, '$.proSubGenre') AS CHAR)) LIKE ?
        OR LOWER(JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.proSubGenre'))) LIKE ?
        OR LOWER(CAST(JSON_EXTRACT(mt.metadata, '$.tags') AS CHAR)) LIKE ?
        OR LOWER(JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.tags'))) LIKE ?
        OR LOWER(COALESCE(mt.mood, '')) LIKE ?
        OR LOWER(CAST(JSON_EXTRACT(mt.metadata, '$.mood') AS CHAR)) LIKE ?
        OR LOWER(JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.mood'))) LIKE ?
        OR LOWER(COALESCE(mt.instruments, '')) LIKE ?
        OR LOWER(CAST(JSON_EXTRACT(mt.metadata, '$.instruments') AS CHAR)) LIKE ?
        OR LOWER(JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.instruments'))) LIKE ?
        OR LOWER(CAST(JSON_EXTRACT(mt.metadata, '$.proLeadInstrument') AS CHAR)) LIKE ?
        OR LOWER(JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.proLeadInstrument'))) LIKE ?
        OR LOWER(CAST(JSON_EXTRACT(mt.metadata, '$.proRhythmSection') AS CHAR)) LIKE ?
        OR LOWER(JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.proRhythmSection'))) LIKE ?
        OR LOWER(COALESCE(mt.energy, '')) LIKE ?
        OR LOWER(CAST(JSON_EXTRACT(mt.metadata, '$.energy') AS CHAR)) LIKE ?
        OR LOWER(JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.energy'))) LIKE ?
    )";
}

// Get total count for pagination FIRST (before main query) to validate page number
    $count_sql = "
        SELECT COUNT(*) as total
        FROM music_tracks mt
        INNER JOIN users u ON mt.user_id = u.id
        WHERE mt.status = 'complete'
        AND (mt.audio_url IS NOT NULL AND mt.audio_url != '' OR mt.variations_count > 0)
        AND mt.user_id IS NOT NULL
        AND u.id IS NOT NULL
        AND (mt.is_public = 1 OR mt.is_public IS NULL)
        $time_condition
        $genre_condition
        $search_condition
    ";
$count_stmt = $pdo->prepare($count_sql);
$count_params = [];
if ($genre !== 'all' && !empty($genre)) {
    // Normalize genre parameter to lowercase for consistent case-insensitive matching
    $genre_lower = strtolower(trim($genre));
    $genre_like = '%' . $genre_lower . '%';
    
    // All conditions use case-insensitive LIKE for partial word matching
    $count_params = array_merge($count_params, [
        $genre_like,  // LOWER(mt.genre) LIKE ?
        $genre_like,  // LOWER(mt.tags) LIKE ?
        $genre_like,  // LOWER(JSON_UNQUOTE(JSON_EXTRACT(metadata, '$.genre'))) LIKE ?
        $genre_like,  // LOWER(JSON_UNQUOTE(JSON_EXTRACT(metadata, '$.style'))) LIKE ?
        $genre_like,  // LOWER(CAST(JSON_EXTRACT(metadata, '$.genre') AS CHAR)) LIKE ?
        $genre_like   // LOWER(CAST(JSON_EXTRACT(metadata, '$.style') AS CHAR)) LIKE ?
    ]);
}
if (!empty($search)) {
    // Use lowercase search parameter for case-insensitive matching
    $search_lower = strtolower(trim($search));
    $search_param = '%' . $search_lower . '%';
    // Add search parameters for count query - match SQL placeholders exactly (30 total)
    $count_params = array_merge($count_params, [
        $search_param,  // LOWER(mt.title) LIKE ?
        $search_param,  // LOWER(u.name) LIKE ?
        $search_param,  // LOWER(COALESCE(mt.prompt, '')) LIKE ?
        $search_param,  // LOWER(COALESCE(mt.lyrics, '')) LIKE ?
        $search_param,  // LOWER(mt.genre) LIKE ?
        $search_param,  // LOWER(mt.tags) LIKE ?
        $search_param,  // LOWER(JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.genre'))) LIKE ?
        $search_param,  // LOWER(JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.style'))) LIKE ?
        $search_param,  // LOWER(CAST(JSON_EXTRACT(mt.metadata, '$.genre') AS CHAR)) LIKE ?
        $search_param,  // LOWER(CAST(JSON_EXTRACT(mt.metadata, '$.style') AS CHAR)) LIKE ?
        $search_param,  // LOWER(mt.style) LIKE ?
        $search_param,  // LOWER(CAST(JSON_EXTRACT(mt.metadata, '$.proGenre') AS CHAR)) LIKE ?
        $search_param,  // LOWER(JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.proGenre'))) LIKE ?
        $search_param,  // LOWER(CAST(JSON_EXTRACT(mt.metadata, '$.proSubGenre') AS CHAR)) LIKE ?
        $search_param,  // LOWER(JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.proSubGenre'))) LIKE ?
        $search_param,  // LOWER(CAST(JSON_EXTRACT(mt.metadata, '$.tags') AS CHAR)) LIKE ?
        $search_param,  // LOWER(JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.tags'))) LIKE ?
        $search_param,  // LOWER(COALESCE(mt.mood, '')) LIKE ?
        $search_param,  // LOWER(CAST(JSON_EXTRACT(mt.metadata, '$.mood') AS CHAR)) LIKE ?
        $search_param,  // LOWER(JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.mood'))) LIKE ?
        $search_param,  // LOWER(COALESCE(mt.instruments, '')) LIKE ?
        $search_param,  // LOWER(CAST(JSON_EXTRACT(mt.metadata, '$.instruments') AS CHAR)) LIKE ?
        $search_param,  // LOWER(JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.instruments'))) LIKE ?
        $search_param,  // LOWER(CAST(JSON_EXTRACT(mt.metadata, '$.proLeadInstrument') AS CHAR)) LIKE ?
        $search_param,  // LOWER(JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.proLeadInstrument'))) LIKE ?
        $search_param,  // LOWER(CAST(JSON_EXTRACT(mt.metadata, '$.proRhythmSection') AS CHAR)) LIKE ?
        $search_param,  // LOWER(JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.proRhythmSection'))) LIKE ?
        $search_param,  // LOWER(COALESCE(mt.energy, '')) LIKE ?
        $search_param,  // LOWER(CAST(JSON_EXTRACT(mt.metadata, '$.energy') AS CHAR)) LIKE ?
        $search_param   // LOWER(JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.energy'))) LIKE ?
    ]);
}
    $count_stmt->execute($count_params);
$total_tracks = $count_stmt->fetchColumn();
    $total_pages = $total_tracks > 0 ? ceil($total_tracks / $per_page) : 1; // At least 1 page to show empty state
    
    // Validate page number - redirect if invalid (BEFORE main query)
    // Only redirect if page is too high, NOT if there are no results (which is valid)
    if ($total_tracks > 0 && $page > $total_pages) {
        // Page exceeds total pages - redirect to last valid page
        $redirect_url = "?page=" . $total_pages . "&sort=" . urlencode($sort) . "&time=" . urlencode($time_filter) . "&genre=" . urlencode($genre);
        if (!empty($search)) {
            $redirect_url .= "&search=" . urlencode($search);
        }
        header("Location: " . $redirect_url);
        exit;
    }
    
    // If page is 0 or negative, redirect to page 1
    if ($page < 1) {
        $redirect_url = "?page=1&sort=" . urlencode($sort) . "&time=" . urlencode($time_filter) . "&genre=" . urlencode($genre);
        if (!empty($search)) {
            $redirect_url .= "&search=" . urlencode($search);
        }
        header("Location: " . $redirect_url);
        exit;
    }

// Efficient query - get tracks with all needed data
// IMPORTANT: Only show tracks that actually exist and are complete
// OPTIMIZED: Using JOINs instead of correlated subqueries for better performance
$sql = "
        SELECT 
            mt.id,
            mt.title,
            mt.audio_url,
            mt.duration,
            mt.created_at,
            mt.user_id,
        mt.genre,
        mt.tags,
        mt.image_url,
        mt.task_id,
        mt.metadata,
        mt.variations_count,
        mt.price,
            u.name as artist_name,
        u.id as artist_id,
            u.profile_image,
            COALESCE(like_stats.like_count, 0) as like_count,
            COALESCE(comment_stats.comment_count, 0) as comment_count,
            COALESCE(play_stats.play_count, 0) as play_count,
        COALESCE(share_stats.share_count, 0) as share_count,
            CASE WHEN user_like_stats.track_id IS NOT NULL THEN 1 ELSE 0 END as user_liked,
        COALESCE((SELECT COUNT(*) FROM user_follows WHERE follower_id = ? AND following_id = mt.user_id), 0) as is_following,
        CASE WHEN wishlist_stats.track_id IS NOT NULL THEN 1 ELSE 0 END as is_in_wishlist,
            COALESCE(vote_stats.vote_count, 0) as vote_count,
            COALESCE(rating_stats.average_rating, 0) as average_rating,
            COALESCE(rating_stats.rating_count, 0) as rating_count,
            user_vote_stats.vote_type as user_vote
        FROM music_tracks mt
        INNER JOIN users u ON mt.user_id = u.id
        LEFT JOIN (SELECT track_id, COUNT(*) as like_count FROM track_likes GROUP BY track_id) like_stats ON mt.id = like_stats.track_id
        LEFT JOIN (SELECT track_id, COUNT(*) as comment_count FROM track_comments GROUP BY track_id) comment_stats ON mt.id = comment_stats.track_id
        LEFT JOIN (SELECT track_id, COUNT(*) as play_count FROM track_plays GROUP BY track_id) play_stats ON mt.id = play_stats.track_id
        LEFT JOIN (SELECT track_id, COUNT(*) as share_count FROM track_shares GROUP BY track_id) share_stats ON mt.id = share_stats.track_id
        LEFT JOIN (SELECT track_id, SUM(CASE WHEN vote_type = 'up' THEN 1 ELSE -1 END) as vote_count FROM track_votes GROUP BY track_id) vote_stats ON mt.id = vote_stats.track_id
        LEFT JOIN (SELECT track_id, AVG(rating) as average_rating, COUNT(*) as rating_count FROM track_ratings GROUP BY track_id) rating_stats ON mt.id = rating_stats.track_id
        LEFT JOIN (SELECT track_id FROM track_likes WHERE user_id = ?) user_like_stats ON mt.id = user_like_stats.track_id
        LEFT JOIN (SELECT track_id FROM user_wishlist WHERE user_id = ?) wishlist_stats ON mt.id = wishlist_stats.track_id
        LEFT JOIN (SELECT track_id, vote_type FROM track_votes WHERE user_id = ?) user_vote_stats ON mt.id = user_vote_stats.track_id
        WHERE mt.status = 'complete'
        AND (mt.audio_url IS NOT NULL AND mt.audio_url != '' OR mt.variations_count > 0)
        AND mt.user_id IS NOT NULL
        AND u.id IS NOT NULL
        AND (mt.is_public = 1 OR mt.is_public IS NULL)
        $time_condition
        $genre_condition
        $search_condition
    ORDER BY $order_by
        LIMIT ? OFFSET ?
";

$stmt = $pdo->prepare($sql);
// Parameters: user_like_stats.user_id, wishlist_stats.user_id, user_vote_stats.user_id, is_following user_id (4 total)
$params = [$user_id ?? 0, $user_id ?? 0, $user_id ?? 0, $user_id ?? 0];
if ($genre !== 'all' && !empty($genre)) {
    // Normalize genre parameter to lowercase for consistent case-insensitive matching
    $genre_lower = strtolower(trim($genre));
    $genre_like = '%' . $genre_lower . '%';
    
    // All conditions use case-insensitive LIKE for partial word matching
    $params = array_merge($params, [
        $genre_like,  // LOWER(mt.genre) LIKE ?
        $genre_like,  // LOWER(mt.tags) LIKE ?
        $genre_like,  // LOWER(JSON_UNQUOTE(JSON_EXTRACT(metadata, '$.genre'))) LIKE ?
        $genre_like,  // LOWER(JSON_UNQUOTE(JSON_EXTRACT(metadata, '$.style'))) LIKE ?
        $genre_like,  // LOWER(CAST(JSON_EXTRACT(metadata, '$.genre') AS CHAR)) LIKE ?
        $genre_like   // LOWER(CAST(JSON_EXTRACT(metadata, '$.style') AS CHAR)) LIKE ?
    ]);
}
if (!empty($search)) {
    // Use lowercase search parameter for case-insensitive matching
    // This ensures "deep" matches "Deep House", "rap" matches "Rap", etc.
    $search_lower = strtolower(trim($search));
    $search_param = '%' . $search_lower . '%';
    // Add search parameters - match SQL placeholders exactly (30 total)
    // Order matches the SQL query above
    $params = array_merge($params, [
        $search_param,  // LOWER(mt.title) LIKE ?
        $search_param,  // LOWER(u.name) LIKE ?
        $search_param,  // LOWER(COALESCE(mt.prompt, '')) LIKE ?
        $search_param,  // LOWER(COALESCE(mt.lyrics, '')) LIKE ?
        $search_param,  // LOWER(mt.genre) LIKE ?
        $search_param,  // LOWER(mt.tags) LIKE ?
        $search_param,  // LOWER(JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.genre'))) LIKE ?
        $search_param,  // LOWER(JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.style'))) LIKE ?
        $search_param,  // LOWER(CAST(JSON_EXTRACT(mt.metadata, '$.genre') AS CHAR)) LIKE ?
        $search_param,  // LOWER(CAST(JSON_EXTRACT(mt.metadata, '$.style') AS CHAR)) LIKE ?
        $search_param,  // LOWER(mt.style) LIKE ?
        $search_param,  // LOWER(CAST(JSON_EXTRACT(mt.metadata, '$.proGenre') AS CHAR)) LIKE ?
        $search_param,  // LOWER(JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.proGenre'))) LIKE ?
        $search_param,  // LOWER(CAST(JSON_EXTRACT(mt.metadata, '$.proSubGenre') AS CHAR)) LIKE ?
        $search_param,  // LOWER(JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.proSubGenre'))) LIKE ?
        $search_param,  // LOWER(CAST(JSON_EXTRACT(mt.metadata, '$.tags') AS CHAR)) LIKE ?
        $search_param,  // LOWER(JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.tags'))) LIKE ?
        $search_param,  // LOWER(COALESCE(mt.mood, '')) LIKE ?
        $search_param,  // LOWER(CAST(JSON_EXTRACT(mt.metadata, '$.mood') AS CHAR)) LIKE ?
        $search_param,  // LOWER(JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.mood'))) LIKE ?
        $search_param,  // LOWER(COALESCE(mt.instruments, '')) LIKE ?
        $search_param,  // LOWER(CAST(JSON_EXTRACT(mt.metadata, '$.instruments') AS CHAR)) LIKE ?
        $search_param,  // LOWER(JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.instruments'))) LIKE ?
        $search_param,  // LOWER(CAST(JSON_EXTRACT(mt.metadata, '$.proLeadInstrument') AS CHAR)) LIKE ?
        $search_param,  // LOWER(JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.proLeadInstrument'))) LIKE ?
        $search_param,  // LOWER(CAST(JSON_EXTRACT(mt.metadata, '$.proRhythmSection') AS CHAR)) LIKE ?
        $search_param,  // LOWER(JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.proRhythmSection'))) LIKE ?
        $search_param,  // LOWER(COALESCE(mt.energy, '')) LIKE ?
        $search_param,  // LOWER(CAST(JSON_EXTRACT(mt.metadata, '$.energy') AS CHAR)) LIKE ?
        $search_param   // LOWER(JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.energy'))) LIKE ?
    ]);
}
// Add LIMIT and OFFSET parameters
$params[] = $per_page;
$params[] = $offset;
    $stmt->execute($params);
$tracks = $stmt->fetchAll(PDO::FETCH_ASSOC);

// Double-check: Filter out any tracks that don't actually exist (safety check)
// This ensures deleted tracks never show up, even if there's a race condition
if (!empty($tracks)) {
    $track_ids = array_column($tracks, 'id');
    if (!empty($track_ids)) {
        $placeholders = implode(',', array_fill(0, count($track_ids), '?'));
        $verify_stmt = $pdo->prepare("SELECT id FROM music_tracks WHERE id IN ($placeholders)");
        $verify_stmt->execute($track_ids);
        $valid_track_ids = array_column($verify_stmt->fetchAll(PDO::FETCH_ASSOC), 'id');
        
        // Filter tracks to only include those that still exist
        $tracks = array_filter($tracks, function($track) use ($valid_track_ids) {
            return in_array($track['id'], $valid_track_ids);
        });
        // Re-index array
        $tracks = array_values($tracks);
    }
} else {
    // Ensure tracks is an empty array, not null
    $tracks = [];
}

// Get variations for each track
foreach ($tracks as &$track) {
    $track['variations'] = [];
    if ($track['variations_count'] > 0) {
        try {
            $var_stmt = $pdo->prepare("
        SELECT 
                    variation_index,
                    audio_url,
                    duration,
                    title,
                    tags,
                    image_url
                FROM audio_variations 
                WHERE track_id = ? 
                ORDER BY variation_index ASC
            ");
            $var_stmt->execute([$track['id']]);
            $track['variations'] = $var_stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (Exception $e) {
            $track['variations'] = [];
        }
    }
    
}
unset($track);

// Calculate track rankings for each track
function calculateTrackRankings($pdo, $track) {
    $rankings = [];
    if ($track['status'] === 'complete') {
        // Check if track_votes table exists
        $votes_table_exists = false;
        try {
            $check_stmt = $pdo->query("SHOW TABLES LIKE 'track_votes'");
            $votes_table_exists = $check_stmt->rowCount() > 0;
        } catch (Exception $e) {
            $votes_table_exists = false;
        }
        
        // Get total tracks for context
        $total_tracks_query = "SELECT COUNT(*) FROM music_tracks WHERE status = 'complete'";
        $stmt_total = $pdo->query($total_tracks_query);
        $total_tracks = $stmt_total->fetchColumn();
        
        // Overall ranking (weighted score) - among all complete tracks
        if ($votes_table_exists) {
            $overall_rank_query = "
                SELECT 
                    COUNT(*) + 1 as rank
                FROM music_tracks mt2
                LEFT JOIN (SELECT track_id, COUNT(*) as play_count FROM track_plays GROUP BY track_id) tp2 ON mt2.id = tp2.track_id
                LEFT JOIN (SELECT track_id, COUNT(*) as like_count FROM track_likes GROUP BY track_id) tl2 ON mt2.id = tl2.track_id
                LEFT JOIN (
                    SELECT 
                        track_id, 
                        COALESCE(SUM(CASE WHEN vote_type = 'up' THEN 1 ELSE -1 END), 0) as vote_count
                    FROM track_votes 
                    GROUP BY track_id
                ) tv2 ON mt2.id = tv2.track_id
                LEFT JOIN (SELECT track_id, AVG(rating) as avg_rating, COUNT(*) as rating_count FROM track_ratings GROUP BY track_id) tr2 ON mt2.id = tr2.track_id
                WHERE mt2.status = 'complete'
                AND (
                    (COALESCE(tp2.play_count, 0) * 1.0 + 
                     COALESCE(tl2.like_count, 0) * 2.0 + 
                     COALESCE(tv2.vote_count, 0) * 3.0 +
                     COALESCE(tr2.avg_rating, 0) * COALESCE(tr2.rating_count, 0) * 5.0) >
                    (COALESCE(?, 0) * 1.0 + 
                     COALESCE(?, 0) * 2.0 + 
                     COALESCE(?, 0) * 3.0 +
                     COALESCE(?, 0) * COALESCE(?, 0) * 5.0)
                    OR (
                        (COALESCE(tp2.play_count, 0) * 1.0 + 
                         COALESCE(tl2.like_count, 0) * 2.0 + 
                         COALESCE(tv2.vote_count, 0) * 3.0 +
                         COALESCE(tr2.avg_rating, 0) * COALESCE(tr2.rating_count, 0) * 5.0) =
                        (COALESCE(?, 0) * 1.0 + 
                         COALESCE(?, 0) * 2.0 + 
                         COALESCE(?, 0) * 3.0 +
                         COALESCE(?, 0) * COALESCE(?, 0) * 5.0)
                        AND mt2.created_at > ?
                    )
                )
            ";
            $stmt_rank = $pdo->prepare($overall_rank_query);
            $stmt_rank->execute([
                $track['play_count'] ?? 0, 
                $track['like_count'] ?? 0, 
                $track['vote_count'] ?? 0,
                $track['average_rating'] ?? 0, 
                $track['rating_count'] ?? 0,
                $track['play_count'] ?? 0, 
                $track['like_count'] ?? 0, 
                $track['vote_count'] ?? 0,
                $track['average_rating'] ?? 0, 
                $track['rating_count'] ?? 0,
                $track['created_at'] ?? date('Y-m-d H:i:s')
            ]);
        } else {
            $overall_rank_query = "
                SELECT 
                    COUNT(*) + 1 as rank
                FROM music_tracks mt2
                LEFT JOIN (SELECT track_id, COUNT(*) as play_count FROM track_plays GROUP BY track_id) tp2 ON mt2.id = tp2.track_id
                LEFT JOIN (SELECT track_id, COUNT(*) as like_count FROM track_likes GROUP BY track_id) tl2 ON mt2.id = tl2.track_id
                LEFT JOIN (SELECT track_id, AVG(rating) as avg_rating, COUNT(*) as rating_count FROM track_ratings GROUP BY track_id) tr2 ON mt2.id = tr2.track_id
                WHERE mt2.status = 'complete'
                AND (
                    (COALESCE(tp2.play_count, 0) * 1.0 + 
                     COALESCE(tl2.like_count, 0) * 2.0 + 
                     COALESCE(tr2.avg_rating, 0) * COALESCE(tr2.rating_count, 0) * 5.0) >
                    (COALESCE(?, 0) * 1.0 + 
                     COALESCE(?, 0) * 2.0 + 
                     COALESCE(?, 0) * COALESCE(?, 0) * 5.0)
                    OR (
                        (COALESCE(tp2.play_count, 0) * 1.0 + 
                         COALESCE(tl2.like_count, 0) * 2.0 + 
                         COALESCE(tr2.avg_rating, 0) * COALESCE(tr2.rating_count, 0) * 5.0) =
                        (COALESCE(?, 0) * 1.0 + 
                         COALESCE(?, 0) * 2.0 + 
                         COALESCE(?, 0) * COALESCE(?, 0) * 5.0)
                        AND mt2.created_at > ?
                    )
                )
            ";
            $stmt_rank = $pdo->prepare($overall_rank_query);
            $stmt_rank->execute([
                $track['play_count'] ?? 0, 
                $track['like_count'] ?? 0, 
                $track['average_rating'] ?? 0, 
                $track['rating_count'] ?? 0,
                $track['play_count'] ?? 0, 
                $track['like_count'] ?? 0, 
                $track['average_rating'] ?? 0, 
                $track['rating_count'] ?? 0,
                $track['created_at'] ?? date('Y-m-d H:i:s')
            ]);
        }
        $rankings['overall'] = $stmt_rank->fetchColumn();
        
        // Calculate total score for logging
        $total_score = (($track['play_count'] ?? 0) * 1.0) + 
                      (($track['like_count'] ?? 0) * 2.0) + 
                      (($track['vote_count'] ?? 0) * 3.0) + 
                      (($track['average_rating'] ?? 0) * ($track['rating_count'] ?? 0) * 5.0);
        
        // Play count ranking - among all complete tracks
        $play_rank_query = "
            SELECT COUNT(*) + 1
            FROM music_tracks mt2
            LEFT JOIN (SELECT track_id, COUNT(*) as play_count FROM track_plays GROUP BY track_id) tp2 ON mt2.id = tp2.track_id
            WHERE mt2.status = 'complete'
            AND COALESCE(tp2.play_count, 0) > ?
        ";
        $stmt_rank = $pdo->prepare($play_rank_query);
        $stmt_rank->execute([$track['play_count'] ?? 0]);
        $rankings['plays'] = $stmt_rank->fetchColumn();
        
        // Like count ranking - among all complete tracks
        $like_rank_query = "
            SELECT COUNT(*) + 1
            FROM music_tracks mt2
            LEFT JOIN (SELECT track_id, COUNT(*) as like_count FROM track_likes GROUP BY track_id) tl2 ON mt2.id = tl2.track_id
            WHERE mt2.status = 'complete'
            AND COALESCE(tl2.like_count, 0) > ?
        ";
        $stmt_rank = $pdo->prepare($like_rank_query);
        $stmt_rank->execute([$track['like_count'] ?? 0]);
        $rankings['likes'] = $stmt_rank->fetchColumn();
        
        // Vote count ranking - among all complete tracks (if votes table exists)
        if ($votes_table_exists) {
            $vote_rank_query = "
                SELECT COUNT(*) + 1
                FROM music_tracks mt2
                LEFT JOIN (
                    SELECT 
                        track_id, 
                        COALESCE(SUM(CASE WHEN vote_type = 'up' THEN 1 ELSE -1 END), 0) as vote_count
                    FROM track_votes 
                    GROUP BY track_id
                ) tv2 ON mt2.id = tv2.track_id
                WHERE mt2.status = 'complete'
                AND COALESCE(tv2.vote_count, 0) > ?
            ";
            $stmt_rank = $pdo->prepare($vote_rank_query);
            $stmt_rank->execute([$track['vote_count'] ?? 0]);
            $rankings['votes'] = $stmt_rank->fetchColumn();
        }
        
        // Rating ranking (based on average rating with minimum rating count)
        if (($track['rating_count'] ?? 0) >= 3) {
            $rating_rank_query = "
                SELECT COUNT(*) + 1
                FROM music_tracks mt2
                LEFT JOIN (SELECT track_id, AVG(rating) as avg_rating, COUNT(*) as rating_count FROM track_ratings GROUP BY track_id) tr2 ON mt2.id = tr2.track_id
                WHERE mt2.status = 'complete'
                AND COALESCE(tr2.rating_count, 0) >= 3
                AND COALESCE(tr2.avg_rating, 0) > ?
            ";
            $stmt_rank = $pdo->prepare($rating_rank_query);
            $stmt_rank->execute([$track['average_rating'] ?? 0]);
            $rankings['rating'] = $stmt_rank->fetchColumn();
        }
        
        $rankings['total_tracks'] = $total_tracks;
        // Percentile: Top X% means you're in the top X% of tracks
        // Formula: ((total - rank + 1) / total) * 100
        $rankings['overall_percentile'] = round((($total_tracks - $rankings['overall'] + 1) / max($total_tracks, 1)) * 100, 1);
        
        // Calculate detailed score breakdown for display
        $rankings['score_breakdown'] = [
            'plays_score' => $track['play_count'] * 1.0,
            'likes_score' => $track['like_count'] * 2.0,
            'votes_score' => ($track['vote_count'] ?? 0) * 3.0,
            'rating_score' => ($track['average_rating'] ?? 0) * ($track['rating_count'] ?? 0) * 5.0,
            'total_score' => ($track['play_count'] * 1.0) + ($track['like_count'] * 2.0) + (($track['vote_count'] ?? 0) * 3.0) + (($track['average_rating'] ?? 0) * ($track['rating_count'] ?? 0) * 5.0)
        ];
    }
    return $rankings;
}

// Calculate rankings for each track
// Check if track_votes table exists once
$votes_table_exists = false;
try {
    $check_stmt = $pdo->query("SHOW TABLES LIKE 'track_votes'");
    $votes_table_exists = $check_stmt->rowCount() > 0;
} catch (Exception $e) {
    $votes_table_exists = false;
}

foreach ($tracks as &$track) {
    $track['status'] = 'complete'; // Ensure status is set
    $trackRankings = calculateTrackRankings($pdo, $track);
    $track['trackRankings'] = $trackRankings;
}
unset($track);

// Get community stats
$stats_stmt = $pdo->prepare("
    SELECT 
        COUNT(DISTINCT mt.id) as total_tracks,
        COUNT(DISTINCT mt.user_id) as total_artists,
        COALESCE(SUM(mt.duration), 0) as total_duration
    FROM music_tracks mt
    INNER JOIN users u ON mt.user_id = u.id
    WHERE mt.status = 'complete'
    AND (mt.audio_url IS NOT NULL AND mt.audio_url != '' OR mt.variations_count > 0)
    AND mt.user_id IS NOT NULL
    AND u.id IS NOT NULL
    AND (mt.is_public = 1 OR mt.is_public IS NULL)
");
$stats_stmt->execute();
$stats = $stats_stmt->fetch(PDO::FETCH_ASSOC);
?>

<div class="community-page">
    <!-- Hero Section -->
    <div class="community-hero">
            <div class="container">
            <div class="hero-header">
                <div class="hero-title-section">
                    <h1><?= t('community.hero_title') ?></h1>
                    <p class="subtitle"><?= t('community.hero_subtitle') ?></p>
                </div>
                <button class="share-community-btn" onclick="shareCommunityFeed()" title="Share Community Feed">
                    <i class="fas fa-share-alt"></i>
                    <span>Share Feed</span>
                </button>
            </div>
            
            <!-- Quick Stats -->
            <div class="quick-stats">
                <div class="stat-item">
                    <span class="stat-number"><?= number_format($stats['total_tracks']) ?></span>
                    <span class="stat-label"><?= t('community.tracks') ?></span>
                </div>
                <div class="stat-item">
                    <span class="stat-number"><?= number_format($stats['total_artists']) ?></span>
                    <span class="stat-label"><?= t('community.artists') ?></span>
            </div>
                <div class="stat-item">
                    <span class="stat-number"><?= gmdate('H:i:s', $stats['total_duration']) ?></span>
                    <span class="stat-label"><?= t('community.total_music') ?></span>
                </div>
            </div>
                    </div>
                </div>
                
    <!-- Filters & Controls -->
    <div class="community-filters">
        <div class="container">
            <div class="filters-row">
                <!-- Search Input -->
                <div class="filter-group search-group">
                    <label><?= t('community.search') ?>:</label>
                    <input type="text" 
                           id="searchInput" 
                           class="search-input" 
                           placeholder="<?= t('community.search_placeholder') ?>" 
                           value="<?= htmlspecialchars($search) ?>"
                           onkeypress="if(event.key === 'Enter') updateFilters()">
                    <button class="search-btn" onclick="updateFilters()" title="<?= t('community.search') ?>">
                        <i class="fas fa-search"></i>
                    </button>
                </div>
                
                <!-- Sort Options -->
                    <div class="filter-group">
                    <label><?= t('community.sort') ?>:</label>
                    <select id="sortSelect" onchange="updateFilters()">
                        <option value="latest" <?= $sort === 'latest' ? 'selected' : '' ?>><?= t('community.latest') ?></option>
                        <option value="trending" <?= $sort === 'trending' ? 'selected' : '' ?>><?= t('community.trending') ?></option>
                        <option value="popular" <?= $sort === 'popular' ? 'selected' : '' ?>><?= t('community.popular') ?></option>
                        <option value="random" <?= $sort === 'random' ? 'selected' : '' ?>><?= t('community.random') ?></option>
                        </select>
                    </div>
                    
                <!-- Time Filter -->
                    <div class="filter-group">
                    <label><?= t('community.time') ?>:</label>
                    <select id="timeSelect" onchange="updateFilters()">
                            <option value="all" <?= $time_filter === 'all' ? 'selected' : '' ?>><?= t('community.all_time') ?></option>
                            <option value="today" <?= $time_filter === 'today' ? 'selected' : '' ?>><?= t('community.today') ?></option>
                            <option value="week" <?= $time_filter === 'week' ? 'selected' : '' ?>><?= t('community.this_week') ?></option>
                            <option value="month" <?= $time_filter === 'month' ? 'selected' : '' ?>><?= t('community.this_month') ?></option>
                        </select>
                    </div>
                    
                <!-- Genre Filter -->
                    <div class="filter-group">
                    <label><?= t('community.genre') ?>:</label>
                    <select id="genreSelect" onchange="updateFilters()">
                        <option value="all" <?= $genre === 'all' ? 'selected' : '' ?>><?= t('community.all_genres') ?></option>
                        <option value="Electronic" <?= $genre === 'Electronic' ? 'selected' : '' ?>>Electronic</option>
                        <option value="Pop" <?= $genre === 'Pop' ? 'selected' : '' ?>>Pop</option>
                        <option value="Hip Hop" <?= $genre === 'Hip Hop' ? 'selected' : '' ?>>Hip Hop</option>
                        <option value="Rock" <?= $genre === 'Rock' ? 'selected' : '' ?>>Rock</option>
                        <option value="Jazz" <?= $genre === 'Jazz' ? 'selected' : '' ?>>Jazz</option>
                        <option value="Classical" <?= $genre === 'Classical' ? 'selected' : '' ?>>Classical</option>
                        <option value="Ambient" <?= $genre === 'Ambient' ? 'selected' : '' ?>>Ambient</option>
                        </select>
                    </div>
                </div>
                    </div>
                </div>
            
    <!-- Tracks Grid -->
    <div class="container">
        <?php if (empty($tracks)): ?>
            <div class="empty-state">
                <i class="fas fa-music"></i>
                <h2><?= t('community.no_tracks_found') ?></h2>
                <p><?= t('community.no_tracks_desc') ?></p>
            </div>
        <?php else: ?>
            <div class="tracks-grid" id="tracksGrid" data-current-page="1" data-has-more="<?= $page < $total_pages ? 'true' : 'false' ?>">
                <?php foreach ($tracks as $track): 
                    $displayTitle = !empty($track['title']) ? htmlspecialchars($track['title']) : t('community.untitled_track');
                    $duration = $track['duration'] ? gmdate('i:s', $track['duration']) : '0:00';
                    $isWishlisted = !empty($track['is_in_wishlist']);
                    
                    // Handle track image - use original image_url from database (should always be local path)
                    $imageUrl = $track['image_url'] ?? null;
                    
                    // Trim whitespace and check for empty/null values
                    if ($imageUrl !== null) {
                        $imageUrl = trim($imageUrl);
                        if ($imageUrl === '' || $imageUrl === 'null' || $imageUrl === 'NULL') {
                            $imageUrl = null;
                        }
                    }
                    
                    // If image_url exists and is not empty/null, normalize and use it
                    if (!empty($imageUrl)) {
                        // Normalize local paths (add leading / if missing)
                        if (!str_starts_with($imageUrl, '/')) {
                            $imageUrl = '/' . ltrim($imageUrl, '/');
                        }
                    } else {
                        // Only if image_url is empty/null, try fallback sources
                        if (!empty($track['metadata'])) {
                            $metadata = is_string($track['metadata']) ? json_decode($track['metadata'], true) : $track['metadata'];
                            if (isset($metadata['image_url']) && !empty($metadata['image_url'])) {
                                $metaImageUrl = $metadata['image_url'];
                                // Only use if it's a local path (metadata might have external URLs)
                                if (strpos($metaImageUrl, 'http://') !== 0 && strpos($metaImageUrl, 'https://') !== 0) {
                                    if (!str_starts_with($metaImageUrl, '/')) {
                                        $metaImageUrl = '/' . ltrim($metaImageUrl, '/');
                                    }
                                    $imageUrl = $metaImageUrl;
                                }
                            } elseif (isset($metadata['cover_url']) && !empty($metadata['cover_url'])) {
                                $metaCoverUrl = $metadata['cover_url'];
                                // Only use if it's a local path (metadata might have external URLs)
                                if (strpos($metaCoverUrl, 'http://') !== 0 && strpos($metaCoverUrl, 'https://') !== 0) {
                                    if (!str_starts_with($metaCoverUrl, '/')) {
                                        $metaCoverUrl = '/' . ltrim($metaCoverUrl, '/');
                                    }
                                    $imageUrl = $metaCoverUrl;
                                }
                            }
                        }
                        
                        // Try to find image file by task_id pattern
                        if (empty($imageUrl) && !empty($track['task_id'])) {
                            $uploadsDir = $_SERVER['DOCUMENT_ROOT'] . '/uploads/track_covers/';
                            if (is_dir($uploadsDir)) {
                                $pattern = $uploadsDir . "track_{$track['task_id']}_*";
                                $files = glob($pattern);
                                if (!empty($files)) {
                                    $mostRecent = end($files);
                                    $imageUrl = '/uploads/track_covers/' . basename($mostRecent);
                                }
                            }
                        }
                        
                        // Fallback to default only if no image found
                        if (empty($imageUrl)) {
                            $imageUrl = '/assets/images/default-track.jpg';
                        }
                    }
                    
                    // CRITICAL: Check for selected variation and use its audio URL if available
                    $selectedVariationIndex = null;
                    $selectedVariation = null;
                    
                    // Parse metadata to get selected_variation
                    if (!empty($track['metadata'])) {
                        $trackMetadata = is_string($track['metadata']) ? json_decode($track['metadata'], true) : $track['metadata'];
                        if (isset($trackMetadata['selected_variation'])) {
                            $selectedVariationIndex = (int)$trackMetadata['selected_variation'];
                        }
                    }
                    
                    // Also check the selected_variation column if it exists
                    if ($selectedVariationIndex === null && isset($track['selected_variation'])) {
                        $selectedVariationIndex = (int)$track['selected_variation'];
                    }
                    
                    // Normalize variation audio URLs first
                    if (!empty($track['variations'])) {
                        foreach ($track['variations'] as &$var) {
                            $varAudioUrl = $var['audio_url'] ?? '';
                            if ($varAudioUrl && !preg_match('/^https?:\/\//', $varAudioUrl) && !str_starts_with($varAudioUrl, '/')) {
                                // Fix malformed URLs like "audio_files=filename.mp3" to "/audio_files/filename.mp3"
                                if (strpos($varAudioUrl, 'audio_files=') === 0) {
                                    $var['audio_url'] = '/' . str_replace('audio_files=', 'audio_files/', $varAudioUrl);
                                } else {
                                    $var['audio_url'] = '/' . ltrim($varAudioUrl, '/');
                                }
                            } else {
                                $var['audio_url'] = $varAudioUrl;
                            }
                            
                            // Find the selected variation
                            if ($selectedVariationIndex !== null && isset($var['variation_index']) && $var['variation_index'] == $selectedVariationIndex) {
                                $selectedVariation = $var;
                            }
                        }
                        unset($var); // Break reference
                        
                        // Fallback: if selected variation not found by index, try array position
                        if (!$selectedVariation && $selectedVariationIndex !== null && isset($track['variations'][$selectedVariationIndex])) {
                            $selectedVariation = $track['variations'][$selectedVariationIndex];
                        }
                    }
                    
                    // Use selected variation's audio URL if available, otherwise use main track's audio URL
                    $mainAudioUrl = '';
                    if ($selectedVariation && !empty($selectedVariation['audio_url'])) {
                        $mainAudioUrl = $selectedVariation['audio_url'];
                        // Also update duration if available
                        if (!empty($selectedVariation['duration'])) {
                            $duration = gmdate('i:s', $selectedVariation['duration']);
                        }
                    } else {
                        $mainAudioUrl = $track['audio_url'] ?? '';
                        // If main track URL is empty/invalid and we have variations, use first variation as fallback
                        if (empty($mainAudioUrl) && !empty($track['variations']) && is_array($track['variations'])) {
                            $firstVariation = reset($track['variations']);
                            if (!empty($firstVariation['audio_url'])) {
                                $mainAudioUrl = $firstVariation['audio_url'];
                                if (!empty($firstVariation['duration'])) {
                                    $duration = gmdate('i:s', $firstVariation['duration']);
                                }
                            }
                        }
                    }
                    
                    // Use signed proxy URL to hide actual MP3 file paths and prevent URL sharing
                    // Include variation index if a selected variation exists
                    // CRITICAL: Pass user/session to bind tokens - prevents token sharing
                    $sessionId = session_id();
                    if ($selectedVariationIndex !== null) {
                        $mainAudioUrl = getSignedAudioUrl($track['id'], $selectedVariationIndex, null, $user_id, $sessionId);
                    } else {
                        $mainAudioUrl = getSignedAudioUrl($track['id'], null, null, $user_id, $sessionId);
                    }
                ?>
                    <div class="track-card" 
                         data-track-id="<?= $track['id'] ?>"
                         itemscope 
                         itemtype="http://schema.org/MusicRecording">
                        <!-- Track Image -->
                        <div class="track-image-wrapper">
                            <img src="<?= htmlspecialchars($imageUrl) ?>" alt="<?= $displayTitle ?>" class="track-image" loading="lazy">
                            <div class="track-overlay">
                                <button class="play-btn" 
                                        data-track-id="<?= $track['id'] ?>"
                                        data-artist-id="<?= $track['artist_id'] ?>"
                                        data-audio-url="<?= htmlspecialchars($mainAudioUrl ?? '', ENT_QUOTES) ?>"
                                        data-title="<?= htmlspecialchars($displayTitle ?? '', ENT_QUOTES) ?>"
                                        data-artist="<?= htmlspecialchars($track['artist_name'] ?? '', ENT_QUOTES) ?>">
                                    <i class="fas fa-play"></i>
                                </button>
                                <div class="track-duration"><?= $duration ?></div>
                            </div>
                        </div>
                        
                        <!-- Track Info -->
                        <div class="track-info">
                            <div class="track-title-row">
                                <div class="track-title-wrapper">
                                    <a href="/track.php?id=<?= $track['id'] ?>" 
                                       class="track-title" 
                                       title="<?= $displayTitle ?>"
                                       target="_blank"
                                       itemprop="name"><?= $displayTitle ?></a>
                                    <a href="/artist_profile.php?id=<?= $track['artist_id'] ?>" 
                                       class="track-artist"
                                       target="_blank"
                                       itemprop="byArtist"
                                       itemscope
                                       itemtype="http://schema.org/MusicGroup">
                                        <span itemprop="name"><?= htmlspecialchars($track['artist_name']) ?></span>
                                    </a>
                                </div>
                                <?php if (isset($track['price']) && $track['price'] > 0): ?>
                                    <span class="for-sale-badge" title="<?= t('community.available_for_purchase') ?>">
                                        <i class="fas fa-tag"></i>
                                        <span><?= t('community.for_sale') ?></span>
                                    </span>
                                <?php endif; ?>
                            </div>
                            <?php 
                            // Extract genre and mood like artist_profile.php
                            $genre = 'Electronic'; // default
                            $mood = null;
                            
                            // Try to extract genre/mood from metadata if available
                            if (!empty($track['metadata'])) {
                                $metadata = is_string($track['metadata']) ? json_decode($track['metadata'], true) : $track['metadata'];
                                if ($metadata) {
                                    // Check metadata.genre first, then metadata.style (some tracks store genre in style)
                                    if (!empty($metadata['genre'])) {
                                        $genre = trim($metadata['genre']);
                                    } elseif (!empty($metadata['style'])) {
                                        $genre = trim($metadata['style']);
                                    }
                                    if (!empty($metadata['mood'])) {
                                        $mood = trim($metadata['mood']);
                                    }
                                }
                            }
                            
                            // Use track genre if metadata doesn't have it
                            if (($genre === 'Electronic' || empty($genre)) && !empty($track['genre'])) {
                                $genre = trim($track['genre']);
                            }
                            
                            // Ensure genre is not empty
                            if (empty($genre)) {
                                $genre = 'Electronic';
                            }
                            ?>
                            <div class="track-genre">
                                <a href="?genre=<?= urlencode($genre) ?>" class="genre-tag-link"><?= htmlspecialchars($genre) ?></a>
                                <?php if ($mood && $mood !== $genre && strtolower($mood) !== 'neutral'): ?>
                                    <a href="?genre=<?= urlencode($mood) ?>" class="genre-tag-link"><?= htmlspecialchars($mood) ?></a>
                                <?php endif; ?>
                            </div>
                            <?php if (!empty($track['created_at'])): ?>
                                <div class="track-date">
                                    <i class="fas fa-calendar-alt"></i>
                                    <span><?= date('M j, Y', strtotime($track['created_at'])) ?></span>
                                </div>
                            <?php endif; ?>
                            </div>
                            
                            <!-- Track Ranking Display with Integrated Voting -->
                            <?php 
                            $trackRankings = $track['trackRankings'] ?? [];
                            $status = 'complete'; // Tracks shown here are always complete
                            if ($status === 'complete' && !empty($trackRankings) && isset($trackRankings['overall'])): 
                                // Check if track_votes table exists
                                $votes_table_exists = false;
                                try {
                                    $check_stmt = $pdo->query("SHOW TABLES LIKE 'track_votes'");
                                    $votes_table_exists = $check_stmt->rowCount() > 0;
                                } catch (Exception $e) {
                                    $votes_table_exists = false;
                                }
                            ?>
                            <div class="card-track-ranking" 
                                 style="cursor: pointer; position: relative; margin-top: 0.75rem;" 
                                 data-track-id="<?= $track['id'] ?>"
                                 data-rankings='<?= json_encode($trackRankings, JSON_HEX_APOS | JSON_HEX_QUOT) ?>'
                                 data-track='<?= json_encode([
                                     'id' => $track['id'],
                                     'title' => $displayTitle,
                                     'play_count' => $track['play_count'] ?? 0,
                                     'like_count' => $track['like_count'] ?? 0,
                                     'vote_count' => $track['vote_count'] ?? 0,
                                     'average_rating' => $track['average_rating'] ?? 0,
                                     'rating_count' => $track['rating_count'] ?? 0
                                 ], JSON_HEX_APOS | JSON_HEX_QUOT) ?>'
                                 onclick="handleRankingCardClick(this)">
                                <div style="display: flex; justify-content: space-between; align-items: flex-start; gap: 1rem;">
                                    <div style="flex: 1;">
                                        <div class="ranking-badge-compact">
                                            <i class="fas fa-trophy"></i>
                                            <span class="ranking-label-compact"><?= t('track.rankings.breakdown.rank') ?></span>
                                            <span class="ranking-value-compact">#<?= number_format($trackRankings['overall']) ?></span>
                                            <span class="ranking-out-of-compact">/ <?= number_format($trackRankings['total_tracks']) ?></span>
                                        </div>
                                        <div class="ranking-percentile-compact">
                                            <span class="percentile-badge-compact">Top <?= $trackRankings['overall_percentile'] ?>%</span>
                                        </div>
                                        <div class="ranking-details-compact">
                                            <div class="ranking-detail-item">
                                                <i class="fas fa-play-circle"></i>
                                                <span>#<?= number_format($trackRankings['plays']) ?></span>
                                            </div>
                                            <div class="ranking-detail-item">
                                                <i class="fas fa-heart"></i>
                                                <span>#<?= number_format($trackRankings['likes']) ?></span>
                                            </div>
                                            <?php if ($votes_table_exists && isset($trackRankings['votes'])): ?>
                                            <div class="ranking-detail-item">
                                                <i class="fas fa-thumbs-up"></i>
                                                <span>#<?= number_format($trackRankings['votes']) ?></span>
                                            </div>
                                            <?php endif; ?>
                                            <?php if (($track['rating_count'] ?? 0) >= 3 && isset($trackRankings['rating'])): ?>
                                            <div class="ranking-detail-item">
                                                <i class="fas fa-star"></i>
                                                <span>#<?= number_format($trackRankings['rating']) ?></span>
                                            </div>
                                            <?php endif; ?>
                                        </div>
                                    </div>
                                    
                                    <!-- Integrated Voting Section -->
                                    <div class="voting-section-card" style="display: flex; flex-direction: column; align-items: center; gap: 0.3rem; padding-left: 1rem; border-left: 1px solid rgba(251, 191, 36, 0.3);">
                                        <button class="vote-btn-card vote-up-card <?= ($track['user_vote'] ?? null) === 'up' ? 'active' : '' ?>" 
                                                onclick="event.stopPropagation(); voteTrackFromCard(<?= $track['id'] ?>, 'up', this)"
                                                title="<?= t('artist_profile.upvote') ?>">
                                            <i class="fas fa-thumbs-up"></i>
                                        </button>
                                        <div class="vote-count-card" data-track-id="<?= $track['id'] ?>">
                                            <?= number_format($track['vote_count'] ?? 0) ?>
                                        </div>
                                        <button class="vote-btn-card vote-down-card <?= ($track['user_vote'] ?? null) === 'down' ? 'active' : '' ?>" 
                                                onclick="event.stopPropagation(); voteTrackFromCard(<?= $track['id'] ?>, 'down', this)"
                                                title="<?= t('artist_profile.downvote') ?>">
                                            <i class="fas fa-thumbs-down"></i>
                                        </button>
                                    </div>
                                </div>
                                <div style="text-align: center; margin-top: 0.75rem; font-size: 0.7rem; color: #a0aec0; opacity: 0.7; padding-top: 0.5rem; border-top: 1px solid rgba(251, 191, 36, 0.2);">
                                    <i class="fas fa-info-circle"></i> <?= t('artist_profile.click_ranking_for_details') ?>
                                </div>
                            </div>
                            <?php endif; ?>
                            
                        <!-- Track Stats -->
                        <div class="track-stats">
                            <button class="stat-btn" title="<?= t('preview.plays') ?>">
                                <i class="fas fa-headphones-alt"></i>
                                <span><?= number_format($track['play_count']) ?></span>
                            </button>
                            <button class="stat-btn like-btn <?= $track['user_liked'] ? 'liked' : '' ?>" onclick="toggleLike(<?= $track['id'] ?>, this)" title="<?= t('library.card.like') ?>">
                                    <i class="fas fa-heart"></i>
                                <span><?= number_format($track['like_count']) ?></span>
                                </button>
                            <button class="stat-btn" onclick="showComments(<?= $track['id'] ?>)" title="<?= t('artist_profile.comments') ?>">
                                    <i class="fas fa-comment"></i>
                                <span><?= number_format($track['comment_count']) ?></span>
                                </button>
                            <button class="stat-btn" onclick="shareTrack(<?= $track['id'] ?>)" title="<?= t('library.card.share') ?>">
                                <i class="fas fa-share"></i>
                                <span><?= number_format($track['share_count'] ?? 0) ?></span>
                                </button>
                            <?php if ($user_id): ?>
                            <button class="stat-btn add-to-crate-btn" onclick="openAddToCrateModal(<?= $track['id'] ?>, '<?= htmlspecialchars($displayTitle, ENT_QUOTES) ?>')" title="<?= t('library.crates.add_to_crate') ?>">
                                <i class="fas fa-box"></i>
                            </button>
                            <?php endif; ?>
                            <button class="stat-btn" onclick="showTrackRatingModal(<?= $track['id'] ?>, '<?= htmlspecialchars($displayTitle, ENT_QUOTES) ?>')" title="<?= t('artist_profile.rate_track') ?>">
                                <i class="fas fa-star" style="color: <?= ($track['rating_count'] ?? 0) > 0 ? '#fbbf24' : 'inherit' ?>;"></i>
                                <?php if (($track['rating_count'] ?? 0) > 0): ?>
                                <span><?= number_format($track['average_rating'] ?? 0, 1) ?></span>
                                <?php endif; ?>
                            </button>
                            <?php if (!empty($track['variations'])): ?>
                                <button class="stat-btn variations-btn" onclick="showVariations(<?= $track['id'] ?>, this)" title="<?= count($track['variations']) ?> <?= t('community.variations') ?>">
                                    <i class="fas fa-layer-group"></i>
                                    <span><?= count($track['variations']) ?></span>
                                </button>
                            <?php endif; ?>
                            <?php if ($user_id && $user_id != $track['user_id']): ?>
                                <button class="stat-btn follow-btn <?= $track['is_following'] ? 'following' : '' ?>" 
                                        onclick="toggleFollow(<?= $track['user_id'] ?>, this)"
                                        title="<?= $track['is_following'] ? t('community.unfollow_artist') : t('community.follow_artist') ?>">
                                    <i class="fas fa-<?= $track['is_following'] ? 'user-check' : 'user-plus' ?>"></i>
                                </button>
                            <?php endif; ?>
                        </div>
                        
                        <!-- Add to Cart Button -->
                        <div class="track-cart-section">
                            <button class="add-to-cart-btn" 
                                    type="button"
                                    data-track-id="<?= $track['id'] ?>"
                                    data-track-title="<?= htmlspecialchars($displayTitle, ENT_QUOTES | ENT_HTML5, 'UTF-8') ?>"
                                    data-track-price="<?= isset($track['price']) && $track['price'] !== null ? (float)$track['price'] : 1.99 ?>"
                                    onclick="addToCart(<?= $track['id'] ?>, '<?= htmlspecialchars($displayTitle) ?>', <?= isset($track['price']) && $track['price'] !== null ? (float)$track['price'] : 1.99 ?>, this)">
                                <i class="fas fa-shopping-cart"></i>
                                <span><?= t('community.add_to_cart') ?></span>
                                <?php 
                                // Handle price display: null/not set = 1.99, 0 = free, > 0 = actual price
                                $displayPrice = 1.99; // default
                                if (isset($track['price']) && $track['price'] !== null && $track['price'] !== '') {
                                    $displayPrice = (float)$track['price'];
                                }
                                ?>
                                <span class="cart-price"><?= $displayPrice > 0 ? '$' . number_format($displayPrice, 2) : t('common.free') ?></span>
                            </button>
                            <button class="wishlist-inline-btn <?= $isWishlisted ? 'active' : '' ?>" 
                                    onclick="toggleWishlist(<?= $track['id'] ?>, this)" 
                                    aria-pressed="<?= $isWishlisted ? 'true' : 'false' ?>"
                                    title="<?= $isWishlisted ? t('artist_profile.remove_from_wishlist') : t('artist_profile.add_to_wishlist') ?>">
                                <i class="<?= $isWishlisted ? 'fas' : 'far' ?> fa-heart"></i>
                            </button>
                        </div>
                        
                        <!-- Variations Container (hidden by default) -->
                        <?php if (!empty($track['variations'])): ?>
                            <div class="variations-container" id="variations-<?= $track['id'] ?>" style="display: none;">
                                <div class="variations-header">
                                    <span><?= t('community.audio_variations') ?> (<?= count($track['variations']) ?>)</span>
                            </div>
                                <div class="variations-grid">
                                    <?php foreach ($track['variations'] as $var): 
                                        // Ensure variation_index is set and is an integer
                                        $variationIndex = isset($var['variation_index']) ? (int)$var['variation_index'] : null;
                                        
                                        // Use main track title with variation number for consistency
                                        $variationDisplayTitle = $displayTitle . ' - ' . t('community.variation') . ' ' . (($variationIndex !== null) ? ($variationIndex + 1) : 1);
                                        
                                        // Generate signed URL with variation index
                                        // CRITICAL: Pass user/session to bind tokens - prevents token sharing
                                        $sessionId = session_id();
                                        $variationAudioUrl = getSignedAudioUrl($track['id'], $variationIndex, null, $user_id, $sessionId);
                                    ?>
                                        <div class="variation-item">
                                            <div class="variation-info">
                                                <span class="variation-title"><?= htmlspecialchars($variationDisplayTitle) ?></span>
                                                <span class="variation-duration"><?= $var['duration'] ? gmdate('i:s', $var['duration']) : '0:00' ?></span>
                        </div>
                                            <button class="variation-play-btn"
                                                    data-track-id="<?= $track['id'] ?>"
                                                    data-audio-url="<?= htmlspecialchars($variationAudioUrl, ENT_QUOTES) ?>"
                                                    data-title="<?= htmlspecialchars($variationDisplayTitle, ENT_QUOTES) ?>"
                                                    data-artist="<?= htmlspecialchars($track['artist_name'] ?? '', ENT_QUOTES) ?>"
                                                    <?php if ($variationIndex !== null): ?>
                                                    data-variation-index="<?= $variationIndex ?>"
                                                    <?php endif; ?>>
                                                <i class="fas fa-play"></i>
                                            </button>
                    </div>
                 <?php endforeach; ?>
                                </div>
                            </div>
                        <?php endif; ?>
                    </div>
                <?php endforeach; ?>
            </div>

            <!-- Infinite Scroll Loading Indicator -->
            <div id="infiniteScrollLoader" style="display: none; text-align: center; padding: 40px 20px; color: white;">
                <div class="loading-spinner" style="font-size: 2rem; margin-bottom: 1rem;">âŗ</div>
                <p style="font-size: 1.1rem; font-weight: 600;"><?= t('community.loading_more') ?></p>
            </div>
            
            <!-- End of Results Message -->
            <div id="endOfResults" style="display: none; text-align: center; padding: 40px 20px; color: white;">
                <p style="font-size: 1.1rem; font-weight: 600; opacity: 0.8;"><?= t('community.no_more_tracks') ?></p>
            </div>
        <?php endif; ?>
    </div>
    </div>

<style>
/* Animated gradient background */
@keyframes gradientShift {
    0% { background-position: 0% 50%; }
    50% { background-position: 100% 50%; }
    100% { background-position: 0% 50%; }
}

.community-page {
    min-height: 100vh;
    background: linear-gradient(-45deg, #667eea, #764ba2, #f093fb, #4facfe);
    background-size: 400% 400%;
    animation: gradientShift 15s ease infinite;
    padding-bottom: 100px;
    position: relative;
    overflow-x: hidden;
}

/* Floating particles effect */
.community-page::before {
    content: '';
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-image: 
        radial-gradient(circle at 20% 50%, rgba(255,255,255,0.1) 0%, transparent 50%),
        radial-gradient(circle at 80% 80%, rgba(255,255,255,0.1) 0%, transparent 50%),
        radial-gradient(circle at 40% 20%, rgba(255,255,255,0.1) 0%, transparent 50%);
    pointer-events: none;
    z-index: 0;
}

.community-hero {
    position: relative;
    z-index: 1;
    background: rgba(0, 0, 0, 0.2);
    backdrop-filter: blur(20px);
    padding: 80px 20px;
    text-align: center;
    color: white;
    border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

.hero-header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 20px;
    margin-bottom: 20px;
    flex-wrap: wrap;
}

.hero-title-section {
    flex: 1;
    min-width: 300px;
}

.community-hero h1 {
    font-size: 3.5rem;
    margin: 0 0 15px 0;
    font-weight: 700;
    text-shadow: 0 4px 20px rgba(0,0,0,0.3);
    animation: fadeInUp 0.8s ease;
}

.community-hero .subtitle {
    font-size: 1.2rem;
    opacity: 0.95;
    margin-bottom: 40px;
    font-weight: 400;
    animation: fadeInUp 0.8s ease 0.2s both;
}

.share-community-btn {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 16px 32px;
    background: linear-gradient(135deg, rgba(102, 126, 234, 0.9), rgba(118, 75, 162, 0.9));
    border: 2px solid rgba(255, 255, 255, 0.3);
    border-radius: 30px;
    color: white;
    font-size: 1.2rem;
    font-weight: 700;
    cursor: pointer;
    transition: all 0.3s ease;
    backdrop-filter: blur(10px);
    white-space: nowrap;
    animation: fadeInUp 0.8s ease 0.3s both;
    box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
    min-height: 50px;
}

.share-community-btn:hover {
    background: linear-gradient(135deg, rgba(102, 126, 234, 1), rgba(118, 75, 162, 1));
    border-color: rgba(255, 255, 255, 0.5);
    transform: translateY(-3px);
    box-shadow: 0 10px 30px rgba(102, 126, 234, 0.4);
}

.share-community-btn:active {
    transform: translateY(-1px);
}

.share-community-btn i {
    font-size: 1.3rem;
}

@keyframes fadeInUp {
    from {
        opacity: 0;
        transform: translateY(30px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

.quick-stats {
    display: flex;
    justify-content: center;
    gap: 50px;
    margin-top: 40px;
    flex-wrap: wrap;
    animation: fadeInUp 0.8s ease 0.4s both;
}

.stat-item {
    text-align: center;
    padding: 20px 30px;
    background: rgba(255, 255, 255, 0.1);
    backdrop-filter: blur(10px);
    border-radius: 15px;
    border: 1px solid rgba(255, 255, 255, 0.2);
    transition: all 0.3s ease;
    cursor: default;
}

.stat-item:hover {
    transform: translateY(-5px) scale(1.05);
    background: rgba(255, 255, 255, 0.15);
    box-shadow: 0 10px 30px rgba(0,0,0,0.2);
}

.stat-number {
    display: block;
    font-size: 2.5rem;
    font-weight: 800;
    margin-bottom: 8px;
    color: white;
}

.stat-label {
    font-size: 0.85rem;
    opacity: 0.9;
    text-transform: uppercase;
    letter-spacing: 2px;
    font-weight: 600;
}

.community-filters {
    position: relative;
    z-index: 1;
    background: rgba(255, 255, 255, 0.08);
    backdrop-filter: blur(20px);
    padding: 25px;
    margin-bottom: 40px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

.filters-row {
    display: flex;
    gap: 25px;
    justify-content: center;
    flex-wrap: wrap;
    align-items: center;
}

.filter-group {
    display: flex;
    align-items: center;
    gap: 12px;
}

.filter-group label {
    color: white;
    font-weight: 600;
    font-size: 0.95rem;
    text-shadow: 0 2px 10px rgba(0,0,0,0.2);
}

.filter-group select {
    padding: 10px 18px;
    border: 1px solid rgba(255, 255, 255, 0.3);
    border-radius: 12px;
    background: rgba(255, 255, 255, 0.15);
    backdrop-filter: blur(10px);
    color: white;
    font-size: 0.95rem;
    font-weight: 500;
    cursor: pointer;
    transition: all 0.3s ease;
    outline: none;
}

.search-group {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 1;
    max-width: 400px;
}

.search-input {
    flex: 1;
    padding: 10px 18px;
    border: 1px solid rgba(255, 255, 255, 0.3);
    border-radius: 12px;
    background: rgba(255, 255, 255, 0.15);
    backdrop-filter: blur(10px);
    color: white;
    font-size: 0.95rem;
    font-weight: 500;
    transition: all 0.3s ease;
    outline: none;
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

.search-input::placeholder {
    color: rgba(255, 255, 255, 0.5);
}

.search-input:focus {
    background: rgba(255, 255, 255, 0.25);
    border-color: rgba(255, 255, 255, 0.6);
    box-shadow: 0 5px 15px rgba(0,0,0,0.2);
}

.search-btn {
    padding: 10px 18px;
    border: 1px solid rgba(255, 255, 255, 0.3);
    border-radius: 12px;
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    color: white;
    cursor: pointer;
    transition: all 0.3s ease;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.95rem;
}

.search-btn:hover {
    background: linear-gradient(135deg, #5a67d8 0%, #6b46c1 100%);
    transform: translateY(-2px);
    box-shadow: 0 5px 15px rgba(102, 126, 234, 0.3);
}

.filter-group select:hover {
    background: rgba(255, 255, 255, 0.25);
    border-color: rgba(255, 255, 255, 0.5);
    transform: translateY(-2px);
    box-shadow: 0 5px 15px rgba(0,0,0,0.2);
}

.filter-group select:focus {
    background: rgba(255, 255, 255, 0.25);
    border-color: rgba(255, 255, 255, 0.6);
}

.filter-group select option {
    background: #667eea;
    color: white;
    padding: 10px;
}

.container {
    max-width: 1400px;
    margin: 0 auto;
    padding: 0 20px;
    position: relative;
    z-index: 1;
}

.tracks-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 30px;
    margin-top: 40px;
}

.track-card {
    background: rgba(255, 255, 255, 0.98);
    border-radius: 20px;
    overflow: hidden;
    transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
    cursor: pointer;
    box-shadow: 0 8px 25px rgba(0,0,0,0.15);
    border: 1px solid rgba(255, 255, 255, 0.3);
    animation: cardFadeIn 0.6s ease both;
}

@keyframes cardFadeIn {
    from {
        opacity: 0;
        transform: translateY(20px) scale(0.95);
    }
    to {
        opacity: 1;
        transform: translateY(0) scale(1);
    }
}

.track-card:nth-child(1) { animation-delay: 0.1s; }
.track-card:nth-child(2) { animation-delay: 0.15s; }
.track-card:nth-child(3) { animation-delay: 0.2s; }
.track-card:nth-child(4) { animation-delay: 0.25s; }
.track-card:nth-child(5) { animation-delay: 0.3s; }
.track-card:nth-child(6) { animation-delay: 0.35s; }

.track-card:hover {
    transform: translateY(-10px) scale(1.02);
    box-shadow: 0 20px 40px rgba(0,0,0,0.3);
    border-color: rgba(255, 255, 255, 0.5);
}

.track-image-wrapper {
    position: relative;
    width: 100%;
    padding-top: 100%;
    overflow: hidden;
    background: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #f093fb 100%);
}

.track-image {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform 0.5s ease;
}

.track-card:hover .track-image {
    transform: scale(1.1) rotate(2deg);
}

.track-overlay {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: linear-gradient(135deg, rgba(102, 126, 234, 0.8) 0%, rgba(118, 75, 162, 0.8) 100%);
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    transition: all 0.4s ease;
}

.track-card:hover .track-overlay {
    opacity: 1;
}

.play-btn {
    width: 70px;
    height: 70px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.95);
    border: 3px solid rgba(255, 255, 255, 0.5);
    color: #667eea;
    font-size: 1.8rem;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55);
    box-shadow: 0 10px 30px rgba(0,0,0,0.3);
    transform: scale(0.9);
}

.track-card:hover .play-btn {
    transform: scale(1);
}

.play-btn:hover {
    transform: scale(1.15);
    box-shadow: 0 15px 40px rgba(0,0,0,0.4);
    background: white;
}

.play-btn:active {
    transform: scale(0.95);
}

.track-duration {
    position: absolute;
    bottom: 12px;
    right: 12px;
    background: rgba(0, 0, 0, 0.75);
    backdrop-filter: blur(10px);
    color: white;
    padding: 6px 12px;
    border-radius: 20px;
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.5px;
}

.track-info {
    padding: 18px 20px 20px;
    background: white;
}

.track-title-row {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 10px;
    min-height: 48px;
}

.track-title-wrapper {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-width: 0;
    gap: 4px;
}

.track-card .track-title,
.track-info .track-title {
    font-size: 1.3rem;
    font-weight: 700;
    margin: 0;
    color: #1a1a2e !important;
    line-height: 1.4;
    text-decoration: none;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    cursor: pointer;
    transition: all 0.3s ease;
    flex: none;
    min-width: 0;
    letter-spacing: -0.02em;
    word-break: break-word;
    width: 100%;
}

.for-sale-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 4px 10px;
    background: rgba(46, 204, 113, 0.1);
    color: #2ecc71;
    border-radius: 12px;
    font-size: 0.75rem;
    font-weight: 600;
    white-space: nowrap;
    border: 1px solid rgba(46, 204, 113, 0.2);
    transition: all 0.2s ease;
}

.for-sale-badge:hover {
    background: rgba(46, 204, 113, 0.15);
    border-color: rgba(46, 204, 113, 0.3);
}

.for-sale-badge i {
    font-size: 0.7rem;
}

.track-card .track-title:hover,
.track-info .track-title:hover {
    color: #667eea;
    text-decoration: none;
    transform: translateX(2px);
}

.track-card .track-artist,
.track-info .track-artist {
    color: #4a5568 !important;
    text-decoration: none;
    font-size: 1rem;
    font-weight: 600;
    transition: all 0.3s ease;
    display: flex;
    align-items: center;
    gap: 6px;
    margin-top: 0;
    letter-spacing: 0.01em;
}

.track-card .track-artist::before,
.track-info .track-artist::before {
    content: 'by';
    font-size: 0.85rem;
    font-weight: 500;
    color: #718096 !important;
    opacity: 1;
}

.track-card .track-artist span,
.track-info .track-artist span {
    color: #4a5568 !important;
}

.track-card .track-artist:hover,
.track-info .track-artist:hover {
    color: #667eea;
    transform: translateX(3px);
}

.track-card .track-artist:hover::before,
.track-info .track-artist:hover::before {
    color: #a5b4fc;
    opacity: 1;
}

.track-genre {
    margin-top: 6px;
    display: flex;
    gap: 0.5rem;
    flex-wrap: wrap;
    margin-bottom: 6px;
}

.genre-tag-link {
    background: rgba(102, 126, 234, 0.15);
    color: #a5b4fc;
    padding: 6px 12px;
    text-decoration: none;
    border-radius: 12px;
    font-size: 0.85rem;
    font-weight: 600;
    border: 1px solid rgba(102, 126, 234, 0.2);
    display: inline-block;
    transition: all 0.2s ease;
    text-transform: capitalize;
    letter-spacing: 0.3px;
}

.genre-tag-link:hover {
    background: rgba(102, 126, 234, 0.25);
    color: #8b9aff;
    border-color: rgba(102, 126, 234, 0.4);
    transform: translateY(-1px);
}

.track-date {
    display: flex;
    align-items: center;
    gap: 6px;
    color: #999;
    font-size: 0.8rem;
    margin-top: 6px;
    font-weight: 400;
}

.track-date i {
    font-size: 0.75rem;
    opacity: 0.7;
}

.track-stats {
    display: flex;
    flex-wrap: wrap;
    padding: 12px 20px;
    border-top: 1px solid #f0f0f0;
    gap: 8px;
    background: #fafafa;
}

.stat-btn {
    flex: 0 0 auto;
    min-width: 40px;
    padding: 10px;
    border: none;
    background: transparent;
    color: #666;
    cursor: pointer;
    border-radius: 10px;
    transition: all 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55);
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    font-size: 0.85rem;
    font-weight: 600;
    white-space: nowrap;
}

.stat-btn:hover {
    background: linear-gradient(135deg, #667eea15, #764ba215);
    color: #667eea;
    transform: translateY(-2px);
}

.stat-btn.liked {
    color: #e74c3c;
    background: rgba(231, 76, 60, 0.1);
}

.stat-btn.following {
    color: #667eea;
    background: rgba(102, 126, 234, 0.1);
}

.stat-btn.variations-btn {
    color: #764ba2;
}

.stat-btn.variations-btn:hover {
    background: rgba(118, 75, 162, 0.1);
    color: #764ba2;
}

.track-cart-section {
    padding: 12px 20px;
    border-top: 1px solid #f0f0f0;
    background: white;
    display: flex;
    align-items: center;
    gap: 12px;
}

.add-to-cart-btn {
    width: 100%;
    padding: 12px 20px;
    border: none;
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    color: white;
    border-radius: 10px;
    cursor: pointer;
    font-size: 0.9rem;
    font-weight: 600;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    transition: all 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55);
    box-shadow: 0 4px 15px rgba(102, 126, 234, 0.2);
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

.add-to-cart-btn:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4);
    background: linear-gradient(135deg, #5a67d8 0%, #6b46c1 100%);
}

.add-to-cart-btn:active {
    transform: translateY(0);
}

.add-to-cart-btn i {
    font-size: 1rem;
}

.add-to-cart-btn .cart-price {
    margin-left: auto;
    font-weight: 700;
    opacity: 0.95;
}

.track-cart-section .add-to-cart-btn {
    flex: 1;
}

.add-to-cart-btn.added {
    background: linear-gradient(135deg, #48bb78 0%, #38a169 100%);
    box-shadow: 0 4px 15px rgba(72, 187, 120, 0.3);
}

.add-to-cart-btn.added:hover {
    background: linear-gradient(135deg, #38a169 0%, #2f855a 100%);
    box-shadow: 0 6px 20px rgba(72, 187, 120, 0.4);
}

.wishlist-inline-btn {
    margin-left: 12px;
    width: 48px;
    height: 48px;
    border-radius: 12px;
    border: 1px solid rgba(255, 255, 255, 0.25);
    background: rgba(255, 255, 255, 0.08);
    color: #ff7aa2;
    font-size: 1.2rem;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: all 0.3s ease;
}

.wishlist-inline-btn:hover {
    background: rgba(255, 255, 255, 0.15);
    border-color: rgba(255, 255, 255, 0.4);
}

.wishlist-inline-btn.active {
    background: rgba(255, 99, 132, 0.2);
    border-color: rgba(255, 99, 132, 0.4);
    color: #ff6384;
}

.variations-container {
    padding: 15px 20px;
    background: #f8f9fa;
    border-top: 1px solid #e9ecef;
}

.variations-header {
    font-weight: 600;
    color: #333;
    margin-bottom: 12px;
    font-size: 0.9rem;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.variations-grid {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.variation-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 12px;
    background: white;
    border-radius: 8px;
    border: 1px solid #e9ecef;
    transition: all 0.2s;
}

.variation-item:hover {
    background: #f8f9fa;
    border-color: #667eea;
}

.variation-info {
    display: flex;
    flex-direction: column;
    gap: 4px;
    flex: 1;
}

.variation-title {
    font-size: 0.9rem;
    font-weight: 500;
    color: #333;
}

.variation-duration {
    font-size: 0.75rem;
    color: #666;
}

.variation-play-btn {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    border: none;
    background: #667eea;
    color: white;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.2s;
    font-size: 0.9rem;
}

.variation-play-btn:hover {
    background: #764ba2;
    transform: scale(1.1);
}

.empty-state {
    text-align: center;
    padding: 100px 20px;
    color: white;
}

.empty-state i {
    font-size: 5rem;
    opacity: 0.6;
    margin-bottom: 25px;
    animation: float 3s ease-in-out infinite;
}

@keyframes float {
    0%, 100% { transform: translateY(0px); }
    50% { transform: translateY(-20px); }
}

.empty-state h2 {
    margin: 0 0 15px 0;
    font-size: 2rem;
    font-weight: 700;
}

.pagination {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 25px;
    margin-top: 60px;
    padding: 30px 20px;
}

.pagination-btn {
    padding: 12px 25px;
    background: rgba(255, 255, 255, 0.15);
    backdrop-filter: blur(10px);
    color: white;
    text-decoration: none;
    border-radius: 12px;
    transition: all 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55);
    display: flex;
    align-items: center;
    gap: 10px;
    font-weight: 600;
    border: 1px solid rgba(255, 255, 255, 0.2);
}

.pagination-btn:hover {
    background: rgba(255, 255, 255, 0.25);
    transform: translateY(-3px);
    box-shadow: 0 10px 25px rgba(0,0,0,0.2);
}

.pagination-info {
    color: white;
    font-weight: 700;
    font-size: 1.1rem;
    text-shadow: 0 2px 10px rgba(0,0,0,0.2);
}

@media (max-width: 768px) {
    .track-title-row {
        min-height: auto !important;
        margin-bottom: 8px !important;
        gap: 8px !important;
        align-items: flex-start !important;
        flex-wrap: nowrap !important;
    }
    
    .track-title-wrapper {
        flex: 1 !important;
        min-width: 0 !important;
        gap: 2px !important;
        display: flex !important;
        flex-direction: column !important;
    }
    
    .track-card .track-title,
    .track-info .track-title {
        font-size: 1.1rem !important;
        line-height: 1.3 !important;
        -webkit-line-clamp: 2 !important;
        margin-bottom: 0 !important;
        flex: none !important;
        width: 100% !important;
    }
    
    .track-card .track-artist,
    .track-info .track-artist {
        font-size: 0.85rem !important;
        margin-top: 0 !important;
        line-height: 1.2 !important;
        display: flex !important;
        align-items: center !important;
    }
    
    .track-card .track-artist::before,
    .track-info .track-artist::before {
        font-size: 0.7rem !important;
    }
    
    .for-sale-badge {
        flex-shrink: 0 !important;
        font-size: 0.7rem !important;
        padding: 3px 8px !important;
        margin-top: 0 !important;
        align-self: flex-start !important;
    }
    
    .for-sale-badge i {
        font-size: 0.65rem !important;
    }
    
    .hero-header {
        flex-direction: column;
        align-items: center;
        text-align: center;
    }
    
    .hero-title-section {
        width: 100%;
        min-width: auto;
    }
    
    .share-community-btn {
        width: 100%;
        max-width: 300px;
        justify-content: center;
        padding: 18px 32px;
        font-size: 1.1rem;
    }
    
    .tracks-grid {
        grid-template-columns: 1fr !important;
        gap: 20px;
    }
    
    .track-card {
        width: 100%;
        max-width: 100%;
        box-sizing: border-box;
    }
    
    .community-hero h1 {
        font-size: 2.2rem;
    }
    
    .quick-stats {
        gap: 15px;
    }
    
    .stat-item {
        padding: 15px 20px;
    }
    
    .stat-number {
        font-size: 1.8rem;
    }
    
    .filters-row {
        gap: 15px;
    }
    
    .genre-tag-link {
        font-size: 0.8rem;
        padding: 5px 10px;
    }
}

@media (max-width: 480px) {
    .hero-header {
        padding: 1rem;
    }
    
    .community-hero h1 {
        font-size: 1.8rem;
    }
    
    .tracks-grid {
        grid-template-columns: 1fr !important;
        gap: 15px;
    }
    
    .track-card {
        width: 100%;
        max-width: 100%;
        box-sizing: border-box;
    }
    
    .track-info {
        padding: 14px 16px 16px;
    }
    
    .track-title-row {
        min-height: auto !important;
        margin-bottom: 8px !important;
        gap: 8px !important;
        align-items: flex-start !important;
        flex-wrap: nowrap !important;
    }
    
    .track-title-wrapper {
        flex: 1 !important;
        min-width: 0 !important;
        gap: 2px !important;
        display: flex !important;
        flex-direction: column !important;
    }
    
    .track-card .track-title,
    .track-info .track-title {
        font-size: 1.1rem !important;
        line-height: 1.3 !important;
        -webkit-line-clamp: 2 !important;
        margin-bottom: 0 !important;
        flex: none !important;
        width: 100% !important;
    }
    
    .track-card .track-artist,
    .track-info .track-artist {
        font-size: 0.85rem !important;
        margin-top: 0 !important;
        line-height: 1.2 !important;
        display: flex !important;
        align-items: center !important;
    }
    
    .track-card .track-artist::before,
    .track-info .track-artist::before {
        font-size: 0.7rem !important;
    }
    
    .for-sale-badge {
        flex-shrink: 0 !important;
        font-size: 0.7rem !important;
        padding: 3px 8px !important;
        margin-top: 0 !important;
        align-self: flex-start !important;
    }
    
    .for-sale-badge i {
        font-size: 0.65rem !important;
    }
    
    .quick-stats {
        gap: 10px;
    }
    
    .stat-item {
        padding: 12px 15px;
    }
    
    .stat-number {
        font-size: 1.5rem;
    }
    
    .filters-row {
        flex-direction: column;
        gap: 10px;
    }
    
    .track-genre {
        margin-top: 4px;
    }
    
    .genre-tag-link {
        font-size: 0.75rem;
        padding: 5px 10px;
        max-width: 100%;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        display: inline-block;
    }
    
    .track-info {
        padding: 16px 18px 18px;
    }
    
    .track-title-row {
        min-height: 44px;
        margin-bottom: 8px;
    }
    
    .track-card .track-title,
    .track-info .track-title {
        font-size: 1.2rem;
        line-height: 1.35;
        -webkit-line-clamp: 2;
    }
    
    .track-card .track-artist,
    .track-info .track-artist {
        font-size: 0.95rem;
    }
    
    .track-artist::before {
        font-size: 0.8rem;
    }
}

/* Track Ranking Display on Music Cards */
.card-track-ranking {
    margin-top: 0.75rem;
    padding: 0.75rem;
    background: linear-gradient(135deg, rgba(251, 191, 36, 0.08) 0%, rgba(245, 158, 11, 0.08) 100%);
    border-radius: 10px;
    border: 1px solid rgba(251, 191, 36, 0.2);
    transition: all 0.3s ease;
}

.card-track-ranking:hover {
    background: linear-gradient(135deg, rgba(251, 191, 36, 0.15) 0%, rgba(245, 158, 11, 0.15) 100%);
    border-color: rgba(251, 191, 36, 0.4);
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(251, 191, 36, 0.2);
}

.ranking-badge-compact {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 0.5rem;
}

.ranking-badge-compact i {
    font-size: 1rem;
    color: #fbbf24;
}

.ranking-label-compact {
    font-size: 0.7rem;
    color: #a0aec0;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    font-weight: 600;
}

.ranking-value-compact {
    font-size: 1.1rem;
    font-weight: 700;
    color: #fbbf24;
    line-height: 1;
}

.ranking-out-of-compact {
    font-size: 0.75rem;
    color: #a0aec0;
}

.ranking-percentile-compact {
    margin-bottom: 0.5rem;
}

.percentile-badge-compact {
    display: inline-block;
    padding: 0.25rem 0.6rem;
    background: linear-gradient(135deg, #fbbf24, #f59e0b);
    color: #000000;
    border-radius: 12px;
    font-weight: 600;
    font-size: 0.7rem;
}

.ranking-details-compact {
    display: flex;
    gap: 0.5rem;
    flex-wrap: wrap;
}

.ranking-detail-item {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.3rem 0.6rem;
    background: rgba(0, 0, 0, 0.2);
    border-radius: 8px;
    font-size: 0.7rem;
    color: #ffffff;
    border-left: 2px solid #fbbf24;
}

.ranking-detail-item i {
    font-size: 0.7rem;
    color: #fbbf24;
}

/* Voting buttons on track cards */
.vote-btn-card {
    background: rgba(255, 255, 255, 0.1);
    border: 2px solid rgba(255, 255, 255, 0.2);
    border-radius: 6px;
    padding: 0.4rem 0.6rem;
    color: #a0aec0;
    cursor: pointer;
    transition: all 0.3s ease;
    font-size: 0.9rem;
    display: flex;
    align-items: center;
    justify-content: center;
    min-width: 32px;
    min-height: 32px;
    -webkit-tap-highlight-color: transparent;
}

.vote-btn-card:hover {
    background: rgba(255, 255, 255, 0.15);
    border-color: rgba(255, 255, 255, 0.3);
    transform: translateY(-1px);
}

.vote-btn-card.vote-up-card.active {
    background: rgba(34, 197, 94, 0.2);
    border-color: #22c55e;
    color: #22c55e;
}

.vote-btn-card.vote-down-card.active {
    background: rgba(239, 68, 68, 0.2);
    border-color: #ef4444;
    color: #ef4444;
}

.vote-count-card {
    font-size: 0.9rem;
    font-weight: 700;
    color: #ffffff;
    padding: 0.2rem 0;
    min-width: 30px;
    text-align: center;
    line-height: 1;
}

.voting-section-card {
    flex-shrink: 0;
    display: flex !important;
}

@media (max-width: 768px) {
    .card-track-ranking {
        padding: 1rem !important;
        margin-top: 1rem !important;
        box-sizing: border-box !important;
        width: 100% !important;
        max-width: 100% !important;
        overflow: hidden !important;
    }
    
    .card-track-ranking > div:first-child {
        flex-direction: column !important;
        gap: 1rem !important;
    }
    
    .card-track-ranking > div:first-child > div:first-child {
        width: 100% !important;
    }
    
    .card-track-ranking > div:first-child > div:last-child.voting-section-card {
        border-left: none !important;
        border-top: 1px solid rgba(251, 191, 36, 0.3) !important;
        padding-left: 0 !important;
        padding-top: 1rem !important;
        padding-bottom: 0.5rem !important;
        width: 100% !important;
        align-items: center !important;
        justify-content: center !important;
        flex-direction: row !important;
        gap: 1.5rem !important;
    }
    
    .ranking-badge-compact {
        gap: 0.6rem !important;
        margin-bottom: 0.75rem !important;
        flex-wrap: wrap !important;
        align-items: center !important;
        width: 100% !important;
    }
    
    .ranking-badge-compact > * {
        flex-shrink: 0 !important;
    }
    
    .ranking-badge-compact i {
        font-size: 1.1rem !important;
    }
    
    .ranking-label-compact {
        font-size: 0.75rem !important;
    }
    
    .ranking-value-compact {
        font-size: 1.3rem !important;
    }
    
    .ranking-out-of-compact {
        font-size: 0.85rem !important;
    }
    
    .ranking-percentile-compact {
        margin-bottom: 0.75rem !important;
    }
    
    .percentile-badge-compact {
        font-size: 0.75rem !important;
        padding: 0.35rem 0.75rem !important;
    }
    
    .ranking-details-compact {
        gap: 0.4rem !important;
        flex-wrap: wrap !important;
        width: 100% !important;
    }
    
    .ranking-detail-item {
        font-size: 0.75rem !important;
        padding: 0.4rem 0.7rem !important;
        gap: 0.4rem !important;
        flex-shrink: 0 !important;
        white-space: nowrap !important;
    }
    
    .ranking-detail-item span {
        overflow: hidden !important;
        text-overflow: ellipsis !important;
    }
    
    .ranking-detail-item i {
        font-size: 0.75rem !important;
    }
    
    .vote-btn-card {
        min-width: 44px !important;
        min-height: 44px !important;
        padding: 0.5rem 0.75rem !important;
        font-size: 1rem !important;
    }
    
    .vote-count-card {
        font-size: 1rem !important;
        min-width: 40px !important;
        padding: 0.3rem 0 !important;
    }
    
    .card-track-ranking > div:last-child {
        font-size: 0.75rem !important;
        margin-top: 0.75rem !important;
        padding-top: 0.75rem !important;
    }
}

@media (max-width: 480px) {
    .card-track-ranking {
        padding: 0.875rem !important;
    }
    
    .ranking-badge-compact {
        gap: 0.5rem !important;
        margin-bottom: 0.6rem !important;
        align-items: center !important;
        width: 100% !important;
    }
    
    .ranking-badge-compact > * {
        flex-shrink: 0 !important;
    }
    
    .ranking-value-compact {
        font-size: 1.2rem !important;
    }
    
    .ranking-out-of-compact {
        font-size: 0.8rem !important;
    }
    
    .ranking-details-compact {
        gap: 0.35rem !important;
        width: 100% !important;
    }
    
    .ranking-detail-item {
        font-size: 0.7rem !important;
        padding: 0.35rem 0.6rem !important;
        flex-shrink: 0 !important;
        white-space: nowrap !important;
    }
    
    .ranking-detail-item span {
        overflow: hidden !important;
        text-overflow: ellipsis !important;
    }
    
    .card-track-ranking > div:first-child > div:last-child.voting-section-card {
        gap: 1.25rem !important;
        padding-top: 0.875rem !important;
    }
    
    .vote-btn-card {
        min-width: 40px !important;
        min-height: 40px !important;
        padding: 0.45rem 0.65rem !important;
        font-size: 0.95rem !important;
    }
    
    .vote-count-card {
        font-size: 0.95rem !important;
    }
}

/* Profile Edit Modal (for ranking breakdown modal) */
.profile-edit-modal {
    position: fixed;
    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: 10001;
    animation: fadeIn 0.3s ease;
}

.modal-content {
    background: #2a2a2a;
    border-radius: 20px;
    width: 90%;
    max-width: 600px;
    max-height: 80vh;
    overflow: hidden;
    border: 2px solid #667eea;
    animation: slideUp 0.3s ease;
}

.modal-header {
    background: #3a3a3a;
    padding: 1.5rem 2rem;
    border-bottom: 1px solid #4a4a4a;
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.modal-header h3 {
    color: white;
    margin: 0;
    font-size: 1.5rem;
    font-weight: 600;
}

.close-btn {
    background: none;
    border: none;
    color: #a0a0a0;
    font-size: 2rem;
    cursor: pointer;
    padding: 0;
    width: 30px;
    height: 30px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    transition: all 0.3s ease;
}

.close-btn:hover {
    background: rgba(255, 255, 255, 0.1);
    color: white;
}

.modal-body {
    padding: 2rem;
    color: #e0e0e0;
    overflow-y: auto;
}

.modal-footer {
    background: #3a3a3a;
    padding: 1.5rem 2rem;
    border-top: 1px solid #4a4a4a;
    display: flex;
    gap: 1rem;
    justify-content: flex-end;
}

.btn-primary {
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    color: white;
    border: none;
    padding: 0.75rem 1.5rem;
    border-radius: 25px;
    font-size: 1rem;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.3s ease;
}

.btn-primary:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
}

.btn-secondary {
    background: transparent;
    color: #a0a0a0;
    border: 1px solid #4a4a4a;
    padding: 0.75rem 1.5rem;
    border-radius: 25px;
    font-size: 1rem;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.3s ease;
}

.btn-secondary:hover {
    background: rgba(255, 255, 255, 0.1);
    color: white;
}

/* Rating Modal Styles */
.rating-input-section {
    text-align: center;
    margin-bottom: 1.5rem;
}

.stars-input {
    display: flex;
    justify-content: center;
    gap: 0.5rem;
    margin-bottom: 1rem;
}

.stars-input i {
    font-size: 2rem;
    color: #fbbf24;
    cursor: pointer;
    transition: transform 0.2s ease, color 0.2s ease;
}

.stars-input i:hover {
    transform: scale(1.2);
}

.stars-input i.fas {
    color: #fbbf24;
}

.stars-input i.far {
    color: #4a4a4a;
}

.rating-feedback {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.25rem;
}

.rating-feedback .rating-value {
    font-size: 1.5rem;
    font-weight: 700;
    color: #fbbf24;
}

.rating-feedback .rating-label {
    font-size: 0.9rem;
    color: #a0a0a0;
}

.rating-comment {
    margin-top: 1rem;
}

.rating-comment label {
    display: block;
    margin-bottom: 0.5rem;
    color: #e0e0e0;
    font-weight: 500;
}

.rating-comment textarea {
    width: 100%;
    background: #3a3a3a;
    border: 1px solid #4a4a4a;
    border-radius: 10px;
    padding: 1rem;
    color: #e0e0e0;
    font-size: 1rem;
    resize: vertical;
    min-height: 100px;
}

.rating-comment textarea:focus {
    outline: none;
    border-color: #667eea;
}

.rating-comment textarea::placeholder {
    color: #6a6a6a;
}

/* Animations */
@keyframes fadeIn {
    from { opacity: 0; }
    to { opacity: 1; }
}

@keyframes slideUp {
    from { 
        opacity: 0;
        transform: translateY(30px);
    }
    to { 
        opacity: 1;
        transform: translateY(0);
    }
}

/* Mobile optimizations for ranking modal */
@media (max-width: 768px) {
    .profile-edit-modal .modal-content {
        width: 95% !important;
        max-height: 90vh !important;
        border-radius: 15px !important;
    }
    
    .profile-edit-modal .modal-header {
        padding: 1rem !important;
    }
    
    .profile-edit-modal .modal-header h3 {
        font-size: 1.2rem !important;
        line-height: 1.3;
    }
    
    .profile-edit-modal .modal-body {
        padding: 1rem !important;
        font-size: 0.9rem !important;
    }
    
    .profile-edit-modal .modal-footer {
        padding: 1rem !important;
    }
    
    .profile-edit-modal .close-btn {
        font-size: 1.5rem !important;
        width: 24px !important;
        height: 24px !important;
    }
    
    .profile-edit-modal .modal-body h4 {
        font-size: 1rem !important;
    }
}
</style>

<script>
// Ranking Modal Translations
window.rankingTranslations = {
    title: '<?= addslashes(t('track.rankings.breakdown.title')) ?>',
    overall_ranking: '<?= addslashes(t('track.rankings.breakdown.overall_ranking')) ?>',
    rank: '<?= addslashes(t('track.rankings.breakdown.rank')) ?>',
    out_of: '<?= addslashes(t('track.rankings.breakdown.out_of')) ?>',
    tracks: '<?= addslashes(t('track.rankings.breakdown.tracks')) ?>',
    percentile: '<?= addslashes(t('track.rankings.breakdown.percentile')) ?>',
    score_calculation: '<?= addslashes(t('track.rankings.breakdown.score_calculation')) ?>',
    plays: '<?= addslashes(t('track.rankings.breakdown.plays')) ?>',
    likes: '<?= addslashes(t('track.rankings.breakdown.likes')) ?>',
    rating: '<?= addslashes(t('track.rankings.breakdown.rating')) ?>',
    track_votes: '<?= addslashes(t('track.rankings.breakdown.track_votes')) ?>',
    track_votes_label: '<?= addslashes(t('track.rankings.breakdown.track_votes_label')) ?>',
    track_rating: '<?= addslashes(t('track.rankings.breakdown.track_rating')) ?>',
    track_ratings: '<?= addslashes(t('track.rankings.breakdown.track_ratings')) ?>',
    total_score: '<?= addslashes(t('track.rankings.breakdown.total_score')) ?>',
    individual_rankings: '<?= addslashes(t('track.rankings.breakdown.individual_rankings')) ?>',
    formula: '<?= addslashes(t('track.rankings.breakdown.formula')) ?>',
    formula_text: '<?= addslashes(t('track.rankings.breakdown.formula_text')) ?>',
    weight: '<?= addslashes(t('track.rankings.breakdown.weight')) ?>',
    avg_rating: '<?= addslashes(t('track.rankings.breakdown.avg_rating')) ?>',
    ratings: '<?= addslashes(t('track.rankings.breakdown.ratings') ?? 'ratings') ?>',
    close: '<?= addslashes(t('track.rankings.breakdown.close') ?? 'Close') ?>',
    by_plays: '<?= addslashes(t('track.rankings.by_plays')) ?>',
    by_likes: '<?= addslashes(t('track.rankings.by_likes')) ?>',
    by_rating: '<?= addslashes(t('track.rankings.by_rating')) ?>',
    of: '<?= addslashes(t('track.rankings.of')) ?>',
    track: '<?= addslashes(t('track.rankings.breakdown.track') ?? 'Track') ?>',
    showing: '<?= addslashes(t('track.rankings.breakdown.showing') ?? 'Showing') ?>',
    no_tracks: '<?= addslashes(t('track.rankings.breakdown.no_tracks') ?? 'No tracks found') ?>',
    view_all_rankings: '<?= addslashes(t('track.rankings.breakdown.view_all_rankings')) ?>',
    all_rankings_title: '<?= addslashes(t('track.rankings.breakdown.all_rankings_title')) ?>',
    loading_rankings: '<?= addslashes(t('track.rankings.breakdown.loading_rankings')) ?>',
    ratings_for: '<?= addslashes(t('artist_profile.ratings_for')) ?>',
    loading_ratings: '<?= addslashes(t('artist_profile.loading_ratings')) ?>',
    no_comment: '<?= addslashes(t('artist_profile.no_comment')) ?>',
    rate_this_track: '<?= addslashes(t('artist_profile.rate_this_track')) ?>'
};

function updateFilters() {
    const sort = document.getElementById('sortSelect').value;
    const time = document.getElementById('timeSelect').value;
    const genre = document.getElementById('genreSelect').value;
    const search = document.getElementById('searchInput').value.trim();
    
    // Build URL for history
    let url = `?sort=${sort}&time=${time}&genre=${genre}&page=1`;
    if (search) {
        url += `&search=${encodeURIComponent(search)}`;
    }
    
    // Update URL without reload
    window.history.pushState({}, '', url);
    
    // Show loading state
    const tracksGrid = document.getElementById('tracksGrid');
    const loader = document.getElementById('infiniteScrollLoader');
    const endOfResults = document.getElementById('endOfResults');
    
    if (tracksGrid) {
        tracksGrid.innerHTML = '<div class="loading-tracks" style="text-align: center; padding: 2rem;"><i class="fas fa-spinner fa-spin"></i> Loading tracks...</div>';
    }
    if (loader) loader.style.display = 'none';
    if (endOfResults) endOfResults.style.display = 'none';
    
    // Fetch filtered tracks via AJAX
    const queryParams = new URLSearchParams({
        page: 1,
        per_page: 24,
        sort: sort,
        time: time,
        genre: genre,
        ...(search ? { search: search } : {})
    });
    
    fetch(`/api/get_community_fixed_tracks.php?${queryParams}`)
        .then(response => {
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }
            return response.json();
        })
        .then(data => {
            if (data.success && data.tracks && data.tracks.length > 0) {
                // Clear existing tracks
                if (tracksGrid) {
                    tracksGrid.innerHTML = '';
                }
                
                // Render new tracks using exposed function
                const fragment = document.createDocumentFragment();
                data.tracks.forEach(track => {
                    if (typeof window.createTrackCard === 'function') {
                        const trackCard = window.createTrackCard(track);
                        fragment.appendChild(trackCard);
                    }
                });
                
                if (tracksGrid) {
                    tracksGrid.appendChild(fragment);
                }
                
                // Re-attach play button listeners
                if (typeof window.attachPlayButtonListeners === 'function') {
                    window.attachPlayButtonListeners();
                }
                
                // Update infinite scroll state
                if (tracksGrid) {
                    tracksGrid.setAttribute('data-current-page', '1');
                    tracksGrid.setAttribute('data-has-more', data.pagination.has_more ? 'true' : 'false');
                }
                
                // Dispatch event to notify infinite scroll handler of filter change
                document.dispatchEvent(new CustomEvent('filtersUpdated', {
                    detail: {
                        currentPage: 1,
                        hasMore: data.pagination.has_more,
                        totalTracks: data.pagination.total_tracks
                    }
                }));
                
                // Update playlist if global player is active
                if (window.waitForGlobalPlayer) {
                    window.waitForGlobalPlayer(function() {
                        if (window.enhancedGlobalPlayer && window._communityPlaylistType === 'community_fixed') {
                            const buildFn = window.buildCommunityPlaylist;
                            const updatedPlaylist = buildFn ? buildFn() : [];
                            if (updatedPlaylist.length > 0 && typeof window.enhancedGlobalPlayer.loadPagePlaylist === 'function') {
                                window.enhancedGlobalPlayer.loadPagePlaylist(updatedPlaylist, 'community_fixed', 0);
                                console.log('đŸŽĩ Updated playlist after filter change, total:', updatedPlaylist.length);
                            }
                        }
                    });
                }
                
                // Scroll to top of tracks smoothly
                if (tracksGrid) {
                    tracksGrid.scrollIntoView({ behavior: 'smooth', block: 'start' });
                }
            } else {
                // No tracks found
                if (tracksGrid) {
                    tracksGrid.innerHTML = '<div class="no-tracks" style="text-align: center; padding: 3rem; color: #9ca3af;"><i class="fas fa-music"></i><br>No tracks found matching your filters.</div>';
                }
            }
        })
        .catch(error => {
            console.error('Error loading filtered tracks:', error);
            if (tracksGrid) {
                tracksGrid.innerHTML = '<div class="error" style="text-align: center; padding: 3rem; color: #ef4444;"><i class="fas fa-exclamation-triangle"></i><br>Error loading tracks. Please try again.</div>';
            }
            if (typeof showNotification === 'function') {
                showNotification('Error loading tracks. Please try again.', 'error');
            } else {
                alert('Error loading tracks. Please try again.');
            }
        });
}

// NOTE: playTrack function is now defined AFTER footer.php loads global_player.php (see bottom of file)
// This ensures the global player is loaded before we try to use it

// Record track play count
function recordTrackPlay(trackId) {
    // Only record if not already recorded recently
    const lastPlayed = sessionStorage.getItem(`played_${trackId}`);
    const now = Date.now();
    
    if (!lastPlayed || (now - parseInt(lastPlayed)) > 30000) { // 30 seconds minimum between plays
        fetch('/api_social.php', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ action: 'play', track_id: trackId })
        })
        .then(response => response.json())
        .then(data => {
            if (data.success) {
                sessionStorage.setItem(`played_${trackId}`, now.toString());
                console.log('đŸŽĩ Play count recorded for track:', trackId);
            }
        })
        .catch(error => {
            console.warn('đŸŽĩ Play count error:', error);
        });
    }
}

function toggleLike(trackId, button) {
    fetch('/api/toggle_like.php', {
        method: 'POST',
        headers: {'Content-Type': 'application/json'},
        credentials: 'include',
        body: JSON.stringify({track_id: trackId})
    })
    .then(response => response.json())
    .then(data => {
        if (!data.success) {
            if (typeof showNotification === 'function') {
                showNotification(data.error || 'Unable to like this track right now.', 'error');
            } else {
                alert(data.error || 'Unable to like this track right now.');
            }
            return;
        }
        button.classList.toggle('liked', !!data.liked);
        const countSpan = button.querySelector('span');
        if (countSpan) {
            countSpan.textContent = (data.like_count || 0).toLocaleString();
        }
    })
    .catch(error => {
        console.error('toggleLike error', error);
        if (typeof showNotification === 'function') {
            showNotification('Network error while liking track. Please try again.', 'error');
        } else {
            alert('Network error while liking track. Please try again.');
        }
    });
}
    
function toggleFollow(userId, button) {
    const isLoggedIn = <?= isset($_SESSION['user_id']) && $_SESSION['user_id'] ? 'true' : 'false' ?>;
    
    if (!isLoggedIn) {
        if (typeof showNotification === 'function') {
            showNotification(translations.login_required_follow, 'error');
        } else {
            alert(translations.login_required_follow);
        }
        setTimeout(() => {
            window.location.href = '/auth/login.php';
        }, 2000);
        return;
    }
    
    const isFollowing = button.classList.contains('following');
    const icon = button.querySelector('i');
    
    // Disable button during request
    button.disabled = true;
    const originalHTML = button.innerHTML;
    if (icon) {
        icon.className = 'fas fa-spinner fa-spin';
    }
    
    fetch('/api_social.php', {
        method: 'POST',
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify({action: 'follow', user_id: userId})
    })
    .then(response => response.json())
    .then(data => {
        if (data.success) {
            const newFollowingState = data.action === 'followed';
            button.classList.toggle('following', newFollowingState);
            
            // Update icon
            if (icon) {
                icon.className = newFollowingState ? 'fas fa-user-check' : 'fas fa-user-plus';
            }
            
            // Update title
            button.title = newFollowingState ? translations.unfollow_artist : translations.follow_artist;
        } else {
            // Restore button on error
            button.innerHTML = originalHTML;
            if (typeof showNotification === 'function') {
                showNotification(data.message || 'Failed to update follow status', 'error');
            } else {
                alert(data.message || 'Failed to update follow status');
            }
        }
    })
    .catch(error => {
        console.error('Follow error:', error);
        button.innerHTML = originalHTML;
        if (typeof showNotification === 'function') {
            showNotification('Failed to update follow status. Please try again.', 'error');
        } else {
            alert('Failed to update follow status. Please try again.');
        }
    })
    .finally(() => {
        button.disabled = false;
    });
}

// Voting functionality for track cards
function voteTrackFromCard(trackId, voteType, button) {
    const isLoggedIn = <?= isset($_SESSION['user_id']) && $_SESSION['user_id'] ? 'true' : 'false' ?>;
    
    if (!isLoggedIn) {
        if (typeof showNotification === 'function') {
            showNotification(translations.login_to_vote, 'error');
        } else {
            alert(translations.login_to_vote);
        }
        setTimeout(() => {
            window.location.href = '/auth/login.php';
        }, 2000);
        return;
    }
    
    console.log('đŸŽĩ Voting on track from card:', trackId, 'vote type:', voteType);
    
    // Disable buttons during request
    const card = button.closest('.card-track-ranking');
    const upBtn = card ? card.querySelector('.vote-up-card') : null;
    const downBtn = card ? card.querySelector('.vote-down-card') : null;
    const voteCountElement = card ? card.querySelector('.vote-count-card') : null;
    
    if (upBtn) upBtn.style.pointerEvents = 'none';
    if (downBtn) downBtn.style.pointerEvents = 'none';
    
    fetch('/api_social.php', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        },
        credentials: 'include',
        body: JSON.stringify({
            action: 'vote_track',
            track_id: trackId,
            vote_type: voteType
        })
    })
    .then(response => {
        // Check if response is OK
        if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
        }
        // Check if response is JSON
        const contentType = response.headers.get('content-type');
        if (!contentType || !contentType.includes('application/json')) {
            return response.text().then(text => {
                throw new Error('Invalid response format: ' + text.substring(0, 100));
            });
        }
        return response.json();
    })
    .then(data => {
        if (data.success) {
            // Update vote buttons state
            if (upBtn) upBtn.classList.remove('active');
            if (downBtn) downBtn.classList.remove('active');
            
            if (data.user_vote === 'up' && upBtn) {
                upBtn.classList.add('active');
            } else if (data.user_vote === 'down' && downBtn) {
                downBtn.classList.add('active');
            }
            
            // Update vote count display
            if (voteCountElement) {
                const newCount = data.vote_count !== undefined ? parseInt(data.vote_count) || 0 : 0;
                voteCountElement.textContent = newCount.toLocaleString();
                console.log('✅ Vote count updated to:', newCount, 'for track', trackId, 'Action:', data.action);
            } else {
                console.warn('âš ī¸ Vote count element not found for track', trackId);
            }
            
            // Refresh ranking modal if it's open for this track
            if (window.currentRankingModalTrackId == trackId) {
                console.log('🔄 Refreshing ranking modal after vote...');
                // Fetch updated track data and refresh modal
                refreshRankingModal(trackId);
            }
        } else {
            const errorMsg = data.message || translations.error_voting;
            console.error('Vote failed:', errorMsg);
            if (typeof showNotification === 'function') {
                showNotification(errorMsg, 'error');
            } else {
                alert(errorMsg);
            }
        }
    })
    .catch(error => {
        console.error('Error voting on track:', error);
        const errorMsg = error.message || translations.error_voting_retry;
        if (typeof showNotification === 'function') {
            showNotification(errorMsg, 'error');
        } else {
            alert(errorMsg);
        }
    })
    .finally(() => {
        // Re-enable buttons
        if (upBtn) upBtn.style.pointerEvents = '';
        if (downBtn) downBtn.style.pointerEvents = '';
    });
}

function handleRankingCardClick(element) {
    console.log('🔍 Ranking card clicked');
    const trackId = element.getAttribute('data-track-id');
    const rankingsJson = element.getAttribute('data-rankings');
    const trackJson = element.getAttribute('data-track');
    
    if (!rankingsJson || !trackJson) {
        console.error('❌ Missing data attributes');
        alert('Ranking data is not available for this track.');
        return;
    }
    
    try {
        const rankings = JSON.parse(rankingsJson);
        const track = JSON.parse(trackJson);
        console.log('📊 Parsed rankings:', rankings);
        console.log('đŸŽĩ Parsed track:', track);
        openTrackRankingModal(trackId, rankings, track);
    } catch (error) {
        console.error('❌ Error parsing JSON:', error);
        alert('Error loading ranking data: ' + error.message);
    }
}

function openTrackRankingModal(trackId, rankings, track) {
    console.log('🔍 openTrackRankingModal called for track:', trackId);
    console.log('📊 Rankings data:', rankings);
    console.log('đŸŽĩ Track data:', track);
    
    if (!rankings || !track) {
        console.error('❌ Missing rankings or track data');
        alert('Ranking data is not available for this track.');
        return;
    }
    
    try {
        showRankingBreakdown(rankings, track);
    } catch (error) {
        console.error('❌ Error opening ranking breakdown:', error);
        alert('Error opening ranking breakdown: ' + error.message);
    }
}

function showRankingBreakdown(rankings, track) {
    console.log('📊 showRankingBreakdown called with:', rankings, track);
    
    if (!rankings || !track) {
        console.error('❌ Missing rankings or track data');
        alert('Missing data to display ranking breakdown.');
        return;
    }
    
    console.log('✅ Data validated, creating modal...');
    
    // Remove any existing modal
    const existingModal = document.getElementById('rankingBreakdownModal');
    if (existingModal) {
        existingModal.remove();
    }
    
    // Store track ID in modal for refresh functionality
    if (track && track.id) {
        window.currentRankingModalTrackId = track.id;
    }
    
    // Detect mobile
    const isMobile = window.innerWidth <= 768;
    const modalMaxWidth = isMobile ? '95%' : '600px';
    const modalMaxHeight = isMobile ? '90vh' : '80vh';
    
    const breakdown = rankings.score_breakdown || {};
    const plays = parseInt(track.play_count) || 0;
    const likes = parseInt(track.like_count) || 0;
    const votes = parseInt(track.vote_count) || 0;
    const avgRating = parseFloat(track.average_rating) || 0;
    const ratingCount = parseInt(track.rating_count) || 0;
    
    const t = window.rankingTranslations || {};
    const modalHTML = `
        <div class="profile-edit-modal" id="rankingBreakdownModal" style="z-index: 10001;">
            <div class="modal-content" style="max-width: ${modalMaxWidth}; max-height: ${modalMaxHeight}; display: flex; flex-direction: column; width: ${modalMaxWidth};">
                <div class="modal-header" style="flex-shrink: 0; padding: ${isMobile ? '1rem' : '1.5rem 2rem'};">
                    <h3 style="font-size: ${isMobile ? '1.2rem' : '1.5rem'}; margin: 0;">📊 ${t.title || 'Ranking Breakdown'}: ${track.title || t.track || 'Track'}</h3>
                    <button class="close-btn" onclick="closeRankingBreakdownModal()" style="font-size: ${isMobile ? '1.5rem' : '2rem'}; width: ${isMobile ? '24px' : '30px'}; height: ${isMobile ? '24px' : '30px'};">&times;</button>
                </div>
                <div class="modal-body" style="overflow-y: auto; flex: 1; padding: ${isMobile ? '1rem' : '2rem'}; -webkit-overflow-scrolling: touch; font-size: ${isMobile ? '0.9rem' : '1rem'};">
                    <div style="margin-bottom: ${isMobile ? '1.5rem' : '2rem'};">
                        <h4 style="color: #667eea; margin-bottom: 1rem; font-size: ${isMobile ? '1rem' : '1.2rem'};">${t.overall_ranking || 'Overall Ranking'}</h4>
                        <div style="background: rgba(0, 0, 0, 0.2); padding: ${isMobile ? '0.75rem' : '1rem'}; border-radius: 8px; margin-bottom: 1rem;">
                            <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.5rem; flex-wrap: wrap; gap: 0.5rem;">
                                <span style="color: #a0aec0; font-size: ${isMobile ? '0.85rem' : '1rem'};">${t.rank || ''}:</span>
                                <span style="font-size: ${isMobile ? '1.2rem' : '1.5rem'}; font-weight: 700; color: #fbbf24;">#${rankings.overall}</span>
                            </div>
                            <div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 0.5rem;">
                                <span style="color: #a0aec0; font-size: ${isMobile ? '0.85rem' : '1rem'};">${t.out_of || 'Out of'}:</span>
                                <span style="color: #ffffff; font-size: ${isMobile ? '0.9rem' : '1rem'};">${rankings.total_tracks} ${t.tracks || 'tracks'}</span>
                            </div>
                            <div style="display: flex; justify-content: space-between; align-items: center; margin-top: 0.5rem; flex-wrap: wrap; gap: 0.5rem;">
                                <span style="color: #a0aec0; font-size: ${isMobile ? '0.85rem' : '1rem'};">${t.percentile || 'Percentile'}:</span>
                                <span style="color: #ffffff; font-size: ${isMobile ? '0.9rem' : '1rem'};">Top ${rankings.overall_percentile}%</span>
                            </div>
                        </div>
                    </div>
                    
                    <div style="margin-bottom: ${isMobile ? '1.5rem' : '2rem'};">
                        <h4 style="color: #667eea; margin-bottom: 1rem; font-size: ${isMobile ? '1rem' : '1.2rem'};">${t.score_calculation || 'Score Calculation'}</h4>
                        <div style="background: rgba(0, 0, 0, 0.2); padding: ${isMobile ? '0.75rem' : '1rem'}; border-radius: 8px;">
                            <div style="margin-bottom: 0.75rem; padding-bottom: 0.75rem; border-bottom: 1px solid rgba(255, 255, 255, 0.1);">
                                <div style="display: flex; justify-content: space-between; margin-bottom: 0.25rem; flex-wrap: wrap; gap: 0.5rem;">
                                    <span style="color: #a0aec0; font-size: ${isMobile ? '0.85rem' : '1rem'};">${t.plays || 'Plays'} (${plays} × 1.0):</span>
                                    <span style="color: #ffffff; font-weight: 600; font-size: ${isMobile ? '0.9rem' : '1rem'};">${breakdown.plays_score || 0}</span>
                                </div>
                                <small style="color: #888; font-size: ${isMobile ? '0.75rem' : '0.85rem'};">${plays} ${t.plays || 'plays'} × ${t.weight || 'weight'} 1.0</small>
                            </div>
                            <div style="margin-bottom: 0.75rem; padding-bottom: 0.75rem; border-bottom: 1px solid rgba(255, 255, 255, 0.1);">
                                <div style="display: flex; justify-content: space-between; margin-bottom: 0.25rem; flex-wrap: wrap; gap: 0.5rem;">
                                    <span style="color: #a0aec0; font-size: ${isMobile ? '0.85rem' : '1rem'};">${t.likes || 'Likes'} (${likes} × 2.0):</span>
                                    <span style="color: #ffffff; font-weight: 600; font-size: ${isMobile ? '0.9rem' : '1rem'};">${breakdown.likes_score || 0}</span>
                                </div>
                                <small style="color: #888; font-size: ${isMobile ? '0.75rem' : '0.85rem'};">${likes} ${t.likes || 'likes'} × ${t.weight || 'weight'} 2.0</small>
                            </div>
                            ${votes !== undefined ? `
                            <div style="margin-bottom: 0.75rem; padding-bottom: 0.75rem; border-bottom: 1px solid rgba(255, 255, 255, 0.1);">
                                <div style="display: flex; justify-content: space-between; margin-bottom: 0.25rem; flex-wrap: wrap; gap: 0.5rem;">
                                    <span style="color: #a0aec0; font-size: ${isMobile ? '0.85rem' : '1rem'};">${t.track_votes || 'Track Votes'} (${votes} × 3.0):</span>
                                    <span style="color: #ffffff; font-weight: 600; font-size: ${isMobile ? '0.9rem' : '1rem'};">${breakdown.votes_score || 0}</span>
                                </div>
                                <small style="color: #888; font-size: ${isMobile ? '0.75rem' : '0.85rem'};">${votes} ${t.track_votes_label || 'track votes'} × ${t.weight || 'weight'} 3.0</small>
                            </div>
                            ` : ''}
                            <div style="margin-bottom: 0.75rem; padding-bottom: 0.75rem; border-bottom: 1px solid rgba(255, 255, 255, 0.1);">
                                <div style="display: flex; justify-content: space-between; margin-bottom: 0.25rem; flex-wrap: wrap; gap: 0.5rem;">
                                    <span style="color: #a0aec0; font-size: ${isMobile ? '0.85rem' : '1rem'};">${t.track_rating || 'Track Rating'} (${(Number(avgRating) || 0).toFixed(1)} × ${(ratingCount || 0)} × 5.0):</span>
                                    <span style="color: #ffffff; font-weight: 600; font-size: ${isMobile ? '0.9rem' : '1rem'};">${breakdown.rating_score || 0}</span>
                                </div>
                                <small style="color: #888; font-size: ${isMobile ? '0.75rem' : '0.85rem'};">${(Number(avgRating) || 0).toFixed(1)} ${t.avg_rating || 'avg rating'} × ${(ratingCount || 0)} ${t.track_ratings || 'track ratings'} × ${t.weight || 'weight'} 5.0</small>
                            </div>
                            <div style="margin-top: 1rem; padding-top: 1rem; border-top: 2px solid rgba(251, 191, 36, 0.3);">
                                <div style="display: flex; justify-content: space-between; flex-wrap: wrap; gap: 0.5rem;">
                                    <span style="color: #fbbf24; font-weight: 700; font-size: ${isMobile ? '1rem' : '1.1rem'};">${t.total_score || 'Total Score'}:</span>
                                    <span style="color: #fbbf24; font-weight: 700; font-size: ${isMobile ? '1.1rem' : '1.3rem'};">${breakdown.total_score || 0}</span>
                                </div>
                            </div>
                        </div>
                    </div>
                    
                    <div style="margin-bottom: ${isMobile ? '1.5rem' : '2rem'};">
                        <h4 style="color: #667eea; margin-bottom: 1rem; font-size: ${isMobile ? '1rem' : '1.2rem'};">${t.individual_rankings || 'Individual Rankings'}</h4>
                        <div style="display: grid; gap: 0.75rem;">
                            <div style="background: rgba(0, 0, 0, 0.2); padding: ${isMobile ? '0.6rem' : '0.75rem'}; border-radius: 8px; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 0.5rem;">
                                <span style="color: #a0aec0; font-size: ${isMobile ? '0.85rem' : '1rem'};">${t.by_plays || 'By Plays'}:</span>
                                <span style="color: #ffffff; font-weight: 600; font-size: ${isMobile ? '0.9rem' : '1rem'};">#${rankings.plays} ${t.of || 'of'} ${rankings.total_tracks}</span>
                            </div>
                            <div style="background: rgba(0, 0, 0, 0.2); padding: ${isMobile ? '0.6rem' : '0.75rem'}; border-radius: 8px; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 0.5rem;">
                                <span style="color: #a0aec0; font-size: ${isMobile ? '0.85rem' : '1rem'};">${t.by_likes || 'By Likes'}:</span>
                                <span style="color: #ffffff; font-weight: 600; font-size: ${isMobile ? '0.9rem' : '1rem'};">#${rankings.likes} ${t.of || 'of'} ${rankings.total_tracks}</span>
                            </div>
                            ${ratingCount >= 3 && rankings.rating ? `
                            <div style="background: rgba(0, 0, 0, 0.2); padding: ${isMobile ? '0.6rem' : '0.75rem'}; border-radius: 8px; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 0.5rem;">
                                <span style="color: #a0aec0; font-size: ${isMobile ? '0.85rem' : '1rem'};">${t.by_rating || 'By Rating'}:</span>
                                <span style="color: #ffffff; font-weight: 600; font-size: ${isMobile ? '0.9rem' : '1rem'};">#${rankings.rating}</span>
                            </div>
                            ` : ''}
                        </div>
                    </div>
                    
                    <div style="background: rgba(102, 126, 234, 0.1); padding: ${isMobile ? '0.75rem' : '1rem'}; border-radius: 8px; border-left: 3px solid #667eea;">
                        <small style="color: #a0aec0; font-size: ${isMobile ? '0.75rem' : '0.85rem'}; line-height: 1.5;">
                            <strong>${t.formula || 'Formula'}:</strong> ${t.formula_text || 'Total Score = (Plays × 1) + (Likes × 2) + (Avg Rating × Rating Count × 5)'}
                        </small>
                    </div>
                    
                    <div style="margin-top: ${isMobile ? '1.5rem' : '2rem'}; padding-top: ${isMobile ? '1.5rem' : '2rem'}; padding-bottom: 1rem; border-top: 2px solid rgba(255, 255, 255, 0.1);">
                        <button class="btn-primary" onclick="showAllTrackRankings()" style="width: 100%; padding: ${isMobile ? '14px' : '12px'}; font-size: ${isMobile ? '0.9rem' : '1rem'}; font-weight: 600; display: flex; align-items: center; justify-content: center; gap: 0.5rem; visibility: visible !important; opacity: 1 !important;">
                            <i class="fas fa-list"></i> <span>${t.view_all_rankings || 'View All Track Rankings'}</span>
                        </button>
                    </div>
                </div>
                <div class="modal-footer" style="flex-shrink: 0; padding: ${isMobile ? '1rem' : '1.5rem 2rem'}; border-top: 1px solid rgba(255, 255, 255, 0.1);">
                    <button class="btn-primary" onclick="closeRankingBreakdownModal()" style="width: 100%; padding: ${isMobile ? '12px' : '10px 20px'}; font-size: ${isMobile ? '0.9rem' : '1rem'}; font-weight: 600;">${t.close || 'Close'}</button>
                </div>
            </div>
        </div>
    `;
    
    console.log('📝 Inserting modal HTML...');
    document.body.insertAdjacentHTML('beforeend', modalHTML);
    
    // Wait a bit for DOM to update
    setTimeout(() => {
        const modal = document.getElementById('rankingBreakdownModal');
        console.log('🔍 Modal element found:', modal);
        
        if (modal) {
            // Modal should already have styles from CSS class, but ensure it's visible
            modal.style.display = 'flex';
            document.body.style.overflow = 'hidden';
            
            console.log('✅ Modal displayed successfully');
            
            // Add click outside to close
            modal.addEventListener('click', function(e) {
                if (e.target === modal) {
                    closeRankingBreakdownModal();
                }
            });
        } else {
            console.error('❌ Modal not found after insertion');
            alert('Failed to create modal. Please refresh the page.');
        }
    }, 10);
}

function closeRankingBreakdownModal() {
    const modal = document.getElementById('rankingBreakdownModal');
    if (modal) {
        modal.remove();
        document.body.style.overflow = '';
        window.currentRankingModalTrackId = null;
    }
}

function refreshRankingModal(trackId) {
    // Fetch updated track data and refresh the modal
    // This is a simplified version - you may want to fetch from an API endpoint
    console.log('🔄 Refreshing ranking modal for track:', trackId);
    // For now, just close the modal - user can reopen it to see updated data
    closeRankingBreakdownModal();
}

// Helper function to escape HTML for modal content
function escapeHtmlForModal(text) {
    if (!text) return '';
    const div = document.createElement('div');
    div.textContent = text;
    return div.innerHTML;
}

function showAllTrackRankings() {
    // Close the current modal
    closeRankingBreakdownModal();
    
    // Detect mobile device
    const isMobile = window.innerWidth <= 768;
    const modalWidth = isMobile ? '95%' : '900px';
    
    // Create loading modal
    const loadingModal = `
        <div class="profile-edit-modal" id="allRankingsModal" style="z-index: 10002;">
            <div class="modal-content" style="max-width: ${modalWidth}; width: ${modalWidth}; max-height: 90vh;">
                <div class="modal-header">
                    <h3 style="font-size: ${isMobile ? '1.2rem' : '1.5rem'}; margin: 0;">📊 ${window.rankingTranslations?.all_rankings_title || 'All Track Rankings'}</h3>
                    <button class="close-btn" onclick="closeAllRankingsModal()" style="font-size: ${isMobile ? '1.5rem' : '2rem'}; width: ${isMobile ? '24px' : '30px'}; height: ${isMobile ? '24px' : '30px'};">&times;</button>
                </div>
                <div class="modal-body" style="text-align: center; padding: 3rem;">
                    <div class="loading-spinner" style="font-size: 3rem; margin-bottom: 1rem;">âŗ</div>
                    <p style="color: #a0aec0;">${window.rankingTranslations?.loading_rankings || 'Loading rankings...'}</p>
                </div>
            </div>
        </div>
    `;
    
    document.body.insertAdjacentHTML('beforeend', loadingModal);
    const modal = document.getElementById('allRankingsModal');
    if (modal) {
        modal.style.display = 'flex';
        document.body.style.overflow = 'hidden';
    }
    
    // Fetch all rankings
    fetch('/api/get_all_track_rankings.php?per_page=500')
        .then(response => response.json())
        .then(data => {
            if (data.success && data.tracks) {
                displayAllRankings(data.tracks, data.pagination);
            } else {
                if (typeof showNotification === 'function') {
                    showNotification(data.error || 'Failed to load rankings', 'error');
                } else {
                    alert(data.error || 'Failed to load rankings');
                }
                closeAllRankingsModal();
            }
        })
        .catch(error => {
            console.error('Error fetching rankings:', error);
            if (typeof showNotification === 'function') {
                showNotification('Failed to load rankings. Please try again.', 'error');
            } else {
                alert('Failed to load rankings. Please try again.');
            }
            closeAllRankingsModal();
        });
}

function displayAllRankings(tracks, pagination) {
    const modal = document.getElementById('allRankingsModal');
    if (!modal) return;
    
    const t = window.rankingTranslations || {};
    const isMobile = window.innerWidth <= 768;
    
    let tracksHTML = '';
    
    if (tracks.length === 0) {
        tracksHTML = `
            <div style="text-align: center; padding: 3rem; color: #a0aec0;">
                <p>${t.no_tracks || 'No tracks found'}</p>
            </div>
        `;
    } else {
        // Mobile-friendly table or list view
        if (isMobile) {
            tracksHTML = `
                <div style="overflow-y: auto; max-height: 60vh;">
                    ${tracks.map((track, index) => {
                        return `
                            <div style="background: ${index % 2 === 0 ? 'rgba(255, 255, 255, 0.05)' : 'rgba(255, 255, 255, 0.02)'}; padding: 1rem; margin-bottom: 0.5rem; border-radius: 8px; border-left: 3px solid #667eea;">
                                <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.5rem;">
                                    <span style="font-weight: 700; color: #fbbf24; font-size: 0.9rem;">#${track.rank}</span>
                                    <span style="font-weight: 600; color: #ffffff; font-size: 0.85rem;">${track.total_score.toLocaleString()}</span>
                                </div>
                                <div style="margin-bottom: 0.5rem;">
                                    <a href="/track.php?id=${track.id}" style="color: #667eea; text-decoration: none; font-weight: 500; font-size: 0.9rem;" 
                                       onmouseover="this.style.textDecoration='underline'" 
                                       onmouseout="this.style.textDecoration='none'">
                                        ${escapeHtmlForModal(track.title)}
                                    </a>
                                    <div style="font-size: 0.8rem; color: #a0aec0; margin-top: 2px;">
                                        ${escapeHtmlForModal(track.artist_name)}
                                    </div>
                                </div>
                                <div style="display: flex; justify-content: space-between; font-size: 0.8rem; color: #a0aec0;">
                                    <span>${t.plays || 'Plays'}: ${track.play_count.toLocaleString()}</span>
                                    <span>${t.likes || 'Likes'}: ${track.like_count.toLocaleString()}</span>
                                    <span>${t.rating || 'Rating'}: ${track.rating_count > 0 ? track.avg_rating.toFixed(1) : '-'}</span>
                                </div>
                            </div>
                        `;
                    }).join('')}
                </div>
            `;
        } else {
            tracksHTML = `
                <div style="overflow-x: auto; max-height: 60vh;">
                    <table style="width: 100%; border-collapse: collapse; color: white;">
                        <thead>
                            <tr style="background: rgba(102, 126, 234, 0.2); border-bottom: 2px solid rgba(102, 126, 234, 0.5);">
                                <th style="padding: 12px; text-align: left; font-weight: 700; color: #667eea;">${t.rank || ''}</th>
                                <th style="padding: 12px; text-align: left; font-weight: 700; color: #667eea;">${t.track || 'Track'}</th>
                                <th style="padding: 12px; text-align: center; font-weight: 700; color: #667eea;">${t.plays || 'Plays'}</th>
                                <th style="padding: 12px; text-align: center; font-weight: 700; color: #667eea;">${t.likes || 'Likes'}</th>
                                <th style="padding: 12px; text-align: center; font-weight: 700; color: #667eea;">${t.rating || 'Rating'}</th>
                                <th style="padding: 12px; text-align: right; font-weight: 700; color: #fbbf24;">${t.total_score || 'Score'}</th>
                            </tr>
                        </thead>
                        <tbody>
                            ${tracks.map((track, index) => {
                                const rowStyle = index % 2 === 0 
                                    ? 'background: rgba(255, 255, 255, 0.05);' 
                                    : 'background: rgba(255, 255, 255, 0.02);';
                                
                                return `
                                    <tr style="${rowStyle}">
                                        <td style="padding: 12px; font-weight: 600; color: #ffffff;">
                                            #${track.rank}
                                        </td>
                                        <td style="padding: 12px;">
                                            <a href="/track.php?id=${track.id}" style="color: #667eea; text-decoration: none; font-weight: 500;" 
                                               onmouseover="this.style.textDecoration='underline'" 
                                               onmouseout="this.style.textDecoration='none'">
                                                ${escapeHtmlForModal(track.title)}
                                            </a>
                                            <div style="font-size: 0.85rem; color: #a0aec0; margin-top: 2px;">
                                                ${escapeHtmlForModal(track.artist_name)}
                                            </div>
                                        </td>
                                        <td style="padding: 12px; text-align: center; color: #a0aec0;">
                                            ${track.play_count.toLocaleString()}
                                        </td>
                                        <td style="padding: 12px; text-align: center; color: #a0aec0;">
                                            ${track.like_count.toLocaleString()}
                                        </td>
                                        <td style="padding: 12px; text-align: center; color: #a0aec0;">
                                            ${track.rating_count > 0 ? track.avg_rating.toFixed(1) + ' (' + track.rating_count + ')' : '-'}
                                        </td>
                                        <td style="padding: 12px; text-align: right; font-weight: 600; color: #ffffff;">
                                            ${track.total_score.toLocaleString()}
                                        </td>
                                    </tr>
                                `;
                            }).join('')}
                        </tbody>
                    </table>
                </div>
            `;
        }
        
        if (pagination && pagination.total_tracks > pagination.per_page) {
            tracksHTML += `
                <div style="margin-top: 1rem; padding-top: 1rem; border-top: 1px solid rgba(255, 255, 255, 0.1); text-align: center; color: #a0aec0; font-size: ${isMobile ? '0.85rem' : '0.9rem'};">
                    ${t.showing || 'Showing'} ${((pagination.page - 1) * pagination.per_page) + 1}-${Math.min(pagination.page * pagination.per_page, pagination.total_tracks)} ${t.of || 'of'} ${pagination.total_tracks.toLocaleString()} ${t.tracks || 'tracks'}
                </div>
            `;
        }
    }
    
    modal.querySelector('.modal-body').innerHTML = tracksHTML;
    
    // Add click outside to close
    modal.addEventListener('click', function(e) {
        if (e.target === modal) {
            closeAllRankingsModal();
        }
    });
}

function closeAllRankingsModal() {
    const modal = document.getElementById('allRankingsModal');
    if (modal) {
        modal.remove();
        document.body.style.overflow = '';
    }
}

function showComments(trackId) {
    window.location.href = `/track.php?id=${trackId}#comments`;
}

// Track Rating Functions
const ratingLabelMap = <?= json_encode([
    '1' => t('artist_profile.rating_label_1') ?? 'Poor',
    '2' => t('artist_profile.rating_label_2') ?? 'Below Average',
    '3' => t('artist_profile.rating_label_3') ?? 'Fair',
    '4' => t('artist_profile.rating_label_4') ?? 'Decent',
    '5' => t('artist_profile.rating_label_5') ?? 'Average',
    '6' => t('artist_profile.rating_label_6') ?? 'Good',
    '7' => t('artist_profile.rating_label_7') ?? 'Very Good',
    '8' => t('artist_profile.rating_label_8') ?? 'Great',
    '9' => t('artist_profile.rating_label_9') ?? 'Excellent',
    '10' => t('artist_profile.rating_label_10') ?? 'Masterpiece',
    'default' => t('artist_profile.rating_label_default') ?? 'Select a rating',
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;

function getRatingLabel(rating) {
    if (ratingLabelMap && ratingLabelMap[rating]) {
        return ratingLabelMap[rating];
    }
    if (ratingLabelMap && ratingLabelMap['default']) {
        return ratingLabelMap['default'];
    }
    return 'Select a rating';
}

function showTrackRatingModal(trackId, trackTitle) {
    console.log('đŸŽĩ Track rating modal for:', trackId, trackTitle);
    
    // Check if user is logged in
    const isLoggedIn = <?= isset($_SESSION['user_id']) && $_SESSION['user_id'] ? 'true' : 'false' ?>;
    if (!isLoggedIn) {
        if (typeof showNotification === 'function') {
            showNotification('Please log in to rate tracks', 'warning');
        }
        setTimeout(() => {
            window.location.href = '/auth/login.php';
        }, 2000);
        return;
    }
    
    // Remove any existing track rating modal first
    const existingModal = document.getElementById('trackRatingModal');
    if (existingModal) {
        existingModal.remove();
    }
    
    const modalHTML = `
        <div class="profile-edit-modal" id="trackRatingModal" style="z-index: 10001;">
            <div class="modal-content">
                <div class="modal-header">
                    <h3><?= htmlspecialchars(t('artist_profile.rate_track_modal_title') ?? 'Rate Track', ENT_QUOTES, 'UTF-8') ?>: ${trackTitle}</h3>
                    <button class="close-btn" onclick="closeTrackRatingModal()">&times;</button>
                </div>
                <div class="modal-body">
                    <div class="rating-input-section">
                        <div class="stars-input">
                            <i class="far fa-star" data-rating="1"></i>
                            <i class="far fa-star" data-rating="2"></i>
                            <i class="far fa-star" data-rating="3"></i>
                            <i class="far fa-star" data-rating="4"></i>
                            <i class="far fa-star" data-rating="5"></i>
                            <i class="far fa-star" data-rating="6"></i>
                            <i class="far fa-star" data-rating="7"></i>
                            <i class="far fa-star" data-rating="8"></i>
                            <i class="far fa-star" data-rating="9"></i>
                            <i class="far fa-star" data-rating="10"></i>
                        </div>
                        <div class="rating-feedback">
                            <span class="rating-value">0/10</span>
                            <span class="rating-label"><?= htmlspecialchars(t('artist_profile.rate_modal_hint_track') ?? 'Click a star to rate', ENT_QUOTES, 'UTF-8') ?></span>
                        </div>
                    </div>
                    <div class="rating-comment">
                        <label for="trackRatingComment"><?= htmlspecialchars(t('artist_profile.rate_modal_comment_label') ?? 'Comment (optional)', ENT_QUOTES, 'UTF-8') ?></label>
                        <textarea id="trackRatingComment" placeholder="<?= htmlspecialchars(t('artist_profile.rate_modal_comment_placeholder_track') ?? 'Share your thoughts about this track...', ENT_QUOTES, 'UTF-8') ?>" rows="4"></textarea>
                    </div>
                </div>
                <div class="modal-footer">
                    <button class="btn-secondary" onclick="closeTrackRatingModal()"><?= htmlspecialchars(t('artist_profile.cancel') ?? 'Cancel', ENT_QUOTES, 'UTF-8') ?></button>
                    <button class="btn-primary" onclick="submitTrackRating(${trackId})"><?= htmlspecialchars(t('artist_profile.submit_rating') ?? 'Submit Rating', ENT_QUOTES, 'UTF-8') ?></button>
                </div>
            </div>
        </div>
    `;
    
    document.body.insertAdjacentHTML('beforeend', modalHTML);
    
    // Make sure modal is visible
    const modal = document.getElementById('trackRatingModal');
    if (modal) {
        modal.style.display = 'flex';
        modal.dataset.currentRating = '0';
    }
    
    // Fetch user's existing rating for this track
    fetch(`/api_social.php?action=get_user_track_rating&track_id=${trackId}`)
        .then(response => response.json())
        .then(data => {
            let existingRating = 0;
            let existingComment = '';
            
            if (data.success && data.data && data.data.rating !== null) {
                existingRating = parseInt(data.data.rating);
                existingComment = data.data.comment || '';
            }
            
            setTimeout(() => {
                const stars = document.querySelectorAll('#trackRatingModal .stars-input i');
                let currentRating = existingRating;
                
                // Initialize with existing rating if found
                if (existingRating > 0 && modal) {
                    modal.dataset.currentRating = existingRating.toString();
                    stars.forEach((s, index) => {
                        s.className = index < existingRating ? 'fas fa-star' : 'far fa-star';
                    });
                    const ratingValueEl = document.querySelector('#trackRatingModal .rating-value');
                    const ratingLabelEl = document.querySelector('#trackRatingModal .rating-label');
                    if (ratingValueEl) ratingValueEl.textContent = `${existingRating}/10`;
                    if (ratingLabelEl) ratingLabelEl.textContent = getRatingLabel(existingRating);
                    
                    const commentTextarea = document.getElementById('trackRatingComment');
                    if (commentTextarea && existingComment) {
                        commentTextarea.value = existingComment;
                    }
                }
                
                // Add star rating functionality
                stars.forEach(star => {
                    star.addEventListener('click', function() {
                        const rating = parseInt(this.dataset.rating);
                        currentRating = rating;
                        if (modal) modal.dataset.currentRating = rating.toString();
                        
                        stars.forEach((s, index) => {
                            s.className = index < rating ? 'fas fa-star' : 'far fa-star';
                        });
                        
                        const ratingValueEl = document.querySelector('#trackRatingModal .rating-value');
                        const ratingLabelEl = document.querySelector('#trackRatingModal .rating-label');
                        if (ratingValueEl) ratingValueEl.textContent = `${rating}/10`;
                        if (ratingLabelEl) ratingLabelEl.textContent = getRatingLabel(rating);
                    });
                    
                    star.addEventListener('mouseenter', function() {
                        const rating = parseInt(this.dataset.rating);
                        stars.forEach((s, index) => {
                            s.className = index < rating ? 'fas fa-star' : 'far fa-star';
                        });
                    });
                    
                    star.addEventListener('mouseleave', function() {
                        stars.forEach((s, index) => {
                            s.className = index < currentRating ? 'fas fa-star' : 'far fa-star';
                        });
                    });
                });
            }, 100);
        })
        .catch(error => {
            console.error('Error fetching user rating:', error);
        });
}

function closeTrackRatingModal() {
    const modal = document.getElementById('trackRatingModal');
    if (modal) modal.remove();
}

function submitTrackRating(trackId) {
    const modal = document.getElementById('trackRatingModal');
    let rating = 0;
    
    if (modal && modal.dataset.currentRating) {
        rating = parseInt(modal.dataset.currentRating, 10);
    }
    
    if (!rating || rating < 1 || rating > 10) {
        const selectedStars = modal ? modal.querySelectorAll('.stars-input i.fas').length : 0;
        if (selectedStars > 0) rating = selectedStars;
    }
    
    const comment = document.getElementById('trackRatingComment')?.value || '';
    
    if (!rating || rating < 1 || rating > 10) {
        if (typeof showNotification === 'function') {
            showNotification('Please select a rating between 1 and 10', 'warning');
        }
        return;
    }
    
    const formData = new FormData();
    formData.append('action', 'submit_track_rating');
    formData.append('track_id', trackId);
    formData.append('rating', rating);
    formData.append('comment', comment);
    
    fetch('/api_social.php', {
        method: 'POST',
        body: formData
    })
    .then(response => response.json())
    .then(data => {
        if (data.success) {
            if (typeof showNotification === 'function') {
                showNotification('Track rating submitted successfully!', 'success');
            }
            closeTrackRatingModal();
            
            // Update the star display on the page
            if (data.data) {
                const trackCard = document.querySelector(`.track-card[data-track-id="${trackId}"]`);
                if (trackCard) {
                    const starBtn = trackCard.querySelector('.stat-btn .fa-star');
                    if (starBtn) {
                        starBtn.style.color = '#fbbf24';
                        const countSpan = starBtn.parentElement.querySelector('span');
                        if (countSpan) {
                            countSpan.textContent = parseFloat(data.data.average_rating).toFixed(1);
                        } else if (data.data.average_rating) {
                            starBtn.parentElement.insertAdjacentHTML('beforeend', `<span>${parseFloat(data.data.average_rating).toFixed(1)}</span>`);
                        }
                    }
                }
            }
        } else {
            if (typeof showNotification === 'function') {
                showNotification(data.message || 'Failed to submit rating', 'error');
            }
        }
    })
    .catch(error => {
        console.error('Rating submission error:', error);
        if (typeof showNotification === 'function') {
            showNotification('Error submitting rating', 'error');
        }
    });
}

function shareTrack(trackId) {
    // Find the track card to get title and artist
    const trackCard = document.querySelector(`.track-card[data-track-id="${trackId}"]`);
    const trackTitleElement = trackCard?.querySelector('.track-title');
    const trackArtistElement = trackCard?.querySelector('.track-artist');
    
    const trackTitle = trackTitleElement?.textContent?.trim() || 'Track';
    const artistName = trackArtistElement?.textContent?.trim() || 'Artist';
    const url = `${window.location.origin}/track.php?id=${trackId}`;
    const shareText = `Check out "${trackTitle}" by ${artistName} on SoundStudioPro! đŸŽĩ`;
    
    const shareData = {
        title: `${trackTitle} by ${artistName}`,
        text: shareText,
        url: url
    };
    
    // Record the share in the database (don't wait for it)
    const platform = 'web';
    fetch('/api_social.php', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ 
            action: 'share', 
            track_id: trackId, 
            platform: platform 
        })
    })
    .then(response => {
        if (!response.ok) {
            throw new Error('Network response was not ok');
        }
        return response.json();
    })
    .then(data => {
        if (data.success) {
            console.log('🚀 Share recorded for track:', trackId, 'New count:', data.share_count);
            // Update share count in UI - use the count from server
            const shareButtons = document.querySelectorAll(`button[onclick*="shareTrack(${trackId})"]`);
            shareButtons.forEach(button => {
                const countSpan = button.querySelector('span');
                if (countSpan) {
                    // Use the count from server if available, otherwise increment
                    if (data.share_count !== undefined) {
                        countSpan.textContent = parseInt(data.share_count).toLocaleString();
                    } else {
                        const currentCount = parseInt(countSpan.textContent.replace(/,/g, '')) || 0;
                        countSpan.textContent = (currentCount + 1).toLocaleString();
                    }
                }
            });
        } else {
            console.warn('🚀 Share recording failed:', data.message || 'Unknown error');
        }
    })
    .catch(error => {
        console.error('🚀 Share recording error:', error);
    });
    
    // Try native share API first (mobile devices, especially Android)
    if (navigator.share) {
        // Check if we can share this data (Android requirement)
        if (navigator.canShare && navigator.canShare(shareData)) {
            navigator.share(shareData)
            .then(() => {
                console.log('🚀 Track shared successfully via native API');
                if (typeof showNotification === 'function') {
                    showNotification('✅ Track shared successfully!', 'success');
                }
            })
            .catch((error) => {
                // User cancelled or error - fallback to clipboard
                if (error.name !== 'AbortError') {
                    console.log('🚀 Share API failed, using clipboard:', error);
                    copyTrackUrlToClipboard(url, shareText);
                }
            });
        } else if (!navigator.canShare) {
            // canShare not available, try share anyway
            navigator.share(shareData)
            .then(() => {
                console.log('🚀 Track shared successfully via Web Share API');
                if (typeof showNotification === 'function') {
                    showNotification('✅ Track shared successfully!', 'success');
                }
            })
            .catch((error) => {
                // User cancelled or error - fallback to clipboard
                if (error.name !== 'AbortError') {
                    console.log('🚀 Share API failed, using clipboard:', error);
                    copyTrackUrlToClipboard(url, shareText);
                }
            });
        } else {
            // canShare returned false, use clipboard
            console.log('🚀 Share not available, using clipboard');
            copyTrackUrlToClipboard(url, shareText);
        }
    } else {
        // Use clipboard for desktop
        copyTrackUrlToClipboard(url, shareText);
    }
}

// Copy track URL to clipboard
function copyTrackUrlToClipboard(url, shareText) {
    const shareData = `${shareText}\n${url}`;
    
    // Check if we're in a secure context (HTTPS or localhost)
    const isSecureContext = window.isSecureContext || location.protocol === 'https:' || location.hostname === 'localhost' || location.hostname === '127.0.0.1';
    
    // Try modern clipboard API first (requires secure context)
    if (isSecureContext && navigator.clipboard && navigator.clipboard.writeText) {
        navigator.clipboard.writeText(shareData)
            .then(() => {
                console.log('🚀 Clipboard copy successful');
                if (typeof showNotification === 'function') {
                    showNotification('🔗 Track link copied to clipboard!', 'success');
                } else {
                    alert('Track link copied to clipboard!\n\n' + shareData);
                }
            })
            .catch((error) => {
                console.error('🚀 Clipboard API failed:', error);
                // Fallback to execCommand method
                fallbackCopyTrack(shareData);
            });
    } else {
        // Not in secure context or clipboard API not available, use fallback
        console.log('🚀 Clipboard API not available, using fallback');
        fallbackCopyTrack(shareData);
    }
}

// Fallback copy method for track sharing
function fallbackCopyTrack(shareData) {
    console.log('🚀 Using fallback copy method for track');
    
    // Use textarea for better mobile compatibility
    const textarea = document.createElement('textarea');
    textarea.value = shareData;
    textarea.style.position = 'fixed';
    textarea.style.left = '-9999px';
    textarea.style.top = '-9999px';
    textarea.style.opacity = '0';
    textarea.setAttribute('readonly', '');
    textarea.setAttribute('aria-hidden', 'true');
    document.body.appendChild(textarea);
    
    // For Android, we need to ensure the element is visible and focused
    if (/Android/i.test(navigator.userAgent)) {
        textarea.style.position = 'absolute';
        textarea.style.left = '0';
        textarea.style.top = '0';
        textarea.style.width = '1px';
        textarea.style.height = '1px';
        textarea.style.opacity = '0.01';
    }
    
    // Select the text
    textarea.focus();
    textarea.select();
    textarea.setSelectionRange(0, shareData.length);
    
    try {
        const successful = document.execCommand('copy');
        // Clean up
        setTimeout(() => {
            document.body.removeChild(textarea);
        }, 100);
        
        if (successful) {
            console.log('🚀 Fallback copy successful');
            if (typeof showNotification === 'function') {
                showNotification('🔗 Track link copied to clipboard!', 'success');
            } else {
                alert('Track link copied to clipboard!\n\n' + shareData);
            }
        } else {
            console.log('🚀 Fallback copy failed, showing prompt');
            // Show a more user-friendly prompt
            const userCopied = confirm('Please copy this link:\n\n' + shareData + '\n\nClick OK if you copied it.');
            if (userCopied && typeof showNotification === 'function') {
                showNotification('🔗 Link copied!', 'success');
            }
        }
    } catch (error) {
        console.error('🚀 Fallback copy error:', error);
        document.body.removeChild(textarea);
        // Show a more user-friendly prompt
        const userCopied = confirm('Please copy this link:\n\n' + shareData + '\n\nClick OK if you copied it.');
        if (userCopied && typeof showNotification === 'function') {
            showNotification('🔗 Link copied!', 'success');
        }
    }
}

// Share Community Feed
function shareCommunityFeed() {
    console.log('Share Community Feed button clicked');
    const urlToCopy = window.location.href;
    console.log('URL to copy:', urlToCopy);
    
    // Try native share API first (mobile devices)
    if (navigator.share) {
        navigator.share({
            title: 'Community Feed - SoundStudioPro',
            text: 'Check out the community feed on SoundStudioPro!',
            url: urlToCopy
        })
        .then(() => {
            console.log('Share successful');
            if (typeof showNotification === 'function') {
                showNotification('✅ Shared successfully!', 'success');
            }
        })
        .catch((error) => {
            // User cancelled or error - fallback to clipboard
            if (error.name !== 'AbortError') {
                console.log('Share API failed, using clipboard:', error);
                copyCommunityUrlToClipboard(urlToCopy);
            }
        });
    } else {
        // Use clipboard for desktop
        copyCommunityUrlToClipboard(urlToCopy);
    }
}

// Copy community URL to clipboard
function copyCommunityUrlToClipboard(urlToCopy) {
    // Try modern clipboard API first
    if (navigator.clipboard && navigator.clipboard.writeText) {
        navigator.clipboard.writeText(urlToCopy)
            .then(() => {
                console.log('Clipboard copy successful');
                if (typeof showNotification === 'function') {
                    showNotification('🔗 Community Feed link copied to clipboard!', 'success');
                } else {
                    alert('Link copied to clipboard: ' + urlToCopy);
                }
            })
            .catch((error) => {
                console.error('Clipboard API failed:', error);
                fallbackShareCommunity(urlToCopy);
            });
    } else {
        fallbackShareCommunity(urlToCopy);
    }
}

// Fallback share method for community feed
function fallbackShareCommunity(urlToCopy) {
    console.log('Using fallback share method');
    const input = document.createElement('input');
    input.style.position = 'fixed';
    input.style.left = '-9999px';
    input.style.top = '-9999px';
    input.value = urlToCopy;
    document.body.appendChild(input);
    input.focus();
    input.select();
    input.setSelectionRange(0, 99999); // For mobile devices
    
    try {
        const successful = document.execCommand('copy');
        document.body.removeChild(input);
        if (successful) {
            console.log('Fallback copy successful');
            if (typeof showNotification === 'function') {
                showNotification('🔗 Community Feed link copied to clipboard!', 'success');
            } else {
                alert('Link copied to clipboard: ' + urlToCopy);
            }
        } else {
            console.log('Fallback copy failed, showing prompt');
            prompt('Copy this link:', urlToCopy);
        }
    } catch (error) {
        console.error('Fallback copy error:', error);
        document.body.removeChild(input);
        prompt('Copy this link:', urlToCopy);
    }
}

function showVariations(trackId, button) {
    const container = document.getElementById(`variations-${trackId}`);
    if (!container) return;
    
    const isVisible = container.style.display !== 'none';
    container.style.display = isVisible ? 'none' : 'block';
    
    if (button) {
        button.classList.toggle('active');
    }
}

function addToCart(trackId, title, price, button) {
    console.log('🛒 Adding to cart:', { trackId, title, price, button });
    
    // Store original button HTML and disable button to prevent double-clicks
    let originalHTML = null;
    if (button) {
        originalHTML = button.innerHTML;
        button.disabled = true;
        button.innerHTML = '<i class="fas fa-spinner fa-spin"></i> <span>Adding...</span>';
    }
    
    // Use FormData to match cart.php expectations
    const formData = new FormData();
    formData.append('track_id', trackId);
    formData.append('action', 'add');
    formData.append('artist_plan', 'free'); // Default to free plan
    
    fetch('/cart.php', {
        method: 'POST',
        body: formData
    })
    .then(response => {
        console.log('🛒 Response status:', response.status, response.statusText);
        console.log('🛒 Response headers:', response.headers.get('content-type'));
        
        // Check if response is OK
        if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
        }
        
        // Check if response is JSON
        const contentType = response.headers.get('content-type');
        if (!contentType || !contentType.includes('application/json')) {
            return response.text().then(text => {
                console.error('🛒 Non-JSON response:', text);
                throw new Error('Server returned non-JSON response');
            });
        }
        
        return response.json();
    })
    .then(data => {
        console.log('🛒 Cart response data:', data);
        
        if (data.success) {
            // Visual feedback
            if (button) {
                button.classList.add('added');
                button.innerHTML = '<i class="fas fa-check"></i> <span>Added!</span>';
                
                setTimeout(() => {
                    button.classList.remove('added');
                    if (originalHTML) {
                        button.innerHTML = originalHTML;
                    }
                    button.disabled = false;
                }, 2000);
            }
            
            // Show notification if available
            if (typeof showNotification === 'function') {
                showNotification('🛒 "' + title + '" added to cart!', 'success');
            }
            
            // Update cart counter if it exists
            const cartCounts = document.querySelectorAll('.cart-count, .cart-counter');
            if (cartCounts.length > 0 && data.cart_count !== undefined) {
                cartCounts.forEach(count => {
                    count.textContent = data.cart_count;
                    if (data.cart_count > 0) {
                        count.style.display = 'flex';
                        if (count.classList.contains('cart-counter')) {
                            count.style.display = 'block';
                        }
                    } else {
                        count.style.display = 'none';
                    }
                });
            } else if (cartCounts.length > 0) {
                // Fallback: manually increment if API didn't return count
                cartCounts.forEach(count => {
                    const currentCount = parseInt(count.textContent) || 0;
                    count.textContent = currentCount + 1;
                    count.style.display = 'flex';
                    if (count.classList.contains('cart-counter')) {
                        count.style.display = 'block';
                    }
                });
            }
            
            // Refresh cart modal if it's currently open
            const cartModal = document.getElementById('cartModal');
            if (cartModal && cartModal.style.display === 'flex') {
                if (typeof refreshCartModal === 'function') {
                    refreshCartModal();
                }
            }
        } else {
            // Re-enable button on error
            if (button && originalHTML) {
                button.disabled = false;
                button.innerHTML = originalHTML;
            }
            
            // Special handling for "already in cart" - show as warning, not error
            const errorMsg = data.message || data.error || 'Failed to add to cart. Please try again.';
            if (data.already_in_cart) {
                if (typeof showNotification === 'function') {
                    showNotification('â„šī¸ ' + errorMsg, 'warning');
                } else {
                    alert(errorMsg);
                }
            } else {
                if (typeof showNotification === 'function') {
                    showNotification('❌ Error: ' + errorMsg, 'error');
                } else {
                    alert('Error: ' + errorMsg);
                }
            }
        }
    })
    .catch(error => {
        console.error('❌ Cart error:', error);
        
        // Re-enable button on error
        if (button && originalHTML) {
            button.disabled = false;
            button.innerHTML = originalHTML;
        }
        
        const errorMsg = 'An error occurred while adding to cart. Please try again.';
        if (typeof showNotification === 'function') {
            showNotification(errorMsg, 'error');
        } else {
            alert(errorMsg);
        }
    });
}

function downloadTrack(trackId) {
    window.location.href = `/api/download_track.php?id=${trackId}`;
}

// Store our playTrack function before footer overwrites it
const communityFixedPlayTrack = window.playTrack;

// Ensure playTrack function works after AJAX page loads and restore it after footer loads
document.addEventListener('DOMContentLoaded', function() {
    console.log('đŸŽĩ Community Fixed page loaded - playTrack function ready');
    console.log('đŸŽĩ Checking global player availability...');
    console.log('window.waitForGlobalPlayer:', typeof window.waitForGlobalPlayer);
    console.log('window.enhancedGlobalPlayer:', typeof window.enhancedGlobalPlayer);
    console.log('window.globalPlayerReady:', window.globalPlayerReady);
    
    // Restore our function after footer loads (footer loads at end of body)
    setTimeout(function() {
        if (communityFixedPlayTrack) {
            window.playTrack = communityFixedPlayTrack;
            console.log('đŸŽĩ Restored community_fixed playTrack function after footer load');
        }
        
        // Verify global player is ready
        if (window.waitForGlobalPlayer) {
            window.waitForGlobalPlayer(function() {
                console.log('✅ Global player confirmed ready on page load');
            });
        } else {
            console.error('❌ waitForGlobalPlayer still not available after footer load');
        }
    }, 200);
});

// Listen for AJAX page loads
document.addEventListener('ajaxPageLoaded', function() {
    console.log('đŸŽĩ Community Fixed page loaded via AJAX - playTrack function ready');
    // Ensure global player is available
    if (window.waitForGlobalPlayer) {
        window.waitForGlobalPlayer(function() {
            console.log('đŸŽĩ Global player ready after AJAX load');
        });
    }
});
</script>

<!-- Infinite Scroll Implementation -->
<script>
(function() {
    // Translations for JavaScript
    window.wishlistTranslations = {
        add_to_wishlist: '<?= addslashes(t('artist_profile.add_to_wishlist')) ?>',
        remove_from_wishlist: '<?= addslashes(t('artist_profile.remove_from_wishlist')) ?>'
    };
    const translations = {
        for_sale: '<?= addslashes(t('community.for_sale')) ?>',
        available_for_purchase: '<?= addslashes(t('community.available_for_purchase')) ?>',
        unknown_artist: '<?= addslashes(t('artists.unknown_artist')) ?>',
        untitled_track: '<?= addslashes(t('community.untitled_track')) ?>',
        plays: '<?= addslashes(t('preview.plays')) ?>',
        likes: '<?= addslashes(t('library.card.like')) ?>',
        comments: '<?= addslashes(t('artist_profile.comments')) ?>',
        shares: '<?= addslashes(t('library.card.share')) ?>',
        rate_track: '<?= addslashes(t('artist_profile.rate_track')) ?>',
        add_to_crate: '<?= addslashes(t('library.crates.add_to_crate')) ?>',
        variations: '<?= addslashes(t('community.variations')) ?>',
        add_to_cart: '<?= addslashes(t('community.add_to_cart')) ?>',
        free: '<?= addslashes(t('common.free')) ?>',
        error_loading_more: '<?= addslashes(t('community.error_loading_more')) ?>',
        login_to_vote: '<?= addslashes(t('artist_profile.login_to_vote')) ?>',
        error_voting: '<?= addslashes(t('artist_profile.error_voting')) ?>',
        error_voting_retry: '<?= addslashes(t('artist_profile.error_voting_retry')) ?>',
        add_to_wishlist: '<?= addslashes(t('artist_profile.add_to_wishlist')) ?>',
        remove_from_wishlist: '<?= addslashes(t('artist_profile.remove_from_wishlist')) ?>',
        follow_artist: '<?= addslashes(t('community.follow_artist')) ?>',
        unfollow_artist: '<?= addslashes(t('community.unfollow_artist')) ?>',
        login_required_follow: '<?= addslashes(t('notification.please_log_in_follow')) ?>'
    };
    
    let isLoading = false;
    let currentPage = 1;
    let hasMore = true;
    const currentUserId = <?= $user_id ?? 0 ?>;
    const tracksGrid = document.getElementById('tracksGrid');
    const loader = document.getElementById('infiniteScrollLoader');
    const endOfResults = document.getElementById('endOfResults');
    
    if (!tracksGrid) return;
    
    // Get initial state from data attributes
    currentPage = parseInt(tracksGrid.getAttribute('data-current-page')) || 1;
    hasMore = tracksGrid.getAttribute('data-has-more') === 'true';
    
    // Build community playlist from all visible tracks on the page
    function buildCommunityPlaylist() {
        const playlist = [];
        const grid = document.getElementById('tracksGrid');
        if (!grid) {
            console.warn('đŸŽĩ tracksGrid not found');
            return playlist;
        }
        
        const trackCards = grid.querySelectorAll('.track-card[data-track-id]');
        
        trackCards.forEach(card => {
            const trackId = parseInt(card.getAttribute('data-track-id'));
            const playBtn = card.querySelector('.play-btn');
            
            if (playBtn) {
                const audioUrl = playBtn.getAttribute('data-audio-url');
                const title = playBtn.getAttribute('data-title');
                const artist = playBtn.getAttribute('data-artist');
                const artistId = playBtn.getAttribute('data-artist-id');
                
                // Only add if we have valid data
                if (audioUrl && audioUrl !== 'null' && audioUrl !== '' && title) {
                    // Convert relative URL to absolute if needed
                    let finalAudioUrl = audioUrl;
                    if (audioUrl && !audioUrl.startsWith('http') && !audioUrl.startsWith('//')) {
                        if (audioUrl.startsWith('/')) {
                            finalAudioUrl = window.location.origin + audioUrl;
                        } else {
                            finalAudioUrl = window.location.origin + '/' + audioUrl;
                        }
                    }
                    
                    playlist.push({
                        id: trackId,
                        audio_url: finalAudioUrl,
                        title: title,
                        artist_name: artist || translations.unknown_artist,
                        artist_id: artistId ? parseInt(artistId) : null,
                        user_id: currentUserId || 0
                    });
                }
            }
        });
        
        console.log('đŸŽĩ Built community playlist:', playlist.length, 'tracks');
        return playlist;
    }
    
    // Make function globally accessible
    window.buildCommunityPlaylist = buildCommunityPlaylist;
    
    // Get current filter values
    function getFilterParams() {
        return {
            sort: document.getElementById('sortSelect')?.value || '<?= $sort ?>',
            time: document.getElementById('timeSelect')?.value || '<?= $time_filter ?>',
            genre: document.getElementById('genreSelect')?.value || '<?= $genre ?>',
            search: document.getElementById('searchInput')?.value.trim() || '<?= htmlspecialchars($search, ENT_QUOTES) ?>'
        };
    }
    
    // Load more tracks
    async function loadMoreTracks() {
        if (isLoading || !hasMore) return;
        
        isLoading = true;
        loader.style.display = 'block';
        
        const params = getFilterParams();
        const queryParams = new URLSearchParams({
            page: currentPage + 1,
            per_page: 24,
            sort: params.sort,
            time: params.time,
            genre: params.genre,
            ...(params.search ? { search: params.search } : {})
        });
        
        try {
            const response = await fetch(`/api/get_community_fixed_tracks.php?${queryParams}`);
            
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }
            
            const data = await response.json();
            
            if (!data.success) {
                console.error('API returned error:', data);
                throw new Error(data.error || data.message || 'Failed to load tracks');
            }
            
            if (data.success && data.tracks && data.tracks.length > 0) {
                // Render new tracks
                const fragment = document.createDocumentFragment();
                data.tracks.forEach(track => {
                    const trackCard = createTrackCard(track);
                    fragment.appendChild(trackCard);
                });
                
                tracksGrid.appendChild(fragment);
                
                // Update state
                currentPage = data.pagination.page;
                hasMore = data.pagination.has_more;
                tracksGrid.setAttribute('data-current-page', currentPage);
                tracksGrid.setAttribute('data-has-more', hasMore ? 'true' : 'false');
                
                // Re-attach play button listeners for new tracks
                attachPlayButtonListeners();
                
                // Update playlist if one is currently active (so new tracks are included)
                if (window.waitForGlobalPlayer) {
                    window.waitForGlobalPlayer(function() {
                        if (window.enhancedGlobalPlayer && window._communityPlaylistType === 'community_fixed') {
                            const buildFn = window.buildCommunityPlaylist || buildCommunityPlaylist;
                            const updatedPlaylist = buildFn ? buildFn() : [];
                            if (updatedPlaylist.length > 0) {
                                const currentIndex = window._communityTrackIndex || 0;
                                if (typeof window.enhancedGlobalPlayer.loadPagePlaylist === 'function') {
                                    window.enhancedGlobalPlayer.loadPagePlaylist(updatedPlaylist, 'community_fixed', currentIndex);
                                    console.log('đŸŽĩ Updated playlist with new tracks, total:', updatedPlaylist.length);
                                } else {
                                    window._communityPlaylist = updatedPlaylist;
                                    console.log('đŸŽĩ Updated window playlist with new tracks, total:', updatedPlaylist.length);
                                }
                            }
                        }
                    });
                }
                
                // Show end message if no more tracks
                if (!hasMore) {
                    endOfResults.style.display = 'block';
                }
            } else {
                hasMore = false;
                endOfResults.style.display = 'block';
            }
        } catch (error) {
            console.error('Error loading more tracks:', error);
            console.error('Error details:', {
                message: error.message,
                stack: error.stack,
                response: error.response
            });
            
            // Try to get more details from response if available
            if (error.response) {
                error.response.json().then(data => {
                    console.error('API Error Response:', data);
                }).catch(() => {});
            }
            
            if (typeof showNotification === 'function') {
                showNotification(translations.error_loading_more, 'error');
            } else {
                alert(translations.error_loading_more);
            }
        } finally {
            isLoading = false;
            loader.style.display = 'none';
        }
    }
    
    // Create track card HTML (simplified version matching the PHP template)
    function createTrackCard(track) {
        const card = document.createElement('div');
        card.className = 'track-card';
        card.setAttribute('data-track-id', track.id);
        card.setAttribute('itemscope', '');
        card.setAttribute('itemtype', 'http://schema.org/MusicRecording');
        
        const displayTitle = track.title || translations.untitled_track;
        const duration = track.duration ? formatDuration(track.duration) : '0:00';
        // Use resolved_image_url from API (which handles all fallbacks) or fallback to default
        const imageUrl = track.resolved_image_url || track.image_url || '/assets/images/default-track.jpg';
        const audioUrl = track.signed_audio_url || '';
        const isWishlisted = track.is_in_wishlist > 0;
        const displayPrice = track.price && track.price > 0 ? track.price : 1.99;
        
        // Extract genre from metadata
        let genre = 'Electronic';
        let mood = null;
        if (track.metadata) {
            const metadata = typeof track.metadata === 'string' ? JSON.parse(track.metadata) : track.metadata;
            if (metadata.genre) genre = metadata.genre;
            else if (metadata.style) genre = metadata.style;
            if (metadata.mood) mood = metadata.mood;
        }
        if ((genre === 'Electronic' || !genre) && track.genre) {
            genre = track.genre;
        }
        
        const createdDate = track.created_at ? new Date(track.created_at).toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' }) : '';
        
        card.innerHTML = `
            <div class="track-image-wrapper">
                <img src="${escapeHtml(imageUrl)}" alt="${escapeHtml(displayTitle)}" class="track-image" loading="lazy">
                <div class="track-overlay">
                    <button class="play-btn" 
                            data-track-id="${track.id}"
                            data-artist-id="${track.artist_id || ''}"
                            data-audio-url="${escapeHtml(audioUrl)}"
                            data-title="${escapeHtml(displayTitle)}"
                            data-artist="${escapeHtml(track.artist_name || '')}">
                        <i class="fas fa-play"></i>
                    </button>
                    <div class="track-duration">${duration}</div>
                </div>
            </div>
            <div class="track-info">
                <div class="track-title-row">
                    <a href="/track.php?id=${track.id}" class="track-title" title="${escapeHtml(displayTitle)}" target="_blank" itemprop="name">${escapeHtml(displayTitle)}</a>
                    ${track.price > 0 ? `<span class="for-sale-badge" title="${translations.available_for_purchase}"><i class="fas fa-tag"></i><span>${translations.for_sale}</span></span>` : ''}
                </div>
                <a href="/artist_profile.php?id=${track.artist_id}" class="track-artist" target="_blank" itemprop="byArtist" itemscope itemtype="http://schema.org/MusicGroup">
                    <span itemprop="name">${escapeHtml(track.artist_name || translations.unknown_artist)}</span>
                </a>
                <div class="track-genre">
                    <a href="?genre=${encodeURIComponent(genre)}" class="genre-tag-link">${escapeHtml(genre)}</a>
                    ${mood && mood !== genre && mood.toLowerCase() !== 'neutral' ? `<a href="?genre=${encodeURIComponent(mood)}" class="genre-tag-link">${escapeHtml(mood)}</a>` : ''}
                </div>
                ${createdDate ? `<div class="track-date"><i class="fas fa-calendar-alt"></i><span>${createdDate}</span></div>` : ''}
            </div>
            <div class="track-stats">
                <button class="stat-btn" title="${translations.plays}">
                    <i class="fas fa-headphones-alt"></i>
                    <span>${formatNumber(track.play_count || 0)}</span>
                </button>
                <button class="stat-btn like-btn ${track.user_liked > 0 ? 'liked' : ''}" onclick="toggleLike(${track.id}, this)" title="${translations.likes}">
                    <i class="fas fa-heart"></i>
                    <span>${formatNumber(track.like_count || 0)}</span>
                </button>
                <button class="stat-btn" onclick="showComments(${track.id})" title="${translations.comments}">
                    <i class="fas fa-comment"></i>
                    <span>${formatNumber(track.comment_count || 0)}</span>
                </button>
                <button class="stat-btn" onclick="shareTrack(${track.id})" title="${translations.shares}">
                    <i class="fas fa-share"></i>
                    <span>${formatNumber(track.share_count || 0)}</span>
                </button>
                ${currentUserId ? `
                <button class="stat-btn add-to-crate-btn" onclick="openAddToCrateModal(${track.id}, '${escapeHtml(displayTitle).replace(/'/g, "\\'")}')" title="${translations.add_to_crate}">
                    <i class="fas fa-box"></i>
                </button>
                ` : ''}
                <button class="stat-btn" onclick="showTrackRatingModal(${track.id}, '${escapeHtml(displayTitle).replace(/'/g, "\\'")}')" title="${translations.rate_track}">
                    <i class="fas fa-star" style="color: ${(track.rating_count || 0) > 0 ? '#fbbf24' : 'inherit'};"></i>
                    ${(track.rating_count || 0) > 0 ? `<span>${parseFloat(track.average_rating || 0).toFixed(1)}</span>` : ''}
                </button>
                ${track.variations && track.variations.length > 0 ? `
                <button class="stat-btn variations-btn" onclick="showVariations(${track.id}, this)" title="${track.variations.length} ${translations.variations}">
                    <i class="fas fa-layer-group"></i>
                    <span>${track.variations.length}</span>
                </button>
                ` : ''}
                ${track.user_id && track.user_id != currentUserId ? `
                <button class="stat-btn follow-btn ${track.is_following > 0 ? 'following' : ''}" 
                        onclick="toggleFollow(${track.user_id}, this)"
                        title="${track.is_following > 0 ? translations.unfollow_artist : translations.follow_artist}">
                    <i class="fas fa-${track.is_following > 0 ? 'user-check' : 'user-plus'}"></i>
                </button>
                ` : ''}
            </div>
            <div class="track-cart-section">
                <button class="add-to-cart-btn" type="button" data-track-id="${track.id}" data-track-title="${escapeHtml(displayTitle)}" data-track-price="${displayPrice}" onclick="addToCart(${track.id}, '${escapeHtml(displayTitle)}', ${displayPrice}, this)">
                    <i class="fas fa-shopping-cart"></i>
                    <span>${translations.add_to_cart}</span>
                    <span class="cart-price">${displayPrice > 0 ? '$' + displayPrice.toFixed(2) : translations.free}</span>
                </button>
                <button class="wishlist-inline-btn ${isWishlisted ? 'active' : ''}" onclick="toggleWishlist(${track.id}, this)" aria-pressed="${isWishlisted}" title="${isWishlisted ? translations.remove_from_wishlist : translations.add_to_wishlist}">
                    <i class="${isWishlisted ? 'fas' : 'far'} fa-heart"></i>
                </button>
            </div>
        `;
        
        return card;
    }
    
    // Expose createTrackCard to window for use by updateFilters
    window.createTrackCard = createTrackCard;
    
    function escapeHtml(text) {
        const div = document.createElement('div');
        div.textContent = text;
        return div.innerHTML;
    }
    
    function formatDuration(seconds) {
        const mins = Math.floor(seconds / 60);
        const secs = Math.floor(seconds % 60);
        return `${mins}:${secs.toString().padStart(2, '0')}`;
    }
    
    function formatNumber(num) {
        return parseInt(num).toLocaleString();
    }
    
    // Attach play button listeners (matches original behavior with pause support)
    function attachPlayButtonListeners() {
        const playButtons = tracksGrid.querySelectorAll('.play-btn:not([data-listener-attached])');
        playButtons.forEach(button => {
            button.setAttribute('data-listener-attached', 'true');
            button.addEventListener('click', function(e) {
                e.preventDefault();
                e.stopPropagation();
                e.stopImmediatePropagation();
                
                const trackId = this.getAttribute('data-track-id');
                const artistId = this.getAttribute('data-artist-id');
                const audioUrl = this.getAttribute('data-audio-url');
                const title = this.getAttribute('data-title');
                const artist = this.getAttribute('data-artist');
                const isCurrentlyPlaying = this.classList.contains('playing');
                
                console.log('đŸŽĩ Infinite scroll play button clicked:', { trackId, artistId, audioUrl, title, artist, isCurrentlyPlaying });
                
                // Validate audio URL
                if (!audioUrl || audioUrl === 'null' || audioUrl === 'NULL' || audioUrl === '') {
                    console.error('❌ Invalid audio URL:', audioUrl);
                    alert('This track is not available for playback.');
                    return;
                }
                
                // If button is already in playing state, pause instead
                if (isCurrentlyPlaying) {
                    if (window.waitForGlobalPlayer) {
                        window.waitForGlobalPlayer(function() {
                            if (window.enhancedGlobalPlayer) {
                                // Check if global player has togglePlayPause or pause method
                                if (typeof window.enhancedGlobalPlayer.togglePlayPause === 'function') {
                                    console.log('đŸŽĩ Pausing via togglePlayPause');
                                    window.enhancedGlobalPlayer.togglePlayPause();
                                } else if (typeof window.enhancedGlobalPlayer.pause === 'function') {
                                    console.log('đŸŽĩ Pausing via pause method');
                                    window.enhancedGlobalPlayer.pause();
                                }
                                
                                // Update button state
                                button.classList.remove('playing');
                                const icon = button.querySelector('i');
                                if (icon) icon.className = 'fas fa-play';
                                
                                // Clear other playing states
                                document.querySelectorAll('.play-btn').forEach(btn => {
                                    if (btn !== button) {
                                        btn.classList.remove('playing');
                                        const btnIcon = btn.querySelector('i');
                                        if (btnIcon) btnIcon.className = 'fas fa-play';
                                    }
                                });
                            }
                        });
                    }
                    return;
                }
                
                // Clear other playing states
                document.querySelectorAll('.play-btn').forEach(btn => {
                    btn.classList.remove('playing');
                    const icon = btn.querySelector('i');
                    if (icon) icon.className = 'fas fa-play';
                });
                
                // Set this button as playing
                this.classList.add('playing');
                const icon = this.querySelector('i');
                if (icon) icon.className = 'fas fa-pause';
                
                // Play track using global player
                // Ensure audio URL is absolute if it's relative
                // Signed URLs are already in format /utils/play_audio.php?id=X&variation=Y&token=Z&expires=W
                let finalAudioUrl = audioUrl;
                if (audioUrl && !audioUrl.startsWith('http') && !audioUrl.startsWith('//')) {
                    if (audioUrl.startsWith('/')) {
                        // Preserve query parameters for signed URLs
                        finalAudioUrl = window.location.origin + audioUrl;
                    } else {
                        finalAudioUrl = window.location.origin + '/' + audioUrl;
                    }
                    console.log('đŸŽĩ Converted relative URL to absolute:', finalAudioUrl);
                } else if (audioUrl && audioUrl.startsWith('//')) {
                    // Handle protocol-relative URLs
                    finalAudioUrl = window.location.protocol + audioUrl;
                    console.log('đŸŽĩ Converted protocol-relative URL:', finalAudioUrl);
                }
                
                if (!finalAudioUrl || finalAudioUrl.trim() === '') {
                    console.error('❌ Audio URL is empty!', { audioUrl, finalAudioUrl });
                    alert('Audio file not available.');
                    button.classList.remove('playing');
                    if (icon) icon.className = 'fas fa-play';
                    return;
                }
                
                // Log the final URL for debugging
                console.log('đŸŽĩ Final audio URL (infinite scroll):', finalAudioUrl);
                
                if (window.waitForGlobalPlayer) {
                    window.waitForGlobalPlayer(function() {
                        if (window.enhancedGlobalPlayer && typeof window.enhancedGlobalPlayer.playTrack === 'function') {
                            try {
                                // Build and load playlist before playing
                                const buildFn = window.buildCommunityPlaylist || buildCommunityPlaylist;
                                const communityPlaylist = buildFn ? buildFn() : [];
                                if (communityPlaylist.length > 0) {
                                    // Find the index of the clicked track
                                    const clickedTrackId = parseInt(trackId);
                                    const trackIndex = communityPlaylist.findIndex(t => t.id === clickedTrackId);
                                    const startIndex = trackIndex !== -1 ? trackIndex : 0;
                                    
                                    // Load playlist into global player
                                    if (typeof window.enhancedGlobalPlayer.loadPagePlaylist === 'function') {
                                        window.enhancedGlobalPlayer.loadPagePlaylist(communityPlaylist, 'community_fixed', startIndex);
                                        console.log('đŸŽĩ Community: Playlist loaded via loadPagePlaylist, index:', startIndex, 'of', communityPlaylist.length);
                                    } else {
                                        // Fallback to window storage
                                        window._communityPlaylist = communityPlaylist;
                                        window._communityPlaylistType = 'community_fixed';
                                        window._communityTrackIndex = startIndex;
                                        console.log('đŸŽĩ Community: Playlist stored on window, index:', startIndex, 'of', communityPlaylist.length);
                                    }
                                }
                                
                                console.log('đŸŽĩ Playing track:', { finalAudioUrl, title, artist, trackId, artistId });
                                const success = window.enhancedGlobalPlayer.playTrack(finalAudioUrl, title, artist, trackId, artistId);
                                
                                if (success) {
                                    console.log('✅ Track playing successfully');
                                    if (trackId) recordTrackPlay(trackId);
                                } else {
                                    console.error('❌ playTrack returned false');
                                    alert('Failed to play track.');
                                    // Reset button
                                    button.classList.remove('playing');
                                    if (icon) icon.className = 'fas fa-play';
                                }
                            } catch (error) {
                                console.error('❌ Error:', error);
                                alert('Error: ' + error.message);
                                // Reset button
                                button.classList.remove('playing');
                                if (icon) icon.className = 'fas fa-play';
                            }
                        } else {
                            console.error('❌ Global player not available');
                            alert('Player not ready. Please refresh.');
                            // Reset button
                            button.classList.remove('playing');
                            if (icon) icon.className = 'fas fa-play';
                        }
                    });
                } else {
                    // Fallback
                    setTimeout(function() {
                        if (window.enhancedGlobalPlayer && typeof window.enhancedGlobalPlayer.playTrack === 'function') {
                            // Build and load playlist
                            const communityPlaylist = buildCommunityPlaylist();
                            if (communityPlaylist.length > 0) {
                                const clickedTrackId = parseInt(trackId);
                                const trackIndex = communityPlaylist.findIndex(t => t.id === clickedTrackId);
                                const startIndex = trackIndex !== -1 ? trackIndex : 0;
                                
                                if (typeof window.enhancedGlobalPlayer.loadPagePlaylist === 'function') {
                                    window.enhancedGlobalPlayer.loadPagePlaylist(communityPlaylist, 'community_fixed', startIndex);
                                } else {
                                    window._communityPlaylist = communityPlaylist;
                                    window._communityPlaylistType = 'community_fixed';
                                    window._communityTrackIndex = startIndex;
                                }
                            }
                            
                            window.enhancedGlobalPlayer.playTrack(finalAudioUrl, title, artist, trackId, artistId);
                            if (trackId) recordTrackPlay(trackId);
                        } else {
                            alert('Audio player not ready. Please refresh the page.');
                            button.classList.remove('playing');
                            if (icon) icon.className = 'fas fa-play';
                        }
                    }, 500);
                }
            });
        });
    }
    
    // Expose attachPlayButtonListeners to window for use by updateFilters
    window.attachPlayButtonListeners = attachPlayButtonListeners;
    
    // Scroll detection
    function handleScroll() {
        if (isLoading || !hasMore) return;
        
        const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
        const windowHeight = window.innerHeight;
        const documentHeight = document.documentElement.scrollHeight;
        
        // Load more when user is 300px from bottom
        if (scrollTop + windowHeight >= documentHeight - 300) {
            loadMoreTracks();
        }
    }
    
    // Throttle scroll events
    let scrollTimeout;
    window.addEventListener('scroll', function() {
        if (scrollTimeout) {
            clearTimeout(scrollTimeout);
        }
        scrollTimeout = setTimeout(handleScroll, 100);
    });
    
    // Listen for filter updates to sync infinite scroll state
    document.addEventListener('filtersUpdated', function(e) {
        if (e.detail) {
            currentPage = e.detail.currentPage || 1;
            hasMore = e.detail.hasMore !== undefined ? e.detail.hasMore : true;
            isLoading = false;
            if (tracksGrid) {
                tracksGrid.setAttribute('data-current-page', currentPage.toString());
                tracksGrid.setAttribute('data-has-more', hasMore ? 'true' : 'false');
            }
            if (loader) loader.style.display = 'none';
            if (endOfResults) {
                endOfResults.style.display = hasMore ? 'none' : 'block';
            }
            console.log('đŸŽĩ Infinite scroll state updated after filter change:', { currentPage, hasMore });
        }
    });
    
    // Reset on filter change - wrap updateFilters to reset infinite scroll state
    const originalUpdateFilters = window.updateFilters;
    window.updateFilters = function() {
        // Reset infinite scroll state before calling the AJAX update
        currentPage = 1;
        hasMore = true;
        isLoading = false;
        if (tracksGrid) {
            tracksGrid.setAttribute('data-current-page', '1');
            tracksGrid.setAttribute('data-has-more', 'true');
        }
        if (loader) loader.style.display = 'none';
        if (endOfResults) endOfResults.style.display = 'none';
        
        // Call original function (which now uses AJAX)
        if (originalUpdateFilters) {
            originalUpdateFilters();
        }
    };
})();
</script>

<?php if ($user_id): ?>
<!-- Add to Crate Modal -->
<div id="addToCrateModal" class="modal-overlay" style="display: none;">
    <div class="modal-content" style="max-width: 400px;">
        <div class="modal-header">
            <h3><i class="fas fa-box"></i> <?= t('library.crates.add_to_crate') ?></h3>
            <button class="modal-close" onclick="closeAddToCrateModal()">&times;</button>
        </div>
        <div class="modal-body">
            <p id="addToCrateTrackTitle" style="color: #a5b4fc; margin-bottom: 1rem;"></p>
            <div id="cratesList" style="max-height: 300px; overflow-y: auto;">
                <div style="text-align: center; padding: 2rem;">
                    <i class="fas fa-spinner fa-spin"></i> <?= t('library.crates.loading') ?>
                </div>
            </div>
        </div>
        <div class="modal-footer">
            <button class="btn btn-secondary" onclick="closeAddToCrateModal()"><?= t('common.cancel') ?></button>
            <a href="/library.php?tab=crates" class="btn btn-primary" style="text-decoration: none;">
                <i class="fas fa-plus"></i> <?= t('library.crates.create_new') ?>
            </a>
        </div>
    </div>
</div>

<style>
#addToCrateModal.modal-overlay {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 0.85);
    backdrop-filter: blur(8px);
    z-index: 10000;
    display: flex;
    align-items: center;
    justify-content: center;
}
#addToCrateModal .modal-content {
    background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
    border-radius: 16px;
    padding: 0;
    max-width: 400px;
    width: 90%;
    max-height: 80vh;
    overflow: hidden;
    box-shadow: 0 25px 50px rgba(0, 0, 0, 0.5);
    border: 1px solid rgba(255, 255, 255, 0.1);
}
#addToCrateModal .modal-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 1.5rem;
    border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
#addToCrateModal .modal-header h3 { margin: 0; color: white; font-size: 1.25rem; }
#addToCrateModal .modal-close {
    background: none;
    border: none;
    color: #9ca3af;
    font-size: 1.5rem;
    cursor: pointer;
    padding: 0;
    line-height: 1;
}
#addToCrateModal .modal-close:hover { color: white; }
#addToCrateModal .modal-body { padding: 1.5rem; }
#addToCrateModal .modal-footer {
    display: flex;
    justify-content: flex-end;
    gap: 1rem;
    padding: 1rem 1.5rem;
    border-top: 1px solid rgba(255, 255, 255, 0.1);
}
#addToCrateModal .crate-option {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 1rem;
    background: rgba(255,255,255,0.05);
    border-radius: 8px;
    margin-bottom: 0.5rem;
    cursor: pointer;
    transition: all 0.2s ease;
}
#addToCrateModal .crate-option:hover { background: rgba(102, 126, 234, 0.2); }
#addToCrateModal .crate-option .crate-info { display: flex; align-items: center; gap: 0.75rem; }
#addToCrateModal .crate-option .crate-icon { font-size: 1.5rem; }
#addToCrateModal .crate-option .crate-name { font-weight: 600; color: white; }
#addToCrateModal .crate-option .crate-count { font-size: 0.85rem; color: #9ca3af; }
#addToCrateModal .crate-option.adding { opacity: 0.6; pointer-events: none; }
.add-to-crate-btn { color: #a5b4fc !important; }
.add-to-crate-btn:hover { color: #667eea !important; }
</style>

<script>
let currentTrackIdForCrate = null;
let currentTrackTitleForCrate = null;

function openAddToCrateModal(trackId, trackTitle) {
    currentTrackIdForCrate = trackId;
    currentTrackTitleForCrate = trackTitle;
    
    const modal = document.getElementById('addToCrateModal');
    const titleEl = document.getElementById('addToCrateTrackTitle');
    
    if (!modal) return;
    
    titleEl.textContent = '"' + trackTitle + '"';
    modal.style.display = 'flex';
    document.body.style.overflow = 'hidden';
    
    loadUserCratesForModal();
}

function closeAddToCrateModal() {
    const modal = document.getElementById('addToCrateModal');
    if (modal) {
        modal.style.display = 'none';
        document.body.style.overflow = '';
    }
    currentTrackIdForCrate = null;
}

function loadUserCratesForModal() {
    const cratesList = document.getElementById('cratesList');
    cratesList.innerHTML = '<div style="text-align: center; padding: 2rem;"><i class="fas fa-spinner fa-spin"></i> <?= t('library.crates.loading') ?></div>';
    
    fetch('/api/get_user_crates.php')
        .then(response => response.json())
        .then(data => {
            if (data.success && data.crates && data.crates.length > 0) {
                cratesList.innerHTML = data.crates.map(crate => `
                    <div class="crate-option" onclick="addTrackToCrateFromModal(${crate.id}, '${(crate.name || '').replace(/'/g, "\\'")}')">
                        <div class="crate-info">
                            <span class="crate-icon">đŸ“Ļ</span>
                            <div>
                                <div class="crate-name">${escapeHtml(crate.name)}</div>
                                <div class="crate-count">${crate.track_count || 0} <?= t('library.crates.tracks') ?></div>
                            </div>
                        </div>
                        <i class="fas fa-plus" style="color: #667eea;"></i>
                    </div>
                `).join('');
            } else {
                cratesList.innerHTML = '<div style="text-align: center; padding: 2rem; color: #9ca3af;"><?= t('library.crates.no_crates') ?></div>';
            }
        })
        .catch(error => {
            console.error('Error loading crates:', error);
            cratesList.innerHTML = '<div style="text-align: center; padding: 2rem; color: #ef4444;">Error loading crates</div>';
        });
}

function addTrackToCrateFromModal(crateId, crateName) {
    const crateOption = event.currentTarget;
    crateOption.classList.add('adding');
    crateOption.innerHTML = '<div class="crate-info"><i class="fas fa-spinner fa-spin"></i> Adding...</div>';
    
    fetch('/api/add_track_to_crate.php', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ crate_id: crateId, track_id: currentTrackIdForCrate })
    })
    .then(response => response.json())
    .then(data => {
        if (data.success) {
            if (typeof showNotification === 'function') {
                showNotification('<?= t('library.crates.track_added_to') ?>'.replace(':crate', crateName), 'success');
            }
            closeAddToCrateModal();
        } else {
            if (typeof showNotification === 'function') {
                showNotification(data.error || 'Failed to add track', 'error');
            }
            loadUserCratesForModal();
        }
    })
    .catch(error => {
        console.error('Error:', error);
        loadUserCratesForModal();
    });
}

document.addEventListener('keydown', e => { if (e.key === 'Escape') closeAddToCrateModal(); });
document.getElementById('addToCrateModal')?.addEventListener('click', function(e) { if (e.target === this) closeAddToCrateModal(); });
</script>
<?php endif; ?>

<?php include 'includes/footer.php'; ?>

<!-- Play button event listeners - like other working pages -->
<script>
// Setup play button event listeners
document.addEventListener('DOMContentLoaded', function() {
    console.log('đŸŽĩ Setting up play button listeners');
    
    // Main track play buttons
    const playButtons = document.querySelectorAll('.play-btn, .variation-play-btn');
    console.log('đŸŽĩ Found', playButtons.length, 'play buttons');
    
    playButtons.forEach(button => {
        button.addEventListener('click', function(e) {
            e.preventDefault();
            e.stopPropagation();
            e.stopImmediatePropagation();
            
            const trackId = this.getAttribute('data-track-id');
            const artistId = this.getAttribute('data-artist-id');
            const audioUrl = this.getAttribute('data-audio-url');
            const title = this.getAttribute('data-title');
            const artist = this.getAttribute('data-artist');
            const isCurrentlyPlaying = this.classList.contains('playing');
            
            console.log('đŸŽĩ Play button clicked:', { trackId, artistId, audioUrl, title, artist, isCurrentlyPlaying });
            
            // Validate
            if (!audioUrl || audioUrl === 'null' || audioUrl === 'NULL' || audioUrl === '') {
                console.error('❌ Invalid audio URL:', audioUrl);
                alert('This track is not available for playback.');
                return;
            }
            
            // If button is already in playing state, pause instead
            if (isCurrentlyPlaying) {
                if (window.waitForGlobalPlayer) {
                    window.waitForGlobalPlayer(function() {
                        if (window.enhancedGlobalPlayer) {
                            // Check if global player has togglePlayPause or pause method
                            if (typeof window.enhancedGlobalPlayer.togglePlayPause === 'function') {
                                console.log('đŸŽĩ Pausing via togglePlayPause');
                                window.enhancedGlobalPlayer.togglePlayPause();
                            } else if (typeof window.enhancedGlobalPlayer.pause === 'function') {
                                console.log('đŸŽĩ Pausing via pause method');
                                window.enhancedGlobalPlayer.pause();
                            }
                            
                            // Update button state
                            button.classList.remove('playing');
                            const icon = button.querySelector('i');
                            if (icon) icon.className = 'fas fa-play';
                            
                            // Clear other playing states
                            playButtons.forEach(btn => {
                                if (btn !== button) {
                                    btn.classList.remove('playing');
                                    const btnIcon = btn.querySelector('i');
                                    if (btnIcon) btnIcon.className = 'fas fa-play';
                                }
                            });
                        }
                    });
                }
                return;
            }
            
            // Clear other playing states
            playButtons.forEach(btn => {
                btn.classList.remove('playing');
                const icon = btn.querySelector('i');
                if (icon) icon.className = 'fas fa-play';
            });
            
            // Set this button as playing
            this.classList.add('playing');
            const icon = this.querySelector('i');
            if (icon) icon.className = 'fas fa-pause';
            
            // Play track using global player
            // Ensure audio URL is absolute if it's relative
            // Signed URLs are already in format /utils/play_audio.php?id=X&variation=Y&token=Z&expires=W
            let finalAudioUrl = audioUrl;
            if (audioUrl && !audioUrl.startsWith('http') && !audioUrl.startsWith('//')) {
                if (audioUrl.startsWith('/')) {
                    // Preserve query parameters for signed URLs
                    finalAudioUrl = window.location.origin + audioUrl;
                } else {
                    finalAudioUrl = window.location.origin + '/' + audioUrl;
                }
                console.log('đŸŽĩ Converted relative URL to absolute:', finalAudioUrl);
            } else if (audioUrl && audioUrl.startsWith('//')) {
                // Handle protocol-relative URLs
                finalAudioUrl = window.location.protocol + audioUrl;
                console.log('đŸŽĩ Converted protocol-relative URL:', finalAudioUrl);
            }
            
            if (!finalAudioUrl || finalAudioUrl.trim() === '') {
                console.error('❌ Audio URL is empty!', { audioUrl, finalAudioUrl });
                alert('Audio file not available.');
                button.classList.remove('playing');
                if (icon) icon.className = 'fas fa-play';
                return;
            }
            
            // Log the final URL for debugging
            console.log('đŸŽĩ Final audio URL:', finalAudioUrl);
            
            if (window.waitForGlobalPlayer) {
                window.waitForGlobalPlayer(function() {
                    if (window.enhancedGlobalPlayer && typeof window.enhancedGlobalPlayer.playTrack === 'function') {
                        try {
                            // Build and load playlist before playing
                            const buildFn = window.buildCommunityPlaylist || buildCommunityPlaylist;
                            const communityPlaylist = buildFn ? buildFn() : [];
                            if (communityPlaylist.length > 0) {
                                // Find the index of the clicked track
                                const clickedTrackId = parseInt(trackId);
                                const trackIndex = communityPlaylist.findIndex(t => t.id === clickedTrackId);
                                const startIndex = trackIndex !== -1 ? trackIndex : 0;
                                
                                // Load playlist into global player
                                if (typeof window.enhancedGlobalPlayer.loadPagePlaylist === 'function') {
                                    window.enhancedGlobalPlayer.loadPagePlaylist(communityPlaylist, 'community_fixed', startIndex);
                                    console.log('đŸŽĩ Community: Playlist loaded via loadPagePlaylist, index:', startIndex, 'of', communityPlaylist.length);
                                } else {
                                    // Fallback to window storage
                                    window._communityPlaylist = communityPlaylist;
                                    window._communityPlaylistType = 'community_fixed';
                                    window._communityTrackIndex = startIndex;
                                    console.log('đŸŽĩ Community: Playlist stored on window, index:', startIndex, 'of', communityPlaylist.length);
                                }
                            }
                            
                            console.log('đŸŽĩ Playing track:', { finalAudioUrl, title, artist, trackId, artistId });
                            const success = window.enhancedGlobalPlayer.playTrack(finalAudioUrl, title, artist, trackId, artistId);
                            
                            if (success) {
                                console.log('✅ Track playing successfully');
                                if (trackId) recordTrackPlay(trackId);
                            } else {
                                console.error('❌ playTrack returned false');
                                alert('Failed to play track.');
                                // Reset button
                                button.classList.remove('playing');
                                if (icon) icon.className = 'fas fa-play';
                            }
                        } catch (error) {
                            console.error('❌ Error:', error);
                            alert('Error: ' + error.message);
                            // Reset button
                            button.classList.remove('playing');
                            if (icon) icon.className = 'fas fa-play';
                        }
                    } else {
                        console.error('❌ Global player not available');
                        alert('Player not ready. Please refresh.');
                        // Reset button
                        button.classList.remove('playing');
                        if (icon) icon.className = 'fas fa-play';
                    }
                });
            } else {
                // Fallback
                setTimeout(function() {
                    if (window.enhancedGlobalPlayer && typeof window.enhancedGlobalPlayer.playTrack === 'function') {
                        // Build and load playlist
                        const buildFn = window.buildCommunityPlaylist || buildCommunityPlaylist;
                        const communityPlaylist = buildFn();
                        if (communityPlaylist.length > 0) {
                            const clickedTrackId = parseInt(trackId);
                            const trackIndex = communityPlaylist.findIndex(t => t.id === clickedTrackId);
                            const startIndex = trackIndex !== -1 ? trackIndex : 0;
                            
                            if (typeof window.enhancedGlobalPlayer.loadPagePlaylist === 'function') {
                                window.enhancedGlobalPlayer.loadPagePlaylist(communityPlaylist, 'community_fixed', startIndex);
                            } else {
                                window._communityPlaylist = communityPlaylist;
                                window._communityPlaylistType = 'community_fixed';
                                window._communityTrackIndex = startIndex;
                            }
                        }
                        
                        window.enhancedGlobalPlayer.playTrack(finalAudioUrl, title, artist, trackId, artistId);
                        if (trackId) recordTrackPlay(trackId);
                    } else {
                        alert('Audio player not ready. Please refresh the page.');
                        button.classList.remove('playing');
                        if (icon) icon.className = 'fas fa-play';
                    }
                }, 500);
            }
        });
    });
    
    console.log('✅ Play button listeners setup complete');
});
</script>



CasperSecurity Mini