![]() 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/ |
<?php
/**
* Unified Subscription Signup Page
* Handles all subscription tiers: Essential, Starter, Pro, Premium
*/
session_start();
require_once 'config/database.php';
require_once __DIR__ . '/includes/translations.php';
// Check if user is logged in
if (!isset($_SESSION['user_id'])) {
header('Location: /auth/login.php?redirect=' . urlencode('/subscribe.php' . (!empty($_SERVER['QUERY_STRING']) ? '?' . $_SERVER['QUERY_STRING'] : '')));
exit;
}
$pdo = getDBConnection();
$plans_config = require __DIR__ . '/config/subscription_plans.php';
// Get plan from query string
$plan_key = $_GET['plan'] ?? 'essential';
// Handle free plan (special case - not in plans_config)
$is_free_plan = ($plan_key === 'free');
if ($is_free_plan) {
$plan = [
'name' => 'Free',
'price' => 0.00,
'tracks_per_month' => 0,
'features' => [
'Purchase tracks from artists',
'Purchase event tickets',
'Access all platform features',
'Basic AI models',
'Personal use license',
'Credit-based system'
],
'target_audience' => 'Free users',
'icon' => 'fa-gift',
'color' => '#9ca3af'
];
$plan_display_name = getPlanLabel('free', 'Free');
} elseif (!isset($plans_config[$plan_key])) {
$plan_key = 'essential';
$plan = $plans_config[$plan_key];
$plan_display_name = getPlanLabel($plan_key, $plan['name']);
} else {
$plan = $plans_config[$plan_key];
$plan_display_name = getPlanLabel($plan_key, $plan['name']);
}
// Get user info
$stmt = $pdo->prepare("SELECT id, name, email, plan, stripe_customer_id FROM users WHERE id = ?");
$stmt->execute([$_SESSION['user_id']]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
// Check if already subscribed
require_once __DIR__ . '/utils/subscription_helpers.php';
$existing_subscription = hasActiveSubscription($_SESSION['user_id']);
$stripe_secret = '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';
// Handle subscription upgrade/downgrade
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['switch_plan']) && $existing_subscription) {
// Check if trying to switch to the same plan
if ($existing_subscription['plan_name'] === $plan_key) {
$error_message = t('subscribe.same_plan_error', ['default' => 'You are already on this plan.']);
} elseif ($plan_key === 'free') {
// SPECIAL CASE: Switching to free plan = canceling subscription
// This voids subscription agreement and forfeits track rights per terms
try {
// Get active subscription
$stmt = $pdo->prepare("SELECT id, stripe_subscription_id, status FROM user_subscriptions WHERE user_id = ? AND status IN ('active', 'trialing') ORDER BY created_at DESC LIMIT 1");
$stmt->execute([$_SESSION['user_id']]);
$sub_data = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$sub_data) {
throw new Exception(t('subscribe.no_active_subscription', ['default' => 'No active subscription found']));
}
$stripe_subscription_id = $sub_data['stripe_subscription_id'];
// Cancel subscription immediately in Stripe
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://api.stripe.com/v1/subscriptions/{$stripe_subscription_id}");
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer ' . $stripe_secret]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(['cancel_at_period_end' => 'false'])); // Cancel immediately
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($http_code === 200) {
// Update database immediately
$pdo->beginTransaction();
// Mark subscription as canceled
$cancel_stmt = $pdo->prepare("
UPDATE user_subscriptions
SET status = 'canceled',
plan_name = 'free',
updated_at = NOW()
WHERE id = ?
");
$cancel_stmt->execute([$sub_data['id']]);
// Set user plan to free
$user_update_stmt = $pdo->prepare("UPDATE users SET plan = 'free' WHERE id = ?");
$user_update_stmt->execute([$_SESSION['user_id']]);
$pdo->commit();
// Log the cancellation
error_log("User {$_SESSION['user_id']} switched to free plan - subscription {$stripe_subscription_id} canceled. Track rights forfeited per terms.");
// Redirect to success page with warning message
header('Location: /manage_subscription.php?canceled_to_free=1');
exit;
} else {
$error_data = json_decode($response, true);
$error_msg = isset($error_data['error']['message']) ? $error_data['error']['message'] : 'Failed to cancel subscription';
throw new Exception($error_msg);
}
} catch (Exception $e) {
error_log("Error canceling subscription for free plan: " . $e->getMessage());
$error_message = $e->getMessage();
}
} else {
$price_id = $plan['stripe_price_id'] ?? '';
$is_placeholder = (
empty($price_id) ||
$price_id === 'price_essential_monthly' ||
strpos($price_id, 'YOUR_PRICE_ID') !== false ||
strpos($price_id, 'price_') === false ||
strlen($price_id) < 20
);
if ($is_placeholder) {
$error_message = t('subscribe.setup_required', ['plan' => $plan_display_name]);
} else {
try {
// Get ALL active subscriptions to check for duplicates
$stmt = $pdo->prepare("SELECT id, stripe_subscription_id, status, plan_name, created_at FROM user_subscriptions WHERE user_id = ? AND status IN ('active', 'trialing') ORDER BY created_at DESC");
$stmt->execute([$_SESSION['user_id']]);
$all_active_subs = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (empty($all_active_subs)) {
throw new Exception(t('subscribe.no_active_subscription', ['default' => 'No active subscription found']));
}
// Get the most recent active subscription to update
$sub_data = $all_active_subs[0];
// Validate subscription status
if (!in_array($sub_data['status'], ['active', 'trialing'])) {
throw new Exception(t('subscribe.invalid_subscription_status', ['default' => 'Your subscription is not in a valid state for switching plans.']));
}
$stripe_subscription_id = $sub_data['stripe_subscription_id'];
// Cancel any OLD active subscriptions (keep only the most recent one)
if (count($all_active_subs) > 1) {
error_log("User {$_SESSION['user_id']} has multiple active subscriptions. Canceling old ones.");
for ($i = 1; $i < count($all_active_subs); $i++) {
$old_sub = $all_active_subs[$i];
$old_stripe_id = $old_sub['stripe_subscription_id'];
// Cancel old subscription in Stripe
try {
$cancel_ch = curl_init();
curl_setopt($cancel_ch, CURLOPT_URL, "https://api.stripe.com/v1/subscriptions/{$old_stripe_id}");
curl_setopt($cancel_ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer ' . $stripe_secret]);
curl_setopt($cancel_ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($cancel_ch, CURLOPT_POST, true);
curl_setopt($cancel_ch, CURLOPT_POSTFIELDS, http_build_query(['cancel_at_period_end' => 'false'])); // Cancel immediately
$cancel_response = curl_exec($cancel_ch);
$cancel_http = curl_getinfo($cancel_ch, CURLINFO_HTTP_CODE);
curl_close($cancel_ch);
if ($cancel_http === 200) {
// Update database to mark as canceled
$cancel_stmt = $pdo->prepare("UPDATE user_subscriptions SET status = 'canceled', updated_at = NOW() WHERE id = ?");
$cancel_stmt->execute([$old_sub['id']]);
error_log("Canceled old subscription {$old_stripe_id} for user {$_SESSION['user_id']}");
} else {
error_log("Failed to cancel old subscription {$old_stripe_id}: HTTP {$cancel_http}");
}
} catch (Exception $cancel_e) {
error_log("Error canceling old subscription {$old_stripe_id}: " . $cancel_e->getMessage());
}
}
}
// Get current subscription from Stripe to find subscription item ID
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://api.stripe.com/v1/subscriptions/{$stripe_subscription_id}");
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer ' . $stripe_secret]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($http_code !== 200) {
$error_data = json_decode($response, true);
$error_msg = isset($error_data['error']['message']) ? $error_data['error']['message'] : 'Failed to retrieve subscription from Stripe';
throw new Exception($error_msg);
}
$subscription = json_decode($response, true);
// Validate subscription status in Stripe
if (!in_array($subscription['status'] ?? '', ['active', 'trialing'])) {
throw new Exception(t('subscribe.stripe_subscription_invalid', ['default' => 'Your subscription is not active in Stripe.']));
}
// CRITICAL: Check what plan Stripe currently has BEFORE switching
$current_stripe_price_id = null;
if (isset($subscription['items']['data'][0]['price']['id'])) {
$current_stripe_price_id = $subscription['items']['data'][0]['price']['id'];
}
// Determine current plan in Stripe from price ID
$current_stripe_plan = 'essential'; // Default
if ($current_stripe_price_id) {
foreach ($plans_config as $plan_key => $plan_data) {
if (isset($plan_data['stripe_price_id']) && $plan_data['stripe_price_id'] === $current_stripe_price_id) {
$current_stripe_plan = $plan_key;
break;
}
}
}
// Check if user is already on the target plan in Stripe
if ($current_stripe_plan === $plan_key) {
// User is already on this plan in Stripe - sync database and show error
error_log("User {$_SESSION['user_id']} tried to switch to {$plan_key} but is already on {$current_stripe_plan} in Stripe. Syncing database...");
// Sync database to match Stripe
$sync_stmt = $pdo->prepare("
UPDATE user_subscriptions
SET plan_name = ?,
status = ?,
current_period_start = ?,
current_period_end = ?,
updated_at = NOW()
WHERE stripe_subscription_id = ?
");
$sync_period_start = date('Y-m-d H:i:s', $subscription['current_period_start']);
$sync_period_end = date('Y-m-d H:i:s', $subscription['current_period_end']);
$sync_stmt->execute([
$current_stripe_plan,
$subscription['status'] ?? 'active',
$sync_period_start,
$sync_period_end,
$stripe_subscription_id
]);
// Update user plan
$sync_user_stmt = $pdo->prepare("UPDATE users SET plan = ? WHERE id = ?");
$sync_user_stmt->execute([$current_stripe_plan, $_SESSION['user_id']]);
throw new Exception(t('subscribe.same_plan_error', ['default' => 'You are already on this plan in Stripe. Database has been synced.']));
}
// Get subscription item ID - find the main subscription item (not add-ons)
$subscription_item_id = null;
if (isset($subscription['items']['data']) && is_array($subscription['items']['data'])) {
foreach ($subscription['items']['data'] as $item) {
// Use the first subscription item (main plan)
if (isset($item['id'])) {
$subscription_item_id = $item['id'];
break;
}
}
}
if (!$subscription_item_id) {
throw new Exception(t('subscribe.no_subscription_item', ['default' => 'No subscription item found in Stripe subscription']));
}
// Update subscription to new price
$update_params = [
'items[0][id]' => $subscription_item_id,
'items[0][price]' => $price_id,
'proration_behavior' => 'always_invoice' // Charge prorated amount immediately
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://api.stripe.com/v1/subscriptions/{$stripe_subscription_id}");
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer ' . $stripe_secret]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($update_params));
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($http_code === 200) {
$subscription_response = json_decode($response, true);
// FALLBACK: Update database directly as backup (webhook may be delayed or fail)
// This ensures the database is updated even if webhook doesn't fire immediately
try {
// Determine new plan from price ID
$new_price_id = $subscription_response['items']['data'][0]['price']['id'] ?? null;
$new_plan_name = 'essential'; // Default
if ($new_price_id) {
foreach ($plans_config as $plan_key => $plan_data) {
if (isset($plan_data['stripe_price_id']) && $plan_data['stripe_price_id'] === $new_price_id) {
$new_plan_name = $plan_key;
break;
}
}
}
// Update subscription record directly
$update_stmt = $pdo->prepare("
UPDATE user_subscriptions
SET plan_name = ?,
status = ?,
current_period_start = ?,
current_period_end = ?,
updated_at = NOW()
WHERE stripe_subscription_id = ?
");
$period_start = date('Y-m-d H:i:s', $subscription_response['current_period_start']);
$period_end = date('Y-m-d H:i:s', $subscription_response['current_period_end']);
$update_stmt->execute([
$new_plan_name,
$subscription_response['status'] ?? 'active',
$period_start,
$period_end,
$stripe_subscription_id
]);
// Update user plan
$user_update_stmt = $pdo->prepare("UPDATE users SET plan = ? WHERE id = ?");
$user_update_stmt->execute([$new_plan_name, $_SESSION['user_id']]);
// Update track limit if plan changed
$old_plan_name = $existing_subscription['plan_name'] ?? 'essential';
if ($old_plan_name !== $new_plan_name) {
$track_limit = $plans_config[$new_plan_name]['tracks_per_month'] ?? 5;
$current_period_start = $period_start;
// Get subscription DB ID
$sub_id_stmt = $pdo->prepare("SELECT id FROM user_subscriptions WHERE stripe_subscription_id = ?");
$sub_id_stmt->execute([$stripe_subscription_id]);
$sub_db_record = $sub_id_stmt->fetch(PDO::FETCH_ASSOC);
$subscription_db_id = $sub_db_record['id'] ?? null;
if ($subscription_db_id) {
$usage_stmt = $pdo->prepare("
UPDATE monthly_track_usage
SET track_limit = ?,
updated_at = NOW()
WHERE user_id = ? AND subscription_id = ? AND subscription_period_start = ?
");
$usage_stmt->execute([
$track_limit,
$_SESSION['user_id'],
$subscription_db_id,
$current_period_start
]);
error_log("Direct update: Plan changed from {$old_plan_name} to {$new_plan_name}, track limit updated to {$track_limit} for user {$_SESSION['user_id']}");
}
}
error_log("Direct database update successful for subscription {$stripe_subscription_id} (user {$_SESSION['user_id']}) - plan: {$new_plan_name}");
} catch (Exception $fallback_error) {
// Log but don't fail - webhook will handle it
error_log("Fallback database update failed (webhook will handle): " . $fallback_error->getMessage());
}
// Success - database updated directly, webhook will also update (idempotent)
$_SESSION['subscription_switch_success'] = true;
header('Location: /manage_subscription.php?switched=1');
exit;
} else {
$error_data = json_decode($response, true);
$error_message = isset($error_data['error']['message']) ? $error_data['error']['message'] : t('subscribe.switch_failed', ['default' => 'Failed to update subscription']);
error_log("Stripe subscription update error (HTTP $http_code): " . $response);
throw new Exception($error_message);
}
} catch (Exception $e) {
error_log("Subscription switch error: " . $e->getMessage());
$error_message = $e->getMessage();
}
}
}
}
// Handle subscription creation
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['create_subscription'])) {
// Check if price ID is configured
$price_id = $plan['stripe_price_id'] ?? '';
$is_placeholder = (
empty($price_id) ||
$price_id === 'price_essential_monthly' ||
strpos($price_id, 'YOUR_PRICE_ID') !== false ||
strpos($price_id, 'price_') === false ||
strlen($price_id) < 20 // Real Stripe price IDs are longer
);
if ($is_placeholder) {
$error_message = t('subscribe.setup_required', ['plan' => $plan_display_name]);
error_log("Subscription error: Price ID not configured for plan '{$plan_key}'. Current value: '{$price_id}'");
} else {
// HIGH PRIORITY FIX: Check if user already has an active subscription
$existing_subscription = hasActiveSubscription($_SESSION['user_id']);
if ($existing_subscription && in_array($existing_subscription['status'], ['active', 'trialing'])) {
$error_message = t('subscribe.already_subscribed', ['default' => 'You already have an active subscription. Please manage your existing subscription or switch plans instead.']);
error_log("Subscription blocked: User {$_SESSION['user_id']} attempted to create new subscription while having active subscription: {$existing_subscription['stripe_subscription_id']}");
} else {
try {
// Get existing Stripe customer ID if available (optional - Stripe will create one if needed)
$customer_id = !empty($user['stripe_customer_id']) ? $user['stripe_customer_id'] : null;
// Build checkout session parameters
// Stripe requires line_items as array format
$checkout_params = [
'mode' => 'subscription',
'line_items[0][price]' => $price_id,
'line_items[0][quantity]' => 1,
'success_url' => 'https://soundstudiopro.com/subscription_success.php?session_id={CHECKOUT_SESSION_ID}',
'cancel_url' => 'https://soundstudiopro.com/subscribe.php?plan=' . urlencode($plan_key) . '&canceled=1',
'metadata[user_id]' => (string)$user['id'],
'metadata[plan]' => $plan_key
];
// Debug logging
error_log("=== SUBSCRIPTION DEBUG ===");
error_log("Plan Key: {$plan_key}");
error_log("Plan Name: {$plan['name']}");
error_log("Plan Price: \${$plan['price']}");
error_log("Price ID: {$price_id}");
error_log("User ID: {$user['id']}");
error_log("========================");
// Only add customer if we already have one (optional)
if ($customer_id) {
$checkout_params['customer'] = $customer_id;
} else {
// Customer email - Stripe will create customer automatically if customer_id not provided
$checkout_params['customer_email'] = $user['email'];
}
// Create Stripe Checkout Session for subscription
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.stripe.com/v1/checkout/sessions');
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer ' . $stripe_secret]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($checkout_params));
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($http_code === 200) {
$session = json_decode($response, true);
// Debug: Log what Stripe returned
error_log("Stripe Checkout Session Created:");
error_log("Session ID: " . ($session['id'] ?? 'N/A'));
error_log("URL: " . ($session['url'] ?? 'N/A'));
if (isset($session['line_items']['data'][0]['price'])) {
error_log("Price in session: " . $session['line_items']['data'][0]['price']['id']);
error_log("Amount in session: $" . ($session['line_items']['data'][0]['price']['unit_amount'] / 100));
}
if (isset($session['url'])) {
header('Location: ' . $session['url']);
exit;
} else {
throw new Exception('Invalid response from Stripe: ' . $response);
}
} else {
$error_data = json_decode($response, true);
$error_message = t('subscribe.failed_to_create');
if (isset($error_data['error']['message'])) {
$error_message = $error_data['error']['message'];
} elseif (isset($error_data['error'])) {
$error_message = is_string($error_data['error']) ? $error_data['error'] : 'Stripe API error';
}
// Log the full error for debugging
error_log("Stripe subscription error (HTTP $http_code): " . $response);
error_log("Plan: $plan_key, Price ID: " . ($plan['stripe_price_id'] ?? 'NOT SET'));
throw new Exception($error_message);
}
} catch (Exception $e) {
error_log("Subscription creation error: " . $e->getMessage());
$error_message = $e->getMessage();
}
} // End else block for existing subscription check
}
}
/**
* Translate a plan feature string
*/
function translateFeature($feature) {
// Extract number from "X tracks per month" format
if (preg_match('/^(\d+)\s+tracks\s+per\s+month$/i', $feature, $matches)) {
return t('plan.feature.tracks_per_month', ['count' => $matches[1]]);
}
// Map exact feature strings to translation keys
$featureMap = [
'Monthly reset' => 'plan.feature.monthly_reset',
'Basic AI models' => 'plan.feature.basic_ai_models',
'Advanced AI models' => 'plan.feature.advanced_ai_models',
'Standard generation speed' => 'plan.feature.standard_speed',
'High-speed generation' => 'plan.feature.high_speed',
'Priority queue access' => 'plan.feature.priority_queue',
'Highest priority queue' => 'plan.feature.highest_priority',
'Personal use license' => 'plan.feature.personal_license',
'Commercial use license' => 'plan.feature.commercial_license',
'Unlimited downloads' => 'plan.feature.unlimited_downloads',
'API access' => 'plan.feature.api_access',
'Full API access' => 'plan.feature.full_api_access',
'Dedicated support' => 'plan.feature.dedicated_support',
'White-label options' => 'plan.feature.white_label',
'Dedicated account manager' => 'plan.feature.account_manager',
'Custom integrations' => 'plan.feature.custom_integrations',
'SLA guarantee' => 'plan.feature.sla_guarantee',
'Cancel anytime' => 'plan.feature.cancel_anytime',
];
// Return translated feature if mapping exists, otherwise return original
if (isset($featureMap[$feature])) {
return t($featureMap[$feature]);
}
// Fallback to original if no translation found
return $feature;
}
$page_title = t('subscribe.page_title', ['plan' => $plan_display_name]);
include 'includes/header.php';
?>
<style>
.subscribe-container {
max-width: 900px;
margin: 40px auto;
padding: 20px;
}
.subscribe-header {
text-align: center;
margin-bottom: 40px;
}
.subscribe-header h1 {
font-size: 3rem;
color: white;
margin-bottom: 10px;
font-weight: 700;
}
.subscribe-header p {
color: #a0aec0;
font-size: 1.2rem;
}
.current-subscription-card {
background: linear-gradient(135deg, rgba(72, 187, 120, 0.1) 0%, rgba(72, 187, 120, 0.05) 100%);
border: 2px solid rgba(72, 187, 120, 0.3);
border-radius: 20px;
padding: 35px;
margin-bottom: 30px;
backdrop-filter: blur(10px);
position: relative;
overflow: hidden;
}
.current-subscription-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4px;
background: linear-gradient(90deg, #48bb78 0%, #38a169 100%);
}
.subscription-status {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 25px;
}
.subscription-status-icon {
font-size: 1.5rem;
color: #48bb78;
}
.subscription-status-text {
color: #48bb78;
font-size: 1.2rem;
font-weight: 600;
}
.subscription-info-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 20px;
margin-bottom: 30px;
padding: 20px 0;
border-top: 1px solid rgba(255, 255, 255, 0.1);
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.info-item {
text-align: left;
}
.info-label {
color: #a0aec0;
font-size: 0.9rem;
margin-bottom: 5px;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.info-value {
color: white;
font-size: 1.1rem;
font-weight: 600;
}
.switch-section {
background: rgba(255, 255, 255, 0.03);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 16px;
padding: 30px;
margin-top: 30px;
text-align: center;
}
.switch-title {
color: white;
font-size: 1.5rem;
font-weight: 600;
margin-bottom: 15px;
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
}
.switch-title i {
color: <?= $plan['color'] ?>;
font-size: 1.3rem;
}
.switch-button {
position: relative;
background: linear-gradient(135deg, <?= $plan['color'] ?> 0%, <?= $plan['color'] ?>dd 50%, <?= $plan['color'] ?>bb 100%);
color: white;
border: none;
border-radius: 16px;
padding: 18px 48px;
font-size: 1.3rem;
font-weight: 700;
cursor: pointer;
width: 100%;
transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
box-shadow:
0 8px 32px <?= $plan['color'] ?>50,
0 4px 16px <?= $plan['color'] ?>30,
inset 0 1px 0 rgba(255, 255, 255, 0.2);
margin-bottom: 20px;
overflow: hidden;
letter-spacing: 0.5px;
text-transform: none;
}
.switch-button::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
transition: left 0.5s;
}
.switch-button:hover::before {
left: 100%;
}
.switch-button:hover {
transform: translateY(-4px) scale(1.02);
box-shadow:
0 16px 48px <?= $plan['color'] ?>70,
0 8px 24px <?= $plan['color'] ?>50,
inset 0 1px 0 rgba(255, 255, 255, 0.3);
filter: brightness(1.15);
}
.switch-button:active {
transform: translateY(-2px) scale(1.01);
transition: all 0.1s ease;
}
.switch-button i {
transition: transform 0.3s ease;
}
.switch-button:hover i {
transform: translateX(4px);
}
.switch-note {
color: #e2e8f0;
font-size: 1rem;
line-height: 1.7;
margin-top: 20px;
padding: 20px 24px;
background: linear-gradient(135deg, rgba(255, 255, 255, 0.05) 0%, rgba(255, 255, 255, 0.02) 100%);
backdrop-filter: blur(10px);
border-radius: 12px;
border: 1px solid rgba(255, 255, 255, 0.1);
border-left: 4px solid <?= $plan['color'] ?>;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);
display: flex;
align-items: flex-start;
gap: 12px;
}
.switch-note i {
color: <?= $plan['color'] ?>;
font-size: 1.2rem;
margin-top: 2px;
flex-shrink: 0;
}
.manage-button {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
gap: 10px;
padding: 16px 32px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #8b5cf6 100%);
color: white;
text-decoration: none;
border-radius: 14px;
font-weight: 600;
font-size: 1.1rem;
transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
margin-top: 24px;
box-shadow:
0 8px 32px rgba(102, 126, 234, 0.4),
0 4px 16px rgba(118, 75, 162, 0.3),
inset 0 1px 0 rgba(255, 255, 255, 0.2);
overflow: hidden;
letter-spacing: 0.3px;
}
.manage-button::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
transition: left 0.5s;
}
.manage-button:hover::before {
left: 100%;
}
.manage-button:hover {
transform: translateY(-3px) scale(1.03);
box-shadow:
0 16px 48px rgba(102, 126, 234, 0.5),
0 8px 24px rgba(118, 75, 162, 0.4),
inset 0 1px 0 rgba(255, 255, 255, 0.3);
filter: brightness(1.1);
}
.manage-button:active {
transform: translateY(-1px) scale(1.01);
transition: all 0.1s ease;
}
.manage-button i {
transition: transform 0.3s ease;
font-size: 1.1rem;
}
.manage-button:hover i {
transform: rotate(90deg);
}
.subscribe-button {
position: relative;
background: linear-gradient(135deg, <?= $plan['color'] ?> 0%, <?= $plan['color'] ?>dd 50%, <?= $plan['color'] ?>bb 100%);
color: white;
border: none;
border-radius: 16px;
padding: 20px 48px;
font-size: 1.4rem;
font-weight: 700;
cursor: pointer;
width: 100%;
transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
box-shadow:
0 8px 32px <?= $plan['color'] ?>50,
0 4px 16px <?= $plan['color'] ?>30,
inset 0 1px 0 rgba(255, 255, 255, 0.2);
overflow: hidden;
letter-spacing: 0.5px;
text-transform: none;
margin-top: 30px;
}
.subscribe-button::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
transition: left 0.5s;
}
.subscribe-button:hover::before {
left: 100%;
}
.subscribe-button:hover {
transform: translateY(-4px) scale(1.02);
box-shadow:
0 16px 48px <?= $plan['color'] ?>70,
0 8px 24px <?= $plan['color'] ?>50,
inset 0 1px 0 rgba(255, 255, 255, 0.3);
filter: brightness(1.15);
}
.subscribe-button:active {
transform: translateY(-2px) scale(1.01);
transition: all 0.1s ease;
}
.subscribe-button i {
transition: transform 0.3s ease;
}
.subscribe-button:hover i {
transform: translateY(-3px) rotate(-15deg);
}
.error-alert {
background: rgba(229, 62, 62, 0.1);
border: 1px solid rgba(229, 62, 62, 0.3);
border-left: 4px solid #e53e3e;
border-radius: 12px;
padding: 20px;
margin-bottom: 20px;
color: #e53e3e;
}
/* Plan Detail Card Styles */
.plan-detail-card {
background: linear-gradient(135deg, rgba(30, 30, 30, 0.98), rgba(20, 20, 20, 0.98));
border-radius: 24px;
padding: 50px;
margin-bottom: 40px;
border: 2px solid <?= $plan['color'] ?>30;
box-shadow:
0 20px 60px rgba(0, 0, 0, 0.6),
0 0 40px <?= $plan['color'] ?>20;
position: relative;
overflow: hidden;
}
.plan-detail-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4px;
background: linear-gradient(90deg, <?= $plan['color'] ?>, <?= $plan['color'] ?>dd, <?= $plan['color'] ?>);
}
.plan-header-section {
text-align: center;
margin-bottom: 40px;
padding-bottom: 30px;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.plan-icon-wrapper {
width: 100px;
height: 100px;
margin: 0 auto 20px;
background: linear-gradient(135deg, <?= $plan['color'] ?>20, <?= $plan['color'] ?>10);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
border: 3px solid <?= $plan['color'] ?>40;
box-shadow: 0 8px 32px <?= $plan['color'] ?>30;
}
.plan-title {
color: white;
font-size: 3rem;
font-weight: 800;
margin: 0 0 10px 0;
background: linear-gradient(135deg, #ffffff, <?= $plan['color'] ?>);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.plan-audience {
color: #a0aec0;
font-size: 1.3rem;
margin: 0;
font-weight: 500;
}
.plan-pricing-section {
text-align: center;
margin-bottom: 40px;
padding: 30px;
background: linear-gradient(135deg, rgba(102, 126, 234, 0.1), rgba(118, 75, 162, 0.1));
border-radius: 16px;
border: 1px solid rgba(102, 126, 234, 0.2);
}
.price-display {
display: flex;
align-items: baseline;
justify-content: center;
gap: 5px;
margin-bottom: 20px;
}
.currency {
font-size: 2rem;
color: <?= $plan['color'] ?>;
font-weight: 600;
}
.amount {
font-size: 5rem;
color: <?= $plan['color'] ?>;
font-weight: 900;
line-height: 1;
}
.period {
font-size: 1.3rem;
color: #a0aec0;
font-weight: 500;
}
.tracks-highlight {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 15px 30px;
background: linear-gradient(135deg, <?= $plan['color'] ?>20, <?= $plan['color'] ?>10);
border-radius: 12px;
border: 2px solid <?= $plan['color'] ?>40;
}
.tracks-number {
font-size: 2.5rem;
color: <?= $plan['color'] ?>;
font-weight: 800;
}
.tracks-label {
font-size: 1.2rem;
color: white;
font-weight: 600;
}
.plan-features-section {
margin-bottom: 40px;
}
.features-title {
color: white;
font-size: 1.8rem;
font-weight: 700;
margin-bottom: 25px;
display: flex;
align-items: center;
}
.features-list {
list-style: none;
padding: 0;
margin: 0;
display: grid;
gap: 15px;
}
.feature-item {
display: flex;
align-items: flex-start;
gap: 15px;
padding: 18px 20px;
background: rgba(255, 255, 255, 0.03);
border-radius: 12px;
border: 1px solid rgba(255, 255, 255, 0.05);
transition: all 0.3s ease;
}
.feature-item:hover {
background: rgba(255, 255, 255, 0.06);
border-color: <?= $plan['color'] ?>40;
transform: translateX(5px);
}
.feature-item.feature-highlight {
background: linear-gradient(135deg, <?= $plan['color'] ?>15, <?= $plan['color'] ?>08);
border-color: <?= $plan['color'] ?>30;
}
.feature-icon {
color: #48bb78;
font-size: 1.3rem;
flex-shrink: 0;
margin-top: 2px;
}
.feature-text {
color: white;
font-size: 1.1rem;
line-height: 1.6;
flex: 1;
}
.plan-benefits-section {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 20px;
margin-bottom: 40px;
padding: 30px;
background: rgba(15, 15, 15, 0.5);
border-radius: 16px;
}
.benefit-item {
display: flex;
align-items: flex-start;
gap: 15px;
}
.benefit-item i {
font-size: 2rem;
flex-shrink: 0;
margin-top: 5px;
}
.benefit-item strong {
display: block;
color: white;
font-size: 1.1rem;
margin-bottom: 5px;
font-weight: 600;
}
.benefit-item p {
color: #a0aec0;
font-size: 0.95rem;
margin: 0;
line-height: 1.5;
}
.subscribe-form {
margin: 0;
}
.payment-info {
text-align: center;
margin-top: 20px;
padding-top: 20px;
border-top: 1px solid rgba(255, 255, 255, 0.1);
color: #a0aec0;
font-size: 0.95rem;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
}
.payment-info i {
color: #48bb78;
}
@media (max-width: 768px) {
.plan-detail-card {
padding: 30px 20px;
}
.plan-title {
font-size: 2rem;
}
.amount {
font-size: 3.5rem;
}
.plan-benefits-section {
grid-template-columns: 1fr;
}
}
@media (max-width: 768px) {
.subscribe-header h1 {
font-size: 2rem;
}
.subscription-info-grid {
grid-template-columns: 1fr;
}
}
</style>
<main class="subscribe-container">
<div class="subscribe-header">
<h1>🎵 <?= t('subscribe.plan', ['plan' => htmlspecialchars($plan_display_name)]) ?></h1>
<p><?= htmlspecialchars(getPlanAudienceLabel($plan_key, $plan['target_audience'])) ?></p>
</div>
<?php if ($existing_subscription): ?>
<?php
$is_same_plan = $existing_subscription['plan_name'] === $plan_key;
?>
<div class="current-subscription-card">
<div class="subscription-status">
<i class="fas fa-check-circle subscription-status-icon"></i>
<span class="subscription-status-text"><?= t('subscribe.already_subscribed') ?></span>
</div>
<div class="subscription-info-grid">
<div class="info-item">
<div class="info-label"><?= t('subscribe.current_plan') ?></div>
<div class="info-value"><?= htmlspecialchars(getPlanLabel($existing_subscription['plan_name'], ucfirst($existing_subscription['plan_name']))) ?></div>
</div>
<div class="info-item">
<div class="info-label"><?= t('subscribe.status') ?></div>
<div class="info-value" style="color: #48bb78;"><?= ucfirst($existing_subscription['status']) ?></div>
</div>
<div class="info-item">
<div class="info-label"><?= t('subscribe.renews') ?></div>
<div class="info-value"><?= date('M j, Y', strtotime($existing_subscription['current_period_end'])) ?></div>
</div>
</div>
<?php if (!$is_same_plan): ?>
<?php if (isset($error_message)): ?>
<div class="error-alert">
<i class="fas fa-exclamation-circle"></i> <?= htmlspecialchars($error_message) ?>
</div>
<?php endif; ?>
<?php if ($plan_key === 'free'): ?>
<!-- SPECIAL WARNING FOR FREE PLAN - FORFEITS RIGHTS -->
<div class="free-plan-warning" style="background: rgba(255, 193, 7, 0.15); border: 2px solid #ffc107; border-radius: 16px; padding: 30px; margin-bottom: 30px;">
<div style="display: flex; align-items: flex-start; gap: 15px; margin-bottom: 20px;">
<i class="fas fa-exclamation-triangle" style="font-size: 2.5rem; color: #ffc107; flex-shrink: 0;"></i>
<div>
<h3 style="color: #ffc107; font-size: 1.8rem; font-weight: 700; margin: 0 0 10px 0;">
<?= t('subscribe.free_plan_warning_title', ['default' => 'Important: Switching to Free Plan']) ?>
</h3>
<p style="color: #ffc107; font-size: 1.2rem; margin: 0; line-height: 1.6;">
<?= t('subscribe.free_plan_warning_text', ['default' => 'Switching to the Free plan will immediately cancel your subscription and stop all billing.']) ?>
</p>
</div>
</div>
<div style="background: rgba(0, 0, 0, 0.3); padding: 20px; border-radius: 12px; border-left: 4px solid #e53e3e; margin-top: 20px;">
<h4 style="color: #e53e3e; font-size: 1.4rem; font-weight: 700; margin: 0 0 15px 0; display: flex; align-items: center; gap: 10px;">
<i class="fas fa-gavel"></i>
<?= t('subscribe.rights_forfeit_title', ['default' => 'Track Rights Forfeited']) ?>
</h4>
<p style="color: #a0aec0; font-size: 1.1rem; margin: 0 0 15px 0; line-height: 1.7;">
<?= t('subscribe.rights_forfeit_text', ['default' => 'By switching to the Free plan, you forfeit all commercial and subscription-based track rights as per our Terms of Service. Tracks created while on a paid subscription will lose their commercial usage rights.']) ?>
</p>
<ul style="color: #a0aec0; font-size: 1rem; margin: 0; padding-left: 20px; line-height: 1.8;">
<li><?= t('subscribe.rights_forfeit_item1', ['default' => 'Your subscription will be canceled immediately']) ?></li>
<li><?= t('subscribe.rights_forfeit_item2', ['default' => 'All billing will stop']) ?></li>
<li><?= t('subscribe.rights_forfeit_item3', ['default' => 'Commercial track rights will be forfeited']) ?></li>
<li><?= t('subscribe.rights_forfeit_item4', ['default' => 'You will be moved to credit-based system only']) ?></li>
</ul>
</div>
</div>
<?php endif; ?>
<div class="switch-section">
<div class="switch-title">
<i class="fas fa-sync-alt"></i>
<?= t('pricing.switch_to', ['plan' => htmlspecialchars($plan_display_name)]) ?>
</div>
<form method="POST" style="margin: 0;" onsubmit="return confirm('<?= htmlspecialchars($plan_key === 'free' ? t('subscribe.confirm_switch_to_free', ['default' => 'Are you sure you want to switch to the Free plan? This will cancel your subscription immediately and you will forfeit all commercial track rights.']) : t('subscribe.switch_confirm', ['default' => 'Are you sure you want to switch plans?']), ENT_QUOTES) ?>');">
<button type="submit" name="switch_plan" value="1" class="switch-button" style="<?= $plan_key === 'free' ? 'background: linear-gradient(135deg, #e53e3e 0%, #c53030 50%, #9b2c2c 100%);' : '' ?>">
<i class="fas <?= $plan_key === 'free' ? 'fa-times-circle' : 'fa-arrow-right' ?>" style="margin-right: 8px;"></i>
<?= $plan_key === 'free' ? t('subscribe.cancel_to_free', ['default' => 'Cancel Subscription & Switch to Free']) : t('pricing.switch_to', ['plan' => htmlspecialchars($plan_display_name)]) ?>
</button>
</form>
<?php if ($plan_key !== 'free'): ?>
<div class="switch-note">
<i class="fas fa-info-circle"></i>
<span><?= t('subscribe.switch_note') ?></span>
</div>
<?php endif; ?>
</div>
<?php endif; ?>
<a href="/manage_subscription.php" class="manage-button">
<i class="fas fa-cog"></i>
<?= t('subscribe.manage_subscription') ?>
</a>
</div>
<?php else: ?>
<?php if (isset($error_message)): ?>
<div style="background: #5a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 20px;">
<p style="color: #e53e3e;">❌ <?= t('subscribe.error') ?> <?= htmlspecialchars($error_message) ?></p>
</div>
<?php endif; ?>
<?php if ($is_free_plan): ?>
<!-- Free Plan Display -->
<div class="plan-detail-card" style="border-color: #9ca3af30;">
<div class="plan-header-section">
<div class="plan-icon-wrapper" style="background: linear-gradient(135deg, #9ca3af20, #9ca3af10); border-color: #9ca3af40;">
<i class="fas fa-gift" style="font-size: 4rem; color: #9ca3af;"></i>
</div>
<h2 class="plan-title" style="background: linear-gradient(135deg, #ffffff, #9ca3af); -webkit-background-clip: text; -webkit-text-fill-color: transparent;"><?= htmlspecialchars($plan_display_name) ?></h2>
<p class="plan-audience"><?= htmlspecialchars(getPlanAudienceLabel($plan_key, $plan['target_audience'])) ?></p>
</div>
<div class="plan-pricing-section" style="background: linear-gradient(135deg, rgba(156, 163, 175, 0.1), rgba(107, 114, 128, 0.1)); border-color: rgba(156, 163, 175, 0.2);">
<div class="price-display">
<span class="currency" style="color: #9ca3af;">$</span>
<span class="amount" style="color: #9ca3af;">0</span>
<span class="period"><?= t('subscribe.per_month') ?></span>
</div>
<div class="tracks-highlight" style="background: linear-gradient(135deg, #9ca3af20, #9ca3af10); border-color: #9ca3af40;">
<i class="fas fa-music" style="margin-right: 8px; color: #9ca3af;"></i>
<span class="tracks-number" style="color: #9ca3af;">0</span>
<span class="tracks-label"><?= t('subscribe.tracks_per_month') ?></span>
</div>
</div>
<div class="plan-features-section">
<h3 class="features-title">
<i class="fas fa-star" style="margin-right: 10px; color: #9ca3af;"></i>
<?= t('subscribe.plan_features', ['default' => 'Plan Features']) ?>
</h3>
<ul class="features-list">
<?php foreach ($plan['features'] as $index => $feature): ?>
<li class="feature-item">
<div class="feature-icon">
<i class="fas fa-check-circle"></i>
</div>
<span class="feature-text"><?= htmlspecialchars(translateFeature($feature)) ?></span>
</li>
<?php endforeach; ?>
</ul>
</div>
<div style="background: linear-gradient(135deg, rgba(102, 126, 234, 0.15), rgba(118, 75, 162, 0.15)); border: 2px solid rgba(102, 126, 234, 0.3); border-radius: 16px; padding: 30px; margin-bottom: 30px;">
<div style="display: flex; align-items: flex-start; gap: 15px; margin-bottom: 20px;">
<i class="fas fa-star" style="font-size: 1.8rem; color: #667eea; flex-shrink: 0; margin-top: 3px;"></i>
<div>
<h4 style="color: white; font-size: 1.5rem; font-weight: 700; margin: 0 0 10px 0;">
<?= t('subscribe.free_plan_benefits_title', ['default' => 'Full Platform Access']) ?>
</h4>
<p style="color: #a0aec0; font-size: 1.1rem; margin: 0 0 15px 0; line-height: 1.7;">
<?= t('subscribe.free_plan_benefits_text', ['default' => 'Free users enjoy full access to our platform! Buy tracks with credits, purchase event tickets, and use all our services.']) ?>
</p>
</div>
</div>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; margin-bottom: 20px;">
<div style="display: flex; align-items: center; gap: 10px; padding: 12px; background: rgba(255, 255, 255, 0.05); border-radius: 8px;">
<i class="fas fa-music" style="color: #48bb78; font-size: 1.3rem;"></i>
<span style="color: white; font-size: 1rem; font-weight: 600;"><?= t('subscribe.buy_tracks', ['default' => 'Buy Tracks']) ?></span>
</div>
<div style="display: flex; align-items: center; gap: 10px; padding: 12px; background: rgba(255, 255, 255, 0.05); border-radius: 8px;">
<i class="fas fa-ticket-alt" style="color: #48bb78; font-size: 1.3rem;"></i>
<span style="color: white; font-size: 1rem; font-weight: 600;"><?= t('subscribe.buy_tickets', ['default' => 'Buy Tickets']) ?></span>
</div>
<div style="display: flex; align-items: center; gap: 10px; padding: 12px; background: rgba(255, 255, 255, 0.05); border-radius: 8px;">
<i class="fas fa-check-circle" style="color: #48bb78; font-size: 1.3rem;"></i>
<span style="color: white; font-size: 1rem; font-weight: 600;"><?= t('subscribe.all_features', ['default' => 'All Features']) ?></span>
</div>
</div>
<div style="background: rgba(255, 193, 7, 0.1); border-left: 4px solid #ffc107; padding: 15px; border-radius: 8px; margin-top: 20px;">
<p style="color: #ffc107; font-size: 0.95rem; margin: 0; line-height: 1.6;">
<i class="fas fa-info-circle" style="margin-right: 8px;"></i>
<strong><?= t('subscribe.free_plan_terms_title', ['default' => 'Terms:']) ?></strong>
<?= t('subscribe.free_plan_terms_text', ['default' => 'Free plan includes personal use license only. Commercial rights require a paid subscription. See Terms of Service for details.']) ?>
</p>
</div>
</div>
<div style="text-align: center;">
<div style="background: linear-gradient(135deg, rgba(102, 126, 234, 0.1), rgba(118, 75, 162, 0.1)); border: 1px solid rgba(102, 126, 234, 0.3); border-radius: 12px; padding: 1.5rem; margin-bottom: 2rem; max-width: 600px; margin-left: auto; margin-right: auto;">
<p style="color: #667eea; font-size: 1rem; margin: 0 0 10px 0; font-weight: 600;">
<i class="fas fa-info-circle"></i> <?= t('home.credits_subscription_required_title') ?>
</p>
<p style="color: #a0aec0; font-size: 0.9rem; margin: 0;">
<?= t('home.credits_subscription_required_message') ?>
</p>
</div>
<a href="/credits.php" class="subscribe-button" style="display: inline-block; width: auto; padding: 20px 60px; text-decoration: none;">
<i class="fas fa-shopping-cart"></i>
<span><?= t('subscribe.view_credit_packages', ['default' => 'View Credit Packages']) ?></span>
</a>
</div>
</div>
<?php else: ?>
<div class="plan-detail-card">
<div class="plan-header-section">
<div class="plan-icon-wrapper">
<i class="fas <?= $plan['icon'] ?>" style="font-size: 4rem; color: <?= $plan['color'] ?>;"></i>
</div>
<h2 class="plan-title"><?= htmlspecialchars($plan_display_name) ?></h2>
<p class="plan-audience"><?= htmlspecialchars(getPlanAudienceLabel($plan_key, $plan['target_audience'])) ?></p>
</div>
<?php
// Plan-specific persuasive descriptions
$plan_descriptions = [
'essential' => [
'title' => t('subscribe.essential.why_choose_title', ['default' => 'Why Choose Essential?']),
'description' => t('subscribe.essential.why_choose_desc', ['default' => 'Perfect for getting started! Essential gives you everything you need to create professional music at an unbeatable price. Start your creative journey today with 5 tracks per month, commercial licensing, and all the tools you need to bring your ideas to life.']),
'highlights' => [
t('subscribe.essential.highlight_1', ['default' => 'Most affordable entry point']),
t('subscribe.essential.highlight_2', ['default' => 'Perfect for testing the platform']),
t('subscribe.essential.highlight_3', ['default' => 'Upgrade anytime as you grow'])
]
],
'starter' => [
'title' => t('subscribe.starter.why_choose_title', ['default' => 'Why Choose Starter?']),
'description' => t('subscribe.starter.why_choose_desc', ['default' => 'Take your creativity to the next level! Starter is ideal for regular creators who want more tracks and advanced features. With 20 tracks per month, high-speed generation, and priority queue access, you\'ll have everything you need to create consistently.']),
'highlights' => [
t('subscribe.starter.highlight_1', ['default' => '4x more tracks than Essential']),
t('subscribe.starter.highlight_2', ['default' => 'Advanced AI models included']),
t('subscribe.starter.highlight_3', ['default' => 'Perfect for regular creators'])
]
],
'pro' => [
'title' => t('subscribe.pro.why_choose_title', ['default' => 'Why Choose Pro?']),
'description' => t('subscribe.pro.why_choose_desc', ['default' => 'The most popular choice for serious creators! Pro gives you 75 tracks per month, commercial licensing, and most importantly - you keep 85% of all track sales revenue. This is the sweet spot for professional creators who want to monetize their music while having plenty of tracks to work with.']),
'highlights' => [
t('subscribe.pro.highlight_1', ['default' => 'Keep 85% of all sales revenue']),
t('subscribe.pro.highlight_2', ['default' => '75 tracks per month']),
t('subscribe.pro.highlight_3', ['default' => 'Best value for monetizing creators'])
]
],
'premium' => [
'title' => t('subscribe.premium.why_choose_title', ['default' => 'Why Choose Premium?']),
'description' => t('subscribe.premium.why_choose_desc', ['default' => 'For power users and agencies! Premium delivers 200 tracks per month, full API access, and dedicated support. If you\'re creating music at scale or managing multiple projects, Premium gives you the resources and tools to operate like a professional studio.']),
'highlights' => [
t('subscribe.premium.highlight_1', ['default' => '200 tracks per month']),
t('subscribe.premium.highlight_2', ['default' => 'Full API access for automation']),
t('subscribe.premium.highlight_3', ['default' => 'Dedicated support included'])
]
],
'enterprise' => [
'title' => t('subscribe.enterprise.why_choose_title', ['default' => 'Why Choose Enterprise?']),
'description' => t('subscribe.enterprise.why_choose_desc', ['default' => 'The ultimate solution for large-scale operations! Enterprise provides 1000 tracks per month, white-label options, custom integrations, and a dedicated account manager. Perfect for companies, agencies, or creators who need maximum capacity and enterprise-level support.']),
'highlights' => [
t('subscribe.enterprise.highlight_1', ['default' => '1000 tracks per month']),
t('subscribe.enterprise.highlight_2', ['default' => 'Dedicated account manager']),
t('subscribe.enterprise.highlight_3', ['default' => 'Custom integrations available'])
]
]
];
$plan_desc = $plan_descriptions[$plan_key] ?? null;
if ($plan_desc && !$is_free_plan):
?>
<div style="background: linear-gradient(135deg, <?= $plan['color'] ?>15, <?= $plan['color'] ?>08); border: 2px solid <?= $plan['color'] ?>30; border-radius: 16px; padding: 30px; margin-bottom: 30px;">
<h3 style="color: <?= $plan['color'] ?>; font-size: 1.8rem; font-weight: 700; margin: 0 0 15px 0; display: flex; align-items: center; gap: 10px;">
<i class="fas fa-lightbulb"></i>
<?= htmlspecialchars($plan_desc['title']) ?>
</h3>
<p style="color: white; font-size: 1.2rem; line-height: 1.7; margin: 0 0 20px 0;">
<?= htmlspecialchars($plan_desc['description']) ?>
</p>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px;">
<?php foreach ($plan_desc['highlights'] as $highlight): ?>
<div style="display: flex; align-items: center; gap: 10px; padding: 12px; background: rgba(255, 255, 255, 0.05); border-radius: 8px;">
<i class="fas fa-check-circle" style="color: <?= $plan['color'] ?>; font-size: 1.2rem;"></i>
<span style="color: white; font-size: 1rem; font-weight: 500;"><?= htmlspecialchars($highlight) ?></span>
</div>
<?php endforeach; ?>
</div>
</div>
<?php endif; ?>
<div class="plan-pricing-section">
<div class="price-display">
<span class="currency">$</span>
<span class="amount"><?= number_format($plan['price'], 0) ?></span>
<span class="period"><?= t('subscribe.per_month') ?></span>
</div>
<div class="tracks-highlight">
<i class="fas fa-music" style="margin-right: 8px;"></i>
<span class="tracks-number"><?= $plan['tracks_per_month'] ?></span>
<span class="tracks-label"><?= t('subscribe.tracks_per_month') ?></span>
</div>
</div>
<div class="plan-features-section">
<h3 class="features-title">
<i class="fas fa-star" style="margin-right: 10px; color: <?= $plan['color'] ?>;"></i>
<?= t('subscribe.plan_features', ['default' => 'Plan Features']) ?>
</h3>
<ul class="features-list">
<?php foreach ($plan['features'] as $index => $feature): ?>
<li class="feature-item <?= $index < 3 ? 'feature-highlight' : '' ?>">
<div class="feature-icon">
<i class="fas fa-check-circle"></i>
</div>
<span class="feature-text"><?= htmlspecialchars(translateFeature($feature)) ?></span>
</li>
<?php endforeach; ?>
</ul>
</div>
<div class="plan-benefits-section">
<div class="benefit-item">
<i class="fas fa-sync-alt" style="color: <?= $plan['color'] ?>;"></i>
<div>
<strong><?= t('subscribe.monthly_reset', ['default' => 'Monthly Reset']) ?></strong>
<p><?= t('subscribe.monthly_reset_desc', ['default' => 'Your tracks reset every month']) ?></p>
</div>
</div>
<div class="benefit-item">
<i class="fas fa-shield-alt" style="color: <?= $plan['color'] ?>;"></i>
<div>
<strong><?= t('subscribe.cancel_anytime', ['default' => 'Cancel Anytime']) ?></strong>
<p><?= t('subscribe.cancel_anytime_desc', ['default' => 'No long-term commitment']) ?></p>
</div>
</div>
<div class="benefit-item">
<i class="fas fa-headset" style="color: <?= $plan['color'] ?>;"></i>
<div>
<strong><?= t('subscribe.support', ['default' => 'Priority Support']) ?></strong>
<p><?= t('subscribe.support_desc', ['default' => 'Get help when you need it']) ?></p>
</div>
</div>
</div>
<?php if (!$is_free_plan): ?>
<form method="POST" class="subscribe-form">
<button type="submit" name="create_subscription" value="1" class="subscribe-button">
<i class="fas fa-rocket"></i>
<span><?= t('subscribe.subscribe_now', ['price' => number_format($plan['price'], 2)]) ?></span>
</button>
</form>
<div class="payment-info">
<i class="fas fa-lock"></i>
<span><?= t('subscribe.stripe_redirect') ?></span>
</div>
<?php endif; ?>
</div>
<?php endif; ?>
<?php endif; ?>
<div style="margin-top: 30px; padding-top: 30px; border-top: 1px solid #333;">
<a href="/pricing.php" style="color: #667eea; text-decoration: none; margin-right: 20px;"><?= t('subscribe.view_all_plans') ?></a>
<a href="/account_settings.php" style="color: #667eea; text-decoration: none;"><?= t('subscribe.account_settings') ?></a>
</div>
</div>
<?php if ($existing_subscription): ?>
<?php
// Show other upgrade options
$plan_order = ['essential', 'starter', 'pro', 'premium', 'enterprise'];
$plan_levels = ['essential' => 1, 'starter' => 2, 'pro' => 3, 'premium' => 4, 'enterprise' => 5];
$current_plan_level = $plan_levels[$existing_subscription['plan_name']] ?? 0;
$viewing_plan_level = $plan_levels[$plan_key] ?? 0;
// Get higher tier plans (upgrade options)
$upgrade_options = [];
foreach ($plan_order as $option_key) {
$option_level = $plan_levels[$option_key] ?? 0;
// Show plans that are higher than current plan, excluding the one being viewed
if ($option_level > $current_plan_level && $option_key !== $plan_key) {
$upgrade_options[] = $option_key;
}
}
if (!empty($upgrade_options)):
?>
<div style="margin-top: 60px; padding-top: 40px; border-top: 2px solid rgba(102, 126, 234, 0.3);">
<h2 style="color: white; font-size: 2.5rem; text-align: center; margin-bottom: 15px;">
<?= t('subscribe.other_upgrade_options', ['default' => 'Other Upgrade Options']) ?>
</h2>
<p style="color: #a0aec0; text-align: center; font-size: 1.2rem; margin-bottom: 40px;">
<?= t('subscribe.other_upgrade_options_desc', ['default' => 'Explore other plans that might better suit your needs']) ?>
</p>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 30px; max-width: 1200px; margin: 0 auto;">
<?php foreach ($upgrade_options as $option_key):
$option_plan = $plans_config[$option_key];
$option_display_name = getPlanLabel($option_key, $option_plan['name']);
$is_featured = $option_key === 'pro';
?>
<div style="background: #2a2a2a; border-radius: 16px; padding: 30px; text-align: center; position: relative; transition: transform 0.3s, box-shadow 0.3s; border: 2px solid <?= $is_featured ? '#667eea' : 'transparent' ?>;">
<?php if ($is_featured): ?>
<div style="position: absolute; top: -12px; left: 50%; transform: translateX(-50%); background: linear-gradient(135deg, #667eea, #764ba2); color: white; padding: 5px 20px; border-radius: 20px; font-size: 0.85rem; font-weight: 600;">
<?= t('pricing.most_popular') ?>
</div>
<?php endif; ?>
<div style="font-size: 2.5rem; color: <?= $option_plan['color'] ?>; margin-bottom: 15px;">
<i class="fas <?= $option_plan['icon'] ?>"></i>
</div>
<h3 style="color: white; font-size: 1.8rem; font-weight: bold; margin-bottom: 10px;">
<?= htmlspecialchars($option_display_name) ?>
</h3>
<div style="font-size: 3rem; color: <?= $option_plan['color'] ?>; font-weight: 800; margin-bottom: 5px;">
$<?= number_format($option_plan['price'], 2) ?>
</div>
<div style="color: #a0aec0; font-size: 1rem; margin-bottom: 20px;">
<?= t('subscribe.per_month') ?>
</div>
<div style="background: rgba(102, 126, 234, 0.1); padding: 10px; border-radius: 8px; margin-bottom: 25px; color: white; font-size: 1.1rem; font-weight: 600;">
<?= $option_plan['tracks_per_month'] ?> <?= t('subscribe.tracks_per_month') ?>
</div>
<ul style="text-align: left; color: white; list-style: none; padding: 0; margin: 0 0 25px 0; min-height: 150px;">
<?php foreach (array_slice($option_plan['features'], 0, 4) as $feature): ?>
<li style="padding: 8px 0; border-bottom: 1px solid #333; font-size: 0.95rem;">
<i class="fas fa-check" style="color: #48bb78; margin-right: 8px;"></i>
<?= htmlspecialchars(translateFeature($feature)) ?>
</li>
<?php endforeach; ?>
</ul>
<a href="/subscribe.php?plan=<?= $option_key ?>"
style="display: block; padding: 14px 30px; background: <?= $option_plan['color'] ?>; color: white; text-decoration: none; border-radius: 10px; font-size: 1.1rem; font-weight: 600; transition: all 0.3s ease;">
<?= t('pricing.switch_to', ['plan' => htmlspecialchars($option_display_name)]) ?>
</a>
</div>
<?php endforeach; ?>
</div>
</div>
<?php endif; ?>
<?php endif; ?>
</main>
<?php include 'includes/footer.php'; ?>