{{ define "title" }}
  {{ .Pull.Title }} &middot; Pull #{{ .Pull.PullId }} &middot; {{ .RepoInfo.FullName }} &middot; Tangled
{{ end }}

{{ define "mainLayout" }}
{{ template "fragments/resizable" }}
<input type="hidden" id="pull-id" value="{{ .Pull.PullId }}" />
<input type="hidden" id="pull-target-repo-did" value="{{ .Pull.RepoDid }}" />
<input type="hidden" id="pull-active-version-id" value="{{ .ActiveVersionId }}" />
<div class="flex px-1 group/pr-layout">
  <div class="flex-1 min-w-0">
    <div class="max-w-screen-lg mx-auto">
    <!-- repo header -->
    <section id="repo-header" class="mb-2 py-2 px-4 dark:text-white">
      <div class="flex flex-col sm:flex-row items-start gap-4 justify-between mb-2">
        <div class="flex flex-col gap-2">
          {{ template "repoOwnerAndName" . }}
          {{ template "repoForkInfo" . }}
        </div>
        <div class="hidden sm:block sm:flex-shrink-0">
          {{ template "repoActions" . }}
        </div>
      </div>
      {{ template "repoMetadata" . }}

      <div class="block sm:hidden mt-4">
        {{ template "repoActions" . }}
      </div>
    </section>
    <!-- repo nav -->
    <nav class="w-full pl-4 overflow-auto">
      <div class="flex z-60">
        {{ range $item := .RepoInfo.GetTabs }}
          {{ $key   := index $item 0 }}
          {{ $value := index $item 1 }}
          {{ $icon  := index $item 2 }}
          {{ $meta  := index $.RepoInfo.TabMetadata $key }}
          {{/* no hx-boost here because PR page can be super large */}}
          <a
            href="/{{ $.RepoInfo.FullName }}{{ $value }}"
            class="relative -mr-px group"
          >
            <div
              class='px-4 py-1 mr-1 text-black dark:text-white min-w-[80px] text-center relative rounded-t whitespace-nowrap
                {{ if eq "pulls" $key }}
                  -mb-px bg-white dark:bg-gray-800
                {{ else }}
                  group-hover:bg-gray-100/25 group-hover:dark:bg-gray-700/25
                {{ end }}
                '
            >
              <span class="flex items-center justify-center">
                {{ i $icon "size-4 mr-2" }}
                {{ $key | capitalize }}
                {{ if $meta }}
                  <span class="bg-gray-200 dark:bg-gray-700 rounded py-1/2 px-1 text-sm ml-1">{{ scaleFmt $meta }}</span>
                {{ end }}
              </span>
            </div>
          </a>
        {{ end }}
      </div>
    </nav>
    <div class="grid grid-cols-1 lg:grid-cols-[4fr_1fr] gap-4 mb-4">
      <div class="min-w-0">
        <section class="bg-white dark:bg-gray-800 p-6 rounded">
          <!-- PR header -->
          <header class="pb-2">
            <h1 class="text-2xl">
              {{ .Pull.Title | description }}
              <span class="text-gray-500 dark:text-gray-400">#{{ .Pull.PullId }}</span>
            </h1>
          </header>
          <div class="flex items-center gap-2">
            {{ template "repo/pulls/fragments/pullState" .Pull.State }}
            <span class="text-gray-500 dark:text-gray-400 text-sm flex flex-wrap items-center gap-1">
              opened by
              {{ template "user/fragments/picLink" (list .Pull.OwnerDid.String "size-6" (index .VouchRelationships .Pull.OwnerDid)) }}
              <a href="/{{ resolve .Pull.OwnerDid.String }}">{{ resolve .Pull.OwnerDid.String }}</a>
              <span class="select-none before:content-['\00B7']"></span>
              {{ template "repo/fragments/time" .Pull.Created }}
              <span class="select-none before:content-['\00B7']"></span>
              targeting
              <span class="text-xs rounded bg-gray-100 dark:bg-gray-700 text-black dark:text-white font-mono px-2 mx-1/2 inline-flex items-center">
                <a href="/{{ .RepoInfo.FullName }}/tree/{{ .Pull.TargetBranch }}">{{ .Pull.TargetBranch }}</a>
              </span>

              {{ if .Pull.SourceBranch }}
                from
                <span class="text-xs rounded bg-gray-100 dark:bg-gray-700 text-black dark:text-white font-mono px-2 mx-1/2 inline-flex items-center">
                  {{ if not .Pull.IsForkBased }}
                    {{ $repoPath := .RepoInfo.FullName }}
                    <a href="/{{ $repoPath }}/tree/{{ pathEscape .Pull.SourceBranch }}">{{ .Pull.SourceBranch }}</a>
                  {{ else }}
                    <a href="/{{ .Pull.SourceRepo }}">fork</a>:
                    <a href="/{{ .Pull.SourceRepo }}/tree/{{ pathEscape .Pull.SourceBranch }}">{{ .Pull.SourceBranch }}</a>
                  {{ end }}
                </span>
              {{ end }}
            </span>
          </div>
          <article class="mt-4 prose dark:prose-invert">
            {{ if .Pull.Body }}
              {{ .Pull.Body | markdown }}
            {{ else }}
              <span class="italic">No description provided</span>
            {{ end }}
          </article>
          <div class="mt-4">
            {{ $aturi := .Pull.AtUri }}
            {{ template "repo/fragments/reactions"
              (dict "Reactions"   (index .Reactions $aturi)
                    "UserReacted" (index .UserReacted $aturi)
                    "ThreadAt"    $aturi) }}
          </div>
        </section>
      </div>
      <div class="lg:row-start-1 lg:row-end-3 lg:col-start-2 min-w-0">
        {{ template "repo/fragments/labelPanel"
          (dict "RepoInfo" $.RepoInfo
                "Defs"     $.LabelDefs
                "Subject"  $.Pull.AtUri
                "State"    $.Pull.Labels) }}
        {{ template "repo/fragments/participants" $.Pull.Participants }}
        {{ if $.LoggedInUser }}
          {{ template "repo/pulls/fragments/subscribeButton"
            (dict "RepoInfo"     $.RepoInfo
                  "PullId"       $.Pull.PullId
                  "IsSubscribed" $.IsSubscribed) }}
        {{ end }}
        {{ template "repo/fragments/backlinks"
          (dict "RepoInfo"  $.RepoInfo
                "Backlinks" $.Backlinks) }}
        {{ template "repo/fragments/externalLinkPanel" $.Pull.AtUri }}
      </div>
      <div class="lg:row-start-2 lg:col-start-1">
        <h2 id="commits">Commits</h2>
        {{ if .ErrorMsg }}
        <div class="flex items-center justify-center w-full min-h-32 p-4 rounded text-red-600 dark:text-red-300 bg-red-50 dark:bg-red-900/30 border border-red-300 dark:border-red-700">
          <span>{{ .ErrorMsg }}</span>
        </div>
        {{ else }}
        <div class="grid grid-cols-1 bg-white dark:bg-gray-800 rounded shadow-sm border border-gray-200 dark:border-gray-700 divide-y divide-gray-200 dark:divide-gray-700">
          {{ $seeAll := false }}
          {{ if .IsInterdiff }}
            {{ $seeAll = not .ChangeId }}
          {{ else }}
            {{ $version := index .Pull.Versions .VersionId }}
            {{ $seeAll = and .IsDiffBase .IsDiffHead }}
          {{ end }}
          <div class="text-sm px-2 {{ if $seeAll }}bg-gray-100/50 dark:bg-gray-700/50{{ end }}">
            <div class="relative">
              {{ if $seeAll }}
              <div class="flex-shrink-0 absolute top-3 left-0">
                {{ i "arrow-right" "size-4" }}
              </div>
              {{ end }}
              <div class="py-2 ml-6">
                {{ if .IsInterdiff }}
                  <a href="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/{{ .Version1 }}..{{ .Version2 }}/all">See all changes</a>
                {{ else }}
                  <a href="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/{{ .VersionId }}">See all changes</a>
                {{ end }}
              </div>
            </div>
          </div>
          {{ range .Commits }}
          {{ $messageParts := splitN .Message "\n\n" 2 }}
          {{ $active := and (not $seeAll) (eq (shortId $.ActiveCommitId) (shortId .Hash.String)) }}
          {{ $toggleId := printf "commit-message-toggle-%s" .Hash }}
          {{ $pipeline := index $.Pipelines .Hash.String }}
          <div class="text-sm px-2 {{ if $active }}bg-gray-100/50 dark:bg-gray-700/50{{ end }}">
            <input id="{{ $toggleId }}" type="checkbox" class="peer hidden" />
            <div class="relative flex items-center justify-between">
              {{ if $active }}
              <div class="flex-shrink-0 absolute left-0">
                {{ i "arrow-right" "size-4" }}
              </div>
              {{ end }}
              <div class="py-2 ml-6">
                <code class="py-0.5 px-1">{{ shortId .Hash.String }}</code>
                {{ if .ChangeId }}
                  <code class="py-0.5 px-1">{{ shortId .ChangeId }}</code>
                {{ end }}
                {{ if $.IsInterdiff }}
                  <a href="/{{ $.RepoInfo.FullName }}/pulls/{{ $.Pull.PullId }}/{{ $.Version1 }}..{{ $.Version2 }}/{{ .ChangeId }}">{{ index $messageParts 0 }}</a>
                {{ else }}
                  <a href="/{{ $.RepoInfo.FullName }}/pulls/{{ $.Pull.PullId }}/{{ $.VersionId }}/{{ shortId .FirstParentHash.String }}..{{ shortId .Hash.String }}">{{ index $messageParts 0 }}</a>
                {{ end }}
                <label
                  for="{{ $toggleId }}"
                  class="cursor-pointer inline-flex py-0.5 px-1 bg-gray-200 hover:bg-gray-400 rounded dark:bg-gray-700 dark:hover:bg-gray-600"
                >
                  {{ i "ellipsis" "size-3" }}
                </label>
              </div>
              {{ if and $pipeline $pipeline.Id }}
              <div>
                {{ template "repo/pipelines/fragments/pipelineSymbol" (dict "Pipeline" $pipeline "ShortSummary" true) }}
              </div>
              {{ end }}
            </div>
            {{ if gt (len $messageParts) 1 }}
            <pre class="ml-6 mt-1 mb-2 hidden peer-checked:block">{{ index $messageParts 1 }}</pre>
            {{ end }}
          </div>
          {{ end }}
        </div>
        {{ end }}
      </div>
    </div>
    </div>
    <!-- diff -->
    <div hx-include="this" class="min-h-[50vh] group/diff-layout">
      {{ $diffUrl := "" }}
      {{ if not .IsInterdiff }}
        {{ $diffUrl  = (printf "/%s/pulls/%d/_/diff?view=unified" .Pull.RepoDid .Pull.PullId) }}
        {{ $diff    := .DiffParams }}
        <input type="hidden" name="baseRepo" value="{{ .Pull.RepoDid    }}">
        <input type="hidden" name="base"     value="{{ $diff.Base       }}">
        <input type="hidden" name="headRepo" value="{{ .Pull.SourceRepo }}">
        <input type="hidden" name="head"     value="{{ $diff.Head       }}">
      {{ else if .DiffParams.Diff }}
        {{ $diffUrl  = (printf "/%s/pulls/%d/_/diff?view=unified" .Pull.RepoDid .Pull.PullId) }}
        {{ $diff    := .DiffParams.Diff }}
        <input type="hidden" name="baseRepo" value="{{ .Pull.SourceRepo }}">
        <input type="hidden" name="base"     value="{{ $diff.Base       }}">
        <input type="hidden" name="headRepo" value="{{ .Pull.SourceRepo }}">
        <input type="hidden" name="head"     value="{{ $diff.Head       }}">
      {{ else }}
        {{ $diffUrl  = (printf "/%s/pulls/%d/_/interdiff?view=unified" .Pull.RepoDid .Pull.PullId) }}
        {{ $diff    := .DiffParams.Interdiff }}
        <input type="hidden" name="repo" value="{{ .Pull.SourceRepo }}">
        <input type="hidden" name="base1" value="{{ $diff.From.Base }}">
        <input type="hidden" name="head1" value="{{ $diff.From.Head }}">
        <input type="hidden" name="base2" value="{{ $diff.To.Base }}">
        <input type="hidden" name="head2" value="{{ $diff.To.Head }}">
      {{ end }}
      <!-- diff header -->
      <header class="bg-slate-100 dark:bg-gray-900 sticky px-1 top-0 z-20 flex flex-col md:flex-row md:justify-between">
        <!-- left -->
        <div class="h-12 flex items-center gap-2">
          <div class="md:block hidden">
            <label for="diff-tree-toggle" title="Toggle filetree panel" class="btn-flat">
              <span class="group-has-[#diff-tree-toggle:checked]/diff-layout:hidden inline">{{ i "panel-left-open" "size-4" }}</span>
              <span class="hidden group-has-[#diff-tree-toggle:checked]/diff-layout:inline">{{ i "panel-left-close" "size-4" }}</span>
            </label>
          </div>
          <div id="diff-stats">
            <div class="flex items-center font-mono text-sm">
              <span class="rounded-l p-1 select-none bg-green-100 text-green-700 dark:bg-green-800/50 dark:text-green-400">+{{ i "loader-circle" "size-3 inline-flex animate-spin" }}</span>
              <span class="rounded-r p-1 select-none bg-red-100 text-red-700 dark:bg-red-800/50 dark:text-red-400">-{{ i "loader-circle" "size-3 inline-flex animate-spin" }}</span>
            </div>
          </div>
          {{ if .IsInterdiff }}
          <span class="text-sm">
            Interdiff
            <span class="ml-1 text-xs after:content-['|'] after:ml-1 after:text-gray-300 dark:after:text-gray-600">
              <code class="inline-block box-content min-h-[1lh] py-0.5 px-1 border border-gray-300 dark:border-gray-600">v{{ .Version1 }}</code>
              {{ i "arrow-right" "size-3 inline-flex" }}
              <code class="inline-block box-content min-h-[1lh] py-0.5 px-1 border border-gray-300 dark:border-gray-600">v{{ .Version2 }}</code>
            </span>
            <a href="#commits" class="btn-flat text-xs hover:bg-gray-50 dark:hover:bg-gray-800">
              {{ with .ChangeId }}
              <code class="py-0.5 px-1 border border-gray-300 dark:border-gray-600">{{ shortId . }}</code>
              {{ else }}
              <span class="px-1">All changes</span>
              {{ end }}
            </a>
          </span>
          {{ else }}
          <span class="text-sm">
            Diff
            <span class="ml-1 text-xs after:content-['|'] after:ml-1 after:text-gray-300 dark:after:text-gray-600">
              <code class="py-0.5 px-1 border border-gray-300 dark:border-gray-600">v{{ .VersionId }}</code>
            </span>
            <a href="#commits" class="btn-flat text-xs hover:bg-gray-50 dark:hover:bg-gray-800">
              <code class="inline-block box-content min-h-[1lh] py-0.5 px-1 border border-gray-300 dark:border-gray-600">{{ .DisplayDiffBase }}</code>
              {{ i "arrow-right" "size-3 inline-flex" }}
              <code class="inline-block box-content min-h-[1lh] py-0.5 px-1 border border-gray-300 dark:border-gray-600">{{ .DisplayDiffHead }}</code>
            </a>
          </span>
          {{ end }}
        </div>
        <!-- right -->
        <div class="h-12 flex items-center gap-2">
          <label title="Expand/Collapse diffs" class="btn font-normal normal-case">
            <input type="checkbox" id="diff-collapse-toggle" class="peer/collapse hidden" checked/>
            <span class="peer-checked/collapse:hidden inline-flex items-center gap-2">
              {{ i "unfold-vertical" "size-4" }}
              <span class="hidden md:inline">Expand all</span>
            </span>
            <span class="peer-checked/collapse:inline-flex hidden items-center gap-2">
              {{ i "fold-vertical" "size-4" }}
              <span class="hidden md:inline">Collapse all</span>
            </span>
          </label>

          <div class="md:hidden flex-grow"></div>

          <!-- diff settings -->
          <div id="diff-settings">
            {{ template "repo/pulls/fragments/diffSettings" (dict "DiffUrl" $diffUrl "Unified" true) }}
          </div>

          {{ $isInterdiff  := .IsInterdiff }}
          {{ $canInterdiff := gt .ActiveVersionId 0 }}
          <div class="btn-group">
            <button
              type="button"
              role="link"
              onclick="window.location.href='/{{ .Pull.RepoDid }}/pulls/{{ .Pull.PullId }}/{{ .ActiveVersionId }}';"
              class="btn-group-item {{ if not $isInterdiff }}active{{ end }}"
            >
              {{ i "diff" "size-4" }}
              Diff
            </button>
            <button
              type="button"
              role="link"
              onclick="window.location.href='/{{ .Pull.RepoDid }}/pulls/{{ .Pull.PullId }}/{{ sub .ActiveVersionId 1 }}..{{ .ActiveVersionId }}';"
              class="btn-group-item {{ if $isInterdiff }}active{{ end }}"
              {{ if not $canInterdiff }}disabled{{ end }}
            >
              {{ i "chevrons-left-right-ellipsis" "size-4 rotate-90" }}
              Interdiff
            </button>
          </div>
          <label
            for="discussion-toggle"
            title="Toggle discussion panel"
            class="btn-flat hidden lg:inline-flex group-has-[#discussion-toggle:checked]/pr-layout:hidden"
          >
            {{ i "message-square-more" "size-4" }}
          </label>
        </div>
      </header>
      <div class="flex">
        <input type="checkbox" id="diff-tree-toggle" class="peer hidden" checked>
        <aside id="diff-files" class="hidden peer-checked:md:block w-[20%] max-w-[40%]">
          <div class="sticky top-12 bg-white dark:bg-gray-800 rounded shadow-sm border border-gray-200 dark:border-gray-700">
            <div class="
              max-h-[calc(100vh-3rem-0.5rem)] pb-2
              overflow-y-auto
            ">
              <section class="text-sm px-6 py-2 w-full">
                <div class="mb-8">
                  <div id="diff-files-content">
                    {{ i "loader-circle" "size-4 inline-flex animate-spin" }} loading...
                  </div>
                </div>
              </section>
            </div>
          </div>
        </aside>

        {{ template "resize-grip" (list "resize-diff-files" "diff-files" "before" "hidden peer-checked:md:flex") }}

        <div id="diff-list-container" class="flex-1 min-w-0">
          <div
            id="diff-list"
            hx-get="{{ $diffUrl }}"
            hx-swap="outerHTML"
            hx-trigger="load"
          >
            {{ i "loader-circle" "size-4 inline-flex animate-spin" }} loading...
          </div>
        </div>
        <script>
          (() => {
            const checkbox = document.getElementById('diff-collapse-toggle');
            const diffList = document.getElementById('diff-list-container');

            checkbox.addEventListener('change', () => {
              console.debug("checked", checkbox.checked);
              diffList.querySelectorAll('details[id^="file-"]').forEach(detail => {
                detail.open = checkbox.checked;
              });
            });

            if (window.__collapseToggleHandler) {
              diffList.removeEventListener('toggle', window.__collapseToggleHandler, true);
            }

            const handler = (e) => {
              if (!e.target.matches('details[id^="file-"]')) return;
              const details = document.querySelectorAll('details[id^="file-"]');
              const allOpen = Array.from(details).every(d => d.open);
              const allClosed = Array.from(details).every(d => !d.open);

              if (allOpen) checkbox.checked = true;
              else if (allClosed) checkbox.checked = false;
            };

            window.__collapseToggleHandler = handler;
            diffList.addEventListener('toggle', handler, true);
          })();
        </script>
      </div>
    </div>
  </div>

  <div id="bottom-sheet-backdrop" class="fixed inset-0 bg-black/50 lg:hidden opacity-0 pointer-events-none transition-opacity duration-300 z-20"></div>

  <input type="checkbox" id="discussion-toggle" class="peer hidden" checked>
  {{ template "resize-grip" (list "resize-discussion" "discussion" "after" "hidden peer-checked:lg:flex") }}

  <div id="discussion" class="
    fixed z-30 bottom-0 right-0 w-full max-h-[calc(100vh-10rem)] rounded-t-2xl
    bg-slate-100 dark:bg-gray-900
    lg:sticky lg:top-0 lg:hidden peer-checked:lg:block lg:w-[25vw] lg:max-w-[50vw] lg:max-h-screen
    lg:bg-transparent
  ">
  <details open id="bottom-sheet" class="
    flex flex-col group/history
    {{      if .Pull.State.IsOpen      -}} *:border-green-600  *:dark:border-green-900
    {{ else if .Pull.State.IsMerged    -}} *:border-purple-600 *:dark:border-purple-900
    {{ else if .Pull.State.IsAbandoned -}} *:border-red-600    *:dark:border-red-900
    {{ else                            -}} *:border-gray-600   *:dark:border-gray-900
    {{ end }}
  ">
    {{ $versions := len .Pull.Versions  }}
    {{ $comments := .Pull.TotalComments }}
    <summary class="
      list-none z-20 flex items-center justify-between
      pl-3 pr-4 py-2 rounded-t-2xl
      relative
      border-t-4 border-x-4
      group-open/history:bg-transparent
      lg:border-0
      lg:h-12 lg:px-1 lg:pointer-events-none
      lg:bg-transparent
    ">
      <div class="flex items-center gap-2">
        <span class="lg:hidden">
          {{ template "repo/pulls/fragments/pullState" .Pull.State }}
        </span>
        <h2>History</h2>
      </div>
      <div class="flex items-center gap-2 text-sm">
        <span>
          {{ $versions }} version{{ if ne $versions 1 }}s{{ end }}
        </span>
        <span class="select-none before:content-['\00B7']"></span>
        <span>
          {{ $comments }} comment{{ if ne $comments 1 }}s{{ end }}
        </span>
        <label for="discussion-toggle" title="Toggle discussion panel" class="hidden lg:inline-flex btn-flat pointer-events-auto">
          {{ i "message-square" "size-4" }}
        </label>
        <span class="lg:hidden">
          <span class="group-open/history:hidden inline">{{ i "chevron-up" "size-4" }}</span>
          <span class="group-open/history:inline hidden">{{ i "chevron-down" "size-4" }}</span>
        </span>
      </div>
    </summary>
    <div class="
      max-h-[calc(100vh-3rem-0.5rem)] pb-32 overflow-y-auto space-y-4
      px-1 border-x-4
      lg:px-0 lg:border-0
    ">
      {{ range .Pull.Versions }}
        {{ $active := eq .ID $.ActiveVersionId }}
        <div
          id="version-{{ .ID }}"
          class="
            {{ if $active }}active{{ end }}
            w-full shadow-sm rounded overflow-clip bg-gray-50 dark:bg-gray-900
          "
        >
          <!-- header -->
          <header class="sticky top-0 z-20 bg-slate-100 dark:bg-gray-900">
            <div class="pt-2 pr-2 pb-4 pl-4 lg:pl-6 flex gap-2
              rounded-t border-t border-x border-gray-200 dark:border-gray-700
              {{ if $active }}
                bg-blue-50 dark:bg-blue-950
              {{ else }}
                bg-white dark:bg-gray-800
              {{ end }}
            ">
              <!-- left column: just profile picture -->
              <div class="flex-shrink-0 pt-2">
                {{ template "user/fragments/picLink" (list $.Pull.OwnerDid.String "size-8" (index $.VouchRelationships $.Pull.OwnerDid)) }}
              </div>
              <!-- right column -->
              <div class="flex-1 min-w-0 flex flex-col gap-1">
                <!-- submission info -->
                {{ $handle := resolve $.Pull.OwnerDid.String }}
                <div class="flex gap-2 items-center justify-between mb-1">
                  <span class="inline-flex items-center gap-2 text-sm pt-2
                              {{ if $active }}
                                text-gray-600 dark:text-gray-300
                              {{ else }}
                                text-gray-500 dark:text-gray-400
                              {{ end }}"
                  >
                    <a href="/{{ $handle }}">{{ $handle }}</a>
                    submitted
                    <span class="
                      px-2 py-0.5 rounded font-mono text-xs border
                      {{ if $active }}
                        text-blue-800 dark:text-white bg-blue-100 dark:bg-blue-600 border-blue-200 dark:border-blue-500
                      {{ else }}
                        text-black dark:text-white bg-gray-100 dark:bg-gray-700 border-gray-300 dark:border-gray-600
                      {{ end }}
                    ">#{{ .ID }}</span>
                    <span class="select-none before:content-['\00B7']"></span>
                    <a href="/{{ $.Pull.RepoDid }}/pulls/{{ $.Pull.PullId }}/{{ .ID }}">{{ template "repo/fragments/shortTime" .Created }}</a>
                  </span>
                  <a class="btn-flat flex items-center gap-2 no-underline hover:no-underline text-sm"
                    href="/{{ $.Pull.RepoDid }}/pulls/{{ $.Pull.PullId }}/{{ .ID }}">
                    {{ i "diff" "size-4" }}
                    Diff
                  </a>
                </div>
                {{ if eq .ID $.Pull.LatestVersionNumber }}
                <div id="mergecheck-banner">
                  {{ if $.Pull.State.IsOpen }}
                  <div class="flex items-center gap-2 text-gray-500 dark:text-gray-400">
                    {{ i "loader-circle" "size-4 animate-spin" }}
                    <span>Checking mergeability…</span>
                  </div>
                  {{ end }}
                </div>
                {{ end }}
              </div>
            </div>
          </header>
          <!-- comments -->
          {{ $count := len .Comments }}
          <details
            class="relative pl-8 lg:pl-10 rounded-b border-x border-b border-gray-200 dark:border-gray-700 group/comments group/collapse"
            {{ if or $active (eq $count 0) }}open{{ end }}
          >
            <summary class="cursor-pointer list-none">
              <div class="collapse-trigger hidden group-open/comments:block absolute left-2 top-0 bottom-0 w-12 lg:w-16 transition-colors flex items-center justify-center group/border z-4">
                <div class="absolute left-1/2 -translate-x-1/2 top-0 bottom-0 w-0.5 group-open/comments:bg-gray-200 dark:group-open/comments:bg-gray-700 group-has-[.collapse-trigger:hover]/collapse:bg-gray-400 dark:group-has-[.collapse-trigger:hover]/collapse:bg-gray-500 transition-colors"> </div>
              </div>
              <div class="group-open/comments:hidden block relative group/summary py-4">
                <div class="absolute -left-8 top-0 bottom-0 w-16 transition-colors flex items-center justify-center z-4">
                  <div class="absolute left-1/2 -translate-x-1/2 h-1/3 top-0 bottom-0 w-0.5 bg-gray-200 dark:bg-gray-700 group-hover/summary:bg-gray-400 dark:group-hover/summary:bg-gray-500 transition-colors"></div>
                </div>
                <span class="text-gray-500 dark:text-gray-400 text-sm group-hover/summary:text-gray-600 dark:group-hover/summary:text-gray-300 transition-colors flex items-center gap-2 -ml-2 relative">
                  {{ i "circle-plus" "size-4 z-5" }}
                  Expand {{ $count }} comment{{ if ne $count 1 }}s{{ end }}
                </span>
              </div>
            </summary>
            <div id="pull-comments-{{ .ID }}">
              {{ range .Comments }}
                {{ template "fragments/comment/pullComment"
                  (dict "LoggedInUser" $.LoggedInUser
                        "Reactions"    (index (asReactionMapMap $.Reactions) .FeedCommentAtUri)
                        "UserReacted"  (index (asReactionStatusMapMap $.UserReacted) .FeedCommentAtUri)
                        "Comment"      .) }}
              {{ end }}
            </div>
            {{ if gt $count 0}}
              <button
                class="collapse-trigger flex items-center gap-2 -ml-2 relative cursor-pointer text-sm text-gray-500 dark:text-gray-400 group-has-[.collapse-trigger:hover]/collapse:text-gray-600 dark:group-has-[.collapse-trigger:hover]/collapse:text-gray-300 mt-4 pb-4 transition-colors"
                hx-on:click="this.closest('details').open = false"
              >
                <span class="bg-gray-50 dark:bg-slate-900 dark:rounded-full">{{ i "circle-chevron-up" "size-4 z-5" }}</span> Collapse comment{{ if ne $count 1 }}s{{ end }}
              </button>
            {{ end }}

            <div hx-include="this" class="relative -ml-8 lg:-ml-10 rounded-b bg-gray-50 dark:bg-gray-900">
              {{ if eq .ID $.Pull.LatestVersionNumber }}
                {{ block "mergeStatus" $ }} {{ end }}
                <div id="pull-action-error" class="error"></div>
              {{ end }}
              <input name="subject-uri" type="hidden" value="{{ $.Pull.AtUri }}">
              <input name="pull-round-idx" type="hidden" value="{{ .ID }}">
              {{ template "repo/pulls/fragments/pullActions"
                (dict
                  "LoggedInUser"       $.LoggedInUser
                  "Pull"               $.Pull
                  "RepoInfo"           $.RepoInfo
                  "RoundNumber"        .ID
                  "MergeCheck"         $.MergeCheck
                  "ResubmitCheck"      $.ResubmitCheck
                  "BranchDeleteStatus" $.BranchDeleteStatus
                  "Loading"            (eq .ID $.Pull.LatestVersionNumber)) }}
            </div>
          </details>
        </div>
      {{ end }}
    </div>
    <div class="hidden sticky bottom-0 h-12">
      <!-- TODO: bottom PR actions -->
    </div>
  </details>
  </div>
  <script>
    (function() {
      const details = document.getElementById('bottom-sheet');
      const backdrop = document.getElementById('bottom-sheet-backdrop');
      const isDesktop = () => window.matchMedia('(min-width: 1024px)').matches;

      // function to update backdrop
      const updateBackdrop = () => {
        if (backdrop) {
          if (details.open && !isDesktop()) {
            backdrop.classList.remove('opacity-0', 'pointer-events-none');
            backdrop.classList.add('opacity-100', 'pointer-events-auto');
            document.body.style.overflow = 'hidden';
          } else {
            backdrop.classList.remove('opacity-100', 'pointer-events-auto');
            backdrop.classList.add('opacity-0', 'pointer-events-none');
            document.body.style.overflow = '';
          }
        }
      };

      // close on mobile initially
      if (!isDesktop()) {
        details.open = false;
      }
      updateBackdrop(); // initialize backdrop

      // prevent closing on desktop
      details.addEventListener('toggle', function(e) {
        if (isDesktop() && !this.open) {
          this.open = true;
        }
        updateBackdrop();
      });

      const mediaQuery = window.matchMedia('(min-width: 1024px)');
      mediaQuery.addEventListener('change', function(e) {
        if (e.matches) {
          // switched to desktop - keep open
          details.open = true;
        } else {
          // switched to mobile - close
          details.open = false;
        }
        updateBackdrop();
      });

      // close when clicking backdrop
      if (backdrop) {
        backdrop.addEventListener('click', () => {
          if (!isDesktop()) {
            details.open = false;
          }
        });
      }
    })();
  </script>
</div>
{{ end }}
