<?php
/**
 * TRADING ARCHIVE — split out of public/journal.php (2026-08-06).
 * ─────────────────────────────────────────────────────────────
 * journal.php had grown past 7,000 lines with two genuinely separate
 * workspaces (Active Journeys, Trading Archive) sharing one file. This
 * file holds every Trading-Archive-specific render function
 * (renderTradingArchive() and everything it calls — the taRender-prefixed
 * and taSuccess-prefixed functions), so Active Journeys' own code (the
 * rn-prefixed functions) can stay in
 * journal.php without this entire, independently-large feature bloating
 * it further. Purely a code-location split, not a behavior or routing
 * change — the URL is still /journal?workspace=archive&..., unchanged;
 * journal.php require_once's this file once (idempotent) and still calls
 * renderTradingArchive($userId, $db) from its own single dispatch site,
 * exactly as when this code lived inline. A visitor can't tell this
 * split happened.
 *
 * Depends on globals already defined by journal.php by the time any of
 * these functions actually run (dispatch only happens after journal.php
 * has finished parsing top to bottom, so this is safe regardless of
 * include order): activeJourneysUrl(), archiveUrl() (URL builders),
 * rnFormatDuration(), rnStateInfo() (Active Journeys helpers reused here
 * for the same visual language), and the TradingArchiveEngine class
 * (required below, defensively — journal.php already requires it too).
 */
require_once __DIR__ . '/../src/TradingArchiveEngine.php';

/**
 * TRADING ARCHIVE — journal redesign, 2026-07-31.
 * ─────────────────────────────────────────────────────────────
 * This is a real, data-grounded navigation shell, not the insights
 * engine itself. Kevin's brief for Trading Archive (per-phase difficulty/
 * consistency/discipline scoring, autopsy-style breach analysis with
 * confidence + evidence, evidence-linked "View Trades" drill-through
 * distinct per Instant Funding/Funded/Live) is a genuinely large, new
 * body of analytical work — comparable in scope to this codebase's
 * biggest single features (e.g. the Reports 4-Stage Summary rebuild) —
 * and was explicitly deferred to its own dedicated follow-up session
 * rather than rushed here. What IS real in this pass: the type (Prop
 * Firms/Live Accounts) × lens (Lessons From Success/Failure) × program
 * (1/2/3 Step/Instant Funding, Prop only) navigation, and a real account
 * count behind every tab — never a fabricated placeholder number.
 *
 * Counting rule, chosen deliberately to avoid inventing terminal states
 * that don't exist in this schema (see CLAUDE.md's Lifecycle Rule — a
 * prop account has no "successfully finished" terminal state; passing a
 * phase promotes it, it doesn't end it):
 *   - Prop Failure  = accounts with lifecycle_state = 'breached' (a real,
 *     durable terminal fact).
 *   - Prop Success  = accounts with challenge_accounts.passed_at set (a
 *     real, durable fact — reused from the same has_passed_at pattern
 *     Reports' Boundary Analysis already established). This deliberately
 *     is NOT mutually exclusive with Failure: an account can have passed
 *     Phase 1 and later breached Phase 3 — both lenses have real lessons
 *     to teach from that one account, matching the brief's own worked
 *     example ("Phase 1 passed, Phase 2 passed, Phase 3 failed").
 *   - Live Failure  = closed accounts (lifecycle_state = 'closed') whose
 *     ending balance is at or below their starting balance.
 *   - Live Success  = closed accounts whose ending balance exceeds their
 *     starting balance.
 */
/**
 * "All Programs" was removed as a filter (2026-07-31) — it always
 * repeated the exact same blended analytics already shown by picking each
 * program individually, added no real value, and actively caused two
 * real context-isolation bugs: Difficulty Score's per-phase breakdown blended
 * Phase 1 across one_step/two_step/three_step accounts as if they were the
 * same thing, and Comparative Analytics showed the identical four
 * comparisons no matter which program was actually selected. With no
 * "All" option, a program must always be picked explicitly; an
 * unrecognized/missing value falls back to the first real program
 * (1 Step) rather than silently blending everything again.
 */
function renderTradingArchive(string $userId, $db): void {
    $archiveLens = ($_GET['archive_lens'] ?? 'failure') === 'success' ? 'success' : 'failure';
    // Lessons From Failure is strictly a prop-firm-challenge concept
    // (2026-08-06, explicit instruction) — 1-Step/2-Step/3-Step/Instant
    // Funding only, never Live Accounts in any form. archive_type is
    // forced to 'prop' here, before anything else reads it, regardless
    // of what a stale/tampered ?archive_type=live URL might request —
    // Lessons From Success (the other lens) is completely unaffected and
    // still supports both types normally.
    $archiveType = $archiveLens === 'failure' ? 'prop' : (($_GET['archive_type'] ?? 'prop') === 'live' ? 'live' : 'prop');
    $programOptions = ['one_step' => '1 Step', 'two_step' => '2 Step', 'three_step' => '3 Step', 'instant_funding' => 'Instant Funding'];
    $archiveProgram = array_key_first($programOptions);
    if ($archiveType === 'prop') {
        $requested = $_GET['archive_program'] ?? '';
        if (array_key_exists($requested, $programOptions)) $archiveProgram = $requested;
    }

    ?>
    <div class="rn-header">
        <div>
            <h1 class="rn-title">Trading Archive</h1>
            <div class="rn-subtitle">Historical, evidence-backed learning from every account you've finished</div>
        </div>
    </div>
    <?php if ($archiveLens === 'success'): ?>
    <div class="rn-type-switch">
        <a href="<?= archiveUrl(['archive_type' => 'prop', 'archive_lens' => $archiveLens]) ?>" class="rn-type-tab <?= $archiveType === 'prop' ? 'active' : '' ?>">Prop Firms</a>
        <a href="<?= archiveUrl(['archive_type' => 'live', 'archive_lens' => $archiveLens]) ?>" class="rn-type-tab <?= $archiveType === 'live' ? 'active' : '' ?>">Live Accounts</a>
    </div>
    <?php endif; ?>
    <?php
    // 2026-08-10 — lens-scoped active color: whichever tab is .active inside
    // a .rn-lens-success container renders muted green, inside
    // .rn-lens-failure renders muted red (see the CSS rules right next to
    // .rn-challenge-tab.active). Applied to both this lens-selector row AND
    // the program-filter row below it, so "1 Step"/"2 Step"/"3 Step"/
    // "Instant Funding" pick up the same color as whichever lens they're
    // currently being browsed under, not a fixed color of their own.
    $rnLensClass = $archiveLens === 'success' ? 'rn-lens-success' : 'rn-lens-failure';
    ?>
    <div class="rn-challenge-filter <?= $rnLensClass ?>">
        <a href="<?= archiveUrl(['archive_type' => $archiveType, 'archive_lens' => 'success', 'archive_program' => $archiveProgram]) ?>" class="rn-challenge-tab <?= $archiveLens === 'success' ? 'active' : '' ?>">Lessons From Success (Advancing Accounts)</a>
        <a href="<?= archiveUrl(['archive_type' => 'prop', 'archive_lens' => 'failure', 'archive_program' => $archiveProgram]) ?>" class="rn-challenge-tab <?= $archiveLens === 'failure' ? 'active' : '' ?>">Lessons From Failure (Breached Accounts)</a>
    </div>
    <?php if ($archiveType === 'prop'): ?>
    <div class="rn-challenge-filter <?= $rnLensClass ?>">
        <?php foreach ($programOptions as $pv => $pl): ?>
        <a href="<?= archiveUrl(['archive_type' => 'prop', 'archive_lens' => $archiveLens, 'archive_program' => $pv]) ?>" class="rn-challenge-tab <?= $archiveProgram === $pv ? 'active' : '' ?>"><?= htmlspecialchars($pl) ?></a>
        <?php endforeach; ?>
    </div>
    <?php endif;

    $programLabel = $archiveType === 'prop' ? $programOptions[$archiveProgram] : 'Live Accounts';

    // Lessons From Success (rebuilt 2026-08-05 into a single-ACCOUNT
    // archived journey — see TradingArchiveEngine::buildAccountSuccessJourney()'s
    // own doc comment for the full architecture) has its own engine
    // entry points and its own render pipeline (taRenderSuccessLearning()
    // and its sub-functions, below) — deliberately not a reskin of the
    // Failure-lens report-style intelligence body. Failure lens is
    // completely untouched.
    if ($archiveLens === 'success') {
        $gathered = TradingArchiveEngine::gatherSuccessAccounts($userId, $db, $archiveType, $archiveProgram);
        $accountList = TradingArchiveEngine::buildSuccessAccountSelector($gathered['by_account'], $archiveType, $archiveProgram);

        $selectedAccountId = $_GET['archive_account'] ?? null;
        if ($selectedAccountId === null || !isset($gathered['by_account'][$selectedAccountId])) {
            $selectedAccountId = $accountList[0]['id'] ?? null;
        }

        if (!empty($accountList)) {
            taRenderSuccessAccountPicker($accountList, $selectedAccountId, $archiveType, $archiveProgram, $archiveLens);
        }

        $successData = $selectedAccountId !== null
            ? TradingArchiveEngine::buildAccountSuccessJourney($gathered['by_account'][$selectedAccountId], $archiveType, $archiveProgram, $userId, $db)
            : ['empty' => true];
        taRenderSuccessLearning($successData, $archiveType, $archiveProgram, $programLabel);
        return;
    }

    // Lessons From Failure (rebuilt 2026-08-06 into a single-ACCOUNT
    // archived breach story — see TradingArchiveEngine::
    // buildAccountFailureJourney()'s own doc comment for the full
    // architecture) mirrors the Lessons From Success single-account
    // rebuild above: its own account picker, its own engine entry point,
    // its own render pipeline (taRenderFailureLearning() and its
    // sub-functions, below). The old aggregate, multi-account
    // taRenderArchiveIntelligence() body (and everything it calls) is no
    // longer reachable from here — Kevin explicitly asked for the whole
    // old Lessons From Failure page content to be replaced, not kept
    // alongside the new build. Those functions are left defined, not
    // physically deleted (this codebase's usual additive-only
    // convention), but nothing on this page calls them anymore.
    //
    // Strictly prop-firm-only (2026-08-06, explicit instruction) — no
    // $archiveType is threaded through anywhere in this branch anymore;
    // $archiveType is already forced to 'prop' above for this lens, and
    // every engine/render function this branch calls has had its own
    // Live Accounts variant/parameter removed outright, not just made
    // unreachable, so there is no remaining code path in this feature
    // that could ever render a Live Account.
    $gathered = TradingArchiveEngine::gatherFailureAccounts($userId, $db, $archiveProgram);
    $accountList = TradingArchiveEngine::buildFailureAccountSelector($gathered['by_account']);

    $selectedAccountId = $_GET['archive_account'] ?? null;
    if ($selectedAccountId === null || !isset($gathered['by_account'][$selectedAccountId])) {
        $selectedAccountId = $accountList[0]['id'] ?? null;
    }

    $failureData = $selectedAccountId !== null
        ? TradingArchiveEngine::buildAccountFailureJourney($gathered['by_account'][$selectedAccountId], $archiveProgram, $userId, $db)
        : ['empty' => true];
    $allTimeCauses = TradingArchiveEngine::allTimeBreachCauses($userId, $db);

    taRenderFailureLearning($failureData, $accountList, $selectedAccountId, $archiveProgram, $programLabel, $allTimeCauses);
}

/**
 * Lessons From Success's account selector — "below the existing program
 * filters", exactly like Active Journeys' own account picker (same shared
 * src/AccountPicker.php component/CSS/JS, same collapsed "Select account ▾"
 * interaction — selecting a different account is a real full-page
 * navigation, never an in-page re-aggregation). $accountList rows already
 * carry the account's own real current-stage parenthetical baked into
 * `label` (see TradingArchiveEngine::buildSuccessAccountSelector()) — this
 * function only renders the picker, it never invents a label itself.
 */
function taRenderSuccessAccountPicker(array $accountList, ?string $selectedAccountId, string $archiveType, string $archiveProgram, string $archiveLens): void {
    $selectedRow = null;
    foreach ($accountList as $a) { if ($a['id'] === $selectedAccountId) { $selectedRow = $a; break; } }
    $isInstantFunding = $archiveType === 'prop' && $archiveProgram === 'instant_funding';
    ?>
    <div class="ta-account-selector-row">
        <div class="ta-account-selector-label">Account</div>
        <?php
        apRenderAccountPicker(
            $accountList,
            $selectedAccountId,
            '/traderalign/journal',
            ['workspace' => 'archive', 'archive_type' => $archiveType, 'archive_lens' => $archiveLens, 'archive_program' => $archiveProgram],
            'archive_account',
            function (array $a) use ($archiveType): string {
                return $archiveType === 'live' ? 'Live Account' : apChallengeTypeLabel($a['challenge_type'] ?? null);
            }
        );
        ?>
    </div>
    <?php if ($selectedRow !== null): ?>
    <p class="ta-success-subtitle"><?= htmlspecialchars(taSuccessJourneySubtitle($selectedRow, $archiveType, $isInstantFunding)) ?></p>
    <?php endif; ?>
    <?php
}

/** The "Detailed insights from this account's journey to {stage} success." subtitle line — real, derived from the selected account's own current stage (already computed by TradingArchiveEngine::buildSuccessAccountSelector()), never generic portfolio copy. */
function taSuccessJourneySubtitle(array $selectedRow, string $type, bool $isInstantFunding): string {
    if ($type === 'live') {
        return ($selectedRow['lifecycle_state'] ?? '') === 'active'
            ? "Detailed insights from this live account's trading journey."
            : "Detailed insights from this account's completed trading journey.";
    }
    if ($isInstantFunding) return "Detailed insights from this account's Instant Funding journey.";
    $stage = $selectedRow['stage_short'];
    if ($stage === 'Funded') return "Detailed insights from this account's journey to funded status.";
    // §2 Live #3 fix (2026-08-10) — $stage is the account's real CURRENT
    // stage, which is not the same as a stage that's been genuinely
    // resolved: an account that passed Phase 1 and is now mid-way through
    // an unresolved Phase 2 has $stage === 'Phase 2' here (accountStageInfo()
    // reports the highest stage reached, even in-progress), so the old
    // unconditional "journey to Phase 2 success" claimed a success that
    // hasn't happened yet — the same underlying gap the successStory()
    // fix (§2 Live #1) closed for the narrative card, just a second render
    // site reading the same unresolved-vs-resolved fact this row now
    // carries.
    if (!empty($selectedRow['in_progress'])) {
        return "Detailed insights from this account's journey so far, while currently attempting {$stage}.";
    }
    return "Detailed insights from this account's journey to {$stage} success.";
}

/** Small null-safe number formatter shared by every Trading Archive render helper below. */
function taVal($v, int $decimals = 1, string $suffix = ''): string {
    if ($v === null) return '-';
    return number_format((float)$v, $decimals) . $suffix;
}

/** "View Trades" button — reuses the same visual language as Active Journeys' rnFilterChip(), driving the Trading Archive's own single evidence table via taFilterTrades() instead of Active Journeys' rnFilterTrades(). Renders nothing when $filter is null (no accurate filter exists for that finding). */
function taViewTradesButton(?array $filter, int $n = 0): string {
    if ($filter === null) return '';
    $label = $filter['label'] . ($n > 0 ? " ({$n})" : '');
    return ' <button type="button" class="rn-filter-chip" onclick="taFilterTrades(\'' . htmlspecialchars($filter['attr'], ENT_QUOTES) . '\', \'' . htmlspecialchars($filter['value'], ENT_QUOTES) . '\', \'' . htmlspecialchars($label, ENT_QUOTES) . '\')">View Trades →</button>';
}

/**
 * ════════════════════════════════════════════════════════════════════
 * LESSONS FROM FAILURE — single-account rebuild (2026-08-06)
 * ────────────────────────────────────────────────────────────────
 * Built to Kevin's approved prototype image (the final source of truth
 * whenever this comment and the image differ). Every number rendered
 * below comes straight from TradingArchiveEngine::buildAccountFailureJourney()
 * — this file only lays it out. No date-range picker, no "Filters"
 * button (both were flagged as erroneously copied from Reports — this
 * page is a single archived account's story, not a period report).
 * ════════════════════════════════════════════════════════════════════
 */
function taRenderFailureLearning(array $data, array $accountList, ?string $selectedAccountId, string $program, string $programLabel, array $allTimeCauses): void {
    ?>
    <div class="rn-trade-journal ta-fail-page-header">
        <div class="ta-fail-page-header-icon">⚠</div>
        <div>
            <h1 class="rn-title">Lessons From Failure <span class="ta-card-h3-note">(Breached Accounts)</span></h1>
            <div class="rn-subtitle">Learn from what ended your journey so you don't repeat it.</div>
        </div>
    </div>
    <?php
    if (empty($accountList)) {
        ?>
        <div class="empty-state">
            <h3><?= htmlspecialchars($programLabel) ?>: Lessons From Failure</h3>
            <p style="font-size:.85rem">No accounts have breached yet in this scope. Once one does, this page computes its real breach story directly from that account's own trade history, and nothing here is ever invented ahead of the data.</p>
        </div>
        <?php
        return;
    }

    taFailureSelectorRow($data, $accountList, $selectedAccountId, $program);

    if ($data['empty'] ?? true) return;

    taFailureStatsStrip($data);

    echo '<div class="ta-fail-2col-tight">';
    taFailureTimeline($data);
    taFailureGlance($data);
    echo '</div>';

    echo '<div class="ta-fail-2col">';
    taFailureEquityChart($data);
    taFailurePrimaryReasons($data);
    echo '</div>';

    echo '<div class="ta-fail-2col">';
    taFailureRiskBehavior($data);
    taFailureAvoidable($data);
    echo '</div>';

    echo '<div class="ta-fail-2col">';
    taFailureGoalsProgress($data);
    taFailureCoaching($data);
    echo '</div>';

    echo '<div class="ta-fail-2col">';
    taFailureEvidenceTable($data);
    taFailureBreachDonut($allTimeCauses);
    echo '</div>';

    taFailureFooter();
}

/** Row 1 — account selector (≈70%) + breach status card (≈30%), matching the prototype's own proportions. Prop-firm only — see gatherFailureAccounts()'s own doc comment. */
function taFailureSelectorRow(array $data, array $accountList, ?string $selectedAccountId, string $program): void {
    $selected = null;
    foreach ($accountList as $a) { if ($a['id'] === $selectedAccountId) { $selected = $a; break; } }
    ?>
    <div class="ta-fail-2col-tight" style="align-items:stretch">
        <div class="rn-trade-journal" style="margin-bottom:0">
            <div class="ta-fail-selector-inner">
                <div class="ta-account-selector-row" style="flex:1 1 320px;margin-bottom:0">
                    <div class="ta-account-selector-label">Select Breached Account</div>
                    <?php
                    apRenderAccountPicker(
                        $accountList, $selectedAccountId, '/traderalign/journal',
                        ['workspace' => 'archive', 'archive_type' => 'prop', 'archive_lens' => 'failure', 'archive_program' => $program],
                        'archive_account',
                        function (array $a): string { return apChallengeTypeLabel($a['challenge_type'] ?? null); }
                    );
                    ?>
                </div>
                <?php if (!empty($data['empty'])): ?>
                <div class="ta-empty-note">This account has no closed trades to build a breach story from yet.</div>
                <?php else: ?>
                <div class="ta-fail-mini-stat">
                    <span class="ta-fail-mini-label">Account Type</span>
                    <span class="ta-fail-mini-value"><?= htmlspecialchars(apChallengeTypeLabel($data['challenge_type'] ?? null)) ?></span>
                </div>
                <div class="ta-fail-mini-stat">
                    <span class="ta-fail-mini-label">Account Size</span>
                    <span class="ta-fail-mini-value">$<?= number_format($data['account_size'], 0) ?></span>
                </div>
                <div class="ta-fail-mini-stat">
                    <span class="ta-fail-mini-label">Prop Firm</span>
                    <span class="ta-fail-mini-value"><?= htmlspecialchars($data['prop_firm_name'] ?? 'Not specified') ?></span>
                </div>
                <div class="ta-fail-mini-stat">
                    <span class="ta-fail-mini-label">Platform</span>
                    <span class="ta-fail-mini-value">MT5</span>
                </div>
                <?php endif; ?>
            </div>
        </div>
        <?php if (empty($data['empty'])): ?>
        <div class="rn-trade-journal ta-breach-glow-card" style="margin-bottom:0">
            <div class="ta-breach-status">
                <div class="ta-breach-status-icon">⚠</div>
                <div class="ta-breach-status-title">BREACHED</div>
                <div class="ta-breach-status-reason"><?= htmlspecialchars($data['stats']['breach_reason']) ?></div>
                <div class="ta-breach-status-divider"></div>
                <div class="ta-breach-status-date-label">Breached On</div>
                <div class="ta-breach-status-date"><?= !empty($data['stats']['end_date']) ? date('d M Y', strtotime($data['stats']['end_date'])) : '-' ?></div>
            </div>
        </div>
        <?php else: ?>
        <div></div>
        <?php endif; ?>
    </div>
    <?php
}

/** Row 2 — one long card, six equal columns, dividers between. */
function taFailureStatsStrip(array $data): void {
    $s = $data['stats'];
    ?>
    <div class="rn-trade-journal ta-fail-stat-strip">
        <div class="ta-fail-stat-col">
            <div class="ta-fail-stat-label">Days Active</div>
            <div class="ta-fail-stat-value"><?= $s['days_active'] !== null ? (int)round($s['days_active']) : '-' ?></div>
            <div class="ta-fail-stat-sub"><?= (!empty($s['start_date']) && !empty($s['end_date'])) ? 'From ' . date('d M Y', strtotime($s['start_date'])) . ' - ' . date('d M Y', strtotime($s['end_date'])) : '' ?></div>
        </div>
        <div class="ta-fail-stat-col">
            <div class="ta-fail-stat-label">Total Trades</div>
            <div class="ta-fail-stat-value"><?= number_format($s['total_trades']) ?></div>
            <div class="ta-fail-stat-sub"><?= $s['win_rate'] !== null ? 'with ' . number_format($s['win_rate'], 1) . '% win rate' : 'No decided trades yet' ?></div>
        </div>
        <div class="ta-fail-stat-col">
            <div class="ta-fail-stat-label">Net P&amp;L</div>
            <div class="ta-fail-stat-value <?= pnlClass($s['net_pnl']) ?>"><?= pnlFormat($s['net_pnl']) ?></div>
            <div class="ta-fail-stat-sub"><?= $s['net_pnl_pct'] !== null ? number_format($s['net_pnl_pct'], 2) . '% of account' : '' ?></div>
        </div>
        <div class="ta-fail-stat-col">
            <div class="ta-fail-stat-label">Max Drawdown</div>
            <div class="ta-fail-stat-value negative">-<?= number_format($s['max_drawdown_pct'], 2) ?>%</div>
            <div class="ta-fail-stat-sub">(-$<?= number_format($s['max_drawdown_dollar'], 2) ?>)</div>
        </div>
        <div class="ta-fail-stat-col">
            <div class="ta-fail-stat-label">Largest Losing Trade</div>
            <div class="ta-fail-stat-value <?= $s['largest_loss'] !== null ? pnlClass($s['largest_loss']) : '' ?>"><?= $s['largest_loss'] !== null ? pnlFormat($s['largest_loss']) : '-' ?></div>
            <div class="ta-fail-stat-sub"><?= $s['largest_loss_pct'] !== null ? '(' . number_format($s['largest_loss_pct'], 2) . '% of account)' : '' ?></div>
        </div>
        <div class="ta-fail-stat-col">
            <div class="ta-fail-stat-label">Breach Reason</div>
            <div class="ta-fail-stat-value" style="font-size:1.05rem"><?= htmlspecialchars($s['breach_reason']) ?></div>
            <div class="ta-fail-stat-sub"><?= htmlspecialchars($data['glance']['rule_broken']) ?></div>
        </div>
    </div>
    <?php
}

