{# Shared asset timeline fragment (ARG-205). Renders a merged, reverse- chronological list of `TimelineEvent`s β€” status transitions (βœ…), signal alerts (πŸ”­), and successions (🧬). Used by the portfolio card accordion (GET /portfolio/{asset_id}/timeline, limit=5) and the item-detail page (fetch_timeline with no limit). `events` and `empty_message` are read by both call sites. Enhance/Fork's "이 κΈ°μˆ λ„ Keep" hx-post target is built from each event's own `e.link_tech_id` β€” the Replace handoff banner itself lives outside this partial (`_portfolio_cards.html` / `_detail_actions.html`), since it must render even before this fragment is fetched (ARG-209). #} {% set _events = events if events is defined else [] %} {% if _events %}
    {% for e in _events %}
  1. {% if e.kind == "succession" %} {% if e.is_inferred %} {# ARG-209: render-time inference only β€” the handoff (real or manual) already happened, so this is informational text, not a CTA. #} πŸ” {{ e.title }}μ—μ„œ μ΄μ–΄λ°›μŒ {% else %} {{ e.relation_type.value }} {% if e.link_tech_id %} {{ e.title }} {% else %} {{ e.title }} {% endif %} {% if e.reasoning %}

    {{ e.reasoning }}

    {% endif %} {% if e.relation_type.value != "Replace" and e.link_tech_id %} {# Enhance/Fork: no banner (ARG-209 AC3) β€” just a lightweight "also Keep this" CTA that reuses POST /items/{id}/keep as-is (no new route). hx-swap="none" because the response is a feed-card fragment that doesn't fit this row; the mutation itself is what matters here. #} {% endif %} {% endif %} {% elif e.kind == "signal" and e.link_tech_id %} {{ e.label }} {% else %} {{ e.label }} {% endif %}
  2. {% endfor %}
{% else %}

{{ empty_message if empty_message is defined else "아직 좔적 μ΄λ²€νŠΈκ°€ μ—†μŠ΅λ‹ˆλ‹€" }}

{% endif %}