<div
  class="fixed inset-0 z-[112] bg-black/70 backdrop-blur-sm"
  (click)="cancelled.emit(undefined)"
  (keydown.enter)="cancelled.emit(undefined)"
  (keydown.space)="cancelled.emit(undefined)"
  role="button"
  tabindex="0"
  aria-label="Close profile image editor"
></div>

<div class="fixed inset-0 z-[113] flex items-center justify-center p-4 pointer-events-none">
  <div
    class="pointer-events-auto flex max-h-[calc(100vh-2rem)] w-full max-w-4xl flex-col overflow-hidden rounded-2xl border border-border bg-card shadow-2xl"
    role="dialog"
    aria-modal="true"
    tabindex="-1"
  >
    <div class="border-b border-border p-5">
      <h3 class="text-lg font-semibold text-foreground">Adjust profile picture</h3>
      <p class="mt-1 text-sm text-muted-foreground">
        @if (preservesAnimation()) {
          Animated GIF and WebP avatars keep their original animation and framing.
        } @else {
          Drag image to frame subject. Zoom until preview looks right. Final image saves as 256x256 WebP.
        }
      </p>
    </div>

    <div class="grid gap-6 overflow-y-auto p-5 sm:grid-cols-[minmax(0,1fr)_280px]">
      <div class="flex flex-col items-center gap-4">
        <div
          class="relative overflow-hidden rounded-[32px] border border-border bg-secondary/40 shadow-inner touch-none"
          [style.width.px]="frameSize"
          [style.height.px]="frameSize"
          (pointerdown)="onPointerDown($event)"
          (pointermove)="onPointerMove($event)"
          (pointerup)="onPointerUp($event)"
          (pointercancel)="onPointerUp($event)"
          (wheel)="onWheel($event)"
        >
          <img
            [src]="source().objectUrl"
            [alt]="source().name"
            class="pointer-events-none absolute left-1/2 top-1/2 max-w-none select-none"
            [style.transform]="imageTransform()"
            draggable="false"
          />

          <div class="pointer-events-none absolute inset-0 rounded-[32px] ring-1 ring-white/10"></div>
          <div class="pointer-events-none absolute inset-4 rounded-full border border-white/45 shadow-[0_0_0_999px_rgba(4,8,15,0.58)]"></div>
        </div>

        <p class="text-xs text-muted-foreground">
          @if (preservesAnimation()) {
            Animation and original framing are preserved.
          } @else {
            Preview matches saved crop.
          }
        </p>
      </div>

      <div class="space-y-5">
        <div class="rounded-xl border border-border bg-secondary/20 p-4">
          <p class="text-xs uppercase tracking-[0.18em] text-muted-foreground">Source</p>
          <p class="mt-2 truncate text-sm font-medium text-foreground">{{ source().name }}</p>
          <p class="mt-1 text-xs text-muted-foreground">{{ source().width }} x {{ source().height }}</p>
        </div>

        <div
          class="rounded-xl border border-border bg-secondary/20 p-4"
          [class.opacity-60]="preservesAnimation()"
        >
          <div class="flex items-center justify-between gap-3">
            <div>
              <p class="text-sm font-medium text-foreground">Zoom</p>
              <p class="text-xs text-muted-foreground">
                @if (preservesAnimation()) {
                  Animated avatars keep the original frame sequence.
                } @else {
                  Use wheel or slider.
                }
              </p>
            </div>

            <div class="flex items-center gap-2">
              <button
                type="button"
                class="rounded-lg border border-border px-3 py-1.5 text-sm text-foreground transition-colors hover:bg-secondary"
                (click)="zoomBy(-0.12)"
                [disabled]="preservesAnimation()"
              >
                -
              </button>
              <button
                type="button"
                class="rounded-lg border border-border px-3 py-1.5 text-sm text-foreground transition-colors hover:bg-secondary"
                (click)="zoomBy(0.12)"
                [disabled]="preservesAnimation()"
              >
                +
              </button>
            </div>
          </div>

          <input
            type="range"
            min="1"
            max="4"
            step="0.01"
            class="mt-4 w-full accent-primary"
            [value]="clampedTransform().zoom"
            (input)="onZoomInput($event)"
            [disabled]="preservesAnimation()"
          />

          <p class="mt-2 text-xs text-muted-foreground">
            @if (preservesAnimation()) {
              Animated upload detected.
            } @else {
              {{ (clampedTransform().zoom * 100).toFixed(0) }}% zoom
            }
          </p>
        </div>

        @if (errorMessage()) {
          <div class="rounded-xl border border-red-500/40 bg-red-500/10 px-4 py-3 text-sm text-red-200">
            {{ errorMessage() }}
          </div>
        }
      </div>
    </div>

    <div class="flex items-center justify-end gap-2 border-t border-border p-4">
      <button
        type="button"
        class="rounded-lg bg-secondary px-4 py-2 text-sm text-foreground transition-colors hover:bg-secondary/80"
        (click)="cancelled.emit(undefined)"
        [disabled]="processing()"
      >
        Cancel
      </button>
      <button
        type="button"
        class="rounded-lg bg-primary px-4 py-2 text-sm font-medium text-primary-foreground transition-colors hover:bg-primary/90 disabled:cursor-not-allowed disabled:opacity-60"
        (click)="confirm()"
        [disabled]="processing()"
      >
        {{ processing() ? 'Saving...' : 'Apply picture' }}
      </button>
    </div>
  </div>
</div>