/** Row 3, left — horizontal milestone timeline: Account Created → each real segment (green if passed, gold if it's the one active when the account ended) → a final red "Account Breached" node. Prop-firm only. */
function taFailureTimeline(array $data): void {
    $segments = $data['timeline'];
    $terminal = end($segments);
    $terminalLabel = 'Account Breached';
    ?>
    <div class="rn-trade-journal">
        <h3 class="ta-card-h3">Journey To Breach</h3>
        <div class="ta-timeline">
            <div class="ta-timeline-node">
                <div class="ta-timeline-dot ta-timeline-dot-neutral"></div>
                <div class="ta-timeline-date"><?= !empty($data['stats']['start_date']) ? date('d M Y', strtotime($data['stats']['start_date'])) : '-' ?></div>
                <div class="ta-timeline-label">Account Created</div>
            </div>
            <?php foreach ($segments as $seg): $isTerminal = $seg === $terminal;
                $dotClass = $seg['status'] === 'passed' ? 'ta-timeline-dot-green' : 'ta-timeline-dot-gold';
                $badgeText = $seg['status'] === 'passed' ? 'Passed ✓' : 'In Progress';
                $badgeClass = $seg['status'] === 'passed' ? 'rn-badge-green' : 'rn-badge-gold';
            ?>
            <div class="ta-timeline-node">
                <div class="ta-timeline-dot <?= $dotClass ?>"></div>
                <div class="ta-timeline-date"><?= !empty($seg['end_date']) ? date('d M Y', strtotime($seg['end_date'])) : '-' ?></div>
                <div class="ta-timeline-label"><?= htmlspecialchars($seg['phase_label']) ?></div>
                <span class="rn-badge <?= $badgeClass ?>" style="margin-top:.3rem"><?= $badgeText ?></span>
            </div>
            <?php endforeach; ?>
            <div class="ta-timeline-node">
                <div class="ta-timeline-dot ta-timeline-dot-red"></div>
                <div class="ta-timeline-date"><?= !empty($data['stats']['end_date']) ? date('d M Y', strtotime($data['stats']['end_date'])) : '-' ?></div>
                <div class="ta-timeline-label"><?= $terminalLabel ?></div>
            </div>
        </div>
        <?php
        $daysIntoPhase = null;
        if (!empty($terminal['start_date']) && !empty($data['stats']['end_date'])) {
            $daysIntoPhase = max(0, round((strtotime($data['stats']['end_date']) - strtotime($terminal['start_date'])) / 86400));
        }
        ?>
        <p class="ta-timeline-explain">
            <?php if ($daysIntoPhase !== null): ?>
            You were <?= (int)$daysIntoPhase ?> day<?= (int)$daysIntoPhase === 1 ? '' : 's' ?> into <?= htmlspecialchars($terminal['phase_label']) ?> when the breach occurred.
            <?php else: ?>
            This account breached on <?= htmlspecialchars($terminal['phase_label']) ?>.
            <?php endif; ?>
        </p>
    </div>
    <?php
}

/**
 * Row 3, right — item 6 (2026-08-06 refinement pass): rebuilt onto one
 * consistent typographic scale (.ta-glance-row/-label/-value) instead of
 * a mix of ad hoc inline font-weight/font-size overrides that grew one
 * row at a time and ended up looking random. Every label is now the same
 * small-caps weight, every value the same size — meaning (breach vs.
 * neutral vs. positive) is carried by color, never by making one row's
 * text bigger than its neighbor's. Prop-firm only.
 */
function taFailureGlance(array $data): void {
    $g = $data['glance'];
    ?>
    <div class="rn-trade-journal">
        <h3 class="ta-card-h3">Breach At A Glance</h3>
        <div class="ta-glance-list">
            <div class="ta-glance-row"><span class="ta-glance-label">Breach Reason</span><span class="ta-glance-value ta-glance-value-negative"><?= htmlspecialchars($g['breach_reason']) ?></span></div>
            <div class="ta-glance-row"><span class="ta-glance-label">Rule Broken</span><span class="ta-glance-value"><?= htmlspecialchars($g['rule_broken']) ?></span></div>
            <?php
            // Only show the Daily Loss Limit rows when the daily limit is
            // actually the real rule that broke — showing them for a Maximum
            // Drawdown breach (a different real rule) previously read as
            // contradictory: a "Daily Loss Limit" figure sitting next to an
            // "Actual Daily Loss" that could even be a real positive number
            // on the breach day, for a breach that had nothing to do with
            // that day's own P&L.
            $dailyLossIsTheRule = $g['daily_loss_limit_dollar'] !== null && str_starts_with($g['rule_broken'], 'Daily Loss Limit');
            if ($dailyLossIsTheRule):
            ?>
            <div class="ta-glance-row"><span class="ta-glance-label">Daily Loss Limit</span><span class="ta-glance-value">-$<?= number_format($g['daily_loss_limit_dollar'], 2) ?></span></div>
            <div class="ta-glance-row"><span class="ta-glance-label">Actual Daily Loss</span><span class="ta-glance-value <?= $g['actual_daily_loss'] !== null ? 'ta-glance-value-' . ($g['actual_daily_loss'] >= 0 ? 'positive' : 'negative') : '' ?>"><?= $g['actual_daily_loss'] !== null ? pnlFormat($g['actual_daily_loss']) : '-' ?></span></div>
            <?php endif; ?>
            <div class="ta-glance-row"><span class="ta-glance-label">Breach Trade</span><span class="ta-glance-value">#<?= $g['breach_trade_number'] ?><?= !empty($g['breach_trade_date']) ? ' <span class="ta-glance-value-sub">' . date('d M Y, H:i', strtotime($g['breach_trade_date'])) . '</span>' : '' ?></span></div>
            <div class="ta-glance-row"><span class="ta-glance-label">Phase When Breached</span><span class="rn-badge rn-badge-gold"><?= htmlspecialchars($g['phase_when_breached']) ?></span></div>
            <?php if ($g['distance_from_profit_goal'] !== null): ?>
            <div class="ta-glance-row"><span class="ta-glance-label">Distance From Profit Goal</span><span class="ta-glance-value ta-glance-value-<?= $g['distance_from_profit_goal'] >= 0 ? 'positive' : 'negative' ?>"><?= $g['distance_from_profit_goal'] >= 0 ? '+' : '-' ?>$<?= number_format(abs($g['distance_from_profit_goal']), 2) ?></span></div>
            <?php endif; ?>
        </div>
    </div>
    <?php
}

/**
 * Row 4, left — item 7 (2026-08-06 refinement pass): rebuilt from a chart
 * that overlaid three elements a newcomer had to interpret together (the
 * balance line, a separate running-peak line, and the shaded gap between
 * them as "drawdown") into one that tells the story with a single line
 * and a single, plainly-labeled danger zone. One line — the account's
 * real balance over time. One shaded band — a red "Below Breach Level"
 * zone starting at the account's own real minimum-equity floor, so the
 * moment the line touches red is visually obvious without first
 * understanding "peak equity" or "drawdown from peak" as concepts. One
 * marker — a red dot at the final point, plainly labeled "Account
 * Breached Here". A dashed green reference line marks the starting
 * balance for scale. The exact % drawdown figure (already shown in the
 * stats strip above and Risk & Behavior Insights below) is intentionally
 * NOT re-annotated on the chart itself — this chart's only job is "what
 * happened, at a glance," not a second place to read the same number.
 * Same dependency-free inline-SVG convention as taLiveEquityCurveChart()/
 * taSuccessGoalTimelineChart() elsewhere in this file.
 */
function taFailureEquityChart(array $data): void {
    $story = $data['equity']['story'];
    $accountSize = $data['equity']['account_size'];
    $breachLevel = $data['equity']['breach_level_dollar'] ?? null;
    $n = count($story);
    ?>
    <div class="rn-trade-journal">
        <h3 class="ta-card-h3">Equity &amp; Drawdown <span class="ta-card-h3-note">(The Story)</span></h3>
        <?php if ($n === 0): ?>
        <p class="ta-empty-note">No closed trades on this account yet.</p>
        <?php else: ?>
        <div class="ta-equity-legend">
            <span><i class="ta-equity-legend-swatch" style="background:var(--rn-blue)"></i> Account Balance</span>
            <span><i class="ta-equity-legend-swatch" style="background:var(--rn-green);opacity:.7"></i> Starting Balance</span>
            <?php if ($breachLevel !== null): ?>
            <span><i class="ta-equity-legend-swatch" style="background:color-mix(in srgb,var(--rn-red) 55%,transparent)"></i> Below Breach Level</span>
            <?php endif; ?>
            <span><i class="ta-equity-legend-dot"></i> Account Breached Here</span>
        </div>
        <?php
        // A single-trade (or otherwise very short) account has too few
        // real points for a <polyline> to render anything visible on its
        // own — SVG needs at least 2 coordinate pairs to draw a real line
        // segment. Prepending the account's own real starting point (its
        // declared account_size, at the account's own real start date)
        // gives every account, even a 1-trade breach, a genuine 2-point-
        // minimum line from "where it started" to "where it ended" — a
        // real, honest anchor, not a fabricated one.
        $plotPoints = array_merge(
            [['balance' => $accountSize, 'when' => $data['stats']['start_date'] ?? null]],
            array_map(fn($s) => ['balance' => $s['balance'], 'when' => $s['trade']['closed_at'] ?? $s['trade']['captured_at'] ?? null], $story)
        );
        $pn = count($plotPoints);
        $values = array_column($plotPoints, 'balance');
        $floorForRange = $breachLevel !== null ? min($breachLevel, min($values)) : min($values);
        $minV = min($floorForRange, $accountSize) * 0.98;
        $maxV = max(max($values), $accountSize) * 1.04;
        if ($maxV <= $minV) $maxV = $minV + 1;
        $range = $maxV - $minV;
        $w = 640; $h = 240; $padL = 55; $padB = 26; $padT = 16; $padR = 20;
        $plotW = $w - $padL - $padR; $plotH = $h - $padT - $padB;
        $xOf = fn($i) => $padL + ($pn > 1 ? ($i / ($pn - 1)) * $plotW : 0);
        $yOf = fn($v) => $padT + $plotH - (($v - $minV) / ($maxV - $minV)) * $plotH;
        $balCoords = [];
        foreach ($plotPoints as $i => $p) { $balCoords[] = number_format($xOf($i), 1) . ',' . number_format($yOf($p['balance']), 1); }
        $labelCount = min(6, $pn);
        // Below a $2,000 total range, K-rounded labels ("$5K") can all
        // collapse onto the same rounded digit and look like a rendering
        // bug (every gridline reading identical) — show plain, undivided
        // dollar amounts instead once the range is that tight.
        $useK = $range >= 2000;
        $fmtAxisVal = fn($v) => $useK ? '$' . number_format($v / 1000, 0) . 'K' : '$' . number_format($v, 0);
        $breachY = $breachLevel !== null ? $yOf(max($minV, min($maxV, $breachLevel))) : null;
        $startY = $yOf(max($minV, min($maxV, $accountSize)));
        $bi = $pn - 1;
        $dotX = $xOf($bi);
        $dotY = $yOf($plotPoints[$bi]['balance']);

        // Refinement pass (2026-08-06) — the breach-level line's own
        // label used to sit inline on the right edge of the chart,
        // text-anchor="end", in the exact same corner the final data
        // point (and its "Account Breached Here" label) always lands in
        // — since the breach trade is, by construction, always the LAST
        // chronological point. On any account whose balance ended at or
        // near its own breach level (i.e. most breaches), the two labels
        // fought for the same few square pixels and visibly overlapped.
        // Fixed with two real chart-annotation patterns instead of
        // squeezing text into a fixed corner:
        //   1. The breach-level reference line now gets a small, fixed-
        //      width axis badge on the LEFT (the same side every other
        //      value on this chart is read from), with an opaque
        //      background that sits ON TOP of the gridline/tick text
        //      behind it rather than trying to avoid it — the same
        //      "current price tag on the axis" pattern real trading
        //      platforms use for a reference line, which by definition
        //      never competes with anything happening at the right edge.
        //   2. The breach POINT gets a real floating callout box (not
        //      raw <text>) with its own opaque background, connected to
        //      the dot by a short leader line — positioned above-and-
        //      left of the dot and clamped to the plot bounds, so it can
        //      never render truncated or overlapping the right edge
        //      regardless of account size, balance magnitude, or how
        //      close the final balance sits to the breach line.
        $badgeW = 70; $badgeH = 16;
        $badgeY = $breachY !== null ? max($padT, min($h - $padB - $badgeH, $breachY - $badgeH / 2)) : null;

        $calloutW = 122; $calloutH = 34;
        // Anchored so its right edge sits just left of the dot (the dot
        // is always at, or extremely close to, the chart's right edge —
        // the breach trade is always the last point) — clamped so the
        // box itself never crosses either plot boundary.
        $calloutX = max($padL, min($padL + $plotW - $calloutW, $dotX - $calloutW - 6));
        $calloutY = max($padT, min($h - $padB - $calloutH, $dotY - $calloutH - 16));
        $leaderX = $calloutX + $calloutW; $leaderY = $calloutY + $calloutH / 2;
        ?>
        <svg viewBox="0 0 <?= $w ?> <?= $h ?>" class="ta-equity-svg" role="img" aria-label="Account balance over time, with the breach level marked">
            <?php for ($gy = 0; $gy <= 3; $gy++): $ly = $padT + ($plotH / 3) * $gy; $val = $maxV - (($maxV - $minV) / 3) * $gy; ?>
            <line x1="<?= $padL ?>" y1="<?= number_format($ly, 1) ?>" x2="<?= $padL + $plotW ?>" y2="<?= number_format($ly, 1) ?>" class="ta-equity-gridline" />
            <text x="2" y="<?= number_format($ly + 4, 1) ?>" class="ta-equity-tick"><?= $fmtAxisVal($val) ?></text>
            <?php endfor; ?>
            <?php if ($breachY !== null): ?>
            <rect x="<?= $padL ?>" y="<?= number_format($breachY, 1) ?>" width="<?= $plotW ?>" height="<?= number_format(max(0, $padT + $plotH - $breachY), 1) ?>" class="ta-fail-danger-zone" />
            <line x1="<?= $padL ?>" y1="<?= number_format($breachY, 1) ?>" x2="<?= $padL + $plotW ?>" y2="<?= number_format($breachY, 1) ?>" class="ta-fail-breach-line" />
            <?php endif; ?>
            <line x1="<?= $padL ?>" y1="<?= number_format($startY, 1) ?>" x2="<?= $padL + $plotW ?>" y2="<?= number_format($startY, 1) ?>" class="ta-fail-start-line" />
            <polyline points="<?= implode(' ', $balCoords) ?>" class="ta-equity-line" style="stroke:var(--rn-blue)" />
            <?php for ($k = 0; $k < $labelCount; $k++): $i = $pn > 1 ? (int)round($k * ($pn - 1) / max(1, $labelCount - 1)) : 0; $when = $plotPoints[$i]['when']; ?>
            <text x="<?= number_format($xOf($i), 1) ?>" y="<?= $h - 6 ?>" text-anchor="middle" class="ta-equity-tick"><?= $when ? date('d M', strtotime($when)) : '' ?></text>
            <?php endfor; ?>
            <?php if ($breachY !== null && $badgeY !== null): ?>
            <g class="ta-fail-breach-badge">
                <rect x="0" y="<?= number_format($badgeY, 1) ?>" width="<?= $badgeW ?>" height="<?= $badgeH ?>" rx="3" class="ta-fail-breach-badge-bg" />
                <text x="<?= $badgeW / 2 ?>" y="<?= number_format($badgeY + $badgeH / 2 + 3.2, 1) ?>" text-anchor="middle" class="ta-fail-breach-badge-text">$<?= number_format($breachLevel, 0) ?></text>
            </g>
            <?php endif; ?>
            <circle cx="<?= number_format($dotX, 1) ?>" cy="<?= number_format($dotY, 1) ?>" r="4.5" class="ta-fail-breach-dot" />
            <line x1="<?= number_format($dotX, 1) ?>" y1="<?= number_format($dotY, 1) ?>" x2="<?= number_format($leaderX, 1) ?>" y2="<?= number_format($leaderY, 1) ?>" class="ta-fail-breach-leader" />
            <g class="ta-fail-breach-callout">
                <rect x="<?= number_format($calloutX, 1) ?>" y="<?= number_format($calloutY, 1) ?>" width="<?= $calloutW ?>" height="<?= $calloutH ?>" rx="6" class="ta-fail-breach-callout-bg" />
                <text x="<?= number_format($calloutX + $calloutW / 2, 1) ?>" y="<?= number_format($calloutY + 14, 1) ?>" text-anchor="middle" class="ta-fail-breach-callout-title">ACCOUNT BREACHED</text>
                <text x="<?= number_format($calloutX + $calloutW / 2, 1) ?>" y="<?= number_format($calloutY + 27, 1) ?>" text-anchor="middle" class="ta-fail-breach-callout-sub"><?= !empty($data['stats']['end_date']) ? date('d M Y', strtotime($data['stats']['end_date'])) : 'Final trade' ?></text>
            </g>
        </svg>
        <?php endif; ?>
    </div>
    <?php
}

/**
 * Row 4, right — item 8 (2026-08-06 refinement pass): rebuilt from a
 * dense, single-line-per-reason list into individually spaced cards, each
 * with its own icon, an explicit Low/Medium/High impact pill (not just a
 * color on the % number), and full breathing room for the now-longer,
 * beginner-friendly detail sentence to read as a real explanation rather
 * than a caption squeezed under a bar. Content is unchanged from what
 * TradingArchiveEngine::failurePrimaryReasons() computes — this only
 * changes how it's presented.
 */
function taFailurePrimaryReasons(array $data): void {
    $reasons = $data['primary_reasons'];
    ?>
    <div class="rn-trade-journal">
        <h3 class="ta-card-h3">Primary Reasons For The Breach</h3>
        <?php if (empty($reasons)): ?>
        <p class="ta-empty-note">No single clear behavioral signal stood out ahead of this breach. This account's own trade history is still the most complete record of what happened.</p>
        <?php else: ?>
        <div class="ta-reason-list">
        <?php foreach ($reasons as $i => $r): $severity = $r['impact'] >= 60 ? 'High' : ($r['impact'] >= 35 ? 'Medium' : 'Low'); $sevClass = $r['impact'] >= 60 ? 'rn-badge-red' : ($r['impact'] >= 35 ? 'rn-badge-gold' : 'rn-badge-neutral'); ?>
        <div class="ta-reason-card">
            <div class="ta-reason-card-icon"><?= $r['icon'] ?? ($i + 1) ?></div>
            <div class="ta-reason-card-body">
                <div class="ta-reason-card-head">
                    <span class="ta-reason-card-label"><?= htmlspecialchars($r['label']) ?></span>
                    <span class="rn-badge <?= $sevClass ?>"><?= htmlspecialchars($severity) ?> Impact: <?= $r['impact'] ?>%</span>
                </div>
                <div class="ta-cause-bar ta-reason-card-bar"><span class="ta-cause-fill" style="width:<?= $r['impact'] ?>%"></span></div>
                <p class="ta-reason-card-detail"><?= htmlspecialchars($r['detail']) ?></p>
            </div>
        </div>
        <?php endforeach; ?>
        </div>
        <p class="ta-empty-note" style="margin-top:.9rem">These are the behaviors that had the biggest negative impact on this account, ranked by how strongly each one contributed.</p>
        <?php endif; ?>
    </div>
    <?php
}

/** Row 5, left — six real risk/behavior tiles, reusing the existing .ta-difficulty-grid/.ta-difficulty-tile component. */
function taFailureRiskBehavior(array $data): void {
    ?>
    <div class="rn-trade-journal">
        <h3 class="ta-card-h3">Risk &amp; Behavior Insights</h3>
        <div class="ta-difficulty-grid">
            <?php foreach ($data['risk_behavior'] as $tile): ?>
            <div class="ta-difficulty-tile">
                <div class="ta-difficulty-label"><?= htmlspecialchars($tile['label']) ?></div>
                <div class="ta-difficulty-score" style="<?= $tile['tone'] === 'negative' ? 'color:var(--rn-red)' : '' ?>"><?= htmlspecialchars($tile['value']) ?></div>
                <?php if ($tile['note'] !== null): ?><div class="ta-difficulty-explain" style="<?= $tile['tone'] === 'negative' ? 'color:var(--rn-red)' : '' ?>"><?= htmlspecialchars($tile['note']) ?></div><?php endif; ?>
            </div>
            <?php endforeach; ?>
        </div>
    </div>
    <?php
}

/** Row 5, right — a real, computed avoidability verdict (never a fixed "Yes"), with the calculation disclosed via a native <details> disclosure rather than a link to nowhere. */
function taFailureAvoidable(array $data): void {
    $a = $data['avoidable'];
    ?>
    <div class="rn-trade-journal">
        <h3 class="ta-card-h3">Could This Breach Have Been Avoided?</h3>
        <div class="ta-avoid-body">
            <div class="ta-avoid-icon <?= $a['verdict'] ? 'ta-avoid-icon-yes' : 'ta-avoid-icon-no' ?>">🛡</div>
            <div>
                <div class="ta-avoid-headline <?= $a['verdict'] ? 'positive' : '' ?>"><?= htmlspecialchars($a['headline']) ?></div>
                <p class="ta-avoid-explain"><?= htmlspecialchars($a['explanation']) ?></p>
                <?php if ($a['calc_note'] !== null): ?>
                <details class="ta-avoid-calc"><summary>How We Calculated This</summary><p><?= htmlspecialchars($a['calc_note']) ?></p></details>
                <?php endif; ?>
            </div>
        </div>
    </div>
    <?php
}

