{# At a loss — Phase 2 dedicated table (§3.3 of UI/UX redesign spec). Reads `rows` (list of HarvestOpportunity), `only_harvestable` (bool), and `budget` from context — passed by `routes/positions.py` when `selected_view == 'at-loss'`. The harvestable-only checkbox uses `harvest_form_action` and `harvest_form_target` from context (Phase 1 review-fix Critical #1) so HTMX targets work on the new home. Phase 3 polishes: stacked mini-bar in the summary strip (T5-style), inline sim preview on hover, replacement detail (gain/loss for substitute), and density-aware row height. #}
{{ rows|length }} lots at a loss {% if total_unrealized is defined and rows %} · {{ fmt_currency(total_unrealized) }} unrealized {% endif %} {% if harvest_clear_count is defined and rows %} · {{ harvest_clear_count }} currently harvest-clear {% endif %} {% if budget is defined and budget %} · LH-budget {{ fmt_currency(budget.net_realized) }} / {{ fmt_currency(budget.cap_against_ordinary) }} cap {% endif %} {% if replacements_count is defined and rows %} · ETF replacements: {{ replacements_count }} {% endif %}
{# Scope filters (period, account) must round-trip through this HTMX request so the user doesn't get bumped back to the default scope when they toggle the harvestable checkbox. Default action also points back at /positions?view=at-loss so even the fallback path stays on this page instead of bouncing through the /tax?view=harvest 301 redirect. #}
{% if selected_period %} {% endif %} {% for a in selected_accounts %} {% endfor %}

Loading harvest plan…