<script lang="ts">
  /** Controls visibility. */
  export let isOpen = false;
  /** Modal heading text. */
  export let title: string;
  /** aria-label for the dialog element. Defaults to `title`. */
  export let ariaLabel: string = "";
  /** Called when the backdrop is clicked or Escape is pressed. */
  export let onClose: () => void = () => {};

  function handleBackdropClick() {
    onClose();
  }

  function handleBackdropKeydown(e: KeyboardEvent) {
    if (isOpen && e.key === "Escape") onClose();
  }
</script>

<svelte:window on:keydown={handleBackdropKeydown} />

{#if isOpen}
  <!-- svelte-ignore a11y_click_events_have_key_events -->
  <!-- svelte-ignore a11y_no_static_element_interactions -->
  <div class="modal-backdrop" on:click={handleBackdropClick}>
    <!-- svelte-ignore a11y_no_static_element_interactions -->
    <!-- svelte-ignore a11y_click_events_have_key_events -->
    <div
      class="modal"
      role="dialog"
      aria-modal="true"
      aria-label={ariaLabel || title}
      tabindex="-1"
      on:click|stopPropagation
    >
      <div class="modal-header">
        <div class="modal-title-group">
          <slot name="icon" />
          <h2>{title}</h2>
        </div>
        <button
          class="close-btn"
          on:click={onClose}
          type="button"
          aria-label="Close modal"
        >
          <svg
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            stroke-width="2"
            width="18"
            height="18"
          >
            <line x1="18" y1="6" x2="6" y2="18" />
            <line x1="6" y1="6" x2="18" y2="18" />
          </svg>
        </button>
      </div>

      <slot />

      {#if $$slots.footer}
        <div class="modal-footer">
          <slot name="footer" />
        </div>
      {/if}
    </div>
  </div>
{/if}

<style>
  .modal-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.55);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 900;
    backdrop-filter: blur(3px);
    padding: 20px;
  }

  .modal {
    background: var(--surface-primary, #1e1e2e);
    border: 1px solid var(--border-primary, rgba(255, 255, 255, 0.08));
    border-radius: 16px;
    width: 100%;
    max-width: 620px;
    max-height: 90vh;
    display: flex;
    flex-direction: column;
    box-shadow: 0 24px 80px rgba(0, 0, 0, 0.55);
    overflow: hidden;
  }

  .modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 20px 24px 16px;
    border-bottom: 1px solid var(--border-primary, rgba(255, 255, 255, 0.06));
    flex-shrink: 0;
  }

  .modal-title-group {
    display: flex;
    align-items: center;
    gap: 10px;
  }

  .modal-title-group :global(svg) {
    color: var(--text-secondary);
    flex-shrink: 0;
  }

  .modal-title-group h2 {
    margin: 0;
    font-size: 15px;
    font-weight: 650;
    color: var(--text-primary);
  }

  .close-btn {
    background: none;
    border: none;
    cursor: pointer;
    color: var(--text-tertiary, rgba(255, 255, 255, 0.4));
    padding: 4px;
    border-radius: 6px;
    display: flex;
    align-items: center;
    transition:
      color 0.15s,
      background 0.15s;
    flex-shrink: 0;
  }

  .close-btn:hover {
    color: var(--text-primary);
    background: var(--surface-hover, rgba(255, 255, 255, 0.06));
  }

  .modal-footer {
    padding: 16px 24px;
    border-top: 1px solid var(--border-primary, rgba(255, 255, 255, 0.06));
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 8px;
    flex-shrink: 0;
  }
</style>