/** Row 6, left — four goal columns, reusing the existing .rn-goal-bar progress-bar component. */
function taFailureGoalsProgress(array $data): void {
    $isInstantFunding = ($data['challenge_type'] ?? null) === 'instant_funding';
    ?>
    <div class="rn-trade-journal">
        <?php // Item 10 (2026-08-06) — "Goals Progress" renamed: these four
        // columns are the prop firm's own declared evaluation rules and
        // loss/profit thresholds, not personal goals the trader set —
        // "Account Rules & Thresholds" names what they actually are while
        // keeping the same four metrics unchanged. ?>
        <h3 class="ta-card-h3">Account Rules &amp; Thresholds <span class="ta-card-h3-note">(Before Breach)</span></h3>
        <?php if ($isInstantFunding): ?>
        <p class="ta-empty-note" style="margin-bottom:1rem">Instant Funding accounts don't declare phase-style profit/loss-limit percentages the way evaluation challenges do, so targets below show "Not specified" wherever this account's own rules genuinely don't carry one, rather than a guessed number.</p>
        <?php endif; ?>
        <div class="ta-fail-goals-grid">
            <?php foreach ($data['goals'] as $g): $fillColor = $g['state'] === 'negative' ? 'var(--rn-red)' : ($g['state'] === 'positive' ? 'var(--rn-green)' : 'linear-gradient(90deg,var(--rn-gold),var(--rn-green))'); $showBar = $g['show_bar'] ?? true; ?>
            <div class="ta-fail-goal-col">
                <div class="ta-fail-goal-label"><?= htmlspecialchars($g['label']) ?></div>
                <?php /* 2026-08-06 — target_text is now always a complete,
                standalone sentence on its own ("Target: $400.00 (8%)", "No
                profit target applies to this account.") — the template no
                longer hardcodes its own "Target: " prefix in front of it,
                since that duplicated wording already baked into the string
                and produced things like "Target: No target required
                (declared 0%)." */ ?>
                <div class="ta-fail-goal-target"><?= htmlspecialchars($g['target_text']) ?></div>
                <?php if ($showBar): ?>
                <div class="rn-goal-bar"><div class="rn-goal-bar-fill" style="width:<?= $g['bar_pct'] ?>%;background:<?= $fillColor ?>"></div></div>
                <?php else: ?>
                <div class="rn-goal-bar" style="visibility:hidden"></div>
                <?php endif; ?>
                <div class="ta-fail-goal-actual <?= $g['state'] === 'negative' ? 'negative' : ($g['state'] === 'positive' ? 'positive' : '') ?>"><?= htmlspecialchars($g['actual_text']) ?><?= $g['pct_text'] !== null ? ' (' . htmlspecialchars($g['pct_text']) . ')' : '' ?></div>
            </div>
            <?php endforeach; ?>
        </div>
    </div>
    <?php
}

/**
 * Row 6, right — item 11, second refinement pass (2026-08-06): rebuilt
 * from a bullet list of live-sounding coaching instructions into a
 * concise, past-tense NARRATIVE — a historical summary of what
 * TraderAlign was already telling this trader before the breach, not a
 * copy of Active Coaching's current UI. See
 * TradingArchiveEngine::failureCoaching()'s own doc comment for how this
 * differs from Could This Breach Have Been Avoided? (same underlying
 * facts, different question).
 */
function taFailureCoaching(array $data): void {
    ?>
    <div class="rn-trade-journal">
        <h3 class="ta-card-h3">Final Coaching Before Breach</h3>
        <div class="ta-avoid-body">
            <div class="ta-avoid-icon ta-avoid-icon-no">🕐</div>
            <div>
                <p class="ta-avoid-explain" style="margin-bottom:0"><?= htmlspecialchars($data['coaching']) ?></p>
            </div>
        </div>
    </div>
    <?php
}

/** Row 7, left — a compact preview of the trades that led into the breach (same real Impact-star scoring as Lessons From Success), the final row visually marked as the breach trade. "View in Trades Table" routes to renderBreachTradesView() — a dedicated, read-only, past-tense destination, NEVER Active Journeys' own account picker/coaching (see that function's own doc comment for why this account can never appear there). */
/**
 * Item 11 (2026-08-06) — deliberately NOT a separate implementation.
 * Trade quality (the Impact star rating) is the same real signal
 * regardless of whether the account it happened on eventually succeeded
 * or failed, so this now reuses taSuccessEvidenceTrades()'s exact table
 * shape (Date/Instrument/Session/Direction/RR/P&L(R)/Impact-with-
 * popover) byte-for-byte, rather than the bespoke Pair/Result/P&L(USD)/
 * View column set this section used before. Two differences only, both
 * additive to that shared shape: the final (breach) row gets the same
 * .ta-fail-breach-row red highlight + "BREACH TRADE" badge used
 * elsewhere on this page, and the "View" column — which linked into the
 * live 4-Stage trade-review workflow — is gone entirely (the trader
 * already had that workflow available before the breach; Lessons From
 * Failure's own coaching cards are where that gap gets addressed now,
 * not a reopened live-trade-review link on a finished account).
 */
function taFailureEvidenceTable(array $data): void {
    $trades = $data['evidence_trades'];
    ?>
    <div class="rn-trade-journal">
        <h3 class="ta-card-h3">Trades That Led To The Breach <span class="ta-card-h3-note">(Journey Evidence)</span></h3>
        <p class="ta-empty-note" style="margin-bottom:1rem">The most influential trades that contributed to this account's failure, ranked the same way trade quality is ranked everywhere on this page. The final row is the trade that caused the breach.</p>
        <?php if (empty($trades)): ?>
        <div class="rn-empty-note">No closed trades on this account.</div>
        <?php else: ?>
        <div class="rn-table-scroll">
        <table class="rn-table ta-success-table" id="ta-failure-evidence-table">
            <thead>
                <tr>
                    <th>Date</th><th>Instrument</th><th>Session</th><th>Direction</th>
                    <th>RR</th><th>P&amp;L (R)</th>
                    <th><span class="ta-impact-info">Impact <button type="button" class="tl4-expand-btn" onclick="taToggleImpactInfo(this)">View</button>
                        <div class="ta-impact-popover" style="display:none">
                            <div class="ta-impact-popover-head">
                                <span class="ta-impact-popover-title">★ Impact Rating</span>
                                <button type="button" class="ta-impact-popover-close" onclick="event.stopPropagation();this.closest('.ta-impact-popover').style.display='none'" aria-label="Close">✕</button>
                            </div>
                            <div class="ta-impact-popover-row"><span class="ta-impact-popover-star">5★</span><span class="ta-impact-popover-desc">3R+</span></div>
                            <div class="ta-impact-popover-row"><span class="ta-impact-popover-star">4★</span><span class="ta-impact-popover-desc">2R to 3R</span></div>
                            <div class="ta-impact-popover-row"><span class="ta-impact-popover-star">3★</span><span class="ta-impact-popover-desc">1R to 2R</span></div>
                            <div class="ta-impact-popover-row"><span class="ta-impact-popover-star">2★</span><span class="ta-impact-popover-desc">0R to 1R or breakeven</span></div>
                            <div class="ta-impact-popover-row"><span class="ta-impact-popover-star">1★</span><span class="ta-impact-popover-desc">Loss</span></div>
                            <div class="ta-impact-popover-cap"><b>⚠</b><span>Over-risk, tilt, or revenge trades can't score above 2★</span></div>
                        </div>
                    </span></th>
                </tr>
            </thead>
            <tbody>
            <?php foreach ($trades as $t): ?>
                <tr class="<?= $t['is_breach_trade'] ? 'ta-fail-breach-row' : '' ?>">
                    <td><?= !empty($t['date']) ? date('d M Y', strtotime($t['date'])) : '-' ?><?php if ($t['is_breach_trade']): ?> <span class="rn-badge rn-badge-red" style="margin-left:.3rem">BREACH TRADE</span><?php endif; ?></td>
                    <td><?= $t['instrument'] !== '' ? htmlspecialchars($t['instrument']) : '-' ?></td>
                    <td><?= htmlspecialchars($t['session'] ?? '') !== '' ? htmlspecialchars($t['session']) : '-' ?></td>
                    <td class="<?= ($t['direction'] ?? '') === 'long' ? 'positive' : 'negative' ?>"><?= ($t['direction'] ?? '') === 'long' ? 'Long' : 'Short' ?></td>
                    <td><?= $t['planned_rr'] !== null ? '1 : ' . number_format($t['planned_rr'], 1) : '-' ?></td>
                    <?php
                    // 2026-08-06 — a bare "—" here now only ever means this
                    // ONE trade genuinely has neither a recorded planned-
                    // risk dollar amount (max_potential_loss) nor its
                    // sibling risk_per_position to compute a real R-multiple
                    // from — never a break-even trade (that renders "+0.00R"
                    // below, a real value) and never a missing outcome (P&L
                    // itself always exists; only the RATIO needs a planned-
                    // risk denominator this specific trade doesn't have).
                    // Stated explicitly via a tooltip rather than an
                    // unexplained symbol, per explicit instruction.
                    $rUnavailableNote = 'This trade has no recorded planned risk amount (neither Max Potential Loss nor Risk Per Position) to calculate a real R-multiple from, not a break-even trade and not a missing outcome, just no planned-risk figure on record for it.';
                    ?>
                    <td class="<?= $t['r_multiple'] === null ? '' : ($t['r_multiple'] >= 0 ? 'positive' : 'negative') ?>"<?= $t['r_multiple'] === null ? ' title="' . htmlspecialchars($rUnavailableNote) . '"' : '' ?>><?= $t['r_multiple'] === null ? 'Unavailable' : (($t['r_multiple'] >= 0 ? '+' : '') . number_format($t['r_multiple'], 2) . 'R') ?></td>
                    <td class="ta-impact-stars"<?= $t['stars'] === null ? ' title="Impact can\'t be scored without a real R-multiple. See P&amp;L (R) on this row."' : '' ?>><?= $t['stars'] !== null ? str_repeat('★', $t['stars']) . str_repeat('☆', 5 - $t['stars']) : 'N/A' ?></td>
                </tr>
            <?php endforeach; ?>
            </tbody>
        </table>
        </div>
        <div style="margin-top:1rem;text-align:center">
            <a href="<?= htmlspecialchars(activeJourneysUrl(['breach_account' => $data['account_id']])) ?>" class="rn-view-btn">View in Trades Table</a>
            <p class="ta-empty-note" style="margin-top:.5rem">See the full journey including the breaching trade highlighted in red.</p>
        </div>
        <?php endif; ?>
    </div>
    <?php
}

/** Row 7, right — all-time breach-cause donut (deliberately NOT scoped to the current program filter — see TradingArchiveEngine::allTimeBreachCauses()). Prop-firm only — Live Accounts never reaches this feature at all (see gatherFailureAccounts()'s own doc comment). */
function taFailureBreachDonut(array $allTimeCauses): void {
    $causes = $allTimeCauses['causes'];
    $accountCount = $allTimeCauses['account_count'];
    $colors = ['var(--rn-red)', 'var(--rn-gold)', 'var(--rn-purple)', 'var(--rn-blue)', '#26A69A', 'var(--foreground-dim)'];
    ?>
    <div class="rn-trade-journal">
        <h3 class="ta-card-h3">Breaches By Reason <span class="ta-card-h3-note">(All Time)</span></h3>
        <?php if (empty($causes)): ?>
        <p class="ta-empty-note">No breached accounts on record yet.</p>
        <?php else: ?>
        <div class="ta-donut-wrap">
            <svg viewBox="0 0 36 36" class="ta-donut-svg" role="img" aria-label="Breaches by reason">
                <?php $offset = 0.0; foreach ($causes as $i => $c): $dash = max(0, $c['pct'] - ($c['pct'] > 0 && $c['pct'] < 100 ? 1 : 0)); if ($c['pct'] <= 0) continue; ?>
                <circle cx="18" cy="18" r="15.9155" fill="none" stroke="<?= $colors[$i % count($colors)] ?>" stroke-width="4.3"
                    stroke-dasharray="<?= number_format($dash, 3) ?> <?= number_format(100 - $dash, 3) ?>"
                    stroke-dashoffset="<?= number_format(-$offset, 3) ?>" transform="rotate(-90 18 18)" stroke-linecap="round" />
                <?php $offset += $c['pct']; endforeach; ?>
                <text x="18" y="16.5" text-anchor="middle" class="ta-donut-value"><?= $accountCount ?></text>
                <text x="18" y="21.5" text-anchor="middle" class="ta-donut-label">Breached Accounts</text>
            </svg>
            <div class="ta-donut-legend">
                <?php foreach ($causes as $i => $c): ?>
                <div class="ta-donut-legend-row"><span class="ta-donut-swatch" style="background:<?= $colors[$i % count($colors)] ?>"></span><span class="ta-donut-legend-label"><?= htmlspecialchars($c['label']) ?></span><span class="ta-donut-legend-value"><?= $c['count'] ?> (<?= number_format($c['pct'], 1) ?>%)</span></div>
                <?php endforeach; ?>
            </div>
        </div>
        <?php // Item 12 (2026-08-06) — reworded for plain clarity: this
        // covers every account you've ever breached, across every
        // challenge type, regardless of which program is selected above. ?>
        <p class="ta-empty-note" style="margin-top:1rem">This includes every account you've ever breached, across all challenge types. It isn't limited to the program selected above.</p>
        <?php endif; ?>
    </div>
    <?php
}

function taFailureFooter(): void {
    ?>
    <div class="ta-fail-footer">
        <?php // Item 13 (2026-08-06) — replaced the ♥ icon with a shield,
        // matching the risk-preservation theme already used throughout
        // this page (Could This Breach Have Been Avoided?'s own icon). ?>
        <span class="ta-fail-footer-icon">🛡</span>
        Every breach is expensive. Every lesson is priceless. Review, learn, adjust, and come back stronger.
    </div>
    <?php
}

/**
 * Trading Archive's real analytics body — everything below the type/lens/
 * program tabs. Built entirely from TradingArchiveEngine::build()'s output;
 * this function only formats and lays out numbers it did not compute.
 *
 * SUPERSEDED for the Failure lens (2026-08-06) — see renderTradingArchive()'s
 * own comment: Lessons From Failure now dispatches to
 * taRenderFailureLearning() above and never reaches this function anymore.
 * Left defined, not deleted, per this codebase's additive-only convention;
 * still reachable in principle if $lens were ever 'success' here, but the
 * 'success' lens has its own separate dispatch (taRenderSuccessLearning())
 * and never calls this either — so this whole function and everything it
 * calls below (through taRenderEvidenceTable()) is effectively orphaned.
 */
function taRenderArchiveIntelligence(array $data, string $type, string $lens, string $program, string $programLabel): void {
    $lensNoun = $lens === 'success' ? 'succeeded' : 'failed';
    if ($data['empty']) {
        ?>
        <div class="empty-state">
            <h3><?= htmlspecialchars($programLabel) ?>: <?= $lens === 'success' ? 'Lessons From Success' : 'Lessons From Failure' ?></h3>
            <p style="font-size:.85rem">
                No <?= htmlspecialchars(strtolower($type === 'prop' ? 'phases or accounts' : 'accounts')) ?> have <?= $lensNoun ?> yet in this scope.
                Once at least one real <?= $type === 'prop' ? 'phase or account' : 'account' ?> resolves this way, Trading Archive computes real statistics,
                findings, and trade-level evidence from it. Nothing here is ever invented ahead of the data.
            </p>
        </div>
        <?php
        taRenderMt5Note($data);
        return;
    }

    taRenderOverview($data, $type, $lens);
    taRenderHistoricalConsistency($data);
    if ($type === 'prop') taRenderDifficulty($data);
    taRenderStatsGrid($data, $type);
    taRenderFindings($data, $lens);
    taRenderPatterns($data, $lens);
    if ($lens === 'failure') taRenderBreachCauses($data, $type);
    taRenderComparative($data);
    taRenderEvidenceTable($data);
    taRenderMt5Note($data);
}

function taRenderOverview(array $data, string $type, string $lens): void {
    $rows = $data['evidence_rows'];
    $dates = [];
    foreach ($rows as $r) { $when = $r['trade']['closed_at'] ?? $r['trade']['captured_at'] ?? null; if ($when) $dates[] = $when; }
    $span = !empty($dates) ? date('d M Y', strtotime(min($dates))) . ' to ' . date('d M Y', strtotime(max($dates))) : '-';
    ?>
    <div class="rn-trade-journal">
        <div class="rn-coaching-stats">
            <div class="rn-coaching-stat">
                <div class="rn-coaching-stat-label"><?= $type === 'prop' ? 'Phases / Segments' : 'Accounts' ?></div>
                <div class="rn-coaching-stat-value"><?= $data['segment_count'] ?></div>
            </div>
            <div class="rn-coaching-stat">
                <div class="rn-coaching-stat-label">Accounts Represented</div>
                <div class="rn-coaching-stat-value"><?= $data['account_count'] ?></div>
            </div>
            <div class="rn-coaching-stat">
                <div class="rn-coaching-stat-label">Trades in Evidence</div>
                <div class="rn-coaching-stat-value"><?= $data['stats']['pooled_trade_count'] ?></div>
            </div>
            <div class="rn-coaching-stat">
                <div class="rn-coaching-stat-label">Date Range Covered</div>
                <div class="rn-coaching-stat-value" style="font-size:.85rem"><?= htmlspecialchars($span) ?></div>
            </div>
        </div>
    </div>
    <?php
}

/**
 * Historical Discipline Index (renamed 2026-08-08, was "Historical
 * Consistency Score" — confirmed safe to rename in a prior session, no
 * persisted data references the old label; see
 * docs/architecture/SINGLE_SOURCE_OF_TRUTH_AUDIT.md §8b, Wave 4b) — a
 * group-level metric distinct from Active Journeys/Edge Health's
 * "Execution Consistency" factor; see
 * TradingArchiveEngine::historicalConsistency()'s doc comment. Rewritten
 * 2026-07-31 to teach a trader what the number means in plain language
 * first — the exact math (coefficient of variation, pooled trade count)
 * now lives in a hover tooltip for anyone who wants it, not the main copy.
 */
function taRenderHistoricalConsistency(array $data): void {
    $hc = $data['historical_consistency'];
    ?>
    <div class="rn-trade-journal">
        <h3 style="font-size:1rem;font-weight:800;margin-bottom:.4rem">Historical Discipline Index</h3>
        <p style="font-size:.8rem;color:var(--foreground-dim);margin-bottom:.9rem">Measures how consistently disciplined your trading stayed across every account in this archive, not how profitable it was.</p>
        <?php if (!$hc['available']): ?>
        <p style="font-size:.82rem;color:var(--foreground-dim)">Not enough resolved trade history yet (<?= $hc['n'] ?> trade<?= $hc['n'] === 1 ? '' : 's' ?> with a recorded risk %, need at least <?= TradingArchiveEngine::MIN_HISTORICAL_CONSISTENCY_TRADES ?>) to compute a real score.</p>
        <?php else:
            $riskWord = $hc['risk_consistency'] >= 70 ? 'stayed steady' : ($hc['risk_consistency'] >= 40 ? 'varied somewhat' : 'swung widely');
            $disciplineWord = $hc['discipline_rate'] >= 70 ? 'rarely slipped into emotional trading' : ($hc['discipline_rate'] >= 40 ? 'occasionally slipped into emotional trading' : 'often slipped into emotional trading');
            $tooltip = sprintf(
                'Exact numbers: position-sizing stability %s/100 (coefficient of variation %s) and discipline rate %s%% (share of trades classified Disciplined Win, Controlled Loss, or Breakeven, i.e. outside every Tilt Warning / Revenge Trade / Elevated Win / Oversized Loss bucket), across %d trades. The two are averaged equally.',
                taVal($hc['risk_consistency'], 1), taVal($hc['risk_cv'], 2), taVal($hc['discipline_rate'], 1), $hc['n']
            );
        ?>
        <div style="display:flex;align-items:center;gap:1.5rem;flex-wrap:wrap">
            <div class="rn-metric-ring">
                <div class="rn-ring" style="--pct:<?= $hc['score'] ?>"><span><?= $hc['score'] ?></span></div>
                <div class="rn-metric-label">/ 100</div>
            </div>
            <div style="flex:1;min-width:16rem">
                <p style="font-size:.82rem;color:var(--foreground-muted);line-height:1.65;margin:0 0 .5rem">It combines two things, weighted equally:</p>
                <ul style="font-size:.82rem;color:var(--foreground-muted);line-height:1.65;margin:0 0 .6rem 1.1rem;padding:0">
                    <li>How steady your position sizing <?= $riskWord ?> from trade to trade.</li>
                    <li>How often you <?= $disciplineWord ?>: tilt, revenge, or oversized-risk trades.</li>
                </ul>
                <p style="font-size:.78rem;color:var(--foreground-dim)" title="<?= htmlspecialchars($tooltip, ENT_QUOTES) ?>">Higher scores mean your behavior stayed disciplined from beginning to end. Based on <?= $hc['n'] ?> real trades. ⓘ</p>
            </div>
        </div>
        <?php endif; ?>
    </div>
    <?php
}

/** Difficulty Score board — one tile per real phase label with enough resolved history. Prop only (live accounts have no phase concept). */
function taRenderDifficulty(array $data): void {
    if (empty($data['difficulty'])) return;
    ?>
    <div class="rn-trade-journal">
        <h3 style="font-size:1rem;font-weight:800;margin-bottom:.3rem">Difficulty Score by Phase</h3>
        <p style="font-size:.76rem;color:var(--foreground-dim);margin-bottom:1rem">Derived from real pass rate, average time, average drawdown, losing-streak length, and recovery difficulty across every resolved attempt at each phase, never a fixed number.</p>
        <div class="ta-difficulty-grid">
        <?php foreach ($data['difficulty'] as $label => $d): ?>
            <div class="ta-difficulty-tile">
                <div class="ta-difficulty-label"><?= htmlspecialchars($label) ?></div>
                <?php if (!$d['available']): ?>
                <div class="ta-difficulty-score rn-metric-waiting" style="font-size:.85rem">Not enough resolved attempts yet (<?= $d['n_resolved'] ?> of <?= TradingArchiveEngine::MIN_GROUP_SEGMENTS ?> needed)</div>
                <?php else: ?>
                <div class="ta-difficulty-score"><?= number_format($d['score'], 1) ?><span style="font-size:.7rem;color:var(--foreground-dim)"> / 10</span></div>
                <p class="ta-difficulty-explain"><?= htmlspecialchars($d['explanation']) ?></p>
                <?php endif; ?>
            </div>
        <?php endforeach; ?>
        </div>
        <?php if ($data['easiest_phase'] || $data['hardest_phase']): ?>
        <div style="margin-top:1rem;padding-top:1rem;border-top:1px solid var(--border);font-size:.8rem;color:var(--foreground-muted);line-height:1.7">
            <?php if ($data['easiest_phase']): ?><div><strong style="color:var(--rn-green)">Easiest:</strong> <?= htmlspecialchars($data['easiest_phase']['label']) ?>, <?= taVal($data['easiest_phase']['pass_rate'], 1, '%') ?> pass rate across <?= $data['easiest_phase']['n_resolved'] ?> resolved attempts.</div><?php endif; ?>
            <?php if ($data['hardest_phase']): ?><div><strong style="color:var(--rn-red)">Hardest:</strong> <?= htmlspecialchars($data['hardest_phase']['label']) ?>, <?= taVal($data['hardest_phase']['pass_rate'], 1, '%') ?> pass rate across <?= $data['hardest_phase']['n_resolved'] ?> resolved attempts.</div><?php endif; ?>
        </div>
        <?php endif; ?>
    </div>
    <?php
}

/**
 * Core Statistics — every whole-event count (trades to outcome, streak
 * length, recovery speed) now renders in natural language via
 * naturalCount() instead of a raw decimal (a "1.4 consecutive losses" or
 * "0.7 days" read as literally impossible — fixed 2026-07-31). Durations
 * route through formatDurationDays(), which itself no longer emits a
 * fractional hour/day. Only genuinely continuous metrics (risk %,
 * reward:risk, win rate, expectancy) keep decimal precision, since those
 * really can take any value.
 */
