<?php
// Prop Firm account creation — split out of the old combined add-account.php
// per the Trading Center architectural-separation refactor. This page is
// PROP FIRM ONLY: it never renders Live Account fields/controls.
//
// Session (2026-08-xx, "Add Account / Continue Attempt" merge): this page
// now DOES own the Continue Existing Attempt picker's front door too — the
// Trading Center's per-challenge-type stage grid no longer has its own
// separate "Continue Existing Attempt" tile (see public/trading-center.php);
// that tile was replaced with one combined "Add or Continue" tile pointing
// here, scoped via ?challenge=<type>. This page still does NOT reimplement
// the actual promotion UI (the "Ready to Promote" preview + Promote button)
// — an account picked from the Continue panel below still hands off to
// trading-center.php's existing, untouched Account Home/Promote flow
// (?stage=continue&account_id=X). This page only adds the picker itself,
// scoped to a known challenge type, so a trader doesn't have to browse
// there blind first.
$userId = $auth->requireAuth();

$VALID_CHALLENGE_TYPES = ['one_step', 'two_step', 'three_step', 'instant_funding'];
$challenge = in_array($_GET['challenge'] ?? '', $VALID_CHALLENGE_TYPES, true) ? $_GET['challenge'] : null;
$initialMode = ($_GET['mode'] ?? '') === 'continue' ? 'continue' : 'new';

$tcBackUrl = $challenge
    ? '/traderalign/trading-center?hub=accounts&kind=prop&view=center&challenge=' . urlencode($challenge)
    : '/traderalign/trading-center?hub=accounts&kind=prop';

