{% load case_widgets %}

{% partialdef case-series %}
    {% for series in ordered_series %}
        <article class="series-block series-block-interactive series-block-draggable"
                 id="series-block-{{ series.pk }}"
                 data-series-id="{{series.pk}}"
                 data-series-label="Series {{ forloop.counter }}"
                 data-series-name="{{ series.get_viewer_stack_description|escape }}"
                 data-image-ids='{{ series.get_image_url_array_and_count.0 }}'
                 data-series-detail-url="{% url 'atlas:series_detail' pk=series.pk %}"
                 data-series-popup-url="/atlas/series/{{series.pk}}"
                 draggable="true">
            <input type="checkbox" class="hide" name="series-ids" value="{{series.pk}}">
            <div class="series-card-shell">
                <div type="button"
                     class="series-card-main"
                     data-series-action="details"
                     data-series-id="{{series.pk}}"
                     aria-label="Open series actions for Series {{ forloop.counter }}">
                    <div class="series-card-thumb-wrap">
                        {% with series_thumbnail=series.get_thumbnail %}
                            {% if series_thumbnail.1 %}
                                <div class="series-card-thumb-generated" aria-label="Series {{ forloop.counter }} thumbnail">
                                    {{ series_thumbnail.0|safe }}
                                </div>
                            {% else %}
                                <div class="series-card-thumb series-card-thumb-placeholder">
                                    <i class="bi bi-image"></i>
                                </div>
                            {% endif %}
                        {% endwith %}
                    </div>
                    <div class="series-card-content">
                        <div class="series-card-heading">
                            <span class="series-card-series-number">Series {{ forloop.counter }}</span>
                            <span class="series-card-image-count">{{ series.visible_image_count }} image{{ series.visible_image_count|pluralize }}</span>
                        </div>
                        <div class="series-card-description text-truncate" style="max-width: 180px;" title="{{ series.description|default:'No description' }}">
                            {{ series.description|default:"No description" }}
                        </div>
                        <button type="button"
                                class="btn btn-link btn-sm text-muted series-open-primary-btn"
                                title="View series in viewer"
                                data-series-id="{{series.pk}}"
                                data-series-name="{{ series.get_viewer_stack_description|escape }}">
                            <i class="bi bi-eye"></i> View
                        </button>
                        <div class="series-card-inline-actions">
                            <button type="button"
                                    class="btn btn-outline-primary btn-sm select-series-btn"
                                    style="display: none;"
                                    data-series-id="{{series.pk}}">
                                Select
                            </button>
                            <button type="button"
                                    class="btn btn-outline-info btn-sm series-open-new-viewport-btn d-none"
                                    title="View series in a new pane"
                                    data-series-id="{{series.pk}}"
                                    data-series-name="{{ series.get_viewer_stack_description|escape }}"
                                    tabindex="-1"
                                    aria-hidden="true">
                                <i class="bi bi-layout-split"></i> View in new pane
                            </button>
                        </div>
                    </div>
                </div>
            </div>
        </article>
    {% endfor %}
{% endpartialdef %}

<style>
    .case-inline-field {
        position: relative;
    }

    .case-inline-field .quick-edit-button {
        border: 0;
        background: transparent;
        color: var(--bs-secondary-color, #6c757d);
        font-size: 0.8rem;
        line-height: 1.1;
        padding: 0;
        text-decoration: none;
    }

    .case-inline-field .quick-edit-button:hover {
        text-decoration: underline;
    }

    .case-inline-field .quick-edit-compact {
        position: absolute;
        top: 0;
        right: 0;
        z-index: 2;
        opacity: 0.35;
        pointer-events: auto;
    }

    .case-inline-field .quick-edit-trigger {
        opacity: 0;
        pointer-events: none;
        transition: opacity 0.15s ease;
    }

    .case-inline-field:hover .quick-edit-trigger,
    .case-inline-field:focus-within .quick-edit-trigger {
        opacity: 0.65;
        pointer-events: auto;
    }

    .case-inline-field .quick-edit-trigger:hover {
        opacity: 1;
    }

    .case-inline-field .quick-edit-compact.quick-edit-trigger {
        opacity: 0.35;
        pointer-events: auto;
    }

    .case-inline-field:hover .quick-edit-compact.quick-edit-trigger,
    .case-inline-field:focus-within .quick-edit-compact.quick-edit-trigger {
        opacity: 0.9;
    }

    /* Generic hover-only quick-edit behaviour for host-wrapped buttons.
       Buttons are positioned absolutely so revealing them does not shift layout. */
    .quick-edit-wrap { position: relative; display: inline-flex; align-items: center; }
    .quick-edit-wrap .quick-edit-button {
        position: absolute;
        right: 0.25rem;
        top: 50%;
        transform: translateY(-50%);
        z-index: 5;
        opacity: 0;
        pointer-events: none;
        transition: opacity 0.15s ease, transform 0.15s ease;
        background: rgba(255,255,255,0.95) !important;
        border-radius: .25rem;
        padding: 0 .25rem;
        color: #0d6efd !important; /* clearer action colour */
    }
    .quick-edit-wrap:hover .quick-edit-button,
    .quick-edit-wrap:focus-within .quick-edit-button {
        opacity: 0.95;
        pointer-events: auto;
        transform: translateY(-50%);
    }
    .quick-edit-wrap .quick-edit-button:hover { opacity: 1; }

    @media (max-width: 767.98px) {
        .quick-edit-wrap .quick-edit-button,
        .case-meta-item .quick-edit-button,
        .case-inline-field .quick-edit-compact {
            opacity: 0.95;
            pointer-events: auto;
            padding: 0.15rem 0.35rem;
            font-size: 0.9rem;
        }
    }

    /* Metadata-specific quick-edit: ensure edit button overlays without moving badges */
    .case-meta-item { position: relative; }
    .case-meta-item .quick-edit-button {
        position: absolute;
        right: 0.25rem;
        top: 50%;
        transform: translateY(-50%);
        z-index: 6;
        opacity: 0;
        pointer-events: none;
        background: rgba(255,255,255,0.95) !important;
        padding: 0 .25rem;
        border-radius: .25rem;
        color: #0d6efd !important;
        border: 1px solid rgba(13,110,253,0.08);
    }
    .case-meta-item:hover .quick-edit-button,
    .case-meta-item:focus-within .quick-edit-button {
        opacity: 0.95;
        pointer-events: auto;
    }

    /* Normal group visual style */
    .normal-group { border: 1px solid rgba(13,110,253,0.15); background: #f8fbff; padding: .75rem; border-radius: .375rem; margin-bottom: .75rem; }
    .normal-group .normal-heading { font-weight: 600; color: #0d6efd; margin-bottom: .5rem; }
    .normal-group .badge { margin-right: .25rem; }


    .section-icon { display:inline-block; width:10px; height:10px; border-radius:50%; margin-right:0.5rem; }
    .section-icon.description { background:#6c757d; }
    .section-icon.presentation { background:#0d6efd; }
    .section-icon.history { background:#198754; }
    .section-icon.discussion { background:#fd7e14; }
    .section-icon.report { background:#dc3545; }
    /* Series block base (Bootstrap-like card appearance) */
    .series-block {
        display: inline-block;
        vertical-align: top;
        min-width: 180px;
        max-width: 320px;
        margin: .25rem;
        padding: .5rem;
        border-radius: .375rem;
        background: #f8f9fa;
        border: 1px solid rgba(0,0,0,0.06);
        text-align: left;
    }

    /* Enhanced series block with interactive features */
    .series-block-interactive {
        transition: all 0.2s ease;
        cursor: pointer;
    }

    .series-block-interactive:hover {
        box-shadow: 0 2px 8px rgba(13, 110, 253, 0.15);
        border-color: rgba(13, 110, 253, 0.3);
    }

    /* Draggable series block */
    .series-block-draggable {
        cursor: grab;
        position: relative;
    }
    .series-block-draggable:active {
        cursor: grabbing;
    }
    .series-block-draggable::after {
        content: '\2807';
        position: absolute;
        top: 0.35rem;
        right: 0.35rem;
        font-size: 0.85rem;
        color: rgba(120, 150, 200, 0.45);
        pointer-events: none;
        line-height: 1;
    }
    .series-block-draggable.dragging {
        opacity: 0.55;
        box-shadow: 0 4px 16px rgba(25, 118, 210, 0.35);
    }

    .series-block-actions {
        display: flex;
        flex-wrap: wrap;
        gap: 0.25rem;
        margin-top: 0.5rem;
    }

    .series-block-actions .btn {
        padding: 0.25rem 0.5rem;
        font-size: 0.75rem;
    }

    .series-block-actions .btn-xs {
        min-width: auto;
    }

    /* Also support dark theme when site sets a theme attribute/class */
    .atlas[data-bs-theme="dark"] .series-block,
    [data-bs-theme="dark"] .series-block,
    body[data-bs-theme="dark"] .series-block,
    body.bg-dark .series-block,
    .bg-dark .series-block,
    .dark .series-block,
    .theme-dark .series-block {
        background: #071018 !important;
        border-color: rgba(255,255,255,0.03) !important;
        color: #e6eef8 !important;
    }

    .atlas[data-bs-theme="dark"] .series-block-interactive:hover,
    [data-bs-theme="dark"] .series-block-interactive:hover,
    body[data-bs-theme="dark"] .series-block-interactive:hover,
    body.bg-dark .series-block-interactive:hover,
    .bg-dark .series-block-interactive:hover,
    .dark .series-block-interactive:hover,
    .theme-dark .series-block-interactive:hover {
        border-color: rgba(158, 197, 255, 0.3) !important;
        box-shadow: 0 2px 8px rgba(158, 197, 255, 0.1) !important;
    }
    /* Also support dark theme when site sets a theme attribute/class */
    .atlas[data-bs-theme="dark"] .series-block,
    [data-bs-theme="dark"] .series-block,
    body[data-bs-theme="dark"] .series-block,
    body.bg-dark .series-block,
    .bg-dark .series-block,
    .dark .series-block,
    .theme-dark .series-block {
        background: #071018 !important;
        border-color: rgba(255,255,255,0.03) !important;
        color: #e6eef8 !important;
    }
    .case-metadata { border-left: 1px solid #eee; padding-left: 1rem; text-align:left; }
    .case-meta-item { margin-bottom: .5rem; }
    .case-meta-label { font-weight:600; font-size:0.9rem; display:block; }
    @media (min-width: 768px) {
                /* Keep metadata stacked (one per row), but put label and value on same row */
        .case-metadata { text-align: right; }
        .case-meta-item { display: flex; justify-content: space-between; align-items: center; margin-bottom: .5rem; }
        .case-meta-value { display: flex; align-items: center; gap: .5rem; justify-content: flex-end; }
        .case-meta-item .badge { display: inline-block; margin-left: .25rem; margin-right: 0; }
        .case-meta-item > .case-meta-value > div { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
    }
            /* Description & Presentation visual improvements */
    .case-description { background: #eef3f73d; border: 1px solid rgba(0,0,0,0.08); padding: .75rem; border-radius: .375rem; }
    .case-description strong { font-size: 1.05rem; margin-right: .5rem; }
    .case-description .case-inline-field { margin-top: .5rem; }

    .case-presentation ul { list-style: none; padding-left: 0; margin: .25rem 0 0 0; display: flex; flex-wrap: wrap; gap: .5rem; }
    .case-presentation li { background: rgba(13,110,253,0.12); color: #0b5ed7; padding: .25rem .5rem; border-radius: .25rem; font-size: .9rem; }
    .case-presentation b { margin-right: .5rem; }

    .displayset-empty-state {
        display: inline-flex;
        align-items: center;
        gap: .6rem;
        margin: .4rem 0;
        padding: .45rem .65rem;
        border-radius: .5rem;
        border: 1px solid rgba(13, 110, 253, 0.2);
        background: rgba(13, 110, 253, 0.06);
    }

    .displayset-empty-link {
        display: inline-block;
        padding: .25rem .6rem;
        border-radius: 999px;
        background: #0d6efd;
        color: #fff;
        font-size: .82rem;
        font-weight: 600;
        text-decoration: none;
        transition: background-color .15s ease, transform .15s ease;
    }

    .displayset-empty-link:hover,
    .displayset-empty-link:focus {
        background: #0b5ed7;
        color: #fff;
        transform: translateY(-1px);
        text-decoration: none;
    }

            /* Dark mode adjustments */
    @media (prefers-color-scheme: dark) {
        .case-description {
            background: #0f1720;
            border: 1px solid rgba(255,255,255,0.06);
            color: #e6eef8;
        }
        .case-description strong { color: #ffffff; }
        .case-description .case-inline-field { color: #e6eef8; }
        .case-presentation li { background: rgba(255,255,255,0.03); color: #9ec5ff; }
        .quick-edit-wrap .quick-edit-button,
        .case-meta-item .quick-edit-button {
            background: rgba(255,255,255,0.04) !important;
            color: #9ec5ff !important;
            border: 1px solid rgba(255,255,255,0.06);
        }
        .displayset-empty-state {
            border-color: rgba(158, 197, 255, 0.3);
            background: rgba(158, 197, 255, 0.1);
        }
        .displayset-empty-link {
            background: #9ec5ff;
            color: #042b61;
        }
        .displayset-empty-link:hover,
        .displayset-empty-link:focus {
            background: #bfdbff;
            color: #042b61;
        }
        /* Series block dark theme adjustments */
        .series-block {
            background: #071018;
            border-color: rgba(255,255,255,0.03);
            color: #e6eef8;
            box-shadow: none;
        }
        .series-block a { color: inherit; }
        .series-block .series-block-series-number { color: #cfe6ff; }
        .series-block .series-block-popup-link a { color: #9ec5ff; }
        #case-series-row { gap: .5rem; }
    }
</style>

<div class="atlas {% if case.scrapped %}atlas-scrapped{% endif %}">
    <div class="btn-group btn-group-sm link-buttons" role="group">
        <button type="button" class="btn btn-primary btn-sm"
                onclick="window.location.href='/ohif/viewer/dicomjson?url=https://www.penracourses.org.uk{% url 'atlas:case_dicom_json' case.pk %}'">View case in OHIF</button>
        <button type="button" class="btn btn-primary btn-sm dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown" aria-expanded="false">
            <span class="visually-hidden">Toggle dropdown</span>
        </button>
        <ul class="dropdown-menu">
            <li>
                <a class="dropdown-item" target="_blank" href="/ohif/viewer/dicomjson?url=https://www.penracourses.org.uk{% url 'atlas:case_dicom_json' case.pk %}">Open in new tab</a>
            </li>
            {% if can_edit %}
                <li>
                    <a class="dropdown-item" href="{% url 'atlas:case_download' case.pk %}">Download DICOMs + metadata (ZIP)</a>
                </li>
            {% endif %}
        </ul>
    </div>
    <div class="normal-block">
        <div class="mt-1">
            {% include "atlas/partials/_normal_toggle.html" %}
        </div>
    </div>
    <h2 class="d-flex align-items-center" style="gap: .5rem; white-space: nowrap;">
        <span>Case:</span>
        <div class="d-flex align-items-center quick-edit-wrap">
            {% url 'atlas:case_inline_field' case.pk 'title' as title_url %}
            {% with endpoint_default=title_url|add:"?show_label=0" endpoint_edit=title_url|add:"?edit=1&show_label=0" %}
                {% include 'atlas/partials/case_inline_field.html' with show_label=0 editing=False field_label="Title" can_edit=can_edit endpoint_url_default=endpoint_default endpoint_url_edit=endpoint_edit container_id='case-inline-title' field_kind='text' value=case.title display_value=case.title field_name='title' error_message='' %}
            {% endwith %}
            {% if can_edit %}
                <button class="btn btn-sm btn-link text-muted p-0 ms-2 quick-edit-button"
                        hx-get="{% url 'atlas:case_inline_field' case.pk 'title' %}?edit=1&show_label=0"
                        hx-target="#case-inline-title"
                        hx-swap="outerHTML">quick edit</button>
            {% endif %}
        </div>
    </h2>
    {% if case.previous_case or case.next_case %}
        <div class="card border-info bg-info-subtle mb-3">
            <div class="card-body p-3">
                <div class="d-flex justify-content-between align-items-center border-bottom border-info-subtle pb-2 mb-2">
                    <span class="fw-semibold text-info-emphasis"><i class="bi bi-layers-half me-1"></i> Part of a Case Series</span>
                    <a href='{% url "atlas:linked_cases_overview" case.pk %}' class="btn btn-sm btn-outline-info text-decoration-none py-0 px-2" style="font-size: 0.8rem;">View Series Overview</a>
                </div>
                <div class="row text-center text-sm-start g-2">
                    <div class="col-6 border-end border-info-subtle d-flex flex-column justify-content-center">
                        {% if case.previous_case %}
                            <div>
                                <a href="{{ case.previous_case.get_absolute_url }}" class="text-decoration-none fw-semibold link-info" data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-delay='{"show":500,"hide":100}' title="{{ case.previous_case.description|striptags|default:'No description' }}">
                                    <i class="bi bi-arrow-left me-1"></i> Previous Case: {{ case.previous_case.title|default:'Untitled Case' }}
                                </a>
                            </div>
                        {% else %}
                            <div class="small text-muted italic">
                                <i class="bi bi-arrow-left me-1"></i> No previous case
                            </div>
                        {% endif %}
                    </div>
                    <div class="col-6 d-flex flex-column justify-content-center text-sm-end align-items-sm-end">
                        {% if case.next_case %}
                            <div>
                                <a href="{{ case.next_case.get_absolute_url }}" class="text-decoration-none fw-semibold link-info" data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-delay='{"show":500,"hide":100}' title="{{ case.next_case.description|striptags|default:'No description' }}">
                                    Next Case: {{ case.next_case.title|default:'Untitled Case' }} <i class="bi bi-arrow-right ms-1"></i>
                                </a>
                            </div>
                        {% else %}
                            <div class="small text-muted italic">
                                No follow-up case <i class="bi bi-arrow-right ms-1"></i>
                            </div>
                        {% endif %}
                    </div>
                </div>
            </div>
        </div>
    {% endif %}
    <div>

        {% if case.cimar_uuid %}

            <details><summary>Details</summary>
                Case uuid: {{case.cimar_uuid}}
                <br/>

                {% if cimar_sid %}
                    <a href="{{case.get_cimar_case.viewer_link}}?sid={{cimar_sid}}" target="_blank">External</a>
                {% else %}
                    <a href="{{case.get_cimar_case.viewer_link}}" target="_blank">External</a>

                {% endif %}


                <button
                    hx-get='{% url "cimar_study_viewer_embed" case.cimar_uuid %}'
                    hx-target="#modals-here"
                    hx-trigger="click"
                    data-bs-toggle="modal"
                    data-bs-target="#modals-here"
                    class="btn primary">Open Modal</button>

                <div id="modals-here"
                     class="modal modal-blur fade"
                     style="display: none"
                     aria-hidden="false"
                     tabindex="-1">
                    <div class="modal-dialog modal-lg modal-dialog-centered" role="document">
                        <div class="modal-content"></div>
                    </div>
                </div>

                <a href='{% url "cimar_study_viewer" case.cimar_uuid %}'>Viewer</a>


                <details>
                    <summary>Study details</summary>
                    {{ case.get_cimar_case.get_pretty_study_details }}
                </details>
                <details>
                    <summary>Study schema</summary>
                    {{ case.get_cimar_case.get_pretty_study_schema }}
                </details>
                <details>
                    <summary>Study series</summary>
                    <button
                        id='load-series'
                        hx-get='{% url "cimar_study_series_block" case.cimar_uuid %}'
                        hx-trigger='load'
                        hx-swap='outerHTML'>
                        Load Series
                    </button>
                </details>
                <a href='{% url "generic:cimar_case_refresh" case.cimar_uuid %}'>Refresh</a>

            </details>



        {% else %}

        {% endif %}

        <div class="clearfix mb-2">
            <div class="float-start">
                <span class="id">ID: {{ case.id }}</span>
                <span class="mx-1">/</span>
                <span class="date">{{ case.created_date|date:"d/m/Y" }}</span>
            </div>
        </div>

    </div>

    <details id="dicom-viewer-details">
        <summary>Viewer</summary>

        <div id="main_viewer" class="dicom-viewer-root"
             style="box-sizing: border-box; background: #222; width: 100%; height: 600px;"
             data-auto-cache-stack="false"
             data-named-stacks='{{case.get_case_named_stacks}}'
        ></div>
    </details>
    <details class="series-panel" id="case-series-panel" open>
        <summary class="series-panel-summary">
            <span class="series-panel-title">Series</span>
            <span class="series-panel-summary-actions">
                <span class="series-panel-badge">{{ ordered_series|length }} total</span>
                <button type="button"
                        class="btn btn-outline-primary btn-sm series-summary-btn"
                        id="series-import-uploads-btn"
                        onclick="window.location.href='{% url 'atlas:user_uploads_case' case_id=case.pk %}'">
                    Import new uploads
                </button>
                <button type="button"
                        class="btn btn-outline-secondary btn-sm series-summary-btn"
                        id="series-manage-toggle-btn"
                        aria-controls="series-actions-panel"
                        aria-expanded="false">
                    Manage series
                </button>
            </span>
        </summary>
        <div class="series-panel-body">
            <form>
                <div class="series-card-grid" id="case-series-row">
                    {% partial case-series %}
                </div>
            </form>
        </div>
    </details>

    <div class="series-actions-panel" id="series-actions-panel" aria-hidden="true">
        <div class="series-actions-panel-inner">
            <div class="series-actions-panel-header">
                <div>
                    <h5 class="mb-1">Manage series</h5>
                    <div class="small text-muted">Selection tools and bulk actions for this case.</div>
                </div>
                <button type="button" class="btn-close btn-close-white" id="series-manage-close-btn" aria-label="Close"></button>
            </div>
            <div class="series-actions" id="series-actions">
                <div class="series-actions-body">
                    <div class="series-actions-toolbar">
                        <a class="btn btn-sm btn-outline-secondary" href="{% url 'atlas:series_id_create' pk=case.pk %}">Create and add new series</a>
                        <button type="button"
                                class="btn btn-sm btn-secondary"
                                data-bs-toggle="modal"
                                data-bs-target="#reorderSeriesModal">
                            Reorder series
                        </button>
                        <button type="button" class="btn btn-sm btn-outline-primary" id="series-select-all-btn">Select all</button>
                        <button type="button" class="btn btn-sm btn-outline-secondary" id="series-deselect-all-btn">Deselect all</button>
                    </div>

                    <div class="series-actions-grid">
                        <button class="btn btn-sm btn-outline-secondary text-start" hx-get="{% url 'atlas:case_order_dicom' pk=case.pk %}"
                                title="order dicom by slice location"
                                hx-target="#series-action-results"
                                hx-swap="innerHTML"
                                hx-confirm="This will reorder all case series based upon slice location"
                        >
                            Order dicoms by slice location
                        </button>
                        <button class="btn btn-sm btn-outline-primary text-start" hx-post="{% url 'atlas:combine_series' %}"
                                title="merge series"
                                hx-include="[name='series-ids']"
                                hx-target="#series-action-results"
                                hx-swap="innerHTML"
                                hx-confirm="This will merge all selected series into one"
                        >
                            Merge selected series
                        </button>
                        <button class="btn btn-sm btn-outline-secondary text-start" hx-post="{% url 'atlas:use_dates_as_descriptions' case.pk %}"
                                title="use dicom dates as series descriptions"
                                hx-include="[name='series-ids']"
                                hx-target="#series-action-results"
                                hx-swap="innerHTML"
                                hx-confirm="This will use the dicom date as the series description"
                        >
                            Use dates as description
                        </button>
                        <button hx-post="{% url 'atlas:remove_selected_series_from_case' case.pk %}"
                                title="remove selected series from this case"
                                hx-include="[name='series-ids']:checked"
                                hx-target="#series-action-results"
                                hx-swap="innerHTML"
                                hx-confirm="Are you sure you want to remove the selected series from this case? They will not be deleted from the database."
                                class="btn btn-sm btn-warning text-start"
                                type="button"
                        >
                            Remove selected series from case
                        </button>
                        <button hx-post="{% url 'atlas:series_bulk_delete' %}"
                                id="series-delete-selected-btn"
                                title="delete selected series"
                                hx-include="[name='series-ids']:checked"
                                hx-target="#series-action-results"
                                hx-swap="innerHTML"
                                hx-indicator="#series-delete-indicator"
                                hx-confirm="Delete the selected series from the database? This cannot be undone."
                                class="btn btn-sm btn-danger text-start"
                                type="button">
                            Delete selected series
                        </button>
                        <span id="series-delete-indicator" class="htmx-indicator small text-danger">
                            <span class="spinner-border spinner-border-sm me-1" role="status" aria-hidden="true"></span>
                            Deleting...
                        </span>
                    </div>

                    <details class="series-move-panel border rounded p-2">
                        <summary class="small fw-semibold">Move selected series to another case</summary>
                        {% if move_series_form %}
                            <form id="move-selected-series-form" class="d-flex flex-column gap-2 mt-2">
                                {{ move_series_form.destination_case }}
                                <div class="small text-muted">Click any case row below to select the destination case.</div>
                                <div id="selected-move-case" class="small text-muted">No destination case selected.</div>
                                {% case_search_widget collection=None recent_cases=move_series_recent_cases input_id='move-series-case-search-input' target_id='move-series-case-search-results' show_select_button=True %}
                                <button type="button"
                                        id="move-selected-series-submit"
                                        class="btn btn-sm btn-outline-primary text-start"
                                        disabled
                                        hx-post="{% url 'atlas:move_selected_series_to_case' case.pk %}"
                                        hx-include="[name='series-ids']:checked, #move-selected-series-form [name='destination_case']"
                                        hx-target="#series-action-results"
                                        hx-swap="innerHTML"
                                        hx-confirm="Move selected series to the chosen destination case?">
                                    Move selected series
                                </button>
                            </form>
                            <script>
                                (function () {
                                    if (window.__moveSeriesCaseSelectionBound) return;
                                    window.__moveSeriesCaseSelectionBound = true;

                                    function applyMoveCaseSelection(casePk, caseTitle) {
                                        if (!casePk) return;

                                        const form = document.getElementById('move-selected-series-form');
                                        const hiddenInput = form ? form.querySelector("[name='destination_case']") : null;
                                        const label = document.getElementById('selected-move-case');
                                        const results = document.getElementById('move-series-case-search-results');
                                        if (!hiddenInput) return;

                                        hiddenInput.value = casePk;
                                        if (label) {
                                            label.innerHTML = 'Selected destination: <strong>' + caseTitle + ' (' + casePk + ')</strong>';
                                            label.classList.remove('text-muted');
                                        }

                                        if (results) {
                                            results.querySelectorAll('.list-group-item[data-case-pk]').forEach(function (item) {
                                                item.classList.toggle('active', String(item.getAttribute('data-case-pk')) === String(casePk));
                                            });
                                        }

                                        syncMoveSeriesSubmitState();
                                    }

                                    function syncMoveSeriesSubmitState() {
                                        const form = document.getElementById('move-selected-series-form');
                                        const hiddenInput = form ? form.querySelector("[name='destination_case']") : null;
                                        const submitBtn = document.getElementById('move-selected-series-submit');
                                        if (!hiddenInput || !submitBtn) return;
                                        submitBtn.disabled = !hiddenInput.value;
                                    }

                                    document.body.addEventListener('case:selected', function (e) {
                                        try {
                                            const detail = e.detail || {};
                                            const casePk = detail.casePk;
                                            const caseTitle = detail.caseTitle || ('Case #' + casePk);
                                            applyMoveCaseSelection(casePk, caseTitle);
                                        } catch (err) {
                                            console.error('Move series case:selected handler error', err);
                                        }
                                    });

                                    syncMoveSeriesSubmitState();
                                })();
                            </script>
                        {% else %}
                            <div class="text-muted small mt-2">Case move options are unavailable in this view.</div>
                        {% endif %}
                    </details>
                </div>
                <div class="alert alert-info mt-2" id="series-action-alert" style="display:none;">
                    <span id="series-action-results" ></span>
                </div>
            </div>
        </div>
    </div>

    <div class="container">


        <div class="row g-3 mb-3">
            <div class="col-12 col-md-8">
                <div class="mb-3 case-description">
                    <div class="d-flex align-items-start justify-content-between quick-edit-wrap">
                        <div class="d-flex align-items-start flex-grow-1">
                            <span class="section-icon description" aria-hidden="true"></span>
                            <strong>Description:</strong>
                            {% url 'atlas:case_inline_field' case.pk 'description' as desc_url %}
                            {% with endpoint_default=desc_url|add:"?show_label=0" endpoint_edit=desc_url|add:"?edit=1&show_label=0" %}
                                {% include 'atlas/partials/case_inline_field.html' with show_label=0 editing=False field_label="Description" can_edit=can_edit endpoint_url_default=endpoint_default endpoint_url_edit=endpoint_edit container_id='case-inline-description' field_kind='textarea' value=case.description display_value=case.description field_name='description' error_message='' %}
                            {% endwith %}
                        </div>
                        {% if can_edit %}
                            <button class="btn btn-sm btn-link text-muted p-0 ms-2 quick-edit-button"
                                    hx-get="{% url 'atlas:case_inline_field' case.pk 'description' %}?edit=1&show_label=0"
                                    hx-target="#case-inline-description"
                                    hx-swap="outerHTML">quick edit</button>
                        {% endif %}
                    </div>
                </div>

                {# Presentation moved to metadata column for tighter layout #}

                <div class="row g-3 mb-3">
                    <div class="col-12">
                        <div class="card h-100">
                            <div class="card-header d-flex justify-content-between align-items-center quick-edit-wrap">
                                <span><span class="section-icon history" aria-hidden="true"></span>History</span>
                                {% if can_edit %}
                                    <button class="btn btn-sm btn-link text-muted p-0 quick-edit-button"
                                            hx-get="{% url 'atlas:case_inline_field' case.pk 'history' %}?edit=1&show_label=0"
                                            hx-target="#case-inline-history"
                                            hx-swap="outerHTML">quick edit</button>
                                {% endif %}
                            </div>
                            <div class="card-body">
                                {% url 'atlas:case_inline_field' case.pk 'history' as history_url %}
                                {% with endpoint_default=history_url|add:"?show_label=0" endpoint_edit=history_url|add:"?edit=1&show_label=0" %}
                                    {% include 'atlas/partials/case_inline_field.html' with show_label=0 editing=False field_label='History' can_edit=can_edit endpoint_url_default=endpoint_default endpoint_url_edit=endpoint_edit container_id='case-inline-history' field_kind='textarea' value=case.history display_value=case.history field_name='history' error_message='' %}
                                {% endwith %}
                            </div>
                        </div>
                    </div>
                    <div class="col-12">
                        <div class="card h-100">
                            <div class="card-header d-flex justify-content-between align-items-center quick-edit-wrap">
                                <span><span class="section-icon discussion" aria-hidden="true"></span>Discussion</span>
                                {% if can_edit %}
                                    <button class="btn btn-sm btn-link text-muted p-0 quick-edit-button"
                                            hx-get="{% url 'atlas:case_inline_field' case.pk 'discussion' %}?edit=1&show_label=0"
                                            hx-target="#case-inline-discussion"
                                            hx-swap="outerHTML">quick edit</button>
                                {% endif %}
                            </div>
                            <div class="card-body">
                                {% url 'atlas:case_inline_field' case.pk 'discussion' as discussion_url %}
                                {% with endpoint_default=discussion_url|add:"?show_label=0" endpoint_edit=discussion_url|add:"?edit=1&show_label=0" %}
                                    {% include 'atlas/partials/case_inline_field.html' with show_label=0 editing=False field_label='Discussion' can_edit=can_edit endpoint_url_default=endpoint_default endpoint_url_edit=endpoint_edit container_id='case-inline-discussion' field_kind='textarea' value=case.discussion display_value=case.discussion field_name='discussion' error_message='' %}
                                {% endwith %}
                            </div>
                        </div>
                    </div>
                    <div class="col-12">
                        <div class="card h-100">
                            <div class="card-header d-flex justify-content-between align-items-center quick-edit-wrap">
                                <span><span class="section-icon report" aria-hidden="true"></span>Report</span>
                                {% if can_edit %}
                                    <button class="btn btn-sm btn-link text-muted p-0 quick-edit-button"
                                            hx-get="{% url 'atlas:case_inline_field' case.pk 'report' %}?edit=1&show_label=0"
                                            hx-target="#case-inline-report"
                                            hx-swap="outerHTML">quick edit</button>
                                {% endif %}
                            </div>
                            <div class="card-body">
                                {% url 'atlas:case_inline_field' case.pk 'report' as report_url %}
                                {% with endpoint_default=report_url|add:"?show_label=0" endpoint_edit=report_url|add:"?edit=1&show_label=0" %}
                                    {% include 'atlas/partials/case_inline_field.html' with show_label=0 editing=False field_label='Report' can_edit=can_edit endpoint_url_default=endpoint_default endpoint_url_edit=endpoint_edit container_id='case-inline-report' field_kind='textarea' value=case.report display_value=case.report field_name='report' error_message='' %}
                                {% endwith %}
                            </div>
                        </div>
                    </div>
                </div>
            </div>

            <aside class="col-12 col-md-4 case-metadata">
                {# ID/date shown above; removed duplicate here #}

                <div class="case-meta-item">
                    <span class="case-meta-label">Presentation</span>
                    <div class="case-meta-value d-flex align-items-center justify-content-end">
                        <div id="case-inline-presentation">
                            {% if case.presentation.all %}
                                {% for presentation in case.presentation.all %}
                                    <span class="badge bg-secondary ms-1">{{ presentation.get_link|safe }}</span>
                                {% endfor %}
                            {% else %}
                                <span class="text-muted">None</span>
                            {% endif %}
                        </div>
                        {% if can_edit %}
                            <button class="btn btn-sm btn-link text-muted p-0 quick-edit-button ms-2"
                                    hx-get="{% url 'atlas:case_inline_field' case.pk 'presentation' %}?edit=1&show_label=0"
                                    hx-target="#case-inline-presentation"
                                    hx-swap="outerHTML">quick edit</button>
                        {% endif %}
                    </div>
                </div>
                <div class="case-meta-item">
                    <span class="case-meta-label">Subspecialty</span>
                    <div class="case-meta-value d-flex align-items-center justify-content-end">
                        <div id="case-inline-subspecialty">
                            {% if case.subspecialty.all %}
                                {% for sub in case.subspecialty.all %}
                                    <span class="badge bg-secondary ms-1">{{ sub.get_link|safe }}</span>
                                {% endfor %}
                            {% else %}
                                <span class="badge bg-secondary ms-1 text-muted">None</span>
                            {% endif %}
                        </div>
                        {% if can_edit %}
                            <button class="btn btn-sm btn-link text-muted p-0 quick-edit-button ms-2"
                                    hx-get="{% url 'atlas:case_inline_field' case.pk 'subspecialty' %}?edit=1&show_label=0"
                                    hx-target="#case-inline-subspecialty"
                                    hx-swap="outerHTML">quick edit</button>
                        {% endif %}
                    </div>
                </div>

                <div class="case-meta-item">
                    <span class="case-meta-label">Pathological process</span>
                    <div class="case-meta-value d-flex align-items-center justify-content-end">
                        <div>
                            {% if case.pathological_process.all %}
                                {% for p in case.pathological_process.all %}
                                    <span class="badge bg-secondary ms-1">{{ p.get_link|safe }}</span>
                                {% endfor %}
                            {% else %}
                                <span class="badge bg-secondary ms-1 text-muted">None</span>
                            {% endif %}
                        </div>
                    </div>
                </div>

                <div class="case-meta-item">
                    <span class="case-meta-label">Diagnostic certainty</span>
                    <div class="case-meta-value d-flex align-items-center justify-content-end">
                        {% url 'atlas:case_inline_field' case.pk 'diagnostic_certainty' as diag_url %}
                        {% with endpoint_default=diag_url|add:"?show_label=0" endpoint_edit=diag_url|add:"?edit=1&show_label=0" %}
                            {% include 'atlas/partials/case_inline_field.html' with show_label=0 editing=False field_label="Diagnostic certainty" can_edit=can_edit endpoint_url_default=endpoint_default endpoint_url_edit=endpoint_edit container_id='case-inline-diagnostic_certainty' field_kind='select' value=case.get_diagnostic_certainty_display display_value=case.get_diagnostic_certainty_display field_name='diagnostic_certainty' error_message='' %}
                        {% endwith %}
                        {% if can_edit %}
                            <button class="btn btn-sm btn-link text-muted p-0 quick-edit-button ms-2"
                                    hx-get="{% url 'atlas:case_inline_field' case.pk 'diagnostic_certainty' %}?edit=1&show_label=0"
                                    hx-target="#case-inline-diagnostic_certainty"
                                    hx-swap="outerHTML">quick edit</button>
                        {% endif %}
                    </div>
                </div>
            </aside>
        </div>

    </div>
    <section class="case-detail-section card mb-3">
        <div class="card-header d-flex justify-content-between align-items-center flex-wrap gap-2">
            <h5 class="mb-0">Resources</h5>
            {% if can_edit %}
                <div id="resource-search-panel-placeholder" class="d-inline-flex">
                    <button class="btn btn-sm btn-outline-primary"
                            hx-get="{% url 'atlas:resource_search_panel' %}?case_id={{ case.pk }}"
                            hx-target="#resource-search-panel-placeholder"
                            hx-swap="innerHTML">
                        Add Resource
                    </button>
                </div>
            {% endif %}
        </div>
        <div class="card-body">
            {% include 'atlas/partials/case_resources_list.html' with case=case %}
        </div>
    </section>

    {% comment %} <p><b>Scrapped:</b> {{ case.scrapped }} <a
            href="{% url 'atlas:case_scrap' pk=case.pk %}">(toggle)</a> {% endcomment %}

    <section class="case-detail-section card mb-3 atlas-answer">
        <div class="card-header">
            <h5 class="mb-0">Clinical Summary</h5>
        </div>
        <div class="card-body pre-whitespace">
            <div class="mb-3">
                <strong>Condition:</strong>
                <ul class="mb-2">
                    {% for con in case.condition.all %}
                        <li>{{con.get_link}}</li>
                    {% empty %}
                        <li class="text-muted">None</li>
                    {% endfor %}
                </ul>
            </div>
            <div class="mb-3">
                <strong>Procedure(s):</strong>
                {% if case.procedures.all %}
                    <ul class="mb-2">
                        {% for proc in case.procedures.all %}
                            <li>{{ proc.get_link }}</li>
                        {% endfor %}
                    </ul>
                {% else %}
                    <span class="text-muted">None</span>
                {% endif %}
            </div>
            <div class="mb-3">
                {% include 'atlas/partials/_series_findings.html' %}
                {% include 'atlas/partials/_case_displaysets.html' %}
            </div>
            {% include 'atlas/partials/_case_differentials.html' %}
        </div>
    </section>

    <section class="case-detail-section card mb-3">
        <div class="card-header d-flex justify-content-between align-items-center flex-wrap gap-2">
            <h5 class="mb-0">Collections</h5>
            {% if can_edit %}
                <button class="btn btn-sm btn-primary"
                        hx-get="{% url 'atlas:case_collection_form' case.pk %}"
                        hx-target="#collection-form">
                    Add to collection
                </button>
            {% endif %}
        </div>
        <div class="card-body">
            <div id="collection-form" class="mb-2"></div>
            <ul id="case-{{ case.pk }}-collections" class="list-group list-group-flush">
                {% for collection in case.casecollection_set.all %}
                    <li id="collection-{{ collection.pk }}" class="list-group-item d-flex justify-content-between align-items-center flex-wrap gap-2">
                        <a href="{% url 'atlas:collection_detail' pk=collection.pk %}">{{ collection.name }}</a>
                        {% if can_edit %}
                            <button
                                class="btn btn-sm btn-outline-danger remove-button"
                                hx-post="{% url 'atlas:remove_case_from_collection' case.pk collection.pk %}"
                                hx-target="#collection-{{ collection.pk }}"
                                hx-swap="outerHTML"
                                hx-confirm="Are you sure you want to remove this case from the collection?">
                                Remove
                            </button>
                        {% endif %}
                    </li>
                {% empty %}
                    <li class="list-group-item text-muted">No collections linked.</li>
                {% endfor %}
            </ul>
        </div>
    </section>


    {% if casedetail %}
        {% include 'atlas/partials/collection_question_block.html' with can_edit=can_edit %}

    {% endif %}

    <section class="case-detail-section card mb-3">
        <div class="card-header">
            <h5 class="mb-0">Linked Cases</h5>
        </div>
        <div class="card-body">
            <p class="mb-2"><strong>Previous case:</strong> {{ case.previous_case.get_link }}</p>
            <p class="mb-0"><strong>Next case:</strong>
                {% if case.next_case %}
                    {{ case.next_case.get_link }}
                {% else %}
                    <a href="{% url 'atlas:case_clone_next' case.pk %}">Clone and add next case</a>
                {% endif %}
            </p>
        </div>
    </section>

    <section class="case-detail-section card mb-3">
        <div class="card-header">
            <h5 class="mb-0">Notes</h5>
        </div>
        <div class="card-body">
            {% include 'question_notes.html' %}
        </div>
    </section>

    <section class="case-detail-section card mb-3">
        <div class="card-header">
            <h5 class="mb-0">Case Metadata</h5>
        </div>
        <div class="card-body">
            <p class="mb-2"><strong>Checked by:</strong> {% for verified in case.verified.all %} <a
                href="{% url 'atlas:verified_detail' pk=verified.pk %}">{{verified}}</a>{% if not forloop.last %}, {% endif %}{% empty %}<span class="text-muted">None</span>{% endfor %}</p>

            <p class="mb-2"><strong>Author(s):</strong> {% for author in case.author.all %} <a
                href="{% url 'atlas:author_detail' pk=author.pk %}">{{author}}</a>{% if not forloop.last %}, {% endif %}{% empty %}<span class="text-muted">None</span>{% endfor %}</p>

            <p class="mb-0"><strong>Case size:</strong> {{ case.get_total_series_images_size | filesizeformat }}</p>
        </div>
    </section>

    {% include 'atlas/partials/_finding_modal.html' %}
<!-- Reorder Series Modal -->
    <div class="modal fade" id="reorderSeriesModal" tabindex="-1" aria-labelledby="reorderSeriesModalLabel" aria-hidden="true">
        <div class="modal-dialog">
            <form method="post" action="{% url 'atlas:reorder_series' case.pk %}" id="reorder-series-form">
                {% csrf_token %}
                <div class="modal-content">
                    <div class="modal-header">
                        <h5 class="modal-title" id="reorderSeriesModalLabel">Reorder Series</h5>
                        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                    </div>
                    <div class="modal-body">
                        <ul id="series-reorder-list" class="list-group">
                            {% for series in ordered_series %}
                                <li class="list-group-item d-flex justify-content-between align-items-center" data-series-id="{{ series.pk }}">
                                    <span>
                                        <span class="series-block-series-number">Series {{ forloop.counter }}:</span>
                                        {{ series.get_block|default:series }}
                                    </span>
                                    <span>
                                        <button type="button" class="btn btn-sm btn-outline-secondary move-up">↑</button>
                                        <button type="button" class="btn btn-sm btn-outline-secondary move-down">↓</button>
                                    </span>
                                    <input type="hidden" name="series_order" value="{{ series.pk }}">
                                </li>
                            {% endfor %}
                        </ul>
                    </div>
                    <div class="modal-footer">
                        <button type="submit" class="btn btn-primary">Save order</button>
                    </div>
                </div>
            </form>
        </div>
    </div>

    <div class="modal fade" id="seriesActionsModal" tabindex="-1" aria-labelledby="seriesActionsModalLabel" aria-hidden="true">
        <div class="modal-dialog modal-dialog-centered">
            <div class="modal-content">
                <div class="modal-header">
                    <div>
                        <h5 class="modal-title" id="seriesActionsModalLabel">Series actions</h5>
                        <div class="small text-muted" id="seriesActionsModalSubheading"></div>
                    </div>
                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                </div>
                <div class="modal-body d-flex flex-column gap-2">
                    <button type="button" class="btn btn-outline-info" id="series-modal-open-primary-btn">
                        <i class="bi bi-eye"></i> View in viewer
                    </button>
                    <button type="button" class="btn btn-outline-info" id="series-modal-open-new-viewport-btn">
                        <i class="bi bi-layout-split"></i> View in new pane
                    </button>
                    <a href="#" class="btn btn-outline-secondary" id="series-modal-page-link">
                        <i class="bi bi-box-arrow-up-right"></i> Open series page
                    </a>
                    <button type="button" class="btn btn-outline-secondary" id="series-modal-popup-btn">
                        <i class="bi bi-window"></i> Open popup window
                    </button>
                    <button type="button" class="btn btn-outline-primary" id="series-modal-select-btn" style="display:none;">
                        Select for manage series
                    </button>
                </div>
            </div>
        </div>
    </div>

    <script>
    // From series_viewer.html
        function loadAnnotationAndViewportOnElement(annotation, viewport, dicom_element, current_image_id_index) {
            cornerstoneTools.globalImageIdSpecificToolStateManager.clear(dicom_element);
            cornerstone.getEnabledElement(dicom_element).viewport = viewport
            cornerstoneTools.globalImageIdSpecificToolStateManager.restoreToolState(
                annotation);
            console.log("annotation", annotation)
            console.log("viewport", viewport)

        //cornerstone.getEnabledElement(dicom_element).toolStateManager.restoreToolState(annotationjson)
            cornerstone.resize(dicom_element);
            console.log("current_image_id_index", current_image_id_index)
        //current_image_id_index = parseInt(current_image_id_index);

            console.log(current_image_id_index, Number.isInteger(current_image_id_index))
            if (Number.isInteger(current_image_id_index)) {
                console.log("loading stack index")
                dicomViewer.loadStackIndex(current_image_id_index, dicom_element);
            } else {
                try {
                    console.log("current_image_id_index", current_image_id_index)
                    dicomViewer.loadImageById(current_image_id_index, dicom_element);
                } catch (e) {
                    console.log(e)
                    console.log("loading image by id failed")
                    console.log("loading next annotation image")
                    dicomViewer.getNextAnnotationImage(dicom_element);
                }
            }

        }

        document.addEventListener("DOMContentLoaded", function () {
            // Initialize tooltips
            function initAlertTooltips() {
                document.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(function(el) {
                    try { new bootstrap.Tooltip(el); } catch (e) {}
                });
            }
            initAlertTooltips();
            document.body.addEventListener('htmx:afterSwap', function() {
                initAlertTooltips();
            });

            const dicomDetails = document.getElementById("dicom-viewer-details");
            let dicomViewerLoaded = false;
            dicomDetails.addEventListener("toggle", function() {
                if (!dicomViewerLoaded && dicomDetails.open) {
                // Use safe mount helper to avoid arbitrary timeouts
                    try { mountDicomViewersSafely(); } catch (e) { if (window.mountDicomViewers) try { window.mountDicomViewers(); } catch (er) { console.warn(er); } }
                    dicomViewerLoaded = true;
                }
            });


            // Move up/down logic
            document.querySelectorAll("#series-reorder-list .move-up, #series-reorder-list .move-down").forEach(function(btn) {
                btn.addEventListener("click", function(e) {
                    e.preventDefault();
                    const li = btn.closest("li");
                    if (btn.classList.contains("move-up") && li.previousElementSibling) {
                        li.parentNode.insertBefore(li, li.previousElementSibling);
                    }
                    if (btn.classList.contains("move-down") && li.nextElementSibling) {
                        li.parentNode.insertBefore(li.nextElementSibling, li);
                    }
                });
            });

    // On submit, update the hidden inputs to match the new order
            const reorderSeriesForm = document.getElementById("reorder-series-form");
            if (reorderSeriesForm) {
                reorderSeriesForm.addEventListener("submit", function(e) {
                    const lis = document.querySelectorAll("#series-reorder-list li");
                    lis.forEach((li, idx) => {
                        li.querySelector("input[name='series_order']").setAttribute("name", "series_order_" + idx);
                    });
                });
            }

// Drag and drop reordering for series list
            const reorderList = document.getElementById("series-reorder-list");
            let draggedItem = null;

            if (reorderList) {
                reorderList.querySelectorAll("li").forEach(function(li) {
                    li.setAttribute("draggable", "true");

                    li.addEventListener("dragstart", function(e) {
                        draggedItem = li;
                        li.classList.add("dragging");
                        e.dataTransfer.effectAllowed = "move";
                    });

                    li.addEventListener("dragend", function() {
                        draggedItem = null;
                        li.classList.remove("dragging");
                    });

                    li.addEventListener("dragover", function(e) {
                        e.preventDefault();
                        e.dataTransfer.dropEffect = "move";
            // Visual feedback
                        li.classList.add("drag-over");
                    });

                    li.addEventListener("dragleave", function() {
                        li.classList.remove("drag-over");
                    });

                    li.addEventListener("drop", function(e) {
                        e.preventDefault();
                        li.classList.remove("drag-over");
                        if (draggedItem && draggedItem !== li) {
                // Insert before or after depending on mouse position
                            const bounding = li.getBoundingClientRect();
                            const offset = e.clientY - bounding.top;
                            if (offset < bounding.height / 2) {
                                li.parentNode.insertBefore(draggedItem, li);
                            } else {
                                li.parentNode.insertBefore(draggedItem, li.nextSibling);
                            }
                        }
                    });
                });
            }


            const detailsElement = document.getElementById("series-actions");
            const buttons = document.querySelectorAll(".select-series-btn");
            const seriesCheckboxes = document.querySelectorAll("input[type='checkbox'][name='series-ids']");
            const selectAllBtn = document.getElementById("series-select-all-btn");
            const deselectAllBtn = document.getElementById("series-deselect-all-btn");
            const seriesManageToggleBtn = document.getElementById("series-manage-toggle-btn");
            const seriesManageCloseBtn = document.getElementById("series-manage-close-btn");
            const seriesActionsPanel = document.getElementById("series-actions-panel");
            const seriesActionsModalEl = document.getElementById("seriesActionsModal");
            const seriesActionsModal = seriesActionsModalEl ? new bootstrap.Modal(seriesActionsModalEl) : null;
            const seriesModalSubheading = document.getElementById("seriesActionsModalSubheading");
            const seriesModalOpenPrimaryBtn = document.getElementById("series-modal-open-primary-btn");
            const seriesModalOpenNewViewportBtn = document.getElementById("series-modal-open-new-viewport-btn");
            const seriesModalPageLink = document.getElementById("series-modal-page-link");
            const seriesModalPopupBtn = document.getElementById("series-modal-popup-btn");
            const seriesModalSelectBtn = document.getElementById("series-modal-select-btn");
            let activeSeriesCard = null;

            function isSeriesActionsPanelOpen() {
                return !!(seriesActionsPanel && seriesActionsPanel.classList.contains("is-open"));
            }

            function setSeriesActionsPanelOpen(isOpen) {
                if (!seriesActionsPanel) {
                    return;
                }
                seriesActionsPanel.classList.toggle("is-open", isOpen);
                seriesActionsPanel.setAttribute("aria-hidden", isOpen ? "false" : "true");
                if (seriesManageToggleBtn) {
                    seriesManageToggleBtn.setAttribute("aria-expanded", isOpen ? "true" : "false");
                    seriesManageToggleBtn.classList.toggle("btn-secondary", isOpen);
                    seriesManageToggleBtn.classList.toggle("btn-outline-secondary", !isOpen);
                }
                document.body.classList.toggle("series-actions-panel-open", isOpen);
            }

            function toggleCheckboxes() {
                const isOpen = isSeriesActionsPanelOpen();
                buttons.forEach((button) => {
                    button.style.display = isOpen ? "inline-block" : "none";
                });
                if (seriesModalSelectBtn) {
                    seriesModalSelectBtn.style.display = isOpen ? "inline-block" : "none";
                }
            }

            if (seriesManageToggleBtn) {
                seriesManageToggleBtn.addEventListener("click", function(evt) {
                    evt.preventDefault();
                    evt.stopPropagation();
                    setSeriesActionsPanelOpen(!isSeriesActionsPanelOpen());
                    toggleCheckboxes();
                });
            }

            if (seriesManageCloseBtn) {
                seriesManageCloseBtn.addEventListener("click", function() {
                    setSeriesActionsPanelOpen(false);
                    toggleCheckboxes();
                });
            }

            document.getElementById("series-import-uploads-btn")?.addEventListener("click", function(evt) {
                evt.stopPropagation();
            });

            function toggleSeriesSelection(card) {
                if (!card) {
                    return;
                }
                const checkbox = card.querySelector("input[type='checkbox'][name='series-ids']");
                if (!checkbox) {
                    return;
                }
                checkbox.checked = !checkbox.checked;
                syncSeriesSelectionUi();
            }

            function openSeriesActionsModal(card) {
                if (!card || !seriesActionsModal) {
                    return;
                }

                activeSeriesCard = card;

                const seriesId = card.dataset.seriesId;
                const seriesLabel = card.dataset.seriesLabel || "Series";
                const seriesName = card.dataset.seriesName || seriesLabel;
                const detailUrl = card.dataset.seriesDetailUrl;
                const popupUrl = card.dataset.seriesPopupUrl;

                if (seriesModalSubheading) {
                    seriesModalSubheading.textContent = `${seriesLabel} · ${seriesName}`;
                }
                if (seriesModalPageLink) {
                    seriesModalPageLink.href = detailUrl || "#";
                }
                if (seriesModalPopupBtn) {
                    seriesModalPopupBtn.onclick = function() {
                        return window.create_popup_window(popupUrl, 'Series');
                    };
                }
                if (seriesModalOpenPrimaryBtn) {
                    seriesModalOpenPrimaryBtn.dataset.seriesId = seriesId;
                    seriesModalOpenPrimaryBtn.dataset.seriesName = seriesName;
                }
                if (seriesModalOpenNewViewportBtn) {
                    seriesModalOpenNewViewportBtn.dataset.seriesId = seriesId;
                    seriesModalOpenNewViewportBtn.dataset.seriesName = seriesName;
                }
                if (seriesModalSelectBtn) {
                    const checkbox = card.querySelector("input[type='checkbox'][name='series-ids']");
                    const isSelected = checkbox ? checkbox.checked : false;
                    seriesModalSelectBtn.textContent = isSelected ? "Deselect from manage series" : "Select for manage series";
                }

                seriesActionsModal.show();
            }

            function syncSeriesSelectionUi() {
                document.querySelectorAll(".select-series-btn").forEach(function(btn) {
                    const parent = btn.closest(".series-block");
                    if (!parent) {
                        return;
                    }
                    const checkbox = parent.querySelector("input[type='checkbox'][name='series-ids']");
                    if (!checkbox) {
                        return;
                    }
                    btn.classList.toggle("btn-primary", checkbox.checked);
                    btn.classList.toggle("btn-outline-primary", !checkbox.checked);
                    btn.textContent = checkbox.checked ? "Selected" : "Select";
                    if (checkbox.checked) {
                        parent.classList.add("highlight-series");
                    } else {
                        parent.classList.remove("highlight-series");
                    }
                });

                const selectedCount = Array.from(seriesCheckboxes).filter((checkbox) => checkbox.checked).length;
                if (selectAllBtn) {
                    selectAllBtn.disabled = selectedCount === seriesCheckboxes.length && seriesCheckboxes.length > 0;
                }
                if (deselectAllBtn) {
                    deselectAllBtn.disabled = selectedCount === 0;
                }
            }

            document.querySelectorAll(".select-series-btn").forEach(function(btn) {
                btn.addEventListener("click", function(event) {
                    event.preventDefault();
                    event.stopPropagation();
                    const parent = btn.closest(".series-block");
                    toggleSeriesSelection(parent);
                });
            });

            document.querySelectorAll("[data-series-action='details']").forEach(function(btn) {
                btn.addEventListener("click", function() {
                    openSeriesActionsModal(btn.closest(".series-block"));
                });
            });

            if (seriesModalSelectBtn) {
                seriesModalSelectBtn.addEventListener("click", function() {
                    toggleSeriesSelection(activeSeriesCard);
                    const checkbox = activeSeriesCard ? activeSeriesCard.querySelector("input[type='checkbox'][name='series-ids']") : null;
                    seriesModalSelectBtn.textContent = checkbox && checkbox.checked ? "Deselect from manage series" : "Select for manage series";
                });
            }

            if (seriesModalOpenPrimaryBtn) {
                seriesModalOpenPrimaryBtn.addEventListener("click", function() {
                    const matchingButton = document.querySelector(`.series-open-primary-btn[data-series-id='${this.dataset.seriesId}']`);
                    if (matchingButton) {
                        matchingButton.click();
                        if (seriesActionsModal) {
                            seriesActionsModal.hide();
                        }
                    }
                });
            }

            if (seriesModalOpenNewViewportBtn) {
                seriesModalOpenNewViewportBtn.addEventListener("click", function() {
                    const matchingButton = document.querySelector(`.series-open-new-viewport-btn[data-series-id='${this.dataset.seriesId}']`);
                    if (matchingButton) {
                        matchingButton.click();
                        if (seriesActionsModal) {
                            seriesActionsModal.hide();
                        }
                    }
                });
            }

            seriesCheckboxes.forEach((checkbox) => {
                checkbox.addEventListener("change", syncSeriesSelectionUi);
            });

            if (selectAllBtn) {
                selectAllBtn.addEventListener("click", function() {
                    seriesCheckboxes.forEach((checkbox) => {
                        checkbox.checked = true;
                    });
                    syncSeriesSelectionUi();
                });
            }

            if (deselectAllBtn) {
                deselectAllBtn.addEventListener("click", function() {
                    seriesCheckboxes.forEach((checkbox) => {
                        checkbox.checked = false;
                    });
                    syncSeriesSelectionUi();
                });
            }

        // Initial state
            toggleCheckboxes();
            syncSeriesSelectionUi();


    // Show the alert when a result is received
            const resultsSpan = document.getElementById("series-action-results");
            const alertDiv = document.getElementById("series-action-alert");
            const deleteSelectedSeriesBtn = document.getElementById("series-delete-selected-btn");
            const observer = new MutationObserver(function(mutations) {
                if (resultsSpan.textContent.trim() !== "") {
                    alertDiv.style.display = "block";
                } else {
                    alertDiv.style.display = "none";
                }
            });
            observer.observe(resultsSpan, { childList: true, subtree: true });

            if (deleteSelectedSeriesBtn) {
                deleteSelectedSeriesBtn.addEventListener("htmx:beforeRequest", function() {
                    deleteSelectedSeriesBtn.disabled = true;
                    alertDiv.classList.remove("alert-success", "alert-danger");
                    alertDiv.classList.add("alert-info");
                    resultsSpan.textContent = "Deleting selected series...";
                    alertDiv.style.display = "block";
                });

                deleteSelectedSeriesBtn.addEventListener("htmx:afterRequest", function(evt) {
                    deleteSelectedSeriesBtn.disabled = false;
                    const status = evt.detail && evt.detail.xhr ? evt.detail.xhr.status : 0;
                    alertDiv.classList.remove("alert-info", "alert-success", "alert-danger");
                    if (status >= 200 && status < 300) {
                        alertDiv.classList.add("alert-success");
                    } else {
                        alertDiv.classList.add("alert-danger");
                    }
                });
            }

            // Display Set modal handler
            const dsModal = new bootstrap.Modal(document.getElementById("displaysetModal"));
            const dsModalBody = document.getElementById("displaysetModalBody");
            const dsFullscreenModal = new bootstrap.Modal(document.getElementById("displaysetFullscreenModal"));

        // Loader functions: can be called directly on reload
        // Helper: wait for mount function and mount the viewers safely
            function waitForMountFn(timeout = 5000) {
                if (window.mountDicomViewers) return Promise.resolve(window.mountDicomViewers);
                return new Promise((resolve, reject) => {
                    const start = Date.now();
                    function poll() {
                        if (window.mountDicomViewers) return resolve(window.mountDicomViewers);
                        if (Date.now() - start > timeout) return reject(new Error('mountDicomViewers not available'));
                        requestAnimationFrame(poll);
                    }
                    poll();
                });
            }

            async function mountDicomViewersSafely(timeout = 5000) {
                try {
                // wait for layout to stabilise
                    await new Promise(r => requestAnimationFrame(() => requestAnimationFrame(r)));
                    const mountFn = await waitForMountFn(timeout);
                    try { mountFn(); } catch (e) { console.warn('mountDicomViewers failed', e); }
                // allow any async render to settle then force a resize event
                    requestAnimationFrame(() => {
                        try { window.dispatchEvent(new Event('resize')); } catch (e) {}
                        if (typeof window.resizeDicomViewers === 'function') try { window.resizeDicomViewers(); } catch (e) {}
                    });
                } catch (err) {
                    console.warn('Viewer initialization deferred/fallback:', err);
                }
            }

            async function loadDisplaysetModal(url, dsId) {
                if (!url && dsId) url = `/atlas/${dsId}/display_sets/modal`;
                if (!url) return;
                dsModalBody.innerHTML = "<p>Loading...</p>";
                try {
                    const resp = await fetch(url);
                    const html = await resp.text();
                    dsModalBody.innerHTML = html;
                    try {
                        const fsBtn = document.querySelector('.displayset-fullscreen-btn');
                        if (fsBtn) {
                            fsBtn.dataset.url = url;
                            if (dsId) fsBtn.dataset.dsId = dsId;
                        }
                    } catch (e) { console.warn(e); }
                    try { setUrlParam('displayset', dsId); } catch (e) {}
                // Initialize viewer deterministically after injecting HTML
                    mountDicomViewersSafely();
                    dsModal.show();
                } catch (error) {
                    console.error('Error loading display set details:', error);
                    dsModalBody.innerHTML = "<p>Failed to load display set.</p>";
                }
            }

            async function loadDisplaysetFullscreen(url, dsId) {
                if (!url && dsId) url = `/atlas/${dsId}/display_sets/modal`;
                if (!url) return;
                document.getElementById('displaysetFullscreenLeft').innerHTML = '<p style="color:#fff; padding:1rem;">Loading viewer...</p>';
                document.getElementById('displaysetFullscreenRight').innerHTML = '<p>Loading details...</p>';
                try {
                    const resp = await fetch(url);
                    const html = await resp.text();
                    const tmp = document.createElement('div');
                    tmp.innerHTML = html;
                    const viewer = tmp.querySelector('.dicom-viewer-root');
                    if (viewer) {
                        const left = document.getElementById('displaysetFullscreenLeft');
                        left.innerHTML = '';
                        left.appendChild(viewer);
                        try { viewer.style.height='100%'; viewer.style.minHeight='100%'; viewer.style.width='100%'; viewer.style.display='block'; viewer.style.flex='1 1 auto'; } catch (e){}
                    } else {
                        document.getElementById('displaysetFullscreenLeft').innerHTML = '<p style="color:#fff; padding:1rem;">No viewer available</p>';
                    }
                    const viewerInTmp = tmp.querySelector('.dicom-viewer-root');
                    if (viewerInTmp) viewerInTmp.remove();
                    document.getElementById('displaysetFullscreenRight').innerHTML = tmp.innerHTML;
                    try { if (dsId) { setUrlParam('displayset', dsId); setUrlParam('displayset_full', '1'); } } catch (e) {}
                    dsFullscreenModal.show();
                // Ensure viewer is mounted and resized after moving into fullscreen
                    mountDicomViewersSafely();
                } catch (error) {
                    console.error('Error loading fullscreen display set:', error);
                    document.getElementById('displaysetFullscreenLeft').innerHTML = '<p style="color:#fff; padding:1rem;">Failed to load viewer</p>';
                    document.getElementById('displaysetFullscreenRight').innerHTML = '<p>Failed to load details.</p>';
                }
            }

            async function loadFindingModal(findingId, url) {
                if (!url && findingId) url = `/atlas/series_finding/${findingId}/details/`;
                if (!url) return;
                const modalBody = document.getElementById('findingModalBody');
                modalBody.innerHTML = '<p>Loading...</p>';
                try {
                    const resp = await fetch(url);
                    const html = await resp.text();
                    modalBody.innerHTML = html;
                // Ensure viewers mount after content injection
                    mountDicomViewersSafely();
                    try { setUrlParam('finding', findingId); } catch (e) {}
                    const modal = new bootstrap.Modal(document.getElementById('findingModal'));
                    modal.show();
                    document.getElementById('reload-finding')?.addEventListener('click', function () { mountDicomViewersSafely(); });
                } catch (e) {
                    console.error('Error loading finding details:', e);
                    modalBody.innerHTML = '<p>Failed to load finding details.</p>';
                }
            }

        // remove displayset param when modal closed
            document.getElementById('displaysetModal').addEventListener('hidden.bs.modal', function () {
                try { removeUrlParam('displayset'); removeUrlParam('displayset_full'); } catch (e) {}
            });

        // remove fullscreen param when fullscreen modal closed
            document.getElementById('displaysetFullscreenModal').addEventListener('hidden.bs.modal', function () {
                try { removeUrlParam('displayset_full'); } catch (e) {}
            });

        // FINDING modal: push/remove param so it can be reopened after reload
            document.querySelectorAll(".view-finding-modal").forEach(button => {
                button.addEventListener("click", function () {
                    const findingId = this.getAttribute("data-finding-id");
                    const url = this.getAttribute('data-url');
                    loadFindingModal(findingId, url);
                });
            });
            document.getElementById('findingModal').addEventListener('hidden.bs.modal', function () {
                try { removeUrlParam('finding'); } catch (e) {}
            });

        // Helper: set/remove URL search params without reloading
            function setUrlParam(key, value) {
                if (!key) return;
                const url = new URL(window.location.href);
                if (value === null || value === undefined) {
                    url.searchParams.delete(key);
                } else {
                    url.searchParams.set(key, value);
                }
                window.history.replaceState({}, '', url.toString());
            }

            function removeUrlParam(key) {
                const url = new URL(window.location.href);
                url.searchParams.delete(key);
                window.history.replaceState({}, '', url.toString());
            }

        // On load: reopen modals if URL params present — call loader functions directly
            (function reopenModalsFromUrl() {
                const params = new URL(window.location.href).searchParams;
                const dsId = params.get('displayset');
                const dsFull = params.get('displayset_full');
                const findingId = params.get('finding');
                if (dsId) {
                // prefer to use existing button url if present, otherwise construct endpoint
                    const btn = document.querySelector(`.view-displayset-modal[data-ds-id="${dsId}"]`);
                    const url = btn ? btn.dataset.url : null;
                    if (dsFull) {
                        loadDisplaysetFullscreen(url, dsId);
                    } else {
                        loadDisplaysetModal(url, dsId);
                    }
                } else if (findingId) {
                // open finding modal
                    const fbtn = document.querySelector(`.view-finding-modal[data-finding-id="${findingId}"]`);
                    const url = fbtn ? fbtn.getAttribute('data-url') : null;
                    loadFindingModal(findingId, url);
                }
            })();

        // Series viewer button handlers: open series in primary viewport or new viewport.
            (function initSeriesViewerButtons() {
                if (window.__seriesViewerButtonsBound) return;
                window.__seriesViewerButtonsBound = true;

                function getViewerApi(baseName, fallbackName) {
                    const fn = window[`${baseName}_main_viewer`] || (fallbackName ? window[fallbackName] : null);
                    return typeof fn === 'function' ? fn : null;
                }

                function ensureViewerOpen() {
                    const viewerDetails = document.getElementById('dicom-viewer-details');
                    if (viewerDetails && !viewerDetails.hasAttribute('open')) {
                        viewerDetails.setAttribute('open', 'open');
                        viewerDetails.dispatchEvent(new Event('toggle', { bubbles: true }));
                    }
                }

                function flattenNamedStacks(raw) {
                    const out = [];
                    if (!Array.isArray(raw)) {
                        return out;
                    }

                    raw.forEach((item) => {
                        if (item && typeof item === 'object' && Array.isArray(item.stacks)) {
                            const caseId = item.caseId;
                            const studyId = item.studyId;
                            item.stacks.forEach((stack) => {
                                if (stack && Array.isArray(stack.imageIds)) {
                                    out.push({
                                        imageIds: stack.imageIds,
                                        name: stack.name || '',
                                        caseId: stack.caseId || caseId,
                                        studyId: stack.studyId || studyId,
                                        seriesId: stack.seriesId || null,
                                        series: Array.isArray(stack.series) ? stack.series : null,
                                    });
                                }
                            });
                        } else if (item && typeof item === 'object' && Array.isArray(item.imageIds)) {
                            out.push({
                                imageIds: item.imageIds,
                                name: item.name || '',
                                caseId: item.caseId || null,
                                studyId: item.studyId || null,
                                seriesId: item.seriesId || null,
                                series: Array.isArray(item.series) ? item.series : null,
                            });
                        }
                    });

                    return out;
                }

                function getNamedStacksFromMainViewer() {
                    const mainViewer = document.getElementById('main_viewer');
                    if (!mainViewer) {
                        return [];
                    }

                    const raw = mainViewer.getAttribute('data-named-stacks') || '[]';
                    try {
                        return flattenNamedStacks(JSON.parse(raw));
                    } catch (e) {
                        console.warn('Failed to parse data-named-stacks', e);
                        return [];
                    }
                }

                function findStackBySeries(stacks, seriesId, seriesName) {
                    const idNum = Number(seriesId);
                    let match = stacks.find((stack) => Number(stack.seriesId) === idNum);
                    if (!match && seriesName) {
                        match = stacks.find((stack) => String(stack.name || '').trim() === String(seriesName).trim());
                    }
                    return match || null;
                }

                async function openSeriesInPrimary(seriesId, seriesName) {
                    ensureViewerOpen();
                    const mainViewer = document.getElementById('main_viewer');
                    if (!mainViewer) {
                        return;
                    }

                    const stacks = getNamedStacksFromMainViewer();
                    const target = findStackBySeries(stacks, seriesId, seriesName);
                    if (!target) {
                        alert('Series stack not found in this case viewer.');
                        return;
                    }

                    const reordered = [target, ...stacks.filter((s) => s !== target)];
                    mainViewer.setAttribute('data-named-stacks', JSON.stringify(reordered));
                    try {
                        await mountDicomViewersSafely();
                    } catch (e) {
                        console.warn('Failed to remount viewer', e);
                    }
                }

                async function openSeriesInNewViewport(seriesId, seriesName) {
                    ensureViewerOpen();
                    const stacks = getNamedStacksFromMainViewer();
                    const target = findStackBySeries(stacks, seriesId, seriesName);
                    if (!target) {
                        alert('Series stack not found in this case viewer.');
                        return;
                    }

                    const exportStateFn = getViewerApi('exportViewerState');
                    const importStateFn = getViewerApi('importViewerState');

                    if (!exportStateFn || !importStateFn) {
                    // Fallback: at least add stack to viewer list and auto-fill an empty viewport if available.
                        const loadAdditionalStackFn = getViewerApi('loadAdditionalStack');
                        if (loadAdditionalStackFn) {
                            await loadAdditionalStackFn(target.imageIds, target.studyId, target.series || undefined);
                        }
                        return;
                    }

                    let state = {};
                    try {
                        state = JSON.parse(exportStateFn() || '{}');
                    } catch (e) {
                        state = {};
                    }

                    const currentStacks = Array.isArray(state.stacks) ? [...state.stacks] : [];
                    const toNorm = (ids) => (Array.isArray(ids) ? ids.map((id) => String(id).replace(/^wadouri:/, '')) : []);
                    const targetNorm = toNorm(target.imageIds);

                    let targetIdx = currentStacks.findIndex((stack) => {
                        const ids = Array.isArray(stack?.i) ? stack.i : [];
                        const norm = toNorm(ids);
                        return norm.length === targetNorm.length && norm.every((id, i) => id === targetNorm[i]);
                    });

                    if (targetIdx < 0) {
                        currentStacks.push({ i: target.imageIds, u: target.studyId || undefined });
                        targetIdx = currentStacks.length - 1;
                    }

                    const grid = state.grid && Number.isFinite(state.grid.rows) && Number.isFinite(state.grid.cols)
                        ? { rows: Math.max(1, Number(state.grid.rows)), cols: Math.max(1, Number(state.grid.cols)) }
                        : { rows: 1, cols: 1 };

                    let numActive = Math.max(1, grid.rows * grid.cols);
                    const stackIdx = Array.isArray(state.stackIdx) ? [...state.stackIdx] : [];
                    const modes = Array.isArray(state.modes) ? [...state.modes] : [];
                    while (stackIdx.length < numActive) {
                        stackIdx.push(0);
                    }
                    while (modes.length < numActive) {
                        modes.push('stack');
                    }

                    const viewportStacks = Array.from({ length: numActive }, (_, viewportIndex) => {
                        const referencedStack = currentStacks[stackIdx[viewportIndex]];
                        return Array.isArray(referencedStack?.i) ? referencedStack.i : [];
                    });

                    let targetViewportIndex = viewportStacks.findIndex((imageIds) => !Array.isArray(imageIds) || imageIds.length === 0);

                    if (targetViewportIndex < 0) {
                        targetViewportIndex = viewportStacks.findIndex((imageIds) => {
                            const norm = toNorm(imageIds);
                            return norm.length === targetNorm.length && norm.every((id, index) => id === targetNorm[index]);
                        });
                    }

                    if (targetViewportIndex < 0) {
                        grid.cols += 1;
                        numActive = grid.rows * grid.cols;
                        while (stackIdx.length < numActive) {
                            stackIdx.push(0);
                        }
                        while (modes.length < numActive) {
                            modes.push('stack');
                        }
                        targetViewportIndex = numActive - 1;
                    }

                    stackIdx[targetViewportIndex] = targetIdx;
                    modes[targetViewportIndex] = 'stack';

                    const nextState = {
                        ...state,
                        grid,
                        stacks: currentStacks,
                        stackIdx,
                        modes,
                    };

                    importStateFn(JSON.stringify(nextState));
                }

                document.querySelectorAll('.series-open-primary-btn').forEach((btn) => {
                    btn.addEventListener('click', async function (e) {
                        e.preventDefault();
                        const seriesId = this.getAttribute('data-series-id');
                        const seriesName = this.getAttribute('data-series-name') || '';
                        if (!seriesId) {
                            return;
                        }
                        await openSeriesInPrimary(seriesId, seriesName);
                    });
                });

                document.querySelectorAll('.series-open-new-viewport-btn').forEach((btn) => {
                    btn.addEventListener('click', async function (e) {
                        e.preventDefault();
                        const seriesId = this.getAttribute('data-series-id');
                        const seriesName = this.getAttribute('data-series-name') || '';
                        if (!seriesId) {
                            return;
                        }
                        await openSeriesInNewViewport(seriesId, seriesName);
                    });
                });
            })();

            // ── Series-block drag-and-drop to viewer viewports ──────────────────
            (function initSeriesBlockDrag() {
                if (window.__seriesBlockDragBound) return;
                window.__seriesBlockDragBound = true;

                function getApiKey(viewerEl) {
                    if (!viewerEl) return null;
                    return viewerEl.id ? viewerEl.id.replace(/[^a-zA-Z0-9_]/g, '_') : null;
                }

                function getMainViewer() {
                    return document.getElementById('main_viewer') || document.querySelector('.dicom-viewer-root');
                }

                document.querySelectorAll('.series-block-draggable[data-image-ids]').forEach(function (block) {
                    block.addEventListener('dragstart', function (e) {
                        const rawIds = block.getAttribute('data-image-ids') || '[]';
                        const name = block.getAttribute('data-series-name') || block.getAttribute('data-series-label') || 'Series';
                        try {
                            // Validate it parses
                            JSON.parse(rawIds);
                        } catch (_) {
                            e.preventDefault();
                            return;
                        }
                        e.dataTransfer.setData('text/dv3d-imageids', rawIds);
                        e.dataTransfer.setData('text/dv3d-stack-name', name);
                        e.dataTransfer.effectAllowed = 'copy';
                        block.classList.add('dragging');

                        // Ensure viewer is open so viewports can receive the drop.
                        const viewerDetails = document.getElementById('dicom-viewer-details');
                        if (viewerDetails && !viewerDetails.hasAttribute('open')) {
                            viewerDetails.setAttribute('open', 'open');
                            viewerDetails.dispatchEvent(new Event('toggle', { bubbles: true }));
                        }
                    });
                    block.addEventListener('dragend', function () {
                        block.classList.remove('dragging');
                    });
                });

                // Update View / View-in-new-pane buttons to use the direct external
                // stack API when image IDs are embedded on the series block, falling
                // back to the legacy state-import path when they are not.
                document.querySelectorAll('.series-open-primary-btn').forEach(function (btn) {
                    btn._origClick = btn.onclick;
                    btn.addEventListener('click', async function (e) {
                        e.stopImmediatePropagation();
                        const seriesId = btn.getAttribute('data-series-id');
                        const block = document.querySelector(`.series-block-draggable[data-series-id='${seriesId}']`);
                        const rawIds = block ? block.getAttribute('data-image-ids') : null;
                        if (!rawIds) return; // fall through to legacy handler
                        let imageIds;
                        try { imageIds = JSON.parse(rawIds); } catch (_) { return; }
                        if (!Array.isArray(imageIds) || imageIds.length === 0) return;
                        e.preventDefault();
                        const viewerEl = getMainViewer();
                        const apiKey = getApiKey(viewerEl);
                        const loadFn = apiKey ? window[`loadExternalStack_${apiKey}`] : null;
                        if (loadFn) {
                            const name = btn.getAttribute('data-series-name') || 'Series';
                            // Ensure viewer is visible first
                            const viewerDetails = document.getElementById('dicom-viewer-details');
                            if (viewerDetails && !viewerDetails.hasAttribute('open')) {
                                viewerDetails.setAttribute('open', 'open');
                                viewerDetails.dispatchEvent(new Event('toggle', { bubbles: true }));
                            }
                            try { await loadFn(imageIds, name); } catch (err) { console.error('loadExternalStack failed', err); }
                        }
                    }, true);
                });

                document.querySelectorAll('.series-open-new-viewport-btn').forEach(function (btn) {
                    btn.addEventListener('click', async function (e) {
                        e.stopImmediatePropagation();
                        const seriesId = btn.getAttribute('data-series-id');
                        const block = document.querySelector(`.series-block-draggable[data-series-id='${seriesId}']`);
                        const rawIds = block ? block.getAttribute('data-image-ids') : null;
                        if (!rawIds) return;
                        let imageIds;
                        try { imageIds = JSON.parse(rawIds); } catch (_) { return; }
                        if (!Array.isArray(imageIds) || imageIds.length === 0) return;
                        e.preventDefault();
                        const viewerEl = getMainViewer();
                        const apiKey = getApiKey(viewerEl);
                        const loadFn = apiKey ? window[`loadExternalStackNewViewport_${apiKey}`] : null;
                        if (loadFn) {
                            const name = btn.getAttribute('data-series-name') || 'Series';
                            const viewerDetails = document.getElementById('dicom-viewer-details');
                            if (viewerDetails && !viewerDetails.hasAttribute('open')) {
                                viewerDetails.setAttribute('open', 'open');
                                viewerDetails.dispatchEvent(new Event('toggle', { bubbles: true }));
                            }
                            try { await loadFn(imageIds, name); } catch (err) { console.error('loadExternalStackNewViewport failed', err); }
                        }
                    }, true);
                });
            })();

        });


    </script>

    <style>
    /* Highlight style for the series-block (subtle Bootstrap-like accent) */
        .highlight-series {
            background-color: rgba(13,110,253,0.04);
            border: 1px solid rgba(13,110,253,0.12);
            transition: box-shadow 0.18s ease, transform 0.12s ease;
            box-shadow: 0 4px 12px rgba(13,110,253,0.04);
        }
        #series-reorder-list .dragging {
            opacity: 0.5;
        }
        #series-reorder-list .drag-over {
            border-top: 2px solid #0d6efd;
        }
        .series-panel {
            border: 1px solid rgba(13,110,253,0.2);
            border-radius: 0.75rem;
            background: rgba(255,255,255,0.02);
            padding: 0.5rem 0.75rem;
            margin-top: 1rem;
            margin-bottom: 1rem;
            max-width: 100%;
        }
        .series-panel-summary {
            list-style: none;
            display: flex;
            align-items: center;
            justify-content: space-between;
            gap: 1rem;
            padding: 0.5rem 0;
            cursor: pointer;
        }
        .series-panel-summary::-webkit-details-marker { display: none; }
        .series-panel-title {
            font-size: 0.95rem;
            font-weight: 700;
        }
        .series-panel-summary-actions {
            display: inline-flex;
            align-items: center;
            gap: .5rem;
            flex-wrap: wrap;
            justify-content: flex-end;
        }
        .series-panel-badge {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            min-width: 5.5rem;
            padding: .35rem .75rem;
            border-radius: 999px;
            background: rgba(13,110,253,0.12);
            color: #9ec5fe;
            font-size: .8rem;
            font-weight: 600;
        }
        .series-panel-body {
            display: flex;
            flex-direction: column;
            gap: 0.75rem;
            padding: 0.5rem 0;
        }
        .series-summary-btn {
            white-space: nowrap;
        }
        .series-card-grid {
            display: flex;
            flex-wrap: wrap;
            gap: 0.75rem;
            align-items: flex-start;
        }
        .series-block {
            flex: 0 1 auto;
            min-width: 260px;
            max-width: 320px;
        }
        .series-card-shell {
            display: flex;
            flex-direction: column;
            gap: 0.4rem;
            padding: 0.7rem;
            border: 1px solid rgba(255,255,255,0.1);
            border-radius: 0.6rem;
            background: rgba(15,23,42,0.3);
            height: 100%;
        }
        .series-card-main {
            display: flex;
            align-items: flex-start;
            gap: 0.5rem;
            width: 100%;
            border: 0;
            background: transparent;
            padding: 0;
            text-align: left;
            color: inherit;
            cursor: pointer;
            flex-shrink: 0;
        }
        .series-card-main:hover .series-card-description,
        .series-card-main:focus-visible .series-card-description {
            color: #fff;
        }
        .series-card-main:focus-visible {
            outline: 2px solid rgba(13,110,253,0.6);
            outline-offset: 2px;
        }
        .series-card-thumb-wrap {
            flex-shrink: 0;
            width: 64px;
            min-width: 64px;
            height: 64px;
            line-height: 0;
        }
        .series-card-thumb {
            width: 100%;
            height: 100%;
            object-fit: cover;
            border-radius: 0.4rem;
            border: 1px solid rgba(255,255,255,0.1);
            display: block;
            background: rgba(255,255,255,0.04);
        }
        .series-card-thumb-generated,
        .series-card-thumb-generated span {
            width: 100%;
            height: 100%;
            display: block;
            border-radius: 0.4rem;
            overflow: hidden;
            border: 1px solid rgba(255,255,255,0.1);
            background: rgba(255,255,255,0.04);
        }
        .series-card-thumb-generated img {
            width: 100%;
            height: 100%;
            object-fit: cover;
            display: block;
        }
        .series-card-thumb-placeholder {
            width: 100%;
            height: 100%;
            display: flex;
            align-items: center;
            justify-content: center;
            color: #6c757d;
            font-size: 1rem;
            background: rgba(255,255,255,0.04);
            border: 1px solid rgba(255,255,255,0.1);
            border-radius: 0.4rem;
        }
        .series-card-content {
            flex: 1;
            min-width: 0;
            display: flex;
            flex-direction: column;
            gap: 0.3rem;
        }
        .series-card-heading {
            font-size: 0.85rem;
            font-weight: 600;
            line-height: 1.15;
        }
        .series-card-series-number {
            font-weight: 700;
        }
        .series-card-image-count {
            font-size: 0.75rem;
            color: #adb5bd;
        }
        .series-card-description {
            font-size: 0.8rem;
            line-height: 1.2;
            color: #d4d8dd;
            display: -webkit-box;
            -webkit-line-clamp: 1;
            -webkit-box-orient: vertical;
            overflow: hidden;
        }
        .series-card-inline-actions {
            display: flex;
            flex-wrap: wrap;
            gap: 0.4rem;
            margin-top: 0.2rem;
        }
        .series-card-inline-actions .btn {
            flex: 0 0 auto;
            padding: 0.3rem 0.4rem;
            font-size: 0.75rem;
        }
        .series-block.highlight-series .series-card-shell,
        .series-block:hover .series-card-shell {
            border-color: rgba(13,110,253,0.5);
            background: rgba(13,110,253,0.08);
        }
        .series-actions-panel {
            position: fixed;
            left: 0;
            right: 0;
            bottom: 0;
            z-index: 1050;
            pointer-events: none;
            padding: 0 1rem 1rem;
            transform: translateY(calc(100% + 1rem));
            transition: transform 0.22s ease;
        }
        .series-actions-panel.is-open {
            transform: translateY(0);
            pointer-events: auto;
        }
        .series-actions-panel-inner {
            max-width: 1280px;
            margin: 0 auto;
            border: 1px solid rgba(13,110,253,0.22);
            border-radius: 1rem 1rem 0 0;
            background: rgba(20, 25, 36, 0.98);
            box-shadow: 0 -12px 32px rgba(0,0,0,0.28);
            padding: 1rem;
            max-height: min(62vh, 640px);
            overflow: auto;
        }
        .series-actions-panel-header {
            display: flex;
            justify-content: space-between;
            align-items: flex-start;
            gap: 1rem;
            margin-bottom: .75rem;
        }
        .series-actions {
            min-width: 0;
            display: flex;
            flex-direction: column;
            gap: .5rem;
            border: 1px solid rgba(255,255,255,0.08);
            border-radius: .85rem;
            padding: .85rem;
            background: rgba(255,255,255,0.02);
        }
        .series-actions-body {
            display: flex;
            flex-direction: column;
            gap: .5rem;
        }
        .series-actions-toolbar {
            display: flex;
            flex-wrap: wrap;
            gap: .5rem;
            border-top: 1px solid rgba(0,0,0,0.08);
            border-bottom: 1px solid rgba(0,0,0,0.08);
            padding: .5rem 0;
        }
        .series-actions-grid {
            display: grid;
            gap: .5rem;
            grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
            align-items: stretch;
        }
        .series-actions-toolbar .btn {
            flex: 1 1 220px;
        }
        .series-actions-grid .btn,
        .series-move-panel .btn {
            width: 100%;
        }
        .series-move-panel {
            background: rgba(255,255,255,0.03);
        }
        .series-move-panel .case-details {
            margin-bottom: .5rem;
        }
        .series-actions .btn {
            vertical-align: middle;
            text-align: left;
        }
        #series-delete-indicator {
            display: none;
        }
        #series-delete-indicator.htmx-request {
            display: inline-flex;
            align-items: center;
        }
        .case-detail-section {
            border: 1px solid rgba(255,255,255,0.08);
            background: rgba(255,255,255,0.02);
        }
        .case-detail-section .card-header {
            background: rgba(255,255,255,0.03);
            border-bottom: 1px solid rgba(255,255,255,0.08);
        }
        .case-detail-section .card-body {
            overflow-x: auto;
        }
        .case-detail-section .list-group-item {
            background: transparent;
            border-color: rgba(255,255,255,0.08);
        }
        .case-detail-section table {
            width: 100%;
        }
        @media (max-width: 991.98px) {
            .series-panel-summary {
                align-items: flex-start;
            }
            .series-panel-summary-actions {
                width: 100%;
                justify-content: flex-start;
            }
            .case-detail-section .card-header {
                padding: .65rem .85rem;
            }
            .case-detail-section .card-body {
                padding: .75rem .85rem;
            }
            .series-actions-panel {
                padding-left: .5rem;
                padding-right: .5rem;
                padding-bottom: .5rem;
            }
            .series-actions-toolbar .btn {
                flex-basis: calc(50% - .25rem);
            }
        }
        @media (max-width: 575.98px) {
            .series-block {
                min-width: 100%;
                max-width: 100%;
            }
            .series-card-thumb-wrap {
                width: 56px;
                height: 56px;
            }
            .series-summary-btn {
                width: 100%;
            }
            .series-actions-panel-inner {
                padding: .75rem;
            }
            .series-actions-toolbar .btn {
                flex-basis: 100%;
            }
        }
        @media (prefers-color-scheme: dark) {
            .series-actions { background: rgba(255,255,255,0.02); border-color: rgba(255,255,255,0.04); }
        }
        .link-buttons {
            float: right;
        }
        .normal-block {
            float: right;
        }
    </style>