function taRenderStatsGrid(array $data, string $type): void {
    $g = $data['stats']; $p = $g['pooled'];
    $ucNatural = function ($avg, $singular, $plural = null) {
        $phrase = naturalCount($avg, $singular, $plural);
        return $phrase !== null ? ucfirst($phrase) : '-';
    };
    $rows = [
        ['Trades to Outcome (typical)', $ucNatural($g['avg_trades'], 'trade')],
        ['Time to Outcome (average)', $g['avg_days'] !== null ? formatDurationDays($g['avg_days']) : '-'],
        ['Time to Outcome (typical/median)', $g['median_days'] !== null ? formatDurationDays($g['median_days']) : '-'],
        ['Typical Winning Streak', $ucNatural($g['avg_max_win_streak'], 'consecutive win', 'consecutive wins')],
        ['Typical Losing Streak', $ucNatural($g['avg_max_loss_streak'], 'consecutive loss', 'consecutive losses')],
        ['Drawdown Before Outcome (average)', taVal($g['avg_max_drawdown_pct'], 1, '%')],
        ['Declared Risk (average)', taVal($p['avg_declared_risk_pct'], 2, '%')],
        ['Actual Risk Taken (average)', taVal($p['avg_actual_risk_pct'], 2, '%')],
        ['Reward : Risk (average)', $p['avg_rr'] !== null ? '1 : ' . number_format($p['avg_rr'], 2) : '-'],
        ['Win Rate', taVal($p['win_rate'], 1, '%')],
        ['Expectancy (per trade, in R)', $p['expectancy_r'] !== null ? number_format($p['expectancy_r'], 2) . 'R' : '-'],
        ['Recovery After a Loss', $g['n_recovery_samples'] > 0 ? ucfirst('typically recovered within ' . naturalCount($g['avg_recovery_trades'], 'trade')) : 'Not enough data yet'],
        ['Checklist Skip Rate', taVal($g['avg_checklist_skip_rate'], 1, '%')],
        ['Largest Risk Spike (average per segment)', taVal($g['avg_risk_spike'], 2, '%')],
    ];
    ?>
    <div class="rn-trade-journal">
        <h3 style="font-size:1rem;font-weight:800;margin-bottom:.9rem">Core Statistics</h3>
        <div class="ta-stats-grid">
        <?php foreach ($rows as [$label, $val]): ?>
            <div class="ta-stat-row"><span class="ta-stat-label"><?= htmlspecialchars($label) ?></span><span class="ta-stat-value"><?= $val ?></span></div>
        <?php endforeach; ?>
        </div>
    </div>
    <?php
}

function taRenderFindings(array $data, string $lens): void {
    if (empty($data['findings'])) return;
    ?>
    <div class="rn-trade-journal rn-psych-evidence" style="margin-top:0">
        <div class="rn-psych-evidence-title">Evidence-Backed Findings</div>
        <ul>
        <?php foreach ($data['findings'] as $f):
            $counts = $data['stats']['pooled']['classification_counts'];
            $n = ($f['filter']['attr'] ?? null) === 'classification' ? ($counts[$f['filter']['value']] ?? 0) : 0;
        ?>
            <li><?= htmlspecialchars($f['text']) ?><?= taViewTradesButton($f['filter'], $n) ?></li>
        <?php endforeach; ?>
        </ul>
    </div>
    <?php
}

function taRenderPatterns(array $data, string $lens): void {
    if (empty($data['patterns'])) return;
    $title = $lens === 'success' ? 'Success Patterns' : 'Failure Patterns';
    ?>
    <div class="rn-coaching">
        <div class="rn-coaching-head"><span class="rn-coaching-title"><?= htmlspecialchars($title) ?></span></div>
        <p style="font-size:.78rem;color:var(--foreground-dim);margin:-.8rem 0 1rem">Automatically discovered from real trade behavior: each line only appears when the underlying data actually shows it.</p>
        <ul style="list-style:none;display:flex;flex-direction:column;gap:.65rem">
        <?php foreach ($data['patterns'] as $p): ?>
            <li style="font-size:.82rem;color:var(--foreground-muted);line-height:1.6;padding-left:1.1rem;position:relative">
                <span style="position:absolute;left:0;top:.1rem;color:var(--rn-purple)">◆</span>
                <?= htmlspecialchars($p['text']) ?><?= taViewTradesButton($p['filter']) ?>
            </li>
        <?php endforeach; ?>
        </ul>
    </div>
    <?php
}

function taRenderBreachCauses(array $data, string $type): void {
    if (empty($data['breach_causes'])) return;
    $title = $type === 'prop' ? 'Most Common Breach Causes' : 'Most Common Reasons Accounts Closed at a Loss';
    $hasLegacy = false;
    foreach ($data['breach_causes'] as $c) { if ($c['label'] === 'Legacy data (reason unavailable)') $hasLegacy = true; }
    ?>
    <div class="rn-trade-journal">
        <h3 style="font-size:1rem;font-weight:800;margin-bottom:.9rem"><?= htmlspecialchars($title) ?></h3>
        <?php foreach ($data['breach_causes'] as $c): ?>
        <div class="ta-cause-row">
            <span class="ta-cause-label"><?= htmlspecialchars($c['label']) ?></span>
            <div class="ta-cause-bar"><div class="ta-cause-fill" style="width:<?= $c['pct'] ?>%"></div></div>
            <span class="ta-cause-count"><?= $c['count'] ?> (<?= $c['pct'] ?>%)</span>
        </div>
        <?php endforeach; ?>
        <?php if ($hasLegacy): ?>
        <p style="font-size:.74rem;color:var(--foreground-dim);margin-top:.8rem">"Legacy data" means this account's breach was recorded before a reason was required, not that a trader skipped filling it in. Every breach today requires a reason before it can be confirmed.</p>
        <?php endif; ?>
    </div>
    <?php
}

/** One comparison card, given the two sideSummary() arrays from TradingArchiveEngine::compareTwoGroups(). */
function taRenderCompareCard(array $cmp): void {
    $a = $cmp['a']; $b = $cmp['b'];
    $rows = [
        ['Pass / Success Rate', taVal($a['pass_rate'], 1, '%'), taVal($b['pass_rate'], 1, '%')],
        ['Sample Size', $a['n'] . ' resolved', $b['n'] . ' resolved'],
        ['Average Duration', $a['avg_days'] !== null ? formatDurationDays($a['avg_days']) : '-', $b['avg_days'] !== null ? formatDurationDays($b['avg_days']) : '-'],
        ['Average Drawdown', taVal($a['avg_max_drawdown_pct'], 1, '%'), taVal($b['avg_max_drawdown_pct'], 1, '%')],
        ['Win Rate', taVal($a['win_rate'], 1, '%'), taVal($b['win_rate'], 1, '%')],
        ['Expectancy', $a['expectancy_r'] !== null ? number_format($a['expectancy_r'], 2) . 'R' : '-', $b['expectancy_r'] !== null ? number_format($b['expectancy_r'], 2) . 'R' : '-'],
        ['Recovery Speed', $a['avg_recovery_trades'] !== null ? ucfirst(naturalCount($a['avg_recovery_trades'], 'trade')) : '-', $b['avg_recovery_trades'] !== null ? ucfirst(naturalCount($b['avg_recovery_trades'], 'trade')) : '-'],
    ];
    ?>
    <table class="ta-compare-table">
        <thead><tr><th></th><th><?= htmlspecialchars($a['label']) ?></th><th><?= htmlspecialchars($b['label']) ?></th></tr></thead>
        <tbody>
        <?php foreach ($rows as [$label, $av, $bv]): ?>
            <tr><td><?= htmlspecialchars($label) ?></td><td><?= $av ?></td><td><?= $bv ?></td></tr>
        <?php endforeach; ?>
        </tbody>
    </table>
    <?php
}

/**
 * Comparative Analytics — scoped per active type/program by
 * TradingArchiveEngine::comparativeAnalytics() (2026-07-31 context-
 * isolation fix; see that function's doc comment). A comparison entry is
 * now one of two shapes: a real two-sided compare card (['a'=>...,
 * 'b'=>...]), or an explicit ['message'=>...] note for when the data is
 * too thin — rendered as plain text instead of silently disappearing, so
 * e.g. Phase 3 on a 3-Step program always says something rather than just
 * not being there.
 */
function taRenderComparative(array $data): void {
    if (empty($data['comparative'])) return;
    $labels = [
        'one_step_vs_two_step' => '1 Step vs. 2 Step',
        'phase1_vs_phase2' => 'Phase 1 vs. Phase 2',
        'phase2_vs_phase3' => 'Phase 2 vs. Phase 3',
        'instant_vs_challenge' => 'Instant Funding vs. Standard Challenge',
        'broker_comparison' => 'Broker Comparison',
        'account_longevity' => 'Account Longevity',
    ];
    ?>
    <div class="rn-trade-journal">
        <h3 style="font-size:1rem;font-weight:800;margin-bottom:.3rem">Comparative Analytics</h3>
        <p style="font-size:.76rem;color:var(--foreground-dim);margin-bottom:1rem">Shown only where at least <?= TradingArchiveEngine::MIN_GROUP_SEGMENTS ?> resolved outcomes exist on both sides.</p>
        <?php foreach ($data['comparative'] as $key => $cmp): ?>
        <div style="margin-bottom:1.3rem">
            <div style="font-size:.82rem;font-weight:700;margin-bottom:.5rem"><?= htmlspecialchars($labels[$key] ?? $key) ?></div>
            <?php if (isset($cmp['message'])): ?>
            <p style="font-size:.8rem;color:var(--foreground-dim)"><?= htmlspecialchars($cmp['message']) ?></p>
            <?php else: taRenderCompareCard($cmp); endif; ?>
        </div>
        <?php endforeach; ?>
    </div>
    <?php
}

function taRenderMt5Note(array $data): void {
    $mt5 = $data['mt5'];
    ?>
    <div class="rn-trade-journal" style="opacity:.9">
        <h3 style="font-size:.9rem;font-weight:800;margin-bottom:.5rem">Broker (MT5) Reconciliation Analytics</h3>
        <?php if (!$mt5['ready']): ?>
        <p style="font-size:.78rem;color:var(--foreground-dim);line-height:1.6">
            Not yet available: 0 of <?= $mt5['total_trades'] ?> journaled trades are broker-reconciled yet. Once MT5 statements are reconciled,
            this section will automatically compute average holding duration (overall, and separately for winners vs. losers),
            overnight- and weekend-holding frequency, and a scalper/day-trader/swing-trader/position-trader breakdown. The analysis is
            already built, it simply has no reconciled data to run on yet.
        </p>
        <?php elseif ($data['mt5_duration'] === null): ?>
        <p style="font-size:.78rem;color:var(--foreground-dim);line-height:1.6">Some trades platform-wide are broker-reconciled, but none in this specific lens/type/program scope yet.</p>
        <?php else: $md = $data['mt5_duration']; ?>
        <div class="ta-stats-grid">
            <div class="ta-stat-row"><span class="ta-stat-label">Average Holding Duration</span><span class="ta-stat-value"><?= rnFormatDuration($md['avg_minutes']) ?></span></div>
            <div class="ta-stat-row"><span class="ta-stat-label">Avg Holding: Winners</span><span class="ta-stat-value"><?= rnFormatDuration($md['avg_minutes_winners']) ?></span></div>
            <div class="ta-stat-row"><span class="ta-stat-label">Avg Holding: Losers</span><span class="ta-stat-value"><?= rnFormatDuration($md['avg_minutes_losers']) ?></span></div>
            <div class="ta-stat-row"><span class="ta-stat-label">Overnight Holds</span><span class="ta-stat-value"><?= $md['overnight_count'] ?> (<?= $md['overnight_pct'] ?>%)</span></div>
            <div class="ta-stat-row"><span class="ta-stat-label">Weekend Holds</span><span class="ta-stat-value"><?= $md['weekend_count'] ?> (<?= $md['weekend_pct'] ?>%)</span></div>
            <div class="ta-stat-row"><span class="ta-stat-label">Scalper-Style Trades (≤2h)</span><span class="ta-stat-value"><?= $md['style_counts']['scalper'] ?></span></div>
            <div class="ta-stat-row"><span class="ta-stat-label">Day-Trader-Style Trades (≤24h)</span><span class="ta-stat-value"><?= $md['style_counts']['day_trader'] ?></span></div>
            <div class="ta-stat-row"><span class="ta-stat-label">Swing-Style Trades (≤5d)</span><span class="ta-stat-value"><?= $md['style_counts']['swing'] ?></span></div>
            <div class="ta-stat-row"><span class="ta-stat-label">Position-Style Trades (&gt;5d)</span><span class="ta-stat-value"><?= $md['style_counts']['position'] ?></span></div>
        </div>
        <?php endif; ?>
    </div>
    <?php
}

/**
 * The Trading Archive's ONE embedded trade table — every "View Trades"
 * button on this page (findings, patterns, breach causes) filters THIS
 * table via taFilterTrades(), never a second table. Adapted from Active
 * Journeys' renderRnTradeTable() for a multi-account context (adds
 * Account/Segment columns, carries extra data-* attributes for filtering
 * by phase/account/checklist/post-loss-behavior in addition to
 * classification) rather than modifying that approved component.
 */
function taRenderEvidenceTable(array $data): void {
    $rows = $data['evidence_rows'];
    ?>
    <div class="rn-trade-journal">
        <h3 style="font-size:1rem;font-weight:800;margin-bottom:.3rem">Evidence: Every Trade Behind This Page</h3>
        <p style="font-size:.76rem;color:var(--foreground-dim);margin-bottom:1rem">Every finding and pattern above links into this table. Click "View Trades" on any of them to filter it.</p>
        <div id="ta-filter-banner" class="rn-filter-banner" style="display:none">
            <span id="ta-filter-banner-text"></span>
            <button type="button" class="rn-btn-outline" onclick="taClearFilter()">Clear Filter ×</button>
        </div>
        <?php if (empty($rows)): ?>
        <div class="rn-empty-note">No closed trades in this scope yet.</div>
        <?php else: ?>
        <div class="rn-table-scroll">
        <table class="rn-table" id="ta-evidence-table">
            <thead>
                <tr>
                    <th>Date</th><th>Account</th><th>Segment</th><th>Instrument</th><th>Bias</th>
                    <th>Entry</th><th>Exit</th><th>P&amp;L (USD)</th><th>R</th><th>State</th><th>View</th>
                </tr>
            </thead>
            <tbody>
            <?php foreach ($rows as $idx => $r): $t = $r['trade'];
                [$stateLabel, $stateClass] = rnStateInfo($t['trade_classification'] ?? null);
                $entry = $t['actual_entry_price'] ?? $t['entry_price'];
                $exit = $t['actual_exit_price'] ?? null;
                // Same real fallback as TradingArchiveEngine::tradeRMultiple()
                // (2026-08-06) — max_potential_loss first, risk_per_position
                // when that column is genuinely empty. This function is
                // currently unreachable (see renderTradingArchive()'s own
                // doc comment) so it can't call that private engine method
                // directly; duplicated inline rather than widening the
                // class's public API for dead code.
                $maxLoss = $t['max_potential_loss'] ?? null;
                $riskDenom = ($maxLoss !== null && $maxLoss !== '' && (float)$maxLoss > 0) ? (float)$maxLoss
                    : ((isset($t['risk_per_position']) && $t['risk_per_position'] !== null && $t['risk_per_position'] !== '' && (float)$t['risk_per_position'] > 0) ? (float)$t['risk_per_position'] : null);
                $rMult = $riskDenom !== null ? $r['pnl'] / $riskDenom : null;
                $ticked = $t['ticked_pct'] ?? null;
                $checklistSkipped = ($ticked === null || (float)$ticked < 100) ? '1' : '0';
                $isSpike = in_array($t['id'], $data['post_loss_spike_ids'], true) ? '1' : '0';
                $isPause = in_array($t['id'], $data['post_loss_pause_ids'], true) ? '1' : '0';
                $isExtra = $idx >= 8;
                $detailUrl = '/traderalign/journal?' . http_build_query(['trade_id' => $t['id']]);
            ?>
                <tr data-classification="<?= htmlspecialchars($t['trade_classification'] ?? '') ?>"
                    data-account="<?= htmlspecialchars($r['_account_id']) ?>"
                    data-phase="<?= htmlspecialchars($r['_phase_label']) ?>"
                    data-checklist-skipped="<?= $checklistSkipped ?>"
                    data-post-loss-spike="<?= $isSpike ?>"
                    data-post-loss-pause="<?= $isPause ?>"
                    <?= $isExtra ? ' class="rn-row-extra" style="display:none"' : '' ?>>
                    <td><?= !empty($t['closed_at']) ? date('d M Y', strtotime($t['closed_at'])) : '-' ?></td>
                    <td style="font-family:var(--font-sans);font-size:.74rem"><?= htmlspecialchars($r['_account_label']) ?></td>
                    <td><span class="rn-badge rn-badge-neutral" style="font-family:var(--font-sans)"><?= htmlspecialchars($r['_phase_label']) ?></span></td>
                    <td><?= !empty($t['instrument']) ? htmlspecialchars(strtoupper($t['instrument'])) : '-' ?></td>
                    <td class="<?= ($t['direction'] ?? '') === 'long' ? 'positive' : 'negative' ?>"><?= ($t['direction'] ?? '') === 'long' ? 'Long' : 'Short' ?></td>
                    <td><?= ($entry !== null && $entry !== '') ? number_format((float)$entry, 4) : '-' ?></td>
                    <td><?= ($exit !== null && $exit !== '') ? number_format((float)$exit, 4) : '-' ?></td>
                    <td class="<?= pnlClass($r['pnl']) ?>"><?= pnlFormat($r['pnl']) ?></td>
                    <td class="<?= $rMult === null ? '' : ($rMult >= 0 ? 'positive' : 'negative') ?>"><?= $rMult === null ? '-' : (($rMult >= 0 ? '+' : '') . number_format($rMult, 2) . 'R') ?></td>
                    <td><span class="rn-state <?= $stateClass ?>"><?= htmlspecialchars($stateLabel) ?></span></td>
                    <td><a href="<?= htmlspecialchars($detailUrl) ?>" class="rn-view-btn">View</a></td>
                </tr>
            <?php endforeach; ?>
            </tbody>
        </table>
        </div>
        <?php if (count($rows) > 8): ?>
        <div class="rn-table-more-wrap">
            <button type="button" class="rn-show-more-btn" data-table="ta-evidence-table" data-more-label="Show More (<?= count($rows) - 8 ?> more)" onclick="rnToggleTableRows(this)">Show More (<?= count($rows) - 8 ?> more)</button>
        </div>
        <?php endif; ?>
        <?php endif; ?>
    </div>
    <?php
}

/**
 * ════════════════════════════════════════════════════════════════════
 * Lessons From Success — single-account ARCHIVED JOURNEY (rebuilt
 * 2026-08-05; see TradingArchiveEngine::buildAccountSuccessJourney()'s
 * own doc comment for the full architecture). Everything below renders
 * ONLY from that one function's output, for the ONE account currently
 * selected via the account picker (taRenderSuccessAccountPicker() above
 * — rendered by renderTradingArchive() before this pipeline runs). No
 * blended/portfolio averages, no date-range filter, no period-
 * comparison language ("vs last month/quarter"), and no Export button
 * anywhere in this pipeline, per the explicit brief — this page answers
 * "how did THIS ONE account succeed", never "how did this period
 * compare to another one" and never "how do all my accounts compare".
 * ════════════════════════════════════════════════════════════════════
 */

/** Small null-safe number formatter, mirrors taVal() above — kept as its own function since this pipeline is intentionally self-contained. */
function taSVal($v, int $decimals = 1, string $suffix = ''): string {
    if ($v === null) return '-';
    return number_format((float)$v, $decimals) . $suffix;
}

/**
 * Small colored-circle SVG icons for the 5 KPI cards — color hierarchy
 * (green=journey status, purple=timing, blue=risk, gold=performance,
 * teal=volume) made visible, not just described. Plain inline stroke
 * SVGs, no icon font/library dependency, matching this page's existing
 * dependency-free SVG convention (see tl4RenderComplianceRing()
 * elsewhere in this file).
 */
function taSuccessKpiIcon(string $key): string {
    $paths = [
        'accounts' => '<circle cx="10" cy="10" r="7.5"/><path d="M6.5 10.2l2.3 2.3 4.7-4.9" stroke-linecap="round" stroke-linejoin="round"/>',
        'time' => '<circle cx="10" cy="10" r="7.5"/><path d="M10 5.5V10l3 1.8" stroke-linecap="round" stroke-linejoin="round"/>',
        'drawdown' => '<path d="M10 3l6 2.5v4.3c0 4-2.6 6.7-6 7.7-3.4-1-6-3.7-6-7.7V5.5L10 3z" stroke-linejoin="round"/><path d="M7.3 10.2l1.9 1.9 3.5-4" stroke-linecap="round" stroke-linejoin="round"/>',
        'winrate' => '<circle cx="10" cy="10" r="7.5"/><circle cx="10" cy="10" r="4.2"/><circle cx="10" cy="10" r="1"/>',
        'trades' => '<rect x="3" y="3" width="6" height="6" rx="1"/><rect x="11" y="3" width="6" height="6" rx="1"/><rect x="3" y="11" width="6" height="6" rx="1"/><rect x="11" y="11" width="6" height="6" rx="1"/>',
    ];
    $inner = $paths[$key] ?? '';
    return '<svg viewBox="0 0 20 20" class="ta-kpi-icon-svg" fill="none" stroke="currentColor" stroke-width="1.4">' . $inner . '</svg>';
}

function taRenderSuccessLearning(array $data, string $type, string $program, string $programLabel): void {
    if ($data['empty'] ?? true) {
        ?>
        <div class="empty-state">
            <h3><?= htmlspecialchars($programLabel) ?> - Lessons From Success</h3>
            <p style="font-size:.85rem">
                No <?= $type === 'prop' ? 'phases or accounts have' : 'accounts have' ?> succeeded yet in this scope.
                Once a real <?= $type === 'prop' ? 'phase pass or funded account' : 'account' ?> exists here, this page
                computes real statistics and habits directly from it. Nothing here is ever invented ahead of the data.
            </p>
        </div>
        <?php
        return;
    }

    if ($type === 'live') {
        // Live Accounts single-account rebuild (2026-08-06), matching
        // Kevin's approved prototype exactly. Kept as its own dispatch
        // branch rather than threading $isLive checks through the
        // existing prop-firm functions below, so nothing here can ever
        // accidentally change what a Prop Firms visitor sees.
        taLiveSuccessKpiCards($data);
        taLiveSuccessGrowthSection($data);
        taLiveSuccessGoalAchievement($data);
        taLiveSuccessGoalSpeed($data);
        taLiveSuccessGoalReasons($data);
        taLiveSuccessGoalPrevention($data);
        taLiveSuccessFinancialBehaviour($data);
        taLiveSuccessDepositWithdrawal($data);
        taLiveSuccessInterruptionsQualityLongevity($data);
        taLiveSuccessInstrumentsAndTimeline($data);
        taSuccessEvidenceTrades($data);
        return;
    }

    // Prop-firm single-account rebuild (2026-08-07) — brought to the same
    // design/polish standard as Lessons From Failure's own single-account
    // rebuild (page banner, an Account Rules & Thresholds card, a Risk &
    // Behavior Insights card, a closing footer), adapted for a
    // passed/funded account rather than copied verbatim — see
    // TradingArchiveEngine::successRulesThresholds()'s own doc comment for
    // what's genuinely new vs. reused. Live Accounts (the branch above)
    // is completely untouched by this pass.
    taSuccessPageHeader($data);
    taSuccessKpiCards($data);
    // Full-width, stacked — not a 2-col row (a side-by-side pairing
    // between two cards of genuinely different natural heights either
    // stretches the shorter one into empty space, or leaves a floating
    // gap before the next section — confirmed live earlier this session).
    if (!empty($data['pass_story']['available'])) taSuccessPassStory($data);
    if (!empty($data['execution_discipline']['available'])) taSuccessExecutionDiscipline($data);
    taSuccessSectionTwo($data);
    taSuccessFundedGoalSection($data);
    taSuccessSectionFour($data);
    taSuccessEvidenceTrades($data);
    taSuccessFooter();
}

