{% from 'components/session_nav.html' import render_session_nav %}

{{ title }}

{% if page_info %} {% endif %} {% include 'components/timeline.html' %}

🔍 Search & Filter

{% include 'components/search_inline.html' %}
{% if combined_transcript_link %} {% elif sessions and sessions|length > 1 %} {{ render_session_nav(sessions, "toc") }} {% endif %} {% macro render_message(message) %} {%- set message_title = message.rendered_title %} {%- set html_content = message.rendered_html %} {%- set formatted_timestamp = message.rendered_timestamp %} {% if message.fork_only %} {# Fork-only landmark (#233 follow-up): this slot is a fork point whose own message body was filtered out at the current detail level, but it is kept (not ghosted) so the fork point stays visible and anchorable — like the branches it connects. Render ONLY the fork-point box (no message card), at the slot's original position. The anchor id lives on the box so branch back-links (`from ⟂ Fork point`) and the nav fork item resolve here. #}
{% for child in message.children %}{{ render_message(child) }}{% endfor %}{% if message.junction_forward_links %}
⑂ Fork point{% if message.fork_point_preview %} • {{ message.fork_point_preview }}{% endif %}
{% for branch_sid, branch_idx, branch_preview in message.junction_forward_links %} ↳ Branch{% if branch_preview %} • {{ branch_preview }}{% endif %} {% endfor %}
{% endif %}
{% elif is_session_header(message) %} {% if not message.is_branch_header %}
{% endif %} {# Structural wrapper: the message card and its nested .children render as SIBLINGS here, so the card's border/background/margins frame only the card itself, not the whole subtree (issue #174 nested-DOM follow-up). #}
{% if message.is_branch_header %}↳ {% else %}Session: {% endif %}{{ html_content|safe }}{% if message.display_model and not message.is_branch_header %} {{ message.display_model }}{% endif %}
{% if message.has_children %}
{% if message.immediate_children_count == message.total_descendants_count %} {# Same count = only one level, show single full-width button #}
{{ message.get_immediate_children_label() }}
{% else %} {# Multiple levels, show both buttons #}
{{ message.get_immediate_children_label() }}
⏷⏷ {{ message.get_total_descendants_label() }} total
{% endif %}
{% endif %}
{% if message.children or message.junction_forward_links %}
{% for child in message.children %}{{ render_message(child) }}{% endfor %}{% if message.junction_forward_links %} {# Fork point — rendered INSIDE .children so it folds together with the subtree (folding hides .children). For a childless junction it is the sole occupant. The opening tag is glued to endfor so non-junction nodes emit no extra whitespace. #}
⑂ Fork point{% if message.fork_point_preview %} • {{ message.fork_point_preview }}{% endif %}
{% for branch_sid, branch_idx, branch_preview in message.junction_forward_links %} ↳ Branch{% if branch_preview %} • {{ branch_preview }}{% endif %} {% endfor %}
{% endif %}
{% endif %}
{% elif message.should_render %} {%- set msg_css_class = css_class_from_message(message) %} {% set markdown = message.content.has_markdown if message.content else false %}
{% set msg_emoji = get_message_emoji(message) -%} {% if message_title %}{% if message_title == 'Memory' %}💭 {% elif msg_emoji and (message.type != 'tool_use' or not starts_with_emoji(message_title)) %}{{ msg_emoji }} {% endif %}{{ message_title | safe }}{% endif %}
{{ formatted_timestamp }}
{% if message.token_usage %} {{ message.token_usage }} {% endif %}
{% if message.meta %}
{{ message.meta.uuid[:12] }}{% if message.meta.parent_uuid %} → {{ message.meta.parent_uuid[:12] }}{% endif %}
{% endif %}
{{ html_content | safe }}
{% if message.has_children %}
{% if message.immediate_children_count == message.total_descendants_count %} {# Same count = only one level, show single full-width button #}
{{ message.get_immediate_children_label() }}
{% else %} {# Multiple levels, show both buttons #}
{{ message.get_immediate_children_label() }}
⏷⏷ {{ message.get_total_descendants_label() }} total
{% endif %}
{% endif %}
{% if message.children or message.junction_forward_links %}
{% for child in message.children %}{{ render_message(child) }}{% endfor %}{% if message.junction_forward_links %} {# Fork point — rendered INSIDE .children so it folds together with the subtree (folding hides .children). For a childless junction it is the sole occupant. The opening tag is glued to endfor so non-junction nodes emit no extra whitespace. #}
⑂ Fork point{% if message.fork_point_preview %} • {{ message.fork_point_preview }}{% endif %}
{% for branch_sid, branch_idx, branch_preview in message.junction_forward_links %} ↳ Branch{% if branch_preview %} • {{ branch_preview }}{% endif %} {% endfor %}
{% endif %}
{% endif %}
{% endif %} {% endmacro %} {% for root in roots %}{{ render_message(root) }}{% endfor %} 🔝 {% set is_transcript = True %} {% include 'components/search.html' %}