{# One batch of timeline day-sections plus, when more of the library remains, the infinite-scroll sentinel htmx swaps for the next batch. The full page (index.html) includes this for the first batch; the fragment response (?fragment=sections) IS this template, so both renders share one source. A section marked is-continuation carries on the day the previous batch ended with: its header is suppressed and timeline_stream.js merges its cards into the section above. #} {% from "components/photo_card.html" import photo_card %} {% for group in timeline_groups %} {% if group.month_start and group.month_label %} {# The id is the scrubber's jump target: a month's first photo sits mid-page (page = offset // page_size), so landing scrolls here. #}

{{ group.month_label }}

{% endif %}
{% if not group.continuation %}

{{ group.day_label }} {% trans trimmed count=group.media_items|length, shown=group.media_items|length|format_integer %} {{ shown }} item {% pluralize %} {{ shown }} items {% endtrans %}

{% endif %}
{% for media_item in group.media_items %} {{ photo_card(media_item) }} {% endfor %}
{% endfor %} {% if next_fragment_url %} {% endif %}