/**
 * Page banner — the success-lens counterpart to Lessons From Failure's own
 * .ta-fail-page-header, same "icon + title in a real card container"
 * treatment (praised directly, per this component's own commit history)
 * but in this page's own green identity rather than a reskinned red one.
 * Deliberately generic copy (not account-specific) — the account's own
 * real current stage is already stated, dynamically, directly below the
 * account picker via taSuccessJourneySubtitle(), one level up in
 * renderTradingArchive(); repeating it here would just be the same
 * sentence twice.
 */
function taSuccessPageHeader(array $data): void {
    ?>
    <div class="rn-trade-journal ta-success-page-header">
        <div class="ta-success-page-header-icon">🏆</div>
        <div>
            <h1 class="rn-title">Lessons From Success <span class="ta-card-h3-note">(Advancing Accounts)</span></h1>
            <div class="rn-subtitle">Learn what worked on this account so you can repeat it.</div>
        </div>
    </div>
    <?php
}

/**
 * "What Created The Pass" (2026-08-07, correction pass) — a genuinely
 * success-oriented narrative card, REPLACING an earlier "Account Rules &
 * Thresholds" card that reused Failure's own target/limit/exceeded
 * framing almost verbatim. See TradingArchiveEngine::successStory()'s own
 * doc comment for the full reasoning — this renders that function's real,
 * computed narrative (growth achieved, consistency, checklist follow-
 * through, resilience through a real losing stretch) as one paragraph,
 * never a grid of dollar comparisons. Reuses the same icon-+-paragraph
 * shape as Lessons From Failure's own narrative cards (.ta-avoid-body) —
 * but its OWN icon tone (.ta-avoid-icon-yes, already green in this app's
 * existing palette) rather than that card's "yes/no verdict" pairing,
 * since this page never needs a red "no" state at all.
 */
function taSuccessPassStory(array $data): void {
    $s = $data['pass_story'];
    ?>
    <div class="rn-trade-journal ta-success-tint">
        <h3 class="ta-card-h3">What Created The Pass</h3>
        <div class="ta-avoid-body">
            <div class="ta-avoid-icon ta-avoid-icon-yes">📈</div>
            <div>
                <p class="ta-avoid-explain" style="margin-bottom:0"><?= htmlspecialchars($s['narrative']) ?></p>
            </div>
        </div>
    </div>
    <?php
}

/**
 * "Execution Discipline" (2026-08-07, correction pass) — REPLACES an
 * earlier "Risk & Behavior Insights" card that reused Lessons From
 * Failure's own tile SET (avg risk vs. plan, highest risk, losing
 * streak, daily-loss-limit breaches, trades over plan risk, time in
 * drawdown) almost unchanged. See TradingArchiveEngine::
 * successExecutionDiscipline()'s own doc comment for why every one of
 * these six tiles is a genuinely different metric answering "what
 * discipline produced this pass" — none of them is ever colored red on
 * this page (the engine never emits a 'negative' tone here at all); a
 * tile that hasn't cleared its own honest bar renders in this app's
 * existing neutral gold accent, never green it hasn't earned, and never
 * failure's red.
 */
function taSuccessExecutionDiscipline(array $data): void {
    ?>
    <div class="rn-trade-journal ta-success-tint">
        <h3 class="ta-card-h3">Execution Discipline</h3>
        <div class="ta-difficulty-grid ta-difficulty-grid-2col">
            <?php foreach ($data['execution_discipline']['tiles'] as $tile): $isGreen = $tile['tone'] === 'positive'; ?>
            <div class="ta-difficulty-tile">
                <div class="ta-difficulty-label"><?= htmlspecialchars($tile['label']) ?></div>
                <div class="ta-difficulty-score" style="<?= $isGreen ? 'color:var(--rn-green)' : '' ?>"><?= htmlspecialchars($tile['value']) ?></div>
                <?php if ($tile['note'] !== null): ?><div class="ta-difficulty-explain" style="<?= $isGreen ? 'color:var(--rn-green)' : '' ?>"><?= htmlspecialchars($tile['note']) ?></div><?php endif; ?>
            </div>
            <?php endforeach; ?>
        </div>
    </div>
    <?php
}

/** Closing footer — the success-lens counterpart to Lessons From Failure's own .ta-fail-footer, same treatment in this page's green identity. */
function taSuccessFooter(): void {
    ?>
    <div class="ta-success-footer">
        <span class="ta-success-footer-icon">🏆</span>
        Every success leaves real evidence behind. Study what worked here, and repeat it on purpose.
    </div>
    <?php
}

/**
 * Section 1 — five equal KPI cards, all scoped to the ONE selected
 * account: Journey Status (this account's real current stage — never a
 * blanket "Passed"), Journey Duration, Maximum Drawdown, Challenge/Win
 * Rate, Trades Taken. No cross-account averaging anywhere, and no trend
 * arrows — a single account's own finished/in-progress journey has no
 * "earlier vs. recent attempts" of its own to compare against.
 */
function taSuccessKpiCards(array $data): void {
    $kpi = $data['kpi'];
    $stage = $data['stage'];
    $isLive = $data['type'] === 'live';
    $isInstantFunding = $data['is_instant_funding'];

    $durationSub = $isInstantFunding
        ? "Across this account's full Instant Funding journey."
        : ($isLive
            ? 'From account creation to account closure.'
            : ($stage['short'] === 'Funded'
                ? 'From account creation to funded status.'
                : (!empty($stage['in_progress'])
                    ? 'From account creation to today, while attempting ' . $stage['short'] . '.'
                    : 'From account creation to ' . $stage['short'] . ' completion.')));
    $winRateLabel = $isLive ? 'Win Rate' : 'Challenge Win Rate';
    $winRateSub = $isLive ? 'Winning trades across this account.' : 'Winning trades during this challenge.';
    $tradesSub = $isLive ? 'Total trades taken on this account.' : 'Total trades taken during the challenge.';
    $stageColor = match ($stage['badge']) {
        'gold' => 'var(--rn-gold)', 'green' => 'var(--rn-green)', 'blue' => 'var(--rn-blue)', default => 'var(--rn-purple)',
    };
    ?>
    <div class="ta-kpi-grid">
        <div class="ta-kpi-card">
            <div class="ta-kpi-icon ta-kpi-icon-green"><?= taSuccessKpiIcon('accounts') ?></div>
            <div class="ta-kpi-label">Journey Status</div>
            <div class="ta-kpi-value" style="color:<?= $stageColor ?>"><?php if (!empty($stage['in_progress'])): ?><span class="ta-live-dot"></span><?php endif; ?><?= htmlspecialchars($stage['short']) ?></div>
            <div class="ta-kpi-sub"><?= htmlspecialchars($stage['phrase']) ?></div>
        </div>
        <div class="ta-kpi-card">
            <div class="ta-kpi-icon ta-kpi-icon-purple"><?= taSuccessKpiIcon('time') ?></div>
            <div class="ta-kpi-label">Journey Duration</div>
            <div class="ta-kpi-value"><?= $kpi['journey_days'] !== null ? htmlspecialchars(formatTradingJourneyDuration($kpi['journey_days'])) : '-' ?></div>
            <div class="ta-kpi-footnote"><?= htmlspecialchars($durationSub) ?></div>
        </div>
        <div class="ta-kpi-card">
            <div class="ta-kpi-icon ta-kpi-icon-blue"><?= taSuccessKpiIcon('drawdown') ?></div>
            <div class="ta-kpi-label">Maximum Drawdown</div>
            <div class="ta-kpi-value"><?= taSVal($kpi['max_drawdown_pct'], 1, '%') ?></div>
            <div class="ta-kpi-footnote">Highest drawdown recorded during this journey.</div>
        </div>
        <div class="ta-kpi-card">
            <div class="ta-kpi-icon ta-kpi-icon-gold"><?= taSuccessKpiIcon('winrate') ?></div>
            <div class="ta-kpi-label"><?= htmlspecialchars($winRateLabel) ?></div>
            <div class="ta-kpi-value"><?= taSVal($kpi['win_rate'], 1, '%') ?></div>
            <div class="ta-kpi-footnote"><?= htmlspecialchars($winRateSub) ?></div>
        </div>
        <div class="ta-kpi-card">
            <div class="ta-kpi-icon ta-kpi-icon-teal"><?= taSuccessKpiIcon('trades') ?></div>
            <div class="ta-kpi-label">Trades Taken</div>
            <div class="ta-kpi-value"><?= (int)$kpi['trades_taken'] ?></div>
            <div class="ta-kpi-footnote"><?= htmlspecialchars($tradesSub) ?></div>
        </div>
    </div>
    <?php
}

/** Section 2 — Pass Rate by Level (or the Instant Funding/Live activity overview) · Time to Pass by Level (or Trade Frequency) — scoped to the one selected account. "Strongest Success Habits" used to be a third card here (2026-08-10: deleted) — its two facts with no equivalent in Your Winning Edge (Best Session, Checklist Adherence) are now rows inside that existing card (Section 4) instead of a separate card repeating several of the same facts. */
function taSuccessSectionTwo(array $data): void {
    ?>
    <div class="ta-section-grid-2">
        <div class="rn-trade-journal">
            <?php if ($data['has_phase_concept']): ?>
                <h3 class="ta-card-h3">Pass Rate by Level</h3>
                <?php taSuccessLevelDonut($data['levels']); ?>
            <?php else: ?>
                <h3 class="ta-card-h3"><?= $data['is_instant_funding'] ? 'Funding Overview' : 'Account Overview' ?></h3>
                <?php taSuccessActivityOverview($data['activity_overview'], $data['is_instant_funding']); ?>
            <?php endif; ?>
        </div>

        <div class="rn-trade-journal">
            <?php if ($data['has_phase_concept']): ?>
                <h3 class="ta-card-h3">Time to Pass by Level</h3>
                <?php taSuccessLevelBars($data['levels']); ?>
            <?php else: ?>
                <?php // Business rule: Instant Funding and Live Accounts have
                      // no Phase 1/2/3 concept — this card never mentions
                      // levels/phases for either, and shows a genuinely
                      // relevant real stat instead (how often this account
                      // actually traded). ?>
                <h3 class="ta-card-h3">Trade Frequency</h3>
                <?php taSuccessTradeFrequency($data['activity_overview']); ?>
            <?php endif; ?>
        </div>
    </div>
    <?php
}

/**
 * Pass Rate by Level — this ONE account's own real level-by-level
 * outcome, never a population-wide weighted average. Four honest
 * states per level: "Passed" (a fully, unambiguously finished phase —
 * including this account's own highest resolved phase, per direct
 * feedback: a finished phase computes and displays exactly like any
 * other passed phase, full stop; the "this app never auto-promotes"
 * distinction belongs on the NEXT level, not on the one that's already
 * done — see accountLevels()'s own doc comment), "Active" (a real,
 * live, glowing-dot-marked state — currently, really being attempted
 * right now), "Ready to Promote" (the very next stage — a real,
 * one-click-away target once the current phase resolves, computed as
 * nothing more than a placeholder until the trader actually promotes),
 * or "Coming Next"/"Next Target" (genuinely not reached yet — Funded
 * gets its own wording since it's the account's ultimate goal, not
 * just another phase). Wedges are equal-sized by level count — there
 * is no "resolved-attempt weight" concept for a single account the way
 * there was for the old population-wide version. "Overall Pass Rate"
 * is the real share of ATTEMPTED levels (passed or currently active)
 * this account has cleared — "Ready to Promote" levels are excluded
 * from the denominator too, since the account hasn't actually started
 * them yet, only earned the option to.
 */
function taSuccessLevelDonut(array $levels): void {
    if (empty($levels)) { echo '<p class="ta-empty-note">Not enough historical data yet.</p>'; return; }
    $colors = ['Phase 1' => '#26A69A', 'Phase 2' => '#A78BFA', 'Phase 3' => '#E09B3A', 'Funded' => '#E0A64A'];
    $n = count($levels);
    $share = 100 / $n;
    $gap = $n > 1 ? 1.0 : 0.0;
    $offset = 0.0;
    $unattempted = ['not_reached', 'ready_to_promote'];
    $attempted = array_values(array_filter($levels, fn($l) => !in_array($l['status'], $unattempted, true)));
    $overallPct = !empty($attempted) ? round(count(array_filter($attempted, fn($l) => in_array($l['status'], ['passed', 'passed_awaiting_promotion', 'funded'], true))) / count($attempted) * 100, 0) : null;
    ?>
    <div class="ta-donut-wrap">
        <svg viewBox="0 0 36 36" class="ta-donut-svg" role="img" aria-label="Pass rate by level">
            <?php foreach ($levels as $l):
                $reached = !in_array($l['status'], $unattempted, true);
                $color = $reached ? ($colors[$l['label']] ?? '#60A5FA') : 'var(--border)';
                $dash = max(0, $share - $gap);
            ?>
            <circle cx="18" cy="18" r="15.9155" fill="none" stroke="<?= $color ?>" stroke-width="4.3" opacity="<?= $reached ? '1' : '.35' ?>"
                stroke-dasharray="<?= number_format($dash, 3) ?> <?= number_format(100 - $dash, 3) ?>"
                stroke-dashoffset="<?= number_format(-$offset, 3) ?>" transform="rotate(-90 18 18)" stroke-linecap="round" />
            <?php $offset += $share; endforeach; ?>
            <text x="18" y="16.5" text-anchor="middle" class="ta-donut-value"><?= $overallPct !== null ? number_format($overallPct, 0) . '%' : '-' ?></text>
            <text x="18" y="21.5" text-anchor="middle" class="ta-donut-label">Overall Pass Rate</text>
        </svg>
        <div class="ta-donut-legend">
            <?php foreach ($levels as $l): $reached = !in_array($l['status'], $unattempted, true); $color = $reached ? ($colors[$l['label']] ?? '#60A5FA') : 'var(--border)'; ?>
            <div class="ta-donut-legend-row">
                <span class="ta-donut-swatch" style="background:<?= $color ?>"></span>
                <span class="ta-donut-legend-label"><?= htmlspecialchars($l['label']) ?></span>
                <span class="ta-donut-legend-value">
                <?php if ($l['status'] === 'passed' || $l['status'] === 'passed_awaiting_promotion'): ?>Passed
                <?php elseif ($l['status'] === 'active' || $l['status'] === 'funded'): ?><span class="ta-live-dot"></span>Active
                <?php elseif ($l['status'] === 'ready_to_promote'): ?><span class="ta-donut-legend-frac">Ready to Promote</span>
                <?php elseif ($l['label'] === 'Funded'): ?><span class="ta-donut-legend-frac">Next Target</span>
                <?php else: ?><span class="ta-donut-legend-frac">Coming Next</span>
                <?php endif; ?>
                </span>
            </div>
            <?php endforeach; ?>
        </div>
    </div>
    <?php
}

/**
 * Time to Pass by Level — this account's own real per-level duration, in
 * journey-friendly Trading Day terms (formatTradingJourneyDuration() —
 * never hours/minutes/decimals). A level not yet reached shows an
 * honest dimmed "Upcoming" bar; the level this account is genuinely
 * working on right now shows "In Progress" instead — never a fabricated
 * duration for either case.
 */
function taSuccessLevelBars(array $levels): void {
    if (empty($levels)) { echo '<p class="ta-empty-note">Not enough historical data yet.</p>'; return; }
    // Bar width is driven by the same rounded, whole-Trading-Day count the
    // label text actually shows (via formatTradingJourneyDuration()'s own
    // "<=1 day always reads as 1 Trading Day" floor) — NOT the raw
    // fractional day value. Using the raw value here produced a real, live
    // bug: two levels that both display "1 Trading Day" (e.g. 0.16 real
    // days vs. 0.003 real days) rendered wildly different bar widths, since
    // 0.003 is ~50x smaller than 0.16 even though neither is distinguishable
    // in the displayed text. Rounding first means every level that reads
    // "1 Trading Day" gets an identical, equal-width bar; only real
    // multi-day differences (which the text also spells out, e.g. "5
    // Trading Days" vs "1 Trading Day") still scale proportionally.
    $maxDays = 0.0;
    foreach ($levels as $l) {
        if ($l['days'] === null) continue;
        $rounded = max(1.0, (float)round($l['days']));
        if ($rounded > $maxDays) $maxDays = $rounded;
    }
    if ($maxDays <= 0) $maxDays = 1.0;
    ?>
    <div class="ta-bars-wrap">
        <?php foreach ($levels as $l): ?>
        <div class="ta-bar-row">
            <span class="ta-bar-label"><?= htmlspecialchars($l['label']) ?></span>
            <?php if ($l['days'] !== null): $daysRounded = max(1.0, (float)round($l['days'])); $pct = min(100, ($daysRounded / $maxDays) * 100); ?>
            <div class="ta-bar-track"><div class="ta-bar-fill" style="width:<?= number_format($pct, 1) ?>%"></div></div>
            <span class="ta-bar-value"><?= htmlspecialchars(formatTradingJourneyDuration($l['days'])) ?></span>
            <?php elseif ($l['status'] === 'active'): ?>
            <div class="ta-bar-track ta-bar-track-active"></div>
            <span class="ta-bar-value ta-bar-value-active"><span class="ta-live-dot"></span>In Progress</span>
            <?php elseif (in_array($l['status'], ['passed', 'passed_awaiting_promotion', 'funded'], true)): ?>
            <?php // A resolved level with no recoverable start/end dates
                  // (no matching trade segment on record) — real but
                  // undated, never mislabeled "Upcoming". ?>
            <div class="ta-bar-track ta-bar-track-upcoming"></div>
            <span class="ta-bar-value ta-bar-value-upcoming">-</span>
            <?php elseif ($l['status'] === 'ready_to_promote'): ?>
            <div class="ta-bar-track ta-bar-track-active"></div>
            <span class="ta-bar-value ta-bar-value-active">Ready to Promote</span>
            <?php else: ?>
            <div class="ta-bar-track ta-bar-track-upcoming"></div>
            <span class="ta-bar-value ta-bar-value-upcoming">- (Upcoming)</span>
            <?php endif; ?>
        </div>
        <?php endforeach; ?>
    </div>
    <?php
}

/**
 * The "no phase concept" replacement for Section Two's first card —
 * Instant Funding (no phases, ever) and Live Accounts (no evaluation/
 * phase concept either). Real, simple facts about this one account's
 * own activity — never a fabricated population-wide "success rate"
 * that only made sense pooled across many accounts.
 */
function taSuccessActivityOverview(array $overview, bool $isInstantFunding): void {
    if (!$overview['available']) { echo '<p class="ta-empty-note">Not enough historical data yet.</p>'; return; }
    $startLabel = $isInstantFunding ? 'Funded Since' : 'Opened On';
    ?>
    <div class="ta-stats-grid" style="grid-template-columns:1fr">
        <div class="ta-stat-row">
            <span class="ta-stat-label"><?= htmlspecialchars($startLabel) ?></span>
            <span class="ta-stat-value"><?= !empty($overview['start_date']) ? date('d M Y', strtotime($overview['start_date'])) : '-' ?></span>
        </div>
        <div class="ta-stat-row">
            <span class="ta-stat-label">Journey Length</span>
            <span class="ta-stat-value"><?= $overview['days'] !== null ? htmlspecialchars(formatTradingJourneyDuration($overview['days'])) : '-' ?></span>
        </div>
        <div class="ta-stat-row">
            <span class="ta-stat-label">Trades Taken</span>
            <span class="ta-stat-value"><?= (int)$overview['trades'] ?></span>
        </div>
    </div>
    <?php
}

/** Trade Frequency — the Instant Funding/Live counterpart to "Time to Pass by Level." A real, computed trades-per-week figure for this one account, never a fabricated pace. */
function taSuccessTradeFrequency(array $overview): void {
    if (!$overview['available'] || $overview['trades_per_week'] === null) { echo '<p class="ta-empty-note">Not enough historical data yet.</p>'; return; }
    ?>
    <div class="ta-survival-rate">
        <div class="ta-survival-value"><?= number_format($overview['trades_per_week'], 1) ?></div>
        <div class="ta-survival-sub">trades per week, on average, across this account's real trading history</div>
    </div>
    <?php
}

/** Generic label→count bucket renderer (used for Goal Size Distribution, whose buckets aren't pre-computed with a pct by the engine). */
function taSuccessBucketList(array $counts, string $color): void {
    if (empty($counts)) { echo '<p class="ta-empty-note">Not enough historical data yet.</p>'; return; }
    $total = array_sum($counts);
    arsort($counts);
    foreach ($counts as $label => $count) {
        $pct = $total > 0 ? round($count / $total * 100, 1) : 0;
        ?>
        <div class="ta-cause-row">
            <span class="ta-cause-label"><?= htmlspecialchars($label) ?></span>
            <div class="ta-cause-bar"><div class="ta-cause-fill" style="width:<?= $pct ?>%;background:<?= htmlspecialchars($color) ?>"></div></div>
            <span class="ta-cause-count"><?= $count ?> (<?= $pct ?>%)</span>
        </div>
        <?php
    }
}

/** Generic [label,count,pct] bar renderer (used for How Quickly Goals Are Reached and Delay Factors, whose buckets already carry a real pct from the engine). */
function taSuccessBarList(array $items, string $color): void {
    if (empty($items)) { echo '<p class="ta-empty-note">Not enough historical data yet.</p>'; return; }
    foreach ($items as $it) {
        ?>
        <div class="ta-cause-row">
            <span class="ta-cause-label"><?= htmlspecialchars($it['label']) ?></span>
            <div class="ta-cause-bar"><div class="ta-cause-fill" style="width:<?= $it['pct'] ?>%;background:<?= htmlspecialchars($color) ?>"></div></div>
            <span class="ta-cause-count"><?= $it['count'] ?> (<?= $it['pct'] ?>%)</span>
        </div>
        <?php
    }
}

