diff --git a/atlas/templates/atlas/partials/_collection_case_jump.html b/atlas/templates/atlas/partials/_collection_case_jump.html
new file mode 100644
index 00000000..5930b268
--- /dev/null
+++ b/atlas/templates/atlas/partials/_collection_case_jump.html
@@ -0,0 +1,11 @@
+{% for cd in casedetails %}
+ {% with idx=forloop.counter0 %}
+ {% if cid %}
+
+ {% else %}
+
+ {% endif %}
+ Case {{ forloop.counter }}: {{ cd.case.title|default:cd.case.pk|truncatechars:60 }}
+
+ {% endwith %}
+{% endfor %}
diff --git a/atlas/urls.py b/atlas/urls.py
index 17557772..868399fc 100755
--- a/atlas/urls.py
+++ b/atlas/urls.py
@@ -112,6 +112,11 @@ urlpatterns = [
views.CollectionCaseUpdate.as_view(),
name="collection_case_update",
),
+ path(
+ "collection/
/case_jump",
+ views.collection_case_jump_partial,
+ name="collection_case_jump_partial",
+ ),
path(
"collection/add_cases",
views.add_cases_to_collection,
diff --git a/atlas/views.py b/atlas/views.py
index 0c6cb6f7..3995e5a4 100755
--- a/atlas/views.py
+++ b/atlas/views.py
@@ -1134,6 +1134,46 @@ def collection_options(request):
html = render_to_string("atlas/partials/collection_options.html", {"collections": collections}, request=request)
return HttpResponse(html)
+
+@login_required
+def collection_case_jump_partial(request, pk: int):
+ """Return an HTMX partial containing a jump list for cases in the collection.
+
+ Expects optional GET params:
+ - current: the current case index (0-based) to mark active
+ - cid, passcode: optional candidate identifiers so links include them when present
+ """
+ # Allow non-HTMX callers to still get the fragment (useful for testing)
+ collection = get_object_or_404(CaseCollection, pk=pk)
+
+ casedetails = (
+ CaseDetail.objects.filter(collection=collection)
+ .select_related('case')
+ .order_by('sort_order')
+ )
+
+ try:
+ current = int(request.GET.get('current', 0) or 0)
+ except Exception:
+ current = 0
+
+ cid = request.GET.get('cid')
+ passcode = request.GET.get('passcode')
+
+ html = render_to_string(
+ 'atlas/partials/_collection_case_jump.html',
+ {
+ 'collection': collection,
+ 'casedetails': casedetails,
+ 'current': current,
+ 'cid': cid,
+ 'passcode': passcode,
+ },
+ request=request,
+ )
+
+ return HttpResponse(html)
+
@login_required
def remove_cases_from_collection(request):
if not request.htmx: