<section
  appThemeNode="dmChatSurface"
  class="chat-layout relative h-full min-w-0 overflow-x-hidden bg-background"
>
  <header
    appThemeNode="dmChatHeader"
    class="flex h-14 shrink-0 items-center gap-3 border-b border-border px-4"
  >
    @if (peerUser()) {
      <button
        type="button"
        class="flex min-w-0 flex-1 items-center gap-3 rounded-md py-1 pr-2 text-left transition-colors hover:bg-secondary/60 focus:outline-none focus:ring-2 focus:ring-primary/50"
        [attr.aria-label]="openProfileLabel(peerName())"
        [title]="openProfileLabel(peerName())"
        (click)="openHeaderProfileCard($event)"
      >
        <app-user-avatar
          [name]="peerName()"
          [avatarUrl]="peerUser()?.avatarUrl"
          [status]="peerUser()?.status"
          [showStatusBadge]="true"
          size="md"
        />
        <div class="min-w-0 flex-1">
          <h1 class="truncate text-base font-semibold text-foreground">{{ peerName() }}</h1>
          <p class="text-xs text-muted-foreground">{{ 'dm.chat.directMessage' | translate }}</p>
        </div>
      </button>
    } @else {
      <app-user-avatar
        [name]="peerName()"
        [avatarUrl]="peerUser()?.avatarUrl"
        [status]="peerUser()?.status"
        [showStatusBadge]="true"
        size="md"
      />
      <div class="min-w-0 flex-1">
        <h1 class="truncate text-base font-semibold text-foreground">{{ peerName() }}</h1>
        <p class="text-xs text-muted-foreground">
          {{ isGroupConversation() ? ('dm.chat.groupChat' | translate) : ('dm.chat.directMessage' | translate) }}
        </p>
      </div>
    }
    @if (showCallButton() && conversation()) {
      <button
        type="button"
        class="grid h-9 w-9 place-items-center rounded-md bg-emerald-500 text-white transition-colors hover:bg-emerald-600 disabled:opacity-50"
        [disabled]="!canCallConversation()"
        [attr.aria-label]="callPeerLabel(peerName())"
        [title]="callPeerLabel(peerName())"
        (click)="callConversation()"
      >
        <ng-icon
          [name]="peerCallIcon()"
          class="h-4 w-4"
        />
      </button>
    }
  </header>

  @if (conversation()) {
    <div
      appThemeNode="dmMessageRegion"
      class="absolute inset-x-0 bottom-0 top-14"
    >
      <app-chat-message-list
        [allMessages]="chatMessages()"
        [channelMessages]="chatMessages()"
        [loading]="false"
        [syncing]="false"
        [currentUserId]="currentUserId()"
        [isAdmin]="false"
        [bottomPadding]="composerBottomPadding()"
        [conversationKey]="conversationKey()"
        [userLookupOverrides]="participantUsers()"
        (replyRequested)="setReplyTo($event)"
        (deleteRequested)="handleDeleteRequested($event)"
        (editSaved)="handleEditSaved($event)"
        (reactionAdded)="handleReactionAdded($event)"
        (reactionToggled)="handleReactionToggled($event)"
        (downloadRequested)="downloadAttachment($event)"
        (imageOpened)="openLightbox($event)"
        (imageGalleryOpened)="openImageGallery($event)"
        (imageContextMenuRequested)="openImageContextMenu($event)"
        (embedRemoved)="handleEmbedRemoved($event)"
      />

      @for (messageStatus of messageStatuses(); track messageStatus.id) {
        <span
          data-testid="message-status"
          class="sr-only"
          >{{ messageStatus.status }}</span
        >
      }
    </div>

    <div
      appThemeNode="chatComposerBar"
      class="chat-bottom-bar absolute bottom-0 left-0 right-0 z-10 min-w-0 bg-background/85 backdrop-blur-md"
    >
      @if (typingUsers().length > 0) {
        <div
          data-testid="dm-typing-indicator"
          class="px-4 pb-1 text-xs text-muted-foreground"
        >
          {{ typingIndicatorLabel(typingUsers()) }}
        </div>
      }

      <app-chat-message-composer
        [replyTo]="replyTo()"
        [showKlipyGifPicker]="showGifPicker()"
        [klipyEnabled]="klipyEnabled()"
        [klipySignalSource]="null"
        [textareaTestId]="'dm-input'"
        [commandSurface]="'direct'"
        (messageSubmitted)="handleMessageSubmitted($event)"
        (typingStarted)="handleTypingStarted()"
        (replyCleared)="clearReply()"
        (heightChanged)="composerBottomPadding.set($event + 20)"
        (klipyGifPickerToggleRequested)="toggleGifPicker()"
      />
    </div>

    @if (showGifPicker()) {
      @if (isMobile()) {
        <app-bottom-sheet (dismissed)="closeGifPicker()">
          <div appThemeNode="chatGifPickerSurface">
            <app-klipy-gif-picker
              (gifSelected)="handleGifSelected($event)"
              (closed)="closeGifPicker()"
            />
          </div>
        </app-bottom-sheet>
      } @else {
        <div
          class="fixed inset-0 z-[89]"
          tabindex="0"
          role="button"
          [attr.aria-label]="'dm.chat.closeGifPicker' | translate"
          (click)="closeGifPicker()"
          (keydown.enter)="closeGifPicker()"
          (keydown.space)="closeGifPicker()"
        ></div>

        <div class="pointer-events-none fixed inset-0 z-[90]">
          <div
            appThemeNode="chatGifPickerSurface"
            class="pointer-events-auto absolute w-[calc(100vw-2rem)] max-w-5xl sm:w-[34rem] md:w-[42rem] xl:w-[52rem]"
            [style.bottom.px]="composerBottomPadding() + 8"
            [style.right.px]="gifPickerAnchorRight()"
          >
            <app-klipy-gif-picker
              (gifSelected)="handleGifSelected($event)"
              (closed)="closeGifPicker()"
            />
          </div>
        </div>
      }
    }

    <app-chat-message-overlays
      [lightboxState]="lightboxState()"
      [galleryAttachments]="galleryAttachments()"
      [imageContextMenu]="imageContextMenu()"
      (lightboxClosed)="closeLightbox()"
      (lightboxStepRequested)="stepLightbox($event)"
      (galleryClosed)="closeImageGallery()"
      (contextMenuClosed)="closeImageContextMenu()"
      (downloadRequested)="downloadAttachment($event)"
      (copyRequested)="copyImageToClipboard($event)"
      (imageOpened)="openLightbox($event)"
      (imageContextMenuRequested)="openImageContextMenu($event)"
    />
  } @else {
    <div class="flex flex-1 items-center justify-center px-6 text-sm text-muted-foreground">{{ 'dm.chat.selectPrompt' | translate }}</div>
  }
</section>