/** Section 3 — Funded Goal Achievement. Renders nothing at all when the engine says this scope has no eligible/goal-bearing accounts, per the brief's own "only show when funded accounts exist" instruction. */
function taSuccessFundedGoalSection(array $data): void {
    $fg = $data['funded_goal'];
    if (!$fg['applicable']) return;
    $achieved = $fg['goals_achieved']; $total = $fg['goals_set']; $missed = max(0, $total - $achieved);
    $achievedShare = $total > 0 ? ($achieved / $total) * 100 : null;
    // Both "Average" stats below need their OWN real sample size before
    // they're shown as a number — a 1-goal "average" is not a average
    // worth trusting. Neither collapses the tile when thin; both render
    // a "—" placeholder plus the exact helper text the brief asked for
    // ("Need at least 3 achieved goals."), matching MIN_GROUP_SEGMENTS
    // (the same 3-sample floor every other group-level stat on this page
    // already uses).
    $minGoalSamples = TradingArchiveEngine::MIN_GROUP_SEGMENTS;
    $timeReady = $fg['n_time_to_goal_samples'] >= $minGoalSamples;
    $completionReady = $fg['n_completion_samples'] >= $minGoalSamples;
    // §2 Live #4 fix (2026-08-10) — "Goal Achievement Rate" (both the
    // top-grid stat and its own donut) and "Goal Size Distribution" were
    // rendering an unconditional, confident-looking figure/chart from as
    // few as ONE real goal, directly beside "Average Time to Goal"'s own
    // honest "Need at least 3" disclaimer on the exact same card, about
    // the exact same underlying goal count. Gated on the same
    // MIN_GROUP_SEGMENTS floor every other group-level stat on this page
    // already uses, keyed off $total (goals SET, not just achieved) — a
    // rate/distribution needs a real population to be meaningful
    // regardless of how many of them succeeded.
    $achievementReady = $total >= $minGoalSamples;
    ?>
    <div class="rn-trade-journal">
        <h3 class="ta-card-h3" style="margin-bottom:.2rem">Funded Goal Achievement <span class="ta-card-h3-note">(Funded Accounts Only)</span></h3>
        <p class="ta-empty-note" style="margin-bottom:1.2rem">Real growth targets set on your funded/live accounts, and how they actually played out.</p>

        <div class="ta-goal-top-grid">
            <div class="ta-goal-stat"><div class="ta-goal-stat-label">Goals Set</div><div class="ta-goal-stat-value"><?= $fg['goals_set'] ?></div></div>
            <div class="ta-goal-stat"><div class="ta-goal-stat-label">Goals Achieved</div><div class="ta-goal-stat-value"><?= $fg['goals_achieved'] ?></div></div>
            <div class="ta-goal-stat">
                <div class="ta-goal-stat-label">Goal Achievement Rate</div>
                <div class="ta-goal-stat-value" style="color:var(--rn-green)"><?= $achievementReady ? taSVal($fg['achievement_pct'], 0, '%') : '-' ?></div>
                <div class="ta-goal-stat-sub"><?= $achievementReady ? ($fg['goals_achieved'] . ' out of ' . $fg['goals_set']) : "Need at least {$minGoalSamples} goals set." ?></div>
            </div>
            <div class="ta-goal-stat">
                <div class="ta-goal-stat-label">Average Time to Goal</div>
                <div class="ta-goal-stat-value"><?= $timeReady ? htmlspecialchars(formatDurationNatural($fg['avg_time_to_goal_days'])) : '-' ?></div>
                <?php if (!$timeReady): ?><div class="ta-goal-stat-sub">Need at least <?= $minGoalSamples ?> achieved goals.</div><?php endif; ?>
            </div>
            <div class="ta-goal-stat">
                <div class="ta-goal-stat-label">Average Goal Completion</div>
                <div class="ta-goal-stat-value"><?= $completionReady ? taSVal($fg['avg_completion_pct'], 0, '%') : '-' ?></div>
                <div class="ta-goal-stat-sub"><?= $completionReady ? 'of target' : "Need at least {$minGoalSamples} resolved goals." ?></div>
            </div>
        </div>

        <div class="ta-goal-bottom-grid">
            <div>
                <h4 class="ta-goal-subhead">Goal Achievement Rate</h4>
                <?php if (!$achievementReady): ?>
                <p class="ta-empty-note">Need at least <?= $minGoalSamples ?> goals set to show a reliable rate.</p>
                <?php elseif ($total === 0 || $achievedShare === null): ?>
                <p class="ta-empty-note">Not enough historical data yet.</p>
                <?php else: ?>
                <div class="ta-donut-wrap">
                    <svg viewBox="0 0 36 36" class="ta-donut-svg" role="img" aria-label="Goal achievement rate">
                        <circle cx="18" cy="18" r="15.9155" fill="none" stroke="var(--border)" stroke-width="4.3" />
                        <circle cx="18" cy="18" r="15.9155" fill="none" stroke="var(--rn-green)" stroke-width="4.3"
                            stroke-dasharray="<?= number_format(max(0, $achievedShare - ($achievedShare > 0 && $achievedShare < 100 ? 1 : 0)), 3) ?> 100"
                            transform="rotate(-90 18 18)" stroke-linecap="round" />
                        <text x="18" y="16.5" text-anchor="middle" class="ta-donut-value"><?= number_format($achievedShare, 0) ?>%</text>
                        <text x="18" y="21.5" text-anchor="middle" class="ta-donut-label">Achieved</text>
                    </svg>
                    <div class="ta-donut-legend">
                        <div class="ta-donut-legend-row"><span class="ta-donut-swatch" style="background:var(--rn-green)"></span><span class="ta-donut-legend-label">Achieved</span><span class="ta-donut-legend-value"><?= $achieved ?> (<?= number_format($achievedShare, 0) ?>%)</span></div>
                        <div class="ta-donut-legend-row"><span class="ta-donut-swatch" style="background:var(--rn-red)"></span><span class="ta-donut-legend-label">Missed</span><span class="ta-donut-legend-value"><?= $missed ?> (<?= number_format(100 - $achievedShare, 0) ?>%)</span></div>
                    </div>
                </div>
                <?php endif; ?>
            </div>
            <div>
                <h4 class="ta-goal-subhead">Goal Size Distribution</h4>
                <?php if (!$achievementReady): ?>
                <p class="ta-empty-note">Need at least <?= $minGoalSamples ?> goals set.</p>
                <?php else: ?>
                <?php taSuccessBucketList($fg['size_distribution'], 'var(--rn-blue)'); ?>
                <?php endif; ?>
            </div>
            <div>
                <h4 class="ta-goal-subhead">How Quickly Goals Are Reached</h4>
                <?php if (!$timeReady): ?>
                <p class="ta-empty-note">Need at least <?= $minGoalSamples ?> achieved goals.</p>
                <?php else: ?>
                <?php taSuccessBarList($fg['speed_buckets'], 'var(--rn-green)'); ?>
                <?php endif; ?>
            </div>
            <div>
                <h4 class="ta-goal-subhead">Why Goals Take Longer (Delay Factors)</h4>
                <?php taSuccessBarList($fg['delay_factors'], 'var(--rn-gold)'); ?>
            </div>
        </div>
    </div>
    <?php
}

/** Section 4 — Instrument Performance · Goal Timeline · Your Winning Edge. */
function taSuccessSectionFour(array $data): void {
    ?>
    <div class="ta-section-grid-3">
        <div class="rn-trade-journal">
            <h3 class="ta-card-h3">Instrument Performance</h3>
            <?php taSuccessInstrumentPie($data['instrument_performance']); ?>
        </div>
        <div class="rn-trade-journal">
            <h3 class="ta-card-h3" style="margin-bottom:.3rem">Goal Timeline</h3>
            <p class="ta-empty-note" style="margin-bottom:.8rem">Average path to goal, typical progress toward target as a goal plays out, not a period comparison.</p>
            <?php taSuccessGoalTimelineChart($data['funded_goal']['applicable'] ? $data['funded_goal']['timeline'] : ['available' => false, 'n' => 0]); ?>
        </div>
        <div class="rn-trade-journal">
            <h3 class="ta-card-h3">Your Winning Edge</h3>
            <?php taSuccessWinningEdge($data['winning_edge'], $data['strongest_habits']); ?>
        </div>
    </div>
    <?php
}

function taSuccessInstrumentPie(array $perf): void {
    if (!$perf['available']) { echo '<p class="ta-empty-note">Not enough historical data yet.</p>'; return; }
    $colors = ['#60A5FA', '#A78BFA', '#E09B3A', '#26A69A', '#EF5350', '#787B86'];
    $offset = 0.0;
    ?>
    <div class="ta-donut-wrap">
        <svg viewBox="0 0 36 36" class="ta-donut-svg" role="img" aria-label="Instrument performance">
            <?php foreach ($perf['slices'] as $i => $s): $color = $colors[$i % count($colors)]; $dash = max(0, $s['pct'] - 1); ?>
            <circle cx="18" cy="18" r="15.9155" fill="none" stroke="<?= $color ?>" stroke-width="4.3"
                stroke-dasharray="<?= number_format($dash, 3) ?> <?= number_format(100 - $dash, 3) ?>"
                stroke-dashoffset="<?= number_format(-$offset, 3) ?>" transform="rotate(-90 18 18)" stroke-linecap="round" />
            <?php $offset += $s['pct']; endforeach; ?>
            <text x="18" y="16.5" text-anchor="middle" class="ta-donut-value"><?= $perf['avg_expectancy_r'] !== null ? number_format($perf['avg_expectancy_r'], 2) . 'R' : '-' ?></text>
            <text x="18" y="21.5" text-anchor="middle" class="ta-donut-label">Avg Expectancy</text>
        </svg>
        <div class="ta-donut-legend">
            <?php foreach ($perf['slices'] as $i => $s): $color = $colors[$i % count($colors)]; ?>
            <div class="ta-donut-legend-row">
                <span class="ta-donut-swatch" style="background:<?= $color ?>"></span>
                <span class="ta-donut-legend-label"><?= htmlspecialchars($s['instrument']) ?></span>
                <span class="ta-donut-legend-value"><?= $s['pct'] ?>%<?= $s['expectancy_r'] !== null ? ' · ' . number_format($s['expectancy_r'], 2) . 'R' : '' ?></span>
            </div>
            <?php endforeach; ?>
        </div>
    </div>
    <?php
}

/**
 * Average path to goal — a plain inline SVG line, x-axis = % of the way
 * through a typical goal's own timeline, y-axis = average % of target
 * reached. No canvas/JS charting library, matching this page's own
 * established dependency-free SVG convention (see
 * tl4RenderComplianceRing()).
 *
 * The chart frame (axes, ticks, card size) always renders, whether or
 * not there's enough data — per explicit instruction not to collapse
 * this card or replace it with bare text. When unavailable, the SAME
 * frame renders in a muted state (reduced opacity, a flat dashed
 * reference line, never a fabricated trend shape someone could mistake
 * for real progress) with the real sample count and the exact
 * threshold as a centered helper label.
 */
function taSuccessGoalTimelineChart(array $timeline): void {
    $available = $timeline['available'] ?? false;
    $n = $timeline['n'] ?? 0;
    $needed = TradingArchiveEngine::MIN_GROUP_SEGMENTS;

    $points = $available ? $timeline['points'] : [];
    $maxY = 0.0;
    foreach ($points as $p) { if ($p['y'] !== null && $p['y'] > $maxY) $maxY = $p['y']; }
    $maxY = max(100.0, ceil($maxY / 10) * 10);
    $w = 300; $h = 150; $padL = 34; $padB = 22; $padT = 10; $padR = 10;
    $plotW = $w - $padL - $padR; $plotH = $h - $padT - $padB;
    $coords = [];
    foreach ($points as $p) {
        if ($p['y'] === null) continue;
        $x = $padL + ($p['x'] / 100) * $plotW;
        $y = $padT + $plotH - ($p['y'] / $maxY) * $plotH;
        $coords[] = number_format($x, 1) . ',' . number_format($y, 1);
    }
    $midY = $padT + $plotH / 2;
    ?>
    <svg viewBox="0 0 <?= $w ?> <?= $h ?>" class="ta-timeline-svg <?= $available ? '' : 'ta-timeline-svg-muted' ?>" role="img" aria-label="Average path to goal">
        <line x1="<?= $padL ?>" y1="<?= $padT ?>" x2="<?= $padL ?>" y2="<?= $padT + $plotH ?>" class="ta-timeline-axis" />
        <line x1="<?= $padL ?>" y1="<?= $padT + $plotH ?>" x2="<?= $padL + $plotW ?>" y2="<?= $padT + $plotH ?>" class="ta-timeline-axis" />
        <text x="2" y="<?= $padT + 4 ?>" class="ta-timeline-tick">100%</text>
        <text x="2" y="<?= $padT + $plotH + 4 ?>" class="ta-timeline-tick">0%</text>
        <text x="<?= $padL ?>" y="<?= $h - 4 ?>" class="ta-timeline-tick">0%</text>
        <text x="<?= $padL + $plotW - 24 ?>" y="<?= $h - 4 ?>" class="ta-timeline-tick">100%</text>
        <?php if ($available && count($coords) >= 2): ?>
        <polyline points="<?= implode(' ', $coords) ?>" class="ta-timeline-line" />
        <?php foreach ($points as $p): if ($p['y'] === null) continue; $x = $padL + ($p['x'] / 100) * $plotW; $y = $padT + $plotH - ($p['y'] / $maxY) * $plotH; ?>
        <circle cx="<?= number_format($x, 1) ?>" cy="<?= number_format($y, 1) ?>" r="3.2" class="ta-timeline-dot" />
        <?php endforeach; ?>
        <?php else: ?>
        <line x1="<?= $padL ?>" y1="<?= $midY ?>" x2="<?= $padL + $plotW ?>" y2="<?= $midY ?>" class="ta-timeline-placeholder-line" />
        <text x="<?= $padL + $plotW / 2 ?>" y="<?= $midY - 4 ?>" text-anchor="middle" class="ta-timeline-placeholder-text">Your Goal Timeline is almost ready</text>
        <?php endif; ?>
    </svg>
    <?php if ($available): ?>
    <p class="ta-empty-note" style="margin-top:.4rem">X-axis: % of the way through a typical goal's own timeline. Y-axis: average % of target reached, across <?= $timeline['n'] ?> achieved goal<?= $timeline['n'] === 1 ? '' : 's' ?>.</p>
    <?php else: ?>
    <?php // Item 15: a motivating empty state — real progress dots from
          // the real achieved-goal count, not a bare "need N more"
          // message with nothing to show for what's already been done. ?>
    <div class="ta-timeline-progress">
        <p class="ta-empty-note" style="margin-bottom:.6rem">Complete at least <?= $needed ?> goals and TraderAlign will automatically build your personal Goal Timeline.</p>
        <div class="ta-timeline-progress-row">
            <div class="ta-timeline-progress-dots">
                <?php for ($i = 0; $i < $needed; $i++): ?>
                <span class="ta-timeline-progress-dot <?= $i < $n ? 'ta-timeline-progress-dot-filled' : '' ?>"></span>
                <?php endfor; ?>
            </div>
            <span class="ta-timeline-progress-label"><?= (int)$n ?> / <?= $needed ?> goals completed</span>
        </div>
    </div>
    <?php endif; ?>
    <?php
}

/**
 * "Your Winning Edge" — six fields only, per the approved brief: best
 * winning streak, best instrument, best strategy, best RR (the RR
 * actually planned on this account's single most-profitable real trade
 * — by realized R-multiple, not an average), market focus, and this
 * account's typical (median) risk per trade — a single value, not a
 * min–max range: a bare "1.01% – 50.00%" reads as "the account risked
 * anywhere from 1% to 50%," which is misleading when it's really one
 * outlier trade stretching an otherwise-tight range. "Core Setup" and
 * "Confirmation Tools" are deliberately excluded (they were the old
 * population-wide version's fields) — those describe a strategy's own
 * declared rules, not this account's real journey.
 *
 * Item 13's original fix is preserved here: a combined long value (e.g.
 * a multi-instrument Market Focus list) could overflow the card at
 * narrower widths, since the shared .ta-stat-value class (also used by
 * Lessons From Failure's Core Statistics grid, which this page must not
 * alter the layout of) sets white-space:nowrap. Rather than change that
 * shared class, every row with a real second fact carries it as a
 * separate, smaller sub-line instead of concatenating it into one long
 * string.
 */
/**
 * Shared empty-state block (2026-08-06) — a centered icon + heading +
 * explanation, replacing a bare one-line "Not enough historical data
 * yet." that left a large, unexplained blank rectangle inside an
 * otherwise-full card. Used wherever a card has genuinely nothing to
 * show yet (not enough closed trades for a real statistic) — never a
 * substitute for a real value when one exists.
 */
function taEmptyStateBlock(string $message, string $heading = 'Not Enough History Yet'): void {
    ?>
    <div class="ta-empty-state-block">
        <svg viewBox="0 0 48 48" class="ta-empty-state-icon" fill="none" stroke="currentColor" stroke-width="1.6" aria-hidden="true">
            <circle cx="24" cy="24" r="19" />
            <path d="M24 15v10l6 4" stroke-linecap="round" stroke-linejoin="round" />
        </svg>
        <div class="ta-empty-state-heading"><?= htmlspecialchars($heading) ?></div>
        <p class="ta-empty-state-text"><?= htmlspecialchars($message) ?></p>
    </div>
    <?php
}

/**
 * "Your Winning Edge" (2026-08-10 content merge) — the exact same card
 * as before (same title, same wrapper, same .ta-stats-grid/.ta-stat-row
 * markup, same position in Section 4's grid) — no layout/styling change
 * of any kind. The former separate "Strongest Success Habits" card
 * (Section 2) has been deleted; its two genuinely UNIQUE facts (Best
 * Session, Checklist Adherence — accountWinningEdge() has no equivalent
 * for either) are now rows in this same card, via the optional $habits
 * param (the 'session'/'checklist' keys strongestSuccessHabits()'s
 * entries now carry). Everywhere the two cards used to repeat the same
 * real fact under two labels, only one instance survives:
 *   - Best Instrument / Market Focus / Typical Risk per Trade were
 *     already sourced correctly here — unchanged.
 *   - Best Strategy now shows strongestSuccessHabits()'s richer "used
 *     in X% of these trades" context instead of a bare name, when
 *     available.
 *   - "Best RR (Most Profitable)" is replaced by "Reward:Risk" showing
 *     the pooled AVERAGE across every winning trade (strongestSuccess-
 *     Habits()'s rr habit) rather than one single trade's own planned
 *     R:R — per direct instruction, when two values are essentially the
 *     same (e.g. 1:3.04 vs 1:3.05 on this account), show the more
 *     consistent one; "maintained" describes a pattern, not a one-off
 *     trade, so the average is kept, falling back to the single best
 *     trade's R:R only on the rare account where the average never
 *     cleared MIN_FAVORABLE_RR.
 * $habits defaults to [] so the Live Accounts call site (which has no
 * "Strongest Success Habits" card to begin with) needs no change.
 */
function taSuccessWinningEdge(array $edge, array $habits = []): void {
    if (!$edge['available']) { taEmptyStateBlock('Once a few more trades close on this account, your best instrument, strategy, and reward:risk will show up here.'); return; }
    $bestStrategy = $edge['best_strategy'];
    $byKey = [];
    foreach ($habits as $h) { if (isset($h['key'])) $byKey[$h['key']] = $h; }

    $rows = [];

    if (isset($byKey['session'])) {
        $rows[] = ['Best Session', $byKey['session']['session'], number_format($byKey['session']['pct'], 1) . '% of total profit generated in this session', false];
    }
    $rows[] = ['Best Winning Streak', $edge['best_winning_streak'] > 0 ? $edge['best_winning_streak'] . ' win' . ($edge['best_winning_streak'] === 1 ? '' : 's') : 'Not enough data yet', null, $edge['best_winning_streak'] <= 0];
    if (isset($byKey['checklist'])) {
        $rows[] = ['Checklist Adherence', number_format($byKey['checklist']['pct'], 1) . '%', 'average completion rate', false];
    }
    $rows[] = ['Best Instrument', $edge['best_instrument'] !== null ? strtoupper($edge['best_instrument']['instrument']) : 'Not enough data yet',
        ($edge['best_instrument'] !== null && $edge['best_instrument']['expectancy_r'] !== null) ? number_format($edge['best_instrument']['expectancy_r'], 2) . 'R expectancy' : null, $edge['best_instrument'] === null];
    if (isset($byKey['strategy'])) {
        $rows[] = ['Best Strategy', $byKey['strategy']['name'], 'used in ' . number_format($byKey['strategy']['used_pct'], 1) . '% of these trades', false];
    } else {
        $rows[] = ['Best Strategy', $bestStrategy !== null ? $bestStrategy['name'] : 'Not enough data yet', null, $bestStrategy === null];
    }
    if (isset($byKey['rr'])) {
        $rows[] = ['Reward:Risk', '1 : ' . number_format($byKey['rr']['avg_rr'], 2), 'average, maintained across winning trades', false];
    } elseif ($edge['best_rr'] !== null) {
        $rows[] = ['Best RR (Most Profitable)', '1 : ' . number_format($edge['best_rr'], 2), null, false];
    } else {
        $rows[] = ['Reward:Risk', 'Not enough data yet', null, true];
    }
    $rows[] = ['Market Focus', !empty($edge['market_focus']) ? implode(', ', array_map('strtoupper', $edge['market_focus'])) : 'Not enough data yet', null, empty($edge['market_focus'])];
    $rows[] = ['Typical Risk per Trade', $edge['median_risk_pct'] !== null ? number_format($edge['median_risk_pct'], 2) . '% of account' : 'Not enough data yet', null, $edge['median_risk_pct'] === null];
    ?>
    <div class="ta-stats-grid" style="grid-template-columns:1fr">
    <?php foreach ($rows as [$label, $val, $sub, $waiting]): ?>
        <div class="ta-stat-row ta-stat-row-wrap">
            <span class="ta-stat-label-icon">
                <?php if (!$waiting): ?><span class="ta-stat-check" aria-hidden="true">✓</span><?php endif; ?>
                <span class="ta-stat-label"><?= htmlspecialchars($label) ?></span>
            </span>
            <span class="ta-winning-edge-value">
                <span class="ta-stat-value <?= $waiting ? 'rn-metric-waiting' : '' ?>"><?= htmlspecialchars($val) ?></span>
                <?php if ($sub !== null): ?><span class="ta-winning-edge-sub"><?= htmlspecialchars($sub) ?></span><?php endif; ?>
            </span>
        </div>
    <?php endforeach; ?>
    </div>
    <?php
}

/**
 * Final section — "Trades That Built This Success" (Journey Evidence).
 * This ONE account's own real closed trades, listed highest-realized-
 * outcome first (real R-multiple, descending). The Impact star rating
 * is a SEPARATE, value-based computation — see
 * TradingArchiveEngine::successTradeImpactStars() — fixed absolute
 * R-multiple thresholds capped by this trade's own real discipline
 * classification, deliberately NOT a rank/percentile position within
 * this list (a real, confirmed bug: two trades sharing the identical
 * +2.98R outcome previously rendered 5 stars and 1 star purely because
 * of which array index a tie landed on). Two trades with the same real
 * R-multiple and the same real classification now always get the same
 * star count, independent of how many other trades are in the list.
 * Never account-level rows the way the old population-wide
 * "Contributing Accounts" table showed. "Setup"/"Classification"
 * columns were dropped — they didn't add anything a trader can't
 * already see in Strongest Success Habits above. "View in Trades
 * Table" reuses Active Journeys' own real account-selection workflow
 * (activeJourneysUrl()), never a new page, scoped to this exact
 * account.
 */