// Real accounts ready to promote, scoped to $challenge when it's known —
// powers the Continue Existing Attempt panel below. Instant Funding has no
// phase concept (see apPromotableLifecycleStates()), so it never has
// anything to promote and is excluded from the challenge-type picker too.
//
// 2026-08-17 account-level workflow isolation: this call previously never
// passed workflow_state at all, so it silently defaulted to 'main' inside
// apFetchAccounts() REGARDLESS of the requester's actual current workflow —
// a real, live bug (not just an omission): a validating user reaching this
// page (Trading Center's own "Add or Continue Attempt" tile is reachable
// identically from both workflows) would have been shown MAIN-workflow
// accounts ready to promote, the exact inverse of what should render.
$apaWorkflowState = ValidationService::getWorkflowState($userId, $db);
$promotableAccounts = [];
if ($challenge && $challenge !== 'instant_funding') {
    $promotableAccounts = apFetchAccounts($userId, $db, [
        'account_type'   => 'prop',
        'challenge_type' => $challenge,
        'lifecycle_in'   => apPromotableLifecycleStates($challenge),
        'workflow_state' => $apaWorkflowState,
    ]);
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Add Prop Firm Account - TraderAlign</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
<link rel="stylesheet" href="/traderalign/assets/tokens.css">
<link rel="icon" type="image/png" sizes="32x32" href="/traderalign/assets/favicon/favicon-32.png">
    <link rel="icon" type="image/png" sizes="16x16" href="/traderalign/assets/favicon/favicon-16.png">
    <link rel="apple-touch-icon" sizes="180x180" href="/traderalign/assets/favicon/apple-touch-icon.png">
    <link rel="shortcut icon" href="/traderalign/assets/favicon/favicon.ico">
<link rel="stylesheet" href="/traderalign/assets/css/brand.css">
<link rel="stylesheet" href="/traderalign/assets/css/account-picker.css">
<script src="/traderalign/assets/js/account-picker.js"></script>
<style>
.dash-layout{display:flex;min-height:100vh}
.sidebar{width:4rem;background:var(--sidebar);border-right:1px solid var(--sidebar-border);display:flex;flex-direction:column;align-items:center;padding-top:1rem;gap:.25rem;position:fixed;top:0;left:0;bottom:0;z-index:40}
.sidebar a{display:flex;align-items:center;justify-content:center;width:2.75rem;height:2.75rem;border-radius:var(--radius-md);color:var(--foreground-dim);transition:background var(--t-fast),color var(--t-fast);position:relative}
.sidebar a:hover{background:var(--background-surface);color:var(--foreground)}
.sidebar a.active{background:var(--background-surface);color:var(--sidebar-primary)}
.sidebar a .tt{position:absolute;left:3.5rem;background:var(--popover);color:var(--foreground);font-size:.75rem;padding:.25rem .625rem;border-radius:var(--radius-sm);white-space:nowrap;pointer-events:none;opacity:0;transition:opacity var(--t-fast)}
.sidebar a:hover .tt{opacity:1}
.main{margin-left:4rem;flex:1;padding:2.25rem 2rem 5rem;max-width:44rem}
body{background:var(--background);margin:0;background-image:radial-gradient(ellipse 1000px 520px at 8% -10%,color-mix(in srgb,var(--primary) 7%,transparent),transparent 60%);background-attachment:fixed}
.page-title{font-size:1.6rem;font-weight:800;letter-spacing:-.02em;color:var(--foreground);margin-bottom:.2rem}
.page-sub{color:var(--foreground-muted);font-size:.9rem;margin-bottom:1.6rem;line-height:1.5}
.back-link{font-size:.78rem;font-weight:600;color:var(--foreground-dim);margin-bottom:1.1rem;display:inline-flex;align-items:center;gap:.4rem;text-decoration:none;transition:all var(--t-fast);background:var(--background-elevated);border:1px solid var(--border);border-radius:var(--radius-full);padding:.35rem .85rem .35rem .6rem}
.back-link:hover{color:var(--primary);border-color:color-mix(in srgb,var(--primary) 40%,var(--border));transform:translateX(-2px)}

/* Mode selector — two clearly, colorfully separated responsibilities: New
   (blue/primary) vs Continue (gold, matching the "ready to promote" glow
   language already established on the Trading Center stage grid). */
.mode-selector{background:linear-gradient(160deg,color-mix(in srgb,var(--primary) 5%,var(--background-elevated)),var(--background-elevated));border:1px solid var(--border);border-radius:var(--radius-xl);padding:1.5rem;margin-bottom:1.5rem;box-shadow:var(--shadow-md)}
.mode-selector h2{font-size:.98rem;font-weight:800;color:var(--foreground);margin-bottom:.25rem}
.mode-selector p{font-size:.8rem;color:var(--foreground-muted);margin-bottom:1.1rem}
.mode-options{display:flex;gap:1rem}
@media(max-width:640px){.mode-options{flex-direction:column}}
.mode-option{flex:1;position:relative}
.mode-option input[type="radio"]{position:absolute;opacity:0;width:0;height:0}
.mode-option label{display:flex;flex-direction:column;padding:1.1rem 1.15rem;border:2px solid var(--border);border-radius:var(--radius-lg);cursor:pointer;transition:all var(--t-fast);height:100%;background:var(--background-surface)}
.mode-option label:hover{border-color:color-mix(in srgb,var(--foreground-dim) 45%,var(--border))}
.mode-option .mode-icon{font-size:1.3rem;margin-bottom:.5rem}
.mode-option[data-kind="new"] input:checked + label{border-color:var(--primary);background:color-mix(in srgb,var(--primary) 7%,var(--background-surface));box-shadow:0 0 0 1px color-mix(in srgb,var(--primary) 35%,transparent),0 8px 20px -10px color-mix(in srgb,var(--primary) 45%,transparent)}
.mode-option[data-kind="continue"] input:checked + label{border-color:var(--rn-gold,#E0A64A);background:color-mix(in srgb,var(--rn-gold,#E0A64A) 8%,var(--background-surface));box-shadow:0 0 0 1px color-mix(in srgb,var(--rn-gold,#E0A64A) 35%,transparent),0 8px 20px -10px color-mix(in srgb,var(--rn-gold,#E0A64A) 45%,transparent)}
.mode-option .mode-title{font-size:.9rem;font-weight:800;color:var(--foreground);margin-bottom:.3rem}
.mode-option .mode-desc{font-size:.75rem;color:var(--foreground-dim);line-height:1.42}
.mode-count-badge{display:inline-flex;align-items:center;gap:.35rem;font-size:.64rem;font-weight:800;padding:.24rem .6rem;border-radius:var(--radius-full);margin-top:.6rem;width:fit-content}
.mode-count-badge.ready{background:color-mix(in srgb,var(--rn-gold,#E0A64A) 18%,transparent);color:var(--rn-gold,#E0A64A);border:1px solid color-mix(in srgb,var(--rn-gold,#E0A64A) 35%,transparent)}
.mode-count-badge.ready .mcb-dot{width:.38rem;height:.38rem;border-radius:50%;background:currentColor;animation:rn-pulse 1.4s infinite}
.mode-count-badge.none{background:var(--background-elevated);color:var(--foreground-dim);border:1px solid var(--border)}

.form-card{background:var(--background-elevated);border:1px solid var(--border);border-top:3px solid var(--primary);border-radius:var(--radius-xl);padding:1.5rem;box-shadow:var(--shadow-md)}
.field-group{margin-bottom:1.1rem}
.field-group label{display:block;font-size:.72rem;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--foreground-dim);margin-bottom:.4rem}
.field-row{display:flex;gap:.75rem}
.field-row .field-group{flex:1}
input[type="text"], input[type="number"], select{
  width:100%;height:2.5rem;padding:0 .75rem;background:var(--background-surface);
  border:1px solid var(--border);border-radius:var(--radius-md);color:var(--foreground);
  font-family:var(--font-sans);font-size:.9rem;outline:none;transition:border-color var(--t-fast);
}
input:focus, select:focus{border-color:var(--primary)}
.hint{font-size:.7rem;color:var(--foreground-dim);margin-top:.3rem}

.rules-panel{margin-top:.5rem;padding:1rem 1.1rem;background:var(--background-surface);border:1px solid var(--border);border-radius:var(--radius-lg);display:none}
.rules-panel.visible{display:block}
.rules-panel-title{font-size:.74rem;font-weight:700;color:var(--foreground-dim);text-transform:uppercase;letter-spacing:.06em;margin-bottom:.75rem;display:flex;align-items:center;gap:.4rem}
.rules-grid{display:grid;grid-template-columns:1fr 1fr;gap:.75rem}
.rules-grid .field-group{margin-bottom:0}
.optional-tag{font-size:.6rem;font-weight:600;color:var(--foreground-dim);text-transform:none;letter-spacing:0;margin-left:.3rem}
.rules-subsection{margin-top:1.1rem;padding-top:1rem;border-top:1px solid var(--border)}
.rules-subsection-title{font-size:.74rem;font-weight:700;color:var(--foreground-dim);text-transform:uppercase;letter-spacing:.06em;margin-bottom:.3rem}
.rules-subsection-hint{font-size:.72rem;color:var(--foreground-dim);margin-bottom:.6rem;line-height:1.45}

/* Maximum Loss Model selector — compact, minimal buttons (icon + label
   only, no description text, no card padding) — this is the primary
   branch point for the whole rules panel, so it renders first, before
   any numeric field, but it must read as a quick toggle, not a large
   decision card. Selected state is a plain border/background tint, no
   glow/shadow. */
.dd-model-options{display:flex;gap:.6rem;margin-top:.15rem;flex-wrap:wrap}
.dd-model-option{position:relative}
.dd-model-option input[type="radio"]{position:absolute;opacity:0;width:0;height:0}
.dd-model-option label{display:inline-flex;align-items:center;gap:.5rem;padding:.5rem .95rem;border:1.5px solid var(--border);border-radius:var(--radius-md);cursor:pointer;transition:all var(--t-fast);background:var(--background-elevated)}
.dd-model-option label:hover{border-color:color-mix(in srgb,var(--foreground-dim) 45%,var(--border))}
.dd-model-option .dd-model-icon{font-size:.95rem;line-height:1}
.dd-model-option[data-kind="fixed"] input:checked + label{border-color:var(--primary);background:color-mix(in srgb,var(--primary) 10%,var(--background-elevated))}
.dd-model-option[data-kind="trailing"] input:checked + label{border-color:var(--positive,#26A69A);background:color-mix(in srgb,var(--positive,#26A69A) 10%,var(--background-elevated))}
.dd-model-option .dd-model-title{font-size:.8rem;font-weight:700;color:var(--foreground);letter-spacing:.03em;text-transform:uppercase;line-height:1}

.custom-rules-list{display:flex;flex-direction:column;gap:.5rem;margin-top:.75rem}
.custom-rule-row{display:flex;gap:.5rem;align-items:center}
.custom-rule-row input{flex:1}
.remove-rule-btn{width:2rem;height:2.5rem;flex-shrink:0;border-radius:var(--radius-md);border:1px solid var(--border);background:var(--background-elevated);color:var(--foreground-dim);cursor:pointer;display:flex;align-items:center;justify-content:center}
.remove-rule-btn:hover{color:var(--negative);border-color:color-mix(in srgb,var(--negative) 40%,transparent)}
.add-rule-btn{font-size:.78rem;color:var(--primary);background:none;border:none;cursor:pointer;display:flex;align-items:center;gap:.3rem;margin-top:.6rem;padding:0}
.add-rule-btn:hover{text-decoration:underline}

.form-actions{display:flex;gap:.6rem;justify-content:flex-end;margin-top:1.5rem;padding-top:1.25rem;border-top:1px solid var(--border)}
.error-banner{display:none;background:color-mix(in srgb,var(--negative) 10%,transparent);border:1px solid color-mix(in srgb,var(--negative) 30%,transparent);color:var(--negative);border-radius:var(--radius-md);padding:.6rem .8rem;font-size:.82rem;margin-bottom:1rem}
.error-banner.show{display:block}
.preview-label{font-size:.78rem;color:var(--foreground-dim);margin-top:.5rem}
.preview-label b{color:var(--foreground);font-family:var(--font-mono);font-weight:600}

.continue-card{background:linear-gradient(160deg,color-mix(in srgb,var(--rn-gold,#E0A64A) 6%,var(--background-elevated)),var(--background-elevated));border:1px solid var(--border);border-top:3px solid var(--rn-gold,#E0A64A);border-radius:var(--radius-xl);padding:1.5rem;box-shadow:var(--shadow-md);display:flex;flex-direction:column;gap:1.1rem}
.continue-head{display:flex;align-items:center;gap:.8rem}
.continue-icon{width:2.5rem;height:2.5rem;flex-shrink:0;border-radius:var(--radius-lg);background:linear-gradient(155deg,color-mix(in srgb,var(--rn-gold,#E0A64A) 34%,var(--background-elevated)),var(--background-elevated));border:1px solid color-mix(in srgb,var(--rn-gold,#E0A64A) 38%,var(--border));display:flex;align-items:center;justify-content:center;font-size:1.2rem;box-shadow:0 4px 14px color-mix(in srgb,var(--rn-gold,#E0A64A) 22%,transparent)}
.continue-title{font-size:1.02rem;font-weight:800;color:var(--foreground)}
.continue-sub{font-size:.8rem;color:var(--foreground-dim);margin-top:.15rem}
.continue-card p{font-size:.85rem;color:var(--foreground-muted);line-height:1.55}

.challenge-pick-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(11rem,1fr));gap:.75rem}
.challenge-pick-tile{display:flex;flex-direction:column;gap:.4rem;padding:1.1rem;border-radius:var(--radius-lg);border:1px solid var(--border);background:var(--background-surface);text-decoration:none;color:var(--foreground);transition:all var(--t-fast)}
.challenge-pick-tile:hover{border-color:var(--rn-gold,#E0A64A);transform:translateY(-2px);box-shadow:0 8px 20px -10px color-mix(in srgb,var(--rn-gold,#E0A64A) 40%,transparent)}
.challenge-pick-icon{font-size:1.35rem}
.challenge-pick-label{font-size:.88rem;font-weight:700}

.continue-empty{text-align:center;padding:2.25rem 1rem;color:var(--foreground-dim)}
.continue-empty .ce-icon{font-size:2.1rem;margin-bottom:.7rem;opacity:.75}
.continue-empty .ce-title{color:var(--foreground);font-weight:700;font-size:.92rem;margin-bottom:.35rem}
.continue-empty .ce-sub{font-size:.8rem;line-height:1.5;max-width:32rem;margin:0 auto}
</style>
</head>
<body class="dash-layout">
<?php include __DIR__ . '/sidebar.php'; ?>

<?php
$promotableCount = count($promotableAccounts);
$challengeLabel = $challenge ? apChallengeTypeLabel($challenge) : null;
?>
<main class="main">
    <a href="<?= htmlspecialchars($tcBackUrl) ?>" class="back-link">← Back to <?= $challenge ? htmlspecialchars($challengeLabel) : 'Prop Firms' ?></a>
    <h1 class="page-title">Add Prop Firm Account<?= $challenge ? ' - ' . htmlspecialchars($challengeLabel) : '' ?></h1>
    <p class="page-sub"><?= $challenge ? 'Start a new ' . htmlspecialchars($challengeLabel) . ' evaluation, or promote an account that\'s already completed a phase.' : 'Start a new challenge evaluation, or promote an existing attempt.' ?></p>

    <!-- Mode Selector — two clearly separated jobs, one page -->
    <div class="mode-selector">
        <h2>What would you like to do?</h2>
        <p>Starting a new attempt and promoting an existing one are two different workflows: pick one below.</p>
        <div class="mode-options">
            <div class="mode-option" data-kind="new">
                <input type="radio" id="mode_new" name="account_mode" value="new" <?= $initialMode === 'new' ? 'checked' : '' ?> onchange="handleModeChange()">
                <label for="mode_new">
                    <span class="mode-icon">🆕</span>
                    <span class="mode-title">Start New Challenge Attempt</span>
                    <span class="mode-desc">Purchase a new evaluation, creating a brand new account with the attempt number assigned automatically</span>
                </label>
            </div>
            <div class="mode-option" data-kind="continue">
                <input type="radio" id="mode_continue" name="account_mode" value="continue" <?= $initialMode === 'continue' ? 'checked' : '' ?> onchange="handleModeChange()">
                <label for="mode_continue">
                    <span class="mode-icon">🏆</span>
                    <span class="mode-title">Continue Existing Attempt</span>
                    <span class="mode-desc">Promote an account that already completed a phase to its next stage</span>
                    <?php if ($challenge && $challenge !== 'instant_funding'): ?>
                        <?php if ($promotableCount > 0): ?>
                        <span class="mode-count-badge ready"><span class="mcb-dot"></span>🔥 <?= $promotableCount ?> ready now</span>
                        <?php else: ?>
                        <span class="mode-count-badge none">None ready yet</span>
                        <?php endif; ?>
                    <?php endif; ?>
                </label>
            </div>
        </div>
    </div>

    <!-- Continue Existing Attempt — a real, scoped picker, not a link-away card -->
    <div class="continue-card" id="continueCard" style="<?= $initialMode === 'continue' ? '' : 'display:none;' ?>">
        <div class="continue-head">
            <div class="continue-icon">🏆</div>
            <div>
                <div class="continue-title">Continue Existing Attempt</div>
                <div class="continue-sub"><?= $challenge ? htmlspecialchars($challengeLabel) . ' accounts ready to move up' : 'Pick a challenge type to see which accounts are ready' ?></div>
            </div>
        </div>

        <?php if (!$challenge): ?>
        <p>Instant Funding accounts start funded immediately, so there's nothing to promote there. Pick one of the phased challenge types below.</p>
        <div class="challenge-pick-grid">
            <?php foreach (['one_step', 'two_step', 'three_step'] as $ct): ?>
            <a class="challenge-pick-tile" href="/traderalign/add-prop-account?challenge=<?= $ct ?>&mode=continue">
                <span class="challenge-pick-icon">🪜</span>
                <span class="challenge-pick-label"><?= htmlspecialchars(apChallengeTypeLabel($ct)) ?></span>
            </a>
            <?php endforeach; ?>
        </div>

        <?php elseif ($challenge === 'instant_funding'): ?>
        <div class="continue-empty">
            <div class="ce-icon">🏆</div>
            <div class="ce-title">Instant Funding has no phases to promote through</div>
            <div class="ce-sub">These accounts start funded immediately, so there's nothing to continue here. Use "Start New Challenge Attempt" above to add another one.</div>
        </div>

        <?php elseif (empty($promotableAccounts)): ?>
        <div class="continue-empty">
            <div class="ce-icon">🕐</div>
            <div class="ce-title">Nothing ready to promote yet</div>
            <div class="ce-sub">Keep trading. A <?= htmlspecialchars($challengeLabel) ?> account that completes a phase will appear here automatically, ready to move to its next stage.</div>
        </div>

        <?php else: ?>
        <p>Pick an account below to review its promotion and confirm. You'll land directly on that account's page.</p>
        <?php
        apRenderAccountPicker(
            $promotableAccounts, null, '/traderalign/trading-center',
            ['hub' => 'accounts', 'kind' => 'prop', 'view' => 'center', 'challenge' => $challenge, 'stage' => 'continue'],
            'account_id',
            fn(array $a) => apHumanizeLifecycleState($a['lifecycle_state'] ?? null),
            null,
            true
        );
        ?>
        <?php endif; ?>
    </div>

    <!-- New Challenge Attempt Form -->
    <div class="form-card" id="newAccountForm" style="<?= $initialMode === 'continue' ? 'display:none;' : '' ?>">
        <div class="error-banner" id="errorBanner"></div>

        <div class="field-row">
            <div class="field-group">
                <label for="propFirmName">Prop Firm</label>
                <select id="propFirmKnown" onchange="handleFirmSelect()">
                    <option value="FTMO">FTMO</option>
                    <option value="FundedNext">FundedNext</option>
                    <option value="Maven">Maven</option>
                    <option value="The5ers">The5ers</option>
                    <option value="__custom__">Custom…</option>
                </select>
                <input type="text" id="propFirmName" placeholder="Firm name" style="display:none;margin-top:.5rem">
            </div>
            <div class="field-group">
                <label for="accountSize">Account Size ($)</label>
                <input type="number" id="accountSize" placeholder="10000" min="1" step="any">
            </div>
        </div>

        <!-- Maximum Loss Model — the primary entry point for choosing the
             account's rule model, static, always visible, right here
             between Account Size and Leverage — never gated behind
             Challenge Type. This is only the MODEL choice (Fixed vs.
             Trailing); the actual Maximum Drawdown (%) input this choice
             governs lives inside the Challenge Rules panel below, as the
             card right after Daily Drawdown (%) — the same place a trader
             would naturally expect to set it, immediately after setting
             the daily loss limit — not stranded up here disconnected from
             the rest of the challenge's numbers (2026-08-17 fix). -->
        <div class="field-group">
            <label>Maximum Loss Model</label>
            <div class="dd-model-options">
                <div class="dd-model-option" data-kind="fixed">
                    <input type="radio" id="ddModelFixed" name="max_loss_model" value="fixed" checked onchange="handleDdModelChange()">
                    <label for="ddModelFixed" title="Maximum drawdown is a fixed % of your starting balance. Never moves.">
                        <span class="dd-model-icon">📌</span>
                        <span class="dd-model-title">Fixed</span>
                    </label>
                </div>
                <div class="dd-model-option" data-kind="trailing">
                    <input type="radio" id="ddModelTrailing" name="max_loss_model" value="trailing" onchange="handleDdModelChange()">
                    <label for="ddModelTrailing" title="Maximum drawdown trails your highest balance reached. Rises with new highs, never falls back.">
                        <span class="dd-model-icon">📈</span>
                        <span class="dd-model-title">Trailing</span>
                    </label>
                </div>
            </div>
        </div>

        <div class="field-row">
            <div class="field-group">
                <label for="leverage">Leverage</label>
                <select id="leverage" onchange="handleLeverageSelect()">
                    <option value="1:10">1:10</option>
                    <option value="1:20">1:20</option>
                    <option value="1:30" selected>1:30</option>
                    <option value="1:50">1:50</option>
                    <option value="1:100">1:100</option>
                    <option value="__custom__">Custom…</option>
                </select>
                <input type="text" id="leverageCustom" placeholder="e.g. 1:200" style="display:none;margin-top:.5rem">
            </div>
        </div>

        <div class="field-group">
            <label for="challengeType">Challenge Type</label>
            <select id="challengeType" onchange="renderRulesPanel()">
                <option value="">Select…</option>
                <option value="two_step" <?= $challenge === 'two_step' ? 'selected' : '' ?>>Two-Step</option>
                <option value="three_step" <?= $challenge === 'three_step' ? 'selected' : '' ?>>Three-Step</option>
                <option value="one_step" <?= $challenge === 'one_step' ? 'selected' : '' ?>>One-Step</option>
                <option value="instant_funding" <?= $challenge === 'instant_funding' ? 'selected' : '' ?>>Instant Funding</option>
            </select>
            <?php if ($challenge): ?><div class="hint">Pre-filled from where you came in. Change it if you'd rather add a different type.</div><?php endif; ?>
        </div>

        <!-- Dynamic rules panel — content swapped entirely based on challenge_type -->
        <div class="rules-panel" id="rulesPanel"></div>

        <div class="field-group" style="margin-top:1.1rem">
            <label for="nickname">Optional Nickname</label>
            <input type="text" id="nickname" placeholder="Leave blank to auto-generate" oninput="updatePreview()">
            <div class="preview-label" id="previewLabel"></div>
        </div>

        <div class="form-actions">
            <button class="btn-ghost" onclick="window.location.href='<?= htmlspecialchars($tcBackUrl) ?>'">Cancel</button>
            <button class="btn btn-primary btn-md" onclick="saveAccount()">Save Account</button>
        </div>
    </div>
</main>

<script>
function handleModeChange() {
    const mode = document.querySelector('input[name="account_mode"]:checked').value;
    if (mode === 'new') {
        document.getElementById('newAccountForm').style.display = '';
        document.getElementById('continueCard').style.display = 'none';
        clearError();
    } else {
        document.getElementById('newAccountForm').style.display = 'none';
        document.getElementById('continueCard').style.display = '';
    }
}

function handleFirmSelect() {
    const sel = document.getElementById('propFirmKnown');
    const custom = document.getElementById('propFirmName');
    if (sel.value === '__custom__') {
        custom.style.display = '';
        custom.value = '';
        custom.focus();
    } else {
        custom.style.display = 'none';
        custom.value = sel.value;
    }
    updatePreview();
}
document.getElementById('propFirmName').value = 'FTMO';

function handleLeverageSelect() {
    const sel = document.getElementById('leverage');
    const custom = document.getElementById('leverageCustom');
    if (sel.value === '__custom__') {
        custom.style.display = '';
        custom.value = '';
        custom.focus();
    } else {
        custom.style.display = 'none';
    }
}

function getLeverageValue() {
    const sel = document.getElementById('leverage');
    if (sel.value === '__custom__') {
        return document.getElementById('leverageCustom').value.trim();
    }
    return sel.value;
}

// Rule field definitions per challenge type. Each entry: [id, label, optional]
// max_dd_pct IS listed here now (2026-08-17 fix) — it's a real required
// field of the Challenge Rules panel, positioned right after Daily
// Drawdown (%) in every type below, matching the natural order a trader
// fills these in: phase target(s) first, then Daily Drawdown, then
// Maximum Drawdown. Its actual label text ("Maximum Drawdown (Fixed)" vs
// "Maximum Drawdown (Trailing)") is filled in dynamically by
// renderRulesPanel() from the Maximum Loss Model radio above — the label
// string here is only ever used as a fallback, never rendered directly.
const RULE_FIELDS = {
    two_step: [
        ['phase_1_target_pct', 'Phase 1 Target (%)', false],
        ['phase_2_target_pct', 'Phase 2 Target (%)', false],
        ['daily_dd_pct', 'Daily Drawdown (%)', false],
        ['max_dd_pct', 'Maximum Drawdown (%)', false],
        ['profit_split_pct', 'Profit Split (%)', true],
    ],
    three_step: [
        ['phase_1_target_pct', 'Phase 1 Target (%)', false],
        ['phase_2_target_pct', 'Phase 2 Target (%)', false],
        ['phase_3_target_pct', 'Phase 3 Target (%)', false],
        ['daily_dd_pct', 'Daily Drawdown (%)', false],
        ['max_dd_pct', 'Maximum Drawdown (%)', false],
        ['profit_split_pct', 'Profit Split (%)', true],
    ],
    one_step: [
        ['target_pct', 'Target (%)', false],
        ['daily_dd_pct', 'Daily Drawdown (%)', false],
        ['max_dd_pct', 'Maximum Drawdown (%)', false],
        ['profit_split_pct', 'Profit Split (%)', true],
    ],
    instant_funding: [
        ['daily_dd_pct', 'Daily Drawdown (%)', false],
        ['max_dd_pct', 'Maximum Drawdown (%)', false],
        // Renamed from "Consistency Requirement (%)" to avoid colliding
        // with the real, new Consistency Rule section below (Biggest Day
        // / Total Profit) — same stored key (consistency_requirement_pct,
        // unchanged, no data migration needed), different real-world
        // concept: this one is Instant Funding's stand-in declared value
        // in the profit-target slot (see AccountPicker::apChallengeRulesSummary()),
        // never computed against real trades. The Consistency Rule below
        // is a genuinely different, computed check that applies uniformly
        // across every challenge type, not just Instant Funding.
        ['consistency_requirement_pct', 'Funding Requirement (%)', true],
        ['profit_split_pct', 'Profit Split (%)', true],
    ],
};

const TYPE_LABELS = {
    two_step: 'Two-Step',
    three_step: 'Three-Step',
    one_step: 'One-Step',
    instant_funding: 'Instant Funding',
};

let customRuleCount = 0;

// Common prop-firm-relevant zones, plus a Custom… free-text fallback —
// same known-options-plus-custom pattern already used for Prop Firm
// Name / Leverage above. Only IANA identifiers here (never a fixed
// offset) — DST-correctness depends on it (see PropFirmRuleEngine's own
// header comment on why this must be a real named zone).
const RESET_TIMEZONES = [
    'America/New_York', 'America/Chicago', 'America/Los_Angeles',
    'Europe/London', 'Europe/Berlin', 'Europe/Warsaw',
    'Africa/Nairobi', 'Asia/Dubai', 'Asia/Tokyo', 'Australia/Sydney', 'UTC',
];

function renderRulesPanel() {
    const type = document.getElementById('challengeType').value;
    const panel = document.getElementById('rulesPanel');
    customRuleCount = 0;

    if (!type) {
        panel.classList.remove('visible');
        panel.innerHTML = '';
        return;
    }

    const fields = RULE_FIELDS[type];
    let html = '<div class="rules-panel-title">▾ Challenge Rules: ' + TYPE_LABELS[type] + '</div>';

    // Maximum Loss Model (Fixed/Trailing) stays static above, before
    // Challenge Type — it's not itself challenge-type-dependent. The
    // Maximum Drawdown (%) INPUT it governs, though, lives right here as
    // a real card in this grid, positioned right after Daily Drawdown
    // (%) — the natural fill-in order: phase target(s), Daily Drawdown,
    // then Maximum Drawdown (2026-08-17 fix — this used to be a stray
    // static field disconnected from the rest of the challenge's rule
    // cards; see RULE_FIELDS above). Its label text is filled in
    // dynamically from the currently-selected Maximum Loss Model radio
    // ("Maximum Drawdown (Fixed)" / "Maximum Drawdown (Trailing)"), and
    // it carries the same trailing-explanation hint the old static field
    // used to, shown only when Trailing is selected.
    //
    // Required and optional fields are rendered as two SEPARATE blocks,
    // never interleaved into one grid, so Profit Split (the one optional
    // field most challenge types share) always lands in its own row below
    // the required fields regardless of how many required fields a given
    // challenge type has.
    const requiredFields = fields.filter(f => !f[2]);
    const optionalFields = fields.filter(f => f[2]);
    const isTrailing = document.getElementById('ddModelTrailing') && document.getElementById('ddModelTrailing').checked;

    html += '<div class="rules-grid">';
    requiredFields.forEach(([id, label]) => {
        if (id === 'max_dd_pct') {
            html += '<div class="field-group">' +
                '<label id="ddPctLabel" for="rule_max_dd_pct">' + (isTrailing ? 'Maximum Drawdown (Trailing)' : 'Maximum Drawdown (Fixed)') + '</label>' +
                '<input type="number" id="rule_max_dd_pct" data-rule-field="max_dd_pct" data-optional="0" step="any" min="0">' +
                '<div class="hint" id="ddPctHint" style="display:' + (isTrailing ? '' : 'none') + '">TraderAlign automatically tracks your highest balance reached and calculates the current breach floor from it. You only enter the percentage.</div>' +
                '</div>';
            return;
        }
        html += '<div class="field-group">' +
            '<label for="rule_' + id + '">' + label + '</label>' +
            '<input type="number" id="rule_' + id + '" data-rule-field="' + id + '" data-optional="0" step="any" min="0">' +
            '</div>';
    });
    html += '</div>';

    optionalFields.forEach(([id, label]) => {
        html += '<div class="field-group" style="margin-top:.85rem">' +
            '<label for="rule_' + id + '">' + label + '<span class="optional-tag">optional</span></label>' +
            '<input type="number" id="rule_' + id + '" data-rule-field="' + id + '" data-optional="1" step="any" min="0">' +
            '</div>';
    });

    // Daily Drawdown reset — optional. Leaving both blank retains the
    // existing calendar-day (server-local midnight) behavior, disclosed
    // honestly rather than guessed at.
    html += '<div class="rules-subsection">';
    html += '<div class="rules-subsection-title">Daily Reset Time <span class="optional-tag">optional</span></div>';
    html += '<div class="rules-subsection-hint">If your firm resets the daily loss limit at a specific time, set it here so TraderAlign measures "today" the same way. Leave blank to use calendar-day tracking.</div>';
    html += '<div class="field-row">' +
        '<div class="field-group"><label for="ruleResetTime">Reset Time</label><input type="time" id="ruleResetTime"></div>' +
        '<div class="field-group"><label for="ruleResetTzKnown">Timezone</label>' +
        '<select id="ruleResetTzKnown" onchange="handleResetTzSelect()"><option value="">Select…</option>' +
        RESET_TIMEZONES.map(tz => '<option value="' + tz + '">' + tz + '</option>').join('') +
        '<option value="__custom__">Custom…</option></select>' +
        '<input type="text" id="ruleResetTzCustom" placeholder="e.g. America/Toronto" style="display:none;margin-top:.5rem"></div>' +
        '</div>';
    html += '</div>';

    // Consistency Rule — optional. Only one method has a defined,
    // concrete formula so far; if TraderAlign later adds another, it
    // gets its own <option>, never a fabricated one added here.
    html += '<div class="rules-subsection">';
    html += '<div class="rules-subsection-title">Consistency Rule <span class="optional-tag">optional</span></div>';
    html += '<div class="rules-subsection-hint">Some firms cap how much of your total profit can come from a single day. TraderAlign tracks this against your real trade history and it does not affect your breach boundary.</div>';
    html += '<div class="field-row">' +
        '<div class="field-group"><label for="ruleConsistencyMethod">Method</label>' +
        '<select id="ruleConsistencyMethod"><option value="">Not required</option>' +
        '<option value="biggest_day_over_total_profit">Biggest Winning Day ÷ Total Profit</option>' +
        '</select></div>' +
        '<div class="field-group"><label for="ruleConsistencyMaxPct">Maximum Allowed (%)</label><input type="number" id="ruleConsistencyMaxPct" placeholder="e.g. 20" min="0" max="100" step="any"></div>' +
        '</div>';
    html += '</div>';

    html += '<div class="custom-rules-list" id="customRulesList"></div>';
    html += '<button type="button" class="add-rule-btn" onclick="addCustomRule()">+ Add Additional Rule</button>';

    panel.innerHTML = html;
    panel.classList.add('visible');
}

// Updates the existing Maximum Drawdown card's label/hint in place —
// deliberately does NOT re-render the whole rules panel, so an
// already-typed drawdown % (or any other field) is never wiped just
// because the trader changed their mind on Fixed vs. Trailing. A no-op
// if the rules panel hasn't been rendered yet (no challenge type chosen).
function handleDdModelChange() {
    const isTrailing = document.getElementById('ddModelTrailing').checked;
    const label = document.getElementById('ddPctLabel');
    const hint = document.getElementById('ddPctHint');
    if (!label || !hint) return;
    label.textContent = isTrailing ? 'Maximum Drawdown (Trailing)' : 'Maximum Drawdown (Fixed)';
    hint.style.display = isTrailing ? '' : 'none';
}

function handleResetTzSelect() {
    const sel = document.getElementById('ruleResetTzKnown');
    const custom = document.getElementById('ruleResetTzCustom');
    if (!sel || !custom) return;
    if (sel.value === '__custom__') {
        custom.style.display = '';
        custom.value = '';
        custom.focus();
    } else {
        custom.style.display = 'none';
    }
}

function getResetTzValue() {
    const sel = document.getElementById('ruleResetTzKnown');
    if (!sel) return '';
    if (sel.value === '__custom__') {
        const custom = document.getElementById('ruleResetTzCustom');
        return custom ? custom.value.trim() : '';
    }
    return sel.value;
}

function addCustomRule() {
    const id = 'custom_' + (customRuleCount++);
    const list = document.getElementById('customRulesList');
    const row = document.createElement('div');
    row.className = 'custom-rule-row';
    row.id = id;
    row.innerHTML =
        '<input type="text" placeholder="Rule name (e.g. Min Trading Days)" data-custom-label>' +
        '<input type="text" placeholder="Value" data-custom-value>' +
        '<button type="button" class="remove-rule-btn" onclick="document.getElementById(\'' + id + '\').remove()" aria-label="Remove">×</button>';
    list.appendChild(row);
}

function updatePreview() {
    const firmRaw = document.getElementById('propFirmName').value.trim();
    const sizeRaw = document.getElementById('accountSize').value;
    const size = parseFloat(sizeRaw) || 0;
    const nickname = document.getElementById('nickname').value.trim();
    const previewEl = document.getElementById('previewLabel');

    // Nothing meaningful to preview yet (no firm typed, or no account size
    // entered) — showing "FTMO 0 - Attempt N" before the trader has typed
    // an amount reads like broken output, not a real preview. Stay quiet
    // until there's a real size to show.
    if (nickname || firmRaw === '' || size <= 0) {
        previewEl.innerHTML = '';
        return;
    }

    const sizeLabel = size >= 1000 ? (size / 1000).toFixed(size % 1000 === 0 ? 0 : 1) + 'K' : size;
    const label = firmRaw + ' ' + sizeLabel + ' - Attempt #';
    previewEl.innerHTML = 'Will display as <b>' + label + '</b> (the attempt number is assigned automatically when you save)';
}
document.getElementById('accountSize').addEventListener('input', updatePreview);
updatePreview();

// Arrived pre-scoped to a challenge type (?challenge=X) — the dropdown is
// already server-side pre-selected, so show its rules panel immediately
// instead of waiting for a manual change event.
if (document.getElementById('challengeType').value) renderRulesPanel();

function showError(msg) {
    const el = document.getElementById('errorBanner');
    el.textContent = msg;
    el.classList.add('show');
}
function clearError() {
    document.getElementById('errorBanner').classList.remove('show');
}

function saveAccount() {
    clearError();

    const propFirmName = document.getElementById('propFirmName').value.trim();
    const accountSize = parseFloat(document.getElementById('accountSize').value);
    const challengeType = document.getElementById('challengeType').value;
    const nickname = document.getElementById('nickname').value.trim();

    if (!propFirmName) return showError('Prop firm name is required.');
    if (!accountSize || accountSize <= 0) return showError('Enter a valid account size.');
    if (!challengeType) return showError('Select a challenge type.');

    const leverage = getLeverageValue();
    if (!leverage) return showError('Select or enter a leverage value.');

    const rules = {};
    let missingRequired = null;
    document.querySelectorAll('[data-rule-field]').forEach(input => {
        const field = input.dataset.ruleField;
        const optional = input.dataset.optional === '1';
        const val = input.value.trim();
        if (val === '') {
            if (!optional) missingRequired = field;
            rules[field] = null;
        } else {
            rules[field] = parseFloat(val);
        }
    });
    if (missingRequired) return showError('Please fill in all required rule fields.');

    // Maximum Loss Model — a real radio choice (always present once the
    // rules panel has been shown), defaults to 'fixed'.
    const ddModelChecked = document.querySelector('input[name="max_loss_model"]:checked');
    if (ddModelChecked) rules.max_loss_model = ddModelChecked.value;

    // Daily Reset — both-or-neither, mirrored client-side to match the
    // server's own validation rather than letting a half-filled pair
    // silently save as if nothing were configured.
    const resetTimeEl = document.getElementById('ruleResetTime');
    const resetTime = resetTimeEl ? resetTimeEl.value.trim() : '';
    const resetTz = getResetTzValue();
    if (resetTime && !resetTz) return showError('Select a timezone for the daily reset time, or clear the reset time.');
    if (!resetTime && resetTz) return showError('Enter a daily reset time, or clear the selected timezone.');
    if (resetTime && resetTz) {
        rules.daily_reset_time = resetTime;
        rules.daily_reset_timezone = resetTz;
    }

    // Consistency Rule — both-or-neither, same reasoning.
    const consistencyMethodEl = document.getElementById('ruleConsistencyMethod');
    const consistencyMethod = consistencyMethodEl ? consistencyMethodEl.value : '';
    const consistencyMaxPctEl = document.getElementById('ruleConsistencyMaxPct');
    const consistencyMaxPctRaw = consistencyMaxPctEl ? consistencyMaxPctEl.value.trim() : '';
    if (consistencyMethod && consistencyMaxPctRaw === '') return showError('Enter a maximum allowed % for the Consistency Rule, or set its method back to "Not required".');
    if (!consistencyMethod && consistencyMaxPctRaw !== '') return showError('Select a Consistency Rule method, or clear the maximum allowed %.');
    if (consistencyMethod && consistencyMaxPctRaw !== '') {
        rules.consistency_method = consistencyMethod;
        rules.consistency_max_pct = parseFloat(consistencyMaxPctRaw);
    }

    const customRules = [];
    document.querySelectorAll('.custom-rule-row').forEach(row => {
        const label = row.querySelector('[data-custom-label]').value.trim();
        const value = row.querySelector('[data-custom-value]').value.trim();
        if (label && value) customRules.push({ label, value });
    });

    fetch('/traderalign/api/accounts/create', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
            prop_firm_name: propFirmName,
            account_size: accountSize,
            challenge_type: challengeType,
            nickname: nickname,
            rules: rules,
            custom_rules: customRules,
            leverage: leverage,
        }),
    })
    .then(r => r.json())
    .then(d => {
        if (d.error) {
            showError(d.error);
            return;
        }
        // Land on the new account's own Trading Center Account Home, not
        // the old checklist.php page — a fresh challenge account always
        // starts at Phase 1 (or, for Instant Funding, straight at Instant
        // Funded, since it has no phases), so the target stage is known
        // without needing another round trip. "Start Trade →" on that page
        // is the deliberate, explicit path into checklist.php from here.
        const initialStage = challengeType === 'instant_funding' ? 'instant_funded' : 'phase_1';
        window.location.href = '/traderalign/trading-center?hub=accounts&kind=prop&view=center&challenge=' + encodeURIComponent(challengeType) + '&stage=' + initialStage + '&account_id=' + encodeURIComponent(d.account_id);
    })
    .catch(() => showError('Failed to save account. Please try again.'));
}
</script>
</body>
</html>