function taSuccessEvidenceTrades(array $data): void {
    $trades = $data['evidence_trades'];
    ?>
    <div class="rn-trade-journal">
        <h3 class="ta-card-h3" style="margin-bottom:.3rem">Trades That Built This Success <span class="ta-card-h3-note">(Journey Evidence)</span></h3>
        <p class="ta-empty-note" style="margin-bottom:1rem">These are the highest-impact trades that contributed most to this account's success, ranked by real realized outcome.</p>
        <?php if (empty($trades)): ?>
        <div class="rn-empty-note">No closed trades on this account yet.</div>
        <?php else: ?>
        <div class="rn-table-scroll">
        <table class="rn-table ta-success-table" id="ta-success-evidence-table">
            <thead>
                <tr>
                    <th>Date</th><th>Instrument</th><th>Session</th><th>Direction</th>
                    <th>RR</th><th>P&amp;L (R)</th>
                    <th><span class="ta-impact-info">Impact <button type="button" class="tl4-expand-btn" onclick="taToggleImpactInfo(this)">View</button>
                        <div class="ta-impact-popover" style="display:none">
                            <div class="ta-impact-popover-head">
                                <span class="ta-impact-popover-title">★ Impact Rating</span>
                                <button type="button" class="ta-impact-popover-close" onclick="event.stopPropagation();this.closest('.ta-impact-popover').style.display='none'" aria-label="Close">✕</button>
                            </div>
                            <div class="ta-impact-popover-row"><span class="ta-impact-popover-star">5★</span><span class="ta-impact-popover-desc">3R+</span></div>
                            <div class="ta-impact-popover-row"><span class="ta-impact-popover-star">4★</span><span class="ta-impact-popover-desc">2R to 3R</span></div>
                            <div class="ta-impact-popover-row"><span class="ta-impact-popover-star">3★</span><span class="ta-impact-popover-desc">1R to 2R</span></div>
                            <div class="ta-impact-popover-row"><span class="ta-impact-popover-star">2★</span><span class="ta-impact-popover-desc">0R to 1R or breakeven</span></div>
                            <div class="ta-impact-popover-row"><span class="ta-impact-popover-star">1★</span><span class="ta-impact-popover-desc">Loss</span></div>
                            <div class="ta-impact-popover-cap"><b>⚠</b><span>Over-risk, tilt, or revenge trades can't score above 2★</span></div>
                        </div>
                    </span></th>
                </tr>
            </thead>
            <tbody>
            <?php foreach ($trades as $idx => $t): $isExtra = $idx >= 8; ?>
                <tr<?= $isExtra ? ' class="rn-row-extra" style="display:none"' : '' ?>>
                    <td><?= !empty($t['date']) ? date('d M Y', strtotime($t['date'])) : '-' ?></td>
                    <td><?= $t['instrument'] !== '' ? htmlspecialchars($t['instrument']) : '-' ?></td>
                    <td><?= htmlspecialchars($t['session'] ?? '') !== '' ? htmlspecialchars($t['session']) : '-' ?></td>
                    <td class="<?= ($t['direction'] ?? '') === 'long' ? 'positive' : 'negative' ?>"><?= ($t['direction'] ?? '') === 'long' ? 'Long' : 'Short' ?></td>
                    <td><?= $t['planned_rr'] !== null ? '1 : ' . number_format($t['planned_rr'], 1) : '-' ?></td>
                    <?php
                    // 2026-08-06 — a bare "—" here now only ever means this
                    // ONE trade genuinely has neither a recorded planned-
                    // risk dollar amount (max_potential_loss) nor its
                    // sibling risk_per_position to compute a real R-multiple
                    // from — never a break-even trade (that renders "+0.00R"
                    // below, a real value) and never a missing outcome (P&L
                    // itself always exists; only the RATIO needs a planned-
                    // risk denominator this specific trade doesn't have).
                    // Stated explicitly via a tooltip rather than an
                    // unexplained symbol, per explicit instruction.
                    $rUnavailableNote = 'This trade has no recorded planned risk amount (neither Max Potential Loss nor Risk Per Position) to calculate a real R-multiple from, not a break-even trade and not a missing outcome, just no planned-risk figure on record for it.';
                    ?>
                    <td class="<?= $t['r_multiple'] === null ? '' : ($t['r_multiple'] >= 0 ? 'positive' : 'negative') ?>"<?= $t['r_multiple'] === null ? ' title="' . htmlspecialchars($rUnavailableNote) . '"' : '' ?>><?= $t['r_multiple'] === null ? 'Unavailable' : (($t['r_multiple'] >= 0 ? '+' : '') . number_format($t['r_multiple'], 2) . 'R') ?></td>
                    <td class="ta-impact-stars"<?= $t['stars'] === null ? ' title="Impact can\'t be scored without a real R-multiple. See P&amp;L (R) on this row."' : '' ?>><?= $t['stars'] !== null ? str_repeat('★', $t['stars']) . str_repeat('☆', 5 - $t['stars']) : 'N/A' ?></td>
                </tr>
            <?php endforeach; ?>
            </tbody>
        </table>
        </div>
        <?php if (count($trades) > 8): ?>
        <div class="rn-table-more-wrap">
            <button type="button" class="rn-show-more-btn" data-table="ta-success-evidence-table" data-more-label="Show More (<?= count($trades) - 8 ?> more)" onclick="rnToggleTableRows(this)">Show More (<?= count($trades) - 8 ?> more)</button>
        </div>
        <?php endif; ?>
        <div style="margin-top:1rem">
            <a href="<?= htmlspecialchars(activeJourneysUrl(['rn_type' => $data['type'], 'rn_account' => $data['account_id']])) ?>" class="rn-view-btn">View in Trades Table</a>
        </div>
        <?php endif; ?>
    </div>
    <?php
}

/**
 * ════════════════════════════════════════════════════════════════════
 * LIVE ACCOUNTS — single-account rebuild (2026-08-06)
 * ────────────────────────────────────────────────────────────────
 * Everything below renders exclusively from the taRenderSuccessLearning()
 * live branch — never called for Prop Firms. See
 * TradingArchiveEngine's own "LIVE ACCOUNTS — single-account extras"
 * section for what each field is computed from and the real data
 * constraints behind it (no per-deposit/withdrawal dollar amount exists
 * anywhere in this schema — only event timestamps + running totals).
 * ════════════════════════════════════════════════════════════════════
 */

/** Six KPI cards — Account Status / Account Age / Closed Trades / Current Balance / Total Blown Accounts / Total Closed Accounts. Matches the approved prototype exactly; deliberately a different card set from Prop Firms' own five (taSuccessKpiCards()), which this function never touches. */
function taLiveSuccessKpiCards(array $data): void {
    $isActive = $data['is_still_active'];
    $ageDays = $data['account_age_days'];
    $sinceLabel = !empty($data['account_created_at']) ? date('M Y', strtotime($data['account_created_at'])) : null;
    $snap = $data['account_snapshot'];
    ?>
    <div class="ta-kpi-grid ta-kpi-grid-6">
        <div class="ta-kpi-card">
            <div class="ta-kpi-icon ta-kpi-icon-green"><?= taSuccessKpiIcon('accounts') ?></div>
            <div class="ta-kpi-label">Account Status</div>
            <div class="ta-kpi-value" style="color:var(--rn-green)"><?php if ($isActive): ?><span class="ta-live-dot"></span><?php endif; ?><?= $isActive ? 'Active' : 'Closed' ?></div>
            <div class="ta-kpi-sub"><?= $isActive ? 'Live and funded' : 'Closed with a real, realized profit' ?></div>
        </div>
        <div class="ta-kpi-card">
            <div class="ta-kpi-icon ta-kpi-icon-purple"><?= taSuccessKpiIcon('time') ?></div>
            <div class="ta-kpi-label">Account Age</div>
            <div class="ta-kpi-value"><?= $ageDays !== null ? htmlspecialchars(formatAccountLongevity($ageDays)) : '-' ?></div>
            <div class="ta-kpi-footnote"><?= $sinceLabel !== null ? 'Since ' . htmlspecialchars($sinceLabel) : 'Account creation date not on record.' ?></div>
        </div>
        <div class="ta-kpi-card">
            <div class="ta-kpi-icon ta-kpi-icon-blue"><?= taSuccessKpiIcon('trades') ?></div>
            <div class="ta-kpi-label">Closed Trades</div>
            <div class="ta-kpi-value"><?= number_format((int)$data['kpi']['trades_taken']) ?></div>
            <div class="ta-kpi-footnote">Total closed trades on this account.</div>
        </div>
        <div class="ta-kpi-card">
            <div class="ta-kpi-icon ta-kpi-icon-gold"><?= taSuccessKpiIcon('winrate') ?></div>
            <div class="ta-kpi-label"><?= $isActive ? 'Current Balance' : 'Final Balance' ?></div>
            <div class="ta-kpi-value">$<?= number_format($data['current_balance'], 2) ?></div>
            <div class="ta-kpi-footnote"><?= $isActive ? 'Live and funded' : 'Balance when this account was closed.' ?></div>
        </div>
        <div class="ta-kpi-card">
            <div class="ta-kpi-icon ta-kpi-icon-blue" style="color:<?= ($snap['current_drawdown_pct'] ?? 0) > 0 ? 'var(--rn-red)' : 'var(--rn-blue)' ?>"><?= taSuccessKpiIcon('drawdown') ?></div>
            <div class="ta-kpi-label">Current Drawdown</div>
            <div class="ta-kpi-value" style="color:<?= ($snap['current_drawdown_pct'] ?? 0) > 0 ? 'var(--rn-red)' : 'var(--foreground)' ?>"><?= $snap['current_drawdown_pct'] !== null ? number_format($snap['current_drawdown_pct'], 1) . '%' : '-' ?></div>
            <div class="ta-kpi-footnote">How far below this account's own real peak equity it sits right now.</div>
        </div>
        <div class="ta-kpi-card">
            <div class="ta-kpi-icon ta-kpi-icon-teal"><?= taSuccessKpiIcon('winrate') ?></div>
            <div class="ta-kpi-label">Largest Win</div>
            <div class="ta-kpi-value <?= $snap['largest_win'] !== null ? 'positive' : '' ?>"><?= $snap['largest_win'] !== null ? '+$' . number_format($snap['largest_win'], 2) : '-' ?></div>
            <div class="ta-kpi-footnote">Largest realized profit on a single trade.</div>
        </div>
    </div>
    <?php
}

/** Trading Consistency donut (narrow) + Account Growth equity curve (wide) — a 2-column row, matching the prototype's own proportions. */
function taLiveSuccessGrowthSection(array $data): void {
    ?>
    <div class="ta-live-growth-row">
        <div class="rn-trade-journal">
            <h3 class="ta-card-h3">Trading Consistency <span title="Built from the same real signals as the Historical Discipline Index elsewhere on this page: how steady your risk-sizing stayed, and how often trades avoided tilt/revenge/over-risk classification, scoped to this one account." class="ta-info-dot">ⓘ</span></h3>
            <p class="ta-empty-note" style="margin-bottom:.8rem">Measures how consistently profitable your trading has been in this account.</p>
            <?php taLiveConsistencyDonut($data['trading_consistency']); ?>
        </div>
        <div class="rn-trade-journal">
            <h3 class="ta-card-h3">Equity Curve <span title="Real trade P&L merged with deposit/withdrawal timing, sampled at each calendar year. The endpoint always matches this account's real current balance exactly." class="ta-info-dot">ⓘ</span></h3>
            <?php taLiveEquityCurveChart($data['equity_curve']); ?>
        </div>
    </div>
    <?php
}

function taLiveConsistencyDonut(array $c): void {
    if (!$c['available']) { taEmptyStateBlock('Consistency is calculated from your real risk-sizing and discipline history. A few more closed trades on this account will unlock it.'); return; }
    $segs = [
        ['label' => 'Consistent Growth', 'pct' => $c['consistent_pct'], 'color' => 'var(--rn-green)'],
        ['label' => 'Moderate', 'pct' => $c['moderate_pct'], 'color' => 'var(--rn-purple)'],
        ['label' => 'Inconsistent', 'pct' => $c['inconsistent_pct'], 'color' => 'var(--rn-gold)'],
    ];
    $offset = 0.0;
    // §2 Live #8 fix (2026-08-10) — $c['score'] is historicalConsistency()'s
    // 0-100 composite grade (50% risk-sizing steadiness + 50% discipline
    // rate — see that function's own doc comment), never a percentile rank
    // against this account's own trading history; nothing anywhere computes
    // such a percentile. "Above X% of your own trading history" claimed a
    // statistic the underlying number doesn't measure. Reworded to state
    // the real grade plainly, matching the sibling Historical Discipline
    // Index card's own already-correct "combines two things" framing
    // (taRenderHistoricalConsistency()) instead of inventing a new claim.
    $praiseLine = $c['score'] >= 70
        ? 'Your long-term consistency score is strong, at ' . number_format($c['score'], 0) . '/100. Steady risk-sizing and disciplined trade selection, sustained over time.'
        : ($c['score'] >= 40 ? 'Your consistency is moderate, at ' . number_format($c['score'], 0) . '/100. Steadier risk-sizing would help.' : 'Consistency is currently low, at ' . number_format($c['score'], 0) . '/100. Risk-sizing and discipline both need attention.');
    ?>
    <div class="ta-donut-wrap">
        <svg viewBox="0 0 36 36" class="ta-donut-svg" role="img" aria-label="Trading consistency">
            <?php foreach ($segs as $s): $dash = max(0, $s['pct'] - ($s['pct'] > 0 && $s['pct'] < 100 ? 1 : 0)); ?>
            <?php if ($s['pct'] <= 0) continue; ?>
            <circle cx="18" cy="18" r="15.9155" fill="none" stroke="<?= $s['color'] ?>" stroke-width="4.3"
                stroke-dasharray="<?= number_format($dash, 3) ?> <?= number_format(100 - $dash, 3) ?>"
                stroke-dashoffset="<?= number_format(-$offset, 3) ?>" transform="rotate(-90 18 18)" stroke-linecap="round" />
            <?php $offset += $s['pct']; endforeach; ?>
            <text x="18" y="16.5" text-anchor="middle" class="ta-donut-value"><?= number_format($c['score'], 0) ?>%</text>
            <text x="18" y="21.5" text-anchor="middle" class="ta-donut-label">Consistency Score</text>
        </svg>
        <div class="ta-donut-legend">
            <?php foreach ($segs as $s): ?>
            <div class="ta-donut-legend-row"><span class="ta-donut-swatch" style="background:<?= $s['color'] ?>"></span><span class="ta-donut-legend-label"><?= htmlspecialchars($s['label']) ?></span><span class="ta-donut-legend-value"><?= number_format($s['pct'], 0) ?>%</span></div>
            <?php endforeach; ?>
        </div>
    </div>
    <p class="ta-live-praise"><?= htmlspecialchars($praiseLine) ?></p>
    <?php
}

/** Real merged equity curve — plain inline SVG line chart, same dependency-free convention as taSuccessGoalTimelineChart(). */
function taLiveEquityCurveChart(array $curve): void {
    if (!$curve['available']) { echo '<p class="ta-empty-note">Not enough historical data yet on this account.</p>'; return; }
    $points = $curve['points'];
    $values = array_column($points, 'value');
    $minV = min(0, min($values));
    $maxV = max($values);
    if ($maxV <= $minV) $maxV = $minV + 1;
    $w = 600; $h = 220; $padL = 55; $padB = 26; $padT = 16; $padR = 20;
    $plotW = $w - $padL - $padR; $plotH = $h - $padT - $padB;
    $n = count($points);
    $coords = [];
    foreach ($points as $i => $p) {
        $x = $padL + ($n > 1 ? ($i / ($n - 1)) * $plotW : 0);
        $y = $padT + $plotH - (($p['value'] - $minV) / ($maxV - $minV)) * $plotH;
        $coords[] = number_format($x, 1) . ',' . number_format($y, 1);
    }
    $areaCoords = $coords;
    $areaCoords[] = number_format($padL + $plotW, 1) . ',' . number_format($padT + $plotH, 1);
    $areaCoords[] = number_format($padL, 1) . ',' . number_format($padT + $plotH, 1);
    ?>
    <div style="display:flex;justify-content:flex-end;margin-bottom:.3rem">
        <span class="ta-live-growth-total">Total Growth <b class="<?= $curve['total_growth_pct'] >= 0 ? 'positive' : 'negative' ?>"><?= $curve['total_growth_pct'] >= 0 ? '+' : '' ?><?= number_format($curve['total_growth_pct'], 2) ?>%</b></span>
    </div>
    <svg viewBox="0 0 <?= $w ?> <?= $h ?>" class="ta-equity-svg" role="img" aria-label="Equity curve">
        <?php for ($gy = 0; $gy <= 3; $gy++): $ly = $padT + ($plotH / 3) * $gy; $val = $maxV - (($maxV - $minV) / 3) * $gy; ?>
        <line x1="<?= $padL ?>" y1="<?= number_format($ly, 1) ?>" x2="<?= $padL + $plotW ?>" y2="<?= number_format($ly, 1) ?>" class="ta-equity-gridline" />
        <text x="2" y="<?= number_format($ly + 4, 1) ?>" class="ta-equity-tick"><?= number_format($val / 1000, 0) ?>k</text>
        <?php endfor; ?>
        <polygon points="<?= implode(' ', $areaCoords) ?>" class="ta-equity-area" />
        <polyline points="<?= implode(' ', $coords) ?>" class="ta-equity-line" />
        <?php foreach ($points as $i => $p): $x = $padL + ($n > 1 ? ($i / ($n - 1)) * $plotW : 0); $y = $padT + $plotH - (($p['value'] - $minV) / ($maxV - $minV)) * $plotH; ?>
        <circle cx="<?= number_format($x, 1) ?>" cy="<?= number_format($y, 1) ?>" r="3" class="ta-equity-dot" />
        <text x="<?= number_format($x, 1) ?>" y="<?= $h - 6 ?>" text-anchor="middle" class="ta-equity-tick"><?= htmlspecialchars($p['label']) ?></text>
        <?php endforeach; ?>
    </svg>
    <div class="ta-equity-stats">
        <div><span class="ta-equity-stat-label">Starting Balance</span><span class="ta-equity-stat-value">$<?= number_format($curve['starting_balance'], 2) ?></span></div>
        <div><span class="ta-equity-stat-label">Current Balance</span><span class="ta-equity-stat-value">$<?= number_format($curve['current_balance'], 2) ?></span></div>
        <div><span class="ta-equity-stat-label">Total Growth</span><span class="ta-equity-stat-value <?= $curve['total_growth_pct'] >= 0 ? 'positive' : 'negative' ?>"><?= $curve['total_growth_pct'] >= 0 ? '+' : '' ?><?= number_format($curve['total_growth_pct'], 2) ?>%</span></div>
    </div>
    <?php
}

/** "Goal Achievement" — Goals Created/Achieved/Rate/Avg Time to Goal + Goal Progress donut + Goal Size Breakdown. Reuses fundedGoalAchievement()'s exact data (goals_set/goals_achieved/achievement_pct/etc.) — same source Prop Firms' taSuccessFundedGoalSection() reads, just laid out as a standalone card per the Live Accounts prototype. Renders nothing when no goal has ever been set on this account. */
function taLiveSuccessGoalAchievement(array $data): void {
    $fg = $data['funded_goal'];
    if (!$fg['applicable']) return;
    $achieved = $fg['goals_achieved']; $total = $fg['goals_set']; $missed = max(0, $total - $achieved);
    $achievedShare = $total > 0 ? ($achieved / $total) * 100 : null;
    $minGoalSamples = TradingArchiveEngine::MIN_GROUP_SEGMENTS;
    $timeReady = $fg['n_time_to_goal_samples'] >= $minGoalSamples;
    // §2 Live #4 fix (2026-08-10) — same gap and same fix as the Prop
    // Firms sibling above (taSuccessFundedGoalSection()): Achievement
    // Rate/Goal Size Distribution rendered unconditionally from as few
    // as one real goal, while Average Time To Goal on the same card
    // correctly disclosed a thin sample.
    $achievementReady = $total >= $minGoalSamples;
    ?>
    <div class="rn-trade-journal">
        <h3 class="ta-card-h3">Goal Achievement <span title="Real growth targets you've set on this account (Journal's own Growth Target feature) and how they actually played out." class="ta-info-dot">ⓘ</span></h3>
        <div class="ta-goal-top-grid">
            <div class="ta-goal-stat"><div class="ta-goal-stat-label">Goals Created</div><div class="ta-goal-stat-value"><?= $fg['goals_set'] ?></div></div>
            <div class="ta-goal-stat"><div class="ta-goal-stat-label">Goals Achieved</div><div class="ta-goal-stat-value"><?= $fg['goals_achieved'] ?></div></div>
            <div class="ta-goal-stat">
                <div class="ta-goal-stat-label">Achievement Rate</div>
                <div class="ta-goal-stat-value" style="color:var(--rn-green)"><?= $achievementReady ? taSVal($fg['achievement_pct'], 0, '%') : '-' ?></div>
                <?php if (!$achievementReady): ?><div class="ta-goal-stat-sub">Need at least <?= $minGoalSamples ?> goals set.</div><?php endif; ?>
            </div>
            <div class="ta-goal-stat">
                <div class="ta-goal-stat-label">Average Time To Goal</div>
                <div class="ta-goal-stat-value"><?= $timeReady ? htmlspecialchars(formatDurationNatural($fg['avg_time_to_goal_days'])) : '-' ?></div>
                <?php if (!$timeReady): ?><div class="ta-goal-stat-sub">Need at least <?= $minGoalSamples ?> achieved goals.</div><?php endif; ?>
            </div>
        </div>
        <div class="ta-live-goal-bottom-grid">
            <div>
                <h4 class="ta-goal-subhead">Goal Achievement Rate</h4>
                <?php if (!$achievementReady): ?>
                <p class="ta-empty-note">Need at least <?= $minGoalSamples ?> goals set to show a reliable rate.</p>
                <?php elseif ($total === 0 || $achievedShare === null): ?>
                <p class="ta-empty-note">Not enough historical data yet.</p>
                <?php else: ?>
                <div class="ta-donut-wrap">
                    <svg viewBox="0 0 36 36" class="ta-donut-svg" role="img" aria-label="Goal achievement rate">
                        <circle cx="18" cy="18" r="15.9155" fill="none" stroke="var(--border)" stroke-width="4.3" />
                        <circle cx="18" cy="18" r="15.9155" fill="none" stroke="var(--rn-green)" stroke-width="4.3"
                            stroke-dasharray="<?= number_format(max(0, $achievedShare - ($achievedShare > 0 && $achievedShare < 100 ? 1 : 0)), 3) ?> 100"
                            transform="rotate(-90 18 18)" stroke-linecap="round" />
                        <text x="18" y="16.5" text-anchor="middle" class="ta-donut-value"><?= number_format($achievedShare, 0) ?>%</text>
                        <text x="18" y="21.5" text-anchor="middle" class="ta-donut-label">Achieved</text>
                    </svg>
                    <div class="ta-donut-legend">
                        <div class="ta-donut-legend-row"><span class="ta-donut-swatch" style="background:var(--rn-green)"></span><span class="ta-donut-legend-label">Achieved</span><span class="ta-donut-legend-value"><?= $achieved ?> (<?= number_format($achievedShare, 0) ?>%)</span></div>
                        <div class="ta-donut-legend-row"><span class="ta-donut-swatch" style="background:var(--rn-red)"></span><span class="ta-donut-legend-label">Missed</span><span class="ta-donut-legend-value"><?= $missed ?> (<?= number_format(100 - $achievedShare, 0) ?>%)</span></div>
                    </div>
                </div>
                <?php endif; ?>
            </div>
            <div>
                <h4 class="ta-goal-subhead">Goal Size Distribution</h4>
                <?php if (!$achievementReady): ?>
                <p class="ta-empty-note">Need at least <?= $minGoalSamples ?> goals set.</p>
                <?php else: ?>
                <?php taSuccessBucketList($fg['size_distribution'], 'var(--rn-blue)'); ?>
                <?php endif; ?>
            </div>
        </div>
    </div>
    <?php
}

/** "Goal Completion Speed" — Fastest/Typical/Longest goal + the real time-to-goal distribution, its own separate card per the Live Accounts prototype. */
function taLiveSuccessGoalSpeed(array $data): void {
    $fg = $data['funded_goal'];
    if (!$fg['applicable']) return;
    $ready = $fg['fastest_goal_days'] !== null;
    ?>
    <div class="rn-trade-journal">
        <h3 class="ta-card-h3">Goal Completion Speed <span title="How quickly this account's own achieved goals were reached, in real days." class="ta-info-dot">ⓘ</span></h3>
        <?php if (!$ready): ?>
        <p class="ta-empty-note">Need at least <?= TradingArchiveEngine::MIN_GROUP_SEGMENTS ?> achieved goals to show fastest/typical/longest.</p>
        <?php else: ?>
        <div class="ta-goal-top-grid" style="grid-template-columns:repeat(3,1fr)">
            <div class="ta-goal-stat"><div class="ta-goal-stat-label">Fastest Goal</div><div class="ta-goal-stat-value"><?= (int)round($fg['fastest_goal_days']) ?></div><div class="ta-goal-stat-sub">days</div></div>
            <div class="ta-goal-stat"><div class="ta-goal-stat-label">Typical Goal</div><div class="ta-goal-stat-value"><?= (int)round($fg['typical_goal_days']) ?></div><div class="ta-goal-stat-sub">days</div></div>
            <div class="ta-goal-stat"><div class="ta-goal-stat-label">Longest Goal</div><div class="ta-goal-stat-value"><?= (int)round($fg['longest_goal_days']) ?></div><div class="ta-goal-stat-sub">days</div></div>
        </div>
        <h4 class="ta-goal-subhead" style="margin-top:1.1rem">Goal Completion Time Distribution</h4>
        <?php
        // §2 Live #4 fix (2026-08-10) — this bar list used to render
        // unconditionally, OUTSIDE the $ready check above, so a thin
        // sample (< 3 achieved goals) showed a real, confident-looking
        // distribution chart directly beneath the "Need at least 3..."
        // disclaimer with no heading of its own. Now only renders once
        // $ready (the exact same MIN_GROUP_SEGMENTS floor gating
        // Fastest/Typical/Longest above it) is true.
        taSuccessBarList($fg['speed_buckets'], 'var(--rn-green)');
        endif; ?>
    </div>
    <?php
}

/**
 * "Most Common Reasons Goals Took Longer" — the real classifyGoalDelays()
 * tally, relabeled into plain everyday language for a live-account
 * audience via a small display-only translation map. The underlying
 * engine bucket keys (shared with Prop Firms' own delay-factor card) are
 * completely unchanged — only how they're WORDED here changes, and only
 * on this branch.
 */
function taLiveDelayFactorDisplay(array $delayFactors): array {
    $map = [
        'Revenge trading' => 'Revenge trading / emotional decisions',
        'Over-risking' => 'Over risk per trade',
        'Overtrading' => 'Over trading / too many trades',
        'Reducing trade frequency' => 'Missed sessions / inconsistent routine',
        'Waiting too long between entries' => 'Missed sessions / inconsistent routine',
        'Poor consistency after drawdown' => 'Poor trade management',
        'Other' => 'Other',
    ];
    $merged = [];
    foreach ($delayFactors as $f) {
        $label = $map[$f['label']] ?? $f['label'];
        $merged[$label] = ($merged[$label] ?? 0) + $f['count'];
    }
    if (empty($merged)) return [];
    arsort($merged);
    $total = array_sum($merged);
    $out = [];
    foreach ($merged as $label => $count) { $out[] = ['label' => $label, 'count' => $count, 'pct' => round($count / $total * 100, 1)]; }
    return $out;
}
function taLiveSuccessGoalReasons(array $data): void {
    $fg = $data['funded_goal'];
    if (!$fg['applicable']) return;
    $display = taLiveDelayFactorDisplay($fg['delay_factors']);
    ?>
    <div class="rn-trade-journal">
        <h3 class="ta-card-h3">Most Common Reasons Goals Took Longer</h3>
        <?php taSuccessBarList($display, 'var(--rn-gold)'); ?>
    </div>
    <?php
}

/** "How To Prevent This" — a real, data-driven checklist: one plain-language tip per delay-factor bucket that actually fired on this account, never a fixed 6-item list shown regardless of data. */
function taLiveSuccessGoalPrevention(array $data): void {
    $fg = $data['funded_goal'];
    if (!$fg['applicable']) return;
    $display = taLiveDelayFactorDisplay($fg['delay_factors']);
    if (empty($display)) return;
    $tips = [
        'Revenge trading / emotional decisions' => 'Stop after revenge trading. Step away instead of re-entering immediately.',
        'Over risk per trade' => "Keep risk the same every trade. Don't risk too much on any single position.",
        'Over trading / too many trades' => 'Stick to your daily trade limits. More trades is not the same as better trades.',
        'Missed sessions / inconsistent routine' => 'Follow your trading schedule strictly. Consistency beats sporadic bursts of activity.',
        'Poor trade management' => 'Review and learn from mistakes. Allow trades to play out per your plan.',
        'Other' => 'Follow your trading plan. Be patient and consistent.',
    ];
    $shown = [];
    foreach ($display as $d) { $tip = $tips[$d['label']] ?? null; if ($tip !== null && !in_array($tip, $shown, true)) $shown[] = $tip; }
    if (empty($shown)) return;
    ?>
    <div class="rn-trade-journal">
        <h3 class="ta-card-h3">How To Prevent This</h3>
        <ul class="ta-habit-list">
            <?php foreach ($shown as $tip): ?>
            <li class="ta-habit-item"><span class="ta-habit-icon">✓</span><div class="ta-habit-title"><?= htmlspecialchars($tip) ?></div></li>
            <?php endforeach; ?>
        </ul>
    </div>
    <?php
}

/** Capital Summary (internally: Financial Behaviour, briefly "Money Management") — six real, independently-sourced figures (see TradingArchiveEngine::liveFinancialBehaviour()'s own doc comment for exactly how each is computed and why Organic Growth is a genuine second measure, not a relabeled copy of Trading Profit). "Money Management" was corrected to "Capital Summary" the same session (2026-08-06) — these cards summarize money MOVEMENT (deposits, withdrawals, growth), not an evaluation of trading skill, so "Money Management" over-implied a judgment these numbers don't actually make. Trader-facing text only, underlying data/key names unchanged. */
function taLiveSuccessFinancialBehaviour(array $data): void {
    $fb = $data['financial_behaviour'];
    ?>
    <div class="rn-trade-journal">
        <h3 class="ta-card-h3">Capital Summary <span title="Trading Profit is summed directly from this account's real closed trades. Organic Growth is derived independently from the account's balance ledger (total change minus net new capital), a real cross-check, not a duplicate number." class="ta-info-dot">ⓘ</span></h3>
        <div class="ta-fin-grid">
            <div class="ta-fin-stat"><div class="ta-fin-label">Trading Profit</div><div class="ta-fin-value <?= $fb['trading_profit'] >= 0 ? 'positive' : 'negative' ?>"><?= $fb['trading_profit'] >= 0 ? '+' : '-' ?>$<?= number_format(abs($fb['trading_profit']), 2) ?></div><div class="ta-fin-sub">(From trading only)</div></div>
            <div class="ta-fin-stat"><div class="ta-fin-label">Net Deposits</div><div class="ta-fin-value">$<?= number_format($fb['net_deposits'], 2) ?></div><div class="ta-fin-sub">(Deposits − Withdrawals)</div></div>
            <div class="ta-fin-stat"><div class="ta-fin-label">Net Withdrawals</div><div class="ta-fin-value" style="color:var(--rn-gold)">$<?= number_format($fb['net_withdrawals'], 2) ?></div><div class="ta-fin-sub">(Total withdrawn)</div></div>
            <div class="ta-fin-stat"><div class="ta-fin-label">Organic Growth</div><div class="ta-fin-value <?= $fb['organic_growth'] >= 0 ? 'positive' : 'negative' ?>"><?= $fb['organic_growth'] >= 0 ? '+' : '-' ?>$<?= number_format(abs($fb['organic_growth']), 2) ?></div><div class="ta-fin-sub">(Growth without new capital)</div></div>
            <div class="ta-fin-stat"><div class="ta-fin-label">Capital Dependency</div><div class="ta-fin-value" style="color:var(--rn-purple)"><?= taSVal($fb['capital_dependency_pct'], 0, '%') ?></div><div class="ta-fin-sub">(Lower is better)</div></div>
            <div class="ta-fin-stat ta-fin-stat-score">
                <div class="ta-fin-label">Capital Efficiency Score</div>
                <?php if ($fb['capital_efficiency_score'] === null): ?>
                <div class="ta-fin-value">-</div>
                <?php else: $score = $fb['capital_efficiency_score']; $scoreColor = $score >= 80 ? 'var(--rn-green)' : ($score >= 50 ? 'var(--rn-gold)' : 'var(--rn-red)'); ?>
                <div class="ta-fin-score-ring" style="color:<?= $scoreColor ?>">
                    <svg viewBox="0 0 36 36" class="ta-donut-svg" style="width:5.5rem;height:5.5rem">
                        <circle cx="18" cy="18" r="15.9155" fill="none" stroke="var(--border)" stroke-width="3.2" />
                        <circle cx="18" cy="18" r="15.9155" fill="none" stroke="currentColor" stroke-width="3.2"
                            stroke-dasharray="<?= number_format(max(0, $score - 1), 3) ?> 100" transform="rotate(-90 18 18)" stroke-linecap="round" />
                        <text x="18" y="17" text-anchor="middle" style="font-size:8px;font-weight:800;fill:currentColor"><?= (int)$score ?></text>
                        <text x="18" y="23.5" text-anchor="middle" style="font-size:4.5px;fill:currentColor;opacity:.75">out of 100</text>
                    </svg>
                </div>
                <div class="ta-fin-sub"><?= $score >= 80 ? 'Excellent' : ($score >= 50 ? 'Good' : 'Needs Improvement') ?></div>
                <?php endif; ?>
            </div>
        </div>
    </div>
    <?php
}

/** Deposit History / Withdrawal History (internally: Deposit/Withdrawal Behaviour) — two cards side by side, each with its own stats + real 2/3-bucket donut (see the engine's own doc comments for why these are 2/3 real buckets, not a fabricated 4th). Renamed 2026-08-06 for plain-language wording. */
function taLiveSuccessDepositWithdrawal(array $data): void {
    $dep = $data['deposit_behaviour'];
    $wd = $data['withdrawal_behaviour'];
    ?>
    <div class="ta-section-grid-2">
        <div class="rn-trade-journal">
            <h3 class="ta-card-h3">Deposit History <span title="Regular = not preceded by a real losing stretch. After a Loss = this deposit followed real losses in the prior 14 days." class="ta-info-dot">ⓘ</span></h3>
            <?php if (!$dep['available']): ?>
            <p class="ta-empty-note">No deposits recorded on this account yet.</p>
            <?php else: ?>
            <div class="ta-live-substats">
                <div><span class="ta-live-substat-label">Total Deposits</span><span class="ta-live-substat-value">$<?= number_format($dep['total_deposits'], 2) ?></span></div>
                <div><span class="ta-live-substat-label">Average Deposit</span><span class="ta-live-substat-value">$<?= number_format($dep['avg_deposit'], 2) ?></span></div>
                <?php if ($dep['avg_gap_days'] !== null): ?>
                <div><span class="ta-live-substat-label">Avg. Days Between Deposits</span><span class="ta-live-substat-value"><?= (int)$dep['avg_gap_days'] ?> days</span></div>
                <?php endif; ?>
            </div>
            <?php if ($dep['n'] === 1): ?>
            <?php // A donut showing "100% Regular Deposits" from a single
                  // real deposit doesn't add insight over just saying so
                  // in plain language (2026-08-06 correction) — a chart
                  // only earns its place once there's a real split to show. ?>
            <p class="ta-empty-note">Your only deposit was $<?= number_format($dep['total_deposits'], 2) ?>, classified as <?= $dep['planned_count'] === 1 ? 'a regular deposit' : 'following a losing stretch' ?>.</p>
            <?php else: ?>
            <?php taLiveTwoBucketDonut($dep['planned_pct'], $dep['reactive_pct'], 'Regular Deposits', 'After a Loss'); ?>
            <?php endif; ?>
            <?php endif; ?>
        </div>
        <div class="rn-trade-journal">
            <h3 class="ta-card-h3">Withdrawal History <span title="After a Goal = within 3 days of a real achieved growth target. Regular Profit Taking = not goal-tied, and not during a losing stretch. Other = withdrawn during/after real recent losses." class="ta-info-dot">ⓘ</span></h3>
            <?php if (!$wd['available']): ?>
            <p class="ta-empty-note">No withdrawals recorded on this account yet.</p>
            <?php else: ?>
            <div class="ta-live-substats">
                <div><span class="ta-live-substat-label">Total Withdrawals</span><span class="ta-live-substat-value">$<?= number_format($wd['total_withdrawals'], 2) ?></span></div>
                <div><span class="ta-live-substat-label">Average Withdrawal</span><span class="ta-live-substat-value">$<?= number_format($wd['avg_withdrawal'], 2) ?></span></div>
                <?php if ($wd['avg_gap_days'] !== null): ?>
                <div><span class="ta-live-substat-label">Avg. Days Before Withdrawal</span><span class="ta-live-substat-value"><?= (int)$wd['avg_gap_days'] ?> days</span></div>
                <?php endif; ?>
            </div>
            <?php if ($wd['n'] === 1): ?>
            <?php // Same reasoning as Deposit History above — a donut over
                  // one real withdrawal doesn't add anything a sentence
                  // doesn't already say. ?>
            <p class="ta-empty-note">Your only withdrawal was $<?= number_format($wd['total_withdrawals'], 2) ?>, <?= htmlspecialchars($wd['buckets'][0]['label'] ?? 'Unclassified') ?>.</p>
            <?php else: ?>
            <?php $colors = ['#26A69A', '#60A5FA', '#E09B3A']; $offset = 0.0; ?>
            <div class="ta-donut-wrap">
                <svg viewBox="0 0 36 36" class="ta-donut-svg" role="img" aria-label="Withdrawal history">
                    <?php foreach ($wd['buckets'] as $i => $b): $dash = max(0, $b['pct'] - ($b['pct'] > 0 && $b['pct'] < 100 ? 1 : 0)); $color = $colors[$i % count($colors)]; ?>
                    <circle cx="18" cy="18" r="15.9155" fill="none" stroke="<?= $color ?>" stroke-width="4.3"
                        stroke-dasharray="<?= number_format($dash, 3) ?> <?= number_format(100 - $dash, 3) ?>"
                        stroke-dashoffset="<?= number_format(-$offset, 3) ?>" transform="rotate(-90 18 18)" stroke-linecap="round" />
                    <?php $offset += $b['pct']; endforeach; ?>
                </svg>
                <div class="ta-donut-legend">
                    <?php foreach ($wd['buckets'] as $i => $b): $color = $colors[$i % count($colors)]; ?>
                    <div class="ta-donut-legend-row"><span class="ta-donut-swatch" style="background:<?= $color ?>"></span><span class="ta-donut-legend-label"><?= htmlspecialchars($b['label']) ?></span><span class="ta-donut-legend-value"><?= number_format($b['pct'], 0) ?>%</span></div>
                    <?php endforeach; ?>
                </div>
            </div>
            <?php endif; ?>
            <?php endif; ?>
        </div>
    </div>
    <?php
}

/** Shared 2-segment donut (Regular/After a Loss) — used by both Deposit History and Deposit Pattern, since they're the same real classification presented twice. */
function taLiveTwoBucketDonut(float $pct1, float $pct2, string $label1, string $label2): void {
    $dash1 = max(0, $pct1 - ($pct1 > 0 && $pct1 < 100 ? 1 : 0));
    ?>
    <div class="ta-donut-wrap">
        <svg viewBox="0 0 36 36" class="ta-donut-svg" role="img" aria-label="<?= htmlspecialchars($label1) ?> vs <?= htmlspecialchars($label2) ?>">
            <circle cx="18" cy="18" r="15.9155" fill="none" stroke="var(--rn-gold)" stroke-width="4.3" />
            <circle cx="18" cy="18" r="15.9155" fill="none" stroke="var(--rn-green)" stroke-width="4.3"
                stroke-dasharray="<?= number_format($dash1, 3) ?> 100" transform="rotate(-90 18 18)" stroke-linecap="round" />
            <text x="18" y="16.5" text-anchor="middle" class="ta-donut-value"><?= number_format($pct1, 0) ?>%</text>
            <text x="18" y="21.5" text-anchor="middle" class="ta-donut-label"><?= htmlspecialchars($label1) ?></text>
        </svg>
        <div class="ta-donut-legend">
            <div class="ta-donut-legend-row"><span class="ta-donut-swatch" style="background:var(--rn-green)"></span><span class="ta-donut-legend-label"><?= htmlspecialchars($label1) ?></span><span class="ta-donut-legend-value"><?= number_format($pct1, 0) ?>%</span></div>
            <div class="ta-donut-legend-row"><span class="ta-donut-swatch" style="background:var(--rn-gold)"></span><span class="ta-donut-legend-label"><?= htmlspecialchars($label2) ?></span><span class="ta-donut-legend-value"><?= number_format($pct2, 0) ?>%</span></div>
        </div>
    </div>
    <?php
}

/** Growth Interruptions (bars) · Deposit Pattern (donut, same classification as Deposit History) · Trading Longevity (stats) — three cards in one row. */
function taLiveSuccessInterruptionsQualityLongevity(array $data): void {
    $interruptions = $data['growth_interruptions'];
    $fq = $data['funding_quality'];
    $long = $data['trading_longevity'];
    ?>
    <div class="ta-section-grid-3">
        <div class="rn-trade-journal">
            <h3 class="ta-card-h3">Growth Interruptions <span title="Real, independently-gated behavioral signals. Each only appears when this account's own history actually shows it." class="ta-info-dot">ⓘ</span></h3>
            <?php if (empty($interruptions)): ?>
            <p class="ta-empty-note">No real interruption patterns detected on this account.</p>
            <?php else: ?>
            <?php taSuccessBarList($interruptions, 'var(--rn-red)'); ?>
            <?php endif; ?>
        </div>
        <div class="rn-trade-journal">
            <h3 class="ta-card-h3">Deposit Pattern <span title="What share of your deposits were regular/steady vs. following a recent losing stretch, the same classification as Deposit History above." class="ta-info-dot">ⓘ</span></h3>
            <?php if (!$fq['available']): ?>
            <p class="ta-empty-note">No deposits recorded on this account yet.</p>
            <?php elseif ($fq['n'] === 1): ?>
            <p class="ta-empty-note">Your only deposit was $<?= number_format($fq['total_deposits'], 2) ?>, classified as <?= $fq['planned_count'] === 1 ? 'a regular deposit' : 'following a losing stretch' ?>. Not enough deposit history yet for a real pattern.</p>
            <?php else: ?>
            <?php taLiveTwoBucketDonut($fq['planned_pct'], $fq['reactive_pct'], 'Regular Deposits', 'After a Loss'); ?>
            <p class="ta-live-praise"><?= $fq['planned_pct'] >= 70 ? 'Most deposits were regular, steady additions.' : ($fq['planned_pct'] >= 40 ? 'A mix of regular and loss-driven deposits.' : 'Most deposits followed a losing stretch.') ?></p>
            <?php endif; ?>
        </div>
        <div class="rn-trade-journal">
            <h3 class="ta-card-h3">Trading Longevity <span title="Longest inactive period = the single largest real gap between two trading days. Current active streak = distinct trading days since the last real 14+ day break." class="ta-info-dot">ⓘ</span></h3>
            <?php if (!$long['available']): ?>
            <p class="ta-empty-note">Not enough historical data yet on this account.</p>
            <?php else: ?>
            <div class="ta-longevity-headline"><?= $long['account_age_days'] !== null ? htmlspecialchars(formatAccountLongevity($long['account_age_days'])) : '-' ?></div>
            <div class="ta-live-substats">
                <div><span class="ta-live-substat-label">Longest inactive period</span><span class="ta-live-substat-value"><?= $long['longest_inactive_days'] ?> day<?= $long['longest_inactive_days'] === 1 ? '' : 's' ?></span></div>
                <div><span class="ta-live-substat-label">Current active streak</span><span class="ta-live-substat-value"><?= number_format($long['current_streak_trading_days']) ?> trading day<?= $long['current_streak_trading_days'] === 1 ? '' : 's' ?></span></div>
            </div>
            <p class="ta-live-praise"><?= $long['current_streak_trading_days'] >= 60 ? 'Strong long-term trading consistency.' : 'Building real trading consistency over time.' ?></p>
            <?php endif; ?>
        </div>
    </div>
    <?php
}

/** Best Instruments (horizontal bars, live-only — Prop Firms' Instrument Performance keeps its existing donut, taSuccessInstrumentPie(), untouched) · Goal Timeline (reused unchanged) · Your Winning Edge (reused unchanged — its 6 fields already match the approved spec exactly). */
function taLiveSuccessInstrumentsAndTimeline(array $data): void {
    // Goal Timeline always keeps its place on the page (2026-08-06
    // correction, reversing an earlier "hide it entirely" attempt) —
    // don't make a feature disappear just because this account hasn't
    // used it yet; make its state obvious instead. Mirrors Prop Firms'
    // own taSuccessSectionFour() exactly: when this account has never
    // set a growth goal, taSuccessGoalTimelineChart() already renders a
    // real, intentional empty state (a muted placeholder line, "Your
    // Goal Timeline is almost ready", and a real 0/N progress-dot row)
    // rather than a bare missing card — same function, same fallback
    // shape, no new logic needed here.
    ?>
    <div class="ta-section-grid-3">
        <div class="rn-trade-journal">
            <h3 class="ta-card-h3">Best Instruments</h3>
            <?php taLiveInstrumentBars($data['instrument_performance']); ?>
        </div>
        <div class="rn-trade-journal">
            <h3 class="ta-card-h3" style="margin-bottom:.3rem">Goal Timeline</h3>
            <p class="ta-empty-note" style="margin-bottom:.8rem">Average path to goal, typical progress toward target as a goal plays out, not a period comparison.</p>
            <?php taSuccessGoalTimelineChart($data['funded_goal']['applicable'] ? $data['funded_goal']['timeline'] : ['available' => false, 'n' => 0]); ?>
        </div>
        <div class="rn-trade-journal">
            <h3 class="ta-card-h3">Your Winning Edge</h3>
            <?php taSuccessWinningEdge($data['winning_edge']); ?>
        </div>
    </div>
    <?php
}

/** Simple horizontal bar list, by real trade share — the live-account equivalent of taSuccessInstrumentPie()'s donut, per the approved prototype ("XAUUSD / EURUSD / GBPUSD / US30 / Others" as plain bars). Same underlying instrumentPerformance() data, no new query. */
/** A bare "100%" bar communicates nothing when it's really just one or two trades — every row now always states its own real trade count first, since that's the context a percentage alone can't convey, and adds real expectancy (only once 3+ R-multiple samples exist for that instrument — see instrumentPerformance()'s own gate) when it's statistically meaningful. */
function taLiveInstrumentBars(array $perf): void {
    if (!$perf['available']) { taEmptyStateBlock('Once trades close on this account, your best-performing instruments will show up here.'); return; }
    ?>
    <div class="ta-live-instrument-bars">
        <?php foreach ($perf['slices'] as $s): ?>
        <div class="ta-cause-row">
            <span class="ta-cause-label"><?= htmlspecialchars($s['instrument']) ?></span>
            <div class="ta-cause-bar"><div class="ta-cause-fill" style="width:<?= $s['pct'] ?>%;background:var(--rn-blue)"></div></div>
            <span class="ta-cause-count"><?= (int)$s['count'] ?> trade<?= (int)$s['count'] === 1 ? '' : 's' ?> · <?= $s['pct'] ?>%<?= $s['expectancy_r'] !== null ? ' · ' . number_format($s['expectancy_r'], 2) . 'R' : '' ?></span>
        </div>
        <?php endforeach; ?>
    </div>
    <?php
